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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.browsing.ui.content;
\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
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
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
30 * A Labeler is responsible for providing a modifier for itself (
\r
31 * {@link #getModifier(String)}).
\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
44 * @author Antti Villberg
\r
46 * @see ArrayMap A space-optimized immutable Map implementation for multicolumn values
\r
48 public interface Labeler {
\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
55 public interface Modifier {
\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
62 * @return the original property value to be modified
\r
64 public String getValue();
\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
71 public String isValid(String label);
\r
74 * @param label the new value to set for the property of this Labeler
\r
75 * modified by this Modifier
\r
77 public void modify(String label);
\r
80 public static class DeniedModifier implements Modifier {
\r
82 final private String message;
\r
84 public DeniedModifier(String message) {
\r
85 this.message = message;
\r
88 public String getMessage() {
\r
93 public String getValue() {
\r
94 throw new IllegalStateException();
\r
98 public String isValid(String label) {
\r
99 throw new IllegalStateException();
\r
103 public void modify(String label) {
\r
104 throw new IllegalStateException();
\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
114 * @author Tuukka Lehtonen
\r
116 public interface FilteringModifier {
\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
124 * the text that is about to be inserted before filtering
\r
125 * @return filtered input
\r
127 public String filter(String input);
\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
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
139 public interface EnumerationModifier extends Modifier {
\r
141 * @return all possible and valid values for the enumeration to be
\r
144 public List<String> getValues();
\r
148 * A special modifier that allows the use of customized controls for editing.
\r
150 public interface CustomModifier extends Modifier {
\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
158 Object createControl(Object parentControl, Object controlItem, int columnIndex, NodeContext context);
\r
162 * A special modifier that allows the use of customized controls for
\r
165 * {@link Modifier#getValue()} is unused for these since the dialog is
\r
166 * responsible for getting its own data.
\r
168 public interface DialogModifier extends Modifier {
\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
176 * @return status describing the result of the operation or
\r
177 * <code>null</code> to ignore reporting
\r
179 String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context,
\r
180 Consumer<String> applyCallback);
\r
183 String NO_LABEL = "<no label>";
\r
186 * Use this map as a return value of {@link #getLabels()} to indicate no
\r
189 Map<String, String> NO_LABELS = Collections.emptyMap();
\r
192 * Get the per-column labels associated with this labeler.
\r
194 * See <code>org.simantics.browsing.ui.common.ColumnKeys</code> for some
\r
195 * re-usable column keys.
\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
200 Map<String, String> getLabels();
\r
203 * Get the per-column labels associated with this labeler.
\r
206 * TODO: what is the difference to {@link #getLabels()}, is this really
\r
207 * necessary or just an unnecessary optimization?
\r
210 * See <code>org.simantics.browsing.ui.common.ColumnKeys</code> for some
\r
211 * re-usable column keys.
\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
218 Map<String, String> getRuntimeLabels();
\r
221 * Attempt to get a modifier for the specified columns of this label.
\r
224 * not used at the moment, ignore
\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
234 Modifier getModifier(ModificationContext context, String key);
\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
242 * @return the category
\r
244 * @return a numeric value to categorize this label.
\r
253 void setListener(LabelerListener listener);
\r