-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.scenegraph.ui;\r
-\r
-import java.lang.reflect.Field;\r
-import java.lang.reflect.Modifier;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import org.eclipse.jface.dialogs.Dialog;\r
-import org.eclipse.jface.dialogs.IDialogSettings;\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
-import org.eclipse.jface.layout.TableColumnLayout;\r
-import org.eclipse.jface.resource.ColorDescriptor;\r
-import org.eclipse.jface.resource.FontDescriptor;\r
-import org.eclipse.jface.resource.JFaceResources;\r
-import org.eclipse.jface.resource.LocalResourceManager;\r
-import org.eclipse.jface.resource.ResourceManager;\r
-import org.eclipse.jface.viewers.ColumnLabelProvider;\r
-import org.eclipse.jface.viewers.ColumnWeightData;\r
-import org.eclipse.jface.viewers.ISelection;\r
-import org.eclipse.jface.viewers.ISelectionChangedListener;\r
-import org.eclipse.jface.viewers.ISelectionProvider;\r
-import org.eclipse.jface.viewers.IStructuredSelection;\r
-import org.eclipse.jface.viewers.ITreeContentProvider;\r
-import org.eclipse.jface.viewers.SelectionChangedEvent;\r
-import org.eclipse.jface.viewers.TableViewer;\r
-import org.eclipse.jface.viewers.TableViewerColumn;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.jface.viewers.ViewerCell;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.events.KeyAdapter;\r
-import org.eclipse.swt.events.KeyEvent;\r
-import org.eclipse.swt.events.SelectionAdapter;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.graphics.Color;\r
-import org.eclipse.swt.graphics.Point;\r
-import org.eclipse.swt.graphics.RGB;\r
-import org.eclipse.swt.layout.GridData;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.Event;\r
-import org.eclipse.swt.widgets.Listener;\r
-import org.eclipse.swt.widgets.Shell;\r
-import org.eclipse.swt.widgets.ToolBar;\r
-import org.eclipse.swt.widgets.ToolItem;\r
-import org.simantics.scenegraph.INode;\r
-import org.simantics.scenegraph.g2d.IG2DNode;\r
-import org.simantics.scenegraph.utils.NodeUtil;\r
-import org.simantics.utils.datastructures.ValueUtils;\r
-\r
-/**\r
- * @author Tuukka Lehtonen\r
- */\r
-public class AttributeDialog extends Dialog implements ISelectionChangedListener {\r
-\r
- private static final String DIALOG = "AttributeDialog"; //$NON-NLS-1$\r
-\r
- private IDialogSettings dialogBoundsSettings;\r
-\r
- private ResourceManager resourceManager;\r
-\r
- private TableViewer viewer;\r
-\r
- private final ISelectionProvider selectionProvider;\r
-\r
- private final boolean showClass = true;\r
- private boolean showTransient = false;\r
- private boolean showStatic = false;\r
-\r
- private final ColorDescriptor staticColor = ColorDescriptor.createFrom(new RGB(224, 224, 224));\r
- private final ColorDescriptor transientColor = ColorDescriptor.createFrom(new RGB(192, 255, 255));\r
- \r
- protected AttributeDialog(Shell parentShell, ISelectionProvider selectionProvider) {\r
- super(parentShell);\r
- this.selectionProvider = selectionProvider;\r
-\r
- IDialogSettings settings = Activator.getDefault().getDialogSettings();\r
- dialogBoundsSettings = settings.getSection(DIALOG);\r
- if (dialogBoundsSettings == null)\r
- dialogBoundsSettings = settings.addNewSection(DIALOG);\r
- }\r
-\r
- @Override\r
- protected IDialogSettings getDialogBoundsSettings() {\r
- return dialogBoundsSettings;\r
- }\r
-\r
- @Override\r
- protected int getShellStyle() {\r
- return SWT.RESIZE | SWT.MODELESS | SWT.TITLE | SWT.CLOSE | SWT.BORDER;\r
- }\r
-\r
- @Override\r
- protected void configureShell(Shell newShell) {\r
- super.configureShell(newShell);\r
- newShell.setText("Scene Graph Node Attributes");\r
- }\r
-\r
- @Override\r
- protected Control createButtonBar(Composite parent) {\r
- return parent;\r
- }\r
-\r
- @Override\r
- protected void createButtonsForButtonBar(Composite parent) {\r
- // No buttons, this is a non-modal property dialog.\r
- }\r
-\r
- @Override\r
- protected Point getInitialSize() {\r
- Point defaultSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);\r
- Point result = super.getInitialSize();\r
- if (defaultSize.equals(result))\r
- return new Point(500, 300);\r
- return result;\r
- }\r
-\r
- @Override\r
- protected Control createDialogArea(Composite parent) {\r
- Composite composite = (Composite) super.createDialogArea(parent);\r
-\r
- this.resourceManager = new LocalResourceManager(JFaceResources.getResources());\r
- composite.addListener(SWT.Dispose, new Listener() {\r
- @Override\r
- public void handleEvent(Event event) {\r
- selectionProvider.removeSelectionChangedListener(AttributeDialog.this);\r
- resourceManager.dispose();\r
- resourceManager = null;\r
- }\r
- });\r
-\r
- GridLayoutFactory.fillDefaults().margins(0, 0).spacing(0, 0).applyTo(composite);\r
-\r
- ToolBar toolbar = new ToolBar(composite, SWT.NONE);\r
- GridDataFactory.fillDefaults().grab(true, false).applyTo(toolbar);\r
- final ToolItem showStaticItem = new ToolItem(toolbar, SWT.CHECK);\r
- showStaticItem.setText("Show &Static");\r
- showStaticItem.setToolTipText("Show Static Fields of Selected Object");\r
- final ToolItem showTransientItem = new ToolItem(toolbar, SWT.CHECK);\r
- showTransientItem.setText("Show &Transient");\r
- showTransientItem.setToolTipText("Show Transient Fields of Selected Object");\r
- final ToolItem refresh = new ToolItem(toolbar, SWT.PUSH);\r
- refresh.setText("&Refresh");\r
- refresh.setToolTipText("Refresh Values");\r
-\r
- Composite tableComposite = new Composite(composite, SWT.NONE);\r
- GridDataFactory.fillDefaults().grab(true, true).applyTo(tableComposite);\r
-\r
- viewer = new TableViewer(tableComposite, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);\r
- viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
- viewer.setContentProvider(new FieldContentProvider());\r
- viewer.getTable().addKeyListener(new KeyAdapter() {\r
- @Override\r
- public void keyPressed(KeyEvent e) {\r
- if (e.keyCode == SWT.F5)\r
- refresh();\r
- }\r
- });\r
-\r
- TableColumnLayout ad = new TableColumnLayout();\r
- tableComposite.setLayout(ad);\r
-\r
- viewer.getTable().setHeaderVisible(true);\r
- viewer.getTable().setLinesVisible(true);\r
- viewer.setUseHashlookup(true);\r
-\r
- TableViewerColumn nameColumn = new TableViewerColumn(viewer, SWT.LEFT);\r
- nameColumn.setLabelProvider(new FieldName());\r
- TableViewerColumn typeColumn = new TableViewerColumn(viewer, SWT.LEFT);\r
- typeColumn.setLabelProvider(new FieldType());\r
- TableViewerColumn valueColumn = new TableViewerColumn(viewer, SWT.LEFT);\r
- valueColumn.setLabelProvider(new FieldValue());\r
-\r
- typeColumn.getColumn().setText("Type");\r
- typeColumn.getColumn().setWidth(20);\r
- ad.setColumnData(typeColumn.getColumn(), new ColumnWeightData(10, 140));\r
- nameColumn.getColumn().setText("Name");\r
- nameColumn.getColumn().setWidth(20);\r
- ad.setColumnData(nameColumn.getColumn(), new ColumnWeightData(10, 140));\r
- valueColumn.getColumn().setText("Value");\r
- valueColumn.getColumn().setWidth(20);\r
- ad.setColumnData(valueColumn.getColumn(), new ColumnWeightData(90, 200));\r
-\r
- selectionProvider.addSelectionChangedListener(this);\r
-\r
- showStaticItem.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e) {\r
- showStatic = showStaticItem.getSelection();\r
- refresh();\r
- }\r
- });\r
- showTransientItem.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e) {\r
- showTransient = showTransientItem.getSelection();\r
- refresh();\r
- }\r
- });\r
- refresh.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e) {\r
- refresh();\r
- }\r
- });\r
-\r
- // Bootstrap dialog.\r
- refresh();\r
-\r
- applyDialogFont(composite);\r
- return composite;\r
- }\r
-\r
- static class Header {\r
- String name;\r
- public Header(String name) {\r
- this.name = name;\r
- }\r
- @Override\r
- public String toString() {\r
- return name;\r
- }\r
- }\r
-\r
- static class ComputedAttr {\r
- public String name;\r
- public Object object;\r
- public String stringValue;\r
- public ComputedAttr(String name, Object object) {\r
- this(name, object, object != null ? object.toString() : "null");\r
- }\r
- public ComputedAttr(String name, Object object, String stringValue) {\r
- this.name = name;\r
- this.object = object;\r
- this.stringValue = stringValue;\r
- }\r
- @Override\r
- public String toString() {\r
- return stringValue;\r
- }\r
- }\r
-\r
- static class Attr {\r
- Object object;\r
- Field field;\r
- public Attr(Object obj, Field f) {\r
- this.object = obj;\r
- this.field = f;\r
- }\r
- public Object getObject() {\r
- return object;\r
- }\r
- public <T> T getObject(Class<T> clazz) {\r
- return clazz.cast(object);\r
- }\r
- public Field getField() {\r
- return field;\r
- }\r
- @Override\r
- public String toString() {\r
- return field.getName();\r
- }\r
- }\r
-\r
- class FieldContentProvider implements ITreeContentProvider {\r
- @Override\r
- public Object[] getChildren(Object parentElement) {\r
- return new Object[0];\r
- }\r
-\r
- @Override\r
- public Object getParent(Object element) {\r
- return null;\r
- }\r
-\r
- @Override\r
- public boolean hasChildren(Object element) {\r
- return false;\r
- }\r
-\r
- @Override\r
- public Object[] getElements(Object inputElement) {\r
- if (inputElement instanceof NodeProxy) {\r
- NodeProxy np = (NodeProxy) inputElement;\r
- INode node = np.getNode();\r
- if (node == null)\r
- return new Object[0];\r
- List<Object> result = new ArrayList<Object>();\r
-\r
- if (node instanceof IG2DNode) {\r
- IG2DNode g2dnode = (IG2DNode) node;\r
- // Calculate some useful computational properties\r
- result.add(new Header("Computational IG2DNode properties"));\r
- result.add(new ComputedAttr("local bounds", g2dnode.getBoundsInLocal()));\r
- result.add(new ComputedAttr("world bounds", g2dnode.getBounds()));\r
- result.add(new ComputedAttr("local to world transform", NodeUtil.getLocalToGlobalTransform(g2dnode)));\r
- }\r
-\r
- Class<?> clazz = node.getClass();\r
- while (clazz != null && clazz != Object.class) {\r
- if (showClass)\r
- result.add(clazz);\r
- Field[] fields = clazz.getDeclaredFields();\r
- for (int i = 0; i < fields.length; ++i) {\r
- Field f = fields[i];\r
-\r
- // Ignore transient properties, those are generally just caches.\r
- if (!showTransient && Modifier.isTransient(f.getModifiers()))\r
- continue;\r
-\r
- // Ignore statics, those shouldn't affect data transfer.\r
- if (!showStatic && Modifier.isStatic(f.getModifiers()))\r
- continue;\r
-\r
- result.add(new Attr(np, fields[i]));\r
- }\r
- clazz = clazz.getSuperclass();\r
- }\r
- return result.toArray();\r
- }\r
- return new Object[0];\r
- }\r
-\r
- @Override\r
- public void dispose() {\r
- }\r
-\r
- @Override\r
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
- }\r
- }\r
-\r
- abstract class NodeLabelProvider extends ColumnLabelProvider {\r
- @Override\r
- public final void update(ViewerCell cell) {\r
- Object elem = cell.getElement();\r
- if (elem instanceof Attr) {\r
- Attr attr = (Attr) elem;\r
- NodeProxy np = attr.getObject(NodeProxy.class);\r
- INode node = np.getNode();\r
- update(cell, attr, node);\r
- } else if (elem instanceof ComputedAttr) {\r
- ComputedAttr attr = (ComputedAttr) elem;\r
- update(cell, attr);\r
- } else if (elem instanceof Header) {\r
- updateHeader(cell, ((Header) elem).name);\r
- } else if (elem instanceof Class<?>) {\r
- Class<?> clazz = (Class<?>) elem;\r
- updateHeader(cell, clazz.getSimpleName());\r
- }\r
- }\r
-\r
- public abstract void update(ViewerCell cell, ComputedAttr attr);\r
- public abstract void update(ViewerCell cell, Attr attr, INode node);\r
- public void updateHeader(ViewerCell cell, String header) {\r
- cell.setFont(resourceManager.createFont(FontDescriptor.createFrom(cell.getFont()).withStyle(SWT.BOLD|SWT.ITALIC)));\r
- cell.setForeground(cell.getControl().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));\r
- cell.setBackground(cell.getControl().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));\r
- }\r
- }\r
-\r
- class FieldType extends NodeLabelProvider {\r
- @Override\r
- public void update(ViewerCell cell, ComputedAttr attr) {\r
- cell.setText(attr.object != null ? attr.object.getClass().getSimpleName() : "null");\r
- }\r
- @Override\r
- public void update(ViewerCell cell, Attr attr, INode node) {\r
- Field f = attr.getField();\r
- cell.setText(f.getType().getSimpleName());\r
- }\r
- }\r
-\r
- class FieldName extends NodeLabelProvider {\r
- @Override\r
- public void update(ViewerCell cell, ComputedAttr attr) {\r
- cell.setText(attr.name);\r
- }\r
- @Override\r
- public void update(ViewerCell cell, Attr attr, INode node) {\r
- Field f = attr.getField();\r
- cell.setText(f.getName());\r
- }\r
- @Override\r
- public void updateHeader(ViewerCell cell, String header) {\r
- super.updateHeader(cell, header);\r
- cell.setText(header);\r
- }\r
- }\r
-\r
- class FieldValue extends NodeLabelProvider {\r
- @Override\r
- public void update(ViewerCell cell, ComputedAttr attr) {\r
- cell.setText(attr.stringValue);\r
- }\r
- @Override\r
- public void update(ViewerCell cell, Attr attr, INode node) {\r
- Field f = attr.getField();\r
- boolean accessible = f.isAccessible();\r
- try {\r
- if (!accessible)\r
- f.setAccessible(true);\r
- Object value = f.get(node);\r
- String label = value == null ? "null" : ValueUtils.toString(value);\r
- cell.setText(label);\r
-\r
- if (Modifier.isStatic(f.getModifiers())) {\r
- cell.setBackground((Color) resourceManager.get(staticColor));\r
- } else if (Modifier.isTransient(f.getModifiers())) {\r
- cell.setBackground((Color) resourceManager.get(transientColor));\r
- }\r
- } catch (IllegalArgumentException e) {\r
- e.printStackTrace();\r
- cell.setText(e.getMessage());\r
- } catch (IllegalAccessException e) {\r
- e.printStackTrace();\r
- cell.setText(e.getMessage());\r
- } finally {\r
- if (!accessible)\r
- f.setAccessible(false);\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public void selectionChanged(SelectionChangedEvent event) {\r
- selectionChanged(event.getSelection());\r
- }\r
-\r
- public void selectionChanged(ISelection selection) {\r
- //System.out.println("selection changed: " + event);\r
- IStructuredSelection ss = (IStructuredSelection) selection;\r
- Object obj = ss.getFirstElement();\r
- if (ss.size() == 1 || (obj instanceof NodeProxy)) {\r
- viewer.setInput(obj);\r
- } else {\r
- viewer.setInput(new Object());\r
- }\r
- }\r
-\r
- public void refresh() {\r
- selectionChanged(selectionProvider.getSelection());\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.scenegraph.ui;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.layout.TableColumnLayout;
+import org.eclipse.jface.resource.ColorDescriptor;
+import org.eclipse.jface.resource.FontDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.utils.datastructures.ValueUtils;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class AttributeDialog extends Dialog implements ISelectionChangedListener {
+
+ private static final String DIALOG = "AttributeDialog"; //$NON-NLS-1$
+
+ private IDialogSettings dialogBoundsSettings;
+
+ private ResourceManager resourceManager;
+
+ private TableViewer viewer;
+
+ private final ISelectionProvider selectionProvider;
+
+ private final boolean showClass = true;
+ private boolean showTransient = false;
+ private boolean showStatic = false;
+
+ private final ColorDescriptor staticColor = ColorDescriptor.createFrom(new RGB(224, 224, 224));
+ private final ColorDescriptor transientColor = ColorDescriptor.createFrom(new RGB(192, 255, 255));
+
+ protected AttributeDialog(Shell parentShell, ISelectionProvider selectionProvider) {
+ super(parentShell);
+ this.selectionProvider = selectionProvider;
+
+ IDialogSettings settings = Activator.getDefault().getDialogSettings();
+ dialogBoundsSettings = settings.getSection(DIALOG);
+ if (dialogBoundsSettings == null)
+ dialogBoundsSettings = settings.addNewSection(DIALOG);
+ }
+
+ @Override
+ protected IDialogSettings getDialogBoundsSettings() {
+ return dialogBoundsSettings;
+ }
+
+ @Override
+ protected int getShellStyle() {
+ return SWT.RESIZE | SWT.MODELESS | SWT.TITLE | SWT.CLOSE | SWT.BORDER;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText("Scene Graph Node Attributes");
+ }
+
+ @Override
+ protected Control createButtonBar(Composite parent) {
+ return parent;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ // No buttons, this is a non-modal property dialog.
+ }
+
+ @Override
+ protected Point getInitialSize() {
+ Point defaultSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+ Point result = super.getInitialSize();
+ if (defaultSize.equals(result))
+ return new Point(500, 300);
+ return result;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ this.resourceManager = new LocalResourceManager(JFaceResources.getResources());
+ composite.addListener(SWT.Dispose, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ selectionProvider.removeSelectionChangedListener(AttributeDialog.this);
+ resourceManager.dispose();
+ resourceManager = null;
+ }
+ });
+
+ GridLayoutFactory.fillDefaults().margins(0, 0).spacing(0, 0).applyTo(composite);
+
+ ToolBar toolbar = new ToolBar(composite, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(toolbar);
+ final ToolItem showStaticItem = new ToolItem(toolbar, SWT.CHECK);
+ showStaticItem.setText("Show &Static");
+ showStaticItem.setToolTipText("Show Static Fields of Selected Object");
+ final ToolItem showTransientItem = new ToolItem(toolbar, SWT.CHECK);
+ showTransientItem.setText("Show &Transient");
+ showTransientItem.setToolTipText("Show Transient Fields of Selected Object");
+ final ToolItem refresh = new ToolItem(toolbar, SWT.PUSH);
+ refresh.setText("&Refresh");
+ refresh.setToolTipText("Refresh Values");
+
+ Composite tableComposite = new Composite(composite, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(tableComposite);
+
+ viewer = new TableViewer(tableComposite, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
+ viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ viewer.setContentProvider(new FieldContentProvider());
+ viewer.getTable().addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == SWT.F5)
+ refresh();
+ }
+ });
+
+ TableColumnLayout ad = new TableColumnLayout();
+ tableComposite.setLayout(ad);
+
+ viewer.getTable().setHeaderVisible(true);
+ viewer.getTable().setLinesVisible(true);
+ viewer.setUseHashlookup(true);
+
+ TableViewerColumn nameColumn = new TableViewerColumn(viewer, SWT.LEFT);
+ nameColumn.setLabelProvider(new FieldName());
+ TableViewerColumn typeColumn = new TableViewerColumn(viewer, SWT.LEFT);
+ typeColumn.setLabelProvider(new FieldType());
+ TableViewerColumn valueColumn = new TableViewerColumn(viewer, SWT.LEFT);
+ valueColumn.setLabelProvider(new FieldValue());
+
+ typeColumn.getColumn().setText("Type");
+ typeColumn.getColumn().setWidth(20);
+ ad.setColumnData(typeColumn.getColumn(), new ColumnWeightData(10, 140));
+ nameColumn.getColumn().setText("Name");
+ nameColumn.getColumn().setWidth(20);
+ ad.setColumnData(nameColumn.getColumn(), new ColumnWeightData(10, 140));
+ valueColumn.getColumn().setText("Value");
+ valueColumn.getColumn().setWidth(20);
+ ad.setColumnData(valueColumn.getColumn(), new ColumnWeightData(90, 200));
+
+ selectionProvider.addSelectionChangedListener(this);
+
+ showStaticItem.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ showStatic = showStaticItem.getSelection();
+ refresh();
+ }
+ });
+ showTransientItem.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ showTransient = showTransientItem.getSelection();
+ refresh();
+ }
+ });
+ refresh.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ refresh();
+ }
+ });
+
+ // Bootstrap dialog.
+ refresh();
+
+ applyDialogFont(composite);
+ return composite;
+ }
+
+ static class Header {
+ String name;
+ public Header(String name) {
+ this.name = name;
+ }
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ static class ComputedAttr {
+ public String name;
+ public Object object;
+ public String stringValue;
+ public ComputedAttr(String name, Object object) {
+ this(name, object, object != null ? object.toString() : "null");
+ }
+ public ComputedAttr(String name, Object object, String stringValue) {
+ this.name = name;
+ this.object = object;
+ this.stringValue = stringValue;
+ }
+ @Override
+ public String toString() {
+ return stringValue;
+ }
+ }
+
+ static class Attr {
+ Object object;
+ Field field;
+ public Attr(Object obj, Field f) {
+ this.object = obj;
+ this.field = f;
+ }
+ public Object getObject() {
+ return object;
+ }
+ public <T> T getObject(Class<T> clazz) {
+ return clazz.cast(object);
+ }
+ public Field getField() {
+ return field;
+ }
+ @Override
+ public String toString() {
+ return field.getName();
+ }
+ }
+
+ class FieldContentProvider implements ITreeContentProvider {
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ return new Object[0];
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ return false;
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof NodeProxy) {
+ NodeProxy np = (NodeProxy) inputElement;
+ INode node = np.getNode();
+ if (node == null)
+ return new Object[0];
+ List<Object> result = new ArrayList<Object>();
+
+ if (node instanceof IG2DNode) {
+ IG2DNode g2dnode = (IG2DNode) node;
+ // Calculate some useful computational properties
+ result.add(new Header("Computational IG2DNode properties"));
+ result.add(new ComputedAttr("local bounds", g2dnode.getBoundsInLocal()));
+ result.add(new ComputedAttr("world bounds", g2dnode.getBounds()));
+ result.add(new ComputedAttr("local to world transform", NodeUtil.getLocalToGlobalTransform(g2dnode)));
+ }
+
+ Class<?> clazz = node.getClass();
+ while (clazz != null && clazz != Object.class) {
+ if (showClass)
+ result.add(clazz);
+ Field[] fields = clazz.getDeclaredFields();
+ for (int i = 0; i < fields.length; ++i) {
+ Field f = fields[i];
+
+ // Ignore transient properties, those are generally just caches.
+ if (!showTransient && Modifier.isTransient(f.getModifiers()))
+ continue;
+
+ // Ignore statics, those shouldn't affect data transfer.
+ if (!showStatic && Modifier.isStatic(f.getModifiers()))
+ continue;
+
+ result.add(new Attr(np, fields[i]));
+ }
+ clazz = clazz.getSuperclass();
+ }
+ return result.toArray();
+ }
+ return new Object[0];
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+
+ abstract class NodeLabelProvider extends ColumnLabelProvider {
+ @Override
+ public final void update(ViewerCell cell) {
+ Object elem = cell.getElement();
+ if (elem instanceof Attr) {
+ Attr attr = (Attr) elem;
+ NodeProxy np = attr.getObject(NodeProxy.class);
+ INode node = np.getNode();
+ update(cell, attr, node);
+ } else if (elem instanceof ComputedAttr) {
+ ComputedAttr attr = (ComputedAttr) elem;
+ update(cell, attr);
+ } else if (elem instanceof Header) {
+ updateHeader(cell, ((Header) elem).name);
+ } else if (elem instanceof Class<?>) {
+ Class<?> clazz = (Class<?>) elem;
+ updateHeader(cell, clazz.getSimpleName() + " (" + clazz.getPackage().getName() + ")");
+ }
+ }
+
+ public abstract void update(ViewerCell cell, ComputedAttr attr);
+ public abstract void update(ViewerCell cell, Attr attr, INode node);
+ public void updateHeader(ViewerCell cell, String header) {
+ cell.setFont(resourceManager.createFont(FontDescriptor.createFrom(cell.getFont()).withStyle(SWT.BOLD|SWT.ITALIC)));
+ cell.setForeground(cell.getControl().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ cell.setBackground(cell.getControl().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ }
+ }
+
+ class FieldType extends NodeLabelProvider {
+ @Override
+ public void update(ViewerCell cell, ComputedAttr attr) {
+ cell.setText(attr.object != null ? attr.object.getClass().getSimpleName() : "null");
+ }
+ @Override
+ public void update(ViewerCell cell, Attr attr, INode node) {
+ Field f = attr.getField();
+ cell.setText(f.getType().getSimpleName());
+ }
+ }
+
+ class FieldName extends NodeLabelProvider {
+ @Override
+ public void update(ViewerCell cell, ComputedAttr attr) {
+ cell.setText(attr.name);
+ }
+ @Override
+ public void update(ViewerCell cell, Attr attr, INode node) {
+ Field f = attr.getField();
+ cell.setText(f.getName());
+ }
+ @Override
+ public void updateHeader(ViewerCell cell, String header) {
+ super.updateHeader(cell, header);
+ cell.setText(header);
+ }
+ }
+
+ class FieldValue extends NodeLabelProvider {
+ @Override
+ public void update(ViewerCell cell, ComputedAttr attr) {
+ cell.setText(attr.stringValue);
+ }
+ @Override
+ public void update(ViewerCell cell, Attr attr, INode node) {
+ Field f = attr.getField();
+ boolean accessible = f.isAccessible();
+ try {
+ if (!accessible)
+ f.setAccessible(true);
+ Object value = f.get(node);
+ String label = value == null ? "null" : ValueUtils.toString(value);
+ cell.setText(label);
+
+ if (Modifier.isStatic(f.getModifiers())) {
+ cell.setBackground((Color) resourceManager.get(staticColor));
+ } else if (Modifier.isTransient(f.getModifiers())) {
+ cell.setBackground((Color) resourceManager.get(transientColor));
+ }
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ cell.setText(e.getMessage());
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ cell.setText(e.getMessage());
+ } finally {
+ if (!accessible)
+ f.setAccessible(false);
+ }
+ }
+ }
+
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ selectionChanged(event.getSelection());
+ }
+
+ public void selectionChanged(ISelection selection) {
+ //System.out.println("selection changed: " + event);
+ IStructuredSelection ss = (IStructuredSelection) selection;
+ Object obj = ss.getFirstElement();
+ if (ss.size() == 1 || (obj instanceof NodeProxy)) {
+ viewer.setInput(obj);
+ } else {
+ viewer.setInput(new Object());
+ }
+ }
+
+ public void refresh() {
+ selectionChanged(selectionProvider.getSelection());
+ }
+
+}