]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/multileveldiagram/LayerComposition.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / multileveldiagram / LayerComposition.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.multileveldiagram;
13
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.Iterator;
17 import java.util.List;
18
19 import org.simantics.g2d.diagram.IDiagram;
20 import org.simantics.g2d.diagram.impl.Diagram;
21 import org.simantics.utils.datastructures.hints.IHintContext.Key;
22 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
23
24 /**
25  * This class describes a composition of a multi-layer diagram. 
26  * 
27  * @author Toni Kalajainen
28  */
29 public class LayerComposition {
30
31         /** Diagram hint, MorphHandlers read this key from the diagram */
32         public static final Key KEY_PHASE = new KeyOf(MorphPhase.class);
33         
34         /** Transition function */
35         TransitionFunction function = TransitionFunction.SIGMOID; 
36         
37         /** Diagramming info */
38         ArrayList<Node> nodes = new ArrayList<Node>();
39         /** All diagrams */
40         ArrayList<IDiagram> diagrams = new ArrayList<IDiagram>();
41         /** Zoom levels */
42         MorphLevel[] levels = null;
43         
44         /**
45          * Add a new diagram to the composition.
46          * The top most diagram has startZoom open-ended, and the bottom diagram
47          * has endZoom open-ended.
48          * 
49          * @param diagram
50          * @param startZoom startZoom in percents or null if open-ended
51          * @param endZoom endZoom in percents or null if open-ended
52          */
53         public void addLayer(IDiagram diagram, Double startZoom, Double endZoom)
54         {
55                 assert(diagram!=null);          
56                 if (startZoom!=null && endZoom!=null)
57                         assert(startZoom<endZoom);
58                 assert(startZoom!=null || endZoom!=null);
59                 if (startZoom!=null) {
60                         nodes.add(new Node(diagram, startZoom));
61                 }
62                 if (endZoom!=null) {
63                         nodes.add(new Node(diagram, endZoom));
64                 }
65                 levels = null;
66         }
67         
68         public void removeLayer(IDiagram diagram)
69         {
70                 Iterator<Node> i = nodes.iterator();
71                 while (i.hasNext()) {
72                         Node n = i.next();
73                         if (n.diagram == diagram)
74                                 i.remove();
75                 }
76                 levels = null;
77         }
78         
79         /**
80          * Builds Zoom Levels.
81          */
82         private void _buildZoomLevels()
83         {
84                 diagrams.clear();
85                 Collections.sort(nodes);
86                 int c = nodes.size();
87                 ArrayList<MorphLevel> levels = new ArrayList<MorphLevel>(c+1);
88                 MorphLevel prevZL = null;
89                 for (int i = 0; i<=c; i++ )
90                 {
91                         MorphLevel zl = new MorphLevel();
92                         if (i==0) {
93                                 zl.ud = nodes.get(0).diagram;
94                                 zl.ld = nodes.get(0).diagram;
95                                 zl.ul = -Double.MAX_VALUE;
96                                 zl.ll = nodes.get(0).level;
97                         } else if (i==c) {
98                                 zl.ud = nodes.get(c-1).diagram;
99                                 zl.ld = nodes.get(c-1).diagram;
100                                 zl.ul = nodes.get(c-1).level;
101                                 zl.ll = Double.MAX_VALUE;
102                         } else {
103                                 zl.ud = nodes.get(i-1).diagram;
104                                 zl.ld = nodes.get(i  ).diagram;
105                                 zl.ul = nodes.get(i-1).level;
106                                 zl.ll = nodes.get(i  ).level;
107                         }
108
109                         if (prevZL!=null && prevZL.ld == zl.ld && prevZL.ud == zl.ud)
110                         {
111                                 prevZL.ll = Math.max(prevZL.ll, zl.ll);
112                                 prevZL.ul = Math.min(prevZL.ul, zl.ul);
113                                 zl = prevZL;
114                         } else {
115                                 prevZL = zl;
116                                 levels.add(zl);
117                         }                       
118                         if (i>0) {
119                                 nodes.get(i-1).upper = prevZL;
120                                 nodes.get(i-1).lower = zl;
121                         }
122                         
123                         if (zl.ud!=null && !diagrams.contains(zl.ud))
124                                 diagrams.add(zl.ud);
125                         if (zl.ld!=null && !diagrams.contains(zl.ld))
126                                 diagrams.add(zl.ld);
127                 }
128                 this.levels = levels.toArray(new MorphLevel[levels.size()]);
129         }
130         
131         /**
132          * Get ordered list of zoom levels starting from the top most level 
133          * (which is diagram)
134          * @return ordered list of zoom levels
135          */
136         public MorphLevel[] getMorphLevels()
137         {
138                 if (levels==null) _buildZoomLevels();
139                 return levels;
140         }
141         
142         public MorphPhase getTransitionInfo(double zoomLevel)
143         {
144                 if (levels==null) _buildZoomLevels();
145                 MorphLevel zl = null;
146                 for (int i=0; i<levels.length; i++)
147                 {
148                         zl = levels[i];
149                         if (zl.isInLevel(zoomLevel)) break;
150                 }
151                         
152                 MorphPhase zp = new MorphPhase();
153                 zp.level = zl;
154                 if (zl.ld==null || zl.ud==null || zl.ld==zl.ud)
155                         return zp;
156                 
157                 // Interpolate phase
158                 zp.phase = (zoomLevel - zl.ul) / (zl.ll - zl.ul);               
159                 zp.phase = function.f(zp.phase);
160                 if (zp.phase<0) zp.phase = 0;
161                 if (zp.phase>1) zp.phase = 1;
162                 return zp;
163         }
164         
165         public void setTransitionFunction(TransitionFunction function)
166         {
167                 this.function = function;
168         }
169
170         public TransitionFunction getFunction() {
171                 return function;
172         }
173         
174         /**
175          * Diagrams from (first occurance) top to down order
176          * @return
177          */
178         public List<IDiagram> getDiagrams() {
179                 if (levels==null) _buildZoomLevels();
180                 return Collections.unmodifiableList(diagrams);
181         }
182         
183         @Override
184         public String toString() {
185                 return getDiagrams().toString();
186         }
187         
188         /** Information about a single layer */
189         public static class LayerInfo {
190                 public double ul, ll;
191                 public IDiagram diagram;
192         }
193
194         public List<LayerInfo> buildMorphLayers()
195         {
196                 List<LayerInfo> result = new ArrayList<LayerInfo>();
197                 
198                 for (MorphLevel ml : getMorphLevels())
199                 {
200                         // Upper and lower layers are the same
201                         if (ml.ud != null && ml.ud==ml.ld)
202                         {                               
203                                 LayerInfo li = new LayerInfo();
204                                 li.diagram = ml.ud;
205                                 li.ll = ml.ll;
206                                 li.ul = ml.ul;
207                                 result.add(li);
208                                 continue;
209                         }
210                         // Build morphing layer
211                         IDiagram ud = ml.ud == null ? Diagram.EMPTY_DIAGRAM : ml.ud;
212                         IDiagram ld = ml.ld == null ? Diagram.EMPTY_DIAGRAM : ml.ld;
213                         LayerInfo li = new LayerInfo();
214                         li.ll = ml.ll;
215                         li.ul = ml.ul;
216                         li.diagram = TransitionDiagram.createTransitionDiagram(ud, ld, TransitionDiagram.MORPH_ELEMENT_CLASS);
217                         result.add(li);
218                 }
219                 
220                 return result;
221         }
222         
223         private static class Node implements Comparable<Node> {
224                 double level;
225                 IDiagram diagram;
226                 MorphLevel upper, lower;
227                 @Override
228                 public int compareTo(Node n) {
229                         double diff = level - n.level;
230                         if (diff<0) return -1;
231                         if (diff>0) return 1;
232                         return 0;
233                 }
234                 public Node(IDiagram diagram, double level) {
235                         this.level = level;
236                         this.diagram = diagram;
237                 }               
238         }
239         public static class MorphPhase {
240                 public MorphLevel level;
241                 /** Phase, 0==upper .. 1==lower */
242                 public double phase;
243                 @Override
244                 public String toString() {
245                         return phase + "\t"+level;
246                 }
247         }
248                 
249         public static class MorphLevel {
250                 /**
251                  * Upper and lower diagrams (one may be null)
252                  */
253                 public IDiagram ud, ld;
254                 public double   ul, ll;
255                 public IDiagram diagram;
256                 
257                 /**
258                  * Is zoom level locked to a diagram
259                  * @return
260                  */
261                 public boolean isLocked()
262                 {
263                         return ud == ld;
264                 }
265                 
266                 public boolean isInTransition()
267                 {
268                         return ud != ld;
269                 }
270                 
271                 public boolean isInLevel(double zoomLevel)
272                 {
273                         return zoomLevel >=ul && zoomLevel<=ll;
274                 }
275                 
276                 @Override
277                 public String toString() {
278                         String un = "[]";
279                         if (ud!=null) un = ud.toString();
280                         String ln = "[]";
281                         if (ld!=null) ln = ld.toString();
282                         
283                         return un+" .. "+ln;
284                 }
285                 
286         }       
287         
288 }