]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java
Improvements to modelled SWT documents
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / widgets / GraphExplorerComposite.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2018 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.browsing.ui.swt.widgets;
13
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashSet;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.function.BiFunction;
20
21 import org.eclipse.core.runtime.IAdaptable;
22 import org.eclipse.jface.action.IMenuManager;
23 import org.eclipse.jface.layout.GridDataFactory;
24 import org.eclipse.jface.layout.GridLayoutFactory;
25 import org.eclipse.jface.layout.TreeColumnLayout;
26 import org.eclipse.jface.resource.JFaceResources;
27 import org.eclipse.jface.resource.LocalResourceManager;
28 import org.eclipse.jface.viewers.ColumnWeightData;
29 import org.eclipse.jface.viewers.ISelectionProvider;
30 import org.eclipse.swt.SWT;
31 import org.eclipse.swt.dnd.DND;
32 import org.eclipse.swt.dnd.DragSource;
33 import org.eclipse.swt.dnd.DragSourceEvent;
34 import org.eclipse.swt.dnd.DragSourceListener;
35 import org.eclipse.swt.dnd.DropTarget;
36 import org.eclipse.swt.dnd.DropTargetEvent;
37 import org.eclipse.swt.dnd.DropTargetListener;
38 import org.eclipse.swt.dnd.FileTransfer;
39 import org.eclipse.swt.dnd.TextTransfer;
40 import org.eclipse.swt.dnd.Transfer;
41 import org.eclipse.swt.widgets.Composite;
42 import org.eclipse.swt.widgets.Control;
43 import org.eclipse.swt.widgets.Event;
44 import org.eclipse.swt.widgets.Listener;
45 import org.eclipse.swt.widgets.Tree;
46 import org.eclipse.swt.widgets.TreeItem;
47 import org.eclipse.ui.ISelectionListener;
48 import org.eclipse.ui.IWorkbenchSite;
49 import org.eclipse.ui.contexts.IContextService;
50 import org.simantics.Simantics;
51 import org.simantics.browsing.ui.BuiltinKeys;
52 import org.simantics.browsing.ui.Column;
53 import org.simantics.browsing.ui.ExplorerState;
54 import org.simantics.browsing.ui.GraphExplorer;
55 import org.simantics.browsing.ui.GraphExplorer.TransientExplorerState;
56 import org.simantics.browsing.ui.NodeContext;
57 import org.simantics.browsing.ui.StatePersistor;
58 import org.simantics.browsing.ui.common.AdaptableHintContext;
59 import org.simantics.browsing.ui.common.ColumnKeys;
60 import org.simantics.browsing.ui.common.EvaluatorData;
61 import org.simantics.browsing.ui.common.EvaluatorDataImpl;
62 import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;
63 import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;
64 import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;
65 import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;
66 import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;
67 import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;
68 import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
69 import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
70 import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
71 import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
72 import org.simantics.browsing.ui.common.state.ExplorerStates;
73 import org.simantics.browsing.ui.common.views.FilterAreaSource;
74 import org.simantics.browsing.ui.common.views.IFilterArea;
75 import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
76 import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;
77 import org.simantics.browsing.ui.graph.impl.Evaluators;
78 import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;
79 import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;
80 import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
81 import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;
82 import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
83 import org.simantics.browsing.ui.model.nodetypes.NodeType;
84 import org.simantics.browsing.ui.swt.ComparatorSelector;
85 import org.simantics.browsing.ui.swt.ContextMenuInitializer;
86 import org.simantics.browsing.ui.swt.DefaultExplorerSelectionListener;
87 import org.simantics.browsing.ui.swt.DefaultIsCheckedProcessor2;
88 import org.simantics.browsing.ui.swt.DefaultKeyListener;
89 import org.simantics.browsing.ui.swt.DefaultMouseListener;
90 import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver;
91 import org.simantics.browsing.ui.swt.FilterArea;
92 import org.simantics.browsing.ui.swt.GraphExplorerFactory;
93 import org.simantics.browsing.ui.swt.IContextMenuInitializer;
94 import org.simantics.browsing.ui.swt.RootFilterArea;
95 import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;
96 import org.simantics.browsing.ui.swt.TypesQueryProcessor;
97 import org.simantics.browsing.ui.swt.ViewpointSelector;
98 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
99 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
100 import org.simantics.db.AsyncReadGraph;
101 import org.simantics.db.ReadGraph;
102 import org.simantics.db.Resource;
103 import org.simantics.db.Session;
104 import org.simantics.db.exception.DatabaseException;
105 import org.simantics.db.layer0.SelectionHints;
106 import org.simantics.db.layer0.request.PossibleVariable;
107 import org.simantics.db.layer0.request.PossibleVariableRepresents;
108 import org.simantics.db.layer0.variable.Variable;
109 import org.simantics.db.management.ISessionContext;
110 import org.simantics.db.management.ISessionContextChangedListener;
111 import org.simantics.db.management.ISessionContextProvider;
112 import org.simantics.db.management.SessionContextChangedEvent;
113 import org.simantics.project.ProjectKeys;
114 import org.simantics.ui.SimanticsUI;
115 import org.simantics.ui.dnd.LocalObjectTransfer;
116 import org.simantics.ui.dnd.LocalSelectionDragSourceListener;
117 import org.simantics.ui.dnd.NoImageDragSourceEffect;
118 import org.simantics.ui.dnd.SessionContainer;
119 import org.simantics.ui.selection.AnyResource;
120 import org.simantics.ui.selection.AnyVariable;
121 import org.simantics.ui.selection.ExplorerColumnContentType;
122 import org.simantics.ui.selection.ExplorerInputContentType;
123 import org.simantics.ui.selection.WorkbenchSelectionContentType;
124 import org.simantics.ui.selection.WorkbenchSelectionElement;
125 import org.simantics.ui.selection.WorkbenchSelectionUtils;
126 import org.simantics.utils.ObjectUtils;
127 import org.simantics.utils.datastructures.Function;
128 import org.simantics.utils.datastructures.disposable.DisposeState;
129 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
130 import org.simantics.utils.datastructures.hints.HintTracker;
131 import org.simantics.utils.datastructures.hints.IHintContext.Key;
132 import org.simantics.utils.datastructures.hints.IHintListener;
133 import org.simantics.utils.datastructures.hints.IHintObservable;
134 import org.simantics.utils.datastructures.hints.IHintTracker;
135 import org.simantics.utils.ui.SWTUtils;
136 import org.slf4j.Logger;
137 import org.slf4j.LoggerFactory;
138
139
140 public class GraphExplorerComposite extends Composite implements Widget, IAdaptable {
141
142     private static final Logger LOGGER = LoggerFactory.getLogger(GraphExplorerComposite.class);
143
144     protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
145     protected UserSelectedViewpointFactoryQueryProcessor  userSelectedViewpointFactoryQueryProcessor;
146     protected FilterSelectionRequestQueryProcessor        filterSelectionRequestQueryProcessor;
147     protected IFilterArea                                 filterArea;
148     protected EvaluatorData                               evaluatorData;
149
150     protected LocalResourceManager                        resourceManager;
151
152     protected ISelectionListener                          workbenchSelectionListener;
153
154     private final int                                     style;
155
156     final private IWorkbenchSite                          site;
157
158     protected GraphExplorer                               explorer;
159
160     protected IMenuManager                                menuManager;
161
162     private final Map<String, Object>                     args;
163
164     protected ISessionContextProvider                       contextProvider;
165
166     private ISessionContext                               sessionContext;
167
168     private Object                                        dragSource;
169
170     private IHintTracker                                  sessionContextTracker = new SessionContextProjectTracker();
171
172     private InputSource                                   inputSource           = new DirectInputSource();
173     private FilterAreaSource                              filterAreaSource    = new SelectionFilterAreaSource();
174
175     private final TreeColumnLayout                                                        ad;
176     private String[]                                        editingColumn = ColumnKeys.KEYS_SINGLE;
177     
178     private StatePersistor                                                                      persistor = null;
179
180     private final Composite                                                                       toolComposite;
181     private final Composite                                                                       toolComposite2;
182     private final Composite                                                                       explorerComposite;
183     final private WidgetSupport                                 support;
184     private final boolean                                                                       useNodeBrowseContexts;
185     private final boolean                                                                       useNodeActionContexts;
186
187     static class SelectionElement extends AdaptableHintContext {
188
189         final public WorkbenchSelectionElement wse;
190         final public Object content;
191         final public Resource resource;
192         final public Variable variable;
193         final public Object input;
194         final public TransientExplorerState explorerState;
195         
196         private WorkbenchSelectionElement extractWse(Object content) {
197             if(content instanceof NodeContext) {
198                 NodeContext context = (NodeContext)content;
199                 Object input = context.getConstant(NodeType.TYPE);
200                 if(input instanceof NodeType) 
201                     return ((NodeType)input).getWorkbenchSelectionElement(context);
202             }
203             return null;
204         }
205         
206         private Resource extractResource(Object content) {
207                 if(content instanceof NodeContext) {
208                         NodeContext context = (NodeContext)content;
209                         Object input = context.getConstant(BuiltinKeys.INPUT);
210                         if(input instanceof Resource) return (Resource)input;
211                         if(input instanceof IAdaptable) {
212                                 Resource var = (Resource)((IAdaptable)input).getAdapter(Resource.class);
213                                 if(var != null) return var;
214                         }
215                 }
216                 return null;
217         }
218         
219         private Variable extractVariable(Object content) {
220                 if(content instanceof NodeContext) {
221                         NodeContext context = (NodeContext)content;
222                         Object input = context.getConstant(BuiltinKeys.INPUT);
223                         if(input instanceof Variable) return (Variable)input;
224                         if(input instanceof IAdaptable) {
225                                 Variable var = (Variable)((IAdaptable)input).getAdapter(Variable.class);
226                                 if(var != null) return var;
227                         }
228                 }
229                 return null;
230         }
231
232         private Object extractInput(Object content) {
233                 if(content instanceof NodeContext) {
234                         NodeContext context = (NodeContext)content;
235                         return context.getConstant(BuiltinKeys.INPUT);
236                 }
237                 return null;
238         }
239
240         public SelectionElement(GraphExplorer explorer, Key[] keys, Object content) {
241             super(keys);
242             this.content = content;
243             this.wse = extractWse(content);
244             this.resource = extractResource(content);
245             this.variable = extractVariable(content);
246             this.input = extractInput(content);
247             this.explorerState = explorer.getTransientState();
248         }
249
250         @SuppressWarnings("unchecked")
251         @Override
252         public <T> T getContent(WorkbenchSelectionContentType<T> contentType) {
253             if (wse != null) {
254                 T result = wse.getContent(contentType);
255                 if (result != null)
256                     return result;
257             }
258
259             if (contentType instanceof AnyResource) {
260                 if (resource != null)
261                     return (T) resource;
262                 if (variable == null)
263                     return null;
264                 try {
265                     return (T) ((AnyResource) contentType).processor.syncRequest(new PossibleVariableRepresents(variable));
266                 } catch (DatabaseException e) {
267                     LOGGER.error("Unexpected error occurred while resolving Resource from Variable " + variable, e);
268                 }
269             }
270             else if (contentType instanceof AnyVariable) {
271                 if (variable != null)
272                     return (T) variable;
273                 if (resource == null)
274                     return null;
275                 try {
276                     return (T) ((AnyVariable) contentType).processor.syncRequest(new PossibleVariable(resource));
277                 } catch (DatabaseException e) {
278                     LOGGER.error("Unexpected error occurred while resolving Variable from Resource " + resource, e);
279                 }
280             } else if (contentType instanceof ExplorerInputContentType) {
281                 return (T) input;
282             } else if (contentType instanceof ExplorerColumnContentType) {
283                 return (T) explorerState.getActiveColumn();
284             }
285             return null;
286         }
287
288         @SuppressWarnings("rawtypes")
289         @Override
290         public Object getAdapter(Class adapter) {
291                 if(WorkbenchSelectionElement.class == adapter) {
292                         return wse;
293                 }
294                 if(NodeContext.class == adapter) {
295                     if(content instanceof NodeContext)
296                         return (NodeContext)content;
297                     else
298                         return null;
299                 }
300                 return super.getAdapter(adapter);
301         }
302
303     }
304     private BiFunction<GraphExplorer, Object[], Object[]> selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
305
306         private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN };
307         
308         @Override
309         public Object[] apply(GraphExplorer explorer, Object[] objects) {
310             Object[] result = new Object[objects.length];
311             for (int i = 0; i < objects.length; i++) {
312                 SelectionElement context = new SelectionElement(explorer, KEYS, objects[i]);
313                 context.setHint(SelectionHints.KEY_MAIN, objects[i]);
314                 result[i] = context;
315             }
316             return result;
317         }
318
319     };
320
321     private Set<String>                                   browseContexts        = null;
322
323     private DisposeState                                  disposeState          = DisposeState.Alive;
324
325     private boolean                                       created               = false;
326
327     protected String                                      contextMenuId         = null;
328
329     protected Set<String>                                 uiContext             = null;
330
331     protected ISessionContextChangedListener              contextChangeListener = new ISessionContextChangedListener() {
332         @Override
333         public void sessionContextChanged(SessionContextChangedEvent event) {
334             sessionContext = event.getNewValue();
335             sessionContextTracker.track(sessionContext);
336         }
337     };
338
339     public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, WidgetSupport support, int style) {
340
341         super(parent, SWT.NONE);
342
343         if (args == null)
344             args = Collections.emptyMap();
345
346         this.args = args;
347         this.site = site;
348         this.style = style;
349         this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), this);
350
351         contextProvider = getSessionContextProvider(site);
352
353         Integer maxChildren = (Integer)args.get("maxChildren");
354
355         GridLayoutFactory.fillDefaults().equalWidth(false).numColumns(1).margins(0,0).spacing(0,0).applyTo(this);
356
357         toolComposite = new Composite(this, SWT.NONE);
358 //        toolComposite.setBackground(toolComposite.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
359 //        GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
360         GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite);
361         GridLayoutFactory.fillDefaults().applyTo(toolComposite);
362
363         ad = new TreeColumnLayout();
364         explorerComposite = new Composite(this, SWT.NONE);
365         explorerComposite.setLayout(ad);
366         GridDataFactory.fillDefaults().grab(true, true).minSize(1, 50).applyTo(explorerComposite);
367
368         if (args.containsKey("treeView") && Boolean.TRUE.equals(args.get("treeView"))) {
369                 explorer = createExplorerControl2(explorerComposite, maxChildren);
370         } else if (args.containsKey("natTable") && Boolean.TRUE.equals(args.get("natTable"))) {
371                 explorer = createExplorerControl3(explorerComposite, maxChildren);
372         } else {
373                 explorer = createExplorerControl(explorerComposite, maxChildren);
374         }
375         
376         if (args.containsKey("useNodeBrowseContexts") && Boolean.TRUE.equals(args.get("useNodeBrowseContexts"))) {
377                 useNodeBrowseContexts = true;
378         } else {
379                 useNodeBrowseContexts = false;
380         }
381         
382         if (args.containsKey("useNodeActionContexts") && Boolean.TRUE.equals(args.get("useNodeActionContexts"))) {
383                 useNodeActionContexts = true;
384         } else {
385                 useNodeActionContexts = false;
386         }
387         
388         toolComposite2 = new Composite(this, SWT.NONE);
389 //        toolComposite2.setBackground(toolComposite2.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
390 //        GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
391         GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite2);
392         GridLayoutFactory.fillDefaults().applyTo(toolComposite2);
393
394         this.support = support;
395
396         if (support != null)
397             support.register(this);
398
399     }
400
401     public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, int style) {
402
403         this(args, site, parent, null, style);
404
405     }
406
407     public ISessionContextProvider getSessionContextProvider(IWorkbenchSite site) {
408         if(site != null)
409             return SimanticsUI.getSessionContextProvider(site.getWorkbenchWindow());
410         else
411             return Simantics.getSessionContextProvider();
412     }
413
414     public GraphExplorer getExplorer() {
415         return explorer;
416     }
417
418     public Composite getExplorerComposite() {
419         return explorerComposite;
420     }
421
422     public <T> T getExplorerControl() {
423         return explorer.getControl();
424     }
425
426     public void addListenerToControl(int eventType, Listener listener) {
427         ((Control)explorer.getControl()).addListener(eventType, listener);
428     }
429
430     public void removeListenerFromControl(int eventType, Listener listener) {
431         ((Control)explorer.getControl()).removeListener(eventType, listener);
432     }
433
434     public void finish() {
435         created = true;
436         createControls(site);
437         attachToSession();
438     }
439
440     IWorkbenchSite getSite() {
441         return site;
442     }
443
444     protected void activateUiContexts() {
445         Collection<String> contexts = getUiContexts();
446         if (contexts == null || contexts.isEmpty())
447             return;
448         IWorkbenchSite site = getSite();
449         if (site != null) {
450             IContextService cs = (IContextService) getSite().getService(IContextService.class);
451             for (String context : contexts)
452                 cs.activateContext(context);
453         }
454     }
455
456     protected void createControls(IWorkbenchSite site) {
457
458         // Initialize explorer control.
459 //        GridDataFactory.fillDefaults().grab(true, true).applyTo(explorer.getControl());
460
461         Control control = explorer.getControl();
462
463         // Initialize context menu if an initializer is provided.
464         IContextMenuInitializer cmi = getContextMenuInitializer();
465         if (cmi != null) {
466             ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
467             menuManager = cmi.createContextMenu(control, selectionProvider, site);
468         }
469
470         // Initialize UI contexts
471         activateUiContexts();
472
473         // Initialize DND.
474         dragSource = setupDND(explorer);
475
476         // Listeners are only added once per listener, not every time the
477         // session context changes.
478         addListeners(explorer, menuManager);
479
480         userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();
481         userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();
482         filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();
483         
484         explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
485
486         boolean hasExtraControls = false;
487         boolean hasExtraControls2 = false;
488
489         Boolean displaySelectors = (Boolean)args.get("displaySelectors");
490         if(displaySelectors == null || displaySelectors == true) {
491
492             @SuppressWarnings("unused")
493             ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
494 //            comparatorSelector.moveAbove(control);
495
496             @SuppressWarnings("unused")
497             ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
498 //            viewpointSelector.moveAbove(control);
499
500             hasExtraControls = true;
501
502         }
503
504         Boolean displayFilter = (Boolean)args.get("displayFilter");
505         if(displayFilter == null || displayFilter == true) {
506
507                 
508                 filterArea = filterAreaSource.getFilterArea(toolComposite, explorer);
509 //            filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite, SWT.READ_ONLY);
510             //filterArea.moveAbove(control);
511
512             hasExtraControls = true;
513
514         }
515
516         Boolean displayFilter2 = (Boolean)args.get("displayFilter2");
517         if(displayFilter2 != null && displayFilter2 == true) {
518
519                 filterArea = filterAreaSource.getFilterArea(toolComposite2, explorer);
520 //            filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite2, SWT.READ_ONLY);
521 //            //filterArea.moveAbove(control);
522
523             hasExtraControls2 = true;
524
525         }
526
527 //        filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, this, SWT.READ_ONLY);
528 //        filterArea.moveAbove(control);
529
530         if(!hasExtraControls)
531             GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite);
532         if(!hasExtraControls2)
533             GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite2);
534
535         GridDataFactory.fillDefaults().grab(true, true).span(2,1).applyTo(control);
536
537         //tree.getTree().setLayout(new FillLayout()
538         //this.setLayout(LayoutUtils.createNoBorderGridLayout(2, false));
539
540         DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_DEFAULT);
541         target.setTransfer(getAcceptedDataTypes());
542         if (control instanceof Tree)  {
543         target.addDropListener(new DropTargetListener() {
544
545             Tree tree = (Tree)explorer.getControl();
546
547             @Override
548             public void dragEnter(DropTargetEvent event) {
549                 event.detail = DND.DROP_COPY;
550             }
551
552             @Override
553             public void dragLeave(DropTargetEvent event) {
554             }
555
556             @Override
557             public void dragOperationChanged(DropTargetEvent event) {
558             }
559
560             @Override
561             public void dragOver(DropTargetEvent event) {
562             }
563
564             @Override
565             public void drop(DropTargetEvent event) {
566                 TreeItem item = tree.getItem(tree.toControl(event.x, event.y));
567                 if(item != null) {
568                         Object data = item.getData();
569                         if (data instanceof NodeContext)
570                                 handleDrop(event.data, (NodeContext) data);
571                         else if (data instanceof IAdaptable) {
572                                 IAdaptable a = (IAdaptable) data;
573                                 handleDrop(event.data, (NodeContext) a.getAdapter(NodeContext.class));
574                         }
575                 } else
576                     handleDrop(event.data, null);
577             }
578
579             @Override
580             public void dropAccept(DropTargetEvent event) {
581             }
582
583         });
584         }
585
586         // Add workbench listeners and make sure they are cleaned up
587         setWorkbenchListeners();
588         control.addListener(SWT.Dispose, new Listener() {
589             @Override
590             public void handleEvent(Event event) {
591                 doDispose();
592             }
593         });
594     }
595
596     @SuppressWarnings({ "rawtypes", "unchecked" })
597     @Override
598     public Object getAdapter(Class adapter) {
599         if (GraphExplorer.class == adapter)
600             return explorer;
601         if (EvaluatorData.class == adapter)
602             return evaluatorData;
603         if (BrowseContext.class == adapter) {
604             EvaluatorData ed = evaluatorData;
605             return ed != null ? ed.getBrowseContext() : null;
606         }
607         if (adapter == IFilterAreaProvider.class)
608             return filterArea;
609         return explorer.getAdapter(adapter);
610     }
611
612     protected void doDispose() {
613         //System.out.println(this + ".GraphExplorerComposite.doDispose()");
614         removeWorkbenchListeners();
615         userSelectedComparableFactoryQueryProcessor = null;
616         userSelectedViewpointFactoryQueryProcessor = null;
617         filterSelectionRequestQueryProcessor = null;
618
619         disposeState = DisposeState.Disposing;
620         try {
621             //System.out.println(this + ".GraphExplorerViewBase.dispose()");
622             if (contextProvider != null) {
623                 contextProvider.removeContextChangedListener(contextChangeListener);
624                 contextProvider = null;
625             }
626             sessionContextTracker.untrack();
627             resourceManager = null;
628             explorer = null;
629             sessionContext = null;
630             dragSource = null;
631 //            parent = null;
632         } finally {
633             disposeState = DisposeState.Disposed;
634         }
635     }
636
637     @Override
638     public void dispose() {
639         doDispose();
640         super.dispose();
641     }
642
643     protected StatePersistor getStatePersistor() {
644         return persistor;
645     }
646     
647     public void setStatePersistor(StatePersistor persistor) {
648         this.persistor = persistor;
649     }
650     
651     protected void initializeExplorer(GraphExplorer explorer, ISessionContext context) {
652
653         if(explorer == null || explorer.isDisposed()) return;
654         if(context == null) return;
655         if(browseContexts == null) return;
656
657         Session session = context != null ? context.getSession() : null;
658         setupDragSource(session);
659
660         if (session != null) {
661             evaluatorData = createEvaluatorData(session);
662             explorer.setDataSource(new AsyncReadGraphDataSource(session));
663             explorer.setDataSource(new ReadGraphDataSource(session));
664         }
665         else {
666             evaluatorData = new EvaluatorDataImpl();
667             explorer.removeDataSource(AsyncReadGraph.class);
668             explorer.removeDataSource(ReadGraph.class);
669         }
670
671         explorer.setPersistor(getStatePersistor());
672         
673         explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));
674         explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));
675         explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));
676         explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));
677         explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));
678         explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));
679         explorer.setProcessor(new DefaultIsCheckedProcessor2(evaluatorData));
680         explorer.setPrimitiveProcessor(new TypesQueryProcessor());
681         explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());
682         explorer.setPrimitiveProcessor(new InheritsQueryProcessor());
683         explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());
684
685         explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);
686         explorer.setProcessor(new ComparableSelectorQueryProcessor());
687         explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);
688         explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
689
690         initializeExplorerWithEvaluator(explorer, context, evaluatorData);
691     }
692
693     protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {
694     }
695
696     protected EvaluatorData createEvaluatorData(Session context) {
697
698 //        Set<String> browseContexts = getArgument("browseContexts");
699
700         return Evaluators.load(context.getSession(), browseContexts, resourceManager, useNodeBrowseContexts, useNodeActionContexts);
701
702     }
703
704     protected Transfer[] getAcceptedDataTypes() {
705         return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.getInstance(), TextTransfer.getInstance() };
706     }
707
708     protected void handleDrop(Object data, NodeContext target) {
709     }
710
711     DragSourceListenerFactory dragSourceListenerFactory = new DragSourceListenerFactory() {
712
713         final Transfer[] transfers = new Transfer[] {LocalObjectTransfer.getTransfer(), TextTransfer.getInstance() };
714
715         @Override
716         public DragSourceListener get(ISelectionProvider selectionProvider) {
717
718                 LocalSelectionDragSourceListener ls = new LocalSelectionDragSourceListener(selectionProvider);
719
720                 return new DragSourceListener() {
721                                 
722                                 @Override
723                                 public void dragStart(DragSourceEvent event) {
724                                         ls.dragStart(event);
725                                 }
726                                 
727                                 @Override
728                                 public void dragSetData(DragSourceEvent event) {
729                                         if(TextTransfer.getInstance().isSupportedType(event.dataType)) {
730                                         try {
731                                                         event.data = WorkbenchSelectionUtils.getPossibleJSON(selectionProvider.getSelection());
732                                                 } catch (DatabaseException e) {
733                                                         event.data = "{ type:\"Exception\" }";
734                                                         LOGGER.error("Failed to get current selection as JSON.", e);
735                                                 }
736                                         } else if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {
737                                                 ls.dragSetData(event);
738                                         }
739                                 }
740                                 
741                                 @Override
742                                 public void dragFinished(DragSourceEvent event) {
743                                         ls.dragFinished(event);
744                                 }
745                         };
746         }
747
748         @Override
749         public Transfer[] getTransfers() {
750             return transfers;
751         }
752
753     };
754
755     public void setDragSourceListenerFactory(DragSourceListenerFactory dragSourceListenerFactory) {
756         this.dragSourceListenerFactory = dragSourceListenerFactory;
757     }
758
759     protected DragSourceListener setupDND(GraphExplorer explorer) {
760
761         ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
762
763         DragSourceListener listener = createDragSourceListener(selectionProvider);
764
765         Control control = explorer.getControl();
766         DragSource source = createDragSource(control);
767         source.setTransfer(getTransfers());
768         source.addDragListener(listener);
769         source.setDragSourceEffect(new NoImageDragSourceEffect(control));
770
771         return listener;
772
773     }
774
775     protected DragSourceListener createDragSourceListener(ISelectionProvider selectionProvider) {
776         return dragSourceListenerFactory.get(selectionProvider);
777     }
778
779     private int dragStyle = DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
780
781     protected void setDragStyle(int style) {
782         this.dragStyle = style;
783     }
784
785     protected int getDragStyle() {
786         return dragStyle;
787     }
788
789     protected DragSource createDragSource(Control control) {
790         return new DragSource(control, getDragStyle());
791     }
792
793     protected Transfer[] getTransfers() {
794         return dragSourceListenerFactory.getTransfers();
795     }
796
797     public EvaluatorData getEvaluatorData() {
798         return evaluatorData;
799     }
800
801     public interface InputSource {
802         /**
803          * @param ctx the session context to read the input from. May be
804          *        <code>null</code> if there is no session.
805          * @return the input object of a graph explorer. To indicate no input,
806          *         use {@link GraphExplorerConstants#EMPTY_INPUT}. Never return
807          *         <code>null</code>.
808          */
809         Object get(ISessionContext ctx, Object selection);
810     }
811     
812     public interface FilterSource {
813         
814         
815         
816     }
817
818     /**
819      * The default hint tracker that will be active if
820      * {@link GraphExplorerComposite#setSessionContextTracker(IHintTracker) is
821      * not called.
822      */
823     public class SessionContextProjectTracker extends HintTracker {
824         public SessionContextProjectTracker() {
825             IHintListener activeProjectListener = new HintListenerAdapter() {
826                 @Override
827                 public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
828                     applySessionContext(getSessionContext());
829                 }
830             };
831             addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);
832         }
833     }
834
835     public class DirectInputSource implements InputSource {
836         @Override
837         public Object get(ISessionContext ctx, Object selection) {
838             return selection;
839         }
840     }
841     
842     public static class SelectionFilterAreaSource implements FilterAreaSource {
843
844                 @Override
845                 public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
846                         FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
847                         return new FilterArea(explorer, processor, parent, SWT.READ_ONLY);
848                 }
849         
850     }
851
852     public static class RootFilterAreaSource implements FilterAreaSource {
853
854                 @Override
855                 public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
856                         FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
857                         return new RootFilterArea(explorer, processor, parent, SWT.READ_ONLY);
858                 }
859         
860     }
861
862     protected void setSessionContextTracker(IHintTracker tracker) {
863         this.sessionContextTracker = tracker;
864     }
865
866     public void setInputSource(InputSource source) {
867         this.inputSource = source;
868     }
869     
870     public void setFilterAreaSource(FilterAreaSource provider) {
871         this.filterAreaSource = provider;
872     }
873
874     public void setSelectionTransformation(BiFunction<GraphExplorer, Object[], Object[]> transformation) {
875         this.selectionTransformation = transformation;
876         if(explorer != null) explorer.setSelectionTransformation(transformation);
877     }
878
879     protected Set<String> getBrowseContexts() {
880         return browseContexts;
881     }
882     
883     public void setBrowseContexts(Set<String> contexts) {
884         this.browseContexts = contexts;
885         //initializeExplorer(explorer, getSessionContext());
886     }
887
888     public void setBrowseContexts(String ... contexts) {
889         this.browseContexts = new HashSet<String>();
890         for(String s : contexts) this.browseContexts.add(s);
891         initializeExplorer(explorer, getSessionContext());
892     }
893
894     public void setContextMenuId(String contextMenuId) {
895         this.contextMenuId = contextMenuId;
896     }
897
898 //    protected IContextMenuInitializer getContextMenuInitializer() {
899 //        String contextMenuId = getContextMenuId();
900 //        if(contextMenuId != null) {
901 //            return new ContextMenuInitializer(contextMenuId);
902 //        } else {
903 //            return null;
904 //        }
905 //    }
906
907     protected String getContextMenuId() {
908         return this.contextMenuId;
909     }
910
911     public void setUiContexts(Set<String> uiContext) {
912         this.uiContext = uiContext;
913     }
914
915     public Set<String> getUiContexts() {
916         return uiContext;
917     }
918
919     protected InputSource getInputSource() {
920         return inputSource;
921     }
922
923     protected Map<String, Object> getArguments() {
924         return args;
925     }
926
927     @SuppressWarnings("unchecked")
928     protected <T> T getArgument(String key) {
929         return (T) args.get(key);
930     }
931
932     protected DisposeState getDisposeState() {
933         return disposeState;
934     }
935
936     public ISessionContext getSessionContext() {
937         return sessionContext;
938     }
939
940     public ISessionContextProvider getSessionContextProvider() {
941         return contextProvider;
942     }
943
944     @Override
945     public boolean setFocus() {
946         if (explorer != null && !explorer.isDisposed())
947             explorer.setFocus();
948         return true;
949     }
950
951     public void setWorkbenchListeners() {
952         if (workbenchSelectionListener == null && getSite() != null) {
953             ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
954             getSite().setSelectionProvider(selectionProvider);
955
956             // Listen to the workbench selection also to propagate it to
957             // the explorer also.
958             workbenchSelectionListener = new DefaultExplorerSelectionListener(site.getPage().getActivePart(), explorer);
959             //System.out.println("ADD WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
960             getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(workbenchSelectionListener);
961         }
962     }
963
964     protected void removeWorkbenchListeners() {
965         //System.out.println("REMOVE WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
966         // Remember to remove the installed workbench selection listener
967         if (workbenchSelectionListener != null) {
968             getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(workbenchSelectionListener);
969             workbenchSelectionListener = null;
970
971             ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
972             if(getSite().getSelectionProvider() == selectionProvider) getSite().setSelectionProvider(null);
973             
974         }
975     }
976
977     protected final void attachToSession() {
978
979         // Track active ISessionContext changes
980         //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());
981         contextProvider.addContextChangedListener(contextChangeListener);
982
983         // Start tracking the current session context for input changes.
984         // This will/must cause applySessionContext to get called.
985         // Doing the applySessionContext initialization this way
986         // instead of directly calling it will also make sure that
987         // applySessionContext is only called once when first initialized,
988         // and not twice like with the direct invocation.
989         this.sessionContext = contextProvider.getSessionContext();
990         sessionContextTracker.track(sessionContext);
991     }
992
993     // /////////////////////////////////////////////////////////////////////////
994     // Override / implement these:
995
996 //    /**
997 //     * Returns an ID that is used for persisting a GraphExplorer instance.
998 //     *
999 //     * Used for </code>restoreState(IMemento)</code> and
1000 //     * <code>restoreState(IMemento)</code> in OntologyExplorer. Must be unique
1001 //     * within a workbench part.
1002 //     *
1003 //     * @return a unique name for this particular graph explorer view used for
1004 //     *         saving and restoring the state of this view part
1005 //     */
1006 //    public String getExplorerName() {
1007 //        return "GraphExplorerViewBase";
1008 //    }
1009
1010     /**
1011      * Override this method to add controls to the view part. This is invoked
1012      * before attaching the view part to a database session.
1013      * 
1014      * @param parent
1015      */
1016     protected void createControls(Composite parent) {
1017
1018     }
1019
1020     /**
1021      * Override this method and provide a proper context menu initializer if you
1022      * want to have this base class initialize one for you.
1023      * 
1024      * @return the initializer to be used by {@link #createControls(Composite)}
1025      */
1026     protected IContextMenuInitializer getContextMenuInitializer() {
1027         String contextMenuId = getContextMenuId();
1028         if(contextMenuId != null) {
1029             return new ContextMenuInitializer(contextMenuId);
1030         } else {
1031             return null;
1032         }
1033     }
1034
1035     /**
1036      * @param parent
1037      * @return
1038      */
1039     protected GraphExplorer createExplorerControl(Composite parent, Integer maxChildren) {
1040         GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1041         if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1042
1043         GraphExplorer ge = factory
1044         .selectionDataResolver(new DefaultSelectionDataResolver())
1045         .selectionTransformation(selectionTransformation)
1046         .setServiceLocator(site)
1047         .create(parent, style);
1048
1049         return ge;
1050     }
1051     
1052     protected GraphExplorer createExplorerControl2(Composite parent, Integer maxChildren) {
1053         GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1054         if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1055
1056         GraphExplorer ge = factory
1057         .selectionDataResolver(new DefaultSelectionDataResolver())
1058         .selectionTransformation(selectionTransformation)
1059         .setServiceLocator(site)
1060         .create2(parent, style);
1061
1062         return ge;
1063     }
1064     
1065     protected GraphExplorer createExplorerControl3(Composite parent, Integer maxChildren) {
1066         GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1067         if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1068
1069         GraphExplorer ge = factory
1070         .selectionDataResolver(new DefaultSelectionDataResolver())
1071         .selectionTransformation(selectionTransformation)
1072         .setServiceLocator(site)
1073         .create3(parent, style);
1074
1075         return ge;
1076     }
1077
1078     protected void setupDragSource(Session session) {
1079         if (dragSource instanceof SessionContainer) {
1080             ((SessionContainer) dragSource).setSession(session);
1081         }
1082     }
1083
1084     /**
1085      * Override to customize the addition of listeners a newly created
1086      * GraphExplorer.
1087      * 
1088      * @param explorer
1089      */
1090     protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) {
1091         addSelectionInputListeners(explorer, menuManager);
1092     }
1093
1094     protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) {
1095         // Consider ENTER presses to simulate mouse left button double clicks
1096         explorer.addListener(new DefaultKeyListener(contextProvider, explorer, new Function<String[]>() {
1097             @Override
1098             public String[] execute(Object... obj) {
1099                 return getEditingColumn((NodeContext) obj[0]);
1100             }
1101         }));
1102         // Default double click handling
1103         explorer.addListener(new DefaultMouseListener(explorer));
1104     }
1105
1106     protected String[] getEditingColumn(NodeContext context) {
1107         return editingColumn;
1108     }
1109     
1110     public void setEditingColumn(String... columnKeysInOrderOfTrial) {
1111         this.editingColumn = columnKeysInOrderOfTrial;
1112     }
1113
1114     // Needed for preventing unnecessary re-initialization of the explorer with the same input.
1115     private Object currentInput;
1116     private Object currentRoot;
1117
1118     /**
1119      * Invoke this to reinitialize the explorer and reset its input. The input
1120      * will be resolved from the specified ISessionContext based on the
1121      * {@link SessionContextInputSource} that is currently in use. If the input
1122      * is identical to the previous input, nothing will be done.
1123      * 
1124      * @param context
1125      */
1126     public final boolean applySessionContext(ISessionContext context) {
1127
1128         // If control is not alive anymore, do nothing.
1129         //System.out.println(this + ": applySessionContext(" + context + "), explorer="  + explorer);
1130         if (disposeState != DisposeState.Alive)
1131             return false;
1132
1133         //System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")");
1134         initializeExplorer(explorer, context);
1135
1136
1137         // Start tracking the session context.
1138         //
1139         // If this is not the same session that is currently tracked, it will
1140         // cause IHintListeners of the sessionContextTracker to fire.
1141         // For this we need the above input equality (identity) checking.
1142         // This is here just to make sure that we are tracking the correct
1143         // session context.
1144         sessionContextTracker.track(sessionContext);
1145
1146         this.sessionContext = context;
1147         Object root = inputSource.get(context, currentInput);
1148         if (ObjectUtils.objectEquals(root, currentRoot))
1149             return false;
1150
1151         currentRoot = root;
1152
1153         //System.out.println(this + ": setRoot(" + input + ")");
1154         explorer.setUIContexts(uiContext);
1155         explorer.setRoot(root);
1156
1157         return true;
1158
1159     }
1160
1161     protected boolean isImportantInput(Object previousSelection, Object selection) {
1162         return !ObjectUtils.objectEquals(previousSelection, selection);
1163     }
1164
1165     public void setInput(Object selection, boolean force) {
1166
1167         assert(created);
1168
1169         if (isDisposed())
1170             return;
1171         if (sessionContext == null)
1172             return;
1173
1174         // Check if this is a duplicate of the previous selection to reduce unnecessary flicker.
1175         if (!force && !isImportantInput(currentInput, selection))
1176             return;
1177
1178         currentInput = selection;
1179
1180         Object root = inputSource.get(sessionContext, selection);
1181
1182         currentRoot = root;
1183
1184         explorer.setUIContexts(uiContext);
1185
1186         if (root == null) {
1187             explorer.setRoot(GraphExplorer.EMPTY_INPUT);
1188         } else {
1189             explorer.setRoot(root);
1190         }
1191
1192     }
1193
1194     public void setColumnsVisible(boolean visible) {
1195         explorer.setColumnsVisible(visible);
1196     }
1197
1198     private int getColumnWidth(Column column, ExplorerState state) {
1199         // Get saved width from the persistor if there is one.
1200         if (state != null && state.columnWidths != null) {
1201             Integer width = state.columnWidths.get(column.getLabel());
1202             if (width != null)
1203                 return width;
1204         }
1205         return column.getWidth();
1206     }
1207
1208     protected void restoreColumnSizes(Map<Column, Object> columns) {
1209         if (persistor != null) {
1210             setColumnData(columns, null);
1211             ExplorerStates.scheduleRead(explorer.getRoot(), persistor).thenAccept(state -> {
1212                 SWTUtils.asyncExec(GraphExplorerComposite.this, () -> {
1213                     if (explorerComposite.isDisposed())
1214                         setColumnData(columns, state);
1215                 });
1216             });
1217         } else {
1218             setColumnData(columns, null);
1219         }
1220     }
1221
1222     protected void setColumnData(Map<Column, Object> columns, ExplorerState state) {
1223         columns.forEach((column, widget) -> {
1224             org.eclipse.swt.widgets.Widget columnWidget = (org.eclipse.swt.widgets.Widget) widget;
1225             ad.setColumnData(columnWidget,
1226                     new ColumnWeightData(
1227                             column.hasGrab() ? column.getWeight() : 0,
1228                             getColumnWidth(column, state)));
1229         });
1230     }
1231
1232     public void setColumns(Column[] columns) {
1233         // ColumnWeightData does not support column weight/width < 0
1234         for (Column column : columns) {
1235             if (column.getWeight() < 0)
1236                 throw new IllegalArgumentException("Column weight must be >= 0, got " + column.getWeight() + " for " + column);
1237             if (column.getWidth() < 0)
1238                 throw new IllegalArgumentException("Column minimum width must be >= 0, got " + column.getWidth() + " for " + column);
1239         }
1240         explorer.setColumns(columns, this::restoreColumnSizes);
1241     }
1242
1243     @Override
1244     public void setInput(ISessionContext context, Object input) {
1245         setInput(input, false);
1246     }
1247
1248     public void setMaxChildren(int maxChildren) {
1249         explorer.setMaxChildren(maxChildren);
1250     }
1251     
1252     public <T> void addListener(ExplorerMouseListenerImpl<T> listener) {
1253         
1254         support.register(listener);
1255         listener.register(explorer);
1256         explorer.addListener(listener);
1257         
1258     }
1259
1260 //    @Override
1261 //    public Point computeSize(int wHint, int hHint) {
1262 //      Point p = super.computeSize(wHint, hHint);
1263 //      System.err.println("graphExplorerComposite.computeSize " + p);
1264 //      return p;
1265 //    }
1266 //    
1267 //    @Override
1268 //    public Point computeSize(int wHint, int hHint, boolean changed) {
1269 //      Point p = super.computeSize(wHint, hHint, changed);
1270 //      System.err.println("graphExplorerComposite.computeSize " + p);
1271 //      return p;
1272 //    }
1273     
1274 }