Show last authors
1 Here you'll find an updated version of the minimal examle:
2
3 [[attach:de.cau.cs.kieler.klighd.example.mydata.zip]]
4
5
6
7 Use the same procedure to get it to run as described on the [[parent page>>doc:KIELER.Discontinued Projects.KLighD old Minimal Example HowTo.Minimal Example (Java Model).WebHome]].
8
9
10
11 The example runs with the following current (4.12.2014) version of KLighD: 0.6.0 ([[Pragmatics v. 2014-10>>url:http://rtsys.informatik.uni-kiel.de/%7Ekieler/updatesite/release_pragmatics_2014-10/||rel="nofollow" shape="rect" class="external-link"]])
12
13 The visualized diagrams look like this:
14
15 [[image:attach:klighd-updated1.jpg]][[image:attach:klighd-updated2.jpg]]
16
17 Note that this diagram synthesis requests a specific layout algorithm for each case:
18
19 1. de.cau.cs.kieler.graphviz.dot for splines, and
20 1. de.cau.cs.kieler.klay.layered for NO splines).
21
22 == The Files ==
23
24 {{code title="MyData.java" language="java"}}
25 public class MyData {
26
27 public String name;
28 public List<MyData> subData = new LinkedList<MyData>();
29
30 public static MyData getTestData() {
31 MyData d1 = new MyData();
32 d1.name = "all data";
33 MyData d2 = new MyData();
34 d2.name = "outer data";
35 MyData d3 = new MyData();
36 d3.name = "inner 1";
37 MyData d4 = new MyData();
38 d4.name = "inner 2";
39 MyData d5 = new MyData();
40 d5.name = "inner 5";
41 MyData d6 = new MyData();
42 d6.name = "most inner 6";
43 d1.subData.add(d2);
44 d2.subData.add(d3);
45 d2.subData.add(d4);
46 d2.subData.add(d5);
47 d4.subData.add(d6);
48 return d1;
49 }
50
51 }
52 {{/code}}
53
54 {{code title="MyDataDiagrammSynthesisHandler.java" language="java"}}
55 /*
56 * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient
57 *
58 * http://www.informatik.uni-kiel.de/rtsys/kieler/
59 *
60 * Copyright 2013 by
61 * + Christian-Albrechts-University of Kiel
62 * + Department of Computer Science
63 * + Real-Time and Embedded Systems Group
64 *
65 * This code is provided under the terms of the Eclipse Public License (EPL).
66 * See the file epl-v10.html for the license text.
67 */
68 package de.cau.cs.kieler.klighd.example.mydata;
69
70 import org.eclipse.core.commands.ExecutionEvent;
71 import org.eclipse.core.commands.ExecutionException;
72 import org.eclipse.ui.internal.handlers.WorkbenchWindowHandlerDelegate;
73
74 import de.cau.cs.kieler.klighd.kivi.effects.KlighdUpdateDiagramEffect;
75 import de.cau.cs.kieler.klighd.krendering.SimpleUpdateStrategy;
76 import de.cau.cs.kieler.klighd.util.KlighdSynthesisProperties;
77
78 /**
79 * This is a small mininal example action that triggers a diagram synthesis of a
80 * static data example. In this example the actions is connected to a tool bar
81 * button and can be invoked by clicking on the button.
82 *
83 * UPDATED VERSION 4. DECEMBER 2014
84 *
85 * @author Christian Motika
86 */
87 public class MyDataDiagrammSynthesisHandler extends
88 WorkbenchWindowHandlerDelegate { //IWorkbenchWindowActionDelegate {
89
90
91 public Object execute(ExecutionEvent event) throws ExecutionException {
92 // Get some static dummy test data
93 MyData data = MyData.getTestData();
94
95 // Prepare the diagram synthesis: Create a new klighdUpdateDiagramEffect
96 KlighdUpdateDiagramEffect klighdEffect = new KlighdUpdateDiagramEffect(
97 "de.cau.cs.kieler.klighd.example.mydata.MyDataDiagramSynthesis",
98 "KLighD MyData Diagram", data);
99
100 // FIXME: Note that the incremental update currently is under re-development
101 // for Eclipse Kepler after large API changes to EMF Compare had been made.
102 // At this time we cannot use the incremental update strategy (commented out).
103 // As soon as it is fixed, uncomment the line below and delete the
104 // SimpleUpdateStrategy line:
105
106 // klighdEffect.setProperty(LightDiagramServices.REQUESTED_UPDATE_STRATEGY,
107 // UpdateStrategy.ID);
108
109 klighdEffect.setProperty(
110 KlighdSynthesisProperties.REQUESTED_UPDATE_STRATEGY,
111 SimpleUpdateStrategy.ID);
112
113 // Do the diagram synthesis
114 klighdEffect.execute();
115 return null;
116 }
117
118 }
119
120
121 {{/code}}
122
123 {{code title="MyDataDiagramSynthesis.xtend"}}
124 /*
125 * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient
126 *
127 * http://www.informatik.uni-kiel.de/rtsys/kieler/
128 *
129 * Copyright 2013 by
130 * + Christian-Albrechts-University of Kiel
131 * + Department of Computer Science
132 * + Real-Time and Embedded Systems Group
133 *
134 * This code is provided under the terms of the Eclipse Public License (EPL).
135 * See the file epl-v10.html for the license text.
136 */
137 package de.cau.cs.kieler.klighd.example.mydata
138
139 import com.google.common.collect.ImmutableList
140 import de.cau.cs.kieler.core.kgraph.KNode
141 import de.cau.cs.kieler.core.krendering.KColor
142 import de.cau.cs.kieler.core.krendering.KPolyline
143 import de.cau.cs.kieler.core.krendering.extensions.KColorExtensions
144 import de.cau.cs.kieler.core.krendering.extensions.KContainerRenderingExtensions
145 import de.cau.cs.kieler.core.krendering.extensions.KEdgeExtensions
146 import de.cau.cs.kieler.core.krendering.extensions.KNodeExtensions
147 import de.cau.cs.kieler.core.krendering.extensions.KPolylineExtensions
148 import de.cau.cs.kieler.core.krendering.extensions.KRenderingExtensions
149 import de.cau.cs.kieler.kiml.options.Direction
150 import de.cau.cs.kieler.kiml.options.EdgeRouting
151 import de.cau.cs.kieler.kiml.options.LayoutOptions
152 import de.cau.cs.kieler.klighd.SynthesisOption
153 import de.cau.cs.kieler.klighd.syntheses.AbstractDiagramSynthesis
154 import javax.inject.Inject
155
156 import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
157
158 //import static de.cau.cs.kieler.klighd.example.mydata.MyDataDiagramSynthesis.*
159 /**
160 * This is a small mininal example that creates a hierarchical KLighD diagram
161 * out of very simple hierarchical data structure (MyData).
162 *
163 * @author Christian Motika
164 */
165 class MyDataDiagramSynthesis extends AbstractDiagramSynthesis<MyData> {
166
167 @Inject extension KNodeExtensions
168 @Inject extension KEdgeExtensions
169
170 // @Inject extension KPortExtensions
171 // @Inject extension KLabelExtensions
172 @Inject extension KRenderingExtensions
173 @Inject extension KContainerRenderingExtensions
174 @Inject extension KPolylineExtensions
175 @Inject extension KColorExtensions
176
177 // Some self-defined colors
178 private static val KColor BLUE1 = RENDERING_FACTORY.createKColor() =>
179 [it.red = 248; it.green = 249; it.blue = 253];
180 private static val KColor BLUE2 = RENDERING_FACTORY.createKColor() =>
181 [it.red = 205; it.green = 220; it.blue = 243];
182
183 // Additional transformation option to hide or show a shadow
184 private static val SynthesisOption SHOW_SHADOW = SynthesisOption::createCheckOption("Shadow", true);
185 private static SynthesisOption EDGE_STYLE = SynthesisOption::createCheckOption("Spline", false);
186
187 // Add all transformation options (comma separated)
188 override getDisplayedSynthesisOptions() {
189 return ImmutableList::of(
190 SHOW_SHADOW,
191 EDGE_STYLE
192 );
193 }
194
195 override KNode transform(MyData data) {
196 val rootNode = data.createNode()
197
198 if (EDGE_STYLE.booleanValue) {
199 rootNode.setLayoutOption(LayoutOptions::SPACING, Float::valueOf("25.0"));
200 rootNode.setLayoutOption(LayoutOptions::DIRECTION, Direction::DOWN);
201 rootNode.addLayoutParam(LayoutOptions::EDGE_ROUTING, EdgeRouting::SPLINES);
202 rootNode.addLayoutParam(LayoutOptions::ALGORITHM, "de.cau.cs.kieler.graphviz.dot");
203 } else {
204 rootNode.setLayoutOption(LayoutOptions::SPACING, Float::valueOf("15.0"));
205 rootNode.setLayoutOption(LayoutOptions::DIRECTION, Direction::DOWN);
206 rootNode.addLayoutParam(LayoutOptions::EDGE_ROUTING, EdgeRouting::ORTHOGONAL);
207 rootNode.addLayoutParam(LayoutOptions::ALGORITHM, "de.cau.cs.kieler.klay.layered");
208 }
209
210 buildNodes(data, rootNode)
211 buildConnections(data, rootNode)
212
213 return rootNode;
214 }
215
216 def void buildNodes(MyData parentData, KNode rootNode) {
217 val root = parentData.createNode()
218 root.putToLookUpWith(parentData) => [
219 // Optional Layout parameters can be set
220 //it.addLayoutParam(LayoutOptions::ALGORITHM, "de.cau.cs.kieler.kiml.ogdf.planarization");
221 //it.addLayoutParam(LayoutOptions::SPACING, 75f);
222 //it.addLayoutParam(LayoutOptions::DIRECTION, Direction::UP);
223 // A rounded rectangle is created for every MyData instance
224 it.addRoundedRectangle(5, 5) => [
225 // Set linewith, foreground color, and a fading background color
226 it.lineWidth = 1;
227 it.setForeground("darkGray".color)
228 // We need a fresh copy of each color item, because it is contained by its element
229 it.setBackgroundGradient(BLUE1.copy, BLUE2.copy, 90)
230 // Here we see a how to use a boolean transformation/diagram option
231 if (SHOW_SHADOW.booleanValue) {
232 it.shadow = "black".color;
233 }
234 // Set a text
235 it.addText(" " + parentData.name + " ") => [
236 it.setFontSize(9)
237 it.setForeground("black".color)
238 ]
239 // If this is a hierarchical MyData instance, then create horizontal splitter,
240 // a child area, and add its children
241 if (parentData.subData.length > 0) {
242 it.setGridPlacement(1);
243 it.addHorizontalSeperatorLine(1, 2).setForeground("darkGray".color)
244 it.addChildArea().setGridPlacementData() => [
245 from(LEFT, 3, 0, TOP, 3, 0).to(RIGHT, 3, 0, BOTTOM, 3, 0)
246 minCellHeight = 5;
247 minCellWidth = 5;
248 ];
249 for (subData : parentData.subData) {
250
251 // To the recursive call to transform for all children
252 val child = subData.transform
253
254 // It is important to add all children to the root!
255 root.children.add(child)
256 }
257 }
258 ]
259 ]
260
261 }
262
263 // Connect every first child to all childs (including itself!)
264 def void buildConnections(MyData parentData, KNode rootNode) {
265
266 // only if there is any child there
267 if (parentData.subData.size > 0) {
268 val firstChild = parentData.subData.get(0);
269
270 for (child : parentData.subData) {
271
272 // BE CAREFUL IF YOU CREATE A MAPPING LIKE THIS THERE WILL JUST BE CREATED ONE
273 // EDGE PER "firstchild". That's why better use the child, because we iterate
274 // over different child-objects (targets) but always habe the same firstChild-
275 // -object.
276 //val kEdge = firstChild.createEdge() // THIS IS MOST LIKELY WRONG
277
278 val kEdge = child.createEdge()
279 kEdge.source = firstChild.node;
280 kEdge.target = child.node;
281
282 System::out.println("Connect " + firstChild.name + " to " + child.name);
283
284 if (!EDGE_STYLE.booleanValue) {
285 kEdge.addPolyline(2)
286 } else {
287 kEdge.addSpline(2);
288 }
289
290 kEdge.KRendering as KPolyline => [
291 it.addArrowDecorator()
292 it.setLineWidth(2)
293 ];
294
295 child.buildConnections(rootNode);
296 }
297 }
298
299 }
300
301 }
302
303
304 {{/code}}