1
14 package demo.module;
15
16
17 import y.base.DataProvider;
18 import y.base.Edge;
19 import y.base.EdgeCursor;
20
21 import y.layout.LabelRanking;
22 import y.layout.labeling.AbstractLabelingAlgorithm;
23 import y.layout.labeling.GreedyMISLabeling;
24 import y.layout.labeling.MISLabelingAlgorithm;
25 import y.layout.labeling.SALabeling;
26 import y.option.EnumOptionItem;
27 import y.option.MappedListCellRenderer;
28 import y.option.OptionHandler;
29 import y.util.DataProviderAdapter;
30 import y.view.EdgeLabel;
31 import y.view.EdgeRealizer;
32 import y.view.Graph2D;
33 import y.view.NodeLabel;
34 import y.view.YLabel;
35 import y.view.hierarchy.GroupLayoutConfigurator;
36 import java.util.Map;
37
38 import y.module.YModule;
39
40
46 public class LabelingModule extends YModule {
47
48 private static final String ALLOW_NODE_OVERLAPS = "ALLOW_NODE_OVERLAPS";
49 private static final String AS_IS = "As Is";
50 private static final String INPUT = "INPUT";
51 private static final String CONSIDER_INVISIBLE_LABELS = "CONSIDER_INVISIBLE_LABELS";
52 private static final String ALLOW_EDGE_OVERLAPS = "ALLOW_EDGE_OVERLAPS";
53 private static final String DIVERSE_LABELING = "DIVERSE_LABELING";
54 private static final String QUALITY = "QUALITY";
55 private static final String USE_OPTIMIZATION = "USE_OPTIMIZATION";
56 private static final String USE_POSTPROCESSING = "USE_POSTPROCESSING";
57 private static final String CONSIDER_SELECTED_FEATURES_ONLY = "CONSIDER_SELECTED_FEATURES_ONLY";
58 private static final String SCOPE = "SCOPE";
59 private static final String PLACE_EDGE_LABELS = "PLACE_EDGE_LABELS";
60 private static final String MODEL = "MODEL";
61 private static final String EDGE_LABEL_MODEL = "EDGE_LABEL_MODEL";
62 private static final String UNKNOWN_MODEL_VALUE = "UNKNOWN_MODEL_VALUE";
63 private static final String BEST = "Best";
64 private static final String PLACE_NODE_LABELS = "PLACE_NODE_LABELS";
65 private static final String OPTIMIZATION_BALANCED = "OPTIMIZATION_BALANCED";
66 private static final String OPTIMIZATION_NODE_OVERLAP = "OPTIMIZATION_NODE_OVERLAP";
67 private static final String OPTIMIZATION_LABEL_OVERLAP = "OPTIMIZATION_LABEL_OVERLAP";
68 private static final String OPTIMIZATION_EDGE_OVERLAP = "OPTIMIZATION_EDGE_OVERLAP";
69 private static final String OPTIMIZATION_NONE = "OPTIMIZATION_NONE";
70 private static final String OPTIMIZATION_STRATEGY = "OPTIMIZATION_STRATEGY";
71
72 private static final String[] optimizationStrategy = {
73 OPTIMIZATION_BALANCED, OPTIMIZATION_NONE, OPTIMIZATION_EDGE_OVERLAP, OPTIMIZATION_LABEL_OVERLAP,
74 OPTIMIZATION_NODE_OVERLAP
75 };
76
77 public LabelingModule() {
78 super(DIVERSE_LABELING,"yFiles Layout Team","Places Labels");
79 }
80
81
82 public OptionHandler createOptionHandler() {
83 OptionHandler op = new OptionHandler(getModuleName());
84 op.useSection(SCOPE);
85 op.addBool(PLACE_NODE_LABELS,true);
86 op.addBool(PLACE_EDGE_LABELS,true);
87 op.addBool(CONSIDER_SELECTED_FEATURES_ONLY,false);
88 op.addBool(CONSIDER_INVISIBLE_LABELS,false);
89 op.useSection(QUALITY);
90 op.addBool(USE_OPTIMIZATION, false);
91 op.addEnum(OPTIMIZATION_STRATEGY, optimizationStrategy, 0);
92 op.addBool(ALLOW_NODE_OVERLAPS,false);
93 op.addBool(ALLOW_EDGE_OVERLAPS,true);
94 op.addBool(USE_POSTPROCESSING, false);
95
96 op.useSection(MODEL);
97 Map map = EdgeLabel.modelToStringMap();
98 Object asIs = AS_IS;
99 map.put(asIs, asIs);
100 Object best = BEST;
101 map.put(best, best);
102
103 EnumOptionItem item =
104 op.addEnum(EDGE_LABEL_MODEL,
105 map.keySet().toArray(),
106 best,
107 new MappedListCellRenderer(map));
108 return op;
109 }
110
111 public void init() {
112 OptionHandler op = getOptionHandler();
113 DataProvider labelSet = new LabelSetDP(
114 getGraph2D(),
115 op.getBool(CONSIDER_SELECTED_FEATURES_ONLY),
116 op.getBool(PLACE_NODE_LABELS),
117 op.getBool(PLACE_EDGE_LABELS),
118 op.getBool(CONSIDER_INVISIBLE_LABELS));
119 getGraph2D().addDataProvider(INPUT,labelSet);
120
121 setupEdgeLabelModels(op.get(EDGE_LABEL_MODEL), labelSet);
122 }
123
124 public void mainrun() {
125 AbstractLabelingAlgorithm al;
126 OptionHandler op = getOptionHandler();
127 if (op.getBool(USE_OPTIMIZATION)){
128 al = new SALabeling();
129 } else {
130 al = new GreedyMISLabeling();
131 }
132 if (al instanceof MISLabelingAlgorithm) {
133 ((MISLabelingAlgorithm) al).setOptimizationStrategy((byte) op.getEnum(OPTIMIZATION_STRATEGY));
134 }
135 al.setProfitModel(new LabelRanking());
136 al.setRemoveNodeOverlaps(!op.getBool(ALLOW_NODE_OVERLAPS));
137 al.setRemoveEdgeOverlaps(!op.getBool(ALLOW_EDGE_OVERLAPS));
138 al.setApplyPostprocessing(op.getBool(USE_POSTPROCESSING));
139
140 GroupLayoutConfigurator glc = new GroupLayoutConfigurator(getGraph2D());
142 try {
143 glc.prepareGroupDataProviders();
145 al.label(getGraph2D(),INPUT);
147 } finally {
148 glc.restoreGroupDataProviders();
150 }
151
152 getGraph2D().removeDataProvider(INPUT);
153 getGraph2D().updateViews();
154 }
155
156
157
160 class LabelSetDP extends DataProviderAdapter
161 {
162 private boolean considerOnlySelected;
163 private Graph2D graph;
164 private boolean nodes;
165 private boolean edges;
166 private boolean unvisible;
167
168 LabelSetDP(Graph2D g,boolean sel,boolean n,boolean e,boolean uv)
169 {
170 considerOnlySelected = sel;
171 graph = g;
172 nodes = n;
173 edges = e;
174 unvisible = uv;
175 }
176
177 public boolean getBool(Object o)
178 {
179 YLabel ylabel = (YLabel)o;
180 if (!ylabel.isVisible() && !unvisible) {
181 return false;
182 }
183 if (o instanceof NodeLabel) {
184 NodeLabel l = (NodeLabel)o;
185 if (l.getModel() == NodeLabel.INTERNAL) return false;
186 }
187 if (considerOnlySelected)
188 {
189 if ((o instanceof NodeLabel) && nodes)
190 {
191 NodeLabel l = (NodeLabel)o;
192 if (graph.isSelected(l.getNode())) {
193 return true;
194 } else {
195 return false;
196 }
197 }
198 if ((o instanceof EdgeLabel) && edges) {
199 EdgeLabel l = (EdgeLabel)o;
200 if (graph.isSelected(l.getEdge())) {
201 return true;
202 } else {
203 return false;
204 }
205 }
206 return false;
207 } else {
208 if ((o instanceof NodeLabel) && nodes) return true;
209 if ((o instanceof EdgeLabel) && edges) return true;
210 return false;
211 }
212 }
213 }
214
215 void setupEdgeLabelModels(Object modelValue, DataProvider labelFilter) {
216 if (AS_IS.equals(modelValue)) {
217 return;
218 }
219
220 byte model = 0;
221 if (BEST.equals(modelValue)) {
222 model = EdgeLabel.SIDE_SLIDER;
223 } else if (modelValue instanceof Byte) {
224 model = ((Byte)modelValue).byteValue();
225 } else {
226 throw new IllegalArgumentException(UNKNOWN_MODEL_VALUE + modelValue);
227 }
228
229 Graph2D graph = getGraph2D();
230 for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
231 Edge e = ec.edge();
232 EdgeRealizer er = graph.getRealizer(e);
233 for (int i = 0; i < er.labelCount(); i++) {
234 EdgeLabel label = er.getLabel(i);
235 if (labelFilter.getBool(label)) {
236 label.setModel(model);
237 }
238 }
239 }
240 }
241 }
242
243