]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui/src/org/simantics/browsing/ui/content/Labeler.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.browsing.ui / src / org / simantics / browsing / ui / content / Labeler.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.content;\r
13 \r
14 import java.util.Collections;\r
15 import java.util.List;\r
16 import java.util.Map;\r
17 import java.util.function.Consumer;\r
18 \r
19 import org.simantics.browsing.ui.GraphExplorer.ModificationContext;\r
20 import org.simantics.browsing.ui.NodeContext;\r
21 import org.simantics.browsing.ui.PrimitiveQueryUpdater;\r
22 import org.simantics.utils.datastructures.ArrayMap;\r
23 \r
24 /**\r
25  * A Labeler is used for describing the viewer labeling aspects of a single UI\r
26  * (e.g. tree) node. Labelers are created on a per UI node basis. Labelers are\r
27  * created by {@link LabelerFactory}s.\r
28  * \r
29  * <p>\r
30  * A Labeler is responsible for providing a modifier for itself (\r
31  * {@link #getModifier(String)}).\r
32  * </p>\r
33  * \r
34  * <p>\r
35  * A labeler is also responsible for informing of any changes happening in\r
36  * labels to using the {@link PrimitiveQueryUpdater} received by the\r
37  * {@link LabelerFactory} that created the Labeler. To signal that the labeler\r
38  * has been updated, invoke\r
39  * {@link PrimitiveQueryUpdater#scheduleReplace(NodeContext, org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey, Object)}\r
40  * and eventually the query system will request the labeler for the new\r
41  * results.\r
42  * </p>\r
43  * \r
44  * @author Antti Villberg\r
45  * \r
46  * @see ArrayMap A space-optimized immutable Map implementation for multicolumn values\r
47  */\r
48 public interface Labeler {\r
49 \r
50     public interface LabelerListener {\r
51         boolean columnModified(NodeContext context, String columnKey, String label);\r
52         boolean columnsModified(NodeContext context, Map<String, String> columns);\r
53     }\r
54 \r
55     public interface Modifier {\r
56         /**\r
57          * Returns the value for the property referred by this modifier. Must\r
58          * not return <code>null</code> since the existence of this Modifier\r
59          * should be enough proof that a modifiable value actually does exist\r
60          * (see {@link Labeler#getModifier(String)}).\r
61          * \r
62          * @return the original property value to be modified\r
63          */\r
64         public String getValue();\r
65 \r
66         /**\r
67          * @param label the label to test for validity\r
68          * @return <code>null</code> if the specified label is valid for this\r
69          *         modifier or an error message if the label is invalid\r
70          */\r
71         public String isValid(String label);\r
72 \r
73         /**\r
74          * @param label the new value to set for the property of this Labeler\r
75          *        modified by this Modifier\r
76          */\r
77         public void modify(String label);\r
78     }\r
79     \r
80     public static class DeniedModifier implements Modifier {\r
81 \r
82         final private String message;\r
83         \r
84         public DeniedModifier(String message) {\r
85                 this.message = message;\r
86         }\r
87         \r
88         public String getMessage() {\r
89                 return message;\r
90         }\r
91         \r
92                 @Override\r
93                 public String getValue() {\r
94                         throw new IllegalStateException();\r
95                 }\r
96 \r
97                 @Override\r
98                 public String isValid(String label) {\r
99                         throw new IllegalStateException();\r
100                 }\r
101 \r
102                 @Override\r
103                 public void modify(String label) {\r
104                         throw new IllegalStateException();\r
105                 }\r
106         \r
107     }\r
108 \r
109     /**\r
110      * An additional interface that a modifier may implement if it wishes to\r
111      * filter the user's interactive input in some way before it is applied\r
112      * to the UI control.\r
113      * \r
114      * @author Tuukka Lehtonen\r
115      */\r
116     public interface FilteringModifier {\r
117         /**\r
118          * The filter method receives most recent input received for the edited\r
119          * field. The method shall return a filtered version of the received\r
120          * <code>input</code> that is then applied into the text field as if it\r
121          * was the user's input.\r
122          * \r
123          * @param input\r
124          *            the text that is about to be inserted before filtering\r
125          * @return filtered input\r
126          */\r
127         public String filter(String input);\r
128     }\r
129 \r
130     /**\r
131      * A special modifier for handling editing of enumerations which have a set\r
132      * of predefined values that cannot change. The editing can therefore be\r
133      * performed for example using a read-only combo box.\r
134      * \r
135      * <p>\r
136      * {@link #getValue()} must be implemented to return the currently selected\r
137      * value among the list of possible values returned by {@link #getValues()}.\r
138      */\r
139     public interface EnumerationModifier extends Modifier {\r
140         /**\r
141          * @return all possible and valid values for the enumeration to be\r
142          *         modified\r
143          */\r
144         public List<String> getValues();\r
145     }\r
146 \r
147     /**\r
148      * A special modifier that allows the use of customized controls for editing.\r
149      */\r
150     public interface CustomModifier extends Modifier {\r
151         /**\r
152          * @param parentControl the parenting control for the editor controls\r
153          * @param controlItem the edited item within the parenting control\r
154          * @param columnIndex the column to be modified\r
155          * @param the data context of the item to be edited\r
156          * @return a control for client editing\r
157          */\r
158         Object createControl(Object parentControl, Object controlItem, int columnIndex, NodeContext context);\r
159     }\r
160 \r
161     /**\r
162      * A special modifier that allows the use of customized controls for\r
163      * editing.\r
164      * \r
165      * {@link Modifier#getValue()} is unused for these since the dialog is\r
166      * responsible for getting its own data.\r
167      */\r
168     public interface DialogModifier extends Modifier {\r
169         /**\r
170          * @param parentControl the parenting control for the editor controls\r
171          * @param controlItem the edited item within the parenting control\r
172          * @param columnIndex the column to be modified\r
173          * @param the data context of the item to be edited\r
174          * @param applyCallback the dialog must call this when it wants to apply\r
175          *        its changes\r
176          * @return status describing the result of the operation or\r
177          *         <code>null</code> to ignore reporting\r
178          */\r
179         String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context,\r
180                 Consumer<String> applyCallback);\r
181     }\r
182 \r
183     String              NO_LABEL  = "<no label>";\r
184 \r
185     /**\r
186      * Use this map as a return value of {@link #getLabels()} to indicate no\r
187      * labels.\r
188      */\r
189     Map<String, String> NO_LABELS = Collections.emptyMap();\r
190 \r
191     /**\r
192      * Get the per-column labels associated with this labeler.\r
193      * <p>\r
194      * See <code>org.simantics.browsing.ui.common.ColumnKeys</code> for some\r
195      * re-usable column keys.\r
196      * \r
197      * @return a map of all the produced labels where the keys are the column\r
198      *         names and the values are the corresponding column values\r
199      */\r
200     Map<String, String> getLabels();\r
201 \r
202     /**\r
203      * Get the per-column labels associated with this labeler.\r
204      * \r
205      * <p>\r
206      * TODO: what is the difference to {@link #getLabels()}, is this really\r
207      * necessary or just an unnecessary optimization?\r
208      * \r
209      * <p>\r
210      * See <code>org.simantics.browsing.ui.common.ColumnKeys</code> for some\r
211      * re-usable column keys.\r
212      * \r
213      * @return a map of all the produced labels where the keys are the column\r
214      *         names and the values are the corresponding column values. Use\r
215      *         {@link Labeler#NO_LABELS} or {@link Collections#emptyMap()} when\r
216      *         no labels are available, do not return <code>null</code>.\r
217      */\r
218     Map<String, String> getRuntimeLabels();\r
219 \r
220     /**\r
221      * Attempt to get a modifier for the specified columns of this label.\r
222      * \r
223      * @param context\r
224      *            not used at the moment, ignore\r
225      * @param key\r
226      *            the key of the column of the label to modify. If the key is\r
227      *            prefixed with the character '#', it is an indication that the\r
228      *            client prefers a textual modifier for the column key instead\r
229      *            for the column named without the '#' prefix. Supporting the\r
230      *            '#' prefix is optional but recommended.\r
231      * @return a modifier for the specified label column or <code>null</code> if\r
232      *         there is no modifier for that label\r
233      */\r
234     Modifier getModifier(ModificationContext context, String key);\r
235 \r
236     /**\r
237      * Returns the category of this label. The category is a number used to\r
238      * allocate elements to bins; the bins are arranged in ascending numeric\r
239      * order. The elements within a bin are arranged via a second level sort\r
240      * criterion.\r
241      * \r
242      * @return the category\r
243      * \r
244      * @return a numeric value to categorize this label.\r
245      */\r
246     int getCategory();\r
247 \r
248     /**\r
249      * TODO: specify\r
250      * \r
251      * @param listener\r
252      */\r
253     void setListener(LabelerListener listener);\r
254 \r
255 }\r