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