/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.browsing.ui.content; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Consumer; import org.simantics.browsing.ui.GraphExplorer.ModificationContext; import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.PrimitiveQueryUpdater; import org.simantics.utils.datastructures.ArrayMap; /** * A Labeler is used for describing the viewer labeling aspects of a single UI * (e.g. tree) node. Labelers are created on a per UI node basis. Labelers are * created by {@link LabelerFactory}s. * *

* A Labeler is responsible for providing a modifier for itself ( * {@link #getModifier(String)}). *

* *

* A labeler is also responsible for informing of any changes happening in * labels to using the {@link PrimitiveQueryUpdater} received by the * {@link LabelerFactory} that created the Labeler. To signal that the labeler * has been updated, invoke * {@link PrimitiveQueryUpdater#scheduleReplace(NodeContext, org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey, Object)} * and eventually the query system will request the labeler for the new * results. *

* * @author Antti Villberg * * @see ArrayMap A space-optimized immutable Map implementation for multicolumn values */ public interface Labeler { public interface LabelerListener { boolean columnModified(NodeContext context, String columnKey, String label); boolean columnsModified(NodeContext context, Map columns); } public interface Modifier { /** * Returns the value for the property referred by this modifier. Must * not return null since the existence of this Modifier * should be enough proof that a modifiable value actually does exist * (see {@link Labeler#getModifier(String)}). * * @return the original property value to be modified */ public String getValue(); /** * @param label the label to test for validity * @return null if the specified label is valid for this * modifier or an error message if the label is invalid */ public String isValid(String label); /** * @param label the new value to set for the property of this Labeler * modified by this Modifier */ public void modify(String label); } public static class DeniedModifier implements Modifier { final private String message; public DeniedModifier(String message) { this.message = message; } public String getMessage() { return message; } @Override public String getValue() { throw new IllegalStateException(); } @Override public String isValid(String label) { throw new IllegalStateException(); } @Override public void modify(String label) { throw new IllegalStateException(); } } /** * An additional interface that a modifier may implement if it wishes to * filter the user's interactive input in some way before it is applied * to the UI control. * * @author Tuukka Lehtonen */ public interface FilteringModifier { /** * The filter method receives most recent input received for the edited * field. The method shall return a filtered version of the received * input that is then applied into the text field as if it * was the user's input. * * @param input * the text that is about to be inserted before filtering * @return filtered input */ public String filter(String input); } /** * A special modifier for handling editing of enumerations which have a set * of predefined values that cannot change. The editing can therefore be * performed for example using a read-only combo box. * *

* {@link #getValue()} must be implemented to return the currently selected * value among the list of possible values returned by {@link #getValues()}. */ public interface EnumerationModifier extends Modifier { /** * @return all possible and valid values for the enumeration to be * modified */ public List getValues(); } /** * A special modifier that allows the use of customized controls for editing. */ public interface CustomModifier extends Modifier { /** * @param parentControl the parenting control for the editor controls * @param controlItem the edited item within the parenting control * @param columnIndex the column to be modified * @param the data context of the item to be edited * @return a control for client editing */ Object createControl(Object parentControl, Object controlItem, int columnIndex, NodeContext context); } /** * A special modifier that allows the use of customized controls for * editing. * * {@link Modifier#getValue()} is unused for these since the dialog is * responsible for getting its own data. */ public interface DialogModifier extends Modifier { /** * @param parentControl the parenting control for the editor controls * @param controlItem the edited item within the parenting control * @param columnIndex the column to be modified * @param the data context of the item to be edited * @param applyCallback the dialog must call this when it wants to apply * its changes * @return status describing the result of the operation or * null to ignore reporting */ String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context, Consumer applyCallback); } String NO_LABEL = ""; /** * Use this map as a return value of {@link #getLabels()} to indicate no * labels. */ Map NO_LABELS = Collections.emptyMap(); /** * Get the per-column labels associated with this labeler. *

* See org.simantics.browsing.ui.common.ColumnKeys for some * re-usable column keys. * * @return a map of all the produced labels where the keys are the column * names and the values are the corresponding column values */ Map getLabels(); /** * Get the per-column labels associated with this labeler. * *

* TODO: what is the difference to {@link #getLabels()}, is this really * necessary or just an unnecessary optimization? * *

* See org.simantics.browsing.ui.common.ColumnKeys for some * re-usable column keys. * * @return a map of all the produced labels where the keys are the column * names and the values are the corresponding column values. Use * {@link Labeler#NO_LABELS} or {@link Collections#emptyMap()} when * no labels are available, do not return null. */ Map getRuntimeLabels(); /** * Attempt to get a modifier for the specified columns of this label. * * @param context * not used at the moment, ignore * @param key * the key of the column of the label to modify. If the key is * prefixed with the character '#', it is an indication that the * client prefers a textual modifier for the column key instead * for the column named without the '#' prefix. Supporting the * '#' prefix is optional but recommended. * @return a modifier for the specified label column or null if * there is no modifier for that label */ Modifier getModifier(ModificationContext context, String key); /** * Returns the category of this label. The category is a number used to * allocate elements to bins; the bins are arranged in ascending numeric * order. The elements within a bin are arranged via a second level sort * criterion. * * @return the category * * @return a numeric value to categorize this label. */ int getCategory(); /** * TODO: specify * * @param listener */ void setListener(LabelerListener listener); }