Show last authors
author | version | line-number | content |
---|---|---|---|
1 | This exercise will introduce the usage of the Eclipse Plugin Development Environment for developing new layout algorithms to be used in Eclipse diagram editors. Replace each <login> by your own login name (e.g. msp), and each <Login> by your login name with capitalized first letter (e.g. Msp). For any questions contact msp. | ||
2 | |||
3 | 1. Install and set up Eclipse ((% style="color: rgb(255,0,0);" %)TODO: describe steps to install and set up Eclipse(%%)) | ||
4 | 1. Import the following KIELER plugins: ((% style="color: rgb(255,0,0);" %)TODO: describe steps to access and import the KIELER plugins and update the list(%%))\\ | ||
5 | 1*. de.cau.cs.kieler.core | ||
6 | 1*. de.cau.cs.kieler.core.kgraph | ||
7 | 1*. (% style="font-size: 10.0pt;line-height: 13.0pt;" %)de.cau.cs.kieler.kiml | ||
8 | 1*. (% style="font-size: 10.0pt;line-height: 13.0pt;" %)de.cau.cs.kieler.kiml.service | ||
9 | 1*. de.cau.cs.kieler.kiml.ui | ||
10 | 1*. (% style="font-size: 10.0pt;line-height: 13.0pt;" %)de.cau.cs.kieler.klay.layered | ||
11 | 1. Create a new plugin\\ | ||
12 | 11. //File → New →// Other... //→// Plug-in Development //→// Plug-in Project | ||
13 | 11. Project name: de.cau.cs.rtprak.<login>.tutorial2 | ||
14 | 11. //Next// //→// set version to //0.1.0.qualifier//, provider to //Christian-Albrechts-Universität zu Kiel//, and execution environment to //J2SE-1.5// (do this for all plugins that you create!) | ||
15 | 11. The checkboxes in the //Options// group can be deactivated -> //Finish// | ||
16 | 1. Commit the new plugin project ((% style="color: rgb(255,0,0);" %)TODO: describe steps to commit plugin projects(%%)) | ||
17 | 1. (% style="font-size: 10.0pt;line-height: 13.0pt;" %)Open the file META-INF/MANIFEST.MF //→// //Dependencies// tab(%%)\\ | ||
18 | 1*. Add the plugins de.cau.cs.kieler.core and de.cau.cs.kieler.kiml to the list of dependencies, then save the file. | ||
19 | 1. Create a //layout provider// class with the //New →// Class wizard\\ | ||
20 | 1*. Package: de.cau.cs.rtprak.<login>.tutorial2 | ||
21 | 1*. Name: <Login>LayoutProvider | ||
22 | 1*. Superclass: de.cau.cs.kieler.kiml.AbstractLayoutProvider | ||
23 | 1. ((( | ||
24 | Implement the layout provider class | ||
25 | 1. (% style="font-size: 10.0pt;line-height: 13.0pt;" %)Add the following constant to the class: | ||
26 | 1. (% class="code" %) | ||
27 | ((( | ||
28 | (% class="cm" style="color: rgb(153,153,136);" %)/~*~* default value for spacing between nodes. */(% class="kd" %)privatestaticfinal(% class="kt" style="color: rgb(68,85,136);" %)float(% class="o" %)=(% class="mf" style="color: rgb(0,153,153);" %)15.0f(% class="o" %); | ||
29 | |||
30 | {{{ | ||
31 | DEFAULT_SPACING | ||
32 | }}} | ||
33 | ))) | ||
34 | 1. Write the following lines at the beginning of the {{code language="none"}}doLayout{{/code}} method:(% class="code" %) | ||
35 | ((( | ||
36 | (% class="o" %).(% class="na" style="color: rgb(0,128,128);" %)begin(% class="o" %)((% class="s" style="color: rgb(187,136,68);" %)"<Login> Layouter"(% class="o" %),(% class="mi" style="color: rgb(0,153,153);" %)1(% class="o" %));=.(% class="na" style="color: rgb(0,128,128);" %)getData(% class="o" %)(.(% class="na" style="color: rgb(0,128,128);" %)class(% class="o" %));(% class="kt" style="color: rgb(68,85,136);" %)float(% class="o" %)=.(% class="na" style="color: rgb(0,128,128);" %)getProperty(% class="o" %)(.(% class="na" style="color: rgb(0,128,128);" %)SPACING(% class="o" %));(% class="k" %)if(% class="o" %)(<(% class="mi" style="color: rgb(0,153,153);" %)0(% class="o" %)){=;}(% class="kt" style="color: rgb(68,85,136);" %)float(% class="o" %)=.(% class="na" style="color: rgb(0,128,128);" %)getProperty(% class="o" %)(.(% class="na" style="color: rgb(0,128,128);" %)BORDER_SPACING(% class="o" %));(% class="k" %)if(% class="o" %)(<(% class="mi" style="color: rgb(0,153,153);" %)0(% class="o" %)){=;} | ||
37 | |||
38 | {{{ progressMonitor | ||
39 | KShapeLayout parentLayout layoutNodeKShapeLayout | ||
40 | objectSpacing parentLayoutLayoutOptions | ||
41 | objectSpacing | ||
42 | objectSpacing DEFAULT_SPACING | ||
43 | |||
44 | borderSpacing parentLayoutLayoutOptions | ||
45 | borderSpacing | ||
46 | borderSpacing DEFAULT_SPACING | ||
47 | |||
48 | }}} | ||
49 | ))) | ||
50 | 1. Write the following line at the end of the {{code language="none"}}doLayout{{/code}} method:(% class="code" %) | ||
51 | ((( | ||
52 | (% class="o" %).(% class="na" style="color: rgb(0,128,128);" %)done(% class="o" %)(); | ||
53 | |||
54 | {{{ progressMonitor | ||
55 | }}} | ||
56 | ))) | ||
57 | 1. ((( | ||
58 | Implement the rest of the layouter such that the nodes of the input graph are all put in a row. | ||
59 | * See the [[KGraph>>doc:KIELER.KGraph Meta Model]] and [[KLayoutData>>doc:KIELER.KLayoutData Meta Model]] data structures: the input is a KNode and holds the nodes of the graph in its list of children | ||
60 | * Iterate over the nodes in the {{code language="none"}}getChildren(){{/code}} list of the {{code language="none"}}layoutNode{{/code}} input | ||
61 | * Retrieve the size of a node using the following code:(% class="code" %) | ||
62 | ((( | ||
63 | (% class="o" %)=.(% class="na" style="color: rgb(0,128,128);" %)getData(% class="o" %)(.(% class="na" style="color: rgb(0,128,128);" %)class(% class="o" %));(% class="kt" style="color: rgb(68,85,136);" %)float(% class="o" %)=.(% class="na" style="color: rgb(0,128,128);" %)getWidth(% class="o" %)();(% class="kt" style="color: rgb(68,85,136);" %)float(% class="o" %)=.(% class="na" style="color: rgb(0,128,128);" %)getHeight(% class="o" %)(); | ||
64 | |||
65 | {{{ KShapeLayout nodeLayout nodeKShapeLayout | ||
66 | width nodeLayout | ||
67 | height nodeLayout | ||
68 | }}} | ||
69 | ))) | ||
70 | * Set the position (x, y) of a node's upper left corner using the following code:(% class="code" %) | ||
71 | ((( | ||
72 | (% class="o" %).(% class="na" style="color: rgb(0,128,128);" %)setXpos(% class="o" %)();.(% class="na" style="color: rgb(0,128,128);" %)setYpos(% class="o" %)(); | ||
73 | |||
74 | {{{ nodeLayoutx | ||
75 | nodeLayouty | ||
76 | }}} | ||
77 | ))) | ||
78 | * {{code language="none"}}objectSpacing{{/code}} shall be the spacing to be left between each pair of nodes. | ||
79 | * {{code language="none"}}borderSpacing{{/code}} shall be the spacing to be left to the borders of the drawing: the first node's coordinates shall be (borderSpacing, borderSpacing). | ||
80 | * At the end of the method, set the width and height of {{code language="none"}}parentLayout{{/code}} so that it is large enough to hold the whole drawing, including borders. | ||
81 | * Edges may be ignored for now. | ||
82 | ))) | ||
83 | ))) | ||
84 | 1. Open the file META-INF/MANIFEST.MF //→// //Extensions// tab\\ | ||
85 | 11. Add an extension for de.cau.cs.kieler.kiml.layout.layoutProviders | ||
86 | 11. Right-click the extension //→// //New// //→// //layoutProvider// | ||
87 | 11. Set //name// to //<Login> Test Layouter//, //class// to de.cau.cs.rtprak.<login>.tutorial2.<Login>LayoutProvider | ||
88 | 11. Right-click the new //layoutProvider// //→// //New// //→// //knownOption//, set //option// to de.cau.cs.kieler.spacing | ||
89 | 11. Add another //knownOption//, set to de.cau.cs.kieler.borderSpacing | ||
90 | 1. //Run// //→// //Run Configurations...// //→// right-click //Eclipse Application// //→// //New//\\ | ||
91 | 11. Name: //Layout// | ||
92 | 11. For testing the layouter, a new workspace location will be created; you may configure its destination in //Workspace Data// //→// //Location// | ||
93 | 11. Add the program arguments {{code language="none"}}-debug -consoleLog{{/code}} in the //Arguments// tab. | ||
94 | 11. Go to //Plug-ins// tab, select //Launch with: plug-ins selected below only// | ||
95 | 11. //Deselect All//, activate //Workspace// checkbox, //Add Required Plug-ins//, //Apply//, //Run// | ||
96 | 1. Test the layouter in the new Eclipse instance:\\ | ||
97 | 11. //New// //→// //Project...// //→// //General// //→// //Project//, name //test// | ||
98 | 11. Right-click test project //→// //New// //→// //Other...// //→// //KEG Diagram// ((% style="color: rgb(255,0,0);" %)TODO: if graphs shall be created in another way, describe it here(%%)) | ||
99 | 11. Create a graph using the palette on the right. | ||
100 | 11. //Window// //→// //Show View// //→// //Other...// //→// //KIELER// //→// //Layout// | ||
101 | 11. While the graph diagram is open, set //Layout Provider or Type// in the //Layout// view to //<Login> Test Layouter.// | ||
102 | 11. Open the additional views //Layout Graph// and //Layout Time.// | ||
103 | 11. Trigger layout with the //KIELER Layout// button in the toolbar or Ctrl+R L (first Ctrl+R, then L). | ||
104 | 11. See the direct input and output of your algorithm in the //Layout Graph// view. | ||
105 | 11. See the execution time analysis in the //Layout Time// view. | ||
106 | 1. ((( | ||
107 | Implement another class //EdgeRouter//. | ||
108 | 1. Add the following method:(% class="code" %) | ||
109 | ((( | ||
110 | |||
111 | \\\\\\\\\\\\\\ | ||
112 | |||
113 | {{{ /** * Route the edges that are connected with the children of the given node. * @param parentNode the parent node of the input graph */ public void routeEdges(final KNode parentNode) { getMonitor().begin("Edge Routing", 1); getMonitor().done(); }}}} | ||
114 | ))) | ||
115 | 1. Add the following code to the end of the {{code language="none"}}doLayout{{/code}} method in your layout provider:(% class="code" %) | ||
116 | ((( | ||
117 | (% class="o" %)=(% class="k" %)new(% class="o" %)();.(% class="na" style="color: rgb(0,128,128);" %)routeEdges(% class="o" %)(); | ||
118 | |||
119 | {{{ EdgeRouter edgeRouter EdgeRouter | ||
120 | edgeRouterlayoutNode | ||
121 | }}} | ||
122 | ))) | ||
123 | 1. ((( | ||
124 | Implement the {{code language="none"}}routeEdges{{/code}} method: | ||
125 | * Each edge shall be drawn with three line segments: one vertical segment starting below the source node, one horizonzal segment, and another vertical segment ending below the target node. | ||
126 | * The horizontal segments of two different edges shall not have the same y-coordinate; for consecutive edges, the distance between their horizontal segments shall equal {{code language="none"}}objectSpacing{{/code}}. | ||
127 | * See the attached image [[attach:test-drawing.png]] for an example. | ||
128 | * Find the edges using {{code language="none"}}getOutgoingEdges(){{/code}} or {{code language="none"}}getIncomingEdges(){{/code}} on a node. | ||
129 | * Get the edge layout of an edge to set bend points using this code:(% class="code" %) | ||
130 | ((( | ||
131 | (% class="o" %)=.(% class="na" style="color: rgb(0,128,128);" %)getData(% class="o" %)(.(% class="na" style="color: rgb(0,128,128);" %)class(% class="o" %)); | ||
132 | |||
133 | {{{ KEdgeLayout edgeLayout edgeKEdgeLayout | ||
134 | }}} | ||
135 | ))) | ||
136 | * Create a bend point using this code:(% class="code" %) | ||
137 | ((( | ||
138 | (% class="o" %)=.(% class="na" style="color: rgb(0,128,128);" %)eINSTANCE(% class="o" %).(% class="na" style="color: rgb(0,128,128);" %)createKPoint(% class="o" %)(); | ||
139 | |||
140 | {{{ KPoint point KLayoutDataFactory | ||
141 | }}} | ||
142 | ))) | ||
143 | * Use the {{code language="none"}}getBendPoints(){{/code}} list on the {{code language="none"}}edgeLayout{{/code}} to add bend points (clear the list first to remove points from the previous layout). | ||
144 | * Set the values of the points returned by {{code language="none"}}getSourcePoint(){{/code}} and {{code language="none"}}getTargetPoint(){{/code}} according to the positions where the edge leaves its source node and reches its target node. | ||
145 | ))) | ||
146 | ))) | ||
147 | 1. Use your previous run configuration to test the edge router. |