1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\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.g2d.multileveldiagram;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Collections;
\r
16 import java.util.Iterator;
\r
17 import java.util.List;
\r
19 import org.simantics.g2d.diagram.IDiagram;
\r
20 import org.simantics.g2d.diagram.impl.Diagram;
\r
21 import org.simantics.utils.datastructures.hints.IHintContext.Key;
\r
22 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
\r
25 * This class describes a composition of a multi-layer diagram.
\r
27 * @author Toni Kalajainen
\r
29 public class LayerComposition {
\r
31 /** Diagram hint, MorphHandlers read this key from the diagram */
\r
32 public static final Key KEY_PHASE = new KeyOf(MorphPhase.class);
\r
34 /** Transition function */
\r
35 TransitionFunction function = TransitionFunction.SIGMOID;
\r
37 /** Diagramming info */
\r
38 ArrayList<Node> nodes = new ArrayList<Node>();
\r
40 ArrayList<IDiagram> diagrams = new ArrayList<IDiagram>();
\r
42 MorphLevel[] levels = null;
\r
45 * Add a new diagram to the composition.
\r
46 * The top most diagram has startZoom open-ended, and the bottom diagram
\r
47 * has endZoom open-ended.
\r
50 * @param startZoom startZoom in percents or null if open-ended
\r
51 * @param endZoom endZoom in percents or null if open-ended
\r
53 public void addLayer(IDiagram diagram, Double startZoom, Double endZoom)
\r
55 assert(diagram!=null);
\r
56 if (startZoom!=null && endZoom!=null)
\r
57 assert(startZoom<endZoom);
\r
58 assert(startZoom!=null || endZoom!=null);
\r
59 if (startZoom!=null) {
\r
60 nodes.add(new Node(diagram, startZoom));
\r
62 if (endZoom!=null) {
\r
63 nodes.add(new Node(diagram, endZoom));
\r
68 public void removeLayer(IDiagram diagram)
\r
70 Iterator<Node> i = nodes.iterator();
\r
71 while (i.hasNext()) {
\r
73 if (n.diagram == diagram)
\r
80 * Builds Zoom Levels.
\r
82 private void _buildZoomLevels()
\r
85 Collections.sort(nodes);
\r
86 int c = nodes.size();
\r
87 ArrayList<MorphLevel> levels = new ArrayList<MorphLevel>(c+1);
\r
88 MorphLevel prevZL = null;
\r
89 for (int i = 0; i<=c; i++ )
\r
91 MorphLevel zl = new MorphLevel();
\r
93 zl.ud = nodes.get(0).diagram;
\r
94 zl.ld = nodes.get(0).diagram;
\r
95 zl.ul = -Double.MAX_VALUE;
\r
96 zl.ll = nodes.get(0).level;
\r
98 zl.ud = nodes.get(c-1).diagram;
\r
99 zl.ld = nodes.get(c-1).diagram;
\r
100 zl.ul = nodes.get(c-1).level;
\r
101 zl.ll = Double.MAX_VALUE;
\r
103 zl.ud = nodes.get(i-1).diagram;
\r
104 zl.ld = nodes.get(i ).diagram;
\r
105 zl.ul = nodes.get(i-1).level;
\r
106 zl.ll = nodes.get(i ).level;
\r
109 if (prevZL!=null && prevZL.ld == zl.ld && prevZL.ud == zl.ud)
\r
111 prevZL.ll = Math.max(prevZL.ll, zl.ll);
\r
112 prevZL.ul = Math.min(prevZL.ul, zl.ul);
\r
119 nodes.get(i-1).upper = prevZL;
\r
120 nodes.get(i-1).lower = zl;
\r
123 if (zl.ud!=null && !diagrams.contains(zl.ud))
\r
124 diagrams.add(zl.ud);
\r
125 if (zl.ld!=null && !diagrams.contains(zl.ld))
\r
126 diagrams.add(zl.ld);
\r
128 this.levels = levels.toArray(new MorphLevel[levels.size()]);
\r
132 * Get ordered list of zoom levels starting from the top most level
\r
133 * (which is diagram)
\r
134 * @return ordered list of zoom levels
\r
136 public MorphLevel[] getMorphLevels()
\r
138 if (levels==null) _buildZoomLevels();
\r
142 public MorphPhase getTransitionInfo(double zoomLevel)
\r
144 if (levels==null) _buildZoomLevels();
\r
145 MorphLevel zl = null;
\r
146 for (int i=0; i<levels.length; i++)
\r
149 if (zl.isInLevel(zoomLevel)) break;
\r
152 MorphPhase zp = new MorphPhase();
\r
154 if (zl.ld==null || zl.ud==null || zl.ld==zl.ud)
\r
157 // Interpolate phase
\r
158 zp.phase = (zoomLevel - zl.ul) / (zl.ll - zl.ul);
\r
159 zp.phase = function.f(zp.phase);
\r
160 if (zp.phase<0) zp.phase = 0;
\r
161 if (zp.phase>1) zp.phase = 1;
\r
165 public void setTransitionFunction(TransitionFunction function)
\r
167 this.function = function;
\r
170 public TransitionFunction getFunction() {
\r
175 * Diagrams from (first occurance) top to down order
\r
178 public List<IDiagram> getDiagrams() {
\r
179 if (levels==null) _buildZoomLevels();
\r
180 return Collections.unmodifiableList(diagrams);
\r
184 public String toString() {
\r
185 return getDiagrams().toString();
\r
188 /** Information about a single layer */
\r
189 public static class LayerInfo {
\r
190 public double ul, ll;
\r
191 public IDiagram diagram;
\r
194 public List<LayerInfo> buildMorphLayers()
\r
196 List<LayerInfo> result = new ArrayList<LayerInfo>();
\r
198 for (MorphLevel ml : getMorphLevels())
\r
200 // Upper and lower layers are the same
\r
201 if (ml.ud != null && ml.ud==ml.ld)
\r
203 LayerInfo li = new LayerInfo();
\r
204 li.diagram = ml.ud;
\r
210 // Build morphing layer
\r
211 IDiagram ud = ml.ud == null ? Diagram.EMPTY_DIAGRAM : ml.ud;
\r
212 IDiagram ld = ml.ld == null ? Diagram.EMPTY_DIAGRAM : ml.ld;
\r
213 LayerInfo li = new LayerInfo();
\r
216 li.diagram = TransitionDiagram.createTransitionDiagram(ud, ld, TransitionDiagram.MORPH_ELEMENT_CLASS);
\r
223 private static class Node implements Comparable<Node> {
\r
226 MorphLevel upper, lower;
\r
228 public int compareTo(Node n) {
\r
229 double diff = level - n.level;
\r
230 if (diff<0) return -1;
\r
231 if (diff>0) return 1;
\r
234 public Node(IDiagram diagram, double level) {
\r
235 this.level = level;
\r
236 this.diagram = diagram;
\r
239 public static class MorphPhase {
\r
240 public MorphLevel level;
\r
241 /** Phase, 0==upper .. 1==lower */
\r
242 public double phase;
\r
244 public String toString() {
\r
245 return phase + "\t"+level;
\r
249 public static class MorphLevel {
\r
251 * Upper and lower diagrams (one may be null)
\r
253 public IDiagram ud, ld;
\r
254 public double ul, ll;
\r
255 public IDiagram diagram;
\r
258 * Is zoom level locked to a diagram
\r
261 public boolean isLocked()
\r
266 public boolean isInTransition()
\r
271 public boolean isInLevel(double zoomLevel)
\r
273 return zoomLevel >=ul && zoomLevel<=ll;
\r
277 public String toString() {
\r
279 if (ud!=null) un = ud.toString();
\r
281 if (ld!=null) ln = ld.toString();
\r
283 return un+" .. "+ln;
\r