--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.jfreechart</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Jfreechart
+Bundle-SymbolicName: org.simantics.jfreechart;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.jfreechart.internal.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.jfree.jchart;bundle-version="1.0.13",
+ org.jfree.jcommon;bundle-version="1.0.16",
+ org.simantics.jfreechart.ontology;bundle-version="1.0.0",
+ org.simantics.db;bundle-version="1.1.0",
+ org.simantics.db.layer0;bundle-version="1.1.0",
+ org.simantics.layer0;bundle-version="1.1.0",
+ org.simantics.diagram;bundle-version="1.1.1",
+ org.simantics.diagram.ontology;bundle-version="2.2.0",
+ org.simantics.modeling;bundle-version="1.1.1",
+ org.simantics.ui;bundle-version="1.0.0",
+ org.simantics.browsing.ui.common;bundle-version="1.1.0",
+ org.simantics.browsing.ui.ontology;bundle-version="1.1.0",
+ org.simantics.browsing.ui.swt;bundle-version="1.1.0",
+ org.simantics.modeling.ui;bundle-version="1.1.1",
+ org.simantics.layer0.utils;bundle-version="1.1.0",
+ org.simantics.scenegraph.swing;bundle-version="1.0.0",
+ org.simantics.browsing.ui.model;bundle-version="1.0.0",
+ org.simantics.selectionview;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.jfreechart,
+ org.simantics.jfreechart.chart,
+ org.simantics.jfreechart.chart.element,
+ org.simantics.jfreechart.chart.ge,
+ org.simantics.jfreechart.chart.properties,
+ org.simantics.jfreechart.chart.properties.bar,
+ org.simantics.jfreechart.chart.properties.pie,
+ org.simantics.jfreechart.chart.properties.xyline
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+ Copyright (c) 2010 Association for Decentralized Information Management in\r
+ 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
+\r
+<adapters>\r
+ <target interface="org.simantics.browsing.ui.model.children.ChildRule">\r
+ \r
+ \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/ChartAxisAndVariablesBrowseContext/AxisChildRule"\r
+ class="org.simantics.jfreechart.chart.ge.AxisChildRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/ChartAxisAndVariablesBrowseContext/VariableChildRule"\r
+ class="org.simantics.jfreechart.chart.ge.VariableChildRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/BarSeriesBrowseContext/SeriesChildRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesChildRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/PieSeriesBrowseContext/SeriesChildRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesChildRule"/> \r
+ \r
+ </target>\r
+ <target interface="org.simantics.browsing.ui.model.visuals.VisualsRule">\r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/ChartAxisAndVariablesBrowseContext/SeriesLabelRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesLabelRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/ChartAxisAndVariablesBrowseContext/AxisLabelRule"\r
+ class="org.simantics.jfreechart.chart.ge.AxisLabelRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/BarSeriesBrowseContext/SeriesLabelRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesLabelRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/PieSeriesBrowseContext/SeriesLabelRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesLabelRule"/> \r
+ \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/ChartAxisAndVariablesBrowseContext/SeriesLabelDecorationRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesLabelDecorationRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/BarSeriesBrowseContext/SeriesLabelDecorationRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesLabelDecorationRule"/> \r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/PieSeriesBrowseContext/SeriesLabelDecorationRule"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesLabelDecorationRule"/> \r
+ </target> \r
+ \r
+ <target interface="org.simantics.db.layer0.adapter.DropActionFactory"> \r
+ \r
+ <resource\r
+ uri="http://www.simantics.org/JFreeChart-0.0/ChartAxisAndVariablesActionContext/Actions/SeriesDropAction"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesDropAction" />\r
+ <resource\r
+ uri="http://www.simantics.org/JFreeChart-0.0/ChartAxisAndVariablesActionContext/Actions/AxisDropAction"\r
+ class="org.simantics.jfreechart.chart.ge.AxisDropAction" /> \r
+ \r
+ <resource\r
+ uri="http://www.simantics.org/JFreeChart-0.0/BarSeriesActionContext/Actions/SeriesDropAction"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesDropAction" />\r
+ <resource\r
+ uri="http://www.simantics.org/JFreeChart-0.0/PieSeriesActionContext/Actions/SeriesDropAction"\r
+ class="org.simantics.jfreechart.chart.ge.SeriesDropAction" /> \r
+ </target> \r
+ \r
+ <!-- Charts -->\r
+ <target interface="org.simantics.diagram.adapter.ElementFactory">\r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/ChartElement"\r
+ class="org.simantics.jfreechart.chart.element.ChartElementFactory" />\r
+ \r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/ChartElement"\r
+ class="org.simantics.jfreechart.chart.element.ChartElementFactory" />\r
+ </target>\r
+ \r
+ <target interface="org.simantics.diagram.synchronization.graph.ElementWriter">\r
+ <resource uri="http://www.simantics.org/JFreeChart-0.0/ChartElement"\r
+ class="org.simantics.jfreechart.chart.element.ChartElementWriter" />\r
+ </target>\r
+ \r
+ <target interface="org.simantics.jfreechart.chart.IJFreeChart">\r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/Chart"\r
+ class="org.simantics.jfreechart.chart.JFreeChart">\r
+ <graph />\r
+ <this />\r
+ </type>\r
+ </target> \r
+ \r
+ \r
+ \r
+ <target interface="org.simantics.jfreechart.chart.ITitle">\r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/TextTitle"\r
+ class="org.simantics.jfreechart.chart.TextTitle">\r
+ <graph />\r
+ <this />\r
+ </type>\r
+ </target>\r
+ \r
+ <target interface="org.simantics.jfreechart.chart.IAxis">\r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/NumberAxis"\r
+ class="org.simantics.jfreechart.chart.NumberAxis">\r
+ <graph />\r
+ <this />\r
+ </type>\r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/CategoryAxis"\r
+ class="org.simantics.jfreechart.chart.CategoryAxis">\r
+ <graph />\r
+ <this />\r
+ </type> \r
+ </target>\r
+ \r
+ <target interface="org.simantics.jfreechart.chart.IPlot">\r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/XYPlot"\r
+ class="org.simantics.jfreechart.chart.XYPlot">\r
+ <graph />\r
+ <this />\r
+ </type>\r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/CategoryPlot"\r
+ class="org.simantics.jfreechart.chart.CategoryPlot">\r
+ <graph />\r
+ <this />\r
+ </type> \r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/PiePlot"\r
+ class="org.simantics.jfreechart.chart.PiePlot">\r
+ <graph />\r
+ <this />\r
+ </type> \r
+ </target>\r
+ \r
+ <target interface="org.simantics.jfreechart.chart.IRenderer">\r
+ \r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/XYLineRenderer"\r
+ class="org.simantics.jfreechart.chart.XYLineRenderer">\r
+ <graph />\r
+ <this />\r
+ </type> \r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/XYAreaRenderer"\r
+ class="org.simantics.jfreechart.chart.XYAreaRenderer">\r
+ <graph />\r
+ <this />\r
+ </type> \r
+ \r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/BarRenderer"\r
+ class="org.simantics.jfreechart.chart.BarRenderer">\r
+ <graph />\r
+ <this />\r
+ </type>\r
+ <type uri="http://www.simantics.org/JFreeChart-0.0/StackedBarRenderer"\r
+ class="org.simantics.jfreechart.chart.StackedBarRenderer">\r
+ <graph />\r
+ <this />\r
+ </type> \r
+ </target> \r
+</adapters>
\ No newline at end of file
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ plugin.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?eclipse version="3.4"?>\r
+<plugin>\r
+ <extension\r
+ point="org.eclipse.ui.views">\r
+ <view\r
+ category="org.simantics.sysdyn.ui.category"\r
+ class="org.simantics.jfreechart.ChartPanel"\r
+ icon="platform:/plugin/com.famfamfam.silk/icons/chart_line.png"\r
+ id="org.simantics.jfreechart.chartPanel"\r
+ name="Chart Panel"\r
+ restorable="true">\r
+ </view>\r
+ </extension>\r
+\r
+</plugin>\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart;\r
+\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DropTargetAdapter;\r
+import org.eclipse.swt.dnd.DropTargetEvent;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.simantics.db.Resource;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Drop target for dropping charts in chart panel\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartDropTarget extends DropTargetAdapter {\r
+ \r
+ private Composite separator;\r
+ private ChartPanelElement element;\r
+ private Display display;\r
+ private ChartPanel panel;\r
+ \r
+ public ChartDropTarget(Composite separator, ChartPanelElement element, ChartPanel panel) {\r
+ this.separator = separator;\r
+ this.display = separator.getDisplay();\r
+ this.element = element;\r
+ this.panel = panel;\r
+ }\r
+ \r
+\r
+\r
+ /**\r
+ * Display effect on the composite when drag entered\r
+ */\r
+ @Override\r
+ public void dragEnter(DropTargetEvent event) {\r
+ if ((event.operations & DND.DROP_COPY) != 0) {\r
+ event.detail = DND.DROP_COPY;\r
+ } else if ((event.operations & DND.DROP_MOVE) != 0) {\r
+ event.detail = DND.DROP_MOVE;\r
+ } else {\r
+ event.detail = DND.DROP_NONE;\r
+ }\r
+ separator.setBackground(display.getSystemColor(SWT.COLOR_DARK_GRAY));\r
+ }\r
+\r
+ /**\r
+ * Revert effect when drag leaves\r
+ */\r
+ @Override\r
+ public void dragLeave(DropTargetEvent event) { \r
+ separator.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));\r
+ }\r
+\r
+ /**\r
+ * Drop the data to chart panel\r
+ */\r
+ @Override\r
+ public void drop(DropTargetEvent event) {\r
+ Resource chartResource = AdaptionUtils.adaptToSingle(event.data, Resource.class);\r
+ if(chartResource != null)\r
+ panel.addChart(chartResource, element);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart;\r
+\r
+import java.util.ArrayList;\r
+import java.util.LinkedHashMap;\r
+\r
+import org.eclipse.jface.dialogs.IDialogSettings;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DropTarget;\r
+import org.eclipse.swt.dnd.DropTargetAdapter;\r
+import org.eclipse.swt.dnd.DropTargetEvent;\r
+import org.eclipse.swt.dnd.Transfer;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.graphics.Rectangle;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.ui.IMemento;\r
+import org.eclipse.ui.IViewSite;\r
+import org.eclipse.ui.PartInitException;\r
+import org.eclipse.ui.part.ViewPart;\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.AsyncListener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.jfreechart.internal.Activator;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.utils.RunnableWithObject;\r
+\r
+/**\r
+ * Chart panel displays multiple charts in a single view. The view can be oriented \r
+ * vertically or horizontally, the default is vertical. Charts can be added, removed \r
+ * minimized or expanded. The order of the charts can be changed by dragging the charts.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartPanel extends ViewPart {\r
+\r
+ private Composite body;\r
+ private ScrolledComposite sc;\r
+\r
+ private IDialogSettings settings;\r
+ private LinkedHashMap<Resource, ChartPanelElement> charts;\r
+ private ArrayList<Resource> minimizedResources;\r
+\r
+ private ArrayList<ChartPanelElement> chartElements;\r
+\r
+ public static final String CHART_PANEL_SETTINGS = "CHART_PANEL_SETTINGS";\r
+ public static final String CHARTS = "CHART_PANEL_CHARTS";\r
+ public static final String MINIMIZED_CHARTS = "CHART_PANEL_MINIMIZED_CHARTS";\r
+ public static final String CHART_PANEL_ORIENTATION = "CHART_PANEL_ORIENTATION";\r
+\r
+ public static final String CHART_PANEL_VERTICAL = "CHART_PANEL_ORIENTATION_VERTICAL";\r
+ public static final String CHART_PANEL_HORIZONTAL = "CHART_PANEL_ORIENTATION_HORIZONTAL";\r
+\r
+ private boolean vertical = true;\r
+\r
+ /**\r
+ * Initialize the view. Load charts that have previously been open (if there are any).\r
+ */\r
+ @Override\r
+ public void init(IViewSite site, IMemento memento) throws PartInitException {\r
+ super.init(site, memento);\r
+\r
+ minimizedResources = new ArrayList<Resource>();\r
+\r
+ settings = Activator.getDefault().getDialogSettings().getSection(CHART_PANEL_SETTINGS);\r
+\r
+ // Initialize settings if there are no settings\r
+ if (settings == null) {\r
+ settings = Activator.getDefault().getDialogSettings().addNewSection(CHART_PANEL_SETTINGS);\r
+ }\r
+\r
+ if(settings.getArray(CHARTS) == null) {\r
+ String[] chartUris = new String[] {};\r
+ settings.put(CHARTS, chartUris);\r
+ }\r
+\r
+ if(settings.getArray(MINIMIZED_CHARTS) == null) {\r
+ String[] minimizedChartUris = new String[] {};\r
+ settings.put(MINIMIZED_CHARTS, minimizedChartUris);\r
+ }\r
+\r
+ // initialize chart lists\r
+ charts = new LinkedHashMap<Resource, ChartPanelElement>();\r
+\r
+ // add chart resources to chart lists from settings\r
+ try {\r
+ SimanticsUI.getSession().syncRequest(new ReadRequest() {\r
+\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Resource chart = null;\r
+ String[] chartURIs = settings.getArray(CHARTS);\r
+ for(String uri : chartURIs) {\r
+ chart = graph.getPossibleResource(uri);\r
+ if(chart != null && graph.isInstanceOf(chart, jfree.Chart)) {\r
+ charts.put(chart, null);\r
+ setChartExistingListener(chart);\r
+ }\r
+ }\r
+\r
+ String[] minimizedUris = settings.getArray(MINIMIZED_CHARTS);\r
+ for(String uri : minimizedUris) {\r
+ chart = graph.getPossibleResource(uri);\r
+ if(chart != null && graph.isInstanceOf(chart, jfree.Chart)) {\r
+ minimizedResources.add(chart);\r
+ } \r
+ }\r
+ }\r
+ });\r
+ } catch (DatabaseException e1) {\r
+ e1.printStackTrace();\r
+ }\r
+\r
+ // set the orientation of the panel\r
+ String orientation = settings.get(CHART_PANEL_ORIENTATION);\r
+ if(CHART_PANEL_VERTICAL.equals(orientation))\r
+ this.vertical = true;\r
+ else if(CHART_PANEL_HORIZONTAL.equals(orientation))\r
+ this.vertical = false;\r
+\r
+ }\r
+\r
+ /**\r
+ * Create a scrolled composite that will contain all the charts, then call the actual \r
+ * content creator.\r
+ */\r
+ @Override\r
+ public void createPartControl(Composite parent) {\r
+ sc = new ScrolledComposite(parent, SWT.NONE | SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(sc);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+ sc.setExpandHorizontal(true);\r
+ sc.setExpandVertical(true);\r
+ sc.getVerticalBar().setIncrement(sc.getVerticalBar().getIncrement()*3);\r
+ sc.getHorizontalBar().setIncrement(sc.getHorizontalBar().getIncrement()*3);\r
+\r
+ body = new Composite(sc, SWT.NONE);\r
+ GridLayoutFactory.fillDefaults().margins(3, 0).spacing(0, 0).applyTo(body);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(body);\r
+\r
+ sc.setContent(body);\r
+ createContents();\r
+ \r
+ setupDropTarget();\r
+\r
+ }\r
+ \r
+ /**\r
+ * Creates the contents of this chart panel.\r
+ * Removes all old contents before creating new content\r
+ */\r
+ private void createContents() {\r
+ chartElements = new ArrayList<ChartPanelElement>();\r
+\r
+ for(Control child : body.getChildren()) {\r
+ child.dispose();\r
+ }\r
+ \r
+ // Set the initial layout\r
+ ElementContainer elementHolder;\r
+ for(Resource e : charts.keySet()) {\r
+ elementHolder = new ElementContainer(body, SWT.NONE);\r
+ elementHolder.setBackground(new Color(elementHolder.getDisplay(), 255, 0, 0));\r
+ ChartPanelElement element = new ChartPanelElement(elementHolder, this, e, SWT.NONE);\r
+ elementHolder.setLayout(GridLayoutFactory.copyLayout((GridLayout)element.getLayout()));\r
+ chartElements.add(element);\r
+ charts.put(e, element);\r
+ if(minimizedResources.contains(e)) {\r
+ element.toggleMinimize();\r
+ }\r
+ }\r
+\r
+ elementHolder = new ElementContainer(body, SWT.NONE);\r
+ elementHolder.setBackground(new Color(elementHolder.getDisplay(), 0, 255, 0));\r
+ ChartPanelElement element = new ChartPanelElement(elementHolder, this, null, SWT.NONE); // Last element is empty -> only the separator\r
+ elementHolder.setLayout(GridLayoutFactory.copyLayout((GridLayout)element.getLayout()));\r
+ chartElements.add(element);\r
+\r
+ layout();\r
+ saveState();\r
+\r
+ }\r
+\r
+ /**\r
+ * Lays out this panel (the body composite)\r
+ */\r
+ public void layout() {\r
+ if(vertical) {\r
+ GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(body);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(body);\r
+ } else {\r
+ // Need to calculate horizontal elements for gridLayout\r
+ int chartPanels = chartElements.size();\r
+ GridLayoutFactory.fillDefaults().spacing(0, 0).numColumns(chartPanels).applyTo(body);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(body);\r
+ }\r
+ body.layout();\r
+ sc.setMinSize(body.computeSize(SWT.DEFAULT, SWT.DEFAULT));\r
+ }\r
+\r
+ @Override\r
+ public void setFocus() {\r
+ if(!sc.isDisposed())\r
+ sc.setFocus();\r
+ }\r
+\r
+ @Override\r
+ public void saveState(IMemento memento) {\r
+ super.saveState(memento);\r
+ saveState();\r
+ }\r
+\r
+ /**\r
+ * Save the current state of the view to IDialogSettings \r
+ */\r
+ public void saveState() {\r
+ try {\r
+ SimanticsUI.getSession().syncRequest(new ReadRequest() {\r
+\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ if (settings != null) {\r
+ String[] uris = new String[chartElements.size() - 1];\r
+ ArrayList<String> minimized = new ArrayList<String>();\r
+ minimizedResources.clear();\r
+ for(int i = 0; i < uris.length; i++) {\r
+ ChartPanelElement e = chartElements.get(i);\r
+ Resource r = e.getResource();\r
+ if(r != null) {\r
+ uris[i] = graph.getURI(r);\r
+ if(e.isMinimized()) {\r
+ minimized.add(uris[i]);\r
+ minimizedResources.add(r);\r
+ }\r
+ } else {\r
+ uris[i] = "";\r
+ }\r
+ }\r
+ settings.put(CHARTS, uris);\r
+ if(!minimized.isEmpty())\r
+ settings.put(MINIMIZED_CHARTS, minimized.toArray(new String[minimized.size()]));\r
+ else\r
+ settings.put(MINIMIZED_CHARTS, new String[0]);\r
+\r
+ if(vertical)\r
+ settings.put(CHART_PANEL_ORIENTATION, CHART_PANEL_VERTICAL);\r
+ else\r
+ settings.put(CHART_PANEL_ORIENTATION, CHART_PANEL_HORIZONTAL);\r
+ }\r
+ }\r
+ });\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set the orientation for this chart panel.\r
+ * \r
+ * @param orientation Orientation (ChartPanel.CHART_PANEL_VERTICAL or ChartPanel.CHART_PANEL_HORIZONTAL)\r
+ */\r
+ public void setOrientation(String orientation) {\r
+ if(CHART_PANEL_VERTICAL.equals(orientation))\r
+ this.vertical = true;\r
+ else {\r
+ this.vertical = false;\r
+ }\r
+ createContents();\r
+ }\r
+\r
+ /**\r
+ * Removes a chart from this panel\r
+ * \r
+ * @param chart The chart to be removed\r
+ */\r
+ public void removeChart(Resource chart) {\r
+ ChartPanelElement element = charts.get(chart);\r
+ chartElements.remove(element);\r
+ element.getParent().dispose();\r
+ charts.remove(chart);\r
+ minimizedResources.remove(chart);\r
+ saveState();\r
+ layout();\r
+ }\r
+\r
+ /**\r
+ * Sets up drag-scrolling for a scrolled composite \r
+ * \r
+ * @param control\r
+ */\r
+ protected void setupDropTarget() {\r
+ DropTarget target = new DropTarget(sc, DND.DROP_MOVE);\r
+ target.setTransfer(new Transfer[] { LocalObjectTransfer.getTransfer() });\r
+\r
+ target.addDropListener(new DropTargetAdapter() {\r
+\r
+ private int activeMargin = 20;\r
+ private int moveAmount = 1;\r
+\r
+ @Override\r
+ public void dragOver(DropTargetEvent event) { \r
+ Point original = sc.getOrigin();\r
+ Point origin = sc.getOrigin();\r
+ Point pointer = sc.toControl(event.x, event.y);\r
+ Rectangle bounds = sc.getBounds();\r
+\r
+ if(pointer.y < activeMargin)\r
+ origin.y = origin.y - moveAmount;\r
+ else if(bounds.height - pointer.y < activeMargin)\r
+ origin.y = origin.y + moveAmount;\r
+ if(pointer.x < activeMargin)\r
+ origin.x = origin.x - moveAmount;\r
+ else if(bounds.width - pointer.x < activeMargin)\r
+ origin.x = origin.x + moveAmount;\r
+\r
+ if(origin != original) {\r
+ sc.setOrigin (origin.x, origin.y);\r
+ sc.redraw();\r
+ }\r
+ }\r
+\r
+ });\r
+ \r
+ DropTarget target2 = new DropTarget(body, DND.DROP_COPY | DND.DROP_MOVE);\r
+ target2.setTransfer(new Transfer[] { LocalObjectTransfer.getTransfer() });\r
+ target2.addDropListener(new ChartDropTarget(body, null, this));\r
+\r
+ }\r
+\r
+ /**\r
+ * Is the panel vertically oriented\r
+ * @return Is the panel vertically oriented\r
+ */\r
+ public boolean isVertical() {\r
+ return vertical;\r
+ }\r
+ \r
+ /**\r
+ * Adds chart after given element. If element == null, adds chart to the top.\r
+ * \r
+ * @param element To which place the chart will be placed. (null allowed)\r
+ */\r
+ public void addChart(Resource chartResource, ChartPanelElement element) {\r
+ addChart(chartResource, element, true);\r
+ }\r
+\r
+ /**\r
+ * Adds chart after given element. If element == null, adds chart to the top.\r
+ * \r
+ * @param element To which place the chart will be placed. (null allowed)\r
+ * @param layout refresh layout. use with vertical layout. \r
+ */\r
+ public void addChart(Resource chartResource, ChartPanelElement element, boolean layout) {\r
+ if(element == null)\r
+ element = chartElements.get(chartElements.size() - 1);\r
+ int index = chartElements.indexOf(element);\r
+ if(index >= 0) {\r
+ ChartPanelElement e = chartElements.get(index);\r
+ ChartPanelElement newElement;\r
+\r
+ if(charts.containsKey(chartResource)) {\r
+ // Old element being moved to a new place\r
+ newElement = charts.get(chartResource);\r
+ int oldIndex = chartElements.indexOf(newElement);\r
+ if(newElement.equals(element) || oldIndex == index - 1)\r
+ return; // Not moving anywhere, do nothing\r
+ Composite oldParent = newElement.getParent();\r
+ newElement.setParent(e.getParent());\r
+ oldParent.dispose();\r
+ if(oldIndex < index)\r
+ index--;\r
+ chartElements.remove(newElement);\r
+ } else {\r
+ newElement = new ChartPanelElement(e.getParent(), this, chartResource, SWT.NONE);\r
+ }\r
+\r
+ // Add a new chart element to the location of the old element\r
+ chartElements.add(index, newElement);\r
+ charts.put(chartResource, newElement);\r
+\r
+ ElementContainer elementHolder;\r
+ // Move elements back after index\r
+ for(int i = index + 1 /*indexes after the new element*/; i < chartElements.size(); i++) {\r
+ e = chartElements.get(i);\r
+ if(i == chartElements.size() - 1) {\r
+ // last element (the empty element) element to a new container\r
+ elementHolder = new ElementContainer(body, SWT.NONE);\r
+ elementHolder.setBackground(new Color(elementHolder.getDisplay(), 0, 0, 255));\r
+ elementHolder.setLayout(GridLayoutFactory.copyLayout((GridLayout)e.getLayout()));\r
+ e.setParent(elementHolder);\r
+ } else {\r
+ // element to the next elements container\r
+ elementHolder = (ElementContainer)chartElements.get(i + 1).getParent();\r
+ e.setParent(elementHolder);\r
+ }\r
+ }\r
+ \r
+ layout();\r
+ saveState();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set a listener to listen if the chart resource has been removed.\r
+ * If the resource has been removed, close also the chart element in this panel.\r
+ * \r
+ * @param chart Listened chart resource\r
+ */\r
+ private void setChartExistingListener(final Resource chart) {\r
+ SimanticsUI.getSession().asyncRequest(new Read<Boolean>() {\r
+\r
+ @Override\r
+ public Boolean perform(ReadGraph graph) throws DatabaseException {\r
+ return graph.hasStatement(chart);\r
+ }\r
+ }, new AsyncListener<Boolean>() {\r
+\r
+ boolean disposed = false;\r
+\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, Boolean result) {\r
+ if(result != null && result == false && body != null && !body.isDisposed()) {\r
+ body.getDisplay().asyncExec(new RunnableWithObject(chart){\r
+ public void run() {\r
+ removeChart((Resource)getObject());\r
+ }\r
+ }) ;\r
+ disposed = true;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+ throwable.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return !disposed && !charts.containsKey(chart);\r
+ }\r
+ });\r
+ }\r
+\r
+ public ArrayList<ChartPanelElement> getElements() {\r
+ return chartElements;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DropTarget;\r
+import org.eclipse.swt.dnd.Transfer;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Resource;\r
+import org.simantics.jfreechart.chart.ChartComposite;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+\r
+/**\r
+ * This class represents an expanded chart element in {@link ChartPanel}. It contains \r
+ * a header {@link ChartPanelHeader} and the actual chart.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartPanelElement extends Composite {\r
+\r
+ public static int CHART_MINIMUM_WIDTH = 300;\r
+ public static int CHART_MINIMUM_HEIGHT = 200;\r
+\r
+ private ChartPanel panel;\r
+ private ChartComposite chartComposite;\r
+ private Resource chartResource;\r
+ private boolean minimized = false;\r
+\r
+ public Resource getResource() {\r
+ return chartResource;\r
+ }\r
+\r
+ @Override\r
+ public Object getLayoutData () {\r
+ checkWidget();\r
+ Object oldData = super.getLayoutData();\r
+ if(oldData == null || !(oldData instanceof GridData)) {\r
+ oldData = GridDataFactory.fillDefaults().create();\r
+ }\r
+\r
+ int size = panel.getElements().size();\r
+ GridData data = (GridData) oldData;\r
+ // Horizontal data\r
+ data.widthHint = CHART_MINIMUM_WIDTH;\r
+ if(getResource() == null && size == 1) {\r
+ data.grabExcessHorizontalSpace = true;\r
+ } else if(getResource() == null && !panel.isVertical()){\r
+ data.grabExcessHorizontalSpace = false;\r
+ data.widthHint = SWT.DEFAULT;\r
+ } else if(minimized && !panel.isVertical()) {\r
+ data.grabExcessHorizontalSpace = false;\r
+ data.widthHint = SWT.DEFAULT;\r
+ } else {\r
+ data.grabExcessHorizontalSpace = true;\r
+ }\r
+\r
+ // Vertical data\r
+ if(getResource() == null && size == 1) {\r
+ data.grabExcessVerticalSpace = true;\r
+ } else if(!minimized && getResource() != null) {\r
+ data.grabExcessVerticalSpace = true;\r
+ data.heightHint = CHART_MINIMUM_HEIGHT;\r
+ } else if(!panel.isVertical()){\r
+ data.grabExcessVerticalSpace = true;\r
+ } else {\r
+ data.grabExcessVerticalSpace = false;\r
+ data.heightHint = SWT.DEFAULT;\r
+ }\r
+ return data;\r
+ }\r
+\r
+ /**\r
+ * Creates an expanded chart panel element into parent composite.\r
+ * \r
+ * @param parent The parent composite where the chart element is created\r
+ * @param panel The {@link ChartPanel} containing the chart element\r
+ * @param name The name of the chart\r
+ * @param style The Style of the created chart element\r
+ */\r
+ public ChartPanelElement(Composite parent, ChartPanel panel, Resource chartResource, int style) {\r
+ this(parent, panel, chartResource, false, style);\r
+ }\r
+\r
+ /**\r
+ * Creates a chart panel element into parent composite.\r
+ * @param parent The parent composite where the chart element is created\r
+ * @param panel The {@link ChartPanel} containing the chart element\r
+ * @param name The name of the chart\r
+ * @param minimized Is the chart-section minimized\r
+ * @param style The Style of the created chart element\r
+ */\r
+ public ChartPanelElement(Composite parent, ChartPanel panel, Resource chartResource, boolean minimized, int style) {\r
+ super(parent, style | SWT.NONE );\r
+ \r
+ this.panel = panel;\r
+ this.chartResource = chartResource;\r
+ this.minimized = minimized;\r
+\r
+ if(panel.isVertical() || getResource() == null)\r
+ GridLayoutFactory.fillDefaults().spacing(0,0).applyTo(this);\r
+ else\r
+ GridLayoutFactory.fillDefaults().numColumns(2).spacing(0,0).applyTo(this);\r
+\r
+ GridDataFactory.fillDefaults().applyTo(this);\r
+\r
+ // Separator for dropping other elements\r
+ ChartPanelSeparator separator = new ChartPanelSeparator(this, panel, this, SWT.NONE);\r
+\r
+ if (chartResource != null) {\r
+ Composite c = new Composite(this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(c);\r
+ GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(c);\r
+ // Header\r
+ new ChartPanelHeader(c, this, chartResource, SWT.BORDER);\r
+\r
+ // Chart\r
+ chartComposite = new ChartComposite(c, chartResource, SWT.BORDER);\r
+ }\r
+ \r
+ DropTarget target = new DropTarget(this, DND.DROP_COPY | DND.DROP_MOVE);\r
+ target.setTransfer(new Transfer[] { LocalObjectTransfer.getTransfer() });\r
+ target.addDropListener(new ChartDropTarget(separator, this, panel));\r
+\r
+ }\r
+\r
+ /**\r
+ * Returns the chart resource associated with this element\r
+ * @return chart resource\r
+ */\r
+ public Resource getChartResource() {\r
+ return this.chartResource;\r
+ }\r
+\r
+ /**\r
+ * Returns the minimized state of this element\r
+ * @return is the element minimized\r
+ */\r
+ public boolean isMinimized() {\r
+ return minimized;\r
+ }\r
+\r
+ /**\r
+ * Change the minimized state of this element\r
+ */\r
+ public void toggleMinimize() {\r
+ toggleMinimize(false);\r
+ }\r
+ /**\r
+ * Change the minimized state of this element\r
+ */\r
+ public void toggleMinimize(boolean callSave) {\r
+ minimized = Boolean.FALSE.equals(minimized);\r
+ GridData data = (GridData) chartComposite.getLayoutData();\r
+ if(panel.isVertical())\r
+ data.exclude = minimized;\r
+ else\r
+ data.exclude = false;\r
+ chartComposite.setVisible(!minimized);\r
+\r
+ Composite parent = getParent();\r
+ data = (GridData) getLayoutData();\r
+ GridData parentData = (GridData)parent.getLayoutData();\r
+ parentData.grabExcessHorizontalSpace = data.grabExcessHorizontalSpace;\r
+ parentData.grabExcessVerticalSpace = data.grabExcessVerticalSpace;\r
+ parentData.heightHint = data.heightHint;\r
+\r
+ if(callSave) {\r
+ panel.saveState();\r
+ }\r
+ panel.layout();\r
+ }\r
+\r
+ /**\r
+ * Remove this chart panel element from its panel\r
+ */\r
+ public void remove() {\r
+ panel.removeChart(chartResource);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DragSource;\r
+import org.eclipse.swt.dnd.DragSourceEvent;\r
+import org.eclipse.swt.dnd.DragSourceListener;\r
+import org.eclipse.swt.dnd.Transfer;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.events.PaintEvent;\r
+import org.eclipse.swt.events.PaintListener;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Canvas;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.ToolBar;\r
+import org.eclipse.swt.widgets.ToolItem;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.jfreechart.internal.Activator;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+/**\r
+ * Header of a chart element in {@link ChartPanel}. Only this header is\r
+ * shown if a chart is minimized. If a chart is expanded, this header is added\r
+ * to the charts {@link ChartPanelElement}. \r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartPanelHeader extends Composite {\r
+\r
+ public static int HEADER_MINIMUM_WIDTH = 250;\r
+ private ChartPanelElement element;\r
+ private Resource resource;\r
+ private Label name;\r
+ private Canvas iconCanvas;\r
+ private Image icon;\r
+ private ToolItem minimize, remove;\r
+ private Color defaultColor, darker, evenDarker;\r
+ private Image gradientBackgroundImage, borderImage;\r
+\r
+ private static ImageDescriptor closeDescriptor = ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/close.gif"));\r
+ private static Image closeImage = closeDescriptor.createImage();\r
+\r
+ private static ImageDescriptor minimizeDescriptor = ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/minimize.gif"));\r
+ private static Image minimizeImage = minimizeDescriptor.createImage();\r
+\r
+ private static ImageDescriptor maximizeDescriptor = ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/maximize.gif"));\r
+ private static Image maximizeImage = maximizeDescriptor.createImage();\r
+\r
+ private static ImageDescriptor lineChartDescriptor = ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/chart_line_light.png"));\r
+ private static Image lineChartImage = lineChartDescriptor.createImage();\r
+\r
+ private static ImageDescriptor barChartDescriptor = ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/chart_bar_light.png"));\r
+ private static Image barChartImage = barChartDescriptor.createImage();\r
+\r
+ private static ImageDescriptor pieChartDescriptor = ImageDescriptor.createFromURL(Activator.getDefault().getBundle().getResource("icons/chart_pie_light.png"));\r
+ private static Image pieChartImage = pieChartDescriptor.createImage();\r
+\r
+\r
+ /**\r
+ * Chart panel header with minimize and close buttons.\r
+ * \r
+ * @param parent The composite where the header is added\r
+ * @param panel The {@link ChartPanel} containing the header\r
+ * @param name The name of the chart\r
+ * @param style he Style of the created chart element\r
+ */\r
+ public ChartPanelHeader(Composite c, ChartPanelElement element, Resource chartResource, int style) {\r
+ super(c, style);\r
+ this.resource = chartResource;\r
+ this.element = element;\r
+\r
+ GridLayoutFactory.fillDefaults().margins(3, 0).numColumns(3).applyTo(this);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this);\r
+\r
+ // Colors\r
+\r
+ // Chart icon\r
+ iconCanvas = new Canvas (this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).hint(16, 16).applyTo(iconCanvas);\r
+ iconCanvas.addPaintListener (new PaintListener() {\r
+\r
+ @Override\r
+ public void paintControl(PaintEvent e) {\r
+ if(icon != null)\r
+ e.gc.drawImage (icon, 0, 0); \r
+ }\r
+ });\r
+\r
+ // Label for the chart name (also minimize/expand)\r
+ name = new Label(this, SWT.NONE);\r
+\r
+ try {\r
+ // name updater\r
+ Pair<String, Image> result = SimanticsUI.getSession().syncRequest(new Read<Pair<String, Image>>() {\r
+\r
+ @Override\r
+ public Pair<String, Image> perform(ReadGraph graph) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ String label = graph.getPossibleRelatedValue(resource, l0.HasLabel);\r
+ Image image = null;\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(resource, l0.ConsistsOf, jfree.Plot));\r
+ if(plot != null) {\r
+ if(graph.isInstanceOf(plot, jfree.CategoryPlot))\r
+ image = barChartImage;\r
+ else if(graph.isInstanceOf(plot, jfree.PiePlot))\r
+ image = pieChartImage;\r
+ else\r
+ image = lineChartImage;\r
+ }\r
+ return new Pair<String, Image>(label, image);\r
+ }\r
+\r
+ }, new Listener<Pair<String, Image>>() {\r
+\r
+ @Override\r
+ public void execute(final Pair<String, Image> result) {\r
+ if(result == null)\r
+ return;\r
+\r
+ name.getDisplay().asyncExec(new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+ if(!name.isDisposed() && result.first != null)\r
+ name.setText(result.first);\r
+\r
+ if(!iconCanvas.isDisposed() && result.second != null) {\r
+ icon = result.second;\r
+ iconCanvas.redraw();\r
+ ChartPanelHeader.this.layout();\r
+ }\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return name.isDisposed();\r
+ }\r
+\r
+ });\r
+ name.setText(result.first);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ name.setText("No label");\r
+ }\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(name);\r
+\r
+ ToolBar toolbar = new ToolBar(this, SWT.FLAT);\r
+ // item for minimizing/expanding chart\r
+ minimize = new ToolItem(toolbar, SWT.PUSH);\r
+ minimize.addSelectionListener(new MinimizeListener());\r
+ if(isMinimized()) {\r
+ minimize.setToolTipText("Expand");\r
+ minimize.setImage(maximizeImage);\r
+ } else {\r
+ minimize.setToolTipText("Minimize");\r
+ minimize.setImage(minimizeImage);\r
+ }\r
+\r
+ // item for closing/removing the chart\r
+ remove = new ToolItem(toolbar, SWT.PUSH);\r
+ remove.setImage(closeImage);\r
+ remove.addSelectionListener(new RemoveChartListener());\r
+ remove.setToolTipText("Remove");\r
+\r
+\r
+ /* ********************************\r
+ * DnD \r
+ * ********************************/\r
+\r
+ // Allow data to be copied or moved from the drag source\r
+ int operations = DND.DROP_MOVE;\r
+ source = new DragSource(name, operations);\r
+\r
+ // Provide data in Text format\r
+ Transfer[] types = new Transfer[] { LocalObjectTransfer.getTransfer() };\r
+ source.setTransfer(types);\r
+ dragSourceListener = new DragSourceListener() {\r
+\r
+ @Override\r
+ public void dragStart(DragSourceEvent event) {\r
+ if(name.isDisposed())\r
+ event.doit = false;\r
+ event.detail = DND.DROP_LINK;\r
+\r
+ }\r
+\r
+ @Override\r
+ public void dragSetData(DragSourceEvent event) {\r
+ event.data = new StructuredSelection(resource);\r
+ }\r
+\r
+ @Override\r
+ public void dragFinished(DragSourceEvent event) {\r
+ }\r
+ }; \r
+ source.addDragListener(dragSourceListener);\r
+\r
+ name.addDisposeListener(new DisposeListener() {\r
+\r
+ @Override\r
+ public void widgetDisposed(DisposeEvent e) {\r
+ if(dragSourceListener != null && source != null && !source.isDisposed()) {\r
+ source.removeDragListener(dragSourceListener);\r
+ } \r
+ }\r
+ });\r
+ this.setBackgroundImage(getGradientBackgroundImage());\r
+ this.setBackgroundMode(SWT.INHERIT_FORCE);\r
+\r
+ this.addListener(SWT.MouseEnter, new EnterListener());\r
+ this.addListener(SWT.MouseExit, new ExitListener());\r
+\r
+ for(Control child : this.getChildren()) {\r
+ child.addListener(SWT.MouseEnter, new EnterListener());\r
+ child.addListener(SWT.MouseExit, new ExitListener());\r
+\r
+ }\r
+ }\r
+\r
+ private class EnterListener implements org.eclipse.swt.widgets.Listener {\r
+ public void handleEvent(Event event) {\r
+ ChartPanelHeader.this.setBackgroundImage(getHighlightedGradientBackgroundImage());\r
+ }\r
+ }\r
+\r
+ private class ExitListener implements org.eclipse.swt.widgets.Listener {\r
+ public void handleEvent(Event event) {\r
+ ChartPanelHeader.this.setBackgroundImage(getGradientBackgroundImage());\r
+ }\r
+ }\r
+\r
+ private void createColors() {\r
+ if(defaultColor == null) {\r
+ defaultColor = getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);\r
+ try {\r
+ defaultColor = new Color(getDisplay(), defaultColor.getRed() + 500, defaultColor.getGreen() + 10, defaultColor.getBlue() + 10);\r
+ } catch (IllegalArgumentException e) {\r
+ // Do nothing, use the default color\r
+ }\r
+ }\r
+\r
+ if(darker == null) {\r
+ try {\r
+ darker = new Color(getDisplay(), defaultColor.getRed() - 30, defaultColor.getGreen() - 30, defaultColor.getBlue() - 30);\r
+ } catch (IllegalArgumentException e) {\r
+ // Do nothing, use the default color\r
+ darker = defaultColor;\r
+ }\r
+ }\r
+ \r
+ if(evenDarker == null) {\r
+ try {\r
+ evenDarker = new Color(getDisplay(), defaultColor.getRed() - 50, defaultColor.getGreen() - 50, defaultColor.getBlue() - 50);\r
+ } catch (IllegalArgumentException e) {\r
+ // Do nothing, use the default color\r
+ evenDarker = defaultColor;\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ private Image getHighlightedGradientBackgroundImage() {\r
+ createColors();\r
+ this.layout();\r
+ Point size = this.getSize();\r
+\r
+ borderImage = new Image(this.getDisplay(), 1, Math.max(1, size.y));\r
+ GC gc = new GC(borderImage);\r
+ gc.setForeground(defaultColor);\r
+ gc.setBackground(evenDarker);\r
+ gc.fillGradientRectangle(0, 0, 1, size.y, true);\r
+ gc.dispose();\r
+\r
+ return borderImage;\r
+ }\r
+\r
+ private Image getGradientBackgroundImage() {\r
+ createColors();\r
+ this.layout();\r
+ Point size = this.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ if(gradientBackgroundImage == null) {\r
+ gradientBackgroundImage = new Image(this.getDisplay(), 1, Math.max(1, size.y));\r
+ GC gc = new GC(gradientBackgroundImage);\r
+ gc.setForeground(defaultColor);\r
+ gc.setBackground(darker);\r
+ gc.fillGradientRectangle(0, 0, 1, size.y, true);\r
+ gc.dispose();\r
+ }\r
+\r
+ return gradientBackgroundImage;\r
+ }\r
+\r
+ private DragSourceListener dragSourceListener;\r
+ private DragSource source;\r
+\r
+ /**\r
+ * Return true if this element is minimized, false if expanded\r
+ * @return true if this element is minimized, false if expanded\r
+ */\r
+ private boolean isMinimized() {\r
+ return element.isMinimized();\r
+ }\r
+\r
+ /**\r
+ * Listener to minimize chart button. Expands and minimizes \r
+ * the chart of this header.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class MinimizeListener implements SelectionListener {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ if(ChartPanelHeader.this.isDisposed())\r
+ return;\r
+\r
+ element.toggleMinimize(true);\r
+\r
+ if(!name.isDisposed() && !minimize.isDisposed()) {\r
+ if(isMinimized()) {\r
+ minimize.setToolTipText("Expand");\r
+ } else {\r
+ minimize.setToolTipText("Minimize");\r
+ }\r
+ } \r
+ }\r
+\r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ widgetSelected(e);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Listener for removing this chart from the chart panel.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class RemoveChartListener implements SelectionListener {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ if(!ChartPanelHeader.this.isDisposed()) {\r
+ element.remove();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ widgetSelected(e);\r
+ }\r
+\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.events.MouseAdapter;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.widgets.Composite;\r
+\r
+/**\r
+ * Class for separating charts in {@link ChartPanel}. Acts as a drop participant for adding\r
+ * and moving charts in {@link ChartPanel}.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartPanelSeparator extends Composite {\r
+\r
+ private ChartPanel panel;\r
+\r
+ @Override\r
+ public Object getLayoutData() {\r
+ checkWidget();\r
+ Object oldData = super.getLayoutData();\r
+ if(oldData == null || !(oldData instanceof GridData)) {\r
+ oldData = GridDataFactory.fillDefaults().create();\r
+ }\r
+ GridData data = (GridData) oldData;\r
+ // Empty panel -> drop area the size of the whole panel\r
+ if(panel.getElements().size() == 1 && panel.getElements().get(0).getResource() == null) {\r
+ data.grabExcessHorizontalSpace = true;\r
+ data.grabExcessVerticalSpace = true;\r
+ }\r
+ else {\r
+ if(panel.isVertical()) { \r
+ data.grabExcessHorizontalSpace = true;\r
+ data.grabExcessVerticalSpace = false;\r
+ } else {\r
+ data.grabExcessHorizontalSpace = false;\r
+ data.grabExcessVerticalSpace = true;\r
+ }\r
+ }\r
+ return data;\r
+ }\r
+\r
+ /**\r
+ * Set up a small horizontal or vertical separator depending on SWT style\r
+ * \r
+ * @param parent\r
+ * @param style\r
+ */\r
+ public ChartPanelSeparator(Composite parent, ChartPanel panel, ChartPanelElement element, int style) {\r
+ super(parent, style);\r
+ GridLayoutFactory.fillDefaults().margins(2, 2).applyTo(this);\r
+ GridDataFactory.fillDefaults().applyTo(this);\r
+ this.panel = panel;\r
+ addMouseListener(new SCFocusListener(panel));\r
+ }\r
+\r
+\r
+ /**\r
+ * Listener for directing focus to scrollableComposite\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class SCFocusListener extends MouseAdapter {\r
+ ChartPanel panel;\r
+ public SCFocusListener(ChartPanel panel) {\r
+ this.panel = panel;\r
+ }\r
+ public void mouseDown(MouseEvent e) {\r
+ panel.setFocus();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart;\r
+\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+\r
+/**\r
+ * Container for a chart panel element. Needed for\r
+ * moving chart panel elements around using setParent()\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ElementContainer extends Composite {\r
+\r
+ @Override\r
+ public Object getLayoutData () {\r
+ Control[] children = getChildren();\r
+ if(children.length == 1) {\r
+ if(children[0] instanceof ChartPanelElement) {\r
+ ChartPanelElement element = (ChartPanelElement)children[0];\r
+ return element.getLayoutData();\r
+ }\r
+ }\r
+ return super.getLayoutData();\r
+ }\r
+ \r
+ public ElementContainer(Composite parent, int style) {\r
+ super(parent, style);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import java.awt.Color;\r
+\r
+import org.jfree.chart.axis.Axis;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.G2DUtils;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Abstract axis class for all JFreeChart axis\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public abstract class AbstractAxis implements IAxis {\r
+\r
+ protected Axis axis;\r
+ protected String label;\r
+ protected Boolean tMarksVisible, tLabelsVisible, labelVisible, lineVisible;\r
+ protected Color color;\r
+ protected Double min, max, rotate;\r
+\r
+ /**\r
+ * Creates a new axis\r
+ * @param graph ReadGraph\r
+ * @param axisResource resource of type JFreeChart.NumberAxis\r
+ */\r
+ public AbstractAxis(ReadGraph graph, Resource axisResource) {\r
+ try {\r
+ /*\r
+ * Axis is practically always called from a listener, \r
+ * so it is safe to always create a new axis every time. \r
+ * \r
+ * The parent listener takes care that the axis is updated. \r
+ * (And the code stays much more readable)\r
+ */\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ label = graph.getPossibleRelatedValue(axisResource, l0.HasLabel);\r
+ tMarksVisible = graph.getPossibleRelatedValue(axisResource, jfree.Axis_visibleTickMarks, Bindings.BOOLEAN);\r
+ tLabelsVisible = graph.getPossibleRelatedValue(axisResource, jfree.Axis_visibleTickLabels, Bindings.BOOLEAN);\r
+ labelVisible = graph.getPossibleRelatedValue(axisResource, jfree.Axis_visibleLabel, Bindings.BOOLEAN);\r
+ lineVisible = graph.getPossibleRelatedValue(axisResource, jfree.Axis_visibleAxisLine, Bindings.BOOLEAN);\r
+ Resource c = graph.getPossibleObject(axisResource, jfree.color);\r
+ color = c == null ? null : G2DUtils.getColor(graph, c);\r
+ min = graph.getPossibleRelatedValue(axisResource, jfree.Axis_min, Bindings.DOUBLE);\r
+ max = graph.getPossibleRelatedValue(axisResource, jfree.Axis_max, Bindings.DOUBLE);\r
+ rotate = graph.getPossibleRelatedValue(axisResource, jfree.Axis_rotateLabelDegrees, Bindings.DOUBLE);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ \r
+ }\r
+\r
+ @Override\r
+ public Axis getAxis() {\r
+ if(tMarksVisible != null && tMarksVisible == false)\r
+ axis.setTickMarksVisible(false);\r
+ if(tLabelsVisible != null && tLabelsVisible == false)\r
+ axis.setTickLabelsVisible(false);\r
+ if(lineVisible != null && lineVisible == false)\r
+ axis.setAxisLineVisible(false);\r
+ \r
+ if(color != null) {\r
+ axis.setAxisLinePaint(color);\r
+ axis.setLabelPaint(color);\r
+ axis.setTickLabelPaint(color);\r
+ axis.setTickMarkPaint(color);\r
+ }\r
+ // label exists and its visibility == null or true\r
+ if((labelVisible == null || labelVisible == true) && label != null)\r
+ axis.setLabel(label);\r
+ return axis;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+\r
+/**\r
+ * Abstract dataset class for all JFreeChart datasets\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public abstract class AbstractDataset implements IDataset {\r
+\r
+ protected Resource resource;\r
+ \r
+ public AbstractDataset(ReadGraph graph, Resource resource) {\r
+ this.resource = resource;\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ \r
+ }\r
+\r
+ @Override\r
+ public Resource getResource() {\r
+ return resource;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+\r
+import javax.swing.SwingUtilities;\r
+\r
+import org.jfree.chart.axis.Axis;\r
+import org.jfree.chart.plot.Plot;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+/**\r
+ * Abstract plot class for all JFreeChart plots\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public abstract class AbstractPlot implements IPlot {\r
+\r
+ protected Resource resource;\r
+ protected Plot plot;\r
+ protected PlotProperties currentProperties;\r
+ private PlotPropertyListener listener;\r
+\r
+\r
+ public AbstractPlot(ReadGraph graph, Resource resource) {\r
+ this.resource = resource;\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ if(currentProperties != null) {\r
+ for(IAxis axis : currentProperties.ranges)\r
+ axis.dispose();\r
+\r
+ for(IAxis axis : currentProperties.domains)\r
+ axis.dispose();\r
+\r
+ for(IDataset dataset : currentProperties.datasets)\r
+ dataset.dispose();\r
+ }\r
+ if(listener != null)\r
+ listener.dispose();\r
+ }\r
+\r
+ @Override\r
+ public Resource getResource() {\r
+ return resource;\r
+ }\r
+\r
+ protected abstract Plot newPlot();\r
+ protected abstract void setPlotProperties(PlotProperties properties);\r
+ protected abstract void getOtherProperties(ReadGraph graph, PlotProperties properties) throws DatabaseException;\r
+\r
+ @Override\r
+ public Plot getPlot() {\r
+ if(plot == null)\r
+ plot = newPlot();\r
+\r
+ if(listener == null || listener.isDisposed()) {\r
+ listener = new PlotPropertyListener();\r
+ SimanticsUI.getSession().asyncRequest(new Read<PlotProperties>() {\r
+\r
+ @Override\r
+ public PlotProperties perform(ReadGraph graph) throws DatabaseException {\r
+\r
+ PlotProperties properties = new PlotProperties();\r
+\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+\r
+ HashMap<Resource, IAxis> axisMap = new HashMap<Resource, IAxis>();\r
+\r
+ // Get all range axis\r
+ Resource rangeList = graph.getPossibleObject(resource, jfree.Plot_rangeAxisList);\r
+ if(rangeList != null) {\r
+ for(Resource axisResource : ListUtils.toList(graph, rangeList)) {\r
+ IAxis axis = graph.adapt(axisResource, IAxis.class);\r
+ if(axis.getAxis() instanceof Axis) {\r
+ properties.ranges.add(axis);\r
+ axisMap.put(axisResource, axis);\r
+ }\r
+ }\r
+ }\r
+\r
+ // Get all domain axis\r
+ // There usually is only one domain axis, but this supports also multiple domain axis\r
+ for(Resource axisResource : graph.syncRequest(new ObjectsWithType(resource, jfree.Plot_domainAxis, jfree.Axis))) {\r
+ IAxis axis = graph.adapt(axisResource, IAxis.class);\r
+ if(axis.getAxis() instanceof Axis) {\r
+ properties.domains.add(axis);\r
+ axisMap.put(axisResource, axis);\r
+ }\r
+ }\r
+\r
+ // Get all datasets and map them to axis\r
+ for(Resource datasetResource : graph.syncRequest(new ObjectsWithType(resource, l0.ConsistsOf, jfree.Dataset))) {\r
+ IDataset dataset = graph.adapt(datasetResource, IDataset.class);\r
+ if(dataset != null) {\r
+ properties.datasets.add(dataset);\r
+ Resource axisResource = graph.getPossibleObject(datasetResource, jfree.Dataset_mapToRangeAxis);\r
+ IAxis axis;\r
+ if(axisMap.containsKey(axisResource)) {\r
+ axis = axisMap.get(axisResource);\r
+ properties.rangeMappings.put(dataset, axis);\r
+ }\r
+\r
+ axisResource = graph.getPossibleObject(datasetResource, jfree.Dataset_mapToDomainAxis);\r
+ if(axisMap.containsKey(axisResource)) {\r
+ axis = axisMap.get(axisResource);\r
+ properties.domainMappings.put(dataset, axis);\r
+ }\r
+ }\r
+ }\r
+ getOtherProperties(graph, properties);\r
+ return properties;\r
+\r
+ }\r
+ }, listener);\r
+ }\r
+\r
+ return plot;\r
+ }\r
+\r
+ protected class PlotProperties {\r
+ public ArrayList<IAxis> ranges;\r
+ public ArrayList<IAxis> domains;\r
+ public ArrayList<IDataset> datasets;\r
+ public HashMap<IDataset, IAxis> rangeMappings;\r
+ public HashMap<IDataset, IAxis> domainMappings;\r
+ public HashMap<String, Object> otherProperties;\r
+ \r
+ public PlotProperties() {\r
+ datasets = new ArrayList<IDataset>();\r
+ rangeMappings = new HashMap<IDataset, IAxis>();\r
+ domainMappings = new HashMap<IDataset, IAxis>();\r
+ ranges = new ArrayList<IAxis>();\r
+ domains = new ArrayList<IAxis>();\r
+ otherProperties = new HashMap<String, Object>();\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object other) {\r
+ if(!this.getClass().equals(other.getClass()))\r
+ return false;\r
+ PlotProperties p = (PlotProperties)other;\r
+ if(!ranges.equals(p.ranges))\r
+ return false;\r
+ if(!domains.equals(p.domains))\r
+ return false;\r
+ if(!datasets.equals(p.datasets))\r
+ return false;\r
+ if(!rangeMappings.equals(p.rangeMappings))\r
+ return false;\r
+ if(!domainMappings.equals(p.domainMappings))\r
+ return false;\r
+ if(!otherProperties.equals(p.otherProperties))\r
+ return false;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ private class PlotPropertyListener implements Listener<PlotProperties> {\r
+\r
+ private boolean disposed = false;\r
+\r
+ public void dispose() {\r
+ disposed = true;\r
+ }\r
+ @Override\r
+ public void execute(final PlotProperties result) {\r
+ SwingUtilities.invokeLater(new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+ setPlotProperties(result);\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return disposed;\r
+ }\r
+\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Abstract renderer class for all JFreeChart renderers\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public abstract class AbstractRenderer implements IRenderer {\r
+\r
+ protected Resource resource;\r
+ \r
+ public AbstractRenderer(ReadGraph graph, Resource resource) {\r
+ this.resource = resource;\r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ }\r
+\r
+ @Override\r
+ public Resource getResource() {\r
+ return resource;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.labels.StandardCategoryToolTipGenerator;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+\r
+/**\r
+ * Normal bar renderer\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BarRenderer extends AbstractRenderer {\r
+\r
+ public BarRenderer(ReadGraph graph, Resource resource) {\r
+ super(graph, resource);\r
+ }\r
+\r
+ private org.jfree.chart.renderer.category.BarRenderer renderer;\r
+ \r
+ @Override\r
+ public org.jfree.chart.renderer.AbstractRenderer getRenderer() {\r
+ if(renderer == null) {\r
+ renderer = new org.jfree.chart.renderer.category.BarRenderer();\r
+ renderer.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator());\r
+ }\r
+ return renderer;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.axis.Axis;\r
+import org.jfree.chart.axis.CategoryLabelPositions;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Class representing a JFreeChart.CategoryAxis\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class CategoryAxis extends AbstractAxis {\r
+\r
+ public CategoryAxis(ReadGraph graph, Resource axisResource) {\r
+ super(graph, axisResource);\r
+ }\r
+\r
+ @Override\r
+ public Axis getAxis() {\r
+ axis = new org.jfree.chart.axis.CategoryAxis();\r
+ \r
+ if(rotate != null && rotate > 0) {\r
+ ((org.jfree.chart.axis.CategoryAxis)axis).setCategoryLabelPositions(\r
+ CategoryLabelPositions.createUpRotationLabelPositions(Math.toRadians(rotate)));\r
+ }\r
+ \r
+ return super.getAxis();\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+\r
+/**\r
+ * Class representing a JFreeChart.CategoryDataset\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface CategoryDataset extends IDataset {\r
+\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.axis.CategoryAxis;\r
+import org.jfree.chart.axis.ValueAxis;\r
+import org.jfree.chart.plot.Plot;\r
+import org.jfree.chart.renderer.category.CategoryItemRenderer;\r
+import org.jfree.ui.RectangleInsets;\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
+/**\r
+ * Class representing a CategoryPlot for JFreeChart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class CategoryPlot extends AbstractPlot {\r
+\r
+ public CategoryPlot(ReadGraph graph, Resource resource) {\r
+ super(graph, resource);\r
+ }\r
+\r
+ @Override\r
+ protected Plot newPlot() {\r
+ return new org.jfree.chart.plot.CategoryPlot(null, null, null, null);\r
+ }\r
+\r
+ @Override\r
+ protected void setPlotProperties(PlotProperties properties) {\r
+ if(!(plot instanceof org.jfree.chart.plot.CategoryPlot))\r
+ return;\r
+ \r
+ org.jfree.chart.plot.CategoryPlot cplot = (org.jfree.chart.plot.CategoryPlot) plot;\r
+ /* Support using multiple axis, but prefer using only one domain and \r
+ * one range axis\r
+ */\r
+ for(int i = 0; i < properties.ranges.size(); i++) {\r
+ cplot.setRangeAxis(i, (ValueAxis)properties.ranges.get(i).getAxis());\r
+ }\r
+ \r
+ for(int i = 0; i < properties.domains.size(); i++) {\r
+ cplot.setDomainAxis(i, (CategoryAxis)properties.domains.get(i).getAxis());\r
+ }\r
+ \r
+ IAxis axis;\r
+ for(int i = 0; i < properties.datasets.size(); i++) {\r
+ IDataset dataset = properties.datasets.get(i);\r
+ org.jfree.data.category.CategoryDataset ds = (org.jfree.data.category.CategoryDataset)dataset.getDataset();\r
+ cplot.setDataset(i, ds);\r
+// System.out.println("setting dataset " + i + ": " + ds);\r
+ cplot.setRenderer(i, (CategoryItemRenderer)dataset.getRenderer());\r
+ axis = properties.rangeMappings.get(dataset);\r
+ if(axis != null && properties.ranges.contains(axis))\r
+ cplot.mapDatasetToRangeAxis(i, properties.ranges.indexOf(axis));\r
+ axis = properties.domainMappings.get(dataset);\r
+ if(axis != null && properties.ranges.contains(axis))\r
+ cplot.mapDatasetToDomainAxis(i, properties.domains.indexOf(axis));\r
+ }\r
+\r
+ Boolean visibleGrid = (Boolean)properties.otherProperties.get("visibleGrid");\r
+ if(visibleGrid != null) {\r
+ cplot.setRangeGridlinesVisible(visibleGrid);\r
+ cplot.setDomainGridlinesVisible(false);\r
+ }\r
+ \r
+ // Cleaner look: no outline borders\r
+ cplot.setInsets(new RectangleInsets(2,5,2,2), false);\r
+ cplot.setOutlineVisible(false);\r
+ }\r
+\r
+ @Override\r
+ protected void getOtherProperties(ReadGraph graph, PlotProperties properties) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Boolean visibleGrid = graph.getPossibleRelatedValue(resource, jfree.Plot_visibleGrid);\r
+ properties.otherProperties.put("visibleGrid", visibleGrid);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import java.awt.Frame;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.awt.SWT_AWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.jfree.chart.ChartPanel;\r
+import org.jfree.chart.JFreeChart;\r
+import org.simantics.Simantics;\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.AsyncListener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.RunnableWithObject;\r
+\r
+/**\r
+ * Composite containing a single chart defined by a JFreeChart.Chart\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartComposite extends Composite {\r
+\r
+ private Frame frame;\r
+ private ChartPanel panel;\r
+ private Composite composite;\r
+ private IJFreeChart chart;\r
+\r
+ /**\r
+ * A new ChartComposite with a definition in chartResourceURI\r
+ * @param parent Composite\r
+ * @param chartResourceURI URI for a JFreeChart.Chart definition\r
+ * @param style SWT style\r
+ */\r
+ public ChartComposite(Composite parent, final String chartResourceURI, int style) {\r
+ super(parent, style | SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
+\r
+ try {\r
+ Resource chartResource = SimanticsUI.getSession().syncRequest(new Read<Resource>() {\r
+\r
+ @Override\r
+ public Resource perform(ReadGraph graph) throws DatabaseException {\r
+ return graph.getPossibleResource(chartResourceURI);\r
+ }\r
+\r
+ });\r
+ if(chartResource != null)\r
+ CreateContent(chartResource);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * A new ChartComposite with a chartResource definition\r
+ * @param parent Composite\r
+ * @param chartResource JFreeChart.Chart resource\r
+ * @param style SWT style\r
+ */\r
+ public ChartComposite(Composite parent, final Resource chartResource, int style) {\r
+ super(parent, style | SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
+ CreateContent(chartResource);\r
+ }\r
+\r
+ /**\r
+ * Creates and displays the chart defined in chartResource\r
+ * @param chartResource\r
+ */\r
+ private void CreateContent(final Resource chartResource) {\r
+ composite = this;\r
+\r
+ GridLayoutFactory.fillDefaults().applyTo(composite);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+ frame = SWT_AWT.new_Frame(composite);\r
+\r
+ // Add a listener displaying the contents of the chart. Chart is re-drawn if the definition changes\r
+ Simantics.getSession().asyncRequest(new Read<IJFreeChart>() {\r
+\r
+ @Override\r
+ public IJFreeChart perform(ReadGraph graph) throws DatabaseException {\r
+ // Adapt chartResource to a chart (XY, pie, bar, ...)\r
+ if(graph.isInstanceOf(chartResource, JFreeChartResource.getInstance(graph).Chart)) {\r
+ if(chart != null)\r
+ chart.dispose();\r
+ chart = graph.adapt(chartResource, IJFreeChart.class);\r
+ return chart;\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ } , new AsyncListener<IJFreeChart>() {\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return composite.isDisposed();\r
+ }\r
+\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, IJFreeChart chart) {\r
+ if(chart == null || composite.isDisposed())\r
+ return;\r
+ \r
+ JFreeChart jfreeChart = chart.getChart();\r
+ // Display the result chart\r
+ composite.getDisplay().asyncExec(new RunnableWithObject(jfreeChart) {\r
+\r
+ @Override\r
+ public void run() {\r
+ if(composite.isDisposed())\r
+ return;\r
+ if(panel != null)\r
+ frame.remove(panel);\r
+ composite.layout();\r
+ JFreeChart chart = (JFreeChart)getObject();\r
+ panel = new ChartPanel(chart, false, true, true, true, true);\r
+ frame.add(panel);\r
+ frame.repaint();\r
+ frame.validate();\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+ throwable.printStackTrace();\r
+\r
+ }\r
+ });\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart;\r
+\r
+import java.util.ArrayList;\r
+import java.util.UUID;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.request.PossibleActiveExperiment;\r
+import org.simantics.db.layer0.request.PossibleModel;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.operation.Layer0X;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Utilities for handling charts\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartUtils {\r
+ \r
+ /**\r
+ * Creates a new range axis of type jfree.NumberAxis to a plot\r
+ * \r
+ * @param graph WriteGraph\r
+ * @param plot Plot resource\r
+ * @return Created number axis, null if not successful\r
+ * @throws DatabaseException\r
+ */\r
+ public static Resource createNumberRangeAxis(WriteGraph graph, Resource plot) throws DatabaseException {\r
+ Resource axis = null;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ if(plot != null) {\r
+ // Create range axis\r
+ axis = GraphUtils.create2(graph, jfree.NumberAxis,\r
+ l0.HasName, "NumberAxis" + UUID.randomUUID().toString(),\r
+ l0.HasLabel, NameUtils.findFreshLabel(graph, "Y-axis", plot),\r
+ jfree.Plot_rangeAxis_Inverse, plot,\r
+ l0.PartOf, plot);\r
+ \r
+ // Add range axis to the plot's range axis list\r
+ Resource axisList = graph.getPossibleObject(plot, jfree.Plot_rangeAxisList);\r
+ ArrayList<Resource> list = new ArrayList<Resource>();\r
+ list.add(axis);\r
+ if(axisList == null) {\r
+ axisList = ListUtils.create(graph, list);\r
+ graph.claim(plot, jfree.Plot_rangeAxisList, axisList);\r
+ } else {\r
+ ListUtils.insertBack(graph, axisList, list);\r
+ }\r
+ }\r
+ \r
+ return axis;\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Create a XYDataset and map it to axis\r
+ * @param graph WriteGraph\r
+ * @param plot Plot resource containing the dataset\r
+ * @param domainAxis Mapped domain axis for the dataset\r
+ * @param rangeAxis Mapped range axis for the dataset\r
+ * @return created dataset or null if not successful\r
+ * @throws DatabaseException\r
+ */\r
+ public static Resource createXYDataset(WriteGraph graph, Resource plot, Resource domainAxis, Resource rangeAxis) throws DatabaseException {\r
+ if(plot == null || domainAxis == null || rangeAxis == null)\r
+ return null;\r
+ \r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ \r
+ \r
+ // Create a dataset for the axis\r
+ Resource dataset = GraphUtils.create2(graph, jfree.XYDataset,\r
+ l0.HasName, "XYDataset" + UUID.randomUUID().toString(),\r
+ jfree.Dataset_mapToDomainAxis, domainAxis,\r
+ jfree.Dataset_mapToRangeAxis, rangeAxis,\r
+ jfree.Dataset_renderer, GraphUtils.create2(graph, jfree.XYLineRenderer),\r
+ l0.PartOf, plot);\r
+ \r
+ return dataset;\r
+ }\r
+\r
+ /**\r
+ * Creates a new series to a dataset\r
+ * @param graph WriteGraph\r
+ * @param dataset Dataset for the new series\r
+ * @return created series or null if unsuccessful\r
+ * @throws DatabaseException\r
+ */\r
+ public static Resource createSeries(WriteGraph graph, Resource dataset, String rvi) throws DatabaseException {\r
+ if(dataset == null) return null;\r
+ \r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ // Create series\r
+ Resource series = GraphUtils.create2(graph, jfree.Series,\r
+ l0.HasName, "Series" + UUID.randomUUID().toString(),\r
+ jfree.variableRVI, rvi == null ? " <Write variable name>" : rvi,\r
+ l0.PartOf, dataset);\r
+\r
+ // Add series to the dataset's series list\r
+ Resource seriesList = graph.getPossibleObject(dataset, jfree.Dataset_seriesList);\r
+ ArrayList<Resource> list = new ArrayList<Resource>();\r
+ list.add(series);\r
+ if(seriesList == null) {\r
+ seriesList = ListUtils.create(graph, list);\r
+ graph.claim(dataset, jfree.Dataset_seriesList, seriesList);\r
+ } else {\r
+ ListUtils.insertBack(graph, seriesList, list);\r
+ }\r
+ \r
+ return series;\r
+ }\r
+\r
+ /**\r
+ * Find the current realization uri\r
+ * \r
+ * @param graph ReadGraph\r
+ * @param chartComponent A resource from a chart (consistsOf relation in a chart)\r
+ * @return current realization uri\r
+ * @throws DatabaseException\r
+ */\r
+ public static String getCurrentRealizationURI(ReadGraph graph, Resource chartComponent) throws DatabaseException {\r
+ // Find the model where the chart is located\r
+ Resource model = graph.syncRequest(new PossibleModel(chartComponent)); \r
+ if(model == null)\r
+ return null;\r
+ \r
+ // Find the variable realization of the current experiment\r
+ String realizationURI = null;\r
+ Resource realization = graph.syncRequest(new PossibleActiveExperiment(model));\r
+ if (realization == null) {\r
+ Layer0X L0X = Layer0X.getInstance(graph);\r
+ realization = graph.getPossibleObject(model, L0X.HasBaseRealization);\r
+ }\r
+ if (realization != null)\r
+ realizationURI = graph.getURI(realization);\r
+ \r
+ return realizationURI; \r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.data.Range;\r
+\r
+/**\r
+ * NumberAxis that supports adding only one bound, lower or upper.\r
+ * The standard NumberAxis disables auto adjusting if even one of the bounds is set\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ExtendedNumberAxis extends org.jfree.chart.axis.NumberAxis {\r
+ private static final long serialVersionUID = 3066266986472919998L;\r
+\r
+ private Double lower = null;\r
+ private Double upper = null;\r
+ /**\r
+ * Use own lower and upper bounds to support using only one of them\r
+ */\r
+ protected void autoAdjustRange() {\r
+ super.autoAdjustRange();\r
+ Range range = getRange();\r
+ Double lower = this.lower == null ? range.getLowerBound() : this.lower;\r
+ Double upper = this.upper == null ? range.getUpperBound() : this.upper;\r
+ if(lower > upper)\r
+ upper = lower + 1;\r
+ if(upper - lower < getAutoRangeMinimumSize())\r
+ upper = lower + getAutoRangeMinimumSize();\r
+ \r
+ setRange(new Range(lower, upper), false, false);\r
+\r
+ }\r
+\r
+ public void setLower(Double lower) {\r
+ this.lower = lower;\r
+ }\r
+\r
+ public void setUpper(Double upper) {\r
+ this.upper = upper;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.axis.Axis;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+/**\r
+ * Interface for JFreeChart.Axis type resource\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface IAxis extends IJFreeChartComponent {\r
+ \r
+ /**\r
+ * Returns the axis\r
+ * \r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public Axis getAxis();\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.renderer.AbstractRenderer;\r
+import org.jfree.data.general.Dataset;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Interface for JFreeChart.Dataset type resource\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface IDataset extends IJFreeChartComponent {\r
+ \r
+ /**\r
+ * Returns the JFreeChart dataset represented by the associated resource\r
+ * \r
+ * @return JFreeChart dataset\r
+ */\r
+ public Dataset getDataset();\r
+ \r
+ \r
+ /**\r
+ * Returns the renderer for this dataset\r
+ * \r
+ * @return JFreeChart renderer\r
+ */\r
+ public AbstractRenderer getRenderer();\r
+\r
+ /**\r
+ * Returns the resource of this dataset\r
+ * \r
+ * @return\r
+ */\r
+ public Resource getResource();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.JFreeChart;\r
+import org.simantics.db.exception.DatabaseException;\r
+/**\r
+ * Interface for JFreeChart.Chart type resource\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface IJFreeChart extends IJFreeChartComponent {\r
+\r
+ /**\r
+ * Returns the chart\r
+ * \r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ public JFreeChart getChart();\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+/**\r
+ * Interface for all components that are used to create JFreeCharts based on org.simantics.jfreechart ontology \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface IJFreeChartComponent {\r
+ \r
+ /**\r
+ * Dispose this component. Disposing a component may be useful \r
+ * if the component contains listeners that need to be disposed.\r
+ */\r
+ public void dispose();\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.plot.Plot;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+/**\r
+ * Interface for JFreeChart.Plot type resource\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface IPlot extends IJFreeChartComponent {\r
+\r
+ /**\r
+ * Returns the plot\r
+ * \r
+ * @return Title\r
+ * @throws DatabaseException\r
+ */\r
+ public Plot getPlot();\r
+ \r
+ /**\r
+ * Returns the resource of this plot\r
+ * \r
+ * @return\r
+ */\r
+ public Resource getResource();\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.renderer.AbstractRenderer;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Interface for JFreeChart.Renderer type resource\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface IRenderer extends IJFreeChartComponent {\r
+ \r
+ /**\r
+ * Returns the JFreeChart AbstractRenderer represented by the associated resource\r
+ * \r
+ * @return JFreeChart renderer\r
+ */\r
+ public AbstractRenderer getRenderer();\r
+ \r
+ /**\r
+ * Returns the resource of this renderer\r
+ * @return\r
+ */\r
+ public Resource getResource();\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.title.Title;\r
+import org.simantics.db.exception.DatabaseException;\r
+\r
+/**\r
+ * Interface for JFreeChart.Title type resource\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface ITitle extends IJFreeChartComponent {\r
+ \r
+ /**\r
+ * Returns the title\r
+ * \r
+ * @return Title\r
+ * @throws DatabaseException\r
+ */\r
+ public Title getTitle();\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.util.Collection;\r
+\r
+import javax.swing.SwingUtilities;\r
+\r
+import org.jfree.chart.title.LegendTitle;\r
+import org.jfree.chart.title.TextTitle;\r
+import org.jfree.ui.RectangleInsets;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+/**\r
+ * Class representing a complete JFreeChart.Chart\r
+ * \r
+ * This class supports all types of charts. The details of the chart are \r
+ * defined in plots and other adapted classes.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class JFreeChart implements IJFreeChart {\r
+\r
+ private org.jfree.chart.JFreeChart jfreechart;\r
+ private IPlot plot;\r
+ private ITitle title;\r
+ private Resource chartResource;\r
+\r
+ /**\r
+ * \r
+ * @param graph ReadGraph\r
+ * @param chartResource Resource of type JFreeChart.Chart\r
+ */\r
+ public JFreeChart(ReadGraph graph, Resource chartResource) {\r
+ this.chartResource = chartResource;\r
+\r
+ try {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ Collection<Resource> plotsCollection = graph.syncRequest(new ObjectsWithType(chartResource, l0.ConsistsOf, jfree.Plot));\r
+ for(Resource plotResource : plotsCollection) {\r
+ this.plot = graph.adapt(plotResource, IPlot.class);\r
+ } \r
+\r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+\r
+ JFreeChartListener listener;\r
+\r
+ /**\r
+ * Returns a new chart using the information collected in the constructor\r
+ */\r
+ @Override\r
+ public org.jfree.chart.JFreeChart getChart() {\r
+ if(plot == null)\r
+ return null;\r
+\r
+ if(jfreechart == null)\r
+ jfreechart = new org.jfree.chart.JFreeChart(plot.getPlot());\r
+\r
+ if(listener == null) {\r
+ listener = new JFreeChartListener();\r
+ SimanticsUI.getSession().asyncRequest(new Read<Pair<ITitle, Boolean>>() {\r
+\r
+ @Override\r
+ public Pair<ITitle, Boolean> perform(ReadGraph graph) throws DatabaseException {\r
+ if(chartResource == null || !graph.hasStatement(chartResource))\r
+ return null;\r
+ \r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ Resource titleResource = graph.syncRequest(new PossibleObjectWithType(chartResource, l0.ConsistsOf, jfree.Title));\r
+ title = graph.adapt(titleResource, ITitle.class);\r
+ Boolean legendVisible = graph.getPossibleRelatedValue(chartResource, jfree.Chart_visibleLegend, Bindings.BOOLEAN);\r
+ return new Pair<ITitle, Boolean>(title, legendVisible);\r
+ }\r
+ }, listener);\r
+ }\r
+\r
+ return jfreechart;\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ // Call dispose to title and plots to disable their possible listeners\r
+ if(title != null)\r
+ title.dispose();\r
+ if(listener != null)\r
+ listener.dispose();\r
+ if(plot != null)\r
+ plot.dispose();\r
+ }\r
+\r
+\r
+ private class JFreeChartListener implements Listener<Pair<ITitle, Boolean>> {\r
+\r
+ private boolean disposed = false;\r
+ private LegendTitle legend;\r
+\r
+ public void dispose() {\r
+ disposed = true;\r
+ }\r
+\r
+ @Override\r
+ public void execute(final Pair<ITitle, Boolean> result) {\r
+ if(result == null)\r
+ return;\r
+ \r
+ SwingUtilities.invokeLater(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ if(jfreechart == null)\r
+ return;\r
+\r
+ jfreechart.setBackgroundPaint(Color.WHITE);\r
+ \r
+ if(jfreechart.getLegend() != null && !jfreechart.getLegend().equals(legend)) {\r
+ legend = jfreechart.getLegend(); \r
+ legend.setBorder(0, 0, 0, 0);\r
+ int size = legend.getItemFont().getSize();\r
+ legend.setItemFont(new Font("helvetica", Font.PLAIN, size));\r
+ }\r
+\r
+ if(Boolean.FALSE.equals(result.second)) {\r
+ jfreechart.removeLegend();\r
+ } else if (jfreechart.getLegend() == null && legend != null){\r
+ jfreechart.addLegend(legend);\r
+ }\r
+\r
+ TextTitle t = (org.jfree.chart.title.TextTitle)result.first.getTitle();\r
+ if(t.isVisible()) {\r
+ t.setFont(new Font("georgia", Font.BOLD, 13));\r
+ t.setPadding(new RectangleInsets(4, 0, 0, 0));\r
+ jfreechart.setTitle(t);\r
+ } else {\r
+ jfreechart.setTitle((TextTitle)null);\r
+ }\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return disposed;\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.axis.Axis;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Class representing a JFreeChart.NumberAxis\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class NumberAxis extends AbstractAxis {\r
+\r
+ /**\r
+ *\r
+ * @param graph ReadGraph\r
+ * @param axisResource resource of type JFreeChart.NumberAxis\r
+ */\r
+ public NumberAxis(ReadGraph graph, Resource axisResource) {\r
+ super(graph, axisResource);\r
+ }\r
+\r
+\r
+ @Override\r
+ public Axis getAxis() {\r
+ axis = new ExtendedNumberAxis();\r
+ ((ExtendedNumberAxis)axis).setLower(min);\r
+ ((ExtendedNumberAxis)axis).setUpper(max);\r
+ return super.getAxis();\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import java.awt.Color;\r
+import java.util.HashMap;\r
+\r
+/**\r
+ * Class representing a PieDataset in JFreeChart ontology\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface PieDataset extends IDataset {\r
+\r
+\r
+ /**\r
+ * Map of colors for different slices in a pie chart. Name \r
+ * indicates the key of the value.\r
+ * @return Map of colors for different slices in a pie chart\r
+ */\r
+ public HashMap<String, Color> getColorMap();\r
+\r
+\r
+ /**\r
+ * Map of exploded statuses for slices in a pie chart. Name\r
+ * indicates the key of the slice.\r
+ * @return\r
+ */\r
+ public HashMap<String, Boolean> getExplodedMap();\r
+ \r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.util.HashMap;\r
+\r
+import org.jfree.chart.labels.StandardPieSectionLabelGenerator;\r
+import org.jfree.chart.labels.StandardPieToolTipGenerator;\r
+import org.jfree.chart.plot.DefaultDrawingSupplier;\r
+import org.jfree.chart.plot.Plot;\r
+import org.jfree.data.general.Dataset;\r
+import org.jfree.data.general.DatasetChangeEvent;\r
+import org.jfree.data.general.DatasetChangeListener;\r
+import org.jfree.ui.RectangleInsets;\r
+import org.simantics.databoard.Bindings;\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
+/**\r
+ * Class representing a PiePlot in JFreeChart ontology\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class PiePlot extends AbstractPlot {\r
+\r
+ private org.jfree.data.general.PieDataset pieDataset;\r
+ private DatasetChangeListener listener;\r
+ \r
+ public PiePlot(ReadGraph graph, Resource resource) {\r
+ super(graph, resource);\r
+ }\r
+\r
+ /**\r
+ * Pie plot class with a stricter equals condition\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class MyPiePlot extends org.jfree.chart.plot.PiePlot {\r
+\r
+ private static final long serialVersionUID = -5917620061541212934L;\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ boolean result = super.equals(obj);\r
+ if(result == true) {\r
+ org.jfree.chart.plot.PiePlot that = (org.jfree.chart.plot.PiePlot) obj;\r
+ if (this.getDataset() != that.getDataset()) {\r
+ return false; // Normally plot does not check this. We need this to properly update the charts\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ protected Plot newPlot() {\r
+ MyPiePlot plot = new MyPiePlot();\r
+ plot.setToolTipGenerator(new StandardPieToolTipGenerator());\r
+ return plot;\r
+ }\r
+\r
+ @Override\r
+ protected void getOtherProperties(ReadGraph graph, PlotProperties properties) throws DatabaseException {\r
+ Boolean labelsVisible = graph.getPossibleRelatedValue(resource, JFreeChartResource.getInstance(graph).Plot_visibleLabels, Bindings.BOOLEAN);\r
+ properties.otherProperties.put("labelsVisible", labelsVisible);\r
+ }\r
+ \r
+ @Override\r
+ protected void setPlotProperties(PlotProperties properties) {\r
+ if(!(plot instanceof MyPiePlot))\r
+ return;\r
+ \r
+ final MyPiePlot piePlot = (MyPiePlot)plot;\r
+ \r
+ if(!properties.datasets.isEmpty()) {\r
+ // We assume that a pie plot has only one dataset\r
+ final IDataset ds = properties.datasets.get(0);\r
+ Dataset dataset = ((PieDataset)ds).getDataset();\r
+ \r
+ if(dataset == null)\r
+ return;\r
+\r
+ if(pieDataset != null && listener != null) {\r
+ pieDataset.removeChangeListener(listener);\r
+ }\r
+ \r
+ pieDataset = (org.jfree.data.general.PieDataset)dataset;\r
+ piePlot.setDataset(pieDataset);\r
+ \r
+ Boolean labelsVisible = (Boolean)properties.otherProperties.get("labelsVisible");\r
+ if(Boolean.FALSE.equals(labelsVisible))\r
+ piePlot.setLabelGenerator(null);\r
+ else if(piePlot.getLabelGenerator() == null)\r
+ piePlot.setLabelGenerator(new StandardPieSectionLabelGenerator());\r
+ \r
+ listener = new DatasetChangeListener() {\r
+ \r
+ @Override\r
+ public void datasetChanged(DatasetChangeEvent event) {\r
+ HashMap<String, Color> colorMap = ((PieDataset)ds).getColorMap();\r
+ HashMap<String, Boolean> explodedMap = ((PieDataset)ds).getExplodedMap();\r
+ \r
+ for(Object o : piePlot.getDataset().getKeys()) {\r
+ if(o instanceof Comparable) {\r
+ Comparable<?> key = (Comparable<?>)o;\r
+ if(explodedMap.containsKey(key) && explodedMap.get(key)) {\r
+ piePlot.setExplodePercent(key, 0.3);\r
+\r
+ } else {\r
+ piePlot.setExplodePercent(key, 0);\r
+ }\r
+ }\r
+ }\r
+ \r
+ for(String name : explodedMap.keySet()) {\r
+ Boolean exploded = explodedMap.get(name);\r
+ if(Boolean.TRUE.equals(exploded))\r
+ piePlot.setExplodePercent(name, 0.3);\r
+ } \r
+ piePlot.clearSectionPaints(false);\r
+ piePlot.setDrawingSupplier(new DefaultDrawingSupplier());\r
+ for(String name : colorMap.keySet())\r
+ piePlot.setSectionPaint(name, colorMap.get(name));\r
+ }\r
+ };\r
+ \r
+ pieDataset.addChangeListener(listener);\r
+ }\r
+ \r
+ // Cleaner look: no outline borders\r
+ piePlot.setInsets(new RectangleInsets(0,0,0,0), false);\r
+ piePlot.setOutlineVisible(false);\r
+ piePlot.setLabelBackgroundPaint(Color.WHITE);\r
+ piePlot.setLabelFont(new Font("helvetica", Font.PLAIN, 11));\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.labels.StandardCategoryToolTipGenerator;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Stacked bar renderer\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class StackedBarRenderer extends AbstractRenderer {\r
+\r
+ public StackedBarRenderer(ReadGraph graph, Resource resource) {\r
+ super(graph, resource);\r
+ }\r
+\r
+ private org.jfree.chart.renderer.category.StackedBarRenderer renderer;\r
+ \r
+ @Override\r
+ public org.jfree.chart.renderer.AbstractRenderer getRenderer() {\r
+ if(renderer == null) {\r
+ renderer = new org.jfree.chart.renderer.category.StackedBarRenderer();\r
+ renderer.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator());\r
+ }\r
+ return renderer;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.title.Title;\r
+import org.jfree.ui.RectangleEdge;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Class representing a JFreeChart.TextTitle\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class TextTitle implements ITitle {\r
+ \r
+ private org.jfree.chart.title.TextTitle textTitle;\r
+ private RectangleEdge position;\r
+ private String text;\r
+ private Boolean visible;\r
+ \r
+ public TextTitle(ReadGraph graph, Resource titleResource) {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ try {\r
+ text = graph.getPossibleRelatedValue(titleResource, l0.HasLabel, Bindings.STRING);\r
+ Resource pos = graph.getPossibleObject(titleResource, jfree.Title_position);\r
+ position = getRectangleEdgePosition(graph, pos);\r
+ visible = graph.getPossibleRelatedValue(titleResource, jfree.visible, Bindings.BOOLEAN);\r
+\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Get the RectangleEdge representation for Resource position (JFreeChart.Position)\r
+ * @param graph ReadGraph \r
+ * @param position Resource of type JFreeChart.Position\r
+ * @return RectangleEdge representation for Resource position\r
+ */\r
+ private RectangleEdge getRectangleEdgePosition(ReadGraph graph, Resource position) {\r
+ if(position == null)\r
+ return null;\r
+ \r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ if(position.equals(jfree.Top))\r
+ return RectangleEdge.TOP;\r
+ else if(position.equals(jfree.Bottom))\r
+ return RectangleEdge.BOTTOM;\r
+ else if(position.equals(jfree.Left))\r
+ return RectangleEdge.LEFT;\r
+ else if(position.equals(jfree.Right))\r
+ return RectangleEdge.RIGHT;\r
+ else\r
+ return null;\r
+ \r
+ }\r
+\r
+ @Override\r
+ public Title getTitle() {\r
+ textTitle = new org.jfree.chart.title.TextTitle(text);\r
+ if(position != null)\r
+ textTitle.setPosition(position);\r
+ if(visible != null)\r
+ textTitle.setVisible(visible);\r
+ return textTitle;\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.labels.StandardXYToolTipGenerator;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Renderer representing jfree chart renderer for xy areas\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class XYAreaRenderer extends AbstractRenderer {\r
+\r
+ private org.jfree.chart.renderer.xy.XYAreaRenderer renderer;\r
+ \r
+ public XYAreaRenderer(ReadGraph graph, Resource resource) {\r
+ super(graph, resource);\r
+ }\r
+\r
+ @Override\r
+ public org.jfree.chart.renderer.AbstractRenderer getRenderer() {\r
+ if(renderer == null) {\r
+ renderer = new org.jfree.chart.renderer.xy.XYAreaRenderer();\r
+ renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());\r
+ }\r
+ return renderer;\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+\r
+/**\r
+ * Class representing a JFreeChart.XYDataset\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface XYDataset extends IDataset {\r
+\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.labels.StandardXYToolTipGenerator;\r
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Renderer representing jfree chart renderer for xy lines\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class XYLineRenderer extends AbstractRenderer {\r
+\r
+ XYLineAndShapeRenderer renderer;\r
+ \r
+ public XYLineRenderer(ReadGraph graph, Resource resource) {\r
+ super(graph, resource);\r
+ }\r
+\r
+ @Override\r
+ public org.jfree.chart.renderer.AbstractRenderer getRenderer() {\r
+ if(renderer == null) {\r
+ renderer = new XYLineAndShapeRenderer(true, false);\r
+ renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());\r
+ }\r
+ return renderer;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart;\r
+\r
+import org.jfree.chart.axis.ValueAxis;\r
+import org.jfree.chart.plot.Plot;\r
+import org.jfree.chart.renderer.xy.XYItemRenderer;\r
+import org.jfree.data.xy.XYDataset;\r
+import org.jfree.ui.RectangleInsets;\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
+/**\r
+ * Class representing a JFreeChart.XYPlot\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class XYPlot extends AbstractPlot {\r
+\r
+ public XYPlot(ReadGraph graph, Resource plotResource) {\r
+ super(graph, plotResource);\r
+ }\r
+\r
+ @Override\r
+ protected Plot newPlot() {\r
+ return new org.jfree.chart.plot.XYPlot(null, null, null, null);\r
+ }\r
+\r
+ @Override\r
+ protected void getOtherProperties(ReadGraph graph, PlotProperties properties) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Boolean visibleGrid = graph.getPossibleRelatedValue(resource, jfree.Plot_visibleGrid);\r
+ properties.otherProperties.put("visibleGrid", visibleGrid);\r
+ if(!properties.datasets.isEmpty()) {\r
+ IDataset idataset = properties.datasets.get(0);\r
+ Resource renderer = graph.getPossibleObject(idataset.getResource(), jfree.Dataset_renderer);\r
+ if(renderer != null) {\r
+ properties.otherProperties.put("renderer", graph.adapt(renderer, IRenderer.class));\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected void setPlotProperties(PlotProperties properties) {\r
+ if(!(plot instanceof org.jfree.chart.plot.XYPlot))\r
+ return;\r
+\r
+ org.jfree.chart.plot.XYPlot xyplot = (org.jfree.chart.plot.XYPlot)plot;\r
+ xyplot.clearDomainAxes();\r
+ xyplot.clearRangeAxes();\r
+\r
+ for(int i = 0; i < properties.ranges.size(); i++) {\r
+ xyplot.setRangeAxis(i, (ValueAxis)properties.ranges.get(i).getAxis());\r
+ }\r
+\r
+ for(int i = 0; i < properties.domains.size(); i++) {\r
+ xyplot.setDomainAxis(i, (ValueAxis)properties.domains.get(i).getAxis());\r
+ }\r
+\r
+ IAxis axis;\r
+ for(int i = 0; i < properties.datasets.size(); i++) {\r
+ IDataset dataset = properties.datasets.get(i);\r
+ xyplot.setDataset(i, (XYDataset)dataset.getDataset());\r
+ xyplot.setRenderer(i, (XYItemRenderer)dataset.getRenderer());\r
+ axis = properties.rangeMappings.get(dataset);\r
+ if(axis != null && properties.ranges.contains(axis))\r
+ xyplot.mapDatasetToRangeAxis(i, properties.ranges.indexOf(axis));\r
+ axis = properties.domainMappings.get(dataset);\r
+ if(axis != null && properties.ranges.contains(axis))\r
+ xyplot.mapDatasetToDomainAxis(i, properties.domains.indexOf(axis));\r
+ }\r
+\r
+ Boolean visibleGrid = (Boolean)properties.otherProperties.get("visibleGrid");\r
+ if(visibleGrid == null)\r
+ visibleGrid = true;\r
+\r
+ xyplot.setRangeGridlinesVisible(visibleGrid);\r
+ xyplot.setDomainGridlinesVisible(visibleGrid);\r
+\r
+ // Cleaner look: no outline borders\r
+ xyplot.setInsets(new RectangleInsets(2,5,2,10), false);\r
+ xyplot.setOutlineVisible(false);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.element;\r
+\r
+import java.awt.geom.Rectangle2D;\r
+\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.LifeCycle;\r
+import org.simantics.g2d.element.handler.impl.BoundsOutline;\r
+\r
+/**\r
+ * Outline with default bounds. Needed to avoid crashing when trying to rotate chart elements.\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartBoundsOutline extends BoundsOutline implements LifeCycle {\r
+ private static final long serialVersionUID = -3819495313008722843L;\r
+ \r
+ Rectangle2D defaultBounds;\r
+ \r
+ public ChartBoundsOutline(Rectangle2D defaultBounds) {\r
+ this.defaultBounds = defaultBounds;\r
+ }\r
+\r
+ @Override\r
+ public void onElementCreated(IElement e) {\r
+ e.setHint(ElementHints.KEY_BOUNDS, defaultBounds);\r
+ }\r
+\r
+ @Override\r
+ public void onElementDestroyed(IElement e) {}\r
+ @Override\r
+ public void onElementActivated(IDiagram d, IElement e) {}\r
+ @Override\r
+ public void onElementDeactivated(IDiagram d, IElement e) {}\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.element;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.QuadCurve2D;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+import org.jfree.chart.JFreeChart;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\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.diagram.adapter.ElementFactory;\r
+import org.simantics.diagram.adapter.ElementFactoryUtil;\r
+import org.simantics.diagram.adapter.SyncElementFactory;\r
+import org.simantics.diagram.elements.ElementPropertySetter;\r
+import org.simantics.diagram.synchronization.CompositeHintSynchronizer;\r
+import org.simantics.diagram.synchronization.IHintSynchronizer;\r
+import org.simantics.diagram.synchronization.ISynchronizationContext;\r
+import org.simantics.diagram.synchronization.SynchronizationHints;\r
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
+import org.simantics.diagram.synchronization.graph.RemoveElement;\r
+import org.simantics.diagram.synchronization.graph.TransformSynchronizer;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.LifeCycle;\r
+import org.simantics.g2d.element.handler.impl.DefaultTransform;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+import org.simantics.g2d.element.handler.impl.StaticSymbolImageInitializer;\r
+import org.simantics.g2d.element.handler.impl.StaticSymbolImpl;\r
+import org.simantics.g2d.image.Image;\r
+import org.simantics.g2d.image.impl.ShapeImage;\r
+import org.simantics.jfreechart.chart.IJFreeChart;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
+\r
+/**\r
+ * Element factory for creating chart elements to diagrams\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartElementFactory extends SyncElementFactory {\r
+\r
+ private static final String CLASS_ID = "Chart";\r
+ public static final ElementFactory INSTANCE = new ChartElementFactory();\r
+ public static final Image STATIC_IMAGE = new ShapeImage(getChartShape(), null, new BasicStroke(1f), true);\r
+ public static final double SYMBOL_CHART_SIZE = 10.0;\r
+ public static final Key KEY_CHART_COMPONENT = new KeyOf(Resource.class, "CHART_COMPONENT"); \r
+ public static final Key KEY_CHART = new KeyOf(JFreeChart.class, "CHART"); \r
+ \r
+ static Shape getChartShape() {\r
+ \r
+ Path2D path = new Path2D.Double();\r
+ // First create the axis for a chart symbol\r
+ path.moveTo(-SYMBOL_CHART_SIZE, -SYMBOL_CHART_SIZE);\r
+ path.lineTo(-SYMBOL_CHART_SIZE, SYMBOL_CHART_SIZE);\r
+ path.lineTo( SYMBOL_CHART_SIZE, SYMBOL_CHART_SIZE);\r
+\r
+ // Then a curve to the chart\r
+ QuadCurve2D curve = new QuadCurve2D.Double(\r
+ -SYMBOL_CHART_SIZE + 1, SYMBOL_CHART_SIZE - 1,\r
+ SYMBOL_CHART_SIZE - 5, SYMBOL_CHART_SIZE - 5,\r
+ SYMBOL_CHART_SIZE - 1, -SYMBOL_CHART_SIZE + 3);\r
+\r
+ // Connect shapes\r
+ path.append(curve, false);\r
+ return path;\r
+ }\r
+\r
+ // Hint synchronizer for synchronizing transform and bounds\r
+ private static final IHintSynchronizer HINT_SYNCHRONIZER = new CompositeHintSynchronizer(\r
+ TransformSynchronizer.INSTANCE);\r
+\r
+ public static ElementClass create(ReadGraph graph, Resource chart) throws DatabaseException {\r
+ return ElementClass.compile(\r
+ new ChartSceneGraph(),\r
+ new Initializer(chart),\r
+ new StaticObjectAdapter(JFreeChartResource.getInstance(graph).ChartElement),\r
+ DefaultTransform.INSTANCE,\r
+ StaticSymbolImageInitializer.INSTANCE,\r
+ new StaticSymbolImpl(STATIC_IMAGE),\r
+ new ChartBoundsOutline(new Rectangle2D.Double(-20, -20, 60, 40)),\r
+ new ElementPropertySetter(ChartSceneGraph.KEY_SG_NODE)\r
+ ).setId(CLASS_ID);\r
+ }\r
+\r
+ public ElementClass create(ReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType) throws DatabaseException {\r
+ return create(graph, null);\r
+ }\r
+\r
+ @Override\r
+ public void load(ReadGraph g, ICanvasContext canvas, final IDiagram diagram, Resource element, final IElement e) throws DatabaseException {\r
+\r
+ Resource chartResource;\r
+ ElementPropertySetter ps = e.getElementClass().getSingleItem(ElementPropertySetter.class);\r
+ ps.loadProperties(e, element, g);\r
+ \r
+ AffineTransform at = DiagramGraphUtil.getAffineTransform(g, element);\r
+ // Hack for disabling all rotations in chart elements\r
+ double x = at.getTranslateX();\r
+ double y = at.getTranslateY();\r
+ at.setToRotation(0);\r
+ at.setToTranslation(x, y);\r
+ ElementUtils.setTransform(e, at); // Set hint transform without rotations\r
+ ps.overrideProperty(e, "Transform", at); // Set property Transform without rotations\r
+ \r
+ e.setHint(SynchronizationHints.HINT_SYNCHRONIZER, HINT_SYNCHRONIZER);\r
+ \r
+\r
+ Object o = e.getHint(KEY_CHART_COMPONENT);\r
+ if(o == null || !(o instanceof Resource)) {\r
+ chartResource = g.getPossibleObject(element, JFreeChartResource.getInstance(g).ChartElement_component);\r
+ } else {\r
+ chartResource = (Resource)o;\r
+ }\r
+\r
+ if(chartResource == null || !g.hasStatement(chartResource)) {\r
+ // Remove element if there is no chart resource for it \r
+ final ISynchronizationContext syncContext = ElementFactoryUtil.getContextChecked(diagram); \r
+ g.asyncRequest(new WriteRequest() {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ new RemoveElement(syncContext, diagram, e).perform(graph); \r
+ }\r
+ });\r
+ return;\r
+ }\r
+\r
+ IJFreeChart ichart = g.adapt(chartResource, IJFreeChart.class);\r
+\r
+ if(ichart != null) {\r
+ JFreeChart chart = ichart.getChart();\r
+ e.setHint(KEY_CHART, chart);\r
+ }\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * Initializer for setting a chart component for element\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ static class Initializer implements LifeCycle {\r
+ private static final long serialVersionUID = -5822080013184271204L;\r
+ Object component;\r
+\r
+ Initializer(Object component) {\r
+ this.component = component;\r
+ }\r
+\r
+ @Override\r
+ public void onElementCreated(IElement e) {\r
+ if(component != null) e.setHint(KEY_CHART_COMPONENT, component);\r
+ }\r
+\r
+ @Override\r
+ public void onElementActivated(IDiagram d, IElement e) {}\r
+ @Override\r
+ public void onElementDeactivated(IDiagram d, IElement e) {}\r
+ @Override\r
+ public void onElementDestroyed(IElement e) {}\r
+ };\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.element;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.synchronization.graph.ElementWriter;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Element writer for chart elements. ChartElementWriter stores\r
+ * the reference to a chart definition into the element resource\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartElementWriter implements ElementWriter {\r
+\r
+ @Override\r
+ public void addToGraph(WriteGraph graph, IElement element, Resource elementResource) throws DatabaseException {\r
+ Resource chartComponent = element.getHint(ChartElementFactory.KEY_CHART_COMPONENT);\r
+ if (chartComponent == null)\r
+ throw new IllegalArgumentException("KEY_CHART_COMPONENT hint not set");\r
+ \r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ graph.claim(elementResource, jfree.ChartElement_component, chartComponent);\r
+ }\r
+\r
+ @Override\r
+ public void removeFromGraph(WriteGraph graph, Resource elementResource) throws DatabaseException {\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.element;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Graphics2D;\r
+import java.awt.Stroke;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Line2D;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+import javax.swing.JPanel;\r
+\r
+import org.jfree.chart.ChartPanel;\r
+import org.jfree.chart.JFreeChart;\r
+import org.simantics.scenegraph.ISelectionPainterNode;\r
+import org.simantics.scenegraph.g2d.events.EventTypes;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
+import org.simantics.scenegraph.swing.ComponentNode;\r
+import org.simantics.scenegraph.utils.GeometryUtils;\r
+import org.simantics.scenegraph.utils.NodeUtil;\r
+\r
+/**\r
+ * Chart node for displaying jfreechart charts in diagrams\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartNode extends ComponentNode<JPanel> implements ISelectionPainterNode {\r
+\r
+ private static final long serialVersionUID = 5013911689968911010L;\r
+ private boolean hover = false;\r
+ private boolean dragging = false;\r
+\r
+ private ResizeListener resizeListener; \r
+\r
+ protected transient JFreeChart chart = null;\r
+\r
+ public boolean dragging() {\r
+ return dragging;\r
+ }\r
+\r
+ public void setChart(JFreeChart chart) {\r
+ this.chart = chart;\r
+ }\r
+\r
+ public void setResizeListener(ResizeListener listener) {\r
+ this.resizeListener = listener;\r
+ }\r
+\r
+ @SyncField({"hover"})\r
+ public void setHover(boolean hover) {\r
+ this.hover = hover;\r
+ repaint();\r
+ }\r
+\r
+ @Override\r
+ public void cleanup() {\r
+ removeEventHandler(this);\r
+ super.cleanup();\r
+ }\r
+\r
+ @Override\r
+ public void init() {\r
+ super.init();\r
+ }\r
+\r
+ public static void expand(Rectangle2D rectangle, double scaleX, double scaleY) {\r
+ GeometryUtils.expandRectangle(rectangle,\r
+ 5 * scaleY > 5 ? 5 * scaleY : 5, \r
+ 3 * scaleY > 3 ? 3 * scaleY : 3, \r
+ 3 * scaleX > 3 ? 3 * scaleX : 3, \r
+ 3 * scaleX > 3 ? 3 * scaleX : 3);\r
+ }\r
+\r
+ @Override\r
+ public void render(Graphics2D g2d) {\r
+ if (component == null && chart != null) {\r
+ // Need the chart, so this cannot be done during initialization\r
+ component = new ChartPanel(chart, false);\r
+ ((ChartPanel)component).setRefreshBuffer(false);\r
+ component.setIgnoreRepaint(true); \r
+ component.setDoubleBuffered(false);\r
+ if(bounds != null) {\r
+ component.setBounds(0, 0, 0, 0);\r
+ }\r
+ super.init();\r
+ addEventHandler(this);\r
+ }\r
+\r
+ if (component != null) {\r
+ AffineTransform ot = g2d.getTransform();\r
+ g2d.transform(transform);\r
+ double scaleX = g2d.getTransform().getScaleX();\r
+ double scaleY = g2d.getTransform().getScaleY();\r
+\r
+ AffineTransform at = new AffineTransform(transform);\r
+ synchronized(transform) {\r
+ at.setToTranslation(bounds.getMinX(), bounds.getMinY());\r
+ at.scale(1/scaleX, 1/scaleY);\r
+ }\r
+ g2d.transform(at);\r
+ int width = (int)(bounds.getWidth() * scaleX);\r
+ int height = (int)(bounds.getHeight() * scaleY);\r
+\r
+ if(hover || dragging) {\r
+ // Borders\r
+ Color orig = g2d.getColor();\r
+ BasicStroke oldStroke = (BasicStroke) g2d.getStroke();\r
+ g2d.setColor(Color.LIGHT_GRAY);\r
+ Rectangle2D b = new Rectangle2D.Double(0, 0, width, height);\r
+ Rectangle2D r = b.getBounds2D();\r
+ expand(r, 1 * scaleX, 1 * scaleY);\r
+ g2d.fill(r);\r
+\r
+ // Lower right corner for dragging\r
+ double x = r.getMaxX() - (0.33 * scaleX);\r
+ double y = r.getMaxY() - (0.33 * scaleY);\r
+\r
+ if(r.getMaxX() - x > 0.4) { \r
+ // if there is enough space, use decorated corner\r
+ BasicStroke hilightStroke = new BasicStroke(oldStroke.getLineWidth() * 3);\r
+ for(int i = 1; i < 4; i++) {\r
+ Line2D line = new Line2D.Double(\r
+ x - (i * scaleX), \r
+ y, \r
+ x, \r
+ y - (i * scaleY));\r
+\r
+ g2d.setStroke(hilightStroke);\r
+ g2d.setColor(Color.GRAY);\r
+ g2d.draw(line);\r
+\r
+ g2d.setStroke(oldStroke);\r
+ g2d.setColor(Color.BLACK);\r
+ g2d.draw(line);\r
+ }\r
+\r
+\r
+ } else {\r
+ // not enough space, use a non-decorated corner\r
+ float f = 3;\r
+ Rectangle2D corner = new Rectangle2D.Double(r.getMaxX() - f, r.getMaxY() - f, f, f);\r
+ g2d.setColor(Color.DARK_GRAY);\r
+ g2d.fill(corner);\r
+ }\r
+\r
+ g2d.setStroke(oldStroke);\r
+ g2d.setColor(orig);\r
+ }\r
+\r
+ boolean selected = NodeUtil.isSelected(this, 1);\r
+ if (selected) {\r
+ Color orig = g2d.getColor();\r
+ Stroke origStroke = g2d.getStroke();\r
+\r
+ g2d.setColor(Color.RED);\r
+ double s = GeometryUtils.getScale(g2d.getTransform());\r
+ g2d.setStroke(new BasicStroke(1f * s < 1f ? 1f : 1f * (float)s));\r
+\r
+ Rectangle2D b = new Rectangle2D.Double(0, 0, width, height);\r
+ Rectangle2D r = b.getBounds2D();\r
+ expand(r, scaleX, scaleY);\r
+ g2d.draw(r);\r
+\r
+ g2d.setColor(orig);\r
+ g2d.setStroke(origStroke);\r
+ }\r
+\r
+ synchronized(component) {\r
+ component.setLocation((int)g2d.getTransform().getTranslateX(), (int)g2d.getTransform().getTranslateY());\r
+ if(component.getSize().getWidth() != width || component.getSize().getHeight() != height) {\r
+ component.setSize(width, height);\r
+ }\r
+ component.paint(g2d);\r
+ }\r
+\r
+ g2d.setTransform(ot);\r
+ } else {\r
+ /*\r
+ * Component == null\r
+ * \r
+ * The related chart definition ha been removed. \r
+ */\r
+ System.out.println("TÄÄLLÄ, TÄÄLLÄ");\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected boolean mouseButtonPressed(MouseButtonPressedEvent event) {\r
+ Point2D local = controlToLocal( event.controlPosition );\r
+ local = parentToLocal(local);\r
+ Rectangle2D bounds = getBoundsInLocal().getBounds2D();\r
+ expand(bounds, 1, 1);\r
+ double control = 3.0;\r
+ Rectangle2D corner = new Rectangle2D.Double(bounds.getMaxX() - control, bounds.getMaxY() - control, control, control);\r
+ if (hover && corner.contains(local)) {\r
+ dragging = true;\r
+ return true;\r
+ }\r
+ return super.mouseButtonPressed(event);\r
+ }\r
+\r
+\r
+ @Override\r
+ protected boolean mouseMoved(MouseMovedEvent e) {\r
+ if(dragging) {\r
+ Point2D local = controlToLocal( e.controlPosition );\r
+ local = parentToLocal(local);\r
+\r
+ Rectangle2D bounds = getBoundsInLocal().getBounds2D();\r
+\r
+ if(Math.abs(bounds.getMaxX() - local.getX()) > 3 ||\r
+ Math.abs(bounds.getMaxY() - local.getY()) > 3) {\r
+ resize(local);\r
+ }\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public boolean hitCorner(Point2D point) {\r
+ Rectangle2D bounds = getBoundsInLocal().getBounds2D();\r
+ expand(bounds, 1, 1);\r
+ double control = 3.0;\r
+ Rectangle2D corner = new Rectangle2D.Double(bounds.getMaxX() - control, bounds.getMaxY() - control, control, control);\r
+ return corner.contains(point);\r
+ }\r
+\r
+ private void resize(Point2D local) {\r
+ Rectangle2D bounds = getBoundsInLocal().getBounds2D();\r
+ double x = bounds.getX();\r
+ double y = bounds.getY();\r
+ double dx = local.getX() - bounds.getMaxX();\r
+ double dy = local.getY() - bounds.getMaxY();\r
+ double w = bounds.getWidth() + dx;\r
+ double h = bounds.getHeight() + dy;\r
+ bounds.setRect(\r
+ x, \r
+ y, \r
+ w > 20 ? w : 20, \r
+ h > 20 ? h : 20\r
+ );\r
+ setBounds(bounds);\r
+ }\r
+\r
+ @Override\r
+ protected boolean mouseDragged(MouseDragBegin e) {\r
+ if(dragging) {\r
+ return true; // Eat event for faster resize\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ protected boolean mouseButtonReleased(MouseButtonReleasedEvent e) {\r
+ if(dragging) {\r
+ Point2D local = controlToLocal( e.controlPosition );\r
+ local = parentToLocal(local);\r
+ if(Math.abs(bounds.getMaxX() - local.getX()) > 3 ||\r
+ Math.abs(bounds.getMaxY() - local.getY()) > 3) {\r
+ resize(local);\r
+ }\r
+ dragging = false;\r
+ if(resizeListener != null)\r
+ resizeListener.elementResized(bounds);\r
+ }\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public int getEventMask() {\r
+ return EventTypes.MouseButtonPressedMask\r
+ | EventTypes.MouseMovedMask\r
+ | EventTypes.MouseButtonReleasedMask\r
+ ;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.element;\r
+\r
+import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+import org.jfree.chart.JFreeChart;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.SceneGraphNodeKey;\r
+import org.simantics.g2d.element.handler.HandleMouseEvent;\r
+import org.simantics.g2d.element.handler.InternalSize;\r
+import org.simantics.g2d.element.handler.PropertySetter;\r
+import org.simantics.g2d.element.handler.SceneGraph;\r
+import org.simantics.scenegraph.Node;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.scenegraph.g2d.IG2DNode;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent;\r
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintListener;\r
+import org.simantics.utils.datastructures.hints.IHintObservable;\r
+\r
+/**\r
+ * Chart scenegraph for chart elements in diagrams\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartSceneGraph implements SceneGraph, HandleMouseEvent, InternalSize {\r
+ private static final long serialVersionUID = 1875762898776996989L;\r
+\r
+ public static final Key KEY_SG_NODE = new SceneGraphNodeKey(Node.class, "CHART_SG_NODE");\r
+ public static final Key KEY_SG_SELECTION_NODE = new SceneGraphNodeKey(Node.class, "CHART_SG_SELECTION_NODE");\r
+\r
+ protected IHintListener hoverHintListener;\r
+\r
+ public ChartSceneGraph() {\r
+ }\r
+\r
+ /**\r
+ * Expands bounds a little to allow selecting and grabbing a chart element\r
+ * from outside the chart graphics\r
+ */\r
+ @Override\r
+ public Rectangle2D getBounds(IElement e, Rectangle2D s) {\r
+ if (s==null) s = new Rectangle2D.Double();\r
+\r
+ IG2DNode node = (IG2DNode)e.getHint(KEY_SG_NODE);\r
+ AffineTransform at = (AffineTransform)e.getHint(ElementHints.KEY_TRANSFORM);\r
+ if(at != null && node != null && node.getBoundsInLocal() != null) {\r
+ Shape shape = node.getBoundsInLocal();\r
+ Rectangle2D r = shape.getBounds2D();\r
+ double scaleX = at.getScaleX();\r
+ double scaleY = at.getScaleY();\r
+ ChartNode.expand(r, 1 * scaleX, 1 * scaleY);\r
+ shape = r;\r
+ s.setFrame(shape.getBounds2D());\r
+ } else {\r
+ s.setFrame((Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS));\r
+ }\r
+ return s;\r
+ }\r
+\r
+ @Override\r
+ public void cleanup(IElement e) {\r
+ if(hoverHintListener != null)\r
+ e.removeHintListener(hoverHintListener);\r
+\r
+ Node node = e.removeHint(KEY_SG_NODE);\r
+ if (node != null)\r
+ node.remove();\r
+ }\r
+\r
+ @Override\r
+ public void init(final IElement e, G2DParentNode parent) {\r
+ ChartNode node = e.getHint(KEY_SG_NODE);\r
+ if(node == null) {\r
+ // Create a new chart node\r
+ node = parent.getOrCreateNode("chart_"+e.hashCode(), ChartNode.class);\r
+\r
+ Rectangle2D bounds = (Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS);\r
+ if(bounds == null) {\r
+ bounds = new Rectangle2D.Double(-40, -40, 80, 80);\r
+ e.setHint(ElementHints.KEY_BOUNDS, bounds);\r
+ }\r
+ node.setBounds(bounds);\r
+\r
+ JFreeChart chart = e.getHint(ChartElementFactory.KEY_CHART);\r
+ if(chart != null)\r
+ node.setChart(chart);\r
+\r
+ // Add a resize listener for updating bounds information to graph after resizing\r
+ node.setResizeListener(new ResizeListener() {\r
+\r
+ @Override\r
+ public void elementResized(Rectangle2D newBounds) {\r
+ e.setHint(ElementHints.KEY_BOUNDS, newBounds);\r
+ IDiagram diagram = ElementUtils.getDiagram(e);\r
+ DiagramUtils.synchronizeHintsToBackend(diagram, e);\r
+ }\r
+ });\r
+\r
+ e.setHint(KEY_SG_NODE, node);\r
+ }\r
+\r
+ // Hover listening\r
+ hoverHintListener = new IHintListener() {\r
+ @Override\r
+ public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {\r
+\r
+ }\r
+\r
+ @Override\r
+ public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
+ if(key == ElementHints.KEY_HOVER) {\r
+ IElement e = (IElement)sender;\r
+ ChartNode name = (ChartNode) e.getHint(KEY_SG_NODE);\r
+ if (name != null)\r
+ name.setHover(Boolean.TRUE.equals(e.getHint(ElementHints.KEY_HOVER)));\r
+ }\r
+ }\r
+ };\r
+ e.addHintListener(hoverHintListener);\r
+\r
+ update(e);\r
+ }\r
+\r
+ public void update(IElement e) {\r
+ PropertySetter setter = e.getElementClass().getSingleItem(PropertySetter.class);\r
+ setter.syncPropertiesToNode(e);\r
+ }\r
+\r
+ \r
+ @Override\r
+ public boolean handleMouseEvent(IElement e, ICanvasContext ctx, MouseEvent me) {\r
+ if (me instanceof MouseEnterEvent) {\r
+ e.setHint(ElementHints.KEY_HOVER, true);\r
+ } else if (me instanceof MouseExitEvent) {\r
+ e.setHint(ElementHints.KEY_HOVER, false);\r
+ }\r
+ return false;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.element;\r
+\r
+import java.awt.datatransfer.Transferable;\r
+import java.awt.datatransfer.UnsupportedFlavorException;\r
+import java.awt.dnd.DnDConstants;\r
+import java.awt.dnd.DropTargetDragEvent;\r
+import java.awt.geom.AffineTransform;\r
+import java.io.IOException;\r
+\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.request.UnaryRead;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;\r
+import org.simantics.g2d.dnd.DnDHints;\r
+import org.simantics.g2d.dnd.ElementClassDragItem;\r
+import org.simantics.g2d.dnd.IDnDContext;\r
+import org.simantics.g2d.dnd.IDropTargetParticipant;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.modeling.ui.diagramEditor.PopulateElementDropParticipant;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.LocalObjectTransferable;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Drop participant for dropping chart definitions into diagrams\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class PopulateChartDropParticipant extends PopulateElementDropParticipant implements IDropTargetParticipant {\r
+\r
+ public PopulateChartDropParticipant(GraphToDiagramSynchronizer synchronizer) {\r
+ super(synchronizer);\r
+ }\r
+\r
+ @Override\r
+ public void dragEnter(DropTargetDragEvent dtde, final IDnDContext dp) {\r
+ Transferable tr = dtde.getTransferable();\r
+ if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {\r
+\r
+ Session session = synchronizer.getSession();\r
+\r
+ Object obj = null;\r
+\r
+ try {\r
+ obj = tr.getTransferData(LocalObjectTransferable.FLAVOR);\r
+ \r
+ // Create a structural selection from transfer data\r
+ if (!(obj instanceof IStructuredSelection)) {\r
+ obj = LocalObjectTransfer.getTransfer().getObject();\r
+ }\r
+\r
+ if (obj instanceof IStructuredSelection) {\r
+\r
+ IStructuredSelection sel = (IStructuredSelection) obj;\r
+ \r
+ // Can drop only one chart at the time\r
+ if (sel.size() == 1) {\r
+ \r
+ // Get the chart definition\r
+ Resource chart = AdaptionUtils.adaptToSingle(sel, Resource.class);\r
+ if (chart == null)\r
+ return;\r
+\r
+ ElementClassDragItem item = session.syncRequest(new UnaryRead<Resource,ElementClassDragItem>(chart) {\r
+\r
+ @Override\r
+ public ElementClassDragItem perform(ReadGraph graph) throws DatabaseException {\r
+ if(graph.isInstanceOf(parameter, JFreeChartResource.getInstance(graph).Chart)) {\r
+ ElementClassDragItem item = new ElementClassDragItem(ChartElementFactory.create(graph, parameter));\r
+ AffineTransform initialTr = AffineTransform.getScaleInstance(1, 1);\r
+ item.getHintContext().setHint(ElementHints.KEY_TRANSFORM, initialTr);\r
+ return item;\r
+ } else {\r
+ return null;\r
+ }\r
+\r
+ }\r
+ });\r
+\r
+ if(item != null) {\r
+ dp.add(item);\r
+ dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1));\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ } catch (UnsupportedFlavorException e) {\r
+ e.printStackTrace();\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ }\r
+\r
+ dtde.acceptDrag(DnDConstants.ACTION_COPY);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.element;\r
+\r
+import java.awt.geom.Rectangle2D;\r
+\r
+/**\r
+ * Interface for listeners listening resize events in chart nodes\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public interface ResizeListener {\r
+ \r
+ /**\r
+ * Triggered when a node has been resized\r
+ * @param newBounds new bounds for the node\r
+ */\r
+ public void elementResized(Rectangle2D newBounds);\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.browsing.ui.model.children.ChildRule;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * ChildRule for finding the axis of a JFreeChart\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class AxisChildRule implements ChildRule {\r
+\r
+ @Override\r
+ public boolean isCompatible(Class<?> contentType) {\r
+ return contentType.equals(Resource.class);\r
+ }\r
+\r
+ @Override\r
+ public Collection<?> getChildren(ReadGraph graph, Object parent) throws DatabaseException {\r
+ ArrayList<Resource> result = new ArrayList<Resource>();\r
+ if(!(parent instanceof Resource))\r
+ return result;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ /*\r
+ * 1. chart may have multiple plots\r
+ * 2. plot may have multiple axis\r
+ */\r
+ for(Resource plot : graph.syncRequest(new ObjectsWithType((Resource)parent, l0.ConsistsOf, jfree.Plot))) {\r
+ Resource rangeAxisList = graph.getPossibleObject(plot, jfree.Plot_rangeAxisList);\r
+ if(rangeAxisList != null)\r
+ for(Resource axis : ListUtils.toList(graph, rangeAxisList)) {\r
+ result.add(axis);\r
+ }\r
+ }\r
+ return result;\r
+\r
+\r
+ }\r
+\r
+ @Override\r
+ public Collection<?> getParents(ReadGraph graph, Object child) throws DatabaseException {\r
+ return new ArrayList<Resource>();\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import java.util.List;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.adapter.DropActionFactory;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.jfreechart.chart.properties.xyline.AxisAndVariablesExplorerComposite;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Action for dropping axis on top of other axis or series in {@link AxisAndVariablesExplorerComposite}\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class AxisDropAction implements DropActionFactory {\r
+\r
+ @Override\r
+ public Runnable create(ReadGraph g, Object target, Object source) throws DatabaseException {\r
+ // Make sure that both target and source are resources\r
+ Resource t = AdaptionUtils.adaptToSingle(target, Resource.class);\r
+ Resource s = AdaptionUtils.adaptToSingle(source, Resource.class);\r
+ \r
+ if(t == null || s == null)\r
+ return null;\r
+ \r
+ // Make sure that source and target are of correct type\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(g);\r
+ if(!g.isInstanceOf(s, jfree.Axis))\r
+ return null;\r
+ if(!g.isInstanceOf(t, jfree.Series) && !g.isInstanceOf(t, jfree.Axis))\r
+ return null;\r
+ \r
+ return getRunnable(t, s);\r
+ }\r
+\r
+ /**\r
+ * Get the runnable for doing the drop action \r
+ * \r
+ * @param t target resource\r
+ * @param s source resource\r
+ * @return Runnable\r
+ */\r
+ private Runnable getRunnable(final Resource t, final Resource s) {\r
+ Runnable runnable = new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+ SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ if(t == null || s == null) return;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource target = t;\r
+ Resource source = s;\r
+ \r
+ // Dragged axis always exists in the same list with target axis, so it is safe to get the target index\r
+ Resource plot = graph.getPossibleObject(source, l0.PartOf);\r
+ Resource axisListResource = graph.getPossibleObject(plot, jfree.Plot_rangeAxisList);\r
+ List<Resource> axisList = ListUtils.toList(graph, axisListResource);\r
+ if(graph.isInstanceOf(target, jfree.Series)) {\r
+ // Dropped a axis over a series -> get the axis of the series\r
+ Resource dataset = graph.getPossibleObject(target, l0.PartOf);\r
+ target = graph.getPossibleObject(dataset, jfree.Dataset_mapToRangeAxis);\r
+ }\r
+ \r
+ // move axis to target position\r
+ int targetIndex = axisList.indexOf(target);\r
+ axisList.remove(source);\r
+ axisList.add(targetIndex, source);\r
+ \r
+ // Update the range axis list\r
+ graph.deny(plot, jfree.Plot_rangeAxisList);\r
+ axisListResource = ListUtils.create(graph, axisList);\r
+ graph.claim(plot, jfree.Plot_rangeAxisList, axisListResource);\r
+ }\r
+\r
+ });\r
+ }\r
+ };\r
+ return runnable;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.simantics.browsing.ui.common.ColumnKeys;\r
+import org.simantics.browsing.ui.model.labels.LabelRule;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Label rule for range axis label\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class AxisLabelRule implements LabelRule {\r
+\r
+ @Override\r
+ public boolean isCompatible(Class<?> contentType) {\r
+ return contentType.equals(Resource.class);\r
+ }\r
+\r
+ /**\r
+ * Range axis label\r
+ * \r
+ * Options:\r
+ * 1. Label\r
+ * 2. Default\r
+ */\r
+ @Override\r
+ public Map<String, String> getLabel(ReadGraph graph, Object content) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource resource = (Resource)content;\r
+ String label = graph.getPossibleRelatedValue(resource, l0.HasLabel, Bindings.STRING);\r
+ if(label == null || label.isEmpty()) {\r
+ label = "Range";\r
+ Resource plot = graph.getPossibleObject(resource, l0.PartOf);\r
+ if(plot != null) {\r
+ Resource axisListResource = graph.getPossibleObject(plot, jfree.Plot_rangeAxisList);\r
+ if(axisListResource != null) {\r
+ List<Resource> axisList = ListUtils.toList(graph, axisListResource);\r
+ if(axisList.contains(resource))\r
+ label = label + " " + (axisList.indexOf(resource) + 1);\r
+ }\r
+ }\r
+ }\r
+ return Collections.singletonMap(ColumnKeys.SINGLE, label);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.browsing.ui.model.children.ChildRule;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Child rule for obtaining series in a chart. \r
+ * Assumes that the chart has only one plot and that plot has only one dataset\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class SeriesChildRule implements ChildRule {\r
+\r
+ @Override\r
+ public boolean isCompatible(Class<?> contentType) {\r
+ return contentType.equals(Resource.class);\r
+ }\r
+\r
+ @Override\r
+ public Collection<?> getChildren(ReadGraph graph, Object parent) throws DatabaseException {\r
+ ArrayList<Resource> result = new ArrayList<Resource>();\r
+ if(!(parent instanceof Resource))\r
+ return result;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ /*\r
+ * 1. we assume that there is only one plot\r
+ * 2. we assume that the only plot has only one dataset\r
+ */\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType((Resource)parent, l0.ConsistsOf, jfree.Plot));\r
+ \r
+ Resource dataset = graph.syncRequest(new PossibleObjectWithType(plot, l0.ConsistsOf, jfree.Dataset));\r
+ \r
+ Resource seriesList = graph.getPossibleObject(dataset, jfree.Dataset_seriesList);\r
+ if(seriesList != null)\r
+ for(Resource series : ListUtils.toList(graph, seriesList)) {\r
+ result.add(series);\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ @Override\r
+ public Collection<?> getParents(ReadGraph graph, Object child) throws DatabaseException {\r
+ return new ArrayList<Resource>();\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.adapter.DropActionFactory;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.jfreechart.chart.properties.xyline.XYLineAxisAndVariablesTab;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Drop action for explorer in {@link XYLineAxisAndVariablesTab}. This action is used for dropping \r
+ * both series on axis or another sries\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class SeriesDropAction implements DropActionFactory {\r
+\r
+ @Override\r
+ public Runnable create(ReadGraph g, Object target, Object source) throws DatabaseException {\r
+ // Make sure that both target and source are resources\r
+ Resource t = AdaptionUtils.adaptToSingle(target, Resource.class);\r
+ Resource s = AdaptionUtils.adaptToSingle(source, Resource.class);\r
+ \r
+ if(t == null || s == null)\r
+ return null;\r
+ \r
+ // Make sure that source and target are of correct type\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(g);\r
+ if(!g.isInstanceOf(s, jfree.Series))\r
+ return null;\r
+ if(!g.isInstanceOf(t, jfree.Series) && !g.isInstanceOf(t, jfree.Axis))\r
+ return null;\r
+ \r
+ return getRunnable(t, s);\r
+ }\r
+\r
+ /**\r
+ * Get the runnable for doing the drop action \r
+ * \r
+ * @param t target resource\r
+ * @param s source resource\r
+ * @return Runnable\r
+ */\r
+ private Runnable getRunnable(final Resource t, final Resource s) {\r
+ Runnable runnable = new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+ SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ if(t == null || s == null) return;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource target = t;\r
+ Resource source = s;\r
+ Resource droppedOnSeries = null;\r
+\r
+ // Dropped a series over a series -> get target dataset\r
+ if(graph.isInstanceOf(target, jfree.Series)) {\r
+ droppedOnSeries = target;\r
+ Resource dataset = graph.getPossibleObject(target, l0.PartOf);\r
+ if(dataset != null)\r
+ target = dataset;\r
+ }\r
+\r
+ // Dropped a series over an axis -> get target dataset\r
+ if(graph.isInstanceOf(target, jfree.Axis)) {\r
+ Resource dataset = graph.syncRequest(new PossibleObjectWithType(target, jfree.Dataset_mapToRangeAxis_Inverse, jfree.Dataset));\r
+ if(dataset != null)\r
+ target = dataset;\r
+ }\r
+\r
+ // Move series to a dataset\r
+ if(graph.isInstanceOf(target, jfree.Dataset)) {\r
+ // Remove from old dataset if it was different than the new one\r
+ Resource sourceDataset = graph.getPossibleObject(source, l0.PartOf);\r
+ if(sourceDataset != null && !sourceDataset.equals(target)) {\r
+ Resource sourceSeriesList = graph.getPossibleObject(sourceDataset, jfree.Dataset_seriesList);\r
+ if(sourceSeriesList != null)\r
+ ListUtils.removeElement(graph, sourceSeriesList, source);\r
+ }\r
+ graph.deny(source, l0.PartOf);\r
+\r
+ // Add to new dataset\r
+ Resource targetSeriesList = graph.getPossibleObject(target, jfree.Dataset_seriesList);\r
+ if(targetSeriesList == null) {\r
+ targetSeriesList = ListUtils.create(graph, Collections.<Resource>emptyList());\r
+ graph.claim(target, jfree.Dataset_seriesList, targetSeriesList);\r
+ }\r
+\r
+\r
+ // Series was dropped on another series. Move the dropped series to that place and recreate the list\r
+ if(droppedOnSeries != null) {\r
+ List<Resource> list = ListUtils.toList(graph, targetSeriesList);\r
+ int targetIndex = list.indexOf(droppedOnSeries);\r
+ if(list.contains(source))\r
+ list.remove(source);\r
+ list.add(targetIndex, source);\r
+ graph.deny(target, jfree.Dataset_seriesList);\r
+ targetSeriesList = ListUtils.create(graph, list);\r
+ graph.claim(target, jfree.Dataset_seriesList, targetSeriesList);\r
+ } else {\r
+ ListUtils.insertFront(graph, targetSeriesList, Collections.singleton(source));\r
+ }\r
+\r
+ graph.claim(target, l0.ConsistsOf, source);\r
+ }\r
+ }\r
+ });\r
+ }\r
+ };\r
+ return runnable;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import org.eclipse.jface.resource.FontDescriptor;\r
+import org.simantics.browsing.ui.content.LabelDecorator;\r
+import org.simantics.browsing.ui.model.labeldecorators.LabelDecorationRule;\r
+import org.simantics.databoard.Bindings;\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.ui.utils.AdaptionUtils;\r
+\r
+public class SeriesLabelDecorationRule implements LabelDecorationRule {\r
+\r
+ @Override\r
+ public boolean isCompatible(Class<?> contentType) {\r
+ return contentType.equals(Resource.class);\r
+ }\r
+\r
+ @Override\r
+ public LabelDecorator getLabelDecorator(ReadGraph graph, Object content) throws DatabaseException {\r
+ Resource resource = AdaptionUtils.adaptToSingle(content, Resource.class);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+\r
+ if (resource != null && graph.isInstanceOf(resource, jfree.Series)) {\r
+ final String[] filter = graph.getPossibleRelatedValue(resource, jfree.variableFilter, Bindings.STRING_ARRAY);\r
+ if(filter != null) {\r
+ return new LabelDecorator.Stub() {\r
+ @Override\r
+ public String decorateLabel(String label, String column, int itemIndex) {\r
+ label += " [";\r
+ for(int i = 0; i < filter.length; i++) {\r
+ label += filter[i];\r
+ if(i < filter.length - 1)\r
+ label += ", ";\r
+ }\r
+ label += "]";\r
+ return label;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public <F> F decorateFont(F font, String column, int itemIndex) {\r
+ return (F) ((FontDescriptor) font);\r
+ }\r
+ };\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import java.util.Collections;\r
+import java.util.Map;\r
+\r
+import org.simantics.browsing.ui.common.ColumnKeys;\r
+import org.simantics.browsing.ui.model.labels.LabelRule;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Label rule for dataset series\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class SeriesLabelRule implements LabelRule {\r
+\r
+ @Override\r
+ public boolean isCompatible(Class<?> contentType) {\r
+ return contentType.equals(Resource.class);\r
+ }\r
+\r
+ /**\r
+ * Options:\r
+ * 1. Label\r
+ * 2. Variable rvi\r
+ * 3. Default\r
+ */\r
+ @Override\r
+ public Map<String, String> getLabel(ReadGraph graph, Object content) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource resource = (Resource)content;\r
+ String label = graph.getPossibleRelatedValue(resource, l0.HasLabel, Bindings.STRING);\r
+ if(label == null || label.isEmpty()) {\r
+ label = graph.getPossibleRelatedValue(resource, jfree.variableRVI);\r
+ if(label != null && !label.isEmpty() && label.length() > 1)\r
+ label = label.substring(1).replace('/', '.');\r
+ else\r
+ label = "Set variable";\r
+ }\r
+ return Collections.singletonMap(ColumnKeys.SINGLE, label);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.ge;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.browsing.ui.model.children.ChildRule;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * ChildRule for finding the series of an axis\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class VariableChildRule implements ChildRule {\r
+\r
+ @Override\r
+ public boolean isCompatible(Class<?> contentType) {\r
+ return contentType.equals(Resource.class);\r
+ }\r
+\r
+ @Override\r
+ public Collection<?> getChildren(ReadGraph graph, Object parent) throws DatabaseException {\r
+ ArrayList<Resource> result = new ArrayList<Resource>();\r
+ if(!(parent instanceof Resource))\r
+ return result;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource axis = (Resource)parent;\r
+ /*\r
+ * 1. Axis belongs to a plot\r
+ * 2. Plot may have multiple datasets\r
+ * 3. Dataset is mapped to a single range axis\r
+ * 3. Dataset may have multiple seires\r
+ */\r
+ Resource plot = graph.getPossibleObject(axis, jfree.Plot_rangeAxis_Inverse);\r
+ if(plot == null)\r
+ return result;\r
+\r
+ for(Resource dataset : graph.syncRequest(new ObjectsWithType(plot, l0.ConsistsOf, jfree.Dataset))) {\r
+ if(graph.hasStatement(dataset, jfree.Dataset_mapToRangeAxis, axis)) {\r
+ Resource seriesList = graph.getPossibleObject(dataset, jfree.Dataset_seriesList);\r
+ if(seriesList != null)\r
+ for(Resource series : ListUtils.toList(graph, seriesList)) {\r
+ result.add(series);\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public Collection<?> getParents(ReadGraph graph, Object child) throws DatabaseException {\r
+ return new ArrayList<Resource>();\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+\r
+public class AllVariablesOfModel implements Read<String[]> {\r
+ \r
+ public Resource res;\r
+ \r
+ public AllVariablesOfModel(Resource res) {\r
+ this.res = res;\r
+ }\r
+ \r
+ @Override\r
+ public String[] perform(ReadGraph graph) throws DatabaseException {\r
+ IAllVariablesOfModel query = graph.adapt(res, IAllVariablesOfModel.class);\r
+ return graph.syncRequest(query);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Class containing properties for hiding pars of an axis\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class AxisHidePropertyComposite extends Composite {\r
+\r
+ public AxisHidePropertyComposite(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
+ super(parent, style);\r
+ \r
+ GridLayoutFactory.fillDefaults().applyTo(this);\r
+ \r
+ Group hideGroup = new Group(this, SWT.NONE);\r
+ hideGroup.setText("Hide");\r
+ GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+ \r
+ Button label = new Button(hideGroup, support, SWT.CHECK);\r
+ label.setText("Label");\r
+ label.setSelectionFactory(new BooleanPropertyFactory(null, JFreeChartResource.URIs.Axis_visibleLabel, true));\r
+ label.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Axis_visibleLabel));\r
+ GridDataFactory.fillDefaults().applyTo(label.getWidget());\r
+\r
+ Button tmarks = new Button(hideGroup, support, SWT.CHECK);\r
+ tmarks.setText("Tick marks");\r
+ tmarks.setSelectionFactory(new BooleanPropertyFactory(null, JFreeChartResource.URIs.Axis_visibleTickMarks, true));\r
+ tmarks.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Axis_visibleTickMarks));\r
+ GridDataFactory.fillDefaults().applyTo(tmarks.getWidget());\r
+ \r
+ Button axisLine = new Button(hideGroup, support, SWT.CHECK);\r
+ axisLine.setText("Axis line");\r
+ axisLine.setSelectionFactory(new BooleanPropertyFactory(null, JFreeChartResource.URIs.Axis_visibleAxisLine, true));\r
+ axisLine.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Axis_visibleAxisLine));\r
+ GridDataFactory.fillDefaults().applyTo(axisLine.getWidget());\r
+\r
+ Button tlabels = new Button(hideGroup, support, SWT.CHECK);\r
+ tlabels.setText("Tick labels");\r
+ tlabels.setSelectionFactory(new BooleanPropertyFactory(null, JFreeChartResource.URIs.Axis_visibleTickLabels, true));\r
+ tlabels.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Axis_visibleTickLabels));\r
+ GridDataFactory.fillDefaults().applyTo(tlabels.getWidget());\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.utils.datastructures.Quad;\r
+\r
+/**\r
+ * PropertyFactory for finding a boolean property. Supports also finding the \r
+ * property from a first occurrence of resource ConsistsOf type HasProperty \r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BooleanPropertyFactory extends ReadFactoryImpl<Resource, Boolean> {\r
+\r
+ final private String propertyURI;\r
+ final private String typeURI;\r
+ final private Boolean inverse;\r
+ final private Boolean defaultValue;\r
+ \r
+ /**\r
+ * PropertyFactory for finding a boolean property with propertyURI\r
+ * \r
+ * @param propertyURI URI for the boolean property\r
+ */\r
+ public BooleanPropertyFactory(String propertyURI) {\r
+ this(null, propertyURI, false);\r
+ }\r
+ \r
+ /**\r
+ * PropertyFactory for finding a boolean property with propertyURI.\r
+ * \r
+ * Supports inverting the result (e.g. if required information is IsHidden, but database contains IsVisible)\r
+ * \r
+ * @param propertyURI URI for the boolean property\r
+ * @param inverse Invert the result?\r
+ */\r
+ public BooleanPropertyFactory(String propertyURI, boolean inverse) {\r
+ this(null, propertyURI, inverse);\r
+ }\r
+\r
+ /**\r
+ * PropertyFactory for finding a boolean property with propertyURI.\r
+ * \r
+ * Finds the property for first ObjectWithType(resource, L0.ConsistsOf, type)\r
+ * \r
+ * Supports inverting the result (e.g. if required information is IsHidden, but database contains IsVisible)\r
+ * \r
+ * @param typeURI URI for a resource (resource ConsistsOf type) (null allowed)\r
+ * @param propertyURI URI for the boolean property\r
+ * @param inverse Invert the result?\r
+ */\r
+ public BooleanPropertyFactory(String typeURI, String propertyURI, boolean inverse) {\r
+ this(typeURI, propertyURI, inverse, false);\r
+ }\r
+ \r
+ /**\r
+ * PropertyFactory for finding a boolean property with propertyURI.\r
+ * \r
+ * Finds the property for first ObjectWithType(resource, L0.ConsistsOf, type)\r
+ * \r
+ * Supports inverting the result (e.g. if required information is IsHidden, but database contains IsVisible)\r
+ * \r
+ * @param typeURI URI for a resource (resource ConsistsOf type) (null allowed -> not used)\r
+ * @param propertyURI URI for the boolean property\r
+ * @param inverse Invert the result?\r
+ * @param defaultValue default value\r
+ */\r
+ public BooleanPropertyFactory(String typeURI, String propertyURI, boolean inverse, boolean defaultValue) {\r
+ this.propertyURI = propertyURI;\r
+ this.inverse = inverse;\r
+ this.typeURI = typeURI;\r
+ this.defaultValue = defaultValue;\r
+ }\r
+\r
+ @Override\r
+ public Object getIdentity(Object inputContents) {\r
+ return new Quad<Resource, String, Object, Boolean>((Resource) inputContents, propertyURI, getClass(), defaultValue);\r
+ }\r
+\r
+ @Override\r
+ public Boolean perform(ReadGraph graph, Resource r) throws DatabaseException {\r
+ if(typeURI == null) {\r
+ // if no typeUri, use the default resource r\r
+ return getValue(graph, r);\r
+ } else {\r
+ // typeURI was defined, find the property for the first occurence of ConsistsOf type\r
+ Resource type = graph.getResource(typeURI);\r
+ for(Resource o : graph.syncRequest(new ObjectsWithType(r, Layer0.getInstance(graph).ConsistsOf, type))) {\r
+ // Returns the value for the first occurrence\r
+ return getValue(graph, o);\r
+ }\r
+ }\r
+ // if nothing was found with typeURI\r
+ return false;\r
+ }\r
+ \r
+ /**\r
+ * Return the value for a Boolean literal possibly inverted (or default if resource != Boolean literal) \r
+ * \r
+ * @param graph ReadGraph\r
+ * @param resource Literal Boolean resource \r
+ * @return value of the parameter (or default or inverted)\r
+ * @throws DatabaseException\r
+ */\r
+ private Boolean getValue(ReadGraph graph, Resource resource) throws DatabaseException {\r
+ Boolean value = graph.getPossibleRelatedValue(resource, graph.getResource(propertyURI), Bindings.BOOLEAN);\r
+ if(value != null) {\r
+ return !inverse.equals(value);\r
+ } else {\r
+ return defaultValue;\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.layer0.Layer0;\r
+\r
+/**\r
+ * Class for setting a boolean value when a selection occurs. (check box buttons)\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BooleanSelectionListener extends SelectionListenerImpl<Resource> {\r
+\r
+ final private String propertyURI;\r
+ final private String typeUri;\r
+ \r
+ /**\r
+ * Boolean selection listener for property with propertyURI\r
+ * \r
+ * @param context ISessionContext\r
+ * @param propertyURI uri of the boolean property\r
+ */\r
+ public BooleanSelectionListener(ISessionContext context, String propertyURI) {\r
+ this(context, null, propertyURI);\r
+ }\r
+\r
+ /**\r
+ * Boolean selection listener for property with propertyURI\r
+ * Sets the property for all ObjectWithType(resource, L0.ConsistsOf, type)\r
+ * \r
+ * @param context ISessionContext\r
+ * @param typeUri URI for a resource (resource ConsistsOf type) (null allowed -> not used)\r
+ * @param propertyURI uri of the boolean property\r
+ */\r
+ public BooleanSelectionListener(ISessionContext context, String typeUri, String propertyURI) {\r
+ super(context);\r
+ this.propertyURI = propertyURI;\r
+ this.typeUri = typeUri;\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource chart) throws DatabaseException {\r
+ if(typeUri == null) {\r
+ setValue(graph, chart);\r
+ } else {\r
+ Resource type = graph.getResource(typeUri);\r
+ for(Resource object : graph.syncRequest(new ObjectsWithType(chart, Layer0.getInstance(graph).ConsistsOf, type))) {\r
+ setValue(graph, object);\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ /**\r
+ * Set boolean value for Boolean literal resource (inverts the current value).\r
+ * @param graph ReadGraph\r
+ * @param resource Boolean literal resource\r
+ * @throws DatabaseException\r
+ */\r
+ private void setValue(WriteGraph graph, Resource resource) throws DatabaseException {\r
+ Resource property = graph.getResource(propertyURI);\r
+ Boolean value = graph.getPossibleRelatedValue(resource, property, Bindings.BOOLEAN);\r
+ graph.claimLiteral(resource, property, Boolean.FALSE.equals(value));\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.ui.IWorkbenchSite;\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.Resource;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.ChartComposite;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Tab for displaying a chart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ChartTab extends LabelPropertyTabContributor implements Widget {\r
+\r
+ private Composite parent;\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) {\r
+ support.register(this);\r
+ this.parent = body;\r
+ }\r
+\r
+ @Override\r
+ public void setInput(ISessionContext context, final Object input) {\r
+ Resource chart = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ new ChartComposite(parent, chart, SWT.BORDER);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Device;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.eclipse.swt.widgets.ColorDialog;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\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.ReadGraph;\r
+import org.simantics.db.Resource;\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.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+import org.simantics.utils.RunnableWithObject;\r
+import org.simantics.utils.datastructures.Triple;\r
+\r
+/**\r
+ * Composite for selecting a color for a chart component\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ColorPicker extends Composite implements Widget {\r
+\r
+ Button defaultColor, customColor, color;\r
+\r
+ /**\r
+ * Create a composite containing radio buttons for default or custom color. Color chooser button is active\r
+ * when the custom radio button is selected. Color chooser uses {@link ColorDialog} to select a color \r
+ * \r
+ * @param parent Composite\r
+ * @param context ISessionContext\r
+ * @param support WidgetSupport\r
+ * @param style SWT style\r
+ */\r
+ public ColorPicker(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
+ super(parent, style);\r
+ support.register(this);\r
+ \r
+ GridLayoutFactory.fillDefaults().numColumns(4).applyTo(this);\r
+\r
+ defaultColor = new Button(this, support, SWT.RADIO);\r
+ defaultColor.setText("default");\r
+ defaultColor.setSelectionFactory(new DefaultColorSelectionFactory(false));\r
+ defaultColor.addSelectionListener(new DefaultColorSelectionListener(context));\r
+ GridDataFactory.fillDefaults().applyTo(defaultColor.getWidget());\r
+\r
+ customColor = new Button(this, support, SWT.RADIO);\r
+ customColor.setText("custom");\r
+ customColor.setSelectionFactory(new DefaultColorSelectionFactory(true));\r
+ customColor.addSelectionListener(new DefaultColorSelectionListener(context));\r
+ \r
+ GridDataFactory.fillDefaults().applyTo(customColor.getWidget());\r
+\r
+ color = new Button(this, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(color.getWidget());\r
+ color.setImageFactory(new ColorImageFactoryFactory(color));\r
+ color.addSelectionListener(new ColorSelectionListener(context));\r
+ color.getWidget().setEnabled(false);\r
+ }\r
+\r
+ /**\r
+ * Method for finding the resource for which the color is selected. \r
+ * \r
+ * @param graph ReadGraph\r
+ * @param input input from WidgetSupport\r
+ * @return\r
+ * @throws DatabaseException\r
+ */\r
+ protected Resource getResource(ReadGraph graph, Resource input) throws DatabaseException {\r
+ return input;\r
+ }\r
+ \r
+ /**\r
+ * Method for getting the relation with which the g2d.Color is related to a resource\r
+ * \r
+ * @param graph ReadGraph\r
+ * @return Color relation\r
+ * @throws DatabaseException\r
+ */\r
+ protected Resource getColorRelation(ReadGraph graph) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ return jfree.color;\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ final Resource resource = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ \r
+ // Create a listener to define the enabled state of the color chooser button\r
+ context.getSession().asyncRequest(new Read<Boolean>() {\r
+\r
+ @Override\r
+ public Boolean perform(ReadGraph graph) throws DatabaseException {\r
+ // if there is a color definition, the color chooser is active\r
+ Boolean result = graph.hasStatement(getResource(graph, resource), getColorRelation(graph));\r
+ return result;\r
+ }\r
+ \r
+ }, new Listener<Boolean>() {\r
+\r
+ @Override\r
+ public void execute(Boolean result) {\r
+ if(!color.getWidget().isDisposed()) {\r
+ color.getWidget().getDisplay().asyncExec(new RunnableWithObject(result) {\r
+ @Override\r
+ public void run() {\r
+ if(!color.getWidget().isDisposed())\r
+ color.getWidget().setEnabled((Boolean)getObject());\r
+ }\r
+ });\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return color.getWidget().isDisposed();\r
+ }\r
+ });\r
+ }\r
+ \r
+ /**\r
+ * Get a colored image to be displayed in the color chooser button\r
+ * \r
+ * @param device SWT Device\r
+ * @param red Red 0-255\r
+ * @param green Green 0-255\r
+ * @param blue Blue 0-255\r
+ * @return\r
+ */\r
+ private Image getColorPickerImage(Device device, int red, int green, int blue) {\r
+ Image image = new Image(device, 20, 20);\r
+ GC gc = new GC (image);\r
+ gc.setBackground (new Color(device, red, green, blue));\r
+ gc.fillRectangle (image.getBounds ());\r
+ gc.dispose ();\r
+ return image;\r
+ }\r
+\r
+ /**\r
+ * ImageFactory returning an image for color button\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class ColorImageFactoryFactory extends ReadFactoryImpl<Resource, Image> {\r
+ \r
+ Button button;\r
+ \r
+ public ColorImageFactoryFactory(Button button) {\r
+ super();\r
+ this.button = button;\r
+ }\r
+ \r
+ public Object getIdentity(Object inputContents) {\r
+ return new Triple<Object, Class<?>, Button>(inputContents, getClass(), button);\r
+ }\r
+\r
+ @Override\r
+ public Image perform(ReadGraph graph, Resource input) throws DatabaseException {\r
+ if(button.getWidget().isDisposed())\r
+ return null;\r
+ Display device = button.getWidget().getDisplay();\r
+ if(device == null)\r
+ return null;\r
+ RGB rgb = getColor(graph, getResource(graph, input));\r
+ return getColorPickerImage(device, rgb.red, rgb.green, rgb.blue);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Get RGB from a color literal resource. If resource is not a color resource, return blue (RGB 0, 0, 255)\r
+ * @param graph ReadGraph\r
+ * @param input Color literal resource (float[4])\r
+ * @return RGB color\r
+ * @throws DatabaseException\r
+ */\r
+ private RGB getColor(ReadGraph graph, Resource input) throws DatabaseException{\r
+ float[] colorComponents = graph.getPossibleRelatedValue(input, getColorRelation(graph));\r
+ RGB rgb;\r
+ if(colorComponents == null)\r
+ rgb = new RGB(0, 0, 255);\r
+ else\r
+ rgb = new RGB((int)(colorComponents[0] * 255.0f), \r
+ (int)(colorComponents[1] * 255.0f), \r
+ (int)(colorComponents[2] * 255.0f));\r
+ return rgb;\r
+ }\r
+\r
+\r
+ /**\r
+ * SelectionListener for color button. \r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class ColorSelectionListener extends SelectionListenerImpl<Resource> {\r
+\r
+ private SelectionEvent e;\r
+ private RGB rgb;\r
+ \r
+ /**\r
+ * \r
+ * @param context ISessionContext\r
+ */\r
+ public ColorSelectionListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ if(color.getWidget().isDisposed())\r
+ return;\r
+ // Save the event for coordinates\r
+ this.e = e;\r
+ super.widgetSelected(e);\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ if(color.getWidget().isDisposed())\r
+ return;\r
+ \r
+ final Resource resource = getResource(graph, input);\r
+ final Display display = color.getWidget().getDisplay();\r
+ final RGB oldRGB = getColor(graph, resource);\r
+ \r
+ display.asyncExec(new RunnableWithObject(oldRGB) {\r
+ public void run() {\r
+ // Use color dialog to select a color\r
+ Shell shell = new Shell(display);\r
+ ColorDialog cd = new ColorDialog(shell);\r
+ Point point = color.getWidget().toDisplay(e.x - 150, e.y - 150);\r
+ cd.getParent().setLocation(point.x, point.y);\r
+ cd.setText("Select color");\r
+ cd.setRGB((RGB)getObject());\r
+ rgb = cd.open();\r
+ if(rgb == null)\r
+ return;\r
+ \r
+ SimanticsUI.getSession().asyncRequest(new WriteRequest() {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ float[] components = new float[] {(float)rgb.red / 255.0f, (float)rgb.green / 255.0f, (float)rgb.blue / 255.0f, 1.0f};\r
+ graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components); \r
+ }\r
+ });\r
+ \r
+ }\r
+ });\r
+ \r
+ \r
+\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * SelectionFactory for default and custom color radio buttons\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class DefaultColorSelectionFactory extends ReadFactoryImpl<Resource, Boolean> {\r
+\r
+ private Boolean isCustom;\r
+\r
+ /**\r
+ * \r
+ * @param isCustom Is this custom button?\r
+ */\r
+ public DefaultColorSelectionFactory(Boolean isCustom) {\r
+ super();\r
+ this.isCustom = isCustom;\r
+ }\r
+\r
+ @Override\r
+ public Object getIdentity(Object inputContents) {\r
+ return new Triple<Resource, Object, Boolean>((Resource) inputContents, getClass(), isCustom);\r
+ }\r
+\r
+ @Override\r
+ public Boolean perform(ReadGraph graph, Resource input) throws DatabaseException {\r
+ Resource r = graph.getPossibleObject(getResource(graph, input), getColorRelation(graph));\r
+ boolean result = false; // Default == not selected\r
+ if(r == null && !isCustom) {\r
+ // No color definition and default-button -> selected\r
+ result = true;\r
+ } else if(r != null && isCustom) {\r
+ // color definition and custom button -> selected\r
+ result = true;\r
+ }\r
+ return result;\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * SelectionListener for default and custom radio buttons\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class DefaultColorSelectionListener extends SelectionListenerImpl<Resource> {\r
+\r
+ private SelectionEvent e;\r
+\r
+ public DefaultColorSelectionListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ this.e = e; \r
+ super.widgetSelected(e);\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ Resource resource = getResource(graph, input);\r
+ if(customColor.getWidget().equals(e.widget)) {\r
+ // Custom selected. If there is no color already, create a default Blue color\r
+ G2DResource g2d = G2DResource.getInstance(graph);\r
+ if(graph.getPossibleObject(resource, getColorRelation(graph)) == null) {\r
+ float[] components = java.awt.Color.BLUE.getColorComponents(new float[4]);\r
+ components[3] = 1.0f;\r
+ graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components);\r
+ }\r
+ } else {\r
+ // Default selected, remove color definition\r
+ graph.deny(resource, getColorRelation(graph));\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.dialogs.IInputValidator;\r
+\r
+/**\r
+ * Validator for validating that an input is double.\r
+ * \r
+ * Can allow empty strings.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class DoubleValidator implements IInputValidator {\r
+ \r
+ boolean allowEmpty;\r
+ \r
+ /**\r
+ * New double validator. Does not allow empty strings\r
+ */\r
+ public DoubleValidator() {\r
+ this(false);\r
+ }\r
+ \r
+ /**\r
+ * New double validator.\r
+ * @param allowEmpty Are empty strings allowed\r
+ */\r
+ public DoubleValidator(boolean allowEmpty) {\r
+ this.allowEmpty = allowEmpty;\r
+ }\r
+ \r
+ @Override\r
+ public String isValid(String newText) {\r
+ if (allowEmpty && newText.trim().isEmpty())\r
+ return null;\r
+ try {\r
+ Double.parseDouble(newText);\r
+ return null;\r
+ } catch (NumberFormatException e) {\r
+ return e.getMessage();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import org.simantics.db.request.Read;\r
+\r
+public interface IAllVariablesOfModel extends Read<String[]>{\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.resource.ColorDescriptor;\r
+import org.eclipse.jface.resource.ResourceManager;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ITrackedColorProvider;\r
+\r
+/**\r
+ * ColorProvider providing coloring scheme for chart tab text widgets\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class JFreeChartPropertyColorProvider implements ITrackedColorProvider {\r
+ \r
+ private final ResourceManager resourceManager;\r
+ \r
+ private final ColorDescriptor highlightColor = ColorDescriptor.createFrom(new RGB(254, 255, 197));\r
+ private final ColorDescriptor inactiveColor = ColorDescriptor.createFrom(new RGB(255, 255, 255));\r
+ private final ColorDescriptor invalidInputColor = ColorDescriptor.createFrom(new RGB(255, 128, 128));\r
+\r
+ public JFreeChartPropertyColorProvider(ResourceManager resourceManager) {\r
+ this.resourceManager = resourceManager;\r
+ }\r
+ \r
+ @Override\r
+ public Color getEditingBackground() {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public Color getHoverBackground() {\r
+ return resourceManager.createColor(highlightColor);\r
+ }\r
+\r
+ @Override\r
+ public Color getInactiveBackground() {\r
+ return resourceManager.createColor(inactiveColor);\r
+ }\r
+\r
+ @Override\r
+ public Color getInvalidBackground() {\r
+ return resourceManager.createColor(invalidInputColor);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.procedure.AsyncListener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.selectionview.PropertyTabContributorImpl;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+import org.simantics.utils.datastructures.Callback;\r
+\r
+public abstract class LabelPropertyTabContributor extends PropertyTabContributorImpl {\r
+\r
+ private boolean isDisposed = false;\r
+\r
+\r
+ public void createControl(Composite parent, final IWorkbenchSite site, final ISessionContext context, final WidgetSupportImpl support) {\r
+ super.createControl(parent, site, context, support);\r
+\r
+ // Add dispose listener to make sure name listening receives the correct isDisposed -value\r
+ parent.addDisposeListener(new DisposeListener() {\r
+\r
+ @Override\r
+ public void widgetDisposed(DisposeEvent e) {\r
+ LabelPropertyTabContributor.this.dispose();\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void updatePartName(ISelection forSelection, final Callback<String> updateCallback) {\r
+ final Variable variable = AdaptionUtils.adaptToSingle(forSelection, Variable.class);\r
+ final Resource resource = AdaptionUtils.adaptToSingle(forSelection, Resource.class);\r
+ if(resource == null && variable == null) {\r
+ updateCallback.run("Selection properties");\r
+ return;\r
+ }\r
+\r
+ SimanticsUI.getSession().asyncRequest(new Read<String>() {\r
+\r
+ @Override\r
+ public String perform(ReadGraph graph) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ ModelingResources mr = ModelingResources.getInstance(graph);\r
+ \r
+ Resource r;\r
+ if(variable != null) {\r
+ r = (Resource)variable.getRepresents(graph);\r
+ } else {\r
+ r = resource;\r
+ }\r
+ \r
+ if(graph.hasStatement(r, mr.ElementToComponent)) {\r
+ r = graph.getSingleObject(r, mr.ElementToComponent);\r
+ }\r
+ String label = graph.getPossibleRelatedValue(r, l0.HasLabel);\r
+ if(label != null)\r
+ return label;\r
+ label = graph.getPossibleRelatedValue(r, l0.HasName);\r
+ if(label != null)\r
+ return label;\r
+ return "No name for selection";\r
+ }\r
+ }, new AsyncListener<String>() {\r
+\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, String result) {\r
+ updateCallback.run(result);\r
+ }\r
+\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return isDisposed;\r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ protected void dispose() {\r
+ this.isDisposed = true;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.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
+\r
+/**\r
+ * Class for providing RVI content to a text field with all '/' characters changed to '.'\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class RVIFactory extends ReadFactoryImpl<Resource, String> {\r
+\r
+ @Override\r
+ public String perform(ReadGraph graph, Resource input) throws DatabaseException {\r
+ String value = graph.getPossibleRelatedValue(input, JFreeChartResource.getInstance(graph).variableRVI);\r
+ return value != null ? value = value.substring(1).replace('/', '.') : "";\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.bindings.keys.KeyStroke;\r
+import org.eclipse.jface.bindings.keys.ParseException;\r
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;\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
+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.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Class for modifying variable name to rvi and saving it to database.\r
+ * \r
+ * Modifier also adds content proposal support to the control it is added to.\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class RVIModifier extends TextModifyListenerImpl<Resource> {\r
+\r
+ private boolean active;\r
+ private Control control;\r
+ \r
+ private char[] alphaNumericCharacters = {\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
+ '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
+ /**\r
+ * Create a new RVIModifier and attach a content proposal support to control\r
+ * @param control\r
+ * @param support\r
+ */\r
+ public RVIModifier(Control control, WidgetSupport support) {\r
+ this.control = control;\r
+ this.active = true;\r
+ \r
+ KeyStroke keyStroke = null;\r
+ try {\r
+ keyStroke = KeyStroke.getInstance("Ctrl+Space");\r
+ } catch (ParseException e1) {\r
+ e1.printStackTrace();\r
+ }\r
+ \r
+ SimpleContentProposalProvider scpp = new VariableProposalProvider(control, support);\r
+ scpp.setFiltering(true);\r
+\r
+ ContentProposalAdapter adapter = new ContentProposalAdapter(\r
+ control, new TextContentAdapter(), scpp, keyStroke, alphaNumericCharacters);\r
+ adapter.setAutoActivationDelay(0);\r
+ adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);\r
+ adapter.addContentProposalListener(new IContentProposalListener2() {\r
+\r
+ @Override\r
+ public void proposalPopupOpened(ContentProposalAdapter adapter) {\r
+ if(RVIModifier.this != null)\r
+ RVIModifier.this.deactivate();\r
+ }\r
+\r
+ @Override\r
+ public void proposalPopupClosed(ContentProposalAdapter adapter) {\r
+ if(RVIModifier.this != null)\r
+ RVIModifier.this.activate();\r
+ }\r
+ });\r
+\r
+ adapter.addContentProposalListener(new IContentProposalListener() {\r
+\r
+ @Override\r
+ public void proposalAccepted(IContentProposal proposal) {\r
+ if(RVIModifier.this.control != null && !RVIModifier.this.control.isDisposed())\r
+ RVIModifier.this.modifyText(new TrackedModifyEvent(RVIModifier.this.control, proposal.getContent()));\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
+ text = "/" + text.replace('.', '/');\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ graph.claimLiteral(resource, jfree.variableRVI, text, Bindings.STRING);\r
+ graph.deny(resource, jfree.variableFilter);\r
+ }\r
+ }\r
+\r
+ public void deactivate() {\r
+ active = false;\r
+ }\r
+\r
+ public void activate() {\r
+ active = true;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import java.util.Iterator;\r
+import java.util.LinkedHashMap;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedCombo;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ComboModifyListenerImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.utils.RunnableWithObject;\r
+import org.simantics.utils.datastructures.Triple;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+/**\r
+ * Composite for range controls in chart series properties\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class RangeComposite extends Composite implements Widget {\r
+\r
+ private Composite composite;\r
+ \r
+ public RangeComposite(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
+ super(parent, style);\r
+ support.register(this);\r
+ GridLayoutFactory.fillDefaults().spacing(3, 0).margins(3, 3).applyTo(this);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this);\r
+ composite = this;\r
+ }\r
+\r
+ @Override\r
+ public void setInput(final ISessionContext context, final Object input) {\r
+ if(composite == null || composite.isDisposed())\r
+ return;\r
+\r
+ final Resource series = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+\r
+ RangeHandlerFactory f;\r
+ try {\r
+ f = context.getSession().syncRequest(new Read<RangeHandlerFactory>() {\r
+ @Override\r
+ public RangeHandlerFactory perform(ReadGraph graph)\r
+ throws DatabaseException {\r
+ return graph.adapt(series, RangeHandlerFactory.class);\r
+ }\r
+ });\r
+ \r
+ } catch (DatabaseException e) {\r
+ //ExceptionUtils.logAndShowError("Insert something intelligent here.", e);\r
+ return;\r
+ }\r
+ \r
+ final RangeHandlerFactory factory = f;\r
+ \r
+ /*\r
+ * Listen to the enumerations assigned to the variable in this series.\r
+ * Listener is needed because the user can change the variableRVI for the series\r
+ * and that changes the options for range\r
+ */\r
+ context.getSession().asyncRequest(factory.getRequest(series), new Listener<LinkedHashMap<String, Resource>>() {\r
+\r
+ @Override\r
+ public void execute(LinkedHashMap<String, Resource> result) {\r
+ if(isDisposed())\r
+ return;\r
+\r
+ // Always modify the composite, even with null result\r
+ composite.getDisplay().asyncExec(new RunnableWithObject(result) {\r
+ @Override\r
+ public void run() {\r
+ if(composite == null || composite.isDisposed())\r
+ return;\r
+\r
+ // Remove all content (even with null result)\r
+ for(Control child : composite.getChildren())\r
+ child.dispose();\r
+\r
+ if(getObject() == null)\r
+ return;\r
+\r
+ // New widgetSupport for the combos\r
+ WidgetSupportImpl support = new WidgetSupportImpl();\r
+\r
+ Label label;\r
+ TrackedCombo combo;\r
+ LinkedHashMap<?, ?> result = (LinkedHashMap<?, ?>)getObject();\r
+ Iterator<?> iterator = result.keySet().iterator();\r
+ \r
+ // For each array index (enumeration), create a label and a combo \r
+ int index = 0;\r
+ while(iterator.hasNext()) {\r
+ Object key = iterator.next();\r
+ Composite c = new Composite(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(c);\r
+ GridLayoutFactory.fillDefaults().applyTo(c);\r
+ \r
+ label = new Label(c, SWT.NONE);\r
+ label.setText((String)key);\r
+ GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.END).applyTo(label);\r
+\r
+ combo = new TrackedCombo(c, support, SWT.READ_ONLY);\r
+ combo.setItemFactory(factory.getRangeItemFactory(index, (Resource)result.get(key)));\r
+ combo.setSelectionFactory(new RangeSelectionFactory(index));\r
+ combo.addModifyListener(new RangeModifyListener(index, result.size()));\r
+ GridDataFactory.fillDefaults().applyTo(combo.getWidget());\r
+ index++;\r
+ }\r
+ \r
+ // Set the width of the combo \r
+ GridLayout gl = (GridLayout)composite.getLayout();\r
+ gl.numColumns = index;\r
+ \r
+ // Set input for the combos\r
+ support.fireInput(context, input);\r
+ \r
+ /*\r
+ * Find out if this composite is located in a scrolled composite. \r
+ * If it is, resize the scrolled composite\r
+ */\r
+ Composite previousParent = composite.getParent();\r
+ for(int i = 0; i < 5; i++) {\r
+ if(previousParent.getParent() instanceof ScrolledComposite) {\r
+ previousParent.layout();\r
+ ScrolledComposite sc = (ScrolledComposite) previousParent.getParent();\r
+ Point size = previousParent.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ sc.setMinSize(size);\r
+ break;\r
+ }\r
+ previousParent = previousParent.getParent();\r
+ }\r
+ }\r
+ }); \r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return composite == null || composite.isDisposed();\r
+ }\r
+ });\r
+ }\r
+\r
+ /**\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class RangeSelectionFactory extends ReadFactoryImpl<Resource, String> {\r
+\r
+ int index;\r
+\r
+ /**\r
+ * \r
+ * @param index Index of the enumeration in the variable\r
+ */\r
+ public RangeSelectionFactory(int index) {\r
+ this.index = index;\r
+ }\r
+\r
+ public Object getIdentity(Object inputContents) {\r
+ return new Triple<Object, Integer, Class<?>>(inputContents, index, getClass());\r
+ }\r
+\r
+ @Override\r
+ public String perform(ReadGraph graph, Resource series) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ String[] filter = graph.getPossibleRelatedValue(series, jfree.variableFilter, Bindings.STRING_ARRAY);\r
+ \r
+ /*\r
+ * If no filter was found or the index is not applicable, return "All"\r
+ */\r
+ if(filter == null)\r
+ return "All";\r
+ else if(filter.length < index)\r
+ return "All";\r
+ else\r
+ return filter[index];\r
+ }\r
+\r
+ }\r
+\r
+\r
+\r
+ /**\r
+ * RangeModifyListener for modifying a range filter in chart series \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class RangeModifyListener extends ComboModifyListenerImpl<Resource> {\r
+ \r
+ private int index, size;\r
+\r
+ /**\r
+ * \r
+ * @param index Index of the modified range filter\r
+ * @param size Size of the whole filter (for situations where there is no filter)\r
+ */\r
+ public RangeModifyListener(int index, int size) {\r
+ this.index = index;\r
+ this.size = size;\r
+ }\r
+\r
+ @Override\r
+ public void applyText(WriteGraph graph, Resource series, String text) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ String[] filter = graph.getPossibleRelatedValue(series, jfree.variableFilter, Bindings.STRING_ARRAY);\r
+ \r
+ // If there is no filter, create a default filter with all indexes "All"\r
+ if(filter == null) {\r
+ filter = new String[size];\r
+ for(int i = 0; i < filter.length; i++) {\r
+ filter[i] = "All";\r
+ }\r
+ }\r
+ \r
+ // Modify the filter index\r
+ filter[index] = text;\r
+ graph.claimLiteral(series, jfree.variableFilter, filter, Bindings.STRING_ARRAY);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.LinkedHashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.request.Read;\r
+\r
+public interface RangeHandlerFactory {\r
+ \r
+ public Read<LinkedHashMap<String, Resource>> getRequest(final Resource series);\r
+ \r
+ public ReadFactoryImpl<Resource, Map<String, Object>> getRangeItemFactory(int index, Resource res);\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * TextFactory for chart title\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class TitleFactory extends ReadFactoryImpl<Resource, String> {\r
+ @Override\r
+ public String perform(ReadGraph graph, Resource chart) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Resource title = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.TextTitle));\r
+ if(title == null)\r
+ return "";\r
+ else {\r
+ String label = graph.getPossibleRelatedValue(title, l0.HasLabel, Bindings.STRING);\r
+ return label == null ? "" : label;\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListenerImpl;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * TitleModifier for chart title\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class TitleModifier extends TextModifyListenerImpl<Resource> {\r
+\r
+ @Override\r
+ public void applyText(WriteGraph graph, Resource chart, String text) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Resource title = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.TextTitle));\r
+ if(title == null) {\r
+ title = GraphUtils.create2(graph, jfree.TextTitle,\r
+ jfree.Title_position, jfree.Top);\r
+ }\r
+ graph.claimLiteral(title, l0.HasLabel, text);\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.core.runtime.ListenerList;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Spinner;\r
+import org.simantics.browsing.ui.common.ErrorLogger;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory;\r
+import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListener;\r
+import org.simantics.browsing.ui.swt.widgets.impl.TrackedModifyEvent;\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
+import org.simantics.utils.ui.SWTUtils;\r
+\r
+/**\r
+ * Class for implementing Widget behavior for SWT Spinner in Simantics.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class TrackedSpinner implements Widget {\r
+\r
+ private Spinner spinner;\r
+ private ListenerList modifyListeners;\r
+ private ReadFactory<?, Integer> selectionFactory;\r
+\r
+\r
+ public TrackedSpinner(Composite parent, WidgetSupport support, int style) {\r
+ spinner = new Spinner(parent, style);\r
+ support.register(this);\r
+ \r
+ // Add a ModifyListener that uses all listeners in modifyListeners -list\r
+ spinner.addModifyListener(new ModifyListener() {\r
+ \r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ if (modifyListeners != null) {\r
+ TrackedModifyEvent event = new TrackedModifyEvent(spinner, spinner.getText());\r
+ for (Object o : modifyListeners.getListeners()) {\r
+ ((TextModifyListener) o).modifyText(event);\r
+ }\r
+ } \r
+ }\r
+ });\r
+ }\r
+\r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+\r
+ // Update all modifyListeners\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 (selectionFactory != null) {\r
+ // Get a value for the spinner\r
+ selectionFactory.listen(context, input, new Listener<Integer>() {\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ ErrorLogger.defaultLogError(t);\r
+ }\r
+ @Override\r
+ public void execute(final Integer selection) {\r
+ SWTUtils.asyncExec(spinner, new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ if(isDisposed()) return;\r
+ spinner.setSelection(selection);\r
+ }\r
+ });\r
+ }\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return spinner.isDisposed();\r
+ }\r
+ });\r
+ }\r
+\r
+ }\r
+ \r
+ /**\r
+ * Set a selection factory for the spinner\r
+ * \r
+ * @param selectionFactory ReadFactory<?, Integer> SelectionFactory\r
+ */\r
+ public void setSelectionFactory(ReadFactory<?, Integer> selectionFactory) {\r
+ this.selectionFactory = selectionFactory;\r
+ }\r
+ \r
+ /**\r
+ * Add a modifyListener for the spinner\r
+ * @param listener TextModifyListener\r
+ */\r
+ public synchronized void addModifyListener(TextModifyListener listener) {\r
+ if (modifyListeners == null) {\r
+ modifyListeners = new ListenerList(ListenerList.IDENTITY);\r
+ }\r
+ modifyListeners.add(listener);\r
+ }\r
+\r
+ /**\r
+ * Remove modifyListener from the spinner\r
+ * \r
+ * @param listener TextModifyListener\r
+ */\r
+ public synchronized void removeModifyListener(TextModifyListener listener) {\r
+ if (modifyListeners == null)\r
+ return;\r
+ modifyListeners.remove(listener);\r
+ }\r
+\r
+ /**\r
+ * Get the SWT Spinner of this TrackedSpinner widget\r
+ * @return\r
+ */\r
+ public Spinner getWidget() {\r
+ return spinner;\r
+ }\r
+ \r
+ /**\r
+ * Set minimum value \r
+ * @param value int minimum value\r
+ */\r
+ public void setMinimum(int value) {\r
+ spinner.setMinimum(value);\r
+ }\r
+ \r
+ /**\r
+ * Set maximum value\r
+ * @param value int maximum value\r
+ */\r
+ public void setMaximum(int value) {\r
+ spinner.setMaximum(value);\r
+ }\r
+ \r
+ /**\r
+ * Sets the receiver's selection, minimum value, maximum value, digits, increment and page increment all at once. \r
+ * \r
+ * @param selection the new selection value\r
+ * @param minimum the new minimum value\r
+ * @param maximum the new maximum value\r
+ * @param digits the new digits value\r
+ * @param increment the new increment value\r
+ * @param pageIncrement the new pageIncrement value\r
+ */\r
+ public void setValues(int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {\r
+ spinner.setValues(selection, minimum, maximum, digits, increment, pageIncrement);\r
+ }\r
+ \r
+ /**\r
+ * Sets the selection, which is the receiver's position, to the argument.\r
+ * If the argument is not within the range specified by minimum and maximum, \r
+ * it will be adjusted to fall within this range.\r
+ * \r
+ * @param value\r
+ */\r
+ public void setSelection(int value) {\r
+ spinner.setSelection(value);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.dialogs.IInputValidator;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\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.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Variable exists validator for tracked text widgets. \r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class VariableExistsValidator implements IInputValidator, Widget {\r
+\r
+ private String[] names;\r
+ private TrackedText text;\r
+ private boolean allowEmpty;\r
+ \r
+ /**\r
+ * Validate against all variables\r
+ * \r
+ * Do not allow empty input\r
+ * @param support WidgetSupport\r
+ * @param text Text widget\r
+ */\r
+ public VariableExistsValidator(WidgetSupport support, TrackedText text) {\r
+ this(support, text, false);\r
+ }\r
+ \r
+ /**\r
+ * Validate against all variables\r
+ * \r
+ * @param support WidgetSupport\r
+ * @param text Text widget\r
+ * @param allowEmpty Allow empty input text\r
+ */\r
+ public VariableExistsValidator(WidgetSupport support, TrackedText text, boolean allowEmpty) {\r
+ support.register(this);\r
+ names = new String[] {"time"};\r
+ this.text = text;\r
+ this.allowEmpty = allowEmpty;\r
+ }\r
+ \r
+ /**\r
+ * Returns null if there is a variable named newText in the model\r
+ */\r
+ @Override\r
+ public String isValid(String newText) {\r
+ if(newText == null || newText.isEmpty()) {\r
+ if(allowEmpty)\r
+ return null;\r
+ else\r
+ return "Empty name not allowed";\r
+ }\r
+ \r
+ synchronized (names) {\r
+ for(String s : names) {\r
+ if(newText.equals(s))\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ return "Not a valid variable name";\r
+ }\r
+\r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ final Resource resource = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ \r
+ if(resource == null) {\r
+ names = new String[] {"time"};\r
+ return;\r
+ }\r
+ \r
+ Resource model = null;\r
+ try {\r
+ /* Find the model resource. It can be found with PartOf \r
+ relations from series resource in a chart */\r
+ model = context.getSession().syncRequest(new Read<Resource>() {\r
+\r
+ @Override\r
+ public Resource perform(ReadGraph graph) throws DatabaseException {\r
+ Resource r = resource;\r
+ while((r = graph.getPossibleObject(r, Layer0.getInstance(graph).PartOf)) != null) {\r
+ if(graph.isInstanceOf(r, SimulationResource.getInstance(graph).Model))\r
+ return r;\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ });\r
+ \r
+ if(model != null) {\r
+ // Find all variables and set them as the reference for isValid(String)\r
+ SimanticsUI.getSession().asyncRequest(\r
+ new AllVariablesOfModel(model)\r
+ , new Listener<String[]>() {\r
+\r
+ @Override\r
+ public void execute(String[] result) {\r
+ names = result;\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return text.isDisposed();\r
+ }\r
+\r
+ }); \r
+ }\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;\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.Resource;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Provides all variables a model contains\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class VariableProposalProvider extends SimpleContentProposalProvider implements Widget {\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
+ * \r
+ * @param control Control that is using this provider\r
+ * @param resource A resource that is part of a model\r
+ */\r
+ public VariableProposalProvider(final Control control, WidgetSupport support) {\r
+ super(new String [] {});\r
+ support.register(this);\r
+ this.control = control;\r
+ }\r
+\r
+ private Resource resource;\r
+ private Control control;\r
+ \r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+\r
+ final Resource resource = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ if(resource == null)\r
+ return;\r
+ this.resource = resource;\r
+ \r
+ SimanticsUI.getSession().asyncRequest(\r
+ new AllVariablesOfModel(resource)\r
+ , new Listener<String[]>() {\r
+\r
+ @Override\r
+ public void execute(String[] result) {\r
+ setProposals(result);\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ @Override\r
+ public boolean isDisposed() {\r
+ return control == null || \r
+ control.isDisposed() || \r
+ !resource.equals(VariableProposalProvider.this.resource);\r
+ }\r
+\r
+ }); \r
+ \r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.bar;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Spinner;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListener;\r
+import org.simantics.browsing.ui.swt.widgets.impl.TrackedModifyEvent;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.request.ReadRequest;\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.jfreechart.chart.properties.AxisHidePropertyComposite;\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.LabelPropertyTabContributor;\r
+import org.simantics.jfreechart.chart.properties.TrackedSpinner;\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.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Tab for bar chart axis properties\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BarAxisTab extends LabelPropertyTabContributor implements Widget {\r
+\r
+ private TrackedSpinner angle;\r
+ private Integer angleInt = null;\r
+ private WidgetSupportImpl domainAxisSupport = new WidgetSupportImpl();\r
+ private WidgetSupportImpl rangeAxisSupport = new WidgetSupportImpl();\r
+ private TrackedText rangelabel, rangemin, rangemax;\r
+ private ScrolledComposite sc;\r
+ private Composite composite;\r
+\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) {\r
+ support.register(this);\r
+\r
+ // Scrolled composite containing all of the properties in this tab\r
+ sc = new ScrolledComposite(body, SWT.NONE | SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(sc);\r
+ sc.setExpandHorizontal(true);\r
+ sc.setExpandVertical(true);\r
+\r
+ composite = new Composite(sc, SWT.NONE);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+ // Domain Axis properties\r
+ Group domainGroup = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(2, 1).grab(true, false).applyTo(domainGroup);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(domainGroup);\r
+ domainGroup.setText("Domain axis");\r
+\r
+ // Label for x-axis\r
+ Label label = new Label(domainGroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Label:");\r
+\r
+ rangelabel = new TrackedText(domainGroup, domainAxisSupport, SWT.BORDER);\r
+ rangelabel.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+ rangelabel.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ rangelabel.setColorProvider(new JFreeChartPropertyColorProvider(rangelabel.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(rangelabel.getWidget());\r
+\r
+ Composite axisHide = new AxisHidePropertyComposite(domainGroup, context, domainAxisSupport, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(1, 3).applyTo(axisHide);\r
+\r
+ Label angleLabel = new Label(domainGroup, SWT.NONE);\r
+ angleLabel.setText("Label angle:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(angleLabel);\r
+\r
+ Composite angleComposite = new Composite(domainGroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(angleComposite);\r
+ GridLayoutFactory.fillDefaults().applyTo(angleComposite);\r
+ angle = new TrackedSpinner(angleComposite, domainAxisSupport, SWT.BORDER);\r
+ angle.setSelectionFactory(new AngleSelectionFactory());\r
+ angle.addModifyListener(new AngleModifyListener());\r
+ angle.setMinimum(0);\r
+ angle.setMaximum(90);\r
+ angle.getWidget().setIncrement(5);\r
+ GridDataFactory.fillDefaults().applyTo(angle.getWidget());\r
+\r
+ // Domain Color\r
+ label = new Label(domainGroup, SWT.NONE);\r
+ label.setText("Color:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+ Composite colorPicker = new ColorPicker(domainGroup, context, domainAxisSupport, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(colorPicker);\r
+\r
+ domainGroup.layout();\r
+\r
+ // Range Axis properties\r
+ Group rangeGroup = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(2, 1).grab(true, false).applyTo(rangeGroup);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(rangeGroup);\r
+ rangeGroup.setText("Range axis");\r
+\r
+ // Label for range axis\r
+ label = new Label(rangeGroup, SWT.NONE);\r
+ label.setText("Label:");\r
+ label.setAlignment(SWT.RIGHT);\r
+ GridDataFactory.fillDefaults().hint(angleLabel.getBounds().width, SWT.DEFAULT).align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+ rangelabel = new TrackedText(rangeGroup, rangeAxisSupport, SWT.BORDER);\r
+ rangelabel.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+ rangelabel.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ rangelabel.setColorProvider(new JFreeChartPropertyColorProvider(rangelabel.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(rangelabel.getWidget());\r
+\r
+ axisHide = new AxisHidePropertyComposite(rangeGroup, context, rangeAxisSupport, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(1, 4).applyTo(axisHide);\r
+\r
+ // Min and max values for range axis\r
+ label = new Label(rangeGroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Min:");\r
+\r
+ Composite minmax = new Composite(rangeGroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(minmax);\r
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(minmax);\r
+ rangemin = new TrackedText(minmax, rangeAxisSupport, SWT.BORDER);\r
+ rangemin.setColorProvider(new JFreeChartPropertyColorProvider(rangemin.getResourceManager()));\r
+ rangemin.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Axis_min));\r
+ rangemin.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Axis_min));\r
+ rangemin.setInputValidator(new DoubleValidator(true));\r
+\r
+ label = new Label(minmax, SWT.NONE);\r
+ label.setText("Max:");\r
+ rangemax = new TrackedText(minmax, rangeAxisSupport, SWT.BORDER);\r
+ rangemax.setColorProvider(new JFreeChartPropertyColorProvider(rangemax.getResourceManager()));\r
+ rangemax.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Axis_max));\r
+ rangemax.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Axis_max));\r
+ rangemax.setInputValidator(new DoubleValidator(true));\r
+\r
+ // Range Color\r
+ label = new Label(rangeGroup, SWT.NONE);\r
+ label.setText("Color:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+ colorPicker = new ColorPicker(rangeGroup, context, rangeAxisSupport, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(colorPicker);\r
+\r
+ // Resize scrolled composite\r
+ sc.setContent(composite);\r
+ Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ sc.setMinSize(size);\r
+ }\r
+\r
+ /**\r
+ * ModifyListener for the angle {@link TrackedSpinner}\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class AngleModifyListener implements TextModifyListener, Widget {\r
+\r
+ private ISessionContext context;\r
+ private Object lastInput = null;\r
+\r
+ @Override\r
+ public void modifyText(TrackedModifyEvent e) {\r
+ if(context == null)\r
+ return;\r
+\r
+ // Get the text value from spinner and associated resource (input)\r
+ Spinner spinner = (Spinner)e.getWidget();\r
+ final String textValue = spinner.getText();\r
+ final Object input = lastInput;\r
+\r
+ try {\r
+ context.getSession().syncRequest(new WriteRequest() {\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Resource domainAxis = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ try {\r
+ // usually reliable, since the spinner does all the checks\r
+ Double value = Double.parseDouble(textValue); \r
+ Double oldValue = graph.getPossibleRelatedValue(domainAxis, jfree.Axis_rotateLabelDegrees, Bindings.DOUBLE);\r
+ if(oldValue == null || !oldValue.equals(value)) {\r
+ graph.claimLiteral(domainAxis, jfree.Axis_rotateLabelDegrees, value, Bindings.DOUBLE);\r
+ angleInt = value.intValue();\r
+ }\r
+ } catch (NumberFormatException e) {\r
+ graph.claimLiteral(domainAxis, jfree.Axis_rotateLabelDegrees, 0.0, Bindings.DOUBLE);\r
+ angleInt = 0;\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 = parameter;\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Class for setting the value for angle {@link TrackedSpinner}\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class AngleSelectionFactory extends ReadFactoryImpl<Resource, Integer> {\r
+\r
+ @Override\r
+ public Integer perform(ReadGraph graph, Resource domainAxis) throws DatabaseException {\r
+ if(angleInt == null) {\r
+ Double angle = 0.0;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ if(domainAxis != null) {\r
+ Double value = graph.getPossibleRelatedValue(domainAxis, jfree.Axis_rotateLabelDegrees);\r
+ if(value != null)\r
+ angle = value;\r
+ }\r
+ return angle.intValue();\r
+ } else {\r
+ return angleInt;\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ public void setInput(final ISessionContext context, Object input) {\r
+ final Resource chart = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ if(chart == null)\r
+ return; \r
+\r
+ context.getSession().asyncRequest(new ReadRequest() {\r
+\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.Plot));\r
+ if(plot == null) return;\r
+ Resource rangeAxis = graph.getPossibleObject(plot, jfree.Plot_rangeAxis);\r
+ if(rangeAxis == null) return;\r
+ rangeAxisSupport.fireInput(context, new StructuredSelection(rangeAxis));\r
+\r
+ Resource domainAxis = graph.getPossibleObject(plot, jfree.Plot_domainAxis);\r
+ if(domainAxis == null) return;\r
+ domainAxisSupport.fireInput(context, new StructuredSelection(domainAxis));\r
+ }\r
+ });\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.bar;\r
+\r
+import java.util.LinkedHashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.layout.LayoutConstants;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedCombo;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ComboModifyListenerImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
+import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\r
+import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
+import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\r
+import org.simantics.jfreechart.chart.properties.LabelPropertyTabContributor;\r
+import org.simantics.jfreechart.chart.properties.TitleFactory;\r
+import org.simantics.jfreechart.chart.properties.TitleModifier;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\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
+\r
+\r
+/**\r
+ * General properties of a bar chart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BarGeneralPropertiesTab extends LabelPropertyTabContributor {\r
+\r
+ private ScrolledComposite sc;\r
+ private Composite composite;\r
+ private Button hgrid, htitle, hlegend;\r
+ private TrackedText name, title, time;\r
+ private TrackedCombo type;\r
+\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { \r
+ // Scrolled composite containing all of the properties in this tab\r
+ sc = new ScrolledComposite(body, SWT.NONE | SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+ GridLayoutFactory.fillDefaults().applyTo(sc);\r
+ sc.setExpandHorizontal(true);\r
+ sc.setExpandVertical(true);\r
+\r
+ composite = new Composite(sc, SWT.NONE);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+ // General properties\r
+ Group general = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(general);\r
+ general.setText("General");\r
+\r
+ // first column: labels\r
+ Composite labelColumn1 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn1);\r
+ GridLayoutFactory.fillDefaults().applyTo(labelColumn1);\r
+ \r
+ // second column: name and title\r
+ Composite propertyColumn1 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(propertyColumn1);\r
+ GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(propertyColumn1);\r
+ \r
+ // third column: labels\r
+ Composite labelColumn2 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn2);\r
+ GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(labelColumn2);\r
+ \r
+ // fourth column: type and time\r
+ Composite propertyColumn2 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(propertyColumn2);\r
+ GridLayoutFactory.fillDefaults().applyTo(propertyColumn2);\r
+ \r
+ // Name\r
+ Label label = new Label(labelColumn1, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Name:");\r
+\r
+ name = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+ name.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel));\r
+ name.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ name.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+ // Type\r
+ label = new Label(labelColumn2, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Type:");\r
+\r
+ type = new TrackedCombo(propertyColumn2, support, SWT.BORDER | SWT.READ_ONLY);\r
+ type.addModifyListener(new TypeModifyListener());\r
+ type.setItemFactory(new TypeItemFactory());\r
+ type.setSelectionFactory(new TypeSelectionFactory());\r
+ GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+\r
+ // Title (Which is different than name)\r
+ label = new Label(labelColumn1, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Title:");\r
+\r
+ title = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(title.getWidget());\r
+ title.setTextFactory(new TitleFactory());\r
+ title.addModifyListener(new TitleModifier());\r
+ title.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+ // Time\r
+ label = new Label(labelColumn2, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Time:");\r
+ \r
+ time = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn2, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(time.getWidget());\r
+ time.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Chart_time));\r
+ time.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Chart_time));\r
+ time.setInputValidator(new DoubleValidator(true));\r
+ time.setColorProvider(new JFreeChartPropertyColorProvider(time.getResourceManager()));\r
+ \r
+ // Group for hide options\r
+ Group hideGroup = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+ hideGroup.setText("Hide");\r
+\r
+ hgrid = new Button(hideGroup, support, SWT.CHECK);\r
+ hgrid.setText("Grid");\r
+ hgrid.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Plot_visibleGrid, true));\r
+ hgrid.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Plot_visibleGrid));\r
+ htitle = new Button(hideGroup, support, SWT.CHECK);\r
+ htitle.setText("Title");\r
+ htitle.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.TextTitle, JFreeChartResource.URIs.visible, true));\r
+ htitle.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.TextTitle, JFreeChartResource.URIs.visible));\r
+ hlegend = new Button(hideGroup, support, SWT.CHECK);\r
+ hlegend.setText("Legend");\r
+ hlegend.setSelectionFactory(new BooleanPropertyFactory(null, JFreeChartResource.URIs.Chart_visibleLegend, true));\r
+ hlegend.addSelectionListener(new BooleanSelectionListener(context, null, JFreeChartResource.URIs.Chart_visibleLegend));\r
+\r
+ \r
+ \r
+ // Resize scrolled composite\r
+ sc.setContent(composite);\r
+ Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ sc.setMinSize(size);\r
+ }\r
+\r
+ /**\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeSelectionFactory extends ReadFactoryImpl<Resource, String> {\r
+ @Override\r
+ public String perform(ReadGraph graph, Resource chart) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.CategoryPlot));\r
+ if(plot != null) {\r
+ Resource dataset = graph.syncRequest(new PossibleObjectWithType(plot, l0.ConsistsOf, jfree.CategoryDataset));\r
+\r
+ if(dataset != null) {\r
+ Resource renderer = graph.syncRequest(new PossibleObjectWithType(dataset, jfree.Dataset_renderer, jfree.Renderer));\r
+\r
+ if(renderer != null && graph.isInstanceOf(renderer, jfree.StackedBarRenderer))\r
+ return "Stacked";\r
+ }\r
+ }\r
+ return "Normal";\r
+ }\r
+ }\r
+\r
+ /**\r
+ * RangeItemFactory finds all inexes of a given enumeration \r
+ * and adds "Sum" and "All" to the returned indexes\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeItemFactory extends ReadFactoryImpl<Resource, Map<String, Object>> {\r
+ @Override\r
+ public Map<String, Object> perform(ReadGraph graph, Resource series) throws DatabaseException {\r
+ LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>();\r
+ result.put("Normal", "Normal");\r
+ result.put("Stacked", "Stacked");\r
+ return result;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * TypeModifyListener for modifying the type of a bar chart \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeModifyListener extends ComboModifyListenerImpl<Resource> {\r
+ @Override\r
+ public void applyText(WriteGraph graph, Resource chart, String text) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.CategoryPlot));\r
+ if(plot == null)\r
+ return;\r
+\r
+ Resource dataset = graph.syncRequest(new PossibleObjectWithType(plot, l0.ConsistsOf, jfree.CategoryDataset));\r
+ if(dataset == null)\r
+ return;\r
+\r
+ graph.deny(dataset, jfree.Dataset_renderer);\r
+\r
+ Resource renderer;\r
+ if(text.equals("Stacked"))\r
+ renderer = GraphUtils.create2(graph, jfree.StackedBarRenderer);\r
+ else\r
+ renderer = GraphUtils.create2(graph, jfree.BarRenderer);\r
+\r
+ graph.claim(dataset, jfree.Dataset_renderer, renderer);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.bar;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\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.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
+\r
+/**\r
+ * Composite for modifying properties of a series in a bar chart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BarSeriesPropertyComposite extends Composite {\r
+ \r
+ private TrackedText variable, label, time;\r
+ \r
+ public BarSeriesPropertyComposite(Composite parent, final ISessionContext context, WidgetSupport support, int style) {\r
+ super(parent, style);\r
+ \r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(this);\r
+\r
+ // Variable for the series\r
+ Label label = new Label(this, SWT.NONE);\r
+ label.setText("Variable:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+ variable = new TrackedText(this, support, SWT.BORDER);\r
+ variable.setTextFactory(new RVIFactory());\r
+ variable.addModifyListener(new RVIModifier(variable.getWidget(), support));\r
+ variable.setInputValidator(new VariableExistsValidator(support, variable));\r
+ variable.setColorProvider(new JFreeChartPropertyColorProvider(this.variable.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this.variable.getWidget());\r
+\r
+ // Range\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Range:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ \r
+ RangeComposite rangeComposite = new RangeComposite(this, context, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeComposite);\r
+ \r
+ \r
+ // Label to be displayed in chart for this series\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Label:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+ this.label = new TrackedText(this, support, SWT.BORDER);\r
+ this.label.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+ this.label.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ this.label.setColorProvider(new JFreeChartPropertyColorProvider(this.label.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this.label.getWidget());\r
+ \r
+ // Time\r
+ label = new Label(this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+ label.setText("Time:");\r
+ \r
+ Composite composite = new Composite(this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(composite);\r
+ GridLayoutFactory.fillDefaults().applyTo(composite);\r
+ \r
+ time = new org.simantics.browsing.ui.swt.widgets.TrackedText(composite, support, SWT.BORDER);\r
+ time.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Series_time));\r
+ time.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Series_time));\r
+ time.setInputValidator(new DoubleValidator(true));\r
+ time.setColorProvider(new JFreeChartPropertyColorProvider(time.getResourceManager()));\r
+ GridDataFactory.fillDefaults().applyTo(time.getWidget());\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.bar;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Tree;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.SingleSelectionInputSource;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.GraphExplorerComposite;\r
+import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.RemoverUtil;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.ChartUtils;\r
+import org.simantics.jfreechart.chart.properties.LabelPropertyTabContributor;\r
+import org.simantics.jfreechart.chart.properties.xyline.AxisAndVariablesExplorerComposite;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+import org.simantics.utils.datastructures.ArrayMap;\r
+\r
+/**\r
+ * Tab containing the series of a bar chart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BarSeriesTab extends LabelPropertyTabContributor implements Widget {\r
+\r
+ private GraphExplorerComposite explorer;\r
+ private ScrolledComposite propertyContainer;\r
+ private WidgetSupportImpl additionalSupport;\r
+ private Button add, remove;\r
+ private Resource chartResource;\r
+ private BarSeriesPropertyComposite spc;\r
+\r
+\r
+ public BarSeriesTab() {\r
+ additionalSupport = new WidgetSupportImpl();\r
+ }\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, final ISessionContext context, WidgetSupport support) {\r
+ support.register(this);\r
+ Composite composite = new Composite(body, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+ // (Ontology-based) GraphExplorer displaying variables in a bar chart\r
+ explorer = new AxisAndVariablesExplorerComposite(ArrayMap.keys(\r
+ "displaySelectors", "displayFilter").values(false, false), site, composite, support, SWT.FULL_SELECTION | SWT.BORDER | SWT.SINGLE);\r
+ explorer.setBrowseContexts(JFreeChartResource.URIs.BarSeriesBrowseContext);\r
+ explorer.setInputSource(new SingleSelectionInputSource(\r
+ Resource.class));\r
+ explorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning\r
+ explorer.finish();\r
+\r
+ ((Tree)explorer.getExplorerControl()).addSelectionListener(new SelectionAdapter() {\r
+ public void widgetSelected(SelectionEvent e) {\r
+ updateSelection(context);\r
+ }\r
+ });\r
+ GridDataFactory.fillDefaults().hint(250, SWT.DEFAULT).grab(false, true).applyTo(explorer);\r
+\r
+ // Scrolled composite for displaying properties of a selection in explorer\r
+ propertyContainer = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(propertyContainer);\r
+ GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+ propertyContainer.setExpandHorizontal(true);\r
+ propertyContainer.setExpandVertical(true);\r
+\r
+ // Buttons for adding and removing variables from a pie plot\r
+ Composite buttonComposite = new Composite(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+\r
+ add = new Button(buttonComposite, additionalSupport, SWT.NONE);\r
+ add.setText("Add");\r
+ add.addSelectionListener(new NewVariableListener(context));\r
+\r
+ remove = new Button(buttonComposite, additionalSupport, SWT.NONE);\r
+ remove.setText("Remove");\r
+ remove.addSelectionListener(new RemoveListener(context));\r
+ }\r
+\r
+ /**\r
+ * Updates the content of propertyContainer \r
+ * @param context\r
+ */\r
+ private void updateSelection(ISessionContext context) {\r
+ ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);\r
+ IStructuredSelection selection = (IStructuredSelection)selectionProvider.getSelection();\r
+ final Resource resource = AdaptionUtils.adaptToSingle(selection, Resource.class);\r
+ if(resource == null)\r
+ return;\r
+\r
+ for(Control child : propertyContainer.getChildren()) {\r
+ child.dispose();\r
+ }\r
+ spc = new BarSeriesPropertyComposite(propertyContainer, context, additionalSupport, SWT.NONE);\r
+\r
+ additionalSupport.fireInput(context, selection);\r
+\r
+ propertyContainer.setContent(spc);\r
+ Point size = spc.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ propertyContainer.setMinSize(size);\r
+ }\r
+\r
+ /**\r
+ * SelectionListener for adding a new variable to a plot\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class NewVariableListener extends SelectionListenerImpl<Resource> {\r
+\r
+ public NewVariableListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ Resource dataset = null;\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ if(input == null) {\r
+ if(chartResource != null) {\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chartResource, l0.ConsistsOf, jfree.Plot));\r
+ if(plot != null)\r
+ dataset = graph.syncRequest(new PossibleObjectWithType(plot, l0.ConsistsOf, jfree.Dataset));\r
+ }\r
+ } else {\r
+ if(graph.isInstanceOf(input, jfree.Series)) {\r
+ dataset = graph.getPossibleObject(input, l0.PartOf);\r
+ }\r
+ }\r
+\r
+ if(dataset != null) {\r
+ // Create series with no rvi\r
+ ChartUtils.createSeries(graph, dataset, null);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * SelectionListener for remove button\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class RemoveListener extends SelectionListenerImpl<Resource> {\r
+\r
+ public RemoveListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ /**\r
+ * Removes selected resource from explorer\r
+ */\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ if(input == null)\r
+ return; \r
+\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource list = null;\r
+ if(graph.isInstanceOf(input, jfree.Series)) {\r
+ // Remove series from dataset and seriesList\r
+ Resource dataset = graph.getPossibleObject(input, l0.PartOf);\r
+ if(dataset != null)\r
+ list = graph.getPossibleObject(dataset, jfree.Dataset_seriesList);\r
+\r
+ if(list != null)\r
+ ListUtils.removeElement(graph, list, input);\r
+ RemoverUtil.remove(graph, input);\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ chartResource = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.pie;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.layout.LayoutConstants;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
+import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\r
+import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
+import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\r
+import org.simantics.jfreechart.chart.properties.LabelPropertyTabContributor;\r
+import org.simantics.jfreechart.chart.properties.TitleFactory;\r
+import org.simantics.jfreechart.chart.properties.TitleModifier;\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
+\r
+/**\r
+ * General properties of a pie chart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class PieGeneralPropertiesTab extends LabelPropertyTabContributor {\r
+\r
+ private ScrolledComposite sc;\r
+ private Composite composite;\r
+ private Button htitle, hlegend, hlabels;\r
+ private TrackedText name, title, time;\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { \r
+ // Scrolled composite containing all of the properties in this tab\r
+ sc = new ScrolledComposite(body, SWT.NONE | SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+ GridLayoutFactory.fillDefaults().applyTo(sc);\r
+ sc.setExpandHorizontal(true);\r
+ sc.setExpandVertical(true);\r
+\r
+ composite = new Composite(sc, SWT.NONE);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+ // General properties\r
+ Group general = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(general);\r
+ general.setText("General");\r
+\r
+ // first column: labels\r
+ Composite labelColumn1 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn1);\r
+ GridLayoutFactory.fillDefaults().applyTo(labelColumn1);\r
+ \r
+ // first column: name and title\r
+ Composite propertyColumn1 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(propertyColumn1);\r
+ GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(propertyColumn1);\r
+ \r
+ // first column: labels\r
+ Composite labelColumn2 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn2);\r
+ GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(labelColumn2);\r
+ \r
+ // first column: type and time\r
+ Composite propertyColumn2 = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(propertyColumn2);\r
+ GridLayoutFactory.fillDefaults().applyTo(propertyColumn2);\r
+ \r
+ // Name\r
+ Label label = new Label(labelColumn1, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Name:");\r
+\r
+ name = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+ name.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel));\r
+ name.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ name.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+ // Dummy data for now. Waiting for different pie chart types\r
+ label = new Label(labelColumn2, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(label);\r
+ label.setText("");\r
+ \r
+ label = new Label(propertyColumn2, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).applyTo(label);\r
+ label.setText("");\r
+ \r
+ // Title (Which is different than name)\r
+ label = new Label(labelColumn1, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Title:");\r
+\r
+ title = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(title.getWidget());\r
+ title.setTextFactory(new TitleFactory());\r
+ title.addModifyListener(new TitleModifier());\r
+ title.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+ // Time\r
+ label = new Label(labelColumn2, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Time:");\r
+ \r
+ time = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn2, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(time.getWidget());\r
+ time.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Chart_time));\r
+ time.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Chart_time));\r
+ time.setInputValidator(new DoubleValidator(true));\r
+ time.setColorProvider(new JFreeChartPropertyColorProvider(time.getResourceManager()));\r
+\r
+ // Group for hide options\r
+ Group hideGroup = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+ hideGroup.setText("Hide");\r
+\r
+ htitle = new Button(hideGroup, support, SWT.CHECK);\r
+ htitle.setText("Title");\r
+ htitle.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.TextTitle, JFreeChartResource.URIs.visible, true));\r
+ htitle.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.TextTitle, JFreeChartResource.URIs.visible));\r
+ hlegend = new Button(hideGroup, support, SWT.CHECK);\r
+ hlegend.setText("Legend");\r
+ hlegend.setSelectionFactory(new BooleanPropertyFactory(null, JFreeChartResource.URIs.Chart_visibleLegend, true));\r
+ hlegend.addSelectionListener(new BooleanSelectionListener(context, null, JFreeChartResource.URIs.Chart_visibleLegend));\r
+ hlabels = new Button(hideGroup, support, SWT.CHECK);\r
+ hlabels.setText("Section labels");\r
+ hlabels.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Plot_visibleLabels, true));\r
+ hlabels.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Plot_visibleLabels));\r
+ \r
+ sc.setContent(composite);\r
+ Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ sc.setMinSize(size);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.pie;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
+import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\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.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
+\r
+/**\r
+ * Composite containing the properties of a series\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class PieSeriesPropertyComposite extends Composite {\r
+ \r
+ private TrackedText variable, label, time;\r
+ \r
+ public PieSeriesPropertyComposite(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
+ super(parent, style);\r
+ \r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(this);\r
+\r
+ // Variable for the series\r
+ Label label = new Label(this, SWT.NONE);\r
+ label.setText("Variable:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+ variable = new TrackedText(this, support, SWT.BORDER);\r
+ variable.setTextFactory(new RVIFactory());\r
+ variable.addModifyListener(new RVIModifier(variable.getWidget(), support));\r
+ variable.setInputValidator(new VariableExistsValidator(support, variable));\r
+ variable.setColorProvider(new JFreeChartPropertyColorProvider(this.variable.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this.variable.getWidget());\r
+\r
+ // Range\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Range:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ \r
+ RangeComposite rangeComposite = new RangeComposite(this, context, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeComposite);\r
+ \r
+ \r
+ // Label to be displayed in chart for this series\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Label:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+ this.label = new TrackedText(this, support, SWT.BORDER);\r
+ this.label.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+ this.label.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ this.label.setColorProvider(new JFreeChartPropertyColorProvider(this.label.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this.label.getWidget());\r
+\r
+ // Color\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Color:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+ Composite colorPicker = new ColorPicker(this, context, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(colorPicker);\r
+\r
+ // Time\r
+ label = new Label(this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+ label.setText("Time:");\r
+ \r
+ Composite composite = new Composite(this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(composite);\r
+ GridLayoutFactory.fillDefaults().applyTo(composite);\r
+ \r
+ time = new org.simantics.browsing.ui.swt.widgets.TrackedText(composite, support, SWT.BORDER);\r
+ time.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Series_time));\r
+ time.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Series_time));\r
+ time.setInputValidator(new DoubleValidator(true));\r
+ time.setColorProvider(new JFreeChartPropertyColorProvider(time.getResourceManager()));\r
+ GridDataFactory.fillDefaults().applyTo(time.getWidget());\r
+ \r
+ // Exploded\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+ \r
+ Button exploded = new Button(this, support, SWT.CHECK);\r
+ exploded.setText("Exploded");\r
+ exploded.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Series_exploded));\r
+ exploded.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.Series_exploded));\r
+ GridDataFactory.fillDefaults().applyTo(exploded.getWidget());\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.pie;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Tree;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.SingleSelectionInputSource;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.GraphExplorerComposite;\r
+import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.RemoverUtil;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.ChartUtils;\r
+import org.simantics.jfreechart.chart.properties.LabelPropertyTabContributor;\r
+import org.simantics.jfreechart.chart.properties.xyline.AxisAndVariablesExplorerComposite;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+import org.simantics.utils.datastructures.ArrayMap;\r
+\r
+/**\r
+ * Tab for modifying series in a pie chart configuration\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class PieSeriesTab extends LabelPropertyTabContributor implements Widget {\r
+\r
+ private GraphExplorerComposite explorer;\r
+ private ScrolledComposite propertyContainer;\r
+ private WidgetSupportImpl additionalSupport;\r
+ private Button add, remove;\r
+ private Resource chartResource;\r
+\r
+ public PieSeriesTab() {\r
+ additionalSupport = new WidgetSupportImpl();\r
+ }\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, final ISessionContext context, WidgetSupport support) {\r
+ support.register(this);\r
+ Composite composite = new Composite(body, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+ // (Ontology-based) GraphExplorer displaying variables of a pie chart\r
+ explorer = new AxisAndVariablesExplorerComposite(ArrayMap.keys(\r
+ "displaySelectors", "displayFilter").values(false, false), site, composite, support, SWT.FULL_SELECTION | SWT.BORDER | SWT.SINGLE);\r
+ explorer.setBrowseContexts(JFreeChartResource.URIs.PieSeriesBrowseContext);\r
+ explorer.setInputSource(new SingleSelectionInputSource(\r
+ Resource.class));\r
+ explorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning\r
+ explorer.finish();\r
+\r
+ ((Tree)explorer.getExplorerControl()).addSelectionListener(new SelectionAdapter() {\r
+ public void widgetSelected(SelectionEvent e) {\r
+ updateSelection(context);\r
+ }\r
+ });\r
+ GridDataFactory.fillDefaults().hint(250, SWT.DEFAULT).grab(false, true).applyTo(explorer);\r
+\r
+ // Scrolled composite for displaying properties of a selection in explorer\r
+ propertyContainer = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(propertyContainer);\r
+ GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+ propertyContainer.setExpandHorizontal(true);\r
+ propertyContainer.setExpandVertical(true);\r
+\r
+\r
+ // Buttons for adding and removing variables from a pie plot\r
+ Composite buttonComposite = new Composite(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+\r
+ add = new Button(buttonComposite, additionalSupport, SWT.NONE);\r
+ add.setText("Add");\r
+ add.addSelectionListener(new NewVariableListener(context));\r
+\r
+ remove = new Button(buttonComposite, additionalSupport, SWT.NONE);\r
+ remove.setText("Remove");\r
+ remove.addSelectionListener(new RemoveListener(context));\r
+ }\r
+\r
+ /**\r
+ * Updates the content of propertyContainer \r
+ * @param context\r
+ */\r
+ private void updateSelection(ISessionContext context) {\r
+ ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);\r
+ IStructuredSelection selection = (IStructuredSelection)selectionProvider.getSelection();\r
+ final Resource resource = AdaptionUtils.adaptToSingle(selection, Resource.class);\r
+ if(resource == null)\r
+ return;\r
+\r
+ for(Control child : propertyContainer.getChildren()) {\r
+ child.dispose();\r
+ }\r
+\r
+ PieSeriesPropertyComposite spc = new PieSeriesPropertyComposite(propertyContainer, context, additionalSupport, SWT.NONE);\r
+ propertyContainer.setContent(spc);\r
+ Point size = spc.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ propertyContainer.setMinSize(size);\r
+\r
+ additionalSupport.fireInput(context, selection);\r
+ }\r
+\r
+\r
+ /**\r
+ * SelectionListener for adding a new variable to a plot\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class NewVariableListener extends SelectionListenerImpl<Resource> {\r
+\r
+ public NewVariableListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource dataset = null;\r
+ if(input == null) {\r
+ if(chartResource != null) {\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chartResource, l0.ConsistsOf, jfree.Plot));\r
+ if(plot != null)\r
+ dataset = graph.syncRequest(new PossibleObjectWithType(plot, l0.ConsistsOf, jfree.Dataset));\r
+ }\r
+ } else {\r
+ if(graph.isInstanceOf(input, jfree.Series)) {\r
+ dataset = graph.getPossibleObject(input, l0.PartOf);\r
+ }\r
+ }\r
+ if(dataset != null) {\r
+ // Create series with no rvi\r
+ Resource series = ChartUtils.createSeries(graph, dataset, null);\r
+ graph.claimLiteral(series, jfree.Series_exploded, false);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * SelectionListener for remove button\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class RemoveListener extends SelectionListenerImpl<Resource> {\r
+\r
+ public RemoveListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ /**\r
+ * Removes selected resource from explorer\r
+ */\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ if(input == null)\r
+ return; \r
+\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource list = null;\r
+ if(graph.isInstanceOf(input, jfree.Series)) {\r
+ // Remove series from dataset and seriesList\r
+ Resource dataset = graph.getPossibleObject(input, l0.PartOf);\r
+ if(dataset != null)\r
+ list = graph.getPossibleObject(dataset, jfree.Dataset_seriesList);\r
+\r
+ if(list != null)\r
+ ListUtils.removeElement(graph, list, input);\r
+ RemoverUtil.remove(graph, input);\r
+ }\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ chartResource = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.xyline;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Map;\r
+\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.NodeContext;\r
+import org.simantics.browsing.ui.common.ErrorLogger;\r
+import org.simantics.browsing.ui.model.InvalidContribution;\r
+import org.simantics.browsing.ui.model.dnd.DndBrowseContext;\r
+import org.simantics.browsing.ui.swt.widgets.GraphExplorerComposite;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.Procedure;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.ui.SimanticsUI;\r
+\r
+/**\r
+ * ExplorerComposite allowing ontology-based DnD definitions. DnD Copied from {@link ModelBrowser2}\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class AxisAndVariablesExplorerComposite extends GraphExplorerComposite {\r
+\r
+ volatile DndBrowseContext dndBrowseContext;\r
+ \r
+ public AxisAndVariablesExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent,\r
+ WidgetSupport support, int style) {\r
+ super(args, site, parent, support, style);\r
+ \r
+ SimanticsUI.getSession().asyncRequest(new ReadRequest() {\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException { \r
+ ArrayList<Resource> browseContexts = new ArrayList<Resource>();\r
+ for (String uri : getBrowseContexts()) {\r
+ Resource browseContext = graph.getPossibleResource(uri);\r
+ if (browseContext != null)\r
+ browseContexts.add(browseContext);\r
+ }\r
+ try {\r
+ dndBrowseContext = DndBrowseContext.create(graph, browseContexts);\r
+ } catch (InvalidContribution e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ }\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ protected void handleDrop(final Object data, final NodeContext target) {\r
+ if (target == null)\r
+ return;\r
+\r
+ SimanticsUI.getSession().asyncRequest(new Read<Runnable>() {\r
+ @Override\r
+ public Runnable perform(ReadGraph graph) throws DatabaseException {\r
+ if (dndBrowseContext == null)\r
+ return null;\r
+ return dndBrowseContext.getAction(graph, target, data);\r
+ }\r
+ }, new Procedure<Runnable>() {\r
+ @Override\r
+ public void execute(Runnable result) {\r
+ if (result != null)\r
+ result.run();\r
+ }\r
+\r
+ @Override\r
+ public void exception(Throwable t) {\r
+ ErrorLogger.defaultLogError(t);\r
+ }\r
+ });\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.xyline;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.properties.AxisHidePropertyComposite;\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.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
+\r
+/**\r
+ * Composite for displaying axis properties in {@link XYLineAxisAndVariablesTab}\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class AxisPropertyComposite extends Composite {\r
+\r
+ TrackedText name, units, min, max;\r
+ Button tlabels, tmarks;\r
+ \r
+ public AxisPropertyComposite(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
+ super(parent, style);\r
+ \r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(this);\r
+ \r
+ // Label (units)\r
+ Label label = new Label(this, SWT.NONE);\r
+ label.setText("Label: ");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+ \r
+ units = new TrackedText(this, support, SWT.BORDER);\r
+ units.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, "")); // FIXME: Units \r
+ units.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel)); // FIXME: Units \r
+ units.setColorProvider(new JFreeChartPropertyColorProvider(units.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(units.getWidget());\r
+ \r
+ \r
+ // Minimum and maximum values\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Min:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+ Composite minmax = new Composite(this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(minmax);\r
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(minmax);\r
+ min = new TrackedText(minmax, support, SWT.BORDER);\r
+ min.setColorProvider(new JFreeChartPropertyColorProvider(min.getResourceManager()));\r
+ min.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Axis_min));\r
+ min.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Axis_min));\r
+ min.setInputValidator(new DoubleValidator(true));\r
+\r
+ label = new Label(minmax, SWT.NONE);\r
+ label.setText("Max:");\r
+ max = new TrackedText(minmax, support, SWT.BORDER);\r
+ max.setColorProvider(new JFreeChartPropertyColorProvider(max.getResourceManager()));\r
+ max.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Axis_max));\r
+ max.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Axis_max));\r
+ max.setInputValidator(new DoubleValidator(true));\r
+\r
+ \r
+ // Color\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Color:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ \r
+ Composite colorPicker = new ColorPicker(this, context, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(colorPicker);\r
+ \r
+ // Tick and label visibility\r
+ Composite c = new Composite(this, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(c);\r
+ GridLayoutFactory.fillDefaults().applyTo(c);\r
+ Composite axisHide = new AxisHidePropertyComposite(c, context, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(axisHide);\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.xyline;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Spinner;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListener;\r
+import org.simantics.browsing.ui.swt.widgets.impl.TrackedModifyEvent;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\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.jfreechart.chart.properties.ColorPicker;\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.TrackedSpinner;\r
+import org.simantics.jfreechart.chart.properties.VariableExistsValidator;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * Composite for displaying series properties in {@link XYLineAxisAndVariablesTab}\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class SeriesPropertyComposite extends Composite {\r
+\r
+ private TrackedText variable, label;\r
+ private TrackedSpinner width;\r
+\r
+ public SeriesPropertyComposite(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
+ super(parent, style);\r
+\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(this);\r
+\r
+ // Variable for the series\r
+ Label label = new Label(this, SWT.NONE);\r
+ label.setText("Variable:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+ variable = new TrackedText(this, support, SWT.BORDER);\r
+ variable.setTextFactory(new RVIFactory());\r
+ variable.addModifyListener(new RVIModifier(variable.getWidget(), support));\r
+ variable.setColorProvider(new JFreeChartPropertyColorProvider(this.variable.getResourceManager()));\r
+ variable.setInputValidator(new VariableExistsValidator(support, variable));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this.variable.getWidget());\r
+\r
+ // Range\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Range:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ \r
+ RangeComposite rangeComposite = new RangeComposite(this, context, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeComposite);\r
+ \r
+ // Label to be displayed in chart for this series \r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Label:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+ this.label = new TrackedText(this, support, SWT.BORDER);\r
+ this.label.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+ this.label.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ this.label.setColorProvider(new JFreeChartPropertyColorProvider(this.label.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(this.label.getWidget());\r
+\r
+ // Color\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Color:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+ Composite colorPicker = new ColorPicker(this, context, support, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(colorPicker);\r
+\r
+ // Line width\r
+ label = new Label(this, SWT.NONE);\r
+ label.setText("Line width:");\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+ width = new TrackedSpinner(this, support, SWT.BORDER);\r
+ width.setSelectionFactory(new WidthSelectionFactory());\r
+ width.addModifyListener(new WidthModifyListener());\r
+ width.setMinimum(1);\r
+ width.setMaximum(10);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * ModifyListener for the width {@link TrackedSpinner}\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class WidthModifyListener implements TextModifyListener, Widget {\r
+\r
+ private ISessionContext context;\r
+ private Object lastInput = null;\r
+\r
+ @Override\r
+ public void modifyText(TrackedModifyEvent e) {\r
+ if(context == null)\r
+ return;\r
+\r
+ // Get the text value from spinner and associated resource (input)\r
+ Spinner spinner = (Spinner)e.getWidget();\r
+ final String textValue = spinner.getText();\r
+ final Object input = lastInput;\r
+\r
+ try {\r
+ context.getSession().syncRequest(new WriteRequest() {\r
+\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ // Apply with (textValue) to the series (input)\r
+ Resource series = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ try {\r
+ // usually reliable, since the spinner does all the checks\r
+ Integer value = Integer.parseInt(textValue); \r
+ graph.claimLiteral(series, jfree.Series_lineWidth, value, Bindings.INTEGER);\r
+ } catch (NumberFormatException e) {\r
+ e.printStackTrace();\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 = parameter;\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Class for setting the value for width {@link TrackedSpinner}\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class WidthSelectionFactory extends ReadFactoryImpl<Resource, Integer> {\r
+\r
+ @Override\r
+ public Integer perform(ReadGraph graph, Resource axis) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Integer width = graph.getPossibleRelatedValue(axis, jfree.Series_lineWidth);\r
+ if(width == null)\r
+ // Default width == 1\r
+ width = 1;\r
+ return width;\r
+ }\r
+\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.xyline;\r
+\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Tree;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.NodeContext;\r
+import org.simantics.browsing.ui.swt.SingleSelectionInputSource;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.GraphExplorerComposite;\r
+import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.utils.ListUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.RemoverUtil;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.jfreechart.chart.ChartUtils;\r
+import org.simantics.jfreechart.chart.properties.LabelPropertyTabContributor;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.AdaptionUtils;\r
+import org.simantics.utils.datastructures.ArrayMap;\r
+\r
+/**\r
+ * PropertyTab displaying properties of axis and variables of a chart\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class XYLineAxisAndVariablesTab extends LabelPropertyTabContributor {\r
+\r
+ private GraphExplorerComposite explorer;\r
+ private ScrolledComposite propertyContainer;\r
+ private Button addAxis, addVariable, remove;\r
+ private WidgetSupportImpl additionalSupport;\r
+\r
+ public XYLineAxisAndVariablesTab() {\r
+ additionalSupport = new WidgetSupportImpl();\r
+ }\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, final ISessionContext context, WidgetSupport support) {\r
+ Composite composite = new Composite(body, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+ // (Ontology-based) GraphExplorer displaying range axis and variables mapped to those axis\r
+ explorer = new AxisAndVariablesExplorerComposite(ArrayMap.keys(\r
+ "displaySelectors", "displayFilter").values(false, false), site, composite, support, SWT.FULL_SELECTION | SWT.BORDER | SWT.SINGLE);\r
+ explorer.setBrowseContexts(JFreeChartResource.URIs.ChartAxisAndVariablesBrowseContext);\r
+ explorer.setInputSource(new SingleSelectionInputSource(\r
+ Resource.class));\r
+ explorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning\r
+ explorer.finish();\r
+\r
+ ((Tree)explorer.getExplorerControl()).addSelectionListener(new SelectionAdapter() {\r
+ public void widgetSelected(SelectionEvent e) {\r
+ updateSelection(context);\r
+ }\r
+ });\r
+ GridDataFactory.fillDefaults().hint(250, SWT.DEFAULT).grab(false, true).applyTo(explorer);\r
+\r
+ // Scrolled composite for displaying properties of a selection in explorer\r
+ propertyContainer = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(propertyContainer);\r
+ GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+ propertyContainer.setExpandHorizontal(true);\r
+ propertyContainer.setExpandVertical(true);\r
+\r
+ // Buttons for adding axis and variables and removing selected items from explorer\r
+ Composite buttonComposite = new Composite(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+\r
+ addAxis = new Button(buttonComposite, support, SWT.NONE);\r
+ addAxis.setText("Add axis");\r
+ addAxis.addSelectionListener(new NewAxisListener(context));\r
+\r
+ addVariable = new Button(buttonComposite, additionalSupport, SWT.NONE);\r
+ addVariable.setText("Add variable");\r
+ addVariable.addSelectionListener(new NewVariableListener(context));\r
+\r
+ remove = new Button(buttonComposite, additionalSupport, SWT.NONE);\r
+ remove.setText("Remove");\r
+ remove.addSelectionListener(new RemoveListener(context));\r
+ }\r
+\r
+ /**\r
+ * Updates the content of propertyContainer \r
+ * @param context\r
+ */\r
+ private void updateSelection(ISessionContext context) {\r
+ ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);\r
+ IStructuredSelection selection = (IStructuredSelection)selectionProvider.getSelection();\r
+ final Resource resource = AdaptionUtils.adaptToSingle(selection, Resource.class);\r
+ if(resource == null)\r
+ return;\r
+\r
+ // Get the type of the selected node (axis or series)\r
+ String typeUri = null;\r
+ try {\r
+ typeUri = SimanticsUI.getSession().syncRequest(new Read<String>() {\r
+\r
+ @Override\r
+ public String perform(ReadGraph graph) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ if(graph.isInstanceOf(resource, jfree.Axis))\r
+ return graph.getURI(jfree.Axis);\r
+ else if (graph.isInstanceOf(resource, jfree.Series))\r
+ return graph.getURI(jfree.Series);\r
+ return null;\r
+ }\r
+\r
+ });\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ // Create a PropertyComposite for the selected node\r
+ if(typeUri != null) {\r
+\r
+ for(Control child : propertyContainer.getChildren()) {\r
+ child.dispose();\r
+ }\r
+\r
+ if(typeUri.equals(JFreeChartResource.URIs.Axis)) {\r
+ AxisPropertyComposite apc = new AxisPropertyComposite(propertyContainer, context, additionalSupport, SWT.NONE);\r
+ propertyContainer.setContent(apc);\r
+ Point size = apc.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ propertyContainer.setMinSize(size);\r
+ } else if(typeUri.equals(JFreeChartResource.URIs.Series)) {\r
+ SeriesPropertyComposite spc = new SeriesPropertyComposite(propertyContainer, context, additionalSupport, SWT.NONE);\r
+ propertyContainer.setContent(spc);\r
+ Point size = spc.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ propertyContainer.setMinSize(size);\r
+ }\r
+ }\r
+\r
+ additionalSupport.fireInput(context, selection);\r
+ }\r
+\r
+ /**\r
+ * SelectionListener for adding a new range axis to a plot\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class NewAxisListener extends SelectionListenerImpl<Resource> {\r
+\r
+ public NewAxisListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource chart) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.Plot));\r
+ if(plot != null) {\r
+ Resource rangeAxis = ChartUtils.createNumberRangeAxis(graph, plot);\r
+ if(rangeAxis != null) {\r
+ Resource domainAxis = graph.getPossibleObject(plot, jfree.Plot_domainAxis);\r
+ ChartUtils.createXYDataset(graph, plot, domainAxis, rangeAxis);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * SelectionListener for adding a new variable to a plot\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class NewVariableListener extends SelectionListenerImpl<Resource> {\r
+\r
+ public NewVariableListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ NodeContext nc = explorer.getExplorer().getRoot();\r
+ if(nc == null)\r
+ return;\r
+ \r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ \r
+ if(input == null) {\r
+ Resource chart = AdaptionUtils.adaptToSingle(nc, Resource.class);\r
+ if(chart == null) return;\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.Plot));\r
+ if(plot == null) return;\r
+ Resource rangelist = graph.getPossibleObject(plot, jfree.Plot_rangeAxisList);\r
+ if(rangelist == null) return;\r
+ List<Resource> list = ListUtils.toList(graph, rangelist);\r
+ if(list == null || list.isEmpty()) return;\r
+ input = list.get(0);\r
+ }\r
+ \r
+ Resource dataset;\r
+ if(graph.isInstanceOf(input, jfree.Series)) {\r
+ // Selected resource is series. Add to same dataset\r
+ dataset = graph.getPossibleObject(input, l0.PartOf);\r
+ } else {\r
+ // Selected resource is axis. Find the dataset it is mapped to or create dataset if not created already\r
+ dataset = graph.getPossibleObject(input, jfree.Dataset_mapToRangeAxis_Inverse);\r
+ if(dataset == null) {\r
+ Resource plot = graph.getPossibleObject(input, l0.PartOf);\r
+ if(plot == null) return;\r
+ Resource domainAxis = graph.getPossibleObject(plot, jfree.Plot_domainAxis);\r
+ if(domainAxis == null) return;\r
+ ChartUtils.createXYDataset(graph, plot, domainAxis, input);\r
+ }\r
+ }\r
+\r
+ if(dataset != null) {\r
+ // Create series with no rvi\r
+ ChartUtils.createSeries(graph, dataset, null);\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * SelectionListener for remove button\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class RemoveListener extends SelectionListenerImpl<Resource> {\r
+\r
+ public RemoveListener(ISessionContext context) {\r
+ super(context);\r
+ }\r
+\r
+ /**\r
+ * Removes selected resource from explorer\r
+ */\r
+ @Override\r
+ public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+ if(input == null)\r
+ return; \r
+\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource list = null;\r
+ if(graph.isInstanceOf(input, jfree.Series)) {\r
+ // Remove series from dataset and seriesList\r
+ Resource dataset = graph.getPossibleObject(input, l0.PartOf);\r
+ if(dataset != null)\r
+ list = graph.getPossibleObject(dataset, jfree.Dataset_seriesList);\r
+ } else {\r
+ // Remove associated dataset\r
+ Resource dataset = graph.getPossibleObject(input, jfree.Dataset_mapToRangeAxis_Inverse);\r
+ if(dataset != null) {\r
+ graph.deny(dataset, jfree.Dataset_mapToDomainAxis);\r
+ graph.deny(dataset, jfree.Dataset_mapToRangeAxis);\r
+ RemoverUtil.remove(graph, dataset);\r
+ }\r
+\r
+ // Remove axis from plot and rangeAxisList\r
+ Resource plot = graph.getPossibleObject(input, l0.PartOf);\r
+ if(plot != null)\r
+ list = graph.getPossibleObject(plot, jfree.Plot_rangeAxisList);\r
+ }\r
+ if(list != null)\r
+ ListUtils.removeElement(graph, list, input);\r
+ RemoverUtil.remove(graph, input);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
+ * 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.jfreechart.chart.properties.xyline;\r
+\r
+import java.util.Collection;\r
+import java.util.LinkedHashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.widgets.Button;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedCombo;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ComboModifyListenerImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.jfreechart.chart.properties.AxisHidePropertyComposite;\r
+import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
+import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\r
+import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
+import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\r
+import org.simantics.jfreechart.chart.properties.LabelPropertyTabContributor;\r
+import org.simantics.jfreechart.chart.properties.RVIFactory;\r
+import org.simantics.jfreechart.chart.properties.RVIModifier;\r
+import org.simantics.jfreechart.chart.properties.TitleFactory;\r
+import org.simantics.jfreechart.chart.properties.TitleModifier;\r
+import org.simantics.jfreechart.chart.properties.VariableExistsValidator;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\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.ui.utils.AdaptionUtils;\r
+\r
+/**\r
+ * PropertyTab displaying general properties and x-axis properties of a chart\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class XYLineGeneralPropertiesTab extends LabelPropertyTabContributor implements Widget {\r
+\r
+ private ScrolledComposite sc;\r
+ private Composite composite;\r
+ private TrackedText name, title, xlabel, xvariable, xmin, xmax;\r
+ private TrackedCombo type;\r
+ private Button hgrid, htitle, hlegend;\r
+ private WidgetSupportImpl domainAxisSupport = new WidgetSupportImpl();\r
+\r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { \r
+ support.register(this);\r
+\r
+ // Scrolled composite containing all of the properties in this tab\r
+ sc = new ScrolledComposite(body, SWT.NONE | SWT.H_SCROLL | SWT.V_SCROLL);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+ GridLayoutFactory.fillDefaults().applyTo(sc);\r
+ sc.setExpandHorizontal(true);\r
+ sc.setExpandVertical(true);\r
+\r
+ composite = new Composite(sc, SWT.NONE);\r
+ GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+ // General properties\r
+ Group general = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(general);\r
+ general.setText("General");\r
+\r
+ // Name\r
+ Label nameLabel = new Label(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(nameLabel);\r
+ nameLabel.setText("Name:");\r
+ nameLabel.setAlignment(SWT.RIGHT);\r
+\r
+ Composite c = new Composite(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(c);\r
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(c);\r
+\r
+ name = new org.simantics.browsing.ui.swt.widgets.TrackedText(c, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+ name.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel));\r
+ name.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ name.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+ // Type\r
+ Label label = new Label(c, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Type:");\r
+\r
+ type = new TrackedCombo(c, support, SWT.BORDER | SWT.READ_ONLY);\r
+ type.addModifyListener(new TypeModifyListener());\r
+ type.setItemFactory(new TypeItemFactory());\r
+ type.setSelectionFactory(new TypeSelectionFactory());\r
+ GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+\r
+ // Title (Which is different than name)\r
+ label = new Label(general, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Title:");\r
+\r
+ title = new org.simantics.browsing.ui.swt.widgets.TrackedText(general, support, SWT.BORDER);\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(title.getWidget());\r
+ title.setTextFactory(new TitleFactory());\r
+ title.addModifyListener(new TitleModifier());\r
+ title.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+ // Group for hide options\r
+ Group hideGroup = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+ hideGroup.setText("Hide");\r
+\r
+ hgrid = new Button(hideGroup, support, SWT.CHECK);\r
+ hgrid.setText("Grid");\r
+ hgrid.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Plot_visibleGrid, true));\r
+ hgrid.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Plot_visibleGrid));\r
+ htitle = new Button(hideGroup, support, SWT.CHECK);\r
+ htitle.setText("Title");\r
+ htitle.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.TextTitle, JFreeChartResource.URIs.visible, true));\r
+ htitle.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.TextTitle, JFreeChartResource.URIs.visible));\r
+ hlegend = new Button(hideGroup, support, SWT.CHECK);\r
+ hlegend.setText("Legend");\r
+ hlegend.setSelectionFactory(new BooleanPropertyFactory(null, JFreeChartResource.URIs.Chart_visibleLegend, true));\r
+ hlegend.addSelectionListener(new BooleanSelectionListener(context, null, JFreeChartResource.URIs.Chart_visibleLegend));\r
+\r
+\r
+ // X-Axis properties\r
+ Group xgroup = new Group(composite, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(2, 1).grab(true, false).applyTo(xgroup);\r
+ GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(xgroup);\r
+ xgroup.setText("X-axis");\r
+\r
+ // Variable for x-axis (default: empty == time)\r
+ Label xVariableLabel = new Label(xgroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(xVariableLabel);\r
+ xVariableLabel.setText("Variable:");\r
+\r
+ xvariable = new TrackedText(xgroup, domainAxisSupport, SWT.BORDER);\r
+ xvariable.setTextFactory(new RVIFactory());\r
+ xvariable.addModifyListener(new RVIModifier(xvariable.getWidget(), domainAxisSupport));\r
+ xvariable.setColorProvider(new JFreeChartPropertyColorProvider(xvariable.getResourceManager()));\r
+ xvariable.setInputValidator(new VariableExistsValidator(support, xvariable, true));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(xvariable.getWidget());\r
+ \r
+ Composite axisHide = new AxisHidePropertyComposite(xgroup, context, domainAxisSupport, SWT.NONE);\r
+ GridDataFactory.fillDefaults().span(1, 3).applyTo(axisHide);\r
+\r
+ // Label for x-axis\r
+ label = new Label(xgroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Label:");\r
+\r
+ xlabel = new TrackedText(xgroup, domainAxisSupport, SWT.BORDER);\r
+ xlabel.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+ xlabel.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+ xlabel.setColorProvider(new JFreeChartPropertyColorProvider(xlabel.getResourceManager()));\r
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(xlabel.getWidget());\r
+\r
+ // Min and max values for x-axis\r
+ label = new Label(xgroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+ label.setText("Min:");\r
+\r
+ Composite minmax = new Composite(xgroup, SWT.NONE);\r
+ GridDataFactory.fillDefaults().applyTo(minmax);\r
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(minmax);\r
+ xmin = new TrackedText(minmax, domainAxisSupport, SWT.BORDER);\r
+ xmin.setColorProvider(new JFreeChartPropertyColorProvider(xmin.getResourceManager()));\r
+ xmin.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Axis_min));\r
+ xmin.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Axis_min));\r
+ xmin.setInputValidator(new DoubleValidator(true));\r
+\r
+ label = new Label(minmax, SWT.NONE);\r
+ label.setText("Max:");\r
+ xmax = new TrackedText(minmax, domainAxisSupport, SWT.BORDER);\r
+ xmax.setColorProvider(new JFreeChartPropertyColorProvider(xmax.getResourceManager()));\r
+ xmax.setTextFactory(new DoublePropertyFactory(JFreeChartResource.URIs.Axis_max));\r
+ xmax.addModifyListener(new DoublePropertyModifier(context, JFreeChartResource.URIs.Axis_max));\r
+ xmax.setInputValidator(new DoubleValidator(true));\r
+\r
+ // Set the same width to both label rows\r
+ composite.layout();\r
+ GridDataFactory.fillDefaults().hint(xVariableLabel.getBounds().width, SWT.DEFAULT).align(SWT.END, SWT.CENTER).applyTo(nameLabel);\r
+ \r
+ sc.setContent(composite);\r
+ Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+ sc.setMinSize(size);\r
+ }\r
+\r
+ @Override\r
+ public void setInput(final ISessionContext context, Object input) {\r
+ final Resource chart = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ if(chart == null)\r
+ return; \r
+\r
+ context.getSession().asyncRequest(new ReadRequest() {\r
+\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.Plot));\r
+ if(plot == null) return;\r
+ Resource domainAxis = graph.getPossibleObject(plot, jfree.Plot_domainAxis);\r
+ if(domainAxis == null) return;\r
+ domainAxisSupport.fireInput(context, new StructuredSelection(domainAxis));\r
+ }\r
+ });\r
+ }\r
+ \r
+ /**\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeSelectionFactory extends ReadFactoryImpl<Resource, String> {\r
+ @Override\r
+ public String perform(ReadGraph graph, Resource chart) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.XYPlot));\r
+ if(plot != null) {\r
+ Collection<Resource> datasets = graph.syncRequest(new ObjectsWithType(plot, l0.ConsistsOf, jfree.XYDataset));\r
+ if(!datasets.isEmpty()) {\r
+ Resource dataset = datasets.iterator().next();\r
+ if(dataset != null) {\r
+ Resource renderer = graph.syncRequest(new PossibleObjectWithType(dataset, jfree.Dataset_renderer, jfree.Renderer));\r
+ if(renderer != null && graph.isInstanceOf(renderer, jfree.XYAreaRenderer))\r
+ return "Area";\r
+ }\r
+ }\r
+ }\r
+ return "Line";\r
+ }\r
+ }\r
+\r
+ /**\r
+ * RangeItemFactory finds all inexes of a given enumeration \r
+ * and adds "Sum" and "All" to the returned indexes\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeItemFactory extends ReadFactoryImpl<Resource, Map<String, Object>> {\r
+ @Override\r
+ public Map<String, Object> perform(ReadGraph graph, Resource series) throws DatabaseException {\r
+ LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>();\r
+ result.put("Line", "Line");\r
+ result.put("Area", "Area");\r
+// result.put("Stacked Area", "Stacked Area");\r
+ return result;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * TypeModifyListener for modifying the type of a bar chart \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeModifyListener extends ComboModifyListenerImpl<Resource> {\r
+ @Override\r
+ public void applyText(WriteGraph graph, Resource chart, String text) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.XYPlot));\r
+ if(plot == null)\r
+ return;\r
+\r
+ Collection<Resource> datasets = graph.syncRequest(new ObjectsWithType(plot, l0.ConsistsOf, jfree.XYDataset));\r
+ if(datasets == null || datasets.isEmpty())\r
+ return;\r
+\r
+ for(Resource dataset : datasets) {\r
+ graph.deny(dataset, jfree.Dataset_renderer);\r
+\r
+ Resource renderer;\r
+ if(text.equals("Area"))\r
+ renderer = GraphUtils.create2(graph, jfree.XYAreaRenderer);\r
+ else\r
+ renderer = GraphUtils.create2(graph, jfree.XYLineRenderer);\r
+\r
+ graph.claim(dataset, jfree.Dataset_renderer, renderer);\r
+ }\r
+ }\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.jfreechart.internal;\r
+\r
+import org.eclipse.ui.plugin.AbstractUIPlugin;\r
+import org.osgi.framework.BundleContext;\r
+\r
+/**\r
+ * The activator class controls the plug-in life cycle\r
+ */\r
+public class Activator extends AbstractUIPlugin {\r
+\r
+ // The plug-in ID\r
+ public static final String PLUGIN_ID = "org.simantics.jfreechart"; //$NON-NLS-1$\r
+\r
+ // The shared instance\r
+ private static Activator plugin;\r
+ \r
+ /**\r
+ * The constructor\r
+ */\r
+ public Activator() {\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext context) throws Exception {\r
+ super.start(context);\r
+ plugin = this;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext context) throws Exception {\r
+ plugin = null;\r
+ super.stop(context);\r
+ }\r
+\r
+ /**\r
+ * Returns the shared instance\r
+ *\r
+ * @return the shared instance\r
+ */\r
+ public static Activator getDefault() {\r
+ return plugin;\r
+ }\r
+\r
+}\r