]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
refs #6271
authorluukkainen <luukkainen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Tue, 19 Jan 2016 14:32:59 +0000 (14:32 +0000)
committerluukkainen <luukkainen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Tue, 19 Jan 2016 14:32:59 +0000 (14:32 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/branches/simantics-1.18@32275 ac1ea38d-2e2b-0410-8846-a27921b304fc

125 files changed:
org.simantics.jfreechart/.classpath [new file with mode: 0644]
org.simantics.jfreechart/.project [new file with mode: 0644]
org.simantics.jfreechart/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
org.simantics.jfreechart/META-INF/MANIFEST.MF [new file with mode: 0644]
org.simantics.jfreechart/adapters.xml [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-1.7.zip [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-awt-util.jar [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-dom.jar [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-ext.jar [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-src-1.7.zip [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-svg-dom.jar [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-svggen.jar [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-util.jar [new file with mode: 0644]
org.simantics.jfreechart/batik/batik-xml.jar [new file with mode: 0644]
org.simantics.jfreechart/build.properties [new file with mode: 0644]
org.simantics.jfreechart/icons/chart_bar_light.png [new file with mode: 0644]
org.simantics.jfreechart/icons/chart_line_light.png [new file with mode: 0644]
org.simantics.jfreechart/icons/chart_pie_light.png [new file with mode: 0644]
org.simantics.jfreechart/icons/close.gif [new file with mode: 0644]
org.simantics.jfreechart/icons/maximize.gif [new file with mode: 0644]
org.simantics.jfreechart/icons/minimize.gif [new file with mode: 0644]
org.simantics.jfreechart/plugin.xml [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ChartDropTarget.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanel.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelElement.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelHeader.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelSeparator.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPropertyOptions.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ChartSelectionTabContributor.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/ElementContainer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractAxis.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractPlot.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractRenderer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/BarRenderer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryAxis.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryPlot.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartComposite2.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartUtils.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/DeviationRenderer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ExtendedNumberAxis.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteredDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteringCategoryDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteringPieDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IAxis.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IJFreeChart.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IJFreeChartComponent.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IPlot.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IRenderer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ITitle.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/JFreeChart.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/NumberAxis.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PieDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PiePlot.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PlotProperties.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/StackedBarRenderer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/TextTitle.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYAreaRenderer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYDataset.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYLineRenderer.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYPlot.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartBoundsOutline.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartElementFactory.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartElementWriter.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartNode.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartSceneGraph.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/PopulateChartDropParticipant.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ResizeListener.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisChildRule.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisDropAction.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisLabelRule.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesChildRule.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesDropAction.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesLabelDecorationRule.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesLabelRule.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/VariableChildRule.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AdjustableTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AllVariablesOfModel.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AxisHidePropertyComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/BooleanPropertyFactory.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/BooleanSelectionListener.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariable.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariableFactory.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariableModifier.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ColorPicker.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoublePropertyFactory2.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoublePropertyModifier2.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoubleValidator.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/IAllVariablesOfModel.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/JFreeChartPropertyColorProvider.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/LabelPropertyTabContributor.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RVIFactory.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RVIModifier.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RangeComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RangeHandlerFactory.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooser.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyEvent.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyListener.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyListenerImpl.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TitleFactory.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TitleModifier.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TrackedSpinner.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/VariableExistsValidator.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/VariableProposalProvider.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarAxisTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarGeneralPropertiesTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesPropertyComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesPropertyComposite2.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesTab2.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieGeneralPropertiesTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesPropertyComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesPropertyComposite2.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesTab2.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/AxisAndVariablesExplorerComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/AxisPropertyComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/SeriesPropertyComposite.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/XYLineAxisAndVariablesTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/XYLineGeneralPropertiesTab.java [new file with mode: 0644]
org.simantics.jfreechart/src/org/simantics/jfreechart/internal/Activator.java [new file with mode: 0644]

diff --git a/org.simantics.jfreechart/.classpath b/org.simantics.jfreechart/.classpath
new file mode 100644 (file)
index 0000000..b867942
--- /dev/null
@@ -0,0 +1,14 @@
+<?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.7"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry exported="true" kind="lib" path="batik/batik-awt-util.jar"/>\r
+       <classpathentry exported="true" kind="lib" path="batik/batik-dom.jar"/>\r
+       <classpathentry exported="true" kind="lib" path="batik/batik-ext.jar"/>\r
+       <classpathentry exported="true" kind="lib" path="batik/batik-svg-dom.jar"/>\r
+       <classpathentry exported="true" kind="lib" path="batik/batik-svggen.jar"/>\r
+       <classpathentry exported="true" kind="lib" path="batik/batik-util.jar"/>\r
+       <classpathentry exported="true" kind="lib" path="batik/batik-xml.jar"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/org.simantics.jfreechart/.project b/org.simantics.jfreechart/.project
new file mode 100644 (file)
index 0000000..9c948e2
--- /dev/null
@@ -0,0 +1,28 @@
+<?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
diff --git a/org.simantics.jfreechart/.settings/org.eclipse.jdt.core.prefs b/org.simantics.jfreechart/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..11f6e46
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7\r
+org.eclipse.jdt.core.compiler.compliance=1.7\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.7\r
diff --git a/org.simantics.jfreechart/META-INF/MANIFEST.MF b/org.simantics.jfreechart/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..1edbb33
--- /dev/null
@@ -0,0 +1,45 @@
+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.7
+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
+Bundle-ClassPath: batik/batik-awt-util.jar,
+ batik/batik-dom.jar,
+ batik/batik-ext.jar,
+ batik/batik-svg-dom.jar,
+ batik/batik-svggen.jar,
+ batik/batik-util.jar,
+ batik/batik-xml.jar,
+ .
diff --git a/org.simantics.jfreechart/adapters.xml b/org.simantics.jfreechart/adapters.xml
new file mode 100644 (file)
index 0000000..54fd841
--- /dev/null
@@ -0,0 +1,155 @@
+<?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
+        <type uri="http://www.simantics.org/JFreeChart-0.0/DeviationRenderer"\r
+            class="org.simantics.jfreechart.chart.DeviationRenderer">\r
+            <graph />\r
+            <this />\r
+        </type>           \r
+    </target> \r
+</adapters>
\ No newline at end of file
diff --git a/org.simantics.jfreechart/batik/batik-1.7.zip b/org.simantics.jfreechart/batik/batik-1.7.zip
new file mode 100644 (file)
index 0000000..b1f32e7
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-1.7.zip differ
diff --git a/org.simantics.jfreechart/batik/batik-awt-util.jar b/org.simantics.jfreechart/batik/batik-awt-util.jar
new file mode 100644 (file)
index 0000000..e64605a
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-awt-util.jar differ
diff --git a/org.simantics.jfreechart/batik/batik-dom.jar b/org.simantics.jfreechart/batik/batik-dom.jar
new file mode 100644 (file)
index 0000000..32d5b46
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-dom.jar differ
diff --git a/org.simantics.jfreechart/batik/batik-ext.jar b/org.simantics.jfreechart/batik/batik-ext.jar
new file mode 100644 (file)
index 0000000..8c904e1
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-ext.jar differ
diff --git a/org.simantics.jfreechart/batik/batik-src-1.7.zip b/org.simantics.jfreechart/batik/batik-src-1.7.zip
new file mode 100644 (file)
index 0000000..77478cd
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-src-1.7.zip differ
diff --git a/org.simantics.jfreechart/batik/batik-svg-dom.jar b/org.simantics.jfreechart/batik/batik-svg-dom.jar
new file mode 100644 (file)
index 0000000..b4c8a62
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-svg-dom.jar differ
diff --git a/org.simantics.jfreechart/batik/batik-svggen.jar b/org.simantics.jfreechart/batik/batik-svggen.jar
new file mode 100644 (file)
index 0000000..4d6bb14
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-svggen.jar differ
diff --git a/org.simantics.jfreechart/batik/batik-util.jar b/org.simantics.jfreechart/batik/batik-util.jar
new file mode 100644 (file)
index 0000000..86d75e7
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-util.jar differ
diff --git a/org.simantics.jfreechart/batik/batik-xml.jar b/org.simantics.jfreechart/batik/batik-xml.jar
new file mode 100644 (file)
index 0000000..d05eb25
Binary files /dev/null and b/org.simantics.jfreechart/batik/batik-xml.jar differ
diff --git a/org.simantics.jfreechart/build.properties b/org.simantics.jfreechart/build.properties
new file mode 100644 (file)
index 0000000..3806e2b
--- /dev/null
@@ -0,0 +1,14 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .,\\r
+               plugin.xml,\\r
+               adapters.xml,\\r
+               icons/,\\r
+               batik/batik-awt-util.jar,\\r
+               batik/batik-dom.jar,\\r
+               batik/batik-ext.jar,\\r
+               batik/batik-svg-dom.jar,\\r
+               batik/batik-svggen.jar,\\r
+               batik/batik-util.jar,\\r
+               batik/batik-xml.jar\r
diff --git a/org.simantics.jfreechart/icons/chart_bar_light.png b/org.simantics.jfreechart/icons/chart_bar_light.png
new file mode 100644 (file)
index 0000000..6069b5c
Binary files /dev/null and b/org.simantics.jfreechart/icons/chart_bar_light.png differ
diff --git a/org.simantics.jfreechart/icons/chart_line_light.png b/org.simantics.jfreechart/icons/chart_line_light.png
new file mode 100644 (file)
index 0000000..2a77b24
Binary files /dev/null and b/org.simantics.jfreechart/icons/chart_line_light.png differ
diff --git a/org.simantics.jfreechart/icons/chart_pie_light.png b/org.simantics.jfreechart/icons/chart_pie_light.png
new file mode 100644 (file)
index 0000000..fa553c2
Binary files /dev/null and b/org.simantics.jfreechart/icons/chart_pie_light.png differ
diff --git a/org.simantics.jfreechart/icons/close.gif b/org.simantics.jfreechart/icons/close.gif
new file mode 100644 (file)
index 0000000..1aca259
Binary files /dev/null and b/org.simantics.jfreechart/icons/close.gif differ
diff --git a/org.simantics.jfreechart/icons/maximize.gif b/org.simantics.jfreechart/icons/maximize.gif
new file mode 100644 (file)
index 0000000..5e5999b
Binary files /dev/null and b/org.simantics.jfreechart/icons/maximize.gif differ
diff --git a/org.simantics.jfreechart/icons/minimize.gif b/org.simantics.jfreechart/icons/minimize.gif
new file mode 100644 (file)
index 0000000..7402dc9
Binary files /dev/null and b/org.simantics.jfreechart/icons/minimize.gif differ
diff --git a/org.simantics.jfreechart/plugin.xml b/org.simantics.jfreechart/plugin.xml
new file mode 100644 (file)
index 0000000..9db7546
--- /dev/null
@@ -0,0 +1,16 @@
+<?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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartDropTarget.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartDropTarget.java
new file mode 100644 (file)
index 0000000..a218ada
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************\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.utils.ui.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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanel.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanel.java
new file mode 100644 (file)
index 0000000..a698efe
--- /dev/null
@@ -0,0 +1,471 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelElement.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelElement.java
new file mode 100644 (file)
index 0000000..3102514
--- /dev/null
@@ -0,0 +1,193 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelHeader.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelHeader.java
new file mode 100644 (file)
index 0000000..5935c34
--- /dev/null
@@ -0,0 +1,397 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelSeparator.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPanelSeparator.java
new file mode 100644 (file)
index 0000000..5f7e5e0
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPropertyOptions.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartPropertyOptions.java
new file mode 100644 (file)
index 0000000..7fc2b60
--- /dev/null
@@ -0,0 +1,11 @@
+package org.simantics.jfreechart;\r
+\r
+public class ChartPropertyOptions {\r
+       \r
+       public static final int SHOW_TIME      = 1 << 0;\r
+       public static final int SHOW_FILTER    = 1 << 1;\r
+       public static final int SHOW_VARIABLES = 1 << 2;\r
+       public static final int SHOW_AXIS      = 1 << 3;\r
+       public static final int SHOW_CHART     = 1 << 4;\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartSelectionTabContributor.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ChartSelectionTabContributor.java
new file mode 100644 (file)
index 0000000..48033d8
--- /dev/null
@@ -0,0 +1,170 @@
+package org.simantics.jfreechart;\r
+\r
+import java.util.Collection;\r
+import java.util.List;\r
+\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.jfreechart.chart.properties.ChartTab;\r
+import org.simantics.jfreechart.chart.properties.bar.BarAxisTab;\r
+import org.simantics.jfreechart.chart.properties.bar.BarGeneralPropertiesTab;\r
+import org.simantics.jfreechart.chart.properties.bar.BarSeriesTab;\r
+import org.simantics.jfreechart.chart.properties.bar.BarSeriesTab2;\r
+import org.simantics.jfreechart.chart.properties.pie.PieGeneralPropertiesTab;\r
+import org.simantics.jfreechart.chart.properties.pie.PieSeriesTab;\r
+import org.simantics.jfreechart.chart.properties.pie.PieSeriesTab2;\r
+import org.simantics.jfreechart.chart.properties.xyline.XYLineAxisAndVariablesTab;\r
+import org.simantics.jfreechart.chart.properties.xyline.XYLineGeneralPropertiesTab;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.selectionview.ComparableTabContributor;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+public class ChartSelectionTabContributor {\r
+\r
+       public static boolean contibuteTabs(ReadGraph backend, Resource r, List<ComparableTabContributor> tabs) throws DatabaseException{\r
+               return contibuteTabs(backend, r, tabs, ChartPropertyOptions.SHOW_TIME|ChartPropertyOptions.SHOW_AXIS|ChartPropertyOptions.SHOW_VARIABLES|ChartPropertyOptions.SHOW_CHART);\r
+       }\r
+       public static boolean contibuteTabs(ReadGraph backend, Resource r, List<ComparableTabContributor> tabs, int options) throws DatabaseException {\r
+               JFreeChartResource jfree = JFreeChartResource.getInstance(backend);\r
+               if(backend.isInstanceOf(r, jfree.ChartElement)) {\r
+            if(backend.hasStatement(r, jfree.ChartElement_component))\r
+                r = backend.getSingleObject(r, jfree.ChartElement_component);\r
+        }\r
+               \r
+               if (backend.isInstanceOf(r, jfree.Chart)) {\r
+\r
+             Collection<Resource> plots = backend.syncRequest(new ObjectsWithType(r, Layer0.getInstance(backend).ConsistsOf, jfree.Plot));\r
+             if(!plots.isEmpty()) {\r
+                 Resource plot = plots.iterator().next();\r
+\r
+                 if(backend.isInstanceOf(plot, jfree.XYPlot)) {\r
+                     tabs.add(new ComparableTabContributor(\r
+                             new XYLineGeneralPropertiesTab(r),\r
+                             10,\r
+                             r,\r
+                             "General"));\r
+                     if ((options&ChartPropertyOptions.SHOW_AXIS )>0 ||(options&ChartPropertyOptions.SHOW_VARIABLES)>0 )\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new XYLineAxisAndVariablesTab(r),\r
+                                    9,\r
+                                    r,\r
+                                    "Axis and Variables"));\r
+                 } else if(backend.isInstanceOf(plot, jfree.CategoryPlot)) {\r
+                     tabs.add(new ComparableTabContributor(\r
+                             new BarGeneralPropertiesTab(r, options),\r
+                             10,\r
+                             r,\r
+                             "General"));\r
+                     if ((options&ChartPropertyOptions.SHOW_VARIABLES )>0)\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new BarSeriesTab(r, options),\r
+                                    9,\r
+                                    r,\r
+                                    "Variables"));\r
+                     if ((options&ChartPropertyOptions.SHOW_AXIS )>0)\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new BarAxisTab(r),\r
+                                    8,\r
+                                    r,\r
+                                    "Axis"));                        \r
+                 } else if(backend.isInstanceOf(plot, jfree.PiePlot)) {\r
+                     tabs.add(new ComparableTabContributor(\r
+                             new PieGeneralPropertiesTab(r, options),\r
+                             10,\r
+                             r,\r
+                             "General"));\r
+                     if ((options&ChartPropertyOptions.SHOW_VARIABLES )>0)\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new PieSeriesTab(r, options),\r
+                                    9,\r
+                                    r,\r
+                                    "Variables"));\r
+                 }\r
+                 if ((options&ChartPropertyOptions.SHOW_CHART )>0)\r
+                        tabs.add(new ComparableTabContributor(\r
+                                new ChartTab(r),\r
+                                1,\r
+                                r,\r
+                                "Chart"));\r
+                \r
+                 return true;\r
+             } \r
+         }\r
+               return false;\r
+       }\r
+       \r
+       public static boolean contibuteTabs2(ReadGraph backend, Resource r, List<ComparableTabContributor> tabs) throws DatabaseException{\r
+               return contibuteTabs2(backend, r, tabs, ChartPropertyOptions.SHOW_TIME|ChartPropertyOptions.SHOW_AXIS|ChartPropertyOptions.SHOW_VARIABLES|ChartPropertyOptions.SHOW_CHART);\r
+       }\r
+       \r
+       public static boolean contibuteTabs2(ReadGraph backend, Resource r, List<ComparableTabContributor> tabs, int options) throws DatabaseException {\r
+               JFreeChartResource jfree = JFreeChartResource.getInstance(backend);\r
+               if(backend.isInstanceOf(r, jfree.ChartElement)) {\r
+            if(backend.hasStatement(r, jfree.ChartElement_component))\r
+                r = backend.getSingleObject(r, jfree.ChartElement_component);\r
+        }\r
+               \r
+               if (backend.isInstanceOf(r, jfree.Chart)) {\r
+\r
+             Collection<Resource> plots = backend.syncRequest(new ObjectsWithType(r, Layer0.getInstance(backend).ConsistsOf, jfree.Plot));\r
+             if(!plots.isEmpty()) {\r
+                 Resource plot = plots.iterator().next();\r
+\r
+                 if(backend.isInstanceOf(plot, jfree.XYPlot)) {\r
+                     tabs.add(new ComparableTabContributor(\r
+                             new XYLineGeneralPropertiesTab(r),\r
+                             10,\r
+                             r,\r
+                             "General"));\r
+                     if ((options&ChartPropertyOptions.SHOW_AXIS )>0 ||(options&ChartPropertyOptions.SHOW_VARIABLES)>0 )\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new XYLineAxisAndVariablesTab(r),\r
+                                    9,\r
+                                    r,\r
+                                    "Axis and Variables"));\r
+                               } else if (backend.isInstanceOf(plot, jfree.CategoryPlot)) {\r
+                                       tabs.add(new ComparableTabContributor(\r
+                             new BarGeneralPropertiesTab(r, options),\r
+                             10,\r
+                             r,\r
+                             "General"));\r
+                     if ((options&ChartPropertyOptions.SHOW_VARIABLES)>0)\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new BarSeriesTab2(r, options),\r
+                                    9,\r
+                                    r,\r
+                                    "Variables"));\r
+                     if ((options&ChartPropertyOptions.SHOW_AXIS )>0)\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new BarAxisTab(r),\r
+                                    8,\r
+                                    r,\r
+                                    "Axis"));                        \r
+                 } else if(backend.isInstanceOf(plot, jfree.PiePlot)) {\r
+                     tabs.add(new ComparableTabContributor(\r
+                             new PieGeneralPropertiesTab(r, options),\r
+                             10,\r
+                             r,\r
+                             "General"));\r
+                     if ((options&ChartPropertyOptions.SHOW_VARIABLES)>0)\r
+                            tabs.add(new ComparableTabContributor(\r
+                                    new PieSeriesTab2(r, options),\r
+                                    9,\r
+                                    r,\r
+                                    "Variables"));\r
+                 }\r
+                 if ((options&ChartPropertyOptions.SHOW_CHART )>0)\r
+                        tabs.add(new ComparableTabContributor(\r
+                                new ChartTab(r),\r
+                                1,\r
+                                r,\r
+                                "Chart"));\r
+                \r
+                 return true;\r
+             } \r
+         }\r
+               return false;\r
+       }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/ElementContainer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/ElementContainer.java
new file mode 100644 (file)
index 0000000..3775360
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractAxis.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractAxis.java
new file mode 100644 (file)
index 0000000..4439a9c
--- /dev/null
@@ -0,0 +1,94 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractDataset.java
new file mode 100644 (file)
index 0000000..2207259
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************\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
+import org.simantics.db.exception.DatabaseException;\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) throws DatabaseException {\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractPlot.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractPlot.java
new file mode 100644 (file)
index 0000000..c24759c
--- /dev/null
@@ -0,0 +1,209 @@
+/*******************************************************************************\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.HashMap;\r
+\r
+import javax.swing.SwingUtilities;\r
+\r
+import org.jfree.chart.JFreeChart;\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
+    protected PlotPropertyListener listener;\r
+    protected org.jfree.chart.JFreeChart jfreechart;\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
+    @Override\r
+    public void setJFreeChart(JFreeChart jfreechart) {\r
+       this.jfreechart = jfreechart;\r
+    }\r
+    \r
+    public org.jfree.chart.JFreeChart getJfreechart() {\r
+               return jfreechart;\r
+       }\r
+    \r
+    public PlotProperties getPlotProperties() {\r
+       return currentProperties;\r
+    }\r
+\r
+    protected abstract Plot newPlot();\r
+    protected void setPlotProperties(PlotProperties properties) {\r
+       this.currentProperties = properties;\r
+    }\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 PlotPropertyQuery(), listener);\r
+        }\r
+\r
+        return plot;\r
+    }\r
+    \r
+    protected IDataset getDataset(ReadGraph graph, Resource datasetResource) throws DatabaseException{\r
+         return graph.adapt(datasetResource, IDataset.class);\r
+    }\r
+    \r
+    @Override\r
+    public void configurePlot(PlotProperties properties) {\r
+       \r
+    }\r
+\r
+    protected class PlotPropertyQuery implements Read<PlotProperties> {\r
+       \r
+       public PlotPropertyQuery() {\r
+               \r
+               }\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 = getDataset(graph, datasetResource);\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
+    }\r
+    \r
+    protected class PlotPropertyListener implements Listener<PlotProperties> {\r
+\r
+        private boolean disposed = false;\r
+        \r
+        public PlotPropertyListener() {\r
+               \r
+        }\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
+                    configurePlot(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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractRenderer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/AbstractRenderer.java
new file mode 100644 (file)
index 0000000..7621c35
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/BarRenderer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/BarRenderer.java
new file mode 100644 (file)
index 0000000..30430d3
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryAxis.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryAxis.java
new file mode 100644 (file)
index 0000000..6573161
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryDataset.java
new file mode 100644 (file)
index 0000000..8b67400
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryPlot.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/CategoryPlot.java
new file mode 100644 (file)
index 0000000..2bf3330
--- /dev/null
@@ -0,0 +1,123 @@
+/*******************************************************************************\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.plot.PlotOrientation;\r
+import org.jfree.chart.renderer.category.CategoryItemRenderer;\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 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
+        \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
+            if (ds instanceof FilteredDataset) {\r
+               FilteredDataset f = (FilteredDataset)ds;\r
+               Boolean useFilter = (Boolean)properties.otherProperties.get("useFilter");\r
+                Double filterFraction = (Double)properties.otherProperties.get("filterFraction");\r
+                if (useFilter != null && filterFraction != null) {\r
+                       f.setFiltering(useFilter);\r
+                       f.setFilterFraction(filterFraction*0.01);\r
+                       f.updateFiltered();\r
+                } else {\r
+                       f.setFiltering(false);\r
+                }\r
+            }\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
+        Boolean orientation = (Boolean)properties.otherProperties.get("orientation");\r
+        if(orientation != null) {\r
+               if (orientation)\r
+                       cplot.setOrientation(PlotOrientation.HORIZONTAL);\r
+               else\r
+                       cplot.setOrientation(PlotOrientation.VERTICAL);\r
+        }\r
+        \r
+        // Cleaner look: no outline borders\r
+        cplot.setInsets(new RectangleInsets(2,5,2,2), false);\r
+        cplot.setOutlineVisible(false);\r
+        super.setPlotProperties(properties);\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
+        Boolean orientation = graph.getPossibleRelatedValue(resource, jfree.Plot_orientation);\r
+        properties.otherProperties.put("orientation", orientation);\r
+        \r
+        Boolean useFilter = graph.getPossibleRelatedValue(resource, JFreeChartResource.getInstance(graph).Filter_used, Bindings.BOOLEAN);\r
+        Double  filterFraction = graph.getPossibleRelatedValue(resource, JFreeChartResource.getInstance(graph).Filter_fraction, Bindings.DOUBLE);\r
+        properties.otherProperties.put("useFilter", useFilter);\r
+        properties.otherProperties.put("filterFraction", filterFraction);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartComposite.java
new file mode 100644 (file)
index 0000000..6d571f5
--- /dev/null
@@ -0,0 +1,161 @@
+/*******************************************************************************\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
+                if (composite.isDisposed())\r
+                       return;\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
+                        panel = new ChartPanel(chart,\r
+                                                      ChartPanel.DEFAULT_WIDTH,\r
+                                                      ChartPanel.DEFAULT_HEIGHT,\r
+                                                      ChartPanel.DEFAULT_MINIMUM_DRAW_WIDTH,\r
+                                                      ChartPanel.DEFAULT_MINIMUM_DRAW_HEIGHT,\r
+                                                      ChartPanel.DEFAULT_MAXIMUM_DRAW_WIDTH, \r
+                                                      ChartPanel.DEFAULT_MAXIMUM_DRAW_HEIGHT,\r
+                                                      false,\r
+                                                      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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartComposite2.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartComposite2.java
new file mode 100644 (file)
index 0000000..d3e169d
--- /dev/null
@@ -0,0 +1,170 @@
+/*******************************************************************************\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.BorderLayout;\r
+import java.awt.Component;\r
+import java.awt.GridLayout;\r
+\r
+import javax.swing.JPanel;\r
+\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.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+import org.simantics.utils.ui.SWTAWTComponent;\r
+\r
+/**\r
+ * Composite containing a single chart defined by a JFreeChart.Chart\r
+ * \r
+ * Similar to ChartComposite, but uses SWTAWTComponent as a base implementation. \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ * \r
+ */\r
+public class ChartComposite2 extends SWTAWTComponent {\r
+\r
+       private JPanel jPanel;\r
+    private ChartPanel chartPanel;\r
+    private IJFreeChart chart;\r
+\r
+    public ChartComposite2(Composite parent, final String chartResourceURI, int style) {\r
+               super(parent, style);\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
+               syncPopulate();\r
+       }\r
+    \r
+    public ChartComposite2(Composite parent, final Resource chartResource, int style) {\r
+       super(parent, style);\r
+       CreateContent(chartResource);\r
+       syncPopulate();\r
+    }\r
+\r
+       @Override\r
+    protected Component createSwingComponent() {\r
+       jPanel = new JPanel();\r
+       jPanel.setLayout(new GridLayout(1, 1));\r
+       if (chartPanel != null)\r
+               jPanel.add(chartPanel);\r
+       jPanel.doLayout();\r
+       return jPanel;\r
+    }\r
+       \r
+       protected void setPanel(final ChartPanel panel) {\r
+               ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+                       \r
+                       @Override\r
+                       public void run() {\r
+                               if (jPanel == null) {\r
+                                       chartPanel = panel;\r
+                               } else {\r
+                                       jPanel.removeAll();\r
+\r
+                                       chartPanel = panel;\r
+                                       jPanel.add(chartPanel, BorderLayout.CENTER);\r
+                                       jPanel.add(chartPanel);\r
+                                       jPanel.doLayout();\r
+                               }\r
+                               \r
+                       }\r
+               });\r
+       }\r
+       \r
+       public ChartPanel getChartPanel() {\r
+               return chartPanel;\r
+       }\r
+       \r
+       public IJFreeChart getChart() {\r
+               return chart;\r
+       }\r
+\r
+    /**\r
+     * Creates and displays the chart defined in chartResource\r
+     * @param chartResource\r
+     */\r
+    private void CreateContent(final Resource chartResource) {\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 ChartComposite2.this.isDisposed();\r
+            }\r
+\r
+            @Override\r
+            public void execute(AsyncReadGraph graph, IJFreeChart chart) {\r
+                if(chart == null || ChartComposite2.this.isDisposed())\r
+                    return;\r
+                \r
+                JFreeChart jfreeChart = chart.getChart();\r
+\r
+                ChartPanel panel = new ChartPanel(jfreeChart,\r
+                              ChartPanel.DEFAULT_WIDTH,\r
+                              ChartPanel.DEFAULT_HEIGHT,\r
+                              ChartPanel.DEFAULT_MINIMUM_DRAW_WIDTH,\r
+                              ChartPanel.DEFAULT_MINIMUM_DRAW_HEIGHT,\r
+                              ChartPanel.DEFAULT_MAXIMUM_DRAW_WIDTH, \r
+                              ChartPanel.DEFAULT_MAXIMUM_DRAW_HEIGHT,\r
+                              false,\r
+                              false, true, true, true, true);\r
+                setPanel(panel);\r
+               \r
+            }\r
+\r
+            @Override\r
+            public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+                throwable.printStackTrace();\r
+\r
+            }\r
+        });\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartUtils.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ChartUtils.java
new file mode 100644 (file)
index 0000000..94eb56d
--- /dev/null
@@ -0,0 +1,192 @@
+package org.simantics.jfreechart.chart;\r
+\r
+import java.awt.Dimension;\r
+import java.awt.geom.Rectangle2D;\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.io.OutputStreamWriter;\r
+import java.io.Writer;\r
+import java.util.ArrayList;\r
+import java.util.UUID;\r
+\r
+import org.apache.batik.dom.GenericDOMImplementation;\r
+import org.apache.batik.svggen.SVGGraphics2D;\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
+import org.w3c.dom.DOMImplementation;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * Utilities for handling charts\r
+ * \r
+ * @author Teemu Lempinen\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class ChartUtils {\r
+    \r
+       public static final String emptyVariableName = "<Write variable name>";\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 ? " " + emptyVariableName : 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
+    public static void writeSVG(org.jfree.chart.JFreeChart chart, Rectangle2D bounds, Writer out) throws IOException {\r
+        // Get a DOMImplementation.\r
+        DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();\r
+\r
+        // Create an instance of org.w3c.dom.Document.\r
+        Document document = domImpl.createDocument(null, "svg", null);\r
+\r
+        // Create an instance of the SVG Generator.\r
+        SVGGraphics2D svgGenerator = new SVGGraphics2D(document);\r
+\r
+        // Paint chart panel\r
+        svgGenerator.setSVGCanvasSize(new Dimension((int)bounds.getWidth(), (int)bounds.getHeight()));\r
+        chart.draw(svgGenerator, bounds);\r
+\r
+        // Finally, write to out\r
+        svgGenerator.stream(out, false);\r
+\r
+    }\r
+\r
+    public static void writeSVG(org.jfree.chart.JFreeChart chart, Rectangle2D bounds, File file) throws IOException {\r
+        OutputStream outputStream = new FileOutputStream(file);\r
+        Writer out = new OutputStreamWriter(outputStream, "UTF-8");\r
+        writeSVG(chart, bounds, out);\r
+        outputStream.flush();\r
+        outputStream.close();
+    }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/DeviationRenderer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/DeviationRenderer.java
new file mode 100644 (file)
index 0000000..716bb68
--- /dev/null
@@ -0,0 +1,35 @@
+/*******************************************************************************\r
+ * Copyright (c) 2013 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
+ *     Semantum Oy - 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
+public class DeviationRenderer extends AbstractRenderer {\r
+\r
+    public DeviationRenderer(ReadGraph graph, Resource resource) {\r
+        super(graph, resource);\r
+    }\r
+\r
+    private org.jfree.chart.renderer.xy.DeviationRenderer renderer;\r
+    \r
+    @Override\r
+    public org.jfree.chart.renderer.AbstractRenderer getRenderer() {\r
+        if(renderer == null) {\r
+            renderer = new org.jfree.chart.renderer.xy.DeviationRenderer();\r
+            renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());\r
+        }\r
+        return renderer;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ExtendedNumberAxis.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ExtendedNumberAxis.java
new file mode 100644 (file)
index 0000000..0587a58
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteredDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteredDataset.java
new file mode 100644 (file)
index 0000000..a5770ff
--- /dev/null
@@ -0,0 +1,29 @@
+package org.simantics.jfreechart.chart;\r
+\r
+/**\r
+ * Interface for configuring data filtering.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public interface FilteredDataset {\r
+\r
+       public boolean isFiltering();\r
+       public void setFiltering(boolean filtering);\r
+       \r
+       \r
+       public double getFilterFraction();\r
+       /**\r
+        * Sets filtering fraction 0 <= fraction <= 1\r
+        * With filtering fraction 0 nothing gets filtered.\r
+        * With filtering fraction 1 everything gets filtered.\r
+        * \r
+        * @param filterFraction\r
+        */\r
+       public void setFilterFraction(double filterFraction);\r
+       \r
+       public void updateFiltered();\r
+       \r
+       @SuppressWarnings("rawtypes")\r
+       public Comparable getOther();\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteringCategoryDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteringCategoryDataset.java
new file mode 100644 (file)
index 0000000..aa211ba
--- /dev/null
@@ -0,0 +1,193 @@
+package org.simantics.jfreechart.chart;\r
+\r
+/**\r
+ * Filters CategoryDataset by creating "Other" item for filtered data.\r
+ * \r
+ * Filtering uses sum of absolute values as a comparison point and compares absolute values.\r
+ * If negative values are filtered, their absolute value is added to the others category.  \r
+ * \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+import java.util.List;\r
+\r
+import org.jfree.data.category.DefaultCategoryDataset;\r
+import org.jfree.data.general.AbstractDataset;\r
+import org.jfree.data.general.DatasetChangeEvent;\r
+import org.jfree.data.general.DatasetChangeListener;\r
+\r
+@SuppressWarnings("rawtypes")\r
+public class FilteringCategoryDataset extends AbstractDataset implements org.jfree.data.category.CategoryDataset, FilteredDataset, DatasetChangeListener{\r
+       \r
+       private static final long serialVersionUID = -4955124650051030544L;\r
+       \r
+       org.jfree.data.category.CategoryDataset original;\r
+       DefaultCategoryDataset filtered;\r
+       org.jfree.data.category.CategoryDataset used;\r
+       \r
+       boolean filterRows = true;\r
+       boolean filtering = true;\r
+       double filterFraction = 0.05;\r
+       private Comparable other;\r
+       \r
+       public FilteringCategoryDataset(org.jfree.data.category.CategoryDataset dataset, Comparable other) {\r
+               this.original = dataset;\r
+               this.filtered = new DefaultCategoryDataset();\r
+               this.other = other;\r
+               this.used = filtered;\r
+               this.original.addChangeListener(this);\r
+               updateFiltered();\r
+       }\r
+       \r
+       @Override\r
+       public boolean isFiltering() {\r
+               return filtering;\r
+       }\r
+       \r
+       @Override\r
+       public void setFiltering(boolean filtering) {\r
+               this.filtering = filtering;\r
+               if (filtering)\r
+                       used = filtered;\r
+               else\r
+                       used = original;\r
+               fireDatasetChanged();\r
+       }\r
+       \r
+       public void setFilterFraction(double filterFraction) {\r
+               this.filterFraction = filterFraction;\r
+       }\r
+       \r
+       public double getFilterFraction() {\r
+               return filterFraction;\r
+       }\r
+       \r
+       /**\r
+        * Filter rows or columns.\r
+        * @param filterRows\r
+        */\r
+       public void setFilterRows(boolean filterRows) {\r
+               this.filterRows = filterRows;\r
+       }\r
+       \r
+       public boolean isFilterRows() {\r
+               return filterRows;\r
+       }\r
+       \r
+       public void updateFiltered() {\r
+               filtered.clear();\r
+               if (filterRows) {\r
+                       for (Object column : original.getColumnKeys()) {\r
+                               Double total = 0.0;\r
+                               Double other = 0.0;\r
+                               for (Object row : original.getRowKeys()) {\r
+                                       Number value =  original.getValue((Comparable) row, (Comparable)column);\r
+                                       if (value != null)\r
+                                               total+=Math.abs(value.doubleValue());\r
+                               }\r
+                               total *= filterFraction;\r
+                               for (Object row : original.getRowKeys()) {\r
+                                       Number value = original.getValue((Comparable) row, (Comparable)column);\r
+                                       if (value == null)\r
+                                               continue;\r
+                                       if (Math.abs(value.doubleValue()) > total) {\r
+                                               filtered.addValue(value, (Comparable) row, (Comparable)column);\r
+                                       } else {\r
+                                               other += value.doubleValue(); \r
+                                       }\r
+                               }\r
+                               if (Math.abs(other) > 0.0) {\r
+                                       filtered.addValue(other, this.other, (Comparable)column);\r
+                               }\r
+                       }\r
+               } else {\r
+                       for (Object row : original.getRowKeys()) {\r
+                               Double total = 0.0;\r
+                               Double other = 0.0;\r
+                               for (Object column : original.getColumnKeys()) {\r
+                                       Number value = original.getValue((Comparable) row, (Comparable)column);\r
+                                       if (value != null)\r
+                                               total += Math.abs(value.doubleValue());\r
+                               }\r
+                               total *= filterFraction;\r
+                               for (Object column : original.getColumnKeys()) {\r
+                                       Number value = original.getValue((Comparable) row, (Comparable)column);\r
+                                       if (value == null)\r
+                                               continue;\r
+                                       if (Math.abs(value.doubleValue()) > total) {\r
+                                               filtered.addValue(value, (Comparable) row, (Comparable)column);\r
+                                       } else {\r
+                                               other += value.doubleValue(); \r
+                                       }\r
+                               }\r
+                               if (Math.abs(other) > 0.0) {\r
+                                       filtered.addValue(other, (Comparable)row, this.other);\r
+                               }\r
+                       }\r
+               }\r
+               fireDatasetChanged();\r
+       }\r
+       \r
+       @Override\r
+       public int getColumnCount() {\r
+               return used.getColumnCount();\r
+       }\r
+       \r
+       @Override\r
+       public int getRowCount() {\r
+               return used.getRowCount();\r
+       }\r
+       \r
+       @Override\r
+       public Number getValue(Comparable rowKey, Comparable columnKey) {\r
+               return used.getValue(rowKey, columnKey);\r
+       }\r
+       \r
+       @Override\r
+       public Number getValue(int row, int column) {\r
+               return used.getValue(row, column);\r
+       }\r
+       \r
+       @Override\r
+       public List getColumnKeys() {\r
+               return used.getColumnKeys();\r
+       }       \r
+       \r
+       @Override\r
+       public Comparable getColumnKey(int column) {\r
+               return used.getColumnKey(column);\r
+       }\r
+       \r
+       @Override\r
+       public List getRowKeys() {\r
+               return used.getRowKeys();\r
+       }\r
+       \r
+       @Override\r
+       public Comparable getRowKey(int row) {\r
+               return used.getRowKey(row);\r
+       }\r
+       \r
+       @Override\r
+       public int getRowIndex(Comparable key) {\r
+               return used.getRowIndex(key);\r
+       }\r
+       \r
+       @Override\r
+       public int getColumnIndex(Comparable key) {\r
+               return used.getColumnIndex(key);\r
+       }\r
+       \r
+       public Comparable getOther() {\r
+               return other;\r
+       }\r
+       \r
+       @Override\r
+       public void datasetChanged(DatasetChangeEvent event) {\r
+               // bypass change events from the original dataset.\r
+               fireDatasetChanged();\r
+       }\r
+       \r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteringPieDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/FilteringPieDataset.java
new file mode 100644 (file)
index 0000000..acc6f3b
--- /dev/null
@@ -0,0 +1,120 @@
+package org.simantics.jfreechart.chart;\r
+\r
+import java.util.List;\r
+\r
+import org.jfree.data.general.AbstractDataset;\r
+import org.jfree.data.general.DefaultPieDataset;\r
+import org.jfree.data.general.PieDataset;\r
+\r
+/**\r
+ * Filters PieDataset by creating "Other" item for filtered data.\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+@SuppressWarnings("rawtypes")\r
+public class FilteringPieDataset extends AbstractDataset implements PieDataset, FilteredDataset{\r
+       \r
+       private static final long serialVersionUID = -4955124650051030544L;\r
+       \r
+       PieDataset original;\r
+       DefaultPieDataset filtered;\r
+       PieDataset used;\r
+       \r
+\r
+       boolean filtering = true;\r
+       double filterFraction = 0.05;\r
+       \r
+       private Comparable other = "other";\r
+       \r
+       public FilteringPieDataset(PieDataset dataset, Comparable other) {\r
+               this.original = dataset;\r
+               this.filtered = new DefaultPieDataset();\r
+               this.other = other;\r
+               this.used = filtered;\r
+               updateFiltered();\r
+       }\r
+       \r
+       @Override\r
+       public boolean isFiltering() {\r
+               return filtering;\r
+       }\r
+       \r
+       @Override\r
+       public void setFiltering(boolean filtering) {\r
+               this.filtering = filtering;\r
+               if (filtering)\r
+                       used = filtered;\r
+               else\r
+                       used = original;\r
+               fireDatasetChanged();\r
+       }\r
+       \r
+\r
+       public void setFilterFraction(double filterFraction) {\r
+               this.filterFraction = filterFraction;\r
+       }\r
+       \r
+       public double getFilterFraction() {\r
+               return filterFraction;\r
+       }\r
+       \r
+       public void updateFiltered() {\r
+               filtered.clear();\r
+               Double total = 0.0;\r
+               Double other = 0.0;\r
+               for (Object key : original.getKeys()) {\r
+                       total += original.getValue((Comparable) key).doubleValue();\r
+               }\r
+               total *= filterFraction;\r
+               for (Object key : original.getKeys()) {\r
+                       Number value = original.getValue((Comparable) key).doubleValue();\r
+                       \r
+                       if (value.doubleValue() > total) {\r
+                               filtered.setValue((Comparable) key,value);\r
+                       } else {\r
+                               other += value.doubleValue(); \r
+                       }\r
+               }\r
+               if (other > 0.0) {\r
+                       filtered.setValue(this.other, other);\r
+               }\r
+               fireDatasetChanged();\r
+               \r
+       }\r
+       \r
+       @Override\r
+       public List getKeys() {\r
+               return used.getKeys();\r
+       }\r
+       \r
+       @Override\r
+       public int getItemCount() {\r
+               return used.getItemCount();\r
+       }\r
+       \r
+       @Override\r
+       public Comparable getKey(int index) {\r
+               return used.getKey(index);\r
+       }\r
+       \r
+       @Override\r
+       public int getIndex(Comparable key) {\r
+               return used.getIndex(key);\r
+       }\r
+       \r
+       @Override\r
+       public Number getValue(Comparable key) {\r
+               return used.getValue(key);\r
+       }\r
+       \r
+       @Override\r
+       public Number getValue(int index) {\r
+               return used.getValue(index);\r
+       }\r
+       \r
+       public Comparable getOther() {\r
+               return other;\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IAxis.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IAxis.java
new file mode 100644 (file)
index 0000000..c92f243
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IDataset.java
new file mode 100644 (file)
index 0000000..6af906e
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IJFreeChart.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IJFreeChart.java
new file mode 100644 (file)
index 0000000..44569d6
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************\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
+    public IPlot getPlot();\r
+    \r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IJFreeChartComponent.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IJFreeChartComponent.java
new file mode 100644 (file)
index 0000000..27e1d4c
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IPlot.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IPlot.java
new file mode 100644 (file)
index 0000000..7a2beb4
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************\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.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
+    public void configurePlot(PlotProperties properties);\r
+    \r
+    public PlotProperties getPlotProperties();\r
+    \r
+    public void setJFreeChart(JFreeChart jfreechart);\r
+    \r
+    public JFreeChart getJfreechart();\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IRenderer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/IRenderer.java
new file mode 100644 (file)
index 0000000..7f68e8f
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ITitle.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ITitle.java
new file mode 100644 (file)
index 0000000..aa50612
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/JFreeChart.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/JFreeChart.java
new file mode 100644 (file)
index 0000000..a76cb1d
--- /dev/null
@@ -0,0 +1,209 @@
+/*******************************************************************************\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
+    protected org.jfree.chart.JFreeChart jfreechart;\r
+    protected JFreeChartListener listener;\r
+    protected IPlot plot;\r
+    protected ITitle title;\r
+    protected 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
+        initialize(graph);\r
+    }\r
+    \r
+    protected JFreeChart() {\r
+       // default constructor is used with inherited classes.\r
+    }\r
+    \r
+    protected void initialize(ReadGraph graph) {\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 = getPlot(graph,plotResource);\r
+             } \r
+\r
+         } catch(DatabaseException e) {\r
+             e.printStackTrace();\r
+         }\r
+    }\r
+    \r
+    protected IPlot getPlot(ReadGraph graph, Resource plotResource) throws DatabaseException{\r
+       return graph.adapt(plotResource, IPlot.class);\r
+    }\r
+\r
+\r
+    \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
+        plot.setJFreeChart(jfreechart);\r
+        \r
+        if(listener == null) {\r
+            listener = new JFreeChartListener();\r
+            SimanticsUI.getSession().asyncRequest(new JFreeChartQuery(), listener);\r
+        }\r
+\r
+        return jfreechart;\r
+    }\r
+    \r
+    @Override\r
+    public IPlot getPlot() {\r
+       return plot;\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
+    protected class JFreeChartQuery implements Read<Pair<ITitle, Boolean>> {\r
+       \r
+       public JFreeChartQuery() {\r
+               }\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
+    }\r
+    \r
+    protected class JFreeChartListener implements Listener<Pair<ITitle, Boolean>> {\r
+\r
+        private boolean disposed = false;\r
+        private LegendTitle legend;\r
+        \r
+        public JFreeChartListener() {\r
+               \r
+        }\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/NumberAxis.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/NumberAxis.java
new file mode 100644 (file)
index 0000000..a4216e1
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************\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
+        ((org.jfree.chart.axis.NumberAxis)axis).setAutoRangeIncludesZero(false);\r
+        ((ExtendedNumberAxis)axis).setLower(min);\r
+        ((ExtendedNumberAxis)axis).setUpper(max);\r
+        return super.getAxis();\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PieDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PieDataset.java
new file mode 100644 (file)
index 0000000..c45eb95
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************\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<T extends Comparable<T>> 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<T, 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<T, Boolean> getExplodedMap();\r
+    \r
+   \r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PiePlot.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PiePlot.java
new file mode 100644 (file)
index 0000000..f06bdbe
--- /dev/null
@@ -0,0 +1,173 @@
+/*******************************************************************************\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
+    protected org.jfree.data.general.PieDataset pieDataset;\r
+    private DatasetChangeListener changeListener;\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
+    protected static 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
+        Boolean useFilter = graph.getPossibleRelatedValue(resource, JFreeChartResource.getInstance(graph).Filter_used, Bindings.BOOLEAN);\r
+        Double  filterFraction = graph.getPossibleRelatedValue(resource, JFreeChartResource.getInstance(graph).Filter_fraction, Bindings.DOUBLE);\r
+        properties.otherProperties.put("useFilter", useFilter);\r
+        properties.otherProperties.put("filterFraction", filterFraction);\r
+    }\r
+    \r
+    @SuppressWarnings({ "unchecked", "rawtypes" })\r
+    @Override\r
+    protected void setPlotProperties(PlotProperties properties) {\r
+        if(!(plot instanceof org.jfree.chart.plot.PiePlot))\r
+            return;\r
+        \r
+        final org.jfree.chart.plot.PiePlot piePlot = (org.jfree.chart.plot.PiePlot)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 && changeListener != null) {\r
+                pieDataset.removeChangeListener(changeListener);\r
+            }\r
+            \r
+            pieDataset = (org.jfree.data.general.PieDataset)dataset;\r
+            piePlot.setDataset(pieDataset);\r
+            \r
+            if (pieDataset instanceof FilteredDataset) {\r
+               FilteredDataset f = (FilteredDataset)pieDataset;\r
+               Boolean useFilter = (Boolean)properties.otherProperties.get("useFilter");\r
+                Double filterFraction = (Double)properties.otherProperties.get("filterFraction");\r
+                if (useFilter != null && filterFraction != null) {\r
+                       f.setFiltering(useFilter);\r
+                       f.setFilterFraction(filterFraction*0.01);\r
+                       f.updateFiltered();\r
+                } else {\r
+                       f.setFiltering(false);\r
+                }\r
+            }\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
+            changeListener = new DatasetChangeListener() {\r
+                \r
+                               @Override\r
+                public void datasetChanged(DatasetChangeEvent event) {\r
+                    HashMap<Comparable<?>, Color> colorMap = ((PieDataset)ds).getColorMap();\r
+                    HashMap<Comparable<?>, 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(Comparable<?> 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(Comparable<?> name : colorMap.keySet())\r
+                        piePlot.setSectionPaint(name, colorMap.get(name));\r
+                }\r
+            };\r
+            \r
+            pieDataset.addChangeListener(changeListener);\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
+        super.setPlotProperties(properties);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PlotProperties.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/PlotProperties.java
new file mode 100644 (file)
index 0000000..37c21bc
--- /dev/null
@@ -0,0 +1,44 @@
+package org.simantics.jfreechart.chart;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+\r
+public class PlotProperties {\r
+        \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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/StackedBarRenderer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/StackedBarRenderer.java
new file mode 100644 (file)
index 0000000..a7da60c
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/TextTitle.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/TextTitle.java
new file mode 100644 (file)
index 0000000..bdb73de
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYAreaRenderer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYAreaRenderer.java
new file mode 100644 (file)
index 0000000..6c68034
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYDataset.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYDataset.java
new file mode 100644 (file)
index 0000000..d7433d6
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYLineRenderer.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYLineRenderer.java
new file mode 100644 (file)
index 0000000..7d5abb2
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYPlot.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/XYPlot.java
new file mode 100644 (file)
index 0000000..4ffae63
--- /dev/null
@@ -0,0 +1,106 @@
+/*******************************************************************************\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.plot.PlotOrientation;\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
+        Boolean orientation = (Boolean)properties.otherProperties.get("orientation");\r
+        if(orientation != null) {\r
+               if (orientation)\r
+                       xyplot.setOrientation(PlotOrientation.HORIZONTAL);\r
+               else\r
+                       xyplot.setOrientation(PlotOrientation.VERTICAL);\r
+        }\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartBoundsOutline.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartBoundsOutline.java
new file mode 100644 (file)
index 0000000..990ff4f
--- /dev/null
@@ -0,0 +1,37 @@
+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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartElementFactory.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartElementFactory.java
new file mode 100644 (file)
index 0000000..c1eb01a
--- /dev/null
@@ -0,0 +1,186 @@
+/*******************************************************************************\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.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.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.diagram.ui.DiagramModelHints;\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.ElementHints;\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
+            g.asyncRequest(new WriteRequest() {\r
+                \r
+                @Override\r
+                public void perform(WriteGraph graph) throws DatabaseException {\r
+                    new RemoveElement(\r
+                            (Resource)diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE),\r
+                            (Resource)e.getHint(ElementHints.KEY_OBJECT))\r
+                    .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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartElementWriter.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartElementWriter.java
new file mode 100644 (file)
index 0000000..2fe7fc1
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartNode.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartNode.java
new file mode 100644 (file)
index 0000000..0071503
--- /dev/null
@@ -0,0 +1,292 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartSceneGraph.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ChartSceneGraph.java
new file mode 100644 (file)
index 0000000..7ca9692
--- /dev/null
@@ -0,0 +1,159 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/PopulateChartDropParticipant.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/PopulateChartDropParticipant.java
new file mode 100644 (file)
index 0000000..2d7c5a9
--- /dev/null
@@ -0,0 +1,116 @@
+/*******************************************************************************\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.utils.ui.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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ResizeListener.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/element/ResizeListener.java
new file mode 100644 (file)
index 0000000..4c31a6b
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisChildRule.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisChildRule.java
new file mode 100644 (file)
index 0000000..af8071f
--- /dev/null
@@ -0,0 +1,68 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisDropAction.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisDropAction.java
new file mode 100644 (file)
index 0000000..40bca22
--- /dev/null
@@ -0,0 +1,104 @@
+/*******************************************************************************\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.jfreechart.chart.properties.xyline.AxisAndVariablesExplorerComposite;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.ui.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, int operation) 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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisLabelRule.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/AxisLabelRule.java
new file mode 100644 (file)
index 0000000..d501c6b
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesChildRule.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesChildRule.java
new file mode 100644 (file)
index 0000000..3e058fb
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesDropAction.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesDropAction.java
new file mode 100644 (file)
index 0000000..41c6bb6
--- /dev/null
@@ -0,0 +1,139 @@
+/*******************************************************************************\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.jfreechart.chart.properties.xyline.XYLineAxisAndVariablesTab;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.ui.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, int operation) 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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesLabelDecorationRule.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesLabelDecorationRule.java
new file mode 100644 (file)
index 0000000..b7b9a37
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************\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.utils.ui.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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesLabelRule.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/SeriesLabelRule.java
new file mode 100644 (file)
index 0000000..399c4d0
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************\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.jfreechart.chart.properties.IAllVariablesOfModel;\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
+               IAllVariablesOfModel vom = graph.adapt(resource, IAllVariablesOfModel.class);\r
+               \r
+               String rvi = graph.getPossibleRelatedValue(resource, jfree.variableRVI);\r
+               if (rvi != null) {\r
+                       label =vom.getVariablesLabel(graph, rvi);\r
+                       if (label == null)\r
+                               label = rvi;\r
+               } else\r
+                label = "Set variable";\r
+        }\r
+        return Collections.singletonMap(ColumnKeys.SINGLE, label);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/VariableChildRule.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/ge/VariableChildRule.java
new file mode 100644 (file)
index 0000000..afe693d
--- /dev/null
@@ -0,0 +1,75 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AdjustableTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AdjustableTab.java
new file mode 100644 (file)
index 0000000..a0f8308
--- /dev/null
@@ -0,0 +1,115 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2014 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.events.ControlEvent;\r
+import org.eclipse.swt.events.ControlListener;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.selectionview.StandardProperties;\r
+\r
+/**\r
+ * Tab adjusting the layout depending on its dimensions.\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public abstract class AdjustableTab extends LabelPropertyTabContributor {\r
+\r
+       private Composite spp;\r
+       private ControlListener controlListener;\r
+       private static final int WIDE_SCREEN_WIDTH = 1100;\r
+       protected Composite composite;\r
+       \r
+       public AdjustableTab(Object id) {\r
+           super(id);\r
+       }\r
+       \r
+       @Override\r
+       public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport _support) {\r
+               // Get size of the available area.\r
+               spp = body;\r
+               do {\r
+                       spp = spp.getParent();\r
+               } while (!(spp instanceof StandardProperties));\r
+               \r
+               // Add listener to change the layout when the composite resizes.\r
+               spp.addControlListener(controlListener = new ControlListener(){\r
+\r
+                       @Override\r
+                       public void controlMoved(ControlEvent e) {}\r
+\r
+                       @Override\r
+                       public void controlResized(ControlEvent e) {\r
+                               createLayout();\r
+                       }\r
+               });\r
+               \r
+               // Create the controls and their initial layout.\r
+               createAndAddControls(body, site, context, _support);\r
+               createLayout(); \r
+       }\r
+\r
+       /**\r
+        * Create controls and add them to the tab.\r
+        * @param body the composite where the controls are added.\r
+        * @param site\r
+        * @param context\r
+        * @param _support\r
+        */\r
+       protected abstract void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       ISessionContext context, WidgetSupport _support);\r
+\r
+       /**\r
+        *  Create layout for controls.\r
+        */\r
+       protected void createLayout() {\r
+               if (composite == null || composite.isDisposed())\r
+                       return;\r
+               \r
+               Point size = spp.getSize();\r
+               if (size.x > size.y) {\r
+                       createControlLayoutHorizontal((size.x > WIDE_SCREEN_WIDTH));\r
+               } else {\r
+                       createControlLayoutVertical();\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Determine if the layout uses vertical layout\r
+        * @return true iff the layout uses vertical layout\r
+        */\r
+       protected boolean isVertical() {\r
+               Point size = spp.getSize();\r
+               return size.x < size.y;\r
+       }\r
+       \r
+       /**\r
+        * Create vertical layout for controls.\r
+        */\r
+       protected abstract void createControlLayoutVertical();\r
+\r
+       /**\r
+        * Create horizontal layout for controls.\r
+        * @param wideScreen true iff the control is wider than WIDE_SCREEN_WIDTH\r
+        */\r
+       protected abstract void createControlLayoutHorizontal(boolean wideScreen);\r
+\r
+//     @Override\r
+//     public void dispose() {\r
+//             if(controlListener != null && spp != null)\r
+//                     spp.removeControlListener(controlListener);\r
+//     }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AllVariablesOfModel.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AllVariablesOfModel.java
new file mode 100644 (file)
index 0000000..f3fcd7d
--- /dev/null
@@ -0,0 +1,57 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.Collection;\r
+import java.util.Collections;\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.management.ISessionContext;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.simulation.ontology.SimulationResource;\r
+\r
+public class AllVariablesOfModel implements Read<Collection<ChartVariable>> {\r
+       \r
+       public Resource model;\r
+       \r
+       /**\r
+        * Queries all variables of a model \r
+        * @param res the model.\r
+        */\r
+       public AllVariablesOfModel(Resource res) {\r
+               this.model = res;\r
+       }\r
+       \r
+       public Resource getModel() {\r
+               return model;\r
+       }\r
+       \r
+       @Override\r
+       public Collection<ChartVariable> perform(ReadGraph graph) throws DatabaseException {\r
+               if(!graph.hasStatement(model))\r
+                return Collections.emptyList();\r
+               IAllVariablesOfModel query = graph.adapt(model, IAllVariablesOfModel.class);\r
+               return graph.syncRequest(query.getVariablesQuery());\r
+       }\r
+       \r
+       public static AllVariablesOfModel withRandomResource(ISessionContext context, final Resource resource) throws DatabaseException {\r
+               Resource 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
+               if (model == null)\r
+                       return null;\r
+               return new AllVariablesOfModel(model);\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AxisHidePropertyComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/AxisHidePropertyComposite.java
new file mode 100644 (file)
index 0000000..02960a8
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/BooleanPropertyFactory.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/BooleanPropertyFactory.java
new file mode 100644 (file)
index 0000000..751a134
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/BooleanSelectionListener.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/BooleanSelectionListener.java
new file mode 100644 (file)
index 0000000..ff27eb2
--- /dev/null
@@ -0,0 +1,98 @@
+/*******************************************************************************\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.layer0.util.Layer0Utils;\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
+    final private boolean defaultValue;\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, false);\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
+     * @param defaultValue expected value if the property does not exist\r
+     */\r
+    public BooleanSelectionListener(ISessionContext context, String typeUri, String propertyURI, boolean defaultValue) {\r
+        super(context);\r
+        this.propertyURI = propertyURI;\r
+        this.typeUri = typeUri;\r
+        this.defaultValue = defaultValue;\r
+    }\r
+    \r
+    public BooleanSelectionListener(ISessionContext context, String typeUri, String propertyURI) {\r
+       this(context, typeUri, propertyURI, false);\r
+    }\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
+        if (value == null) {\r
+               graph.claimLiteral(resource, property, !defaultValue);\r
+               Layer0Utils.addCommentMetadata(graph, "Modified " + graph.getPossibleRelatedValue2(property, Layer0.getInstance(graph).HasName, Bindings.STRING) + " for " + graph.getPossibleRelatedValue2(resource, Layer0.getInstance(graph).HasLabel, Bindings.STRING) + " to " + !defaultValue);\r
+        } else { \r
+            boolean newValue = Boolean.FALSE.equals(value);\r
+               graph.claimLiteral(resource, property, newValue);\r
+            Layer0Utils.addCommentMetadata(graph, "Modified " + graph.getPossibleRelatedValue2(property, Layer0.getInstance(graph).HasName, Bindings.STRING) + " for " + graph.getPossibleRelatedValue2(resource, Layer0.getInstance(graph).HasLabel, Bindings.STRING) + " to " + newValue);\r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartTab.java
new file mode 100644 (file)
index 0000000..1135348
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************\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.utils.ui.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
+    public ChartTab(Object id) {\r
+        super(id);\r
+    }\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariable.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariable.java
new file mode 100644 (file)
index 0000000..20ee638
--- /dev/null
@@ -0,0 +1,60 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+public class ChartVariable implements Comparable<ChartVariable>{\r
+       \r
+       private String rvi;\r
+       private String label;\r
+       \r
+       public ChartVariable(String rvi) {\r
+               this.rvi = rvi;\r
+       }\r
+       \r
+       public ChartVariable(String rvi, String label) {\r
+               this.rvi = rvi;\r
+               this.label = label;\r
+       }\r
+       \r
+       public String getRvi() {\r
+               return rvi;\r
+       }\r
+       \r
+       public String getLabel() {\r
+               return label;\r
+       }\r
+       \r
+       @Override\r
+       public String toString() {\r
+               if (label != null)\r
+                       return label;\r
+               return rvi;\r
+       }\r
+       \r
+       @Override\r
+       public int hashCode() {\r
+               return rvi.hashCode();\r
+       }\r
+       \r
+       @Override\r
+       public boolean equals(Object obj) {\r
+               if (obj == null)\r
+                       return false;\r
+               if (obj.getClass() != getClass())\r
+                       return false;\r
+               ChartVariable other = (ChartVariable)obj;\r
+               return rvi.equals(other.rvi);\r
+       }\r
+       \r
+       @Override\r
+       public int compareTo(ChartVariable o) {\r
+               int rvicomp = rvi.compareTo(o.rvi);\r
+               if (rvicomp == 0)\r
+                       return 0;\r
+               if (label != null && o.label != null) {\r
+                       int labelcomp =  label.compareTo(o.label);\r
+                       if (labelcomp != 0)\r
+                               return labelcomp;\r
+               }\r
+               return rvicomp;\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariableFactory.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariableFactory.java
new file mode 100644 (file)
index 0000000..fea5415
--- /dev/null
@@ -0,0 +1,34 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+public class ChartVariableFactory extends ReadFactoryImpl<Resource, ChartVariable>{\r
+       \r
+       private Map<String,ChartVariable> map;\r
+       \r
+       public ChartVariableFactory(Collection<ChartVariable> data) {\r
+               map = new HashMap<String, ChartVariable>();\r
+               for (ChartVariable v : data) {\r
+                       map.put(v.getRvi(), v);\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public ChartVariable perform(ReadGraph graph, Resource input)\r
+                       throws DatabaseException {\r
+                String rvi = graph.getPossibleRelatedValue(input, JFreeChartResource.getInstance(graph).variableRVI);\r
+                if (rvi == null)\r
+                        return null;\r
+                return map.get(rvi);\r
+               \r
+       }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariableModifier.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ChartVariableModifier.java
new file mode 100644 (file)
index 0000000..a1e13dd
--- /dev/null
@@ -0,0 +1,95 @@
+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.TextContentAdapter;\r
+import org.eclipse.swt.widgets.Control;\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
+public class ChartVariableModifier extends StringChooserModifyListenerImpl<Resource, ChartVariable> {\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
+        public ChartVariableModifier(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
+               VariableProposalProvider 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(ChartVariableModifier.this != null)\r
+                               ChartVariableModifier.this.deactivate();\r
+                   }\r
+\r
+                   @Override\r
+                   public void proposalPopupClosed(ContentProposalAdapter adapter) {\r
+                       if(ChartVariableModifier.this != null)\r
+                               ChartVariableModifier.this.activate();\r
+                   }\r
+               });\r
+\r
+               adapter.addContentProposalListener(new IContentProposalListener() {\r
+\r
+                       \r
+                   @Override\r
+                   public void proposalAccepted(IContentProposal proposal) {\r
+                       if(ChartVariableModifier.this.control != null && !ChartVariableModifier.this.control.isDisposed())\r
+                               ChartVariableModifier.this.modifySelection(new StringChooserModifyEvent<ChartVariable>(ChartVariableModifier.this.control, new ChartVariable(proposal.getContent(), proposal.getLabel()), proposal.getLabel()));\r
+                   }\r
+               });\r
+           \r
+           \r
+           }\r
+        \r
+        @Override\r
+       public void applyObject(WriteGraph graph, Resource resource, ChartVariable object, String text) throws DatabaseException {\r
+                   if(active) {\r
+                   JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+                   graph.claimLiteral(resource, jfree.variableRVI, object.getRvi(), Bindings.STRING);\r
+                   graph.deny(resource, jfree.variableFilter);\r
+               }\r
+               \r
+       }\r
+           \r
+\r
+\r
+    public void deactivate() {\r
+        active = false;\r
+    }\r
+\r
+    public void activate() {\r
+        active = true;\r
+    }   \r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ColorPicker.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/ColorPicker.java
new file mode 100644 (file)
index 0000000..7a0d9ce
--- /dev/null
@@ -0,0 +1,402 @@
+/*******************************************************************************\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.Arrays;\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.resource.JFaceResources;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionEvent;\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.Simantics;\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.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.UniqueRead;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.Layer0Utils;\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.layer0.Layer0;\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.gfx.ColorImageDescriptor;\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
+        this(parent, context, support, style, true);\r
+    }\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
+     * @param defaultColor provide default color widget?\r
+     */\r
+    public ColorPicker(Composite parent, ISessionContext context, WidgetSupport support, int style, boolean defaultColor) {\r
+        super(parent, style);\r
+        support.register(this);\r
+        \r
+        if(support.getParameter(WidgetSupport.RESOURCE_MANAGER) == null) {\r
+            LocalResourceManager resourceManager = new LocalResourceManager(JFaceResources.getResources(), this);\r
+            support.setParameter(WidgetSupport.RESOURCE_MANAGER, resourceManager);\r
+        }\r
+        \r
+        if(defaultColor) {\r
+            GridLayoutFactory.fillDefaults().numColumns(4).applyTo(this);\r
+\r
+            this.defaultColor = new Button(this, support, SWT.RADIO);\r
+            this.defaultColor.setText("default");\r
+            this.defaultColor.setSelectionFactory(new DefaultColorSelectionFactory(false));\r
+            this.defaultColor.addSelectionListener(new DefaultColorSelectionListener(context));\r
+            GridDataFactory.fillDefaults().applyTo(this.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
+        } else {\r
+            GridLayoutFactory.fillDefaults().applyTo(this);\r
+        }\r
+        \r
+        \r
+        color = new Button(this, support, SWT.PUSH);\r
+        color.setImageFactory(new ColorImageFactoryFactory(this));\r
+        color.addSelectionListener(new ColorSelectionListener(context));\r
+        color.getWidget().setEnabled(false);\r
+        GridDataFactory.fillDefaults().applyTo(color.getWidget());\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<Float[]>() {\r
+\r
+            @Override\r
+            public Float[] perform(ReadGraph graph) throws DatabaseException {\r
+                if(graph.hasStatement(getResource(graph, resource), getColorRelation(graph))) {\r
+                    float[] components = graph.getPossibleRelatedValue(getResource(graph, resource), getColorRelation(graph));\r
+                    Float[] result = new Float[components.length];\r
+                    for(int i = 0; i < components.length; i++) result[i] = components[i];\r
+                    return result;\r
+                } else {\r
+                    return null;\r
+                }\r
+            }\r
+            \r
+        }, new Listener<Float[]>() {\r
+\r
+            @Override\r
+            public void execute(Float[] result) {\r
+                if(!color.getWidget().isDisposed()) {\r
+                    color.getWidget().getDisplay().asyncExec(new RunnableWithObject(result != null ? true : false) {\r
+                        @Override\r
+                        public void run() {\r
+                            if(!color.getWidget().isDisposed()) {\r
+                                if(!Boolean.TRUE.equals(getObject()))\r
+                                    color.getWidget().setEnabled(false);\r
+                                else\r
+                                    color.getWidget().setEnabled(true);\r
+                            }\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
+    /**\r
+     * ImageFactory returning an image for color button\r
+     * @author Teemu Lempinen\r
+     *\r
+     */\r
+    private class ColorImageFactoryFactory extends ReadFactoryImpl<Resource, ImageDescriptor> {\r
+        \r
+        private ColorPicker picker;\r
+        \r
+        public ColorImageFactoryFactory(ColorPicker colorPicker) {\r
+            this.picker = colorPicker;\r
+        }\r
+\r
+        @Override\r
+        public ImageDescriptor perform(ReadGraph graph, Resource input) throws DatabaseException {\r
+            RGB rgb = getColor(graph, getResource(graph, input));\r
+            return new ColorImageDescriptor(rgb.red, rgb.green, rgb.blue, 20, 20, false);\r
\r
+        }\r
+        \r
+        @Override\r
+        public Object getIdentity(Object inputContents) {\r
+            return new Triple<Object, ColorPicker, Class<?>>(inputContents, picker, getClass());\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 beforeApply(final Resource input) {\r
+            try {\r
+                final RGB oldRGB = Simantics.getSession().syncRequest(new UniqueRead<RGB>() {\r
+\r
+                    @Override\r
+                    public RGB perform(ReadGraph graph) throws DatabaseException {\r
+                        Resource resource = getResource(graph, input);\r
+                        return getColor(graph, resource);\r
+                    }\r
+                });\r
+                \r
+                final Display display = color.getWidget().getDisplay();\r
+                \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(oldRGB);\r
+                rgb = cd.open();\r
+                if(rgb == null)\r
+                    return;\r
+                \r
+                \r
+            } catch (DatabaseException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+\r
+        @Override\r
+        public void apply(WriteGraph graph, Resource input) throws DatabaseException {\r
+            \r
+            G2DResource g2d = G2DResource.getInstance(graph);\r
+            float[] components = new float[] {rgb.red / 255.0f,  rgb.green / 255.0f, rgb.blue / 255.0f, 1.0f};\r
+            Resource resource = getResource(graph, input);\r
+            float[] currentComponents = graph.getPossibleRelatedValue2(resource, getColorRelation(graph));\r
+            if (currentComponents == null || !Arrays.equals(components, currentComponents)) {\r
+                graph.claimLiteral(resource, getColorRelation(graph), g2d.Color, components);\r
+                Layer0Utils.addCommentMetadata(graph, "Modified color of " + NameUtils.getSafeName(graph, resource) + " to " + Arrays.toString(components));\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 final 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
+                    Layer0Utils.addCommentMetadata(graph, "Color for " + graph.getPossibleRelatedValue2(resource, Layer0.getInstance(graph).HasName, Bindings.STRING) + " set to custom ");\r
+                }\r
+            } else {\r
+                // Default selected, remove color definition\r
+                Object o = graph.getPossibleObject(resource, getColorRelation(graph));\r
+                if (o != null) {\r
+                    graph.deny(resource, getColorRelation(graph));\r
+                    Layer0Utils.addCommentMetadata(graph, "Color for " + graph.getPossibleRelatedValue2(resource, Layer0.getInstance(graph).HasName, Bindings.STRING) + " set to Default");\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoublePropertyFactory2.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoublePropertyFactory2.java
new file mode 100644 (file)
index 0000000..3bd4250
--- /dev/null
@@ -0,0 +1,119 @@
+/*******************************************************************************\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 double property. Supports also finding the \r
+ * property from a first occurrence of resource ConsistsOf type HasProperty   \r
+ * \r
+ * @author Teemu Lempinen\r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class DoublePropertyFactory2 extends ReadFactoryImpl<Resource, String> {\r
+\r
+    final private String propertyURI;\r
+    final private String typeURI;\r
+    final private Double defaultValue;\r
+    \r
+    /**\r
+     * PropertyFactory for finding a boolean property with propertyURI\r
+     * \r
+     * @param propertyURI URI for the boolean property\r
+     */\r
+    public DoublePropertyFactory2(String propertyURI) {\r
+        this(null, propertyURI);\r
+    }\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 DoublePropertyFactory2(String typeURI, String propertyURI) {\r
+        this(typeURI, propertyURI, 0.0);\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 DoublePropertyFactory2(String typeURI, String propertyURI, double defaultValue) {\r
+        this.propertyURI = propertyURI;\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, Double>((Resource) inputContents, propertyURI, getClass(), defaultValue);\r
+    }\r
+\r
+    @Override\r
+    public String 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 "";\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 String getValue(ReadGraph graph, Resource resource) throws DatabaseException {\r
+        Double value = graph.getPossibleRelatedValue(resource, graph.getResource(propertyURI), Bindings.DOUBLE);\r
+        if(value != null) {\r
+            return value.toString();\r
+        } else if (defaultValue != null){\r
+            return defaultValue.toString();\r
+        }\r
+        return "";\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoublePropertyModifier2.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoublePropertyModifier2.java
new file mode 100644 (file)
index 0000000..a7dfe81
--- /dev/null
@@ -0,0 +1,49 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListenerImpl;\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
+public class DoublePropertyModifier2 extends TextModifyListenerImpl<Resource> {\r
+\r
+       final private String typeUri;\r
+    final private String propertyURI;\r
+\r
+    public DoublePropertyModifier2(ISessionContext context, String propertyURI) {\r
+        this.propertyURI = propertyURI;\r
+        this.typeUri = null;\r
+    }\r
+    \r
+    public DoublePropertyModifier2(ISessionContext context, String typeURI, String propertyURI) {\r
+        this.propertyURI = propertyURI;\r
+        this.typeUri = typeURI;\r
+    }\r
+\r
+    @Override\r
+    public void applyText(WriteGraph graph, Resource input, String text) throws DatabaseException {\r
+        if (typeUri == null)\r
+               applyValue(graph, input, text);\r
+        else {\r
+               Resource type =  graph.getResource(typeUri);\r
+            for(Resource object : graph.syncRequest(new ObjectsWithType(input, Layer0.getInstance(graph).ConsistsOf, type))) {\r
+                applyValue(graph, object,text);\r
+            }\r
+        }\r
+       \r
+    }\r
+    \r
+    private void applyValue(WriteGraph graph, Resource input, String text) throws DatabaseException {\r
+       if (text == null || text.trim().isEmpty()) {\r
+            if (graph.hasStatement(input, graph.getResource(propertyURI)))\r
+                graph.denyValue(input, graph.getResource(propertyURI));\r
+        } else {\r
+            graph.claimLiteral(input, graph.getResource(propertyURI), Double.parseDouble(text), Bindings.DOUBLE);\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoubleValidator.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/DoubleValidator.java
new file mode 100644 (file)
index 0000000..e41c9b0
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/IAllVariablesOfModel.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/IAllVariablesOfModel.java
new file mode 100644 (file)
index 0000000..9557315
--- /dev/null
@@ -0,0 +1,17 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+\r
+public interface IAllVariablesOfModel {\r
+       \r
+       \r
+       public Read<Collection<ChartVariable>> getVariablesQuery();\r
+       \r
+       public String getVariablesLabel(ReadGraph graph, String rvi) throws DatabaseException;\r
+\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/JFreeChartPropertyColorProvider.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/JFreeChartPropertyColorProvider.java
new file mode 100644 (file)
index 0000000..ab4c432
--- /dev/null
@@ -0,0 +1,57 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/LabelPropertyTabContributor.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/LabelPropertyTabContributor.java
new file mode 100644 (file)
index 0000000..b1cbbbf
--- /dev/null
@@ -0,0 +1,90 @@
+/*******************************************************************************\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.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.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.selectionview.PropertyTabContributorImpl;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+\r
+public abstract class LabelPropertyTabContributor extends PropertyTabContributorImpl {\r
+\r
+    protected final Object id;\r
+    \r
+    public LabelPropertyTabContributor(Object id) {\r
+        assert (id != null);\r
+        this.id = id;\r
+    }\r
+    \r
+    @Override\r
+    public Read<String> getPartNameReadRequest(final ISelection forSelection) {\r
+\r
+        return 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
+                       final Variable variable = AdaptionUtils.adaptToSingle(forSelection, Variable.class);\r
+                final Resource resource = AdaptionUtils.adaptToSingle(forSelection, Resource.class);\r
+                if(resource == null && variable == null) {\r
+                       return "Selection";\r
+                }\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
+            \r
+        };\r
+        \r
+    }\r
+\r
+    @Override\r
+    public int hashCode() {\r
+        return id.hashCode();\r
+    }\r
+\r
+    @Override\r
+    public boolean equals(Object obj) {\r
+        if (this == obj)\r
+            return true;\r
+        if (obj == null)\r
+            return false;\r
+        if (getClass() != obj.getClass())\r
+            return false;\r
+        LabelPropertyTabContributor other = (LabelPropertyTabContributor) obj;\r
+        return id.equals(other.id);\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RVIFactory.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RVIFactory.java
new file mode 100644 (file)
index 0000000..52a9a63
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RVIModifier.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RVIModifier.java
new file mode 100644 (file)
index 0000000..3c87d5a
--- /dev/null
@@ -0,0 +1,135 @@
+/*******************************************************************************\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.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.ReadGraph;\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
+    private String rviUri;\r
+    private String indexUri;\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, support, JFreeChartResource.URIs.variableRVI, JFreeChartResource.URIs.variableFilter);\r
+    }\r
+        \r
+        \r
+    public RVIModifier(Control control, WidgetSupport support, String rviRelationUri, String indexUri) {\r
+        this.rviUri = rviRelationUri;\r
+        this.indexUri = indexUri;\r
+        \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
+        VariableProposalProvider 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
+            graph.claimLiteral(resource, getRVIRelation(graph), text, Bindings.STRING);\r
+            graph.deny(resource, getIndexRelation(graph));\r
+        }\r
+    }\r
+    \r
+    private Resource getRVIRelation(ReadGraph graph) throws DatabaseException {\r
+        return graph.getResource(rviUri);\r
+    }\r
+    \r
+    private Resource getIndexRelation(ReadGraph graph) throws DatabaseException {\r
+        return graph.getResource(indexUri);\r
+    }\r
+\r
+    public void deactivate() {\r
+        active = false;\r
+    }\r
+\r
+    public void activate() {\r
+        active = true;\r
+    }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RangeComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RangeComposite.java
new file mode 100644 (file)
index 0000000..2b3ce82
--- /dev/null
@@ -0,0 +1,296 @@
+/*******************************************************************************\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
+import java.util.Map;\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
+\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, 0).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
+                        composite.layout();\r
+\r
+                        if(getObject() == null) {\r
+                               // No range, print an em dash.\r
+                               Label label = new Label(composite, SWT.NONE);\r
+                            label.setText("\u2014");\r
+                            label.setEnabled(false);\r
+                            GridDataFactory.fillDefaults().applyTo(label);\r
+                            composite.layout();\r
+                            return;\r
+                        }\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
+                        // Set the width of the combo \r
+                        GridLayout gl = (GridLayout)composite.getLayout();\r
+                        gl.numColumns = result.size();\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 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.layout();\r
+                        Composite previousParent = composite.getParent();\r
+                        for(int i = 0; i < 7 && previousParent != null; i++) {\r
+                            previousParent.layout();\r
+                            if(previousParent.getParent() instanceof ScrolledComposite) {\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
+            String[] filter = graph.getPossibleRelatedValue(series, getIndexRelation(graph), Bindings.STRING_ARRAY);\r
+\r
+\r
+            /*\r
+             * If no filter was found or the index is not applicable, return the first index\r
+             */\r
+            String result = null;\r
+            if(filter == null)\r
+                result = getFirstIndex(graph, series, index);\r
+            else if(filter.length < index)\r
+                result = getFirstIndex(graph, series, index);      \r
+            else\r
+                result = filter[index];\r
+\r
+            return result;\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
+            Resource filterRelation = getIndexRelation(graph);\r
+            String[] filter = graph.getPossibleRelatedValue(series, filterRelation, 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] = getFirstIndex(graph, series, i);\r
+                }\r
+            }\r
+\r
+            // Modify the filter index\r
+            filter[index] = text;\r
+            graph.claimLiteral(series, filterRelation, filter, Bindings.STRING_ARRAY);\r
+        }\r
+    }\r
+\r
+    protected Resource getIndexRelation(ReadGraph graph) {\r
+        JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+        return jfree.variableFilter;\r
+    }\r
+    \r
+    private static String getFirstIndex(ReadGraph graph, Resource series, int index) throws DatabaseException {\r
+        RangeHandlerFactory f = graph.adapt(series, RangeHandlerFactory.class);\r
+        LinkedHashMap<String, Resource> map = graph.syncRequest(f.getRequest(series));\r
+        if(map == null)\r
+            return null;\r
+        else {\r
+            Resource enumeration = null;\r
+            Iterator<Resource> iterator = map.values().iterator();\r
+            for(int i = 0; i <= index && iterator.hasNext(); i++) {\r
+                enumeration = iterator.next();\r
+            }\r
+            if(enumeration != null) {\r
+                Map<String, Object> indexmap = f.getRangeItemFactory(index, enumeration).perform(graph, null);\r
+                if(indexmap != null)\r
+                    return indexmap.values().iterator().next().toString();\r
+            }\r
+        }\r
+\r
+        return null;\r
+    }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RangeHandlerFactory.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/RangeHandlerFactory.java
new file mode 100644 (file)
index 0000000..f015878
--- /dev/null
@@ -0,0 +1,15 @@
+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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooser.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooser.java
new file mode 100644 (file)
index 0000000..ce1b351
--- /dev/null
@@ -0,0 +1,600 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.Assert;\r
+import org.eclipse.core.runtime.ListenerList;\r
+import org.eclipse.jface.resource.JFaceResources;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.resource.ResourceManager;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.MouseTrackListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Font;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.simantics.browsing.ui.swt.widgets.DefaultColorProvider;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ITrackedColorProvider;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.procedure.Listener;\r
+\r
+/**\r
+ * Widget for choosing and labeled object from a set of objects.\r
+ * \r
+ * Supports cases when multiple objects have the same label (as much as possible)\r
+ * \r
+ * \r
+ * Based on org.simantics.browsing.ui.swt.widgets.Trackedtext\r
+ * \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class StringChooser<T> implements Widget{\r
+    private static final int      EDITING                 = 1 << 0;\r
+    private static final int      MODIFIED_DURING_EDITING = 1 << 1;\r
+\r
+    /**\r
+     * Used to tell whether or not a mouseDown has occurred after a focusGained\r
+     * event to be able to select the whole text field when it is pressed for\r
+     * the first time while the widget holds focus.\r
+     */\r
+    private static final int      MOUSE_DOWN_FIRST_TIME   = 1 << 2;\r
+    private static final int      MOUSE_INSIDE_CONTROL    = 1 << 3;\r
+    \r
+    private int                   caretPositionBeforeEdit;\r
+    \r
+    private String                textBeforeEdit;\r
+\r
+    private int                   state;\r
+\r
+       private Map<T,String> objectToLabel;\r
+       private Set<String> allowedLabels;\r
+       \r
+       private T selected;\r
+       \r
+    private final Display         display;\r
+\r
+    private final Text            text;\r
+    \r
+    private CompositeListener     listener;\r
+\r
+    private ListenerList          modifyListeners;\r
+\r
+    private ReadFactory<?, T>     objectFactory;\r
+    \r
+    private ITrackedColorProvider colorProvider;\r
+\r
+    private final ResourceManager resourceManager;\r
+    \r
+       private boolean moveCaretAfterEdit = true;\r
+       \r
+       private boolean selectAllOnStartEdit = true;\r
+       \r
+       public StringChooser(Composite parent, WidgetSupport support, int style) {\r
+               this.state = 0;\r
+        this.text = new Text(parent, style);\r
+        this.display = text.getDisplay();\r
+        this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), text);\r
+        this.colorProvider = new DefaultColorProvider(resourceManager);\r
+        if (support!=null) support.register(this);\r
+        initialize();\r
+       }\r
+       \r
+\r
+       \r
+       public ResourceManager getResourceManager() {\r
+       return resourceManager;\r
+    }\r
+       \r
+       public void setFont(Font font) {\r
+               text.setFont(font);\r
+       }\r
+       \r
+       public void setObjectFactory(ReadFactory<?, T> objectFactory) {\r
+               this.objectFactory = objectFactory;\r
+       }\r
+       \r
+       public void setMoveCaretAfterEdit(boolean value) {\r
+               this.moveCaretAfterEdit = value;\r
+       }\r
+       \r
+       public void setData(Map<T,String> data) {\r
+               this.objectToLabel = data;\r
+               this.allowedLabels = new HashSet<String>();\r
+               this.allowedLabels.addAll(objectToLabel.values());\r
+       }\r
+       \r
+       public void setData(Collection<T> data) {\r
+               this.objectToLabel = new HashMap<T, String>();\r
+               this.allowedLabels = new HashSet<String>();\r
+               for (T t : data) {\r
+                       String label = t.toString();\r
+                       objectToLabel.put(t, label);\r
+                       allowedLabels.add(label);\r
+               }\r
+       }\r
+       \r
+       public void setSelected(T selected) {\r
+               if (selected != null) {\r
+                       String label = objectToLabel.get(selected);\r
+                       if (label == null)\r
+                               return;\r
+                       this.selected = selected;\r
+                       this.text.setText(label);\r
+               } else {\r
+                       this.selected = null;\r
+                       this.text.setText("");\r
+               }\r
+       }\r
+       \r
+       public void setSelected(String label) {\r
+               // TODO : we could create a label to object map.\r
+               for (T t : objectToLabel.keySet()) {\r
+                       if (label.equals(objectToLabel.get(t))) {\r
+                               setSelected(t);\r
+                               return;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       \r
+       @Override\r
+       public void setInput(ISessionContext context, Object input) {\r
+        if (modifyListeners != null) {\r
+            for (Object o : modifyListeners.getListeners()) {\r
+               if(o instanceof Widget) {\r
+                    ((Widget) o).setInput(context, input);\r
+               }\r
+            }\r
+        }\r
+               \r
+               if(objectFactory != null) {\r
+                       objectFactory.listen(context, input, new Listener<T>() {\r
+\r
+                               @Override\r
+                public void exception(final Throwable t) {\r
+                                       display.asyncExec(new Runnable() {\r
+\r
+                                               @Override\r
+                                               public void run() {\r
+                                                       if(isDisposed()) return;\r
+//                                                     System.out.println("Button received new text: " + text);\r
+                                                       text.setText(t.toString());\r
+                                               }\r
+\r
+                                       });\r
+                               }\r
+\r
+                               @Override\r
+                               public void execute(final T object) {\r
+                                       \r
+                                       if(text.isDisposed()) return;\r
+                                       \r
+                                       display.asyncExec(new Runnable() {\r
+\r
+                                               @Override\r
+                                               public void run() {\r
+                                                       if(isDisposed()) return;\r
+                                                       setSelected(object);\r
+//                                                     text.getParent().layout();\r
+//                                                     text.getParent().getParent().layout();\r
+                                               }\r
+\r
+                                       });\r
+                               }\r
+\r
+                               @Override\r
+                               public boolean isDisposed() {\r
+                                       return text.isDisposed();\r
+                               }\r
+\r
+                       });\r
+               }\r
+               \r
+       }\r
+       \r
+       /**\r
+     * Common initialization. Assumes that text is already created.\r
+     */\r
+    private void initialize() {\r
+        Assert.isNotNull(text);\r
+\r
+        text.setBackground(colorProvider.getInactiveBackground());\r
+        text.setDoubleClickEnabled(false);\r
+\r
+        listener = new CompositeListener();\r
+\r
+        text.addModifyListener(listener);\r
+        text.addDisposeListener(listener);\r
+        text.addKeyListener(listener);\r
+        text.addMouseTrackListener(listener);\r
+        text.addMouseListener(listener);\r
+        text.addFocusListener(listener);\r
+    }\r
+    \r
+    public void startEdit(boolean selectAll) {\r
+        if (isEditing()) {\r
+            // Print some debug incase we end are in an invalid state\r
+            System.out.println("TrackedText: BUG: startEdit called when in editing state");\r
+        }\r
+//        System.out.println("start edit: selectall=" + selectAll + ", text=" + text.getText() + ", caretpos=" + caretPositionBeforeEdit);\r
+\r
+        // Backup text-field data for reverting purposes\r
+        caretPositionBeforeEdit = text.getCaretPosition();\r
+        textBeforeEdit = text.getText();\r
+\r
+        // Signal editing state\r
+        setBackground(colorProvider.getEditingBackground());\r
+\r
+        if (selectAll) {\r
+            text.selectAll();\r
+        }\r
+        state |= EDITING | MOUSE_DOWN_FIRST_TIME;\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+       private void applyEdit() {\r
+        try {\r
+            if (isTextValid() != null) {\r
+                text.setText(textBeforeEdit);\r
+            } else if (isModified() && !text.getText().equals(textBeforeEdit)) {\r
+               setSelected(text.getText());\r
+                //System.out.println("apply");\r
+                if (modifyListeners != null) {\r
+                    StringChooserModifyEvent<T> event = new StringChooserModifyEvent<T>(text, selected, text.getText());\r
+                    for (Object o : modifyListeners.getListeners()) {\r
+                        ((StringChooserModifyListener<T>) o).modifySelection(event);\r
+                    }\r
+                }\r
+            }\r
+        } catch (Throwable t) {\r
+            t.printStackTrace();\r
+        } finally {\r
+            endEdit();\r
+        }\r
+    }\r
+\r
+    private void endEdit() {\r
+        if (text.isDisposed())\r
+            return;\r
+\r
+        if (!isEditing()) {\r
+            // Print some debug incase we end are in an invalid state\r
+            //ExceptionUtils.logError(new Exception("BUG: endEdit called when not in editing state"));\r
+            //System.out.println();\r
+        }\r
+        setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
+//        System.out.println("endEdit: " + text.getText() + ", caret: " + text.getCaretLocation() + ", selection: " + text.getSelection());\r
+        // Always move the caret to the end of the string\r
+        if(moveCaretAfterEdit)\r
+            text.setSelection(text.getCharCount());\r
+        state &= ~(EDITING | MOUSE_DOWN_FIRST_TIME);\r
+        setModified(false);\r
+    }\r
+\r
+    private void revertEdit() {\r
+        if (!isEditing()) {\r
+            // Print some debug incase we end are in an invalid state\r
+            //ExceptionUtils.logError(new Exception("BUG: revertEdit called when not in editing state"));\r
+            System.out.println("BUG: revertEdit called when not in editing state");\r
+        }\r
+        text.setText(textBeforeEdit);\r
+        text.setSelection(caretPositionBeforeEdit);\r
+        setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
+        state &= ~(EDITING | MOUSE_DOWN_FIRST_TIME);\r
+        setModified(false);\r
+    }\r
+\r
+    private boolean isEditing() {\r
+        return (state & EDITING) != 0;\r
+    }\r
+\r
+    private void setModified(boolean modified) {\r
+        if (modified) {\r
+            state |= MODIFIED_DURING_EDITING;\r
+        } else {\r
+            state &= ~MODIFIED_DURING_EDITING;\r
+        }\r
+    }\r
+\r
+    private boolean isMouseInsideControl() {\r
+        return (state & MOUSE_INSIDE_CONTROL) != 0;\r
+    }\r
+\r
+    private void setMouseInsideControl(boolean inside) {\r
+        if (inside)\r
+            state |= MOUSE_INSIDE_CONTROL;\r
+        else\r
+            state &= ~MOUSE_INSIDE_CONTROL;\r
+    }\r
+\r
+    private boolean isModified() {\r
+        return (state & MODIFIED_DURING_EDITING) != 0;\r
+    }\r
+\r
+    public void setSelectAllOnStartEdit(boolean selectAll) {\r
+        this.selectAllOnStartEdit = selectAll;\r
+    }\r
+    \r
+    public void setEditable(boolean editable) {\r
+        if (editable) {\r
+            text.setEditable(true);\r
+            setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
+        } else {\r
+            text.setEditable(false);\r
+            text.setBackground(null);\r
+        }\r
+    }\r
+\r
+    public void setText(String text) {\r
+        this.text.setText(text);\r
+    }\r
+\r
+    public void setTextWithoutNotify(String text) {\r
+        this.text.removeModifyListener(listener);\r
+        setText(text);\r
+        this.text.addModifyListener(listener);\r
+    }\r
+\r
+    public Text getWidget() {\r
+        return text;\r
+    }\r
+\r
+       public synchronized void addModifyListener(StringChooserModifyListener<T> listener) {\r
+        if (modifyListeners == null) {\r
+            modifyListeners = new ListenerList(ListenerList.IDENTITY);\r
+        }\r
+        modifyListeners.add(listener);\r
+    }\r
+\r
+       public synchronized void removeModifyListener(StringChooserModifyListener<T> listener) {\r
+        if (modifyListeners == null)\r
+            return;\r
+        modifyListeners.remove(listener);\r
+    }\r
+\r
+  \r
+\r
+    private String isTextValid() {\r
+        if (allowedLabels.contains(getWidget().getText()))\r
+               return null;\r
+        return "There is no such object.";\r
+    }\r
+\r
+    public void setColorProvider(ITrackedColorProvider provider) {\r
+        Assert.isNotNull(provider);\r
+        this.colorProvider = provider;\r
+    }\r
+\r
+    private void setBackground(Color background) {\r
+       if(text.isDisposed()) return;\r
+        if (!text.getEditable()) {\r
+            // Do not alter background when the widget is not editable.\r
+            return;\r
+        }\r
+        text.setBackground(background);\r
+    }\r
+    \r
+    public boolean isDisposed() {\r
+       return text.isDisposed();\r
+    }\r
+    \r
+    public Display getDisplay() {\r
+       return display;\r
+    }\r
+    \r
+    public String getText() {\r
+               return text.getText();\r
+       }\r
+    \r
+    public int getCaretPosition() {\r
+       return text.getCaretPosition();\r
+    }\r
+       \r
+       \r
+    /**\r
+     * A composite of many UI listeners for creating the functionality of this\r
+     * class.\r
+     */\r
+    private class CompositeListener\r
+    implements ModifyListener, DisposeListener, KeyListener, MouseTrackListener,\r
+    MouseListener, FocusListener\r
+    {\r
+        // Keyboard/editing events come in the following order:\r
+        //   1. keyPressed\r
+        //   2. verifyText\r
+        //   3. modifyText\r
+        //   4. keyReleased\r
+\r
+        @Override\r
+        public void modifyText(ModifyEvent e) {\r
+            //System.out.println("modifyText: " + e);\r
+            setModified(true);\r
+\r
+            String valid = isTextValid();\r
+            if (valid != null) {\r
+                setBackground(colorProvider.getInvalidBackground());\r
+            } else {\r
+                if (isEditing())\r
+                    setBackground(colorProvider.getEditingBackground());\r
+                else\r
+                    setBackground(colorProvider.getInactiveBackground());\r
+            }\r
+        }\r
+\r
+        @Override\r
+        public void widgetDisposed(DisposeEvent e) {\r
+            getWidget().removeModifyListener(this);\r
+        }\r
+\r
+        private boolean isMultiLine() {\r
+            return (text.getStyle() & SWT.MULTI) != 0;\r
+        }\r
+\r
+        private boolean hasMultiLineCommitModifier(KeyEvent e) {\r
+            return (e.stateMask & SWT.CTRL) != 0;\r
+        }\r
+\r
+        @Override\r
+        public void keyPressed(KeyEvent e) {\r
+            //System.out.println("keyPressed: " + e);\r
+            if (!isEditing()) {\r
+                // ESC, ENTER & keypad ENTER must not start editing\r
+                if (e.keyCode == SWT.ESC)\r
+                    return;\r
+\r
+                if (!isMultiLine()) {\r
+                    if (e.keyCode == SWT.F2 || e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+                        startEdit(selectAllOnStartEdit);\r
+                    } else if (e.character != '\0') {\r
+                        startEdit(false);\r
+                    }\r
+                } else {\r
+                    // In multi-line mode, TAB must not start editing!\r
+                    if (e.keyCode == SWT.F2) {\r
+                        startEdit(selectAllOnStartEdit);\r
+                    } else if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+                        if (hasMultiLineCommitModifier(e)) {\r
+                            e.doit = false;\r
+                        } else {\r
+                            startEdit(false);\r
+                        }\r
+                    } else if (e.keyCode == SWT.TAB) {\r
+                        text.traverse(((e.stateMask & SWT.SHIFT) != 0) ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT);\r
+                        e.doit = false;\r
+                    } else if (e.character != '\0') {\r
+                        startEdit(false);\r
+                    }\r
+                }\r
+            } else {\r
+                // ESC reverts any changes made during this edit\r
+                if (e.keyCode == SWT.ESC) {\r
+                    revertEdit();\r
+                }\r
+                if (!isMultiLine()) {\r
+                    if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+                        applyEdit();\r
+                    }\r
+                } else {\r
+                    if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
+                        if (hasMultiLineCommitModifier(e)) {\r
+                            applyEdit();\r
+                            e.doit = false;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        @Override\r
+        public void keyReleased(KeyEvent e) {\r
+            //System.out.println("keyReleased: " + e);\r
+        }\r
+\r
+        @Override\r
+        public void mouseEnter(MouseEvent e) {\r
+            //System.out.println("mouseEnter");\r
+            if (!isEditing()) {\r
+                setBackground(colorProvider.getHoverBackground());\r
+            }\r
+            setMouseInsideControl(true);\r
+        }\r
+\r
+        @Override\r
+        public void mouseExit(MouseEvent e) {\r
+            //System.out.println("mouseExit");\r
+            if (!isEditing()) {\r
+                setBackground(colorProvider.getInactiveBackground());\r
+            }\r
+            setMouseInsideControl(false);\r
+        }\r
+\r
+        @Override\r
+        public void mouseHover(MouseEvent e) {\r
+            //System.out.println("mouseHover");\r
+            setMouseInsideControl(true);\r
+        }\r
+\r
+        @Override\r
+        public void mouseDoubleClick(MouseEvent e) {\r
+            //System.out.println("mouseDoubleClick: " + e);\r
+            if (e.button == 1) {\r
+                getWidget().selectAll();\r
+            }\r
+        }\r
+\r
+        @Override\r
+        public void mouseDown(MouseEvent e) {\r
+            //System.out.println("mouseDown: " + e);\r
+            if (!isEditing()) {\r
+                // In reality we should never get here, since focusGained\r
+                // always comes before mouseDown, but let's keep this\r
+                // fallback just to be safe.\r
+                if (e.button == 1) {\r
+                    startEdit(selectAllOnStartEdit);\r
+                }\r
+            } else {\r
+                if (e.button == 1 && (state & MOUSE_DOWN_FIRST_TIME) != 0) {\r
+                    if (!isMultiLine()) {\r
+                        // This is useless for multi-line texts\r
+                        getWidget().selectAll();\r
+                    }\r
+                    state &= ~MOUSE_DOWN_FIRST_TIME;\r
+                }\r
+            }\r
+        }\r
+\r
+        @Override\r
+        public void mouseUp(MouseEvent e) {\r
+        }\r
+\r
+        @Override\r
+        public void focusGained(FocusEvent e) {\r
+            //System.out.println("focusGained");\r
+            if (!isEditing()) {\r
+                if (!isMultiLine()) {\r
+                    // Always start edit on single line texts when focus is gained\r
+                    startEdit(selectAllOnStartEdit);\r
+                }\r
+            }\r
+        }\r
+\r
+        @Override\r
+        public void focusLost(FocusEvent e) {\r
+            //System.out.println("focusLost");\r
+            if (isEditing()) {\r
+                applyEdit();\r
+            }\r
+        }\r
+    }\r
+    \r
+    public void dispose() {\r
+       allowedLabels.clear();\r
+       allowedLabels = null;\r
+       objectFactory = null;\r
+       objectToLabel.clear();\r
+       objectToLabel = null;\r
+       \r
+    }\r
+    \r
+    \r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyEvent.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyEvent.java
new file mode 100644 (file)
index 0000000..c491665
--- /dev/null
@@ -0,0 +1,32 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.EventObject;\r
+\r
+import org.eclipse.swt.widgets.Widget;\r
+\r
+public class StringChooserModifyEvent<T>  extends EventObject {\r
+\r
+       private static final long serialVersionUID = 2630732165074702762L;\r
+       \r
+       private T object;\r
+       private String text;\r
+        \r
+       public StringChooserModifyEvent(Widget source, T object, String text) {\r
+                super(source);\r
+                this.object = object;\r
+                this.text = text;\r
+       }\r
+        \r
+       public Widget getWidget() {\r
+               return (Widget) getSource();\r
+       }\r
+       \r
+       public T getObject() {\r
+               return object;\r
+       }\r
+\r
+       public String getText() {\r
+               return text;\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyListener.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyListener.java
new file mode 100644 (file)
index 0000000..b975640
--- /dev/null
@@ -0,0 +1,7 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+public interface StringChooserModifyListener<T> {\r
+\r
+       \r
+       void modifySelection(StringChooserModifyEvent<T> e);\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyListenerImpl.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/StringChooserModifyListenerImpl.java
new file mode 100644 (file)
index 0000000..8fa748d
--- /dev/null
@@ -0,0 +1,71 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.utils.ReflectionUtils;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+\r
+public abstract class StringChooserModifyListenerImpl<T,T2> implements StringChooserModifyListener<T2>, Widget {\r
+       protected ISessionContext context;\r
+       protected T lastInput = null;\r
+\r
+       protected final Class<?> clazz;\r
+\r
+       public StringChooserModifyListenerImpl() {\r
+               clazz = ReflectionUtils.getSingleParameterType(getClass());\r
+       }\r
+\r
+       private Object getInputContents(Object input, Class<?> inputClass) {\r
+               if (inputClass.isInstance(input))\r
+                       return input;\r
+               if (input instanceof ISelection)\r
+                       return ISelectionUtils.filterSingleSelection(input, inputClass);\r
+               return null;\r
+       }\r
+\r
+       @Override\r
+       public void modifySelection(StringChooserModifyEvent<T2> e) {\r
+\r
+               Text text = (Text)e.getWidget();\r
+               final T2 object = e.getObject();\r
+               final String textValue = text.getText();\r
+               final T input = lastInput;\r
+\r
+               try {\r
+                       context.getSession().syncRequest(new WriteRequest() {\r
+\r
+                               @SuppressWarnings("unchecked")\r
+                               @Override\r
+                               public void perform(WriteGraph graph) throws DatabaseException {\r
+                                       \r
+                                       if(clazz.isInstance(input)) {\r
+                                               applyObject(graph, (T)input, object, textValue);\r
+                                       } else {\r
+                                               T single = (T)getInputContents(input, clazz);\r
+                                               if(single != null)\r
+                                                       applyObject(graph, single, object, textValue);\r
+                                       }\r
+\r
+                                       \r
+                               }\r
+                               \r
+                       });\r
+               } catch (DatabaseException e1) {\r
+                       e1.printStackTrace();\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public void setInput(ISessionContext context, Object parameter) {\r
+               this.context = context;\r
+               lastInput = (T)parameter;\r
+       }\r
+\r
+       abstract public void applyObject(WriteGraph graph, T input, T2 object, String text) throws DatabaseException;\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TitleFactory.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TitleFactory.java
new file mode 100644 (file)
index 0000000..c02b3a5
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TitleModifier.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TitleModifier.java
new file mode 100644 (file)
index 0000000..543d173
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TrackedSpinner.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/TrackedSpinner.java
new file mode 100644 (file)
index 0000000..74673a0
--- /dev/null
@@ -0,0 +1,179 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/VariableExistsValidator.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/VariableExistsValidator.java
new file mode 100644 (file)
index 0000000..32abe9e
--- /dev/null
@@ -0,0 +1,129 @@
+package org.simantics.jfreechart.chart.properties;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\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.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.ui.SimanticsUI;\r
+import org.simantics.utils.ui.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
+       protected Collection<ChartVariable> variables;\r
+    protected TrackedText text;\r
+    private boolean allowEmpty;\r
+    @SuppressWarnings("unused")\r
+    private boolean useLabels = false;\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
+    \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
+        this.variables = new ArrayList<ChartVariable>();\r
+        this.text = text;\r
+        this.allowEmpty = allowEmpty;\r
+    }\r
+    \r
+    public VariableExistsValidator(WidgetSupport support, TrackedText text, boolean allowEmpty, boolean useLabels) {\r
+        this(support, text, allowEmpty);\r
+        this.useLabels = useLabels;\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 (variables) {\r
+            for(ChartVariable variable : variables) {\r
+                if(newText.equals(variable.getLabel()))\r
+                    return null;\r
+                if(newText.equals(variable.getRvi()))\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
+            variables = new ArrayList<ChartVariable>();\r
+            return;\r
+        }\r
+        \r
+       \r
+        try {\r
+            /* Find the model resource. It can be found with PartOf \r
+               relations from series resource in a chart */\r
+           AllVariablesOfModel query = AllVariablesOfModel.withRandomResource(context, resource);\r
+            \r
+            if(query != null) {\r
+                // Find all variables and set them as the reference for isValid(String)\r
+                SimanticsUI.getSession().asyncRequest(query\r
+                , new Listener<Collection<ChartVariable>>() {\r
+\r
+                    @Override\r
+                    public void execute(Collection<ChartVariable> variables) {\r
+                        VariableExistsValidator.this.variables = variables;\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/VariableProposalProvider.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/VariableProposalProvider.java
new file mode 100644 (file)
index 0000000..da399f6
--- /dev/null
@@ -0,0 +1,194 @@
+/*******************************************************************************\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.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+\r
+import org.eclipse.jface.fieldassist.ContentProposal;\r
+import org.eclipse.jface.fieldassist.IContentProposal;\r
+import org.eclipse.jface.fieldassist.IContentProposalProvider;\r
+import org.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.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class VariableProposalProvider implements IContentProposalProvider, Widget {\r
+\r
+       /*\r
+        * The proposals provided.\r
+        */\r
+       private Collection<ChartVariable> proposals;\r
+\r
+       /*\r
+        * The proposals mapped to IContentProposal. Cached for speed in the case\r
+        * where filtering is not used.\r
+        */\r
+       private IContentProposal[] contentProposals;\r
+\r
+       /*\r
+        * Boolean that tracks whether filtering is used.\r
+        */\r
+       private boolean filterProposals = false;\r
+\r
+\r
+       private boolean compareRVI = false;\r
+       /**\r
+        * Return an array of Objects representing the valid content proposals for a\r
+        * field. \r
+        * \r
+        * @param contents\r
+        *            the current contents of the field (only consulted if filtering\r
+        *            is set to <code>true</code>)\r
+        * @param position\r
+        *            the current cursor position within the field (ignored)\r
+        * @return the array of Objects that represent valid proposals for the field\r
+        *         given its current content.\r
+        */\r
+       @SuppressWarnings("unchecked")\r
+       public IContentProposal[] getProposals(String contents, int position) {\r
+               if (filterProposals) {\r
+                       @SuppressWarnings("rawtypes")\r
+            ArrayList list = new ArrayList();\r
+                       if (compareRVI) {\r
+                               for (ChartVariable proposal : proposals) {\r
+                                       if (proposal.getRvi().length() >= contents.length() && proposal.getRvi().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
+                                               if (proposal.getLabel() != null)\r
+                                                       list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
+                                               else\r
+                                                       list.add(new ContentProposal(proposal.getRvi()));\r
+                                       } else if (proposal.getLabel() != null && proposal.getLabel().length() >= contents.length() && proposal.getLabel().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
+                                               list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               for (ChartVariable proposal : proposals) {\r
+                                       if (proposal.getLabel() != null && proposal.getLabel().length() >= contents.length() && proposal.getLabel().substring(0, contents.length()).equalsIgnoreCase(contents)) {\r
+                                               list.add(new ContentProposal(proposal.getRvi(),proposal.getLabel(), null));\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       return (IContentProposal[]) list.toArray(new IContentProposal[list\r
+                                       .size()]);\r
+               }\r
+               if (contentProposals == null) {\r
+                       contentProposals = new IContentProposal[proposals.size()];\r
+                       Iterator<ChartVariable> iter = proposals.iterator();\r
+                       for (int i = 0; i < proposals.size(); i++) {\r
+                               ChartVariable proposal = iter.next();\r
+                               if (proposal.getLabel() != null)\r
+                                       contentProposals[i] = new ContentProposal(proposal.getRvi(),proposal.getLabel(),null);\r
+                               else\r
+                                       contentProposals[i] = new ContentProposal(proposal.getRvi());\r
+                       }\r
+               }\r
+               return contentProposals;\r
+       }\r
+\r
+       /**\r
+        * Set the Strings to be used as content proposals.\r
+        * \r
+        * @param items\r
+        *            the array of Strings to be used as proposals.\r
+        */\r
+       public void setProposals(Collection<ChartVariable> items) {\r
+               this.proposals = items;\r
+               contentProposals = null;\r
+       }\r
+\r
+       /**\r
+        * Set the boolean that controls whether proposals are filtered according to\r
+        * the current field content.\r
+        * \r
+        * @param filterProposals\r
+        *            <code>true</code> if the proposals should be filtered to\r
+        *            show only those that match the current contents of the field,\r
+        *            and <code>false</code> if the proposals should remain the\r
+        *            same, ignoring the field content.\r
+        * @since 3.3\r
+        */\r
+       public void setFiltering(boolean filterProposals) {\r
+               this.filterProposals = filterProposals;\r
+               // Clear any cached proposals.\r
+               contentProposals = null;\r
+       }\r
+       \r
+    /**\r
+     * Provides all variables a model contains. Given resource needs to be\r
+     * part of a model (i.e. using PartOf leads eventually to a SysdynModel).\r
+     *  \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
+        this.proposals = new ArrayList<ChartVariable>();\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
+        /* Find the model resource. It can be found with PartOf \r
+        relations from series resource in a chart */\r
+       try {\r
+               AllVariablesOfModel query = AllVariablesOfModel.withRandomResource(context, resource);\r
+                SimanticsUI.getSession().asyncRequest(query\r
+               , new Listener<Collection<ChartVariable>>() {\r
+\r
+                   @Override\r
+                   public void execute(Collection<ChartVariable> 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
+       } catch (DatabaseException e) {\r
+               // TODO Auto-generated catch block\r
+               e.printStackTrace();\r
+       }\r
+        \r
+       \r
+        \r
+    }\r
+    \r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarAxisTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarAxisTab.java
new file mode 100644 (file)
index 0000000..9bb9ade
--- /dev/null
@@ -0,0 +1,434 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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.Display;\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.AdjustableTab;\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.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.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * Tab for bar chart axis properties\r
+ * @author Teemu Lempinen\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class BarAxisTab extends AdjustableTab implements Widget {\r
+\r
+    public BarAxisTab(Object id) {\r
+        super(id);\r
+    }\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 Group domainGroup;\r
+       private Label labelLabel;\r
+       private AxisHidePropertyComposite axisHide;\r
+       private Label angleLabel;\r
+       private Composite angleComposite;\r
+       private Label labelColor;\r
+       private ColorPicker colorPicker;\r
+       private Group rangeGroup;\r
+       private Label labelLabel2;\r
+       private Label labelMin;\r
+       private Composite minmax;\r
+       private Label labelMax;\r
+       private Label labelColor2;\r
+       private TrackedText rangelabel2;\r
+       private AxisHidePropertyComposite axisHide2;\r
+       private ColorPicker colorPicker2;\r
+       private Composite rangeComposite;\r
+       private Composite domainComposite;\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
+                final Resource rangeAxis = graph.getPossibleObject(plot, jfree.Plot_rangeAxis);\r
+                final Resource domainAxis = graph.getPossibleObject(plot, jfree.Plot_domainAxis);\r
+                if(rangeAxis == null && domainAxis == null) return;\r
+                Display.getDefault().asyncExec(new Runnable() {\r
+                                       \r
+                                       @Override\r
+                                       public void run() {\r
+                                               if (rangeAxis != null)\r
+                                                       rangeAxisSupport.fireInput(context, new StructuredSelection(rangeAxis));\r
+                                               if (domainAxis != null)\r
+                                                       domainAxisSupport.fireInput(context, new StructuredSelection(domainAxis));\r
+                                               \r
+                                       }\r
+                               });\r
+            }\r
+        });\r
+    }\r
+\r
+       @Override\r
+       protected void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       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
+        sc.setExpandHorizontal(true);\r
+        sc.setExpandVertical(true);\r
+\r
+        composite = new Composite(sc, SWT.NONE);\r
+\r
+        // Domain Axis properties\r
+        domainGroup = new Group(composite, SWT.NONE);\r
+        domainGroup.setText("Domain axis");\r
+\r
+        domainComposite = new Composite(domainGroup, SWT.NONE);\r
+        \r
+        // Label for x-axis\r
+        labelLabel = new Label(domainComposite, SWT.NONE);\r
+        labelLabel.setText("Label:");\r
+\r
+        rangelabel = new TrackedText(domainComposite, 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
+        \r
+        angleLabel = new Label(domainComposite, SWT.NONE);\r
+        angleLabel.setText("Label angle:");\r
+\r
+        angleComposite = new Composite(domainComposite, SWT.NONE);\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
+\r
+        // Domain Color\r
+        labelColor = new Label(domainComposite, SWT.NONE);\r
+        labelColor.setText("Color:");\r
+\r
+        colorPicker = new ColorPicker(domainComposite, context, domainAxisSupport, SWT.NONE);\r
+\r
+        axisHide = new AxisHidePropertyComposite(domainGroup, context, domainAxisSupport, SWT.NONE);\r
+\r
+        \r
+        // Range Axis properties\r
+        rangeGroup = new Group(composite, SWT.NONE);\r
+        rangeGroup.setText("Range axis");\r
+\r
+        rangeComposite = new Composite(rangeGroup, SWT.NONE);\r
+        \r
+        // Label for range axis\r
+        labelLabel2 = new Label(rangeComposite, SWT.NONE);\r
+        labelLabel2.setText("Label:");\r
+        labelLabel2.setAlignment(SWT.RIGHT);\r
+\r
+        rangelabel2 = new TrackedText(rangeComposite, rangeAxisSupport, SWT.BORDER);\r
+        rangelabel2.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+        rangelabel2.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+        rangelabel2.setColorProvider(new JFreeChartPropertyColorProvider(rangelabel2.getResourceManager()));\r
+\r
+\r
+        // Min and max values for range axis\r
+        labelMin = new Label(rangeComposite, SWT.NONE);\r
+        labelMin.setText("Min:");\r
+\r
+        minmax = new Composite(rangeComposite, SWT.NONE);\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
+        labelMax = new Label(minmax, SWT.NONE);\r
+        labelMax.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
+        labelColor2 = new Label(rangeComposite, SWT.NONE);\r
+        labelColor2.setText("Color:");\r
+\r
+        colorPicker2 = new ColorPicker(rangeComposite, context, rangeAxisSupport, SWT.NONE);\r
+\r
+        axisHide2 = new AxisHidePropertyComposite(rangeGroup, context, rangeAxisSupport, SWT.NONE);\r
+        \r
+        // Resize scrolled composite\r
+        sc.setContent(composite);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutVertical() {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(sc);\r
+\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(composite);\r
+\r
+        // Domain Axis properties\r
+        GridDataFactory.fillDefaults().grab(false, false).applyTo(domainGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(1).applyTo(domainGroup);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(domainComposite);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(domainComposite);\r
+\r
+        // Label for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(rangelabel.getWidget());\r
+        \r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(angleLabel);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(angleComposite);\r
+        GridLayoutFactory.fillDefaults().applyTo(angleComposite);\r
+        GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.CENTER).grab(false, true).applyTo(angle.getWidget());\r
+\r
+        // Domain Color\r
+        GridDataFactory.fillDefaults().grab(false, false).align(SWT.END, SWT.CENTER).applyTo(labelColor);\r
+\r
+        GridDataFactory.fillDefaults().grab(false, true).minSize(SWT.DEFAULT, 31).align(SWT.BEGINNING, SWT.CENTER).applyTo(colorPicker);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(axisHide);\r
+\r
+        domainGroup.layout();\r
+\r
+        // Range Axis properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(1).applyTo(rangeGroup);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeComposite);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(rangeComposite);\r
+\r
+        // Label for range axis\r
+        GridDataFactory.fillDefaults().hint(angleLabel.getBounds().width, SWT.DEFAULT).align(SWT.END, SWT.CENTER).applyTo(labelLabel2);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(rangelabel2.getWidget());\r
+\r
+        // Min and max values for range axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelMin);\r
+\r
+        GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.CENTER).grab(false, true).applyTo(minmax);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(minmax);\r
+        GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).applyTo(rangemax.getWidget());\r
+        GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).applyTo(rangemin.getWidget());\r
+        \r
+        // Range Color\r
+        GridDataFactory.fillDefaults().grab(false, false).align(SWT.END, SWT.CENTER).applyTo(labelColor2);\r
+\r
+        GridDataFactory.fillDefaults().grab(false, true).minSize(SWT.DEFAULT, 31).align(SWT.BEGINNING, SWT.CENTER).applyTo(colorPicker2);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(axisHide2);\r
+\r
+        // Resize scrolled composite\r
+        Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutHorizontal(boolean wideScreen) {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(sc);\r
+\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(composite);\r
+\r
+        // Domain Axis properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(domainGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(domainGroup);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(domainComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(4).applyTo(domainComposite);\r
+\r
+        // Label for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(rangelabel.getWidget());\r
+        \r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(angleLabel);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(angleComposite);\r
+        GridLayoutFactory.fillDefaults().applyTo(angleComposite);\r
+        GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.CENTER).grab(false, true).applyTo(angle.getWidget());\r
+\r
+        // Domain Color\r
+        GridDataFactory.fillDefaults().grab(true, false).align(SWT.END, SWT.CENTER).applyTo(labelColor);\r
+\r
+        GridDataFactory.fillDefaults().grab(false, true).minSize(SWT.DEFAULT, SWT.DEFAULT).align(SWT.BEGINNING, SWT.CENTER).applyTo(colorPicker);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(axisHide);\r
+\r
+        domainGroup.layout();\r
+\r
+        // Range Axis properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(rangeGroup);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(4).applyTo(rangeComposite);\r
+\r
+        // Label for range axis\r
+        GridDataFactory.fillDefaults().hint(angleLabel.getBounds().width, SWT.DEFAULT).align(SWT.END, SWT.CENTER).applyTo(labelLabel2);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(rangelabel2.getWidget());\r
+\r
+        // Min and max values for range axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelMin);\r
+\r
+        GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.CENTER).grab(false, true).applyTo(minmax);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(minmax);\r
+        GridDataFactory.fillDefaults().hint(SWT.DEFAULT, SWT.DEFAULT).applyTo(rangemax.getWidget());\r
+        GridDataFactory.fillDefaults().hint(SWT.DEFAULT, SWT.DEFAULT).applyTo(rangemin.getWidget());\r
+        \r
+        // Range Color\r
+        GridDataFactory.fillDefaults().grab(true, false).align(SWT.END, SWT.CENTER).applyTo(labelColor2);\r
+\r
+        GridDataFactory.fillDefaults().grab(false, true).minSize(SWT.DEFAULT, SWT.DEFAULT).align(SWT.BEGINNING, SWT.CENTER).applyTo(colorPicker2);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(axisHide2);\r
+\r
+        // Resize scrolled composite\r
+        Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarGeneralPropertiesTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarGeneralPropertiesTab.java
new file mode 100644 (file)
index 0000000..79bdf92
--- /dev/null
@@ -0,0 +1,502 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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.ChartPropertyOptions;\r
+import org.simantics.jfreechart.chart.properties.AdjustableTab;\r
+import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
+import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\r
+import org.simantics.jfreechart.chart.properties.DoublePropertyFactory2;\r
+import org.simantics.jfreechart.chart.properties.DoublePropertyModifier2;\r
+import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
+import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\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
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class BarGeneralPropertiesTab extends AdjustableTab {\r
+\r
+    private ScrolledComposite sc;\r
+    private Button hgrid, htitle, hlegend;\r
+    private TrackedText name, title, time;\r
+    private TrackedCombo type;\r
+    private TrackedCombo orientation;\r
+\r
+    private boolean showTime = true;\r
+    private boolean showFilter = false;\r
+       private Group general;\r
+       private Composite labelColumn1;\r
+       private Composite propertyColumn1;\r
+       private Composite labelColumn2;\r
+       private Composite propertyColumn2;\r
+       private Label labelName;\r
+       private Label labelTitle;\r
+       private Label labelTime;\r
+       private Label labelType;\r
+       private Group typeGroup;\r
+       private Label labelOrientation;\r
+       private Group hideGroup;\r
+       private Label labelUse;\r
+       private Label labelPercent;\r
+       private Group filteringGroup;\r
+       private Button useFilter;\r
+       private TrackedText fraction;\r
+       private Point size;\r
+    \r
+    public BarGeneralPropertiesTab(Object id, int options) {\r
+        super(id);\r
+       showTime = ((options & ChartPropertyOptions.SHOW_TIME) > 0); \r
+       showFilter = ((options & ChartPropertyOptions.SHOW_FILTER) > 0);\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
+     * \r
+     * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+     *\r
+     */\r
+    private class OrientationSelectionFactory 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
+               Boolean orientation = graph.getPossibleRelatedValue(plot, jfree.Plot_orientation);\r
+               if (orientation != null) {\r
+                       if (orientation)\r
+                               return "Horizontal";\r
+                       return "Vertical";                      \r
+               }\r
+                            }\r
+            return "Vertical";\r
+        }\r
+    }\r
+\r
+   /**\r
+    * \r
+    * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+    *\r
+    */\r
+    private class OrientationItemFactory 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("Vertical", "Vertical");\r
+            result.put("Horizontal", "Horizontal");\r
+            return result;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * \r
+     * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+     *\r
+     */\r
+    private class OrientationModifyListener  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
+           \r
+            if(text.equals("Horizontal"))\r
+                graph.claimLiteral(plot, jfree.Plot_orientation,true);\r
+            else\r
+               graph.claimLiteral(plot, jfree.Plot_orientation,false);\r
+\r
+            \r
+        }\r
+    }\r
+\r
+       @Override\r
+       protected void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       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
+        sc.setExpandHorizontal(true);\r
+        sc.setExpandVertical(true);\r
+\r
+        composite = new Composite(sc, SWT.NONE);\r
+\r
+        // General properties\r
+        general = new Group(composite, SWT.NONE);\r
+        general.setText("General");\r
+\r
+        // first column: labels\r
+        labelColumn1 = new Composite(general, SWT.NONE);\r
+        \r
+        // second column: name and title\r
+        propertyColumn1 = new Composite(general, SWT.NONE);\r
+        \r
+        // third column: labels\r
+        labelColumn2 = new Composite(general, SWT.NONE);\r
+        \r
+        // fourth column: type and time\r
+        propertyColumn2 = new Composite(general, SWT.NONE);\r
+        \r
+        // Name\r
+        labelName = new Label(labelColumn1, SWT.NONE);\r
+        labelName.setText("Name:");\r
+\r
+        name = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\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
+        labelTitle = new Label(labelColumn2, SWT.NONE);\r
+        labelTitle = new Label(propertyColumn2, SWT.NONE);\r
+        \r
+        // Title (Which is different than name)\r
+        labelTitle = new Label(labelColumn1, SWT.NONE);\r
+        labelTitle.setText("Title:");\r
+\r
+        title = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\r
+        title.setTextFactory(new TitleFactory());\r
+        title.addModifyListener(new TitleModifier());\r
+        title.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+        if (showTime) {\r
+               // Time\r
+               labelTime = new Label(labelColumn2, SWT.NONE);\r
+               labelTime.setText("Time:");\r
+               \r
+               time = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn2, support, SWT.BORDER);\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
+        \r
+        typeGroup = new Group(composite,SWT.NONE);\r
+        typeGroup.setText("Visuals");\r
+        \r
+        labelType = new Label(typeGroup, SWT.NONE);\r
+        labelType.setText("Type:");\r
+\r
+        type = new TrackedCombo(typeGroup, support, SWT.BORDER | SWT.READ_ONLY);\r
+        type.addModifyListener(new TypeModifyListener());\r
+        type.setItemFactory(new TypeItemFactory());\r
+        type.setSelectionFactory(new TypeSelectionFactory());\r
+        \r
+        labelOrientation = new Label(typeGroup, SWT.NONE);\r
+        labelOrientation.setText("Orientation:");\r
+        \r
+        orientation = new TrackedCombo(typeGroup, support, SWT.BORDER | SWT.READ_ONLY);\r
+        orientation.addModifyListener(new OrientationModifyListener());\r
+        orientation.setItemFactory(new OrientationItemFactory());\r
+        orientation.setSelectionFactory(new OrientationSelectionFactory());\r
+\r
+        \r
+        // Group for hide options\r
+        hideGroup = new Group(composite, SWT.NONE);\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,true));\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,true));\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,true));\r
+\r
+        if (showFilter) {\r
+               filteringGroup = new Group(composite, SWT.NONE);\r
+               filteringGroup.setText("Filter");\r
+               labelUse = new Label(filteringGroup, SWT.NONE);\r
+               labelUse.setText("Use:");\r
+               useFilter = new Button(filteringGroup, support, SWT.CHECK);\r
+               useFilter.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Filter_used, false));\r
+               useFilter.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Filter_used));\r
+               labelPercent = new Label(filteringGroup, SWT.NONE);\r
+               labelPercent.setText("Percent:");\r
+               fraction = new TrackedText(filteringGroup, support, SWT.BORDER);\r
+               fraction.setTextFactory(new DoublePropertyFactory2(JFreeChartResource.URIs.Plot,JFreeChartResource.URIs.Filter_fraction));\r
+               fraction.addModifyListener(new DoublePropertyModifier2(context, JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Filter_fraction));\r
+               fraction.setInputValidator(new DoubleValidator(true));\r
+               fraction.setColorProvider(new JFreeChartPropertyColorProvider(fraction.getResourceManager()));\r
+        }\r
+        \r
+        // Resize scrolled composite\r
+        sc.setContent(composite);\r
+        \r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutVertical() {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().applyTo(sc);\r
+\r
+        if (showFilter)\r
+               GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+        else\r
+               GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+\r
+        // General properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(general);\r
+\r
+        // first column: labels\r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn1);\r
+        GridLayoutFactory.fillDefaults().applyTo(labelColumn1);\r
+        \r
+        // second column: name and title\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(propertyColumn1);\r
+        GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(propertyColumn1);\r
+        \r
+        // third column: labels\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
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(propertyColumn2);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyColumn2);\r
+        \r
+        // Name\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelName);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTitle);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(title.getWidget());\r
+\r
+        if (showTime) {\r
+               // Time\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTime);\r
+               \r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(time.getWidget());\r
+        }\r
+        \r
+        GridDataFactory.fillDefaults().applyTo(typeGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(typeGroup);\r
+        \r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelType);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+        \r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelOrientation);\r
+        \r
+        GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+\r
+        // Group for hide options\r
+        GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+\r
+        if (showFilter) {\r
+               GridDataFactory.fillDefaults().applyTo(filteringGroup);\r
+               GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(filteringGroup);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelUse);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelPercent);\r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(fraction.getWidget());\r
+        }\r
+        \r
+        size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutHorizontal(boolean wideScreen) {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().applyTo(sc);\r
+\r
+        if (showFilter)\r
+               GridLayoutFactory.fillDefaults().numColumns(4).margins(3, 3).applyTo(composite);\r
+        else\r
+               GridLayoutFactory.fillDefaults().numColumns(3).margins(3, 3).applyTo(composite);\r
+\r
+        // General properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(general);\r
+\r
+        // first column: labels\r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn1);\r
+        GridLayoutFactory.fillDefaults().applyTo(labelColumn1);\r
+        \r
+        // second column: name and title\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(propertyColumn1);\r
+        GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(propertyColumn1);\r
+        \r
+        // third column: labels\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
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(propertyColumn2);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyColumn2);\r
+        \r
+        // Name\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelName);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTitle);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(title.getWidget());\r
+\r
+        if (showTime) {\r
+               // Time\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTime);\r
+               \r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(time.getWidget());\r
+        }\r
+        \r
+        GridDataFactory.fillDefaults().applyTo(typeGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(typeGroup);\r
+        \r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelType);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+        \r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelOrientation);\r
+        \r
+        GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+\r
+        // Group for hide options\r
+        GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+\r
+        if (showFilter) {\r
+               GridDataFactory.fillDefaults().applyTo(filteringGroup);\r
+               GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(filteringGroup);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelUse);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelPercent);\r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(fraction.getWidget());\r
+        }\r
+        \r
+        size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesPropertyComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesPropertyComposite.java
new file mode 100644 (file)
index 0000000..ca8777e
--- /dev/null
@@ -0,0 +1,100 @@
+/*******************************************************************************\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.ChartPropertyOptions;\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 options, 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
+        if ((options & ChartPropertyOptions.SHOW_TIME) > 0) {\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
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesPropertyComposite2.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesPropertyComposite2.java
new file mode 100644 (file)
index 0000000..a9a1d48
--- /dev/null
@@ -0,0 +1,124 @@
+/*******************************************************************************\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.Collection;\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.ChartPropertyOptions;\r
+import org.simantics.jfreechart.chart.properties.ChartVariable;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableFactory;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableModifier;\r
+import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
+import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\r
+import org.simantics.jfreechart.chart.properties.RangeComposite;\r
+import org.simantics.jfreechart.chart.properties.StringChooser;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ui.chart.property.DoublePropertyFactory;\r
+import org.simantics.modeling.ui.chart.property.DoublePropertyModifier;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Composite for modifying properties of a series in a bar chart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BarSeriesPropertyComposite2 extends Composite {\r
+    \r
+    private TrackedText label, time;\r
+    private StringChooser<ChartVariable> variable;\r
+    \r
+    public BarSeriesPropertyComposite2(Composite parent, final ISessionContext context, WidgetSupport support, Collection<ChartVariable> variables, int options, 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
+//       \r
+//     // FIXME: using bijectionmap and trackedText looses the variables that have the same label.\r
+//     BijectionMap<String , String> map = new BijectionMap<String, String>();\r
+//     for (ChartVariable variable : variables) {\r
+//                     map.map(variable.getRvi(), variable.toString());\r
+//             }\r
+//     variable.setTextFactory(new VariableFactory(map));\r
+//     variable.addModifyListener(new VariableModifier(variable.getWidget(), support));\r
+//     variable.setInputValidator(new VariableExistsValidator(support, variable, false, true));\r
+       \r
+\r
+        variable = new StringChooser<ChartVariable>(this, support, SWT.BORDER);\r
+        variable.setData(variables);\r
+        variable.setObjectFactory(new ChartVariableFactory(variables));\r
+        variable.addModifyListener(new ChartVariableModifier(variable.getWidget(), support));\r
+        \r
+        variable.setColorProvider(new JFreeChartPropertyColorProvider(this.variable.getResourceManager()));\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(this.variable.getWidget());\r
+\r
+        // 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
+        if ((options & ChartPropertyOptions.SHOW_TIME) > 0) {\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
+    \r
+    @Override\r
+    public void dispose() {\r
+       variable.dispose();\r
+       variable = null;\r
+       super.dispose();\r
+    }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesTab.java
new file mode 100644 (file)
index 0000000..9d9ca5c
--- /dev/null
@@ -0,0 +1,242 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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.AdjustableTab;\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.utils.datastructures.ArrayMap;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * Tab containing the series of a bar chart\r
+ * @author Teemu Lempinen\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class BarSeriesTab extends AdjustableTab 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
+    private int options;\r
+       private Composite buttonComposite;\r
+\r
+    public BarSeriesTab(Object id, int options) {\r
+        super(id);\r
+        additionalSupport = new WidgetSupportImpl();\r
+        this.options = options;\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, options,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
+       @Override\r
+       protected void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       final ISessionContext context, WidgetSupport support) {\r
+               support.register(this);\r
+        composite = new Composite(body, SWT.NONE);\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
+\r
+        // Scrolled composite for displaying properties of a selection in explorer\r
+        propertyContainer = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL);\r
+        propertyContainer.setExpandHorizontal(true);\r
+        propertyContainer.setExpandVertical(true);\r
+\r
+        // Buttons for adding and removing variables from a pie plot\r
+        buttonComposite = new Composite(composite, SWT.NONE);\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
+       @Override\r
+       protected void createControlLayoutVertical() {\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+        GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+\r
+        GridDataFactory.fillDefaults().hint(150, 200).grab(false, true).applyTo(explorer);\r
+\r
+        // Scrolled composite for displaying properties of a selection in explorer\r
+        GridDataFactory.fillDefaults().hint(150, 130).span(1, 1).grab(true, false).applyTo(propertyContainer);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+\r
+        // Buttons for adding and removing variables from a pie plot\r
+        GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutHorizontal(boolean wideScreen) {\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+        GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\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
+        GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(propertyContainer);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+\r
+        // Buttons for adding and removing variables from a pie plot\r
+        GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+       }\r
+\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesTab2.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/bar/BarSeriesTab2.java
new file mode 100644 (file)
index 0000000..cff6d71
--- /dev/null
@@ -0,0 +1,228 @@
+/*******************************************************************************\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.Collection;\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.AllVariablesOfModel;\r
+import org.simantics.jfreechart.chart.properties.ChartVariable;\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.utils.datastructures.ArrayMap;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+/**\r
+ * Tab containing the series of a bar chart\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class BarSeriesTab2 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 BarSeriesPropertyComposite2 spc;\r
+    private int options;\r
+\r
+    public BarSeriesTab2(Object id, int options) {\r
+        super(id);\r
+        additionalSupport = new WidgetSupportImpl();\r
+        this.options = options;\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
+        \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
+        \r
+        try {\r
+               AllVariablesOfModel query = AllVariablesOfModel.withRandomResource(context, resource);\r
+               Collection<ChartVariable> variables = context.getSession().syncRequest(query);\r
+               \r
+               spc = new BarSeriesPropertyComposite2(propertyContainer, context, additionalSupport, variables, options, 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
+        } catch (DatabaseException e) {\r
+               ExceptionUtils.logAndShowError(e);\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
+            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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieGeneralPropertiesTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieGeneralPropertiesTab.java
new file mode 100644 (file)
index 0000000..75ee2a6
--- /dev/null
@@ -0,0 +1,315 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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.ChartPropertyOptions;\r
+import org.simantics.jfreechart.chart.properties.AdjustableTab;\r
+import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
+import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\r
+import org.simantics.jfreechart.chart.properties.DoublePropertyFactory2;\r
+import org.simantics.jfreechart.chart.properties.DoublePropertyModifier2;\r
+import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
+import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\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
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class PieGeneralPropertiesTab extends AdjustableTab {\r
+\r
+    private ScrolledComposite sc;\r
+    private Button htitle, hlegend, hlabels;\r
+    private TrackedText name, title, time;\r
+    \r
+    private boolean showTime = true;\r
+    private boolean showFilter = false;\r
+       private Group general;\r
+       private Composite labelColumn1;\r
+       private Composite propertyColumn1;\r
+       private Composite labelColumn2;\r
+       private Composite propertyColumn2;\r
+       private Label labelName;\r
+       private Label labelTitle;\r
+       private Label labelTime;\r
+       private Group hideGroup;\r
+       private Group filteringGroup;\r
+       private Label labelUse;\r
+       private Label labelPercent;\r
+       private Button useFilter;\r
+       private TrackedText fraction;\r
+       private Point size;\r
+    \r
+    public PieGeneralPropertiesTab(Object id, int options) {\r
+        super(id);\r
+       showTime = ((options & ChartPropertyOptions.SHOW_TIME) > 0); \r
+       showFilter = ((options & ChartPropertyOptions.SHOW_FILTER) > 0);\r
+    }\r
+\r
+       @Override\r
+       protected void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       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
+        sc.setExpandHorizontal(true);\r
+        sc.setExpandVertical(true);\r
+\r
+        composite = new Composite(sc, SWT.NONE);\r
+\r
+        // General properties\r
+        general = new Group(composite, SWT.NONE);\r
+        general.setText("General");\r
+\r
+        // first column: labels\r
+        labelColumn1 = new Composite(general, SWT.NONE);\r
+        \r
+        // first column: name and title\r
+        propertyColumn1 = new Composite(general, SWT.NONE);\r
+        \r
+        // first column: labels\r
+        labelColumn2 = new Composite(general, SWT.NONE);\r
+        \r
+        // first column: type and time\r
+        propertyColumn2 = new Composite(general, SWT.NONE);\r
+        \r
+        // Name\r
+        labelName = new Label(labelColumn1, SWT.NONE);\r
+        labelName.setText("Name:");\r
+\r
+        name = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\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
+        labelTitle = new Label(labelColumn2, SWT.NONE);\r
+        labelTitle.setText("");\r
+        \r
+        labelTitle = new Label(propertyColumn2, SWT.NONE);\r
+        labelTitle.setText("");\r
+        \r
+        // Title (Which is different than name)\r
+        labelTitle = new Label(labelColumn1, SWT.NONE);\r
+        labelTitle.setText("Title:");\r
+\r
+        title = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn1, support, SWT.BORDER);\r
+        title.setTextFactory(new TitleFactory());\r
+        title.addModifyListener(new TitleModifier());\r
+        title.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+        if (showTime) {\r
+               // Time\r
+               labelTime = new Label(labelColumn2, SWT.NONE);\r
+               labelTime.setText("Time:");\r
+               \r
+               time = new org.simantics.browsing.ui.swt.widgets.TrackedText(propertyColumn2, support, SWT.BORDER);\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
+        hideGroup = new Group(composite, SWT.NONE);\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,true));\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,true));\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,true));\r
+        \r
+        if (showFilter) {\r
+               filteringGroup = new Group(composite, SWT.NONE);\r
+               filteringGroup.setText("Filter");\r
+               labelUse = new Label(filteringGroup, SWT.NONE);\r
+               labelUse.setText("Use:");\r
+               useFilter = new Button(filteringGroup, support, SWT.CHECK);\r
+               useFilter.setSelectionFactory(new BooleanPropertyFactory(JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Filter_used, false));\r
+               useFilter.addSelectionListener(new BooleanSelectionListener(context, JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Filter_used));\r
+               labelPercent = new Label(filteringGroup, SWT.NONE);\r
+               labelPercent.setText("Percent:");\r
+               fraction = new TrackedText(filteringGroup, support, SWT.BORDER);\r
+               fraction.setTextFactory(new DoublePropertyFactory2(JFreeChartResource.URIs.Plot,JFreeChartResource.URIs.Filter_fraction));\r
+               fraction.addModifyListener(new DoublePropertyModifier2(context, JFreeChartResource.URIs.Plot, JFreeChartResource.URIs.Filter_fraction));\r
+               fraction.setInputValidator(new DoubleValidator(true));\r
+               fraction.setColorProvider(new JFreeChartPropertyColorProvider(fraction.getResourceManager()));\r
+        }\r
+        \r
+        sc.setContent(composite);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutVertical() {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().applyTo(sc);\r
+\r
+        if (showFilter)\r
+               GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+        else\r
+               GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+\r
+        // General properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(general);\r
+\r
+        // first column: labels\r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn1);\r
+        GridLayoutFactory.fillDefaults().applyTo(labelColumn1);\r
+        \r
+        // first column: name and title\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(propertyColumn1);\r
+        GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(propertyColumn1);\r
+        \r
+        // first column: labels\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
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(propertyColumn2);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyColumn2);\r
+        \r
+        // Name\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelName);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+\r
+        // Dummy data for now. Waiting for different pie chart types\r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelTitle);\r
+        \r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelTitle);\r
+        \r
+        // Title (Which is different than name)\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTitle);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(title.getWidget());\r
+\r
+        if (showTime) {\r
+               // Time\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTime);\r
+               \r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(time.getWidget());\r
+        }\r
+        // Group for hide options\r
+        GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+\r
+        if (showFilter) {\r
+               GridDataFactory.fillDefaults().applyTo(filteringGroup);\r
+               GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(filteringGroup);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelUse);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelPercent);\r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(fraction.getWidget());\r
+        }\r
+        \r
+        size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutHorizontal(boolean wideScreen) {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().applyTo(sc);\r
+\r
+        if (showFilter)\r
+               GridLayoutFactory.fillDefaults().numColumns(3).margins(3, 3).applyTo(composite);\r
+        else\r
+               GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+        // General properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(general);\r
+\r
+        // first column: labels\r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelColumn1);\r
+        GridLayoutFactory.fillDefaults().applyTo(labelColumn1);\r
+        \r
+        // first column: name and title\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(propertyColumn1);\r
+        GridLayoutFactory.fillDefaults().spacing(0, LayoutConstants.getSpacing().y).applyTo(propertyColumn1);\r
+        \r
+        // first column: labels\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
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(propertyColumn2);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyColumn2);\r
+        \r
+        // Name\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelName);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+\r
+        // Dummy data for now. Waiting for different pie chart types\r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelTitle);\r
+        \r
+        GridDataFactory.fillDefaults().grab(false, true).applyTo(labelTitle);\r
+        \r
+        // Title (Which is different than name)\r
+        GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTitle);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(title.getWidget());\r
+\r
+        if (showTime) {\r
+               // Time\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelTime);\r
+               \r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(time.getWidget());\r
+        }\r
+        // Group for hide options\r
+        GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+\r
+        if (showFilter) {\r
+               GridDataFactory.fillDefaults().applyTo(filteringGroup);\r
+               GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(filteringGroup);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelUse);\r
+               GridDataFactory.fillDefaults().grab(false, true).align(SWT.END, SWT.CENTER).applyTo(labelPercent);\r
+               GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(fraction.getWidget());\r
+        }\r
+        \r
+        size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesPropertyComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesPropertyComposite.java
new file mode 100644 (file)
index 0000000..1dd80e8
--- /dev/null
@@ -0,0 +1,123 @@
+/*******************************************************************************\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.ChartPropertyOptions;\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 options, 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
+        if ((options & ChartPropertyOptions.SHOW_TIME) > 0) {\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesPropertyComposite2.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesPropertyComposite2.java
new file mode 100644 (file)
index 0000000..3f3c4af
--- /dev/null
@@ -0,0 +1,136 @@
+/*******************************************************************************\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 java.util.Collection;\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.ChartPropertyOptions;\r
+import org.simantics.jfreechart.chart.properties.BooleanPropertyFactory;\r
+import org.simantics.jfreechart.chart.properties.BooleanSelectionListener;\r
+import org.simantics.jfreechart.chart.properties.ChartVariable;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableFactory;\r
+import org.simantics.jfreechart.chart.properties.ChartVariableModifier;\r
+import org.simantics.jfreechart.chart.properties.ColorPicker;\r
+import org.simantics.jfreechart.chart.properties.DoubleValidator;\r
+import org.simantics.jfreechart.chart.properties.JFreeChartPropertyColorProvider;\r
+import org.simantics.jfreechart.chart.properties.RangeComposite;\r
+import org.simantics.jfreechart.chart.properties.StringChooser;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ui.chart.property.DoublePropertyFactory;\r
+import org.simantics.modeling.ui.chart.property.DoublePropertyModifier;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+\r
+/**\r
+ * Composite containing the properties of a series\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class PieSeriesPropertyComposite2 extends Composite {\r
+    \r
+    private TrackedText label, time;\r
+    private StringChooser<ChartVariable> variable;\r
+    \r
+    public PieSeriesPropertyComposite2(Composite parent, ISessionContext context, WidgetSupport support, Collection<ChartVariable> variables,int options, 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
+        \r
+        variable = new StringChooser<ChartVariable>(this, support, SWT.BORDER);\r
+        variable.setData(variables);\r
+        variable.setObjectFactory(new ChartVariableFactory(variables));\r
+        variable.addModifyListener(new ChartVariableModifier(variable.getWidget(), support));\r
+        \r
+        variable.setColorProvider(new JFreeChartPropertyColorProvider(this.variable.getResourceManager()));\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(this.variable.getWidget());\r
+\r
+        // 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
+        if ((options & ChartPropertyOptions.SHOW_TIME) > 0) {\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
+    @Override\r
+    public void dispose() {\r
+       variable.dispose();\r
+       variable = null;\r
+       super.dispose();\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesTab.java
new file mode 100644 (file)
index 0000000..5fbb53c
--- /dev/null
@@ -0,0 +1,241 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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.AdjustableTab;\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.utils.datastructures.ArrayMap;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * Tab for modifying series in a pie chart configuration\r
+ * @author Teemu Lempinen\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class PieSeriesTab extends AdjustableTab 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 int options;\r
+       private Composite buttonComposite;\r
+    \r
+    public PieSeriesTab(Object id, int options) {\r
+        super(id);\r
+        additionalSupport = new WidgetSupportImpl();\r
+        this.options = options;\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, options,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
+       @Override\r
+       protected void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       final ISessionContext context, WidgetSupport support) {\r
+               support.register(this);\r
+        composite = new Composite(body, SWT.NONE);\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
+\r
+        // Scrolled composite for displaying properties of a selection in explorer\r
+        propertyContainer = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL);\r
+        propertyContainer.setExpandHorizontal(true);\r
+        propertyContainer.setExpandVertical(true);\r
+\r
+\r
+        // Buttons for adding and removing variables from a pie plot\r
+        buttonComposite = new Composite(composite, SWT.NONE);\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
+       @Override\r
+       protected void createControlLayoutVertical() {\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+        GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+\r
+        GridDataFactory.fillDefaults().hint(150, 200).grab(false, true).applyTo(explorer);\r
+\r
+        // Scrolled composite for displaying properties of a selection in explorer\r
+        GridDataFactory.fillDefaults().hint(150, 190).span(1, 1).grab(true, false).applyTo(propertyContainer);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+\r
+        // Buttons for adding and removing variables from a pie plot\r
+        GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutHorizontal(boolean wideScreen) {\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+        GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\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
+        GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(propertyContainer);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+\r
+        // Buttons for adding and removing variables from a pie plot\r
+        GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesTab2.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/pie/PieSeriesTab2.java
new file mode 100644 (file)
index 0000000..8d54eb5
--- /dev/null
@@ -0,0 +1,224 @@
+/*******************************************************************************\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 java.util.Collection;\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.AllVariablesOfModel;\r
+import org.simantics.jfreechart.chart.properties.ChartVariable;\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.utils.datastructures.ArrayMap;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+/**\r
+ * Tab for modifying series in a pie chart configuration\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class PieSeriesTab2 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 int options;\r
+\r
+    public PieSeriesTab2(Object id, int options) {\r
+        super(id);\r
+        additionalSupport = new WidgetSupportImpl();\r
+        this.options = options;\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
+        try {\r
+               AllVariablesOfModel query = AllVariablesOfModel.withRandomResource(context, resource);\r
+               Collection<ChartVariable> variables = context.getSession().syncRequest(query);\r
+               PieSeriesPropertyComposite2 spc = new PieSeriesPropertyComposite2(propertyContainer, context, additionalSupport, variables, options, 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
+        } catch (DatabaseException e) {\r
+               ExceptionUtils.logAndShowError(e);\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
+            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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/AxisAndVariablesExplorerComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/AxisAndVariablesExplorerComposite.java
new file mode 100644 (file)
index 0000000..04b0209
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/AxisPropertyComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/AxisPropertyComposite.java
new file mode 100644 (file)
index 0000000..366c29b
--- /dev/null
@@ -0,0 +1,122 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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
+ * @author Tuomas Miettinen\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
+       init(parent, context, support, style, false);\r
+    }\r
+\r
+       public AxisPropertyComposite(Composite parent, ISessionContext context, WidgetSupport support, int style, boolean vertical) {\r
+        super(parent, style);\r
+        init(parent, context, support, style, vertical);\r
+    }\r
+       \r
+       private void init(Composite parent, ISessionContext context, WidgetSupport support, int style, boolean vertical) {\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(vertical ? 2 : 3).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).span(vertical ? 1 : 2, 1).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
+        GridDataFactory.fillDefaults().hint(55, SWT.DEFAULT).applyTo(min.getWidget());\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
+        GridDataFactory.fillDefaults().hint(55, SWT.DEFAULT).applyTo(max.getWidget());\r
+        \r
+        Composite hideComposite = null;\r
+        if (!vertical) {\r
+                   // Tick and label visibility\r
+               hideComposite = new Composite(this, SWT.NONE);\r
+                   GridDataFactory.fillDefaults().span(1, 2).applyTo(hideComposite);\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
+        if (vertical) {\r
+                   // Tick and label visibility\r
+               hideComposite = new Composite(this, SWT.NONE);\r
+                   GridDataFactory.fillDefaults().span(2, 1).applyTo(hideComposite);\r
+               }\r
+        \r
+        // Fill hideComposite\r
+        GridLayoutFactory.fillDefaults().applyTo(hideComposite);\r
+           Composite axisHide = new AxisHidePropertyComposite(hideComposite, context, support, SWT.NONE);\r
+           GridDataFactory.fillDefaults().applyTo(axisHide);\r
+    \r
+       }\r
+    \r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/SeriesPropertyComposite.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/SeriesPropertyComposite.java
new file mode 100644 (file)
index 0000000..9557db7
--- /dev/null
@@ -0,0 +1,212 @@
+/*******************************************************************************\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.utils.ui.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
+    \r
+    public SeriesPropertyComposite(Composite parent, ISessionContext context, WidgetSupport support, int style) {\r
+        super(parent, style);\r
+        createContent(context, support);\r
+    }\r
+    \r
+    protected void createContent(ISessionContext context, WidgetSupport support) {\r
+\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(this);\r
+\r
+        // Variable for the series\r
+        variable(this, context, support);\r
+\r
+        // Range\r
+        range(this, context, support);\r
+        \r
+        // Label to be displayed in chart for this series \r
+        seriesLabel(this, context, support);\r
+\r
+        // Color\r
+        color(this, context, support);\r
+\r
+        // Line width\r
+        lineWidth(this, support);\r
+\r
+    }\r
+    \r
+    protected TrackedText variable(Composite container, ISessionContext context, WidgetSupport support) {\r
+        Label label = new Label(container, SWT.NONE);\r
+        label.setText("Variable:");\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+        TrackedText variable = new TrackedText(container, support, SWT.BORDER);\r
+        variable.setTextFactory(new RVIFactory());\r
+        variable.addModifyListener(new RVIModifier(variable.getWidget(), support));\r
+        variable.setColorProvider(new JFreeChartPropertyColorProvider(variable.getResourceManager()));\r
+        variable.setInputValidator(new VariableExistsValidator(support, variable));\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(variable.getWidget());\r
+        return variable;\r
+    }\r
+    \r
+    protected RangeComposite range(Composite container, ISessionContext context, WidgetSupport support) {\r
+        Label label = new Label(container, SWT.NONE);\r
+        label.setText("Range:");\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+        \r
+        RangeComposite rangeComposite = new RangeComposite(container, context, support, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(rangeComposite);\r
+        return rangeComposite;\r
+    }\r
+    \r
+    protected TrackedText seriesLabel(Composite container, ISessionContext context, WidgetSupport support) {\r
+        Label label = new Label(container, SWT.NONE);\r
+        label.setText("Label:");\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+        TrackedText labelText = new TrackedText(container, support, SWT.BORDER);\r
+        labelText.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasLabel, ""));\r
+        labelText.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasLabel));\r
+        labelText.setColorProvider(new JFreeChartPropertyColorProvider(labelText.getResourceManager()));\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(labelText.getWidget());\r
+        return labelText;\r
+    }\r
+    \r
+    protected ColorPicker color(Composite container, ISessionContext context, WidgetSupport support) {\r
+        Label label = new Label(container, SWT.NONE);\r
+        label.setText("Color:");\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
+\r
+        ColorPicker colorPicker = new ColorPicker(container, context, support, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(colorPicker);\r
+        return colorPicker;\r
+    }\r
+    \r
+    protected TrackedSpinner lineWidth(Composite container, WidgetSupport support) {\r
+        Label label = new Label(container, SWT.NONE);\r
+        label.setText("Line width:");\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL).applyTo(label);\r
+\r
+        TrackedSpinner width = new TrackedSpinner(container, support, SWT.BORDER);\r
+        width.setSelectionFactory(new WidthSelectionFactory());\r
+        width.addModifyListener(new WidthModifyListener());\r
+        width.setMinimum(1);\r
+        width.setMaximum(10);\r
+        return width;\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
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/XYLineAxisAndVariablesTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/XYLineAxisAndVariablesTab.java
new file mode 100644 (file)
index 0000000..ea2714e
--- /dev/null
@@ -0,0 +1,330 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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.AdjustableTab;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.JFreeChartResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.datastructures.ArrayMap;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * PropertyTab displaying properties of axis and variables of a chart\r
+ *  \r
+ * @author Teemu Lempinen\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class XYLineAxisAndVariablesTab extends AdjustableTab {\r
+\r
+    private GraphExplorerComposite explorer;\r
+    private ScrolledComposite propertyContainer;\r
+    private Button addAxis, addVariable, remove;\r
+    private WidgetSupportImpl additionalSupport;\r
+       private Composite buttonComposite;\r
+\r
+    public XYLineAxisAndVariablesTab(Object id) {\r
+        super(id);\r
+        additionalSupport = new WidgetSupportImpl();\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, isVertical());\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
+\r
+       @Override\r
+       protected void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       final ISessionContext context, WidgetSupport support) {\r
+               composite = new Composite(body, SWT.NONE);\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
+\r
+        // Scrolled composite for displaying properties of a selection in explorer\r
+        propertyContainer = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL);\r
+        propertyContainer.setExpandHorizontal(true);\r
+        propertyContainer.setExpandVertical(true);\r
+\r
+        // Buttons for adding axis and variables and removing selected items from explorer\r
+        buttonComposite = new Composite(composite, SWT.NONE);\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
+       @Override\r
+       protected void createControlLayoutVertical() {\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+        GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+\r
+        GridDataFactory.fillDefaults().hint(220, SWT.DEFAULT).grab(false, true).applyTo(explorer);\r
+\r
+        // Scrolled composite for displaying properties of a selection in explorer\r
+        GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 210).span(1, 1).grab(true, false).applyTo(propertyContainer);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+\r
+        // Buttons for adding axis and variables and removing selected items from explorer\r
+        GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutHorizontal(boolean wideScreen) {\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+        GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\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
+        GridDataFactory.fillDefaults().hint(SWT.DEFAULT, SWT.DEFAULT).span(1, 2).grab(true, true).applyTo(propertyContainer);\r
+        GridLayoutFactory.fillDefaults().applyTo(propertyContainer);\r
+\r
+        // Buttons for adding axis and variables and removing selected items from explorer\r
+        GridDataFactory.fillDefaults().applyTo(buttonComposite);\r
+        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);\r
+       }\r
+}\r
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/XYLineGeneralPropertiesTab.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/chart/properties/xyline/XYLineGeneralPropertiesTab.java
new file mode 100644 (file)
index 0000000..3521025
--- /dev/null
@@ -0,0 +1,456 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2011, 2014 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.Display;\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.AdjustableTab;\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.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.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * PropertyTab displaying general properties and x-axis properties of a chart\r
+ * \r
+ * @author Teemu Lempinen\r
+ * @author Tuomas Miettinen\r
+ *\r
+ */\r
+public class XYLineGeneralPropertiesTab extends AdjustableTab implements Widget {\r
+\r
+    public XYLineGeneralPropertiesTab(Object id) {\r
+        super(id);\r
+    }\r
+\r
+    private ScrolledComposite sc;\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
+       private Group general;\r
+       private Label nameLabel;\r
+       private Label labelTitle;\r
+       private Label labelType;\r
+       private Group hideGroup;\r
+       private Group xgroup;\r
+       private Label xVariableLabel;\r
+       private Label labelMin;\r
+       private AxisHidePropertyComposite axisHide;\r
+       private Label labelLabel;\r
+       private Label labelMax;\r
+       private Composite xColumn1;\r
+       private Composite xColumn2;\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
+                final Resource domainAxis = graph.getPossibleObject(plot, jfree.Plot_domainAxis);\r
+                if(domainAxis == null) return;\r
+                Display.getDefault().asyncExec(new Runnable() {\r
+                                       @Override\r
+                                       public void run() {\r
+                                               domainAxisSupport.fireInput(context, new StructuredSelection(domainAxis));\r
+                                       }\r
+                               });\r
+                \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
+       @Override\r
+       protected void createAndAddControls(Composite body, IWorkbenchSite site,\r
+                       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
+        sc.setExpandHorizontal(true);\r
+        sc.setExpandVertical(true);\r
+\r
+        composite = new Composite(sc, SWT.NONE);\r
+\r
+        // General properties\r
+        general = new Group(composite, SWT.NONE);\r
+        general.setText("General");\r
+\r
+        // Name\r
+        nameLabel = new Label(general, SWT.NONE);\r
+        nameLabel.setText("Name:");\r
+        nameLabel.setAlignment(SWT.RIGHT);\r
+\r
+        name = new org.simantics.browsing.ui.swt.widgets.TrackedText(general, support, SWT.BORDER);\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
+        labelType = new Label(general, SWT.NONE);\r
+        labelType.setText("Type:");\r
+\r
+        type = new TrackedCombo(general, support, SWT.BORDER | SWT.READ_ONLY);\r
+        type.addModifyListener(new TypeModifyListener());\r
+        type.setItemFactory(new TypeItemFactory());\r
+        type.setSelectionFactory(new TypeSelectionFactory());\r
+\r
+        // Title (Which is different than name)\r
+        labelTitle = new Label(general, SWT.NONE);\r
+        labelTitle.setText("Title:");\r
+\r
+        title = new org.simantics.browsing.ui.swt.widgets.TrackedText(general, support, SWT.BORDER);\r
+        title.setTextFactory(new TitleFactory());\r
+        title.addModifyListener(new TitleModifier());\r
+        title.setColorProvider(new JFreeChartPropertyColorProvider(name.getResourceManager()));\r
+\r
+        // Group for hide options\r
+        hideGroup = new Group(composite, SWT.NONE);\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,true));\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,true));\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,true));\r
+\r
+\r
+        // X-Axis properties\r
+        xgroup = new Group(composite, SWT.NONE);\r
+        xgroup.setText("X-axis");\r
+\r
+        xColumn1 = new Composite(xgroup, SWT.NONE);\r
+        \r
+        // Variable for x-axis (default: empty == time)\r
+        xVariableLabel = new Label(xColumn1, SWT.NONE);\r
+        xVariableLabel.setText("Variable:");\r
+        \r
+        xvariable = new TrackedText(xColumn1, 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
+        \r
+        // Label for x-axis\r
+        labelLabel = new Label(xColumn1, SWT.NONE);\r
+        labelLabel.setText("Label:");\r
+        \r
+        xlabel = new TrackedText(xColumn1, 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
+\r
+        xColumn2 = new Composite(xgroup, SWT.NONE);\r
+        \r
+        // Min value for x-axis\r
+        labelMin = new Label(xColumn2, SWT.NONE);\r
+        labelMin.setText("Min:");\r
+        labelMin.setAlignment(SWT.RIGHT);\r
+\r
+        xmin = new TrackedText(xColumn2, 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
+        // Max value for x-axis\r
+        labelMax = new Label(xColumn2, SWT.NONE);\r
+        labelMax.setText("Max:");\r
+        \r
+        xmax = new TrackedText(xColumn2, 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
+        // Axis hide buttons\r
+        axisHide = new AxisHidePropertyComposite(composite, context, domainAxisSupport, SWT.NONE);\r
+\r
+        sc.setContent(composite);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutVertical() {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().applyTo(sc);\r
+\r
+        GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);\r
+\r
+        // General properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(general);\r
+\r
+        // Name\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(nameLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+\r
+        // Type\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelType);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+\r
+        // Title (Which is different than name)\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelTitle);\r
+\r
+        GridDataFactory.fillDefaults().span(1, 1).grab(true, false).applyTo(title.getWidget());\r
+\r
+        // Group for hide options\r
+        GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+\r
+        // X-Axis properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xgroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(1).applyTo(xgroup);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xColumn1);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(xColumn1);\r
+        \r
+        // Variable for x-axis (default: empty == time)\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(xVariableLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xvariable.getWidget());\r
+        \r
+        // Label for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xlabel.getWidget());\r
+\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(xColumn2);\r
+\r
+        // Min value for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelMin);\r
+        GridDataFactory.fillDefaults().applyTo(xmin.getWidget());\r
+        \r
+        // Max value for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelMax);\r
+        GridDataFactory.fillDefaults().applyTo(xmax.getWidget());\r
+        \r
+        // Axis hide buttons\r
+        GridDataFactory.fillDefaults().applyTo(axisHide);\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
+        GridDataFactory.fillDefaults().hint(xVariableLabel.getBounds().width, SWT.DEFAULT).align(SWT.END, SWT.CENTER).applyTo(labelMin);\r
+        \r
+        Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+\r
+       @Override\r
+       protected void createControlLayoutHorizontal(boolean wideScreen) {\r
+               // Scrolled composite containing all of the properties in this tab\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(sc);\r
+        GridLayoutFactory.fillDefaults().applyTo(sc);\r
+\r
+        GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(composite);\r
+\r
+        // General properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(general);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(general);\r
+\r
+        // Name\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(nameLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(name.getWidget());\r
+\r
+        // Type\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelType);\r
+\r
+        GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
+\r
+        // Title (Which is different than name)\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelTitle);\r
+\r
+        GridDataFactory.fillDefaults().span(3, 1).grab(true, false).applyTo(title.getWidget());\r
+\r
+        // Group for hide options\r
+        GridDataFactory.fillDefaults().applyTo(hideGroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(hideGroup);\r
+\r
+        // X-Axis properties\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xgroup);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(xgroup);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xColumn1);\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(xColumn1);\r
+        \r
+        // Variable for x-axis (default: empty == time)\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(xVariableLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xvariable.getWidget());\r
+        \r
+        // Label for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelLabel);\r
+\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(xlabel.getWidget());\r
+\r
+        GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(xColumn2);\r
+\r
+        // Min value for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelMin);\r
+        GridDataFactory.fillDefaults().applyTo(xmin.getWidget());\r
+        \r
+        // Max value for x-axis\r
+        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(labelMax);\r
+        GridDataFactory.fillDefaults().applyTo(xmax.getWidget());\r
+        \r
+        // Axis hide buttons\r
+        GridDataFactory.fillDefaults().applyTo(axisHide);\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
+        Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);\r
+        sc.setMinSize(size);\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.jfreechart/src/org/simantics/jfreechart/internal/Activator.java b/org.simantics.jfreechart/src/org/simantics/jfreechart/internal/Activator.java
new file mode 100644 (file)
index 0000000..97597b7
--- /dev/null
@@ -0,0 +1,50 @@
+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