-package org.simantics.browsing.ui.nattable;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.eclipse.core.runtime.IAdaptable;\r
-import org.eclipse.jface.resource.ColorDescriptor;\r
-import org.eclipse.jface.resource.FontDescriptor;\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;\r
-import org.eclipse.nebula.widgets.nattable.style.Style;\r
-import org.eclipse.swt.graphics.Color;\r
-import org.eclipse.swt.graphics.Font;\r
-import org.eclipse.swt.graphics.Image;\r
-import org.simantics.browsing.ui.BuiltinKeys;\r
-import org.simantics.browsing.ui.NodeContext;\r
-import org.simantics.browsing.ui.common.internal.GENodeQueryManager;\r
-import org.simantics.browsing.ui.content.ImageDecorator;\r
-import org.simantics.browsing.ui.content.Imager;\r
-import org.simantics.browsing.ui.content.LabelDecorator;\r
-import org.simantics.browsing.ui.content.Labeler;\r
-import org.simantics.browsing.ui.nattable.NatTableGraphExplorer.GECache2;\r
-import org.simantics.browsing.ui.nattable.NatTableGraphExplorer.GeViewerContext;\r
-import org.simantics.browsing.ui.swt.ViewerRowReference;\r
-import org.simantics.utils.datastructures.BijectionMap;\r
-\r
-public class TreeNode implements IAdaptable {\r
- private static boolean DEBUG = false;\r
- \r
- private NodeContext context;\r
- GENodeQueryManager manager;\r
- GeViewerContext explorerContext;\r
- \r
- TreeNode parent;\r
- List<TreeNode> children = new ArrayList<TreeNode>();\r
- boolean expanded;\r
- \r
- public TreeNode(NodeContext context, GeViewerContext explorerContext) {\r
- this.context = context;\r
- this.explorerContext = explorerContext;\r
- this.expanded = false;\r
- manager = new GENodeQueryManager(explorerContext, null, null, ViewerRowReference.create(this));\r
- explorerContext.getContextToNodeMap().add(context, this);\r
- }\r
- \r
- int getDepth() {\r
- if (parent == null)\r
- return 0;\r
- return parent.getDepth() + 1;\r
- }\r
- \r
- int listIndex;\r
- \r
- public int getListIndex() {\r
- return listIndex;\r
- }\r
- \r
- public void setListIndex(int listIndex) {\r
- this.listIndex = listIndex;\r
- }\r
- \r
- List<TreeNode> getChildren() {\r
- return children;\r
- }\r
- \r
- public TreeNode getParent() {\r
- return parent;\r
- }\r
- \r
- public void setExpanded(boolean expanded) {\r
- this.expanded = expanded;\r
- }\r
- \r
- public boolean isExpanded() {\r
- return expanded;\r
- }\r
- \r
- public NodeContext getContext() {\r
- return context;\r
- }\r
- \r
- private Labeler labeler;\r
- private Imager imager;\r
- Collection<LabelDecorator> labelDecorators;\r
- Collection<ImageDecorator> imageDecorators;\r
- \r
- Map<String, String> labels;\r
- Map<String, String> runtimeLabels;\r
- \r
- public String getValueString(int column) {\r
- if (column == 0) {\r
- initData();\r
- }\r
- if (labeler != null) {\r
- String key = explorerContext.getGe().getColumns()[column].getKey();\r
- String s = null;\r
- if (runtimeLabels != null)\r
- s = runtimeLabels.get(key);\r
- if (s == null)\r
- s = labels.get(key);\r
- if (labelDecorators != null && !labelDecorators.isEmpty()) {\r
- int index = 0;\r
- for (LabelDecorator ld : labelDecorators) {\r
- String ds = ld.decorateLabel(s, key, index);\r
- if (ds != null)\r
- s = ds;\r
- }\r
- }\r
- return s;\r
- }\r
- return null;\r
- }\r
- \r
- public Image getImage(int column) {\r
- String key = explorerContext.getGe().getColumns()[column].getKey();\r
- if (imager != null) {\r
- Object descOrImage = null;\r
- boolean hasUncachedImages = false;\r
-\r
- ImageDescriptor desc = imager.getImage(key);\r
- if (desc != null) {\r
- int index = 0;\r
- // Attempt to decorate the label\r
- if (!imageDecorators.isEmpty()) {\r
- for (ImageDecorator id : imageDecorators) {\r
- ImageDescriptor ds = id.decorateImage(desc, key, index);\r
- if (ds != null)\r
- desc = ds;\r
- }\r
- }\r
-\r
- // Try resolving only cached images here and now\r
- Object img = explorerContext.getGe().localResourceManager.find(desc);\r
- if (img == null)\r
- img = explorerContext.getGe().resourceManager.find(desc);\r
-\r
- descOrImage = img != null ? img : desc;\r
- hasUncachedImages |= img == null;\r
- }\r
-\r
- if (!hasUncachedImages) {\r
- return (Image) descOrImage;\r
- } else {\r
- // Schedule loading to another thread to refrain from\r
- // blocking\r
- // the UI with database operations.\r
- explorerContext.getGe().queueImageTask(this, new ImageTask(this, descOrImage));\r
- return null;\r
- }\r
- } else {\r
- return null;\r
- }\r
- }\r
- \r
- public void getStyle(int column, Style style) {\r
- String key = explorerContext.getGe().getColumns()[column].getKey();\r
- FontDescriptor font = explorerContext.getGe().originalFont;\r
- ColorDescriptor bg = explorerContext.getGe().originalBackground;\r
- ColorDescriptor fg = explorerContext.getGe().originalForeground;\r
- \r
- // Attempt to decorate the label\r
- if (labelDecorators != null && !labelDecorators.isEmpty()) {\r
- int index = 0;\r
- for (LabelDecorator ld : labelDecorators) {\r
-\r
- FontDescriptor dfont = ld.decorateFont(font, key, index);\r
- if (dfont != null)\r
- font = dfont;\r
-\r
- ColorDescriptor dbg = ld.decorateBackground(bg, key, index);\r
- if (dbg != null)\r
- bg = dbg;\r
-\r
- ColorDescriptor dfg = ld.decorateForeground(fg, key, index);\r
- if (dfg != null)\r
- fg = dfg;\r
- }\r
- }\r
-\r
- if (font != explorerContext.getGe().originalFont) {\r
- // System.out.println("set font: " + index + ": " +\r
- // font);\r
- style.setAttributeValue(CellStyleAttributes.FONT,(Font) explorerContext.getGe().localResourceManager.get(font));\r
- } else {\r
- style.setAttributeValue(CellStyleAttributes.FONT,(Font) (explorerContext.getGe().originalFont != null ? explorerContext.getGe().localResourceManager.get(explorerContext.getGe().originalFont) : null));\r
- }\r
- if (bg != explorerContext.getGe().originalBackground)\r
- style.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR,(Color) explorerContext.getGe().localResourceManager.get(bg));\r
- else\r
- style.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR,(Color) (explorerContext.getGe().originalBackground != null ? explorerContext.getGe().localResourceManager.get(explorerContext.getGe().originalBackground) : null));\r
- if (fg != explorerContext.getGe().originalForeground)\r
- style.setAttributeValue(CellStyleAttributes.FOREGROUND_COLOR,(Color) explorerContext.getGe().localResourceManager.get(fg));\r
- else\r
- style.setAttributeValue(CellStyleAttributes.FOREGROUND_COLOR,(Color) (explorerContext.getGe().originalForeground != null ? explorerContext.getGe().localResourceManager.get(explorerContext.getGe().originalForeground) : null));\r
-\r
- }\r
- \r
- private void initData() {\r
- labeler = manager.query(context, BuiltinKeys.SELECTED_LABELER);\r
- imager = manager.query(context, BuiltinKeys.SELECTED_IMAGER);\r
- labelDecorators = manager.query(context, BuiltinKeys.LABEL_DECORATORS);\r
- imageDecorators = manager.query(context, BuiltinKeys.IMAGE_DECORATORS);\r
- \r
- if (labeler != null) {\r
- labels = labeler.getLabels();\r
- runtimeLabels = labeler.getRuntimeLabels();\r
- } else {\r
- labels = null;\r
- runtimeLabels = null;\r
- }\r
- }\r
- \r
- public TreeNode addChild(NodeContext context, GeViewerContext explorerContext) {\r
- TreeNode child = new TreeNode(context, explorerContext);\r
- child.parent = this;\r
- children.add(child);\r
- if (DEBUG) System.out.println("Add " + this + " -> " + child);\r
- return child;\r
- }\r
- \r
- public TreeNode addChild(int index, NodeContext context,GeViewerContext explorerContext) {\r
- \r
- TreeNode child = new TreeNode(context, explorerContext);\r
- child.parent = this;\r
- children.add(index,child);\r
- if (DEBUG) System.out.println("Add " + this + " -> " + child + " at " + index);\r
- return child;\r
- }\r
- \r
- public TreeNode setChild(int index, NodeContext context, GeViewerContext explorerContext) {\r
- \r
- TreeNode child = new TreeNode(context, explorerContext);\r
- child.parent = this;\r
- children.set(index,child);\r
- if (DEBUG) System.out.println("Set " + this + " -> " + child + " at " + index);\r
- return child;\r
- }\r
- \r
- public void dispose() {\r
- if (parent != null)\r
- parent.children.remove(this);\r
- dispose2();\r
- }\r
- \r
- public void dispose2() {\r
- if (DEBUG) System.out.println("dispose " + this);\r
- parent = null;\r
- for (TreeNode n : children) {\r
- n.dispose2();\r
- }\r
- clearCache();\r
- children.clear();\r
- explorerContext.getContextToNodeMap().remove(context, this);\r
- context = null;\r
- explorerContext = null;\r
- manager.dispose();\r
- manager = null; \r
- }\r
- \r
- private void clearCache() {\r
- if (explorerContext != null) {\r
- GECache2 cache = explorerContext.cache;\r
- \r
- if (cache != null) {\r
- cache.dispose(context);\r
- }\r
- }\r
- }\r
- \r
- public boolean updateChildren() {\r
- if (context == null)\r
- throw new IllegalStateException("Node is disposed.");\r
- \r
- NodeContext[] childContexts = manager.query(context, BuiltinKeys.FINAL_CHILDREN);\r
- \r
- if (DEBUG) System.out.println("updateChildren " + childContexts.length + " " + this);\r
- \r
- \r
- boolean modified = false;\r
- synchronized (children) {\r
- \r
- int oldCount = children.size();\r
- BijectionMap<Integer, Integer> indexes = new BijectionMap<Integer, Integer>();\r
- Set<Integer> mapped = new HashSet<Integer>();\r
- boolean reorder = false;\r
- // locate matching pairs form old and new children\r
- for (int i = 0; i < oldCount; i++) {\r
- NodeContext oldCtx = children.get(i).context;\r
- for (int j = 0; j <childContexts.length; j++) {\r
- if (mapped.contains(j))\r
- continue;\r
- if (oldCtx.equals(childContexts[j])) {\r
- indexes.map(i, j);\r
- mapped.add(j);\r
- if (i != j)\r
- reorder = true;\r
- break;\r
- }\r
- }\r
- }\r
- // update children if required\r
- if (childContexts.length != oldCount || reorder || childContexts.length != indexes.size()) {\r
- modified = true;\r
- List<TreeNode> oldChildren = new ArrayList<TreeNode>(oldCount);\r
- oldChildren.addAll(children);\r
- if (childContexts.length >= oldCount) {\r
- for (int i = 0; i < oldCount; i++) {\r
- Integer oldIndex = indexes.getLeft(i);\r
- if (oldIndex == null) {\r
- setChild(i, childContexts[i], explorerContext);\r
- } else {\r
- TreeNode n = oldChildren.get(oldIndex);\r
- children.set(i, n);\r
- }\r
- \r
- }\r
- for (int i = oldCount; i < childContexts.length; i++) {\r
- addChild(childContexts[i], explorerContext);\r
- }\r
- } else {\r
- for (int i = 0; i < childContexts.length; i++) {\r
- Integer oldIndex = indexes.getLeft(i);\r
- if (oldIndex == null) {\r
- setChild(i, childContexts[i], explorerContext);\r
- } else {\r
- TreeNode n = oldChildren.get(oldIndex);\r
- children.set(i, n);\r
- }\r
- }\r
- for (int i = oldCount -1; i >= childContexts.length; i--) {\r
- children.remove(i);\r
- }\r
- }\r
- for (int i = 0; i < oldChildren.size(); i++) {\r
- if (!indexes.containsLeft(i)) {\r
- oldChildren.get(i).dispose2();\r
- }\r
- }\r
- \r
- }\r
- \r
- }\r
- return modified;\r
- }\r
- \r
- public boolean isDisposed() {\r
- return context == null;\r
- }\r
- \r
- public GENodeQueryManager getManager() {\r
- return manager;\r
- }\r
- \r
- @SuppressWarnings("rawtypes")\r
- @Override\r
- public Object getAdapter(Class adapter) {\r
- if (adapter == NodeContext.class)\r
- return context;\r
- \r
- return context.getAdapter(adapter);\r
- }\r
-\r
-}\r
+package org.simantics.browsing.ui.nattable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.resource.ColorDescriptor;
+import org.eclipse.jface.resource.FontDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
+import org.eclipse.nebula.widgets.nattable.style.Style;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.simantics.browsing.ui.BuiltinKeys;
+import org.simantics.browsing.ui.NodeContext;
+import org.simantics.browsing.ui.common.internal.GENodeQueryManager;
+import org.simantics.browsing.ui.content.ImageDecorator;
+import org.simantics.browsing.ui.content.Imager;
+import org.simantics.browsing.ui.content.LabelDecorator;
+import org.simantics.browsing.ui.content.Labeler;
+import org.simantics.browsing.ui.nattable.NatTableGraphExplorer.GECache2;
+import org.simantics.browsing.ui.nattable.NatTableGraphExplorer.GeViewerContext;
+import org.simantics.browsing.ui.swt.ViewerRowReference;
+import org.simantics.utils.datastructures.BijectionMap;
+
+public class TreeNode implements IAdaptable {
+ private static boolean DEBUG = false;
+
+ private NodeContext context;
+ GENodeQueryManager manager;
+ GeViewerContext explorerContext;
+
+ TreeNode parent;
+ List<TreeNode> children = new ArrayList<TreeNode>();
+ boolean expanded;
+ boolean autoExpanded = false;
+
+ public TreeNode(NodeContext context, GeViewerContext explorerContext) {
+ this.context = context;
+ this.explorerContext = explorerContext;
+ this.expanded = false;
+ manager = new GENodeQueryManager(explorerContext, null, null, ViewerRowReference.create(this));
+ explorerContext.getContextToNodeMap().add(context, this);
+ }
+
+ public int getDepth() {
+ if (parent == null)
+ return 0;
+ return parent.getDepth() + 1;
+ }
+
+ int listIndex = -1;
+
+ public int getListIndex() {
+ return listIndex;
+ }
+
+ public void setListIndex(int listIndex) {
+ this.listIndex = listIndex;
+ }
+
+ List<TreeNode> getChildren() {
+ return children;
+ }
+
+ public TreeNode getParent() {
+ return parent;
+ }
+
+ public void setExpanded(boolean expanded) {
+ this.expanded = expanded;
+ }
+
+ public boolean isExpanded() {
+ return expanded;
+ }
+
+ public boolean isHidden() {
+ TreeNode n = parent;
+ while (n != null) {
+ if (!n.isExpanded())
+ return true;
+ n = n.getParent();
+ }
+ return false;
+ }
+
+ public TreeNode getCollapsedAncestor() {
+ TreeNode collapsed = null;
+ TreeNode n = parent;
+ while (n != null) {
+ if (!n.isExpanded())
+ collapsed = n;
+ n = n.getParent();
+ }
+ return collapsed;
+ }
+
+ public NodeContext getContext() {
+ return context;
+ }
+
+ private Labeler labeler;
+ private Imager imager;
+ Collection<LabelDecorator> labelDecorators;
+ Collection<ImageDecorator> imageDecorators;
+
+ Map<String, String> labels;
+ Map<String, String> runtimeLabels;
+
+ public String getValueString(int column) {
+ if (labels == null)
+ initData();
+ if (labeler != null) {
+ String key = explorerContext.getGe().getColumns()[column].getKey();
+ return getValue(key);
+ }
+ return null;
+ }
+
+ private String getValue(String key) {
+ String s = null;
+ if (runtimeLabels != null)
+ s = runtimeLabels.get(key);
+ if (s == null)
+ s = labels.get(key);
+ if (labelDecorators != null && !labelDecorators.isEmpty()) {
+ int index = 0;
+ for (LabelDecorator ld : labelDecorators) {
+ String ds = ld.decorateLabel(s, key, index);
+ if (ds != null)
+ s = ds;
+ }
+ }
+ return s;
+ }
+
+ public String getValueString(String key) {
+ if (labels == null)
+ initData();
+ if (labeler != null) {
+ return getValue(key);
+ }
+ return null;
+ }
+
+ public Image getImage(int column) {
+ String key = explorerContext.getGe().getColumns()[column].getKey();
+ if (imager != null) {
+ Object descOrImage = null;
+ boolean hasUncachedImages = false;
+
+ ImageDescriptor desc = imager.getImage(key);
+ if (desc != null) {
+ int index = 0;
+ // Attempt to decorate the label
+ if (!imageDecorators.isEmpty()) {
+ for (ImageDecorator id : imageDecorators) {
+ ImageDescriptor ds = id.decorateImage(desc, key, index);
+ if (ds != null)
+ desc = ds;
+ }
+ }
+
+ // Try resolving only cached images here and now
+ Object img = explorerContext.getGe().localResourceManager.find(desc);
+ if (img == null)
+ img = explorerContext.getGe().resourceManager.find(desc);
+
+ descOrImage = img != null ? img : desc;
+ hasUncachedImages |= img == null;
+ }
+
+ if (!hasUncachedImages) {
+ return (Image) descOrImage;
+ } else {
+ // Schedule loading to another thread to refrain from
+ // blocking
+ // the UI with database operations.
+ explorerContext.getGe().queueImageTask(this, new ImageTask(this, descOrImage));
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public void getStyle(int column, Style style) {
+ String key = explorerContext.getGe().getColumns()[column].getKey();
+ FontDescriptor font = explorerContext.getGe().originalFont;
+ ColorDescriptor bg = explorerContext.getGe().originalBackground;
+ ColorDescriptor fg = explorerContext.getGe().originalForeground;
+
+ // Attempt to decorate the label
+ if (labelDecorators != null && !labelDecorators.isEmpty()) {
+ int index = 0;
+ for (LabelDecorator ld : labelDecorators) {
+
+ FontDescriptor dfont = ld.decorateFont(font, key, index);
+ if (dfont != null)
+ font = dfont;
+
+ ColorDescriptor dbg = ld.decorateBackground(bg, key, index);
+ if (dbg != null)
+ bg = dbg;
+
+ ColorDescriptor dfg = ld.decorateForeground(fg, key, index);
+ if (dfg != null)
+ fg = dfg;
+ }
+ }
+
+ if (font != explorerContext.getGe().originalFont) {
+ // System.out.println("set font: " + index + ": " +
+ // font);
+ style.setAttributeValue(CellStyleAttributes.FONT,(Font) explorerContext.getGe().localResourceManager.get(font));
+ } else {
+ style.setAttributeValue(CellStyleAttributes.FONT,(Font) (explorerContext.getGe().originalFont != null ? explorerContext.getGe().localResourceManager.get(explorerContext.getGe().originalFont) : null));
+ }
+ if (bg != explorerContext.getGe().originalBackground)
+ style.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR,(Color) explorerContext.getGe().localResourceManager.get(bg));
+ else
+ style.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR,(Color) (explorerContext.getGe().originalBackground != null ? explorerContext.getGe().localResourceManager.get(explorerContext.getGe().originalBackground) : null));
+ if (fg != explorerContext.getGe().originalForeground)
+ style.setAttributeValue(CellStyleAttributes.FOREGROUND_COLOR,(Color) explorerContext.getGe().localResourceManager.get(fg));
+ else
+ style.setAttributeValue(CellStyleAttributes.FOREGROUND_COLOR,(Color) (explorerContext.getGe().originalForeground != null ? explorerContext.getGe().localResourceManager.get(explorerContext.getGe().originalForeground) : null));
+
+ }
+
+ public void initData() {
+ labeler = manager.query(context, BuiltinKeys.SELECTED_LABELER);
+ imager = manager.query(context, BuiltinKeys.SELECTED_IMAGER);
+ labelDecorators = manager.query(context, BuiltinKeys.LABEL_DECORATORS);
+ imageDecorators = manager.query(context, BuiltinKeys.IMAGE_DECORATORS);
+
+ if (labeler != null) {
+ labels = labeler.getLabels();
+ runtimeLabels = labeler.getRuntimeLabels();
+ } else {
+ labels = null;
+ runtimeLabels = null;
+ }
+ }
+
+ public TreeNode addChild(NodeContext context, GeViewerContext explorerContext) {
+ TreeNode child = new TreeNode(context, explorerContext);
+ child.parent = this;
+ children.add(child);
+ if (DEBUG) System.out.println("Add " + this + " -> " + child);
+ return child;
+ }
+
+ public TreeNode addChild(int index, NodeContext context,GeViewerContext explorerContext) {
+
+ TreeNode child = new TreeNode(context, explorerContext);
+ child.parent = this;
+ children.add(index,child);
+ if (DEBUG) System.out.println("Add " + this + " -> " + child + " at " + index);
+ return child;
+ }
+
+ public TreeNode setChild(int index, NodeContext context, GeViewerContext explorerContext) {
+
+ TreeNode child = new TreeNode(context, explorerContext);
+ child.parent = this;
+ children.set(index,child);
+ if (DEBUG) System.out.println("Set " + this + " -> " + child + " at " + index);
+ return child;
+ }
+
+ public void dispose() {
+ if (parent != null)
+ parent.children.remove(this);
+ dispose2();
+ }
+
+ public void dispose2() {
+ if (DEBUG) System.out.println("dispose " + this);
+ parent = null;
+ for (TreeNode n : children) {
+ n.dispose2();
+ }
+ clearCache();
+ children.clear();
+ explorerContext.getContextToNodeMap().remove(context, this);
+ context = null;
+ explorerContext = null;
+ manager.dispose();
+ manager = null;
+ }
+
+ /**
+ * Fast dispose is used to wipe the whole tree.
+ *
+ * ContextToNodeMap is cleared with one command, so we do not need to remove nodes one by one from the map.
+ */
+ public void fastDispose() {
+ if (DEBUG) System.out.println("dispose " + this);
+ parent = null;
+ for (TreeNode n : children) {
+ n.fastDispose();
+ }
+ clearCache();
+ children.clear();
+ context = null;
+ explorerContext = null;
+ manager.dispose();
+ manager = null;
+ }
+
+ private void clearCache() {
+ if (explorerContext != null) {
+ GECache2 cache = explorerContext.cache;
+
+ if (cache != null) {
+ cache.dispose(context);
+ }
+ }
+ }
+
+ public boolean updateChildren() {
+ if (context == null)
+ throw new IllegalStateException("Node is disposed.");
+
+ NodeContext[] childContexts = manager.query(context, BuiltinKeys.FINAL_CHILDREN);
+
+ if (DEBUG) System.out.println("updateChildren " + childContexts.length + " " + this);
+
+
+ boolean modified = false;
+ synchronized (children) {
+
+ int oldCount = children.size();
+ BijectionMap<Integer, Integer> indexes = new BijectionMap<Integer, Integer>();
+ Set<Integer> mapped = new HashSet<Integer>();
+ boolean reorder = false;
+ // locate matching pairs form old and new children
+ for (int i = 0; i < oldCount; i++) {
+ NodeContext oldCtx = children.get(i).context;
+ for (int j = 0; j <childContexts.length; j++) {
+ if (mapped.contains(j))
+ continue;
+ if (oldCtx.equals(childContexts[j])) {
+ indexes.map(i, j);
+ mapped.add(j);
+ if (i != j)
+ reorder = true;
+ break;
+ }
+ }
+ }
+ // update children if required
+ if (childContexts.length != oldCount || reorder || childContexts.length != indexes.size()) {
+ modified = true;
+ List<TreeNode> oldChildren = new ArrayList<TreeNode>(oldCount);
+ oldChildren.addAll(children);
+ if (childContexts.length >= oldCount) {
+ for (int i = 0; i < oldCount; i++) {
+ Integer oldIndex = indexes.getLeft(i);
+ if (oldIndex == null) {
+ setChild(i, childContexts[i], explorerContext);
+ } else {
+ TreeNode n = oldChildren.get(oldIndex);
+ children.set(i, n);
+ }
+
+ }
+ for (int i = oldCount; i < childContexts.length; i++) {
+ Integer oldIndex = indexes.getLeft(i);
+ if (oldIndex == null) {
+ addChild(childContexts[i], explorerContext);
+ } else {
+ TreeNode n = oldChildren.get(oldIndex);
+ children.add(n);
+ }
+ }
+ } else {
+ for (int i = 0; i < childContexts.length; i++) {
+ Integer oldIndex = indexes.getLeft(i);
+ if (oldIndex == null) {
+ setChild(i, childContexts[i], explorerContext);
+ } else {
+ TreeNode n = oldChildren.get(oldIndex);
+ children.set(i, n);
+ }
+ }
+ for (int i = oldCount -1; i >= childContexts.length; i--) {
+ children.remove(i);
+ }
+ }
+ for (int i = 0; i < oldChildren.size(); i++) {
+ if (!indexes.containsLeft(i)) {
+ oldChildren.get(i).dispose2();
+ }
+ }
+
+ }
+
+ }
+ return modified;
+ }
+
+ public boolean isDisposed() {
+ return context == null;
+ }
+
+ public GENodeQueryManager getManager() {
+ return manager;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Object getAdapter(Class adapter) {
+ if (adapter == NodeContext.class)
+ return context;
+
+ return context.getAdapter(adapter);
+ }
+
+ @Override
+ public String toString() {
+ return "TreeNode: " + listIndex + " " + (expanded ? "(+)" : "(-)") + " " + context ;
+ }
+
+}