]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/DefaultIsCheckedProcessor.java
Merge remote-tracking branch 'origin/svn' commit 'ccc1271c9d6657fb9dcf4cf3cb115fa0c8c...
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / DefaultIsCheckedProcessor.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.browsing.ui.swt;\r
13 \r
14 import java.util.HashMap;\r
15 \r
16 import org.eclipse.swt.SWT;\r
17 import org.eclipse.swt.widgets.Event;\r
18 import org.eclipse.swt.widgets.Listener;\r
19 import org.eclipse.swt.widgets.Tree;\r
20 import org.eclipse.swt.widgets.TreeItem;\r
21 import org.eclipse.swt.widgets.Widget;\r
22 import org.simantics.browsing.ui.BuiltinKeys;\r
23 import org.simantics.browsing.ui.CheckedState;\r
24 import org.simantics.browsing.ui.GraphExplorer;\r
25 import org.simantics.browsing.ui.NodeContext;\r
26 import org.simantics.browsing.ui.PrimitiveQueryUpdater;\r
27 import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey;\r
28 import org.simantics.browsing.ui.common.processors.AbstractPrimitiveQueryProcessor;\r
29 import org.simantics.browsing.ui.common.processors.IsCheckedProcessor;\r
30 import org.simantics.browsing.ui.common.processors.ProcessorLifecycle;\r
31 \r
32 /**\r
33  * @author Tuukka Lehtonen\r
34  */\r
35 public class DefaultIsCheckedProcessor extends AbstractPrimitiveQueryProcessor<CheckedState> implements\r
36 IsCheckedProcessor, ProcessorLifecycle {\r
37 \r
38     private static final boolean DEBUG = false;\r
39 \r
40     /**\r
41      * The map of node contexts that currently have another checked state than\r
42      * {@link CheckedState#NOT_CHECKED}.\r
43      */\r
44     private final HashMap<NodeContext, CheckedState>          checkedStates  = new HashMap<NodeContext, CheckedState>();\r
45     private final HashMap<NodeContext, PrimitiveQueryUpdater> checkedQueries = new HashMap<NodeContext, PrimitiveQueryUpdater>();\r
46 \r
47     private final CheckedState                                defaultState;\r
48 \r
49     private Tree                                              tree;\r
50 \r
51     private boolean                                           viewerSupportsChecking;\r
52 \r
53     public DefaultIsCheckedProcessor() {\r
54         this(CheckedState.NOT_CHECKED);\r
55     }\r
56 \r
57     public DefaultIsCheckedProcessor(CheckedState defaultState) {\r
58         if (defaultState == null)\r
59             throw new NullPointerException("null default state");\r
60         this.defaultState = defaultState;\r
61     }\r
62 \r
63     @Override\r
64     public Object getIdentifier() {\r
65         return BuiltinKeys.IS_CHECKED;\r
66     }\r
67 \r
68     @Override\r
69     public String toString() {\r
70         return "IsCheckedProcessor";\r
71     }\r
72 \r
73     @Override\r
74     public CheckedState query(PrimitiveQueryUpdater updater, NodeContext context, PrimitiveQueryKey<CheckedState> key) {\r
75         // Don't gather records if the Tree we are attached to does not support\r
76         // checked items. This optimizes memory consumption while allowing this\r
77         // processor to exist in the attached GraphExplorer.\r
78         if (!viewerSupportsChecking)\r
79             return defaultState;\r
80 \r
81         CheckedState checked = checkedStates.get(context);\r
82 \r
83         if (DEBUG)\r
84             System.out.println("isChecked(" + updater + ", " + context + "): " + checked);\r
85 \r
86         checkedQueries.put(context, updater);\r
87         return checked != null ? checked : CheckedState.NOT_CHECKED;\r
88     }\r
89 \r
90     @Override\r
91     public boolean setChecked(NodeContext context, CheckedState checked) {\r
92         return _setChecked(context, checked);\r
93     }\r
94 \r
95     private boolean _setChecked(NodeContext context, CheckedState checked) {\r
96         if (checked != defaultState) {\r
97             return this.checkedStates.put(context, checked) != checked;\r
98         } else {\r
99             return this.checkedStates.remove(context) != null;\r
100         }\r
101     }\r
102 \r
103     Listener treeListener = new Listener() {\r
104         @Override\r
105         public void handleEvent(Event event) {\r
106             NodeContext context = (NodeContext) event.item.getData();\r
107             switch (event.type) {\r
108                 case SWT.Selection:\r
109                     if (event.detail == SWT.CHECK && event.item != null) {\r
110                         TreeItem item = (TreeItem) event.item;\r
111                         boolean checked = item.getChecked();\r
112                         boolean grayed = item.getGrayed();\r
113                         nodeStatusChanged(context, toCheckedState(checked, grayed));\r
114                     }\r
115                     break;\r
116             }\r
117         }\r
118     };\r
119 \r
120     protected void nodeStatusChanged(NodeContext context, CheckedState checked) {\r
121         if (DEBUG)\r
122             System.out.println("isChecked status changed for " + context + ": " + checked);\r
123 \r
124         _setChecked(context, checked);\r
125 //        PrimitiveQueryUpdater updater = checkedQueries.get(context);\r
126 //        if (updater != null)\r
127 //            updater.scheduleReplace(context, BuiltinKeys.IS_CHECKED, checked);\r
128     }\r
129 \r
130     @Override\r
131     public void attached(GraphExplorer explorer) {\r
132         if (DEBUG)\r
133             System.out.println(this + " attaching to " + explorer);\r
134 \r
135         Object control = explorer.getControl();\r
136         if (control instanceof Tree) {\r
137             this.tree = (Tree) control;\r
138             viewerSupportsChecking = supportsChecking(tree);\r
139             if (viewerSupportsChecking) {\r
140                 if (DEBUG)\r
141                     System.out.println("\ttree supports checking, adding listener");\r
142                 tree.addListener(SWT.Selection, treeListener);\r
143             }\r
144         } else {\r
145             System.out.println("WARNING: " + getClass().getSimpleName() + " attached to unsupported control: " + control);\r
146         }\r
147     }\r
148 \r
149     @Override\r
150     public void clear() {\r
151         checkedStates.clear();\r
152         checkedQueries.clear();\r
153     }\r
154 \r
155     @Override\r
156     public void detached(GraphExplorer explorer) {\r
157         if (DEBUG)\r
158             System.out.println(this + " detaching from " + explorer);\r
159 \r
160         clear();\r
161         if (tree != null) {\r
162             if (viewerSupportsChecking) {\r
163                 if (DEBUG)\r
164                     System.out.println("\ttree supported checking, removing listener");\r
165                 tree.removeListener(SWT.Selection, treeListener);\r
166             }\r
167             tree = null;\r
168             viewerSupportsChecking = false;\r
169         }\r
170     }\r
171 \r
172     private static boolean supportsChecking(Widget control) {\r
173         return (control.getStyle() & SWT.CHECK) != 0;\r
174     }\r
175 \r
176     private static CheckedState toCheckedState(boolean checked, boolean grayed) {\r
177         if (checked)\r
178             return grayed ? CheckedState.GRAYED : CheckedState.CHECKED;\r
179         return CheckedState.NOT_CHECKED;\r
180     }\r
181 \r
182 }