X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph.ui%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Fui%2FAttributeDialog.java;h=f291d07b198152c75dd522aa9893857dab7d00e7;hb=7396956f115b87067970f690588017fc05393e7a;hp=bd6d7670ac84b544cbec4e426133ae68a9ce232f;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scenegraph.ui/src/org/simantics/scenegraph/ui/AttributeDialog.java b/bundles/org.simantics.scenegraph.ui/src/org/simantics/scenegraph/ui/AttributeDialog.java index bd6d7670a..f291d07b1 100644 --- a/bundles/org.simantics.scenegraph.ui/src/org/simantics/scenegraph/ui/AttributeDialog.java +++ b/bundles/org.simantics.scenegraph.ui/src/org/simantics/scenegraph/ui/AttributeDialog.java @@ -1,456 +1,456 @@ -/******************************************************************************* - * 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 getObject(Class 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 result = new ArrayList(); - - 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()); - } - } - - 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()); - } - -} +/******************************************************************************* + * 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 getObject(Class 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 result = new ArrayList(); + + 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()); + } + +}