return rvi;\r
}\r
\r
-// @Override\r
-// public int hashCode() {\r
-// return rvi.hashCode();\r
-// }\r
-// \r
-// @Override\r
-// public boolean equals(Object obj) {\r
-// if (obj.getClass() != getClass())\r
-// return false;\r
-// ChartVariable other = (ChartVariable)obj;\r
-// return rvi.equals(other.rvi);\r
-// }\r
+ @Override\r
+ public int hashCode() {\r
+ return rvi.hashCode();\r
+ }\r
+ \r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (obj.getClass() != getClass())\r
+ return false;\r
+ ChartVariable other = (ChartVariable)obj;\r
+ return rvi.equals(other.rvi);\r
+ }\r
\r
}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+public class ChartVariableFactory extends ReadFactoryImpl<Resource, ChartVariable>{\r
+ \r
+ private Map<String,ChartVariable> map;\r
+ \r
+ public ChartVariableFactory(Collection<ChartVariable> data) {\r
+ map = new HashMap<String, ChartVariable>();\r
+ for (ChartVariable v : data) {\r
+ map.put(v.getRvi(), v);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public ChartVariable perform(ReadGraph graph, Resource input)\r
+ throws DatabaseException {\r
+ String rvi = graph.getPossibleRelatedValue(input, JFreeChartResource.getInstance(graph).variableRVI);\r
+ if (rvi == null)\r
+ return null;\r
+ return map.get(rvi);\r
+ \r
+ }\r
+\r
+}\r
import org.eclipse.jface.fieldassist.IContentProposalListener2;\r
import org.eclipse.jface.fieldassist.TextContentAdapter;\r
import org.eclipse.swt.widgets.Control;\r
-import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListenerImpl;\r
-import org.simantics.browsing.ui.swt.widgets.impl.TrackedModifyEvent;\r
import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
import org.simantics.databoard.Bindings;\r
import org.simantics.db.Resource;\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.sysdyn.JFreeChartResource;\r
\r
-public class VariableModifier extends TextModifyListenerImpl<Resource> {\r
+public class ChartVariableModifier extends StringChooserModifyListenerImpl<Resource, ChartVariable> {\r
\r
private boolean active;\r
private Control control;\r
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','Å','Ä','Ö',\r
'1','2','3','4','5','6','7','8','9','0','.','_'};\r
\r
- public VariableModifier(Control control, WidgetSupport support) {\r
+ public ChartVariableModifier(Control control, WidgetSupport support) {\r
this.control = control;\r
this.active = true;\r
\r
}\r
\r
//SimpleContentProposalProvider scpp = new VariableProposalProvider(control, support);\r
- IdLabelProposalProvider scpp = new VariableProposalProvider(control, support);\r
+ VariableProposalProvider scpp = new VariableProposalProvider(control, support);\r
scpp.setFiltering(true);\r
\r
ContentProposalAdapter adapter = new ContentProposalAdapter(\r
\r
@Override\r
public void proposalPopupOpened(ContentProposalAdapter adapter) {\r
- if(VariableModifier.this != null)\r
- VariableModifier.this.deactivate();\r
+ if(ChartVariableModifier.this != null)\r
+ ChartVariableModifier.this.deactivate();\r
}\r
\r
@Override\r
public void proposalPopupClosed(ContentProposalAdapter adapter) {\r
- if(VariableModifier.this != null)\r
- VariableModifier.this.activate();\r
+ if(ChartVariableModifier.this != null)\r
+ ChartVariableModifier.this.activate();\r
}\r
});\r
\r
\r
@Override\r
public void proposalAccepted(IContentProposal proposal) {\r
- if(VariableModifier.this.control != null && !VariableModifier.this.control.isDisposed())\r
- VariableModifier.this.modifyText(new TrackedModifyEvent(VariableModifier.this.control, proposal.getLabel()));\r
+ if(ChartVariableModifier.this.control != null && !ChartVariableModifier.this.control.isDisposed())\r
+ ChartVariableModifier.this.modifySelection(new StringChooserModifyEvent<ChartVariable>(ChartVariableModifier.this.control, new ChartVariable(proposal.getContent(), proposal.getLabel()), proposal.getLabel()));\r
}\r
});\r
\r
\r
}\r
- \r
-\r
- @Override\r
- public void applyText(WriteGraph graph, Resource resource, String text) throws DatabaseException {\r
- if(active) {\r
+ \r
+ @Override\r
+ public void applyObject(WriteGraph graph, Resource resource, ChartVariable object, String text) throws DatabaseException {\r
+ if(active) {\r
JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
- graph.claimLiteral(resource, jfree.variableRVI, text, Bindings.STRING);\r
+ graph.claimLiteral(resource, jfree.variableRVI, object.getRvi(), Bindings.STRING);\r
graph.deny(resource, jfree.variableFilter);\r
}\r
- }\r
+ \r
+ }\r
+ \r
\r
- public void deactivate() {\r
- active = false;\r
- }\r
\r
- public void activate() {\r
- active = true;\r
- } \r
+ public void deactivate() {\r
+ active = false;\r
+ }\r
+\r
+ public void activate() {\r
+ active = true;\r
+ } \r
\r
}\r
+++ /dev/null
-package org.simantics.jfreechart.chart.properties;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Iterator;\r
-\r
-import org.eclipse.jface.fieldassist.ContentProposal;\r
-import org.eclipse.jface.fieldassist.IContentProposal;\r
-import org.eclipse.jface.fieldassist.IContentProposalProvider;\r
-import org.simantics.utils.datastructures.Pair;\r
-\r
-public class IdLabelProposalProvider implements IContentProposalProvider{\r
-\r
- /*\r
- * The proposals provided.\r
- */\r
- private Collection<ChartVariable> proposals;\r
-\r
- /*\r
- * The proposals mapped to IContentProposal. Cached for speed in the case\r
- * where filtering is not used.\r
- */\r
- private IContentProposal[] contentProposals;\r
-\r
- /*\r
- * Boolean that tracks whether filtering is used.\r
- */\r
- private boolean filterProposals = false;\r
-\r
- /**\r
- * Construct a SimpleContentProposalProvider whose content proposals are\r
- * always the specified array of Objects.\r
- * \r
- * @param proposals\r
- * the array of Strings to be returned whenever proposals are\r
- * requested.\r
- */\r
- public IdLabelProposalProvider(Collection<ChartVariable> proposals) {\r
- super();\r
- this.proposals = proposals;\r
- }\r
-\r
- /**\r
- * Return an array of Objects representing the valid content proposals for a\r
- * field. \r
- * \r
- * @param contents\r
- * the current contents of the field (only consulted if filtering\r
- * is set to <code>true</code>)\r
- * @param position\r
- * the current cursor position within the field (ignored)\r
- * @return the array of Objects that represent valid proposals for the field\r
- * given its current content.\r
- */\r
- @SuppressWarnings("unchecked")\r
- public IContentProposal[] getProposals(String contents, int position) {\r
- if (filterProposals) {\r
- ArrayList list = new ArrayList();\r
- for (ChartVariable proposal : proposals) {\r
- if (proposal.getRvi().length() >= contents.length() && proposal.getRvi().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
- if (proposal.getLabel() != null)\r
- list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
- else\r
- list.add(new ContentProposal(proposal.getRvi()));\r
- } else if (proposal.getLabel() != null && proposal.getLabel().length() >= contents.length() && proposal.getLabel().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
- list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
- }\r
- }\r
- \r
- return (IContentProposal[]) list.toArray(new IContentProposal[list\r
- .size()]);\r
- }\r
- if (contentProposals == null) {\r
- contentProposals = new IContentProposal[proposals.size()];\r
- Iterator<ChartVariable> iter = proposals.iterator();\r
- for (int i = 0; i < proposals.size(); i++) {\r
- ChartVariable proposal = iter.next();\r
- if (proposal.getLabel() != null)\r
- contentProposals[i] = new ContentProposal(proposal.getRvi(),proposal.getLabel(),null);\r
- else\r
- contentProposals[i] = new ContentProposal(proposal.getRvi());\r
- }\r
- }\r
- return contentProposals;\r
- }\r
-\r
- /**\r
- * Set the Strings to be used as content proposals.\r
- * \r
- * @param items\r
- * the array of Strings to be used as proposals.\r
- */\r
- public void setProposals(Collection<ChartVariable> items) {\r
- this.proposals = items;\r
- contentProposals = null;\r
- }\r
-\r
- /**\r
- * Set the boolean that controls whether proposals are filtered according to\r
- * the current field content.\r
- * \r
- * @param filterProposals\r
- * <code>true</code> if the proposals should be filtered to\r
- * show only those that match the current contents of the field,\r
- * and <code>false</code> if the proposals should remain the\r
- * same, ignoring the field content.\r
- * @since 3.3\r
- */\r
- public void setFiltering(boolean filterProposals) {\r
- this.filterProposals = filterProposals;\r
- // Clear any cached proposals.\r
- contentProposals = null;\r
- }\r
-}\r
import org.eclipse.jface.fieldassist.IContentProposal;\r
import org.eclipse.jface.fieldassist.IContentProposalListener;\r
import org.eclipse.jface.fieldassist.IContentProposalListener2;\r
-import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;\r
import org.eclipse.jface.fieldassist.TextContentAdapter;\r
import org.eclipse.swt.widgets.Control;\r
import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListenerImpl;\r
}\r
\r
//SimpleContentProposalProvider scpp = new VariableProposalProvider(control, support);\r
- IdLabelProposalProvider scpp = new VariableProposalProvider(control, support);\r
+ VariableProposalProvider scpp = new VariableProposalProvider(control, support);\r
scpp.setFiltering(true);\r
\r
ContentProposalAdapter adapter = new ContentProposalAdapter(\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.Assert;\r
+import org.eclipse.core.runtime.ListenerList;\r
+import org.eclipse.jface.dialogs.IInputValidator;\r
+import org.eclipse.jface.resource.JFaceResources;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.resource.ResourceManager;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.MouseTrackListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Font;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.simantics.browsing.ui.swt.widgets.DefaultColorProvider;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ITrackedColorProvider;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.procedure.Listener;\r
+\r
+/**\r
+ * Widget for choosing and labeled object from a set of objects.\r
+ * \r
+ * Supports cases when multiple objects have the same label (as much as possible)\r
+ * \r
+ * \r
+ * Based on org.simantics.browsing.ui.swt.widgets.Trackedtext\r
+ * \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class StringChooser<T> implements Widget{\r
+ private static final int EDITING = 1 << 0;\r
+ private static final int MODIFIED_DURING_EDITING = 1 << 1;\r
+\r
+ /**\r
+ * Used to tell whether or not a mouseDown has occurred after a focusGained\r
+ * event to be able to select the whole text field when it is pressed for\r
+ * the first time while the widget holds focus.\r
+ */\r
+ private static final int MOUSE_DOWN_FIRST_TIME = 1 << 2;\r
+ private static final int MOUSE_INSIDE_CONTROL = 1 << 3;\r
+ \r
+ private int caretPositionBeforeEdit;\r
+ \r
+ private String textBeforeEdit;\r
+\r
+ private int state;\r
+\r
+ private Map<T,String> objectToLabel;\r
+ private Set<String> allowedLabels;\r
+ \r
+ private T selected;\r
+ \r
+ private final Display display;\r
+\r
+ private final Text text;\r
+ \r
+ private CompositeListener listener;\r
+\r
+ private ListenerList modifyListeners;\r
+\r
+ private ReadFactory<?, T> objectFactory;\r
+ \r
+ private ITrackedColorProvider colorProvider;\r
+\r
+ private final ResourceManager resourceManager;\r
+ \r
+ private boolean moveCaretAfterEdit = true;\r
+ \r
+ private boolean selectAllOnStartEdit = true;\r
+ \r
+ public StringChooser(Composite parent, WidgetSupport support, int style) {\r
+ this.state = 0;\r
+ this.text = new Text(parent, style);\r
+ this.display = text.getDisplay();\r
+ this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), text);\r
+ this.colorProvider = new DefaultColorProvider(resourceManager);\r
+ if (support!=null) support.register(this);\r
+ initialize();\r
+ }\r
+ \r
+\r
+ \r
+ public ResourceManager getResourceManager() {\r
+ return resourceManager;\r
+ }\r
+ \r
+ public void setFont(Font font) {\r
+ text.setFont(font);\r
+ }\r
+ \r
+ public void setObjectFactory(ReadFactory<?, T> objectFactory) {\r
+ this.objectFactory = objectFactory;\r
+ }\r
+ \r
+ public void setMoveCaretAfterEdit(boolean value) {\r
+ this.moveCaretAfterEdit = value;\r
+ }\r
+ \r
+ public void setData(Map<T,String> data) {\r
+ this.objectToLabel = data;\r
+ this.allowedLabels = new HashSet<String>();\r
+ this.allowedLabels.addAll(objectToLabel.values());\r
+ }\r
+ \r
+ public void setData(Collection<T> data) {\r
+ this.objectToLabel = new HashMap<T, String>();\r
+ this.allowedLabels = new HashSet<String>();\r
+ for (T t : data) {\r
+ String label = t.toString();\r
+ objectToLabel.put(t, label);\r
+ allowedLabels.add(label);\r
+ }\r
+ }\r
+ \r
+ public void setSelected(T selected) {\r
+ if (selected != null) {\r
+ String label = objectToLabel.get(selected);\r
+ if (label == null)\r
+ return;\r
+ this.selected = selected;\r
+ this.text.setText(label);\r
+ } else {\r
+ this.selected = null;\r
+ this.text.setText("");\r
+ }\r
+ }\r
+ \r
+ public void setSelected(String label) {\r
+ // TODO : we could create a label to object map.\r
+ for (T t : objectToLabel.keySet()) {\r
+ if (label.equals(objectToLabel.get(t))) {\r
+ setSelected(t);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ if (modifyListeners != null) {\r
+ for (Object o : modifyListeners.getListeners()) {\r
+ if(o instanceof Widget) {\r
+ ((Widget) o).setInput(context, input);\r
+ }\r
+ }\r
+ }\r
+ \r
+ if(objectFactory != null) {\r
+ objectFactory.listen(context, input, new Listener<T>() {\r
+\r
+ @Override\r
+ public void exception(final Throwable t) {\r
+ display.asyncExec(new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+ if(isDisposed()) return;\r
+// System.out.println("Button received new text: " + text);\r
+ text.setText(t.toString());\r
+ }\r
+\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void execute(final T object) {\r
+ \r
+ if(text.isDisposed()) return;\r
+ \r
+ display.asyncExec(new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+ if(isDisposed()) return;\r
+ setSelected(object);\r
+// text.getParent().layout();\r
+// text.getParent().getParent().layout();\r
+ }\r
+\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return text.isDisposed();\r
+ }\r
+\r
+ });\r
+ }\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Common initialization. Assumes that text is already created.\r
+ */\r
+ private void initialize() {\r
+ Assert.isNotNull(text);\r
+\r
+ text.setBackground(colorProvider.getInactiveBackground());\r
+ text.setDoubleClickEnabled(false);\r
+\r
+ listener = new CompositeListener();\r
+\r
+ text.addModifyListener(listener);\r
+ text.addDisposeListener(listener);\r
+ text.addKeyListener(listener);\r
+ text.addMouseTrackListener(listener);\r
+ text.addMouseListener(listener);\r
+ text.addFocusListener(listener);\r
+ }\r
+ \r
+ public void startEdit(boolean selectAll) {\r
+ if (isEditing()) {\r
+ // Print some debug incase we end are in an invalid state\r
+ System.out.println("TrackedText: BUG: startEdit called when in editing state");\r
+ }\r
+// System.out.println("start edit: selectall=" + selectAll + ", text=" + text.getText() + ", caretpos=" + caretPositionBeforeEdit);\r
+\r
+ // Backup text-field data for reverting purposes\r
+ caretPositionBeforeEdit = text.getCaretPosition();\r
+ textBeforeEdit = text.getText();\r
+\r
+ // Signal editing state\r
+ setBackground(colorProvider.getEditingBackground());\r
+\r
+ if (selectAll) {\r
+ text.selectAll();\r
+ }\r
+ state |= EDITING | MOUSE_DOWN_FIRST_TIME;\r
+ }\r
+\r
+ private void applyEdit() {\r
+ try {\r
+ if (isTextValid() != null) {\r
+ text.setText(textBeforeEdit);\r
+ } else if (isModified() && !text.getText().equals(textBeforeEdit)) {\r
+ setSelected(text.getText());\r
+ //System.out.println("apply");\r
+ if (modifyListeners != null) {\r
+ StringChooserModifyEvent event = new StringChooserModifyEvent(text, selected, text.getText());\r
+ for (Object o : modifyListeners.getListeners()) {\r
+ ((StringChooserModifyListener) o).modifySelection(event);\r
+ }\r
+ }\r
+ }\r
+ } catch (Throwable t) {\r
+ t.printStackTrace();\r
+ } finally {\r
+ endEdit();\r
+ }\r
+ }\r
+\r
+ private void endEdit() {\r
+ if (text.isDisposed())\r
+ return;\r
+\r
+ if (!isEditing()) {\r
+ // Print some debug incase we end are in an invalid state\r
+ //ExceptionUtils.logError(new Exception("BUG: endEdit called when not in editing state"));\r
+ //System.out.println();\r
+ }\r
+ setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
+// System.out.println("endEdit: " + text.getText() + ", caret: " + text.getCaretLocation() + ", selection: " + text.getSelection());\r
+ // Always move the caret to the end of the string\r
+ if(moveCaretAfterEdit)\r
+ text.setSelection(text.getCharCount());\r
+ state &= ~(EDITING | MOUSE_DOWN_FIRST_TIME);\r
+ setModified(false);\r
+ }\r
+\r
+ private void revertEdit() {\r
+ if (!isEditing()) {\r
+ // Print some debug incase we end are in an invalid state\r
+ //ExceptionUtils.logError(new Exception("BUG: revertEdit called when not in editing state"));\r
+ System.out.println("BUG: revertEdit called when not in editing state");\r
+ }\r
+ text.setText(textBeforeEdit);\r
+ text.setSelection(caretPositionBeforeEdit);\r
+ setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
+ state &= ~(EDITING | MOUSE_DOWN_FIRST_TIME);\r
+ setModified(false);\r
+ }\r
+\r
+ private boolean isEditing() {\r
+ return (state & EDITING) != 0;\r
+ }\r
+\r
+ private void setModified(boolean modified) {\r
+ if (modified) {\r
+ state |= MODIFIED_DURING_EDITING;\r
+ } else {\r
+ state &= ~MODIFIED_DURING_EDITING;\r
+ }\r
+ }\r
+\r
+ private boolean isMouseInsideControl() {\r
+ return (state & MOUSE_INSIDE_CONTROL) != 0;\r
+ }\r
+\r
+ private void setMouseInsideControl(boolean inside) {\r
+ if (inside)\r
+ state |= MOUSE_INSIDE_CONTROL;\r
+ else\r
+ state &= ~MOUSE_INSIDE_CONTROL;\r
+ }\r
+\r
+ private boolean isModified() {\r
+ return (state & MODIFIED_DURING_EDITING) != 0;\r
+ }\r
+\r
+ public void setSelectAllOnStartEdit(boolean selectAll) {\r
+ this.selectAllOnStartEdit = selectAll;\r
+ }\r
+ \r
+ public void setEditable(boolean editable) {\r
+ if (editable) {\r
+ text.setEditable(true);\r
+ setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
+ } else {\r
+ text.setEditable(false);\r
+ text.setBackground(null);\r
+ }\r
+ }\r
+\r
+ public void setText(String text) {\r
+ this.text.setText(text);\r
+ }\r
+\r
+ public void setTextWithoutNotify(String text) {\r
+ this.text.removeModifyListener(listener);\r
+ setText(text);\r
+ this.text.addModifyListener(listener);\r
+ }\r
+\r
+ public Text getWidget() {\r
+ return text;\r
+ }\r
+\r
+ public synchronized void addModifyListener(StringChooserModifyListener listener) {\r
+ if (modifyListeners == null) {\r
+ modifyListeners = new ListenerList(ListenerList.IDENTITY);\r
+ }\r
+ modifyListeners.add(listener);\r
+ }\r
+\r
+ public synchronized void removeModifyListener(StringChooserModifyListener listener) {\r
+ if (modifyListeners == null)\r
+ return;\r
+ modifyListeners.remove(listener);\r
+ }\r
+\r
+ \r
+\r
+ private String isTextValid() {\r
+ if (allowedLabels.contains(getWidget().getText()))\r
+ return null;\r
+ return "There is no such object.";\r
+ }\r
+\r
+ public void setColorProvider(ITrackedColorProvider provider) {\r
+ Assert.isNotNull(provider);\r
+ this.colorProvider = provider;\r
+ }\r
+\r
+ private void setBackground(Color background) {\r
+ if(text.isDisposed()) return;\r
+ if (!text.getEditable()) {\r
+ // Do not alter background when the widget is not editable.\r
+ return;\r
+ }\r
+ text.setBackground(background);\r
+ }\r
+ \r
+ public boolean isDisposed() {\r
+ return text.isDisposed();\r
+ }\r
+ \r
+ public Display getDisplay() {\r
+ return display;\r
+ }\r
+ \r
+ public String getText() {\r
+ return text.getText();\r
+ }\r
+ \r
+ public int getCaretPosition() {\r
+ return text.getCaretPosition();\r
+ }\r
+ \r
+ \r
+ /**\r
+ * A composite of many UI listeners for creating the functionality of this\r
+ * class.\r
+ */\r
+ private class CompositeListener\r
+ implements ModifyListener, DisposeListener, KeyListener, MouseTrackListener,\r
+ MouseListener, FocusListener\r
+ {\r
+ // Keyboard/editing events come in the following order:\r
+ // 1. keyPressed\r
+ // 2. verifyText\r
+ // 3. modifyText\r
+ // 4. keyReleased\r
+\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ //System.out.println("modifyText: " + e);\r
+ setModified(true);\r
+\r
+ String valid = isTextValid();\r
+ if (valid != null) {\r
+ setBackground(colorProvider.getInvalidBackground());\r
+ } else {\r
+ if (isEditing())\r
+ setBackground(colorProvider.getEditingBackground());\r
+ else\r
+ setBackground(colorProvider.getInactiveBackground());\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void widgetDisposed(DisposeEvent e) {\r
+ getWidget().removeModifyListener(this);\r
+ }\r
+\r
+ private boolean isMultiLine() {\r
+ return (text.getStyle() & SWT.MULTI) != 0;\r
+ }\r
+\r
+ private boolean hasMultiLineCommitModifier(KeyEvent e) {\r
+ return (e.stateMask & SWT.CTRL) != 0;\r
+ }\r
+\r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ //System.out.println("keyPressed: " + e);\r
+ if (!isEditing()) {\r
+ // ESC, ENTER & keypad ENTER must not start editing\r
+ if (e.keyCode == SWT.ESC)\r
+ return;\r
+\r
+ if (!isMultiLine()) {\r
+ if (e.keyCode == SWT.F2 || e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+ startEdit(selectAllOnStartEdit);\r
+ } else if (e.character != '\0') {\r
+ startEdit(false);\r
+ }\r
+ } else {\r
+ // In multi-line mode, TAB must not start editing!\r
+ if (e.keyCode == SWT.F2) {\r
+ startEdit(selectAllOnStartEdit);\r
+ } else if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+ if (hasMultiLineCommitModifier(e)) {\r
+ e.doit = false;\r
+ } else {\r
+ startEdit(false);\r
+ }\r
+ } else if (e.keyCode == SWT.TAB) {\r
+ text.traverse(((e.stateMask & SWT.SHIFT) != 0) ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT);\r
+ e.doit = false;\r
+ } else if (e.character != '\0') {\r
+ startEdit(false);\r
+ }\r
+ }\r
+ } else {\r
+ // ESC reverts any changes made during this edit\r
+ if (e.keyCode == SWT.ESC) {\r
+ revertEdit();\r
+ }\r
+ if (!isMultiLine()) {\r
+ if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+ applyEdit();\r
+ }\r
+ } else {\r
+ if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+ if (hasMultiLineCommitModifier(e)) {\r
+ applyEdit();\r
+ e.doit = false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void keyReleased(KeyEvent e) {\r
+ //System.out.println("keyReleased: " + e);\r
+ }\r
+\r
+ @Override\r
+ public void mouseEnter(MouseEvent e) {\r
+ //System.out.println("mouseEnter");\r
+ if (!isEditing()) {\r
+ setBackground(colorProvider.getHoverBackground());\r
+ }\r
+ setMouseInsideControl(true);\r
+ }\r
+\r
+ @Override\r
+ public void mouseExit(MouseEvent e) {\r
+ //System.out.println("mouseExit");\r
+ if (!isEditing()) {\r
+ setBackground(colorProvider.getInactiveBackground());\r
+ }\r
+ setMouseInsideControl(false);\r
+ }\r
+\r
+ @Override\r
+ public void mouseHover(MouseEvent e) {\r
+ //System.out.println("mouseHover");\r
+ setMouseInsideControl(true);\r
+ }\r
+\r
+ @Override\r
+ public void mouseDoubleClick(MouseEvent e) {\r
+ //System.out.println("mouseDoubleClick: " + e);\r
+ if (e.button == 1) {\r
+ getWidget().selectAll();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void mouseDown(MouseEvent e) {\r
+ //System.out.println("mouseDown: " + e);\r
+ if (!isEditing()) {\r
+ // In reality we should never get here, since focusGained\r
+ // always comes before mouseDown, but let's keep this\r
+ // fallback just to be safe.\r
+ if (e.button == 1) {\r
+ startEdit(selectAllOnStartEdit);\r
+ }\r
+ } else {\r
+ if (e.button == 1 && (state & MOUSE_DOWN_FIRST_TIME) != 0) {\r
+ if (!isMultiLine()) {\r
+ // This is useless for multi-line texts\r
+ getWidget().selectAll();\r
+ }\r
+ state &= ~MOUSE_DOWN_FIRST_TIME;\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void mouseUp(MouseEvent e) {\r
+ }\r
+\r
+ @Override\r
+ public void focusGained(FocusEvent e) {\r
+ //System.out.println("focusGained");\r
+ if (!isEditing()) {\r
+ if (!isMultiLine()) {\r
+ // Always start edit on single line texts when focus is gained\r
+ startEdit(selectAllOnStartEdit);\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void focusLost(FocusEvent e) {\r
+ //System.out.println("focusLost");\r
+ if (isEditing()) {\r
+ applyEdit();\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.EventObject;\r
+\r
+import org.eclipse.swt.widgets.Widget;\r
+\r
+public class StringChooserModifyEvent<T> extends EventObject {\r
+\r
+ private static final long serialVersionUID = 2630732165074702762L;\r
+ \r
+ private T object;\r
+ private String text;\r
+ \r
+ public StringChooserModifyEvent(Widget source, T object, String text) {\r
+ super(source);\r
+ this.object = object;\r
+ this.text = text;\r
+ }\r
+ \r
+ public Widget getWidget() {\r
+ return (Widget) getSource();\r
+ }\r
+ \r
+ public T getObject() {\r
+ return object;\r
+ }\r
+\r
+ public String getText() {\r
+ return text;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+public interface StringChooserModifyListener<T> {\r
+\r
+ \r
+ void modifySelection(StringChooserModifyEvent<T> e);\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.utils.ReflectionUtils;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+\r
+public abstract class StringChooserModifyListenerImpl<T,T2> implements StringChooserModifyListener<T2>, Widget {\r
+ protected ISessionContext context;\r
+ protected T lastInput = null;\r
+\r
+ protected final Class<?> clazz;\r
+\r
+ public StringChooserModifyListenerImpl() {\r
+ clazz = ReflectionUtils.getSingleParameterType(getClass());\r
+ }\r
+\r
+ private Object getInputContents(Object input, Class<?> inputClass) {\r
+ if (inputClass.isInstance(input))\r
+ return input;\r
+ if (input instanceof ISelection)\r
+ return ISelectionUtils.filterSingleSelection(input, inputClass);\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void modifySelection(StringChooserModifyEvent<T2> e) {\r
+\r
+ Text text = (Text)e.getWidget();\r
+ final T2 object = e.getObject();\r
+ final String textValue = text.getText();\r
+ final T input = lastInput;\r
+\r
+ try {\r
+ context.getSession().syncRequest(new WriteRequest() {\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ \r
+ if(clazz.isInstance(input)) {\r
+ applyObject(graph, (T)input, object, textValue);\r
+ } else {\r
+ T single = (T)getInputContents(input, clazz);\r
+ if(single != null)\r
+ applyObject(graph, single, object, textValue);\r
+ }\r
+\r
+ \r
+ }\r
+ \r
+ });\r
+ } catch (DatabaseException e1) {\r
+ e1.printStackTrace();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void setInput(ISessionContext context, Object parameter) {\r
+ this.context = context;\r
+ lastInput = (T)parameter;\r
+ }\r
+\r
+ abstract public void applyObject(WriteGraph graph, T input, T2 object, String text) throws DatabaseException;\r
+\r
+}\r
+++ /dev/null
-package org.simantics.jfreechart.chart.properties;\r
-\r
-import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.sysdyn.JFreeChartResource;\r
-import org.simantics.utils.datastructures.BijectionMap;\r
-\r
-public class VariableFactory extends ReadFactoryImpl<Resource, String> {\r
- BijectionMap<String , String> map = new BijectionMap<String, String>();\r
- \r
- public VariableFactory(BijectionMap<String , String> map) {\r
- this.map = map;\r
- }\r
- \r
- @Override\r
- public String perform(ReadGraph graph, Resource input) throws DatabaseException {\r
- String value = graph.getPossibleRelatedValue(input, JFreeChartResource.getInstance(graph).variableRVI);\r
- if (value == null)\r
- return "";\r
- value = map.getRight(value);\r
- if (value == null)\r
- return "";\r
- return value;\r
- \r
- }\r
-\r
-}\r
\r
import java.util.ArrayList;\r
import java.util.Collection;\r
+import java.util.Iterator;\r
\r
-import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;\r
+import org.eclipse.jface.fieldassist.ContentProposal;\r
+import org.eclipse.jface.fieldassist.IContentProposal;\r
+import org.eclipse.jface.fieldassist.IContentProposalProvider;\r
import org.eclipse.swt.widgets.Control;\r
import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
import org.simantics.db.procedure.Listener;\r
import org.simantics.ui.SimanticsUI;\r
import org.simantics.ui.utils.AdaptionUtils;\r
-import org.simantics.utils.datastructures.Pair;\r
\r
/**\r
- * Provides all variables a model contains\r
* \r
- * @author Teemu Lempinen\r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
*\r
*/\r
-public class VariableProposalProvider extends IdLabelProposalProvider implements Widget {\r
+public class VariableProposalProvider implements IContentProposalProvider, Widget {\r
\r
+ /*\r
+ * The proposals provided.\r
+ */\r
+ private Collection<ChartVariable> proposals;\r
+\r
+ /*\r
+ * The proposals mapped to IContentProposal. Cached for speed in the case\r
+ * where filtering is not used.\r
+ */\r
+ private IContentProposal[] contentProposals;\r
+\r
+ /*\r
+ * Boolean that tracks whether filtering is used.\r
+ */\r
+ private boolean filterProposals = false;\r
+\r
+\r
+ private boolean compareRVI = false;\r
+ /**\r
+ * Return an array of Objects representing the valid content proposals for a\r
+ * field. \r
+ * \r
+ * @param contents\r
+ * the current contents of the field (only consulted if filtering\r
+ * is set to <code>true</code>)\r
+ * @param position\r
+ * the current cursor position within the field (ignored)\r
+ * @return the array of Objects that represent valid proposals for the field\r
+ * given its current content.\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public IContentProposal[] getProposals(String contents, int position) {\r
+ if (filterProposals) {\r
+ ArrayList list = new ArrayList();\r
+ if (compareRVI) {\r
+ for (ChartVariable proposal : proposals) {\r
+ if (proposal.getRvi().length() >= contents.length() && proposal.getRvi().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
+ if (proposal.getLabel() != null)\r
+ list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
+ else\r
+ list.add(new ContentProposal(proposal.getRvi()));\r
+ } else if (proposal.getLabel() != null && proposal.getLabel().length() >= contents.length() && proposal.getLabel().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
+ list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
+ }\r
+ }\r
+ } else {\r
+ for (ChartVariable proposal : proposals) {\r
+ if (proposal.getLabel() != null && proposal.getLabel().length() >= contents.length() && proposal.getLabel().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
+ list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
+ }\r
+ }\r
+ }\r
+ \r
+ return (IContentProposal[]) list.toArray(new IContentProposal[list\r
+ .size()]);\r
+ }\r
+ if (contentProposals == null) {\r
+ contentProposals = new IContentProposal[proposals.size()];\r
+ Iterator<ChartVariable> iter = proposals.iterator();\r
+ for (int i = 0; i < proposals.size(); i++) {\r
+ ChartVariable proposal = iter.next();\r
+ if (proposal.getLabel() != null)\r
+ contentProposals[i] = new ContentProposal(proposal.getRvi(),proposal.getLabel(),null);\r
+ else\r
+ contentProposals[i] = new ContentProposal(proposal.getRvi());\r
+ }\r
+ }\r
+ return contentProposals;\r
+ }\r
+\r
+ /**\r
+ * Set the Strings to be used as content proposals.\r
+ * \r
+ * @param items\r
+ * the array of Strings to be used as proposals.\r
+ */\r
+ public void setProposals(Collection<ChartVariable> items) {\r
+ this.proposals = items;\r
+ contentProposals = null;\r
+ }\r
+\r
+ /**\r
+ * Set the boolean that controls whether proposals are filtered according to\r
+ * the current field content.\r
+ * \r
+ * @param filterProposals\r
+ * <code>true</code> if the proposals should be filtered to\r
+ * show only those that match the current contents of the field,\r
+ * and <code>false</code> if the proposals should remain the\r
+ * same, ignoring the field content.\r
+ * @since 3.3\r
+ */\r
+ public void setFiltering(boolean filterProposals) {\r
+ this.filterProposals = filterProposals;\r
+ // Clear any cached proposals.\r
+ contentProposals = null;\r
+ }\r
+ \r
/**\r
* Provides all variables a model contains. Given resource needs to be\r
* part of a model (i.e. using PartOf leads eventually to a SysdynModel).\r
* @param resource A resource that is part of a model\r
*/\r
public VariableProposalProvider(final Control control, WidgetSupport support) {\r
- super(new ArrayList<ChartVariable>());// super(String [] {});\r
+ this.proposals = new ArrayList<ChartVariable>();\r
support.register(this);\r
this.control = control;\r
}\r
import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
import org.simantics.db.management.ISessionContext;\r
import org.simantics.jfreechart.chart.properties.ChartVariable;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableFactory;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableModifier;\r
import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\r
-import org.simantics.jfreechart.chart.properties.RVIFactory;\r
-import org.simantics.jfreechart.chart.properties.RVIModifier;\r
import org.simantics.jfreechart.chart.properties.RangeComposite;\r
-import org.simantics.jfreechart.chart.properties.VariableExistsValidator;\r
-import org.simantics.jfreechart.chart.properties.VariableFactory;\r
-import org.simantics.jfreechart.chart.properties.VariableModifier;\r
+import org.simantics.jfreechart.chart.properties.StringChooser;\r
import org.simantics.layer0.Layer0;\r
import org.simantics.modeling.ui.chart.property.DoublePropertyFactory;\r
import org.simantics.modeling.ui.chart.property.DoublePropertyModifier;\r
import org.simantics.sysdyn.JFreeChartResource;\r
-import org.simantics.utils.datastructures.BijectionMap;\r
-import org.simantics.utils.datastructures.Pair;\r
\r
/**\r
* Composite for modifying properties of a series in a bar chart\r
*/\r
public class BarSeriesPropertyComposite2 extends Composite {\r
\r
- private TrackedText variable, label, time;\r
+ private TrackedText label, time;\r
+ private StringChooser<ChartVariable> variable;\r
\r
public BarSeriesPropertyComposite2(Composite parent, final ISessionContext context, WidgetSupport support, Collection<ChartVariable> variables, int style) {\r
super(parent, style);\r
label.setText("Variable:");\r
GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
\r
- variable = new TrackedText(this, support, SWT.BORDER);\r
- \r
- // FIXME: using bijectionmap and trackedText looses the variables that have the same label.\r
- BijectionMap<String , String> map = new BijectionMap<String, String>();\r
- for (ChartVariable variable : variables) {\r
- map.map(variable.getRvi(), variable.toString());\r
- }\r
- variable.setTextFactory(new VariableFactory(map));\r
- variable.addModifyListener(new VariableModifier(variable.getWidget(), support));\r
- variable.setInputValidator(new VariableExistsValidator(support, variable, false, true));\r
+// variable = new TrackedText(this, support, SWT.BORDER);\r
+// \r
+// // FIXME: using bijectionmap and trackedText looses the variables that have the same label.\r
+// BijectionMap<String , String> map = new BijectionMap<String, String>();\r
+// for (ChartVariable variable : variables) {\r
+// map.map(variable.getRvi(), variable.toString());\r
+// }\r
+// variable.setTextFactory(new VariableFactory(map));\r
+// variable.addModifyListener(new VariableModifier(variable.getWidget(), support));\r
+// variable.setInputValidator(new VariableExistsValidator(support, variable, false, true));\r
\r
+\r
+ variable = new StringChooser<ChartVariable>(this, support, SWT.BORDER);\r
+ variable.setData(variables);\r
+ variable.setObjectFactory(new ChartVariableFactory(variables));\r
+ variable.addModifyListener(new ChartVariableModifier(variable.getWidget(), support));\r
+ \r
variable.setColorProvider(new JFreeChartPropertyColorProvider(this.variable.getResourceManager()));\r
GridDataFactory.fillDefaults().grab(true, false).applyTo(this.variable.getWidget());\r
\r
import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\r
import org.simantics.jfreechart.chart.properties.ChartVariable;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableFactory;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableModifier;\r
import org.simantics.jfreechart.chart.properties.ColorPicker;\r
import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\r
-import org.simantics.jfreechart.chart.properties.RVIFactory;\r
-import org.simantics.jfreechart.chart.properties.RVIModifier;\r
import org.simantics.jfreechart.chart.properties.RangeComposite;\r
-import org.simantics.jfreechart.chart.properties.VariableExistsValidator;\r
-import org.simantics.jfreechart.chart.properties.VariableFactory;\r
-import org.simantics.jfreechart.chart.properties.VariableModifier;\r
+import org.simantics.jfreechart.chart.properties.StringChooser;\r
import org.simantics.layer0.Layer0;\r
import org.simantics.modeling.ui.chart.property.DoublePropertyFactory;\r
import org.simantics.modeling.ui.chart.property.DoublePropertyModifier;\r
import org.simantics.sysdyn.JFreeChartResource;\r
-import org.simantics.utils.datastructures.BijectionMap;\r
-import org.simantics.utils.datastructures.Pair;\r
\r
/**\r
* Composite containing the properties of a series\r
*/\r
public class PieSeriesPropertyComposite2 extends Composite {\r
\r
- private TrackedText variable, label, time;\r
+ private TrackedText label, time;\r
+ private StringChooser<ChartVariable> variable;\r
\r
public PieSeriesPropertyComposite2(Composite parent, ISessionContext context, WidgetSupport support, Collection<ChartVariable> variables,int style) {\r
super(parent, style);\r
label.setText("Variable:");\r
GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
\r
- variable = new TrackedText(this, support, SWT.BORDER);\r
- BijectionMap<String , String> map = new BijectionMap<String, String>();\r
- for (ChartVariable variable : variables) {\r
- map.map(variable.getRvi(), variable.toString());\r
- }\r
- variable.setTextFactory(new VariableFactory(map));\r
- variable.addModifyListener(new VariableModifier(variable.getWidget(), support));\r
- variable.setInputValidator(new VariableExistsValidator(support, variable, false, true));\r
+ \r
+ variable = new StringChooser<ChartVariable>(this, support, SWT.BORDER);\r
+ variable.setData(variables);\r
+ variable.setObjectFactory(new ChartVariableFactory(variables));\r
+ variable.addModifyListener(new ChartVariableModifier(variable.getWidget(), support));\r
\r
variable.setColorProvider(new JFreeChartPropertyColorProvider(this.variable.getResourceManager()));\r
GridDataFactory.fillDefaults().grab(true, false).applyTo(this.variable.getWidget());\r