1
14 package demo.layout.module;
15
16 import y.module.LayoutModule;
17 import y.module.YModule;
18
19 import y.layout.Layouter;
20 import y.layout.router.EdgeGroupRouterStage;
21 import y.layout.router.GroupNodeRouterStage;
22 import y.layout.router.OrthogonalEdgeRouter;
23 import y.layout.router.PatchRouterStage;
24 import y.layout.router.ReducedSphereOfActionStage;
25 import y.option.ConstraintManager;
26 import y.option.IntOptionItem;
27 import y.option.OptionGroup;
28 import y.option.OptionHandler;
29
30
37 public class OrthogonalEdgeRouterModule extends LayoutModule
38 {
39 private static final String NAME = "ORTHOGONAL_EDGE_ROUTER";
40 private static final String SCOPE = "SCOPE";
41 private static final String SCOPE_ALL_EDGES = "ALL_EDGES";
42 private static final String SCOPE_SELECTED_EDGES = "SELECTED_EDGES";
43 private static final String SCOPE_AT_SELECTED_NODES = "AT_SELECTED_NODES";
44 private static final String MINIMUM_DISTANCE_TO_EDGE = "MINIMUM_DISTANCE_TO_EDGE";
45 private static final String USE_CUSTOM_MINIMUM_DISTANCE_TO_NODE = "USE_CUSTOM_MINIMUM_DISTANCE_TO_NODE";
46 private static final String CUSTOM_MINIMUM_DISTANCE_TO_NODE = "CUSTOM_MINIMUM_DISTANCE_TO_NODE";
47 private static final String SPACE_DRIVEN_VS_CENTER_DRIVEN_SEARCH = "SPACE_DRIVEN_VS_CENTER_DRIVEN_SEARCH";
48 private static final String LOCAL_CROSSING_MINIMIZATION = "LOCAL_CROSSING_MINIMIZATION";
49 private static final String GRID_SPACING = "GRID_SPACING";
50 private static final String ROUTE_ON_GRID = "ROUTE_ON_GRID";
51 private static final String CROSSING_COST = "CROSSING_COST";
52 private static final String REROUTING_ENABLED = "REROUTING_ENABLED";
53 private static final String MONOTONIC_NONE = "MONOTONIC_NONE";
54 private static final String MONOTONIC_VERTICAL = "MONOTONIC_VERTICAL";
55 private static final String MONOTONIC_HORIZONTAL = "MONOTONIC_HORIZONTAL";
56 private static final String MONOTONIC_BOTH = "MONOTONIC_BOTH";
57 private static final String MONOTONIC_RESTRICTION = "MONOTONIC_RESTRICTION";
58 private static final String ENFORCE_MONOTONIC_RESTRICTIONS = "ENFORCE_MONOTONIC_RESTRICTIONS";
59 private static final String CONSIDER_NODE_LABELS = "CONSIDER_NODE_LABELS";
60
61 private static final String LAYOUT_OPTIONS = "LAYOUT_OPTIONS";
62 private static final String CROSSING_MINIMIZATION = "CROSSING_MINIMIZATION";
63 private static final Object[] monotonyFlagEnum = {
64 MONOTONIC_NONE,
65 MONOTONIC_HORIZONTAL,
66 MONOTONIC_VERTICAL,
67 MONOTONIC_BOTH};
68
69
70 private OrthogonalEdgeRouter router;
74
75 public OrthogonalEdgeRouterModule()
79 {
80 super(NAME, "yFiles Layout Team", "Routes edges orthogonally.");
81 setPortIntersectionCalculatorEnabled(true);
82 }
83
84 protected void init(){ instantiateRouter(); }
88
89 protected void mainrun()
90 {
91 launchLayouter(
93 new EdgeGroupRouterStage(
94 new GroupNodeRouterStage(
95 new ReducedSphereOfActionStage(
96 new PatchRouterStage(router)))));
97 }
98
99 protected void dispose(){ router = null; }
100
101
105 protected OptionHandler createOptionHandler()
106 {
107 OptionHandler oh = new OptionHandler(getModuleName());
108 initOptionHandler(oh, null);
109 return oh;
110 }
111
112 void initOptionHandler(OptionHandler oh, Layouter layouter)
113 {
114 oh.clear();
115 if(layouter == null) layouter = new OrthogonalEdgeRouter();
116 OrthogonalEdgeRouter router = (OrthogonalEdgeRouter)layouter;
117
118 OptionGroup og = new OptionGroup();
119 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, LAYOUT_OPTIONS);
120 String[] enums = { SCOPE_ALL_EDGES, SCOPE_SELECTED_EDGES, SCOPE_AT_SELECTED_NODES };
121 if(router.getSphereOfAction() == OrthogonalEdgeRouter.ROUTE_ALL_EDGES)
122 og.addItem(oh.addEnum(SCOPE, enums, 0));
123 else if(router.getSphereOfAction() == OrthogonalEdgeRouter.ROUTE_EDGES_AT_SELECTED_NODES)
124 og.addItem(oh.addEnum(SCOPE, enums, 1));
125 else
126 og.addItem(oh.addEnum(SCOPE, enums, 2));
127 og.addItem(oh.addEnum(MONOTONIC_RESTRICTION, monotonyFlagEnum, 0));
128 og.addItem(oh.addBool(ENFORCE_MONOTONIC_RESTRICTIONS, router.isEnforceMonotonicPathRestrictions()));
129
130 og.addItem(oh.addInt(MINIMUM_DISTANCE_TO_EDGE, router.getMinimumDistance()));
133 oh.getItem(MINIMUM_DISTANCE_TO_EDGE)
134 .setAttribute(IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(4));
135 og.addItem(oh.addBool(USE_CUSTOM_MINIMUM_DISTANCE_TO_NODE, !router.getCoupledDistances()));
136 og.addItem(oh.addInt(CUSTOM_MINIMUM_DISTANCE_TO_NODE, router.getMinimumDistanceToNode()));
137 oh.getItem(CUSTOM_MINIMUM_DISTANCE_TO_NODE)
138 .setAttribute(IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(2));
139 og.addItem(oh.addBool(ROUTE_ON_GRID, router.isGridRoutingEnabled()));
140 og.addItem(oh.addInt(GRID_SPACING, router.getGridSpacing()));
141 oh.getItem(GRID_SPACING)
142 .setAttribute(IntOptionItem.ATTRIBUTE_MIN_VALUE, new Integer(2));
143 og.addItem(oh.addDouble(SPACE_DRIVEN_VS_CENTER_DRIVEN_SEARCH,
144 router.getCenterToSpaceRatio(), 0.0, 1.0));
145 og.addItem(oh.addBool(CONSIDER_NODE_LABELS, router.isConsiderNodeLabelsEnabled()));
146
147 og = new OptionGroup();
148 og.setAttribute(OptionGroup.ATTRIBUTE_TITLE, CROSSING_MINIMIZATION);
149 og.addItem(oh.addBool(LOCAL_CROSSING_MINIMIZATION,
150 router.isLocalCrossingMinimizationEnabled()));
151
152 og.addItem(oh.addDouble(CROSSING_COST, router.getCrossingCost()));
153 og.addItem(oh.addBool(REROUTING_ENABLED, router.isReroutingEnabled()));
154
155 ConstraintManager cm = new ConstraintManager(oh);
156 cm.setEnabledOnValueEquals(ROUTE_ON_GRID, Boolean.TRUE, GRID_SPACING);
157 cm.setEnabledOnValueEquals(USE_CUSTOM_MINIMUM_DISTANCE_TO_NODE,
158 Boolean.TRUE,
159 CUSTOM_MINIMUM_DISTANCE_TO_NODE);
160 }
161
162
167 public void initOptionHandler(Layouter layouter)
168 {
169 OptionHandler oh = getOptionHandler();
170 initOptionHandler(oh, layouter);
171 }
172
173
177 public void configure(Layouter layouter)
178 {
179 if (layouter instanceof OrthogonalEdgeRouter)
180 {
181 OrthogonalEdgeRouter router = (OrthogonalEdgeRouter)layouter;
182 OptionHandler oh = getOptionHandler();
183
184 String choice = oh.getString(SCOPE);
185 if (choice.equals(SCOPE_AT_SELECTED_NODES))
186 router.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_EDGES_AT_SELECTED_NODES);
187 else if (choice.equals(SCOPE_SELECTED_EDGES))
188 router.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_SELECTED_EDGES);
189 else
190 router.setSphereOfAction(OrthogonalEdgeRouter.ROUTE_ALL_EDGES);
191
192 router.setMinimumDistance(oh.getInt(MINIMUM_DISTANCE_TO_EDGE));
193 router.setCoupledDistances(!oh.getBool(USE_CUSTOM_MINIMUM_DISTANCE_TO_NODE));
194 router.setMinimumDistanceToNode(oh.getInt(CUSTOM_MINIMUM_DISTANCE_TO_NODE));
195
196 router.setGridRoutingEnabled(oh.getBool(ROUTE_ON_GRID));
197 router.setGridSpacing(oh.getInt(GRID_SPACING));
198
199 router.setCenterToSpaceRatio(oh.getDouble(SPACE_DRIVEN_VS_CENTER_DRIVEN_SEARCH));
200
201 router.setLocalCrossingMinimizationEnabled(oh.getBool(LOCAL_CROSSING_MINIMIZATION));
202 if(MONOTONIC_BOTH.equals(oh.getString(MONOTONIC_RESTRICTION))) {
203 router.setMonotonicPathRestriction(OrthogonalEdgeRouter.MONOTONIC_BOTH);
204 } else if(MONOTONIC_HORIZONTAL.equals(oh.getString(MONOTONIC_RESTRICTION))) {
205 router.setMonotonicPathRestriction(OrthogonalEdgeRouter.MONOTONIC_HORIZONTAL);
206 } else if(MONOTONIC_VERTICAL.equals(oh.getString(MONOTONIC_RESTRICTION))) {
207 router.setMonotonicPathRestriction(OrthogonalEdgeRouter.MONOTONIC_VERTICAL);
208 } else {
209 router.setMonotonicPathRestriction(OrthogonalEdgeRouter.MONOTONIC_NONE);
210 }
211 router.setEnforceMonotonicPathRestrictions(oh.getBool(ENFORCE_MONOTONIC_RESTRICTIONS));
212
213 router.setConsiderNodeLabelsEnabled(oh.getBool(CONSIDER_NODE_LABELS));
214 router.setCrossingCost(oh.getDouble(CROSSING_COST));
215 router.setReroutingEnabled(oh.getBool(REROUTING_ENABLED));
216
217 }
220 else
221 {
222 throw new IllegalArgumentException("argument must be of type y.layout.router.OrthogonalEdgeRouter");
223 }
224 }
225
226 private void instantiateRouter()
230 {
231 if (router != null)
232 return;
233 router = new OrthogonalEdgeRouter();
234 configure(router);
235 }
236 }
237