--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.browsing.ui.content;\r
+\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.function.Consumer;\r
+\r
+import org.simantics.browsing.ui.GraphExplorer.ModificationContext;\r
+import org.simantics.browsing.ui.NodeContext;\r
+import org.simantics.browsing.ui.PrimitiveQueryUpdater;\r
+import org.simantics.utils.datastructures.ArrayMap;\r
+\r
+/**\r
+ * A Labeler is used for describing the viewer labeling aspects of a single UI\r
+ * (e.g. tree) node. Labelers are created on a per UI node basis. Labelers are\r
+ * created by {@link LabelerFactory}s.\r
+ * \r
+ * <p>\r
+ * A Labeler is responsible for providing a modifier for itself (\r
+ * {@link #getModifier(String)}).\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * A labeler is also responsible for informing of any changes happening in\r
+ * labels to using the {@link PrimitiveQueryUpdater} received by the\r
+ * {@link LabelerFactory} that created the Labeler. To signal that the labeler\r
+ * has been updated, invoke\r
+ * {@link PrimitiveQueryUpdater#scheduleReplace(NodeContext, org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey, Object)}\r
+ * and eventually the query system will request the labeler for the new\r
+ * results.\r
+ * </p>\r
+ * \r
+ * @author Antti Villberg\r
+ * \r
+ * @see ArrayMap A space-optimized immutable Map implementation for multicolumn values\r
+ */\r
+public interface Labeler {\r
+\r
+ public interface LabelerListener {\r
+ boolean columnModified(NodeContext context, String columnKey, String label);\r
+ boolean columnsModified(NodeContext context, Map<String, String> columns);\r
+ }\r
+\r
+ public interface Modifier {\r
+ /**\r
+ * Returns the value for the property referred by this modifier. Must\r
+ * not return <code>null</code> since the existence of this Modifier\r
+ * should be enough proof that a modifiable value actually does exist\r
+ * (see {@link Labeler#getModifier(String)}).\r
+ * \r
+ * @return the original property value to be modified\r
+ */\r
+ public String getValue();\r
+\r
+ /**\r
+ * @param label the label to test for validity\r
+ * @return <code>null</code> if the specified label is valid for this\r
+ * modifier or an error message if the label is invalid\r
+ */\r
+ public String isValid(String label);\r
+\r
+ /**\r
+ * @param label the new value to set for the property of this Labeler\r
+ * modified by this Modifier\r
+ */\r
+ public void modify(String label);\r
+ }\r
+ \r
+ public static class DeniedModifier implements Modifier {\r
+\r
+ final private String message;\r
+ \r
+ public DeniedModifier(String message) {\r
+ this.message = message;\r
+ }\r
+ \r
+ public String getMessage() {\r
+ return message;\r
+ }\r
+ \r
+ @Override\r
+ public String getValue() {\r
+ throw new IllegalStateException();\r
+ }\r
+\r
+ @Override\r
+ public String isValid(String label) {\r
+ throw new IllegalStateException();\r
+ }\r
+\r
+ @Override\r
+ public void modify(String label) {\r
+ throw new IllegalStateException();\r
+ }\r
+ \r
+ }\r
+\r
+ /**\r
+ * An additional interface that a modifier may implement if it wishes to\r
+ * filter the user's interactive input in some way before it is applied\r
+ * to the UI control.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+ public interface FilteringModifier {\r
+ /**\r
+ * The filter method receives most recent input received for the edited\r
+ * field. The method shall return a filtered version of the received\r
+ * <code>input</code> that is then applied into the text field as if it\r
+ * was the user's input.\r
+ * \r
+ * @param input\r
+ * the text that is about to be inserted before filtering\r
+ * @return filtered input\r
+ */\r
+ public String filter(String input);\r
+ }\r
+\r
+ /**\r
+ * A special modifier for handling editing of enumerations which have a set\r
+ * of predefined values that cannot change. The editing can therefore be\r
+ * performed for example using a read-only combo box.\r
+ * \r
+ * <p>\r
+ * {@link #getValue()} must be implemented to return the currently selected\r
+ * value among the list of possible values returned by {@link #getValues()}.\r
+ */\r
+ public interface EnumerationModifier extends Modifier {\r
+ /**\r
+ * @return all possible and valid values for the enumeration to be\r
+ * modified\r
+ */\r
+ public List<String> getValues();\r
+ }\r
+\r
+ /**\r
+ * A special modifier that allows the use of customized controls for editing.\r
+ */\r
+ public interface CustomModifier extends Modifier {\r
+ /**\r
+ * @param parentControl the parenting control for the editor controls\r
+ * @param controlItem the edited item within the parenting control\r
+ * @param columnIndex the column to be modified\r
+ * @param the data context of the item to be edited\r
+ * @return a control for client editing\r
+ */\r
+ Object createControl(Object parentControl, Object controlItem, int columnIndex, NodeContext context);\r
+ }\r
+\r
+ /**\r
+ * A special modifier that allows the use of customized controls for\r
+ * editing.\r
+ * \r
+ * {@link Modifier#getValue()} is unused for these since the dialog is\r
+ * responsible for getting its own data.\r
+ */\r
+ public interface DialogModifier extends Modifier {\r
+ /**\r
+ * @param parentControl the parenting control for the editor controls\r
+ * @param controlItem the edited item within the parenting control\r
+ * @param columnIndex the column to be modified\r
+ * @param the data context of the item to be edited\r
+ * @param applyCallback the dialog must call this when it wants to apply\r
+ * its changes\r
+ * @return status describing the result of the operation or\r
+ * <code>null</code> to ignore reporting\r
+ */\r
+ String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context,\r
+ Consumer<String> applyCallback);\r
+ }\r
+\r
+ String NO_LABEL = "<no label>";\r
+\r
+ /**\r
+ * Use this map as a return value of {@link #getLabels()} to indicate no\r
+ * labels.\r
+ */\r
+ Map<String, String> NO_LABELS = Collections.emptyMap();\r
+\r
+ /**\r
+ * Get the per-column labels associated with this labeler.\r
+ * <p>\r
+ * See <code>org.simantics.browsing.ui.common.ColumnKeys</code> for some\r
+ * re-usable column keys.\r
+ * \r
+ * @return a map of all the produced labels where the keys are the column\r
+ * names and the values are the corresponding column values\r
+ */\r
+ Map<String, String> getLabels();\r
+\r
+ /**\r
+ * Get the per-column labels associated with this labeler.\r
+ * \r
+ * <p>\r
+ * TODO: what is the difference to {@link #getLabels()}, is this really\r
+ * necessary or just an unnecessary optimization?\r
+ * \r
+ * <p>\r
+ * See <code>org.simantics.browsing.ui.common.ColumnKeys</code> for some\r
+ * re-usable column keys.\r
+ * \r
+ * @return a map of all the produced labels where the keys are the column\r
+ * names and the values are the corresponding column values. Use\r
+ * {@link Labeler#NO_LABELS} or {@link Collections#emptyMap()} when\r
+ * no labels are available, do not return <code>null</code>.\r
+ */\r
+ Map<String, String> getRuntimeLabels();\r
+\r
+ /**\r
+ * Attempt to get a modifier for the specified columns of this label.\r
+ * \r
+ * @param context\r
+ * not used at the moment, ignore\r
+ * @param key\r
+ * the key of the column of the label to modify. If the key is\r
+ * prefixed with the character '#', it is an indication that the\r
+ * client prefers a textual modifier for the column key instead\r
+ * for the column named without the '#' prefix. Supporting the\r
+ * '#' prefix is optional but recommended.\r
+ * @return a modifier for the specified label column or <code>null</code> if\r
+ * there is no modifier for that label\r
+ */\r
+ Modifier getModifier(ModificationContext context, String key);\r
+\r
+ /**\r
+ * Returns the category of this label. The category is a number used to\r
+ * allocate elements to bins; the bins are arranged in ascending numeric\r
+ * order. The elements within a bin are arranged via a second level sort\r
+ * criterion.\r
+ * \r
+ * @return the category\r
+ * \r
+ * @return a numeric value to categorize this label.\r
+ */\r
+ int getCategory();\r
+\r
+ /**\r
+ * TODO: specify\r
+ * \r
+ * @param listener\r
+ */\r
+ void setListener(LabelerListener listener);\r
+\r
+}\r