X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui.nattable%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fnattable%2FTreeNode.java;h=4f9273d9120cfd48547986b1fcb630120fe98582;hp=941c6f319be56e491909cc35472e7173a5040ccf;hb=bbfae087089fa3126eefb18207fde0cfaa7315a3;hpb=e02b8761385c8b353cccabab32897353f764cac6 diff --git a/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/TreeNode.java b/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/TreeNode.java index 941c6f319..4f9273d91 100644 --- a/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/TreeNode.java +++ b/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/TreeNode.java @@ -1,367 +1,412 @@ -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 children = new ArrayList(); - boolean expanded; - - 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); - } - - int getDepth() { - if (parent == null) - return 0; - return parent.getDepth() + 1; - } - - int listIndex; - - public int getListIndex() { - return listIndex; - } - - public void setListIndex(int listIndex) { - this.listIndex = listIndex; - } - - List getChildren() { - return children; - } - - public TreeNode getParent() { - return parent; - } - - public void setExpanded(boolean expanded) { - this.expanded = expanded; - } - - public boolean isExpanded() { - return expanded; - } - - public NodeContext getContext() { - return context; - } - - private Labeler labeler; - private Imager imager; - Collection labelDecorators; - Collection imageDecorators; - - Map labels; - Map runtimeLabels; - - public String getValueString(int column) { - if (column == 0) { - initData(); - } - if (labeler != null) { - String key = explorerContext.getGe().getColumns()[column].getKey(); - 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; - } - 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)); - - } - - private 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; - } - - 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 indexes = new BijectionMap(); - Set mapped = new HashSet(); - 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 oldChildren = new ArrayList(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++) { - addChild(childContexts[i], explorerContext); - } - } 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); - } - -} +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 children = new ArrayList(); + 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 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 labelDecorators; + Collection imageDecorators; + + Map labels; + Map 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; + } + + 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 indexes = new BijectionMap(); + Set mapped = new HashSet(); + 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 oldChildren = new ArrayList(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 ; + } + +}