]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/DefaultIsExpandedProcessor.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / DefaultIsExpandedProcessor.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 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;
13
14 import gnu.trove.map.hash.THashMap;
15 import gnu.trove.set.hash.THashSet;
16
17 import java.util.Collection;
18 import java.util.HashSet;
19 import java.util.Map;
20 import java.util.Set;
21
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.widgets.Event;
24 import org.eclipse.swt.widgets.Listener;
25 import org.eclipse.swt.widgets.Tree;
26 import org.simantics.browsing.ui.BuiltinKeys;
27 import org.simantics.browsing.ui.GraphExplorer;
28 import org.simantics.browsing.ui.NodeContext;
29 import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey;
30 import org.simantics.browsing.ui.PrimitiveQueryUpdater;
31 import org.simantics.browsing.ui.common.processors.AbstractPrimitiveQueryProcessor;
32 import org.simantics.browsing.ui.common.processors.IsExpandedProcessor;
33 import org.simantics.browsing.ui.common.processors.ProcessorLifecycle;
34
35 /**
36  * @author Tuukka Lehtonen
37  */
38 public class DefaultIsExpandedProcessor extends AbstractPrimitiveQueryProcessor<Boolean> implements
39 IsExpandedProcessor, ProcessorLifecycle {
40
41     /**
42      * The set of currently expanded node contexts.
43      */
44     private final Set<NodeContext>                        expanded        = new THashSet<NodeContext>();
45     private final Map<NodeContext, PrimitiveQueryUpdater> expandedQueries = new THashMap<NodeContext, PrimitiveQueryUpdater>();
46
47     private Tree tree;
48
49     public DefaultIsExpandedProcessor() {
50     }
51
52     @Override
53     public Object getIdentifier() {
54         return BuiltinKeys.IS_EXPANDED;
55     }
56
57     @Override
58     public String toString() {
59         return "IsExpandedProcessor";
60     }
61
62     @Override
63     public Boolean query(PrimitiveQueryUpdater updater, NodeContext context, PrimitiveQueryKey<Boolean> key) {
64         boolean isExpanded = expanded.contains(context);
65         //System.out.println("isExpanded(" + updater + ", " + context + "): " + isExpanded);
66         expandedQueries.put(context, updater);
67         return Boolean.valueOf(isExpanded);
68     }
69
70     @Override
71     public Collection<NodeContext> getExpanded() {
72         return new HashSet<NodeContext>(expanded);
73     }
74
75     @Override
76     public boolean getExpanded(NodeContext context) {
77         return this.expanded.contains(context);
78     }
79
80     @Override
81     public boolean setExpanded(NodeContext context, boolean expanded) {
82         return _setExpanded(context, expanded);
83     }
84
85     @Override
86     public boolean replaceExpanded(NodeContext context, boolean expanded) {
87         return nodeStatusChanged(context, expanded);
88     }
89
90     private boolean _setExpanded(NodeContext context, boolean expanded) {
91         if (expanded) {
92             return this.expanded.add(context);
93         } else {
94             return this.expanded.remove(context);
95         }
96     }
97
98     Listener treeListener = new Listener() {
99         @Override
100         public void handleEvent(Event event) {
101             NodeContext context = (NodeContext) event.item.getData();
102             switch (event.type) {
103                 case SWT.Expand:
104                     nodeStatusChanged(context, true);
105                     break;
106                 case SWT.Collapse:
107                     nodeStatusChanged(context, false);
108                     break;
109             }
110         }
111     };
112
113     protected boolean nodeStatusChanged(NodeContext context, boolean expanded) {
114         boolean result = _setExpanded(context, expanded);
115         PrimitiveQueryUpdater updater = expandedQueries.get(context);
116         if (updater != null)
117             updater.scheduleReplace(context, BuiltinKeys.IS_EXPANDED, expanded);
118         return result;
119     }
120
121     @Override
122     public void attached(GraphExplorer explorer) {
123         Object control = explorer.getControl();
124         if (control instanceof Tree) {
125             this.tree = (Tree) control;
126             tree.addListener(SWT.Expand, treeListener);
127             tree.addListener(SWT.Collapse, treeListener);
128         } else {
129             System.out.println("WARNING: " + getClass().getSimpleName() + " attached to unsupported control: " + control);
130         }
131     }
132
133     @Override
134     public void clear() {
135         expanded.clear();
136         expandedQueries.clear();
137     }
138
139     @Override
140     public void detached(GraphExplorer explorer) {
141         clear();
142         if (tree != null) {
143             tree.removeListener(SWT.Expand, treeListener);
144             tree.removeListener(SWT.Collapse, treeListener);
145             tree = null;
146         }
147     }
148
149 }