1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.jfreechart.chart.element;
\r
14 import java.awt.Shape;
\r
15 import java.awt.geom.AffineTransform;
\r
16 import java.awt.geom.Rectangle2D;
\r
18 import org.jfree.chart.JFreeChart;
\r
19 import org.simantics.g2d.canvas.ICanvasContext;
\r
20 import org.simantics.g2d.diagram.DiagramUtils;
\r
21 import org.simantics.g2d.diagram.IDiagram;
\r
22 import org.simantics.g2d.element.ElementHints;
\r
23 import org.simantics.g2d.element.ElementUtils;
\r
24 import org.simantics.g2d.element.IElement;
\r
25 import org.simantics.g2d.element.SceneGraphNodeKey;
\r
26 import org.simantics.g2d.element.handler.HandleMouseEvent;
\r
27 import org.simantics.g2d.element.handler.InternalSize;
\r
28 import org.simantics.g2d.element.handler.PropertySetter;
\r
29 import org.simantics.g2d.element.handler.SceneGraph;
\r
30 import org.simantics.scenegraph.Node;
\r
31 import org.simantics.scenegraph.g2d.G2DParentNode;
\r
32 import org.simantics.scenegraph.g2d.IG2DNode;
\r
33 import org.simantics.scenegraph.g2d.events.MouseEvent;
\r
34 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent;
\r
35 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;
\r
36 import org.simantics.utils.datastructures.hints.IHintContext.Key;
\r
37 import org.simantics.utils.datastructures.hints.IHintListener;
\r
38 import org.simantics.utils.datastructures.hints.IHintObservable;
\r
41 * Chart scenegraph for chart elements in diagrams
\r
42 * @author Teemu Lempinen
\r
45 public class ChartSceneGraph implements SceneGraph, HandleMouseEvent, InternalSize {
\r
46 private static final long serialVersionUID = 1875762898776996989L;
\r
48 public static final Key KEY_SG_NODE = new SceneGraphNodeKey(Node.class, "CHART_SG_NODE");
\r
49 public static final Key KEY_SG_SELECTION_NODE = new SceneGraphNodeKey(Node.class, "CHART_SG_SELECTION_NODE");
\r
51 protected IHintListener hoverHintListener;
\r
53 public ChartSceneGraph() {
\r
57 * Expands bounds a little to allow selecting and grabbing a chart element
\r
58 * from outside the chart graphics
\r
61 public Rectangle2D getBounds(IElement e, Rectangle2D s) {
\r
62 if (s==null) s = new Rectangle2D.Double();
\r
64 IG2DNode node = (IG2DNode)e.getHint(KEY_SG_NODE);
\r
65 AffineTransform at = (AffineTransform)e.getHint(ElementHints.KEY_TRANSFORM);
\r
66 if(at != null && node != null && node.getBoundsInLocal() != null) {
\r
67 Shape shape = node.getBoundsInLocal();
\r
68 Rectangle2D r = shape.getBounds2D();
\r
69 double scaleX = at.getScaleX();
\r
70 double scaleY = at.getScaleY();
\r
71 ChartNode.expand(r, 1 * scaleX, 1 * scaleY);
\r
73 s.setFrame(shape.getBounds2D());
\r
75 s.setFrame((Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS));
\r
81 public void cleanup(IElement e) {
\r
82 if(hoverHintListener != null)
\r
83 e.removeHintListener(hoverHintListener);
\r
85 Node node = e.removeHint(KEY_SG_NODE);
\r
91 public void init(final IElement e, G2DParentNode parent) {
\r
92 ChartNode node = e.getHint(KEY_SG_NODE);
\r
94 // Create a new chart node
\r
95 node = parent.getOrCreateNode("chart_"+e.hashCode(), ChartNode.class);
\r
97 Rectangle2D bounds = (Rectangle2D)e.getHint(ElementHints.KEY_BOUNDS);
\r
98 if(bounds == null) {
\r
99 bounds = new Rectangle2D.Double(-40, -40, 80, 80);
\r
100 e.setHint(ElementHints.KEY_BOUNDS, bounds);
\r
102 node.setBounds(bounds);
\r
104 JFreeChart chart = e.getHint(ChartElementFactory.KEY_CHART);
\r
106 node.setChart(chart);
\r
108 // Add a resize listener for updating bounds information to graph after resizing
\r
109 node.setResizeListener(new ResizeListener() {
\r
112 public void elementResized(Rectangle2D newBounds) {
\r
113 e.setHint(ElementHints.KEY_BOUNDS, newBounds);
\r
114 IDiagram diagram = ElementUtils.getDiagram(e);
\r
115 DiagramUtils.synchronizeHintsToBackend(diagram, e);
\r
119 e.setHint(KEY_SG_NODE, node);
\r
123 hoverHintListener = new IHintListener() {
\r
125 public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
\r
130 public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
\r
131 if(key == ElementHints.KEY_HOVER) {
\r
132 IElement e = (IElement)sender;
\r
133 ChartNode name = (ChartNode) e.getHint(KEY_SG_NODE);
\r
135 name.setHover(Boolean.TRUE.equals(e.getHint(ElementHints.KEY_HOVER)));
\r
139 e.addHintListener(hoverHintListener);
\r
144 public void update(IElement e) {
\r
145 PropertySetter setter = e.getElementClass().getSingleItem(PropertySetter.class);
\r
146 setter.syncPropertiesToNode(e);
\r
151 public boolean handleMouseEvent(IElement e, ICanvasContext ctx, MouseEvent me) {
\r
152 if (me instanceof MouseEnterEvent) {
\r
153 e.setHint(ElementHints.KEY_HOVER, true);
\r
154 } else if (me instanceof MouseExitEvent) {
\r
155 e.setHint(ElementHints.KEY_HOVER, false);
\r