1
14 package demo.layout.router;
15
16 import y.base.DataMap;
17 import y.base.DataProvider;
18 import y.base.Edge;
19 import y.base.EdgeCursor;
20 import y.base.EdgeList;
21 import y.base.GraphEvent;
22 import y.base.GraphListener;
23 import y.base.Node;
24 import y.base.NodeCursor;
25 import y.base.NodeList;
26 import y.layout.LayoutGraph;
27 import y.layout.router.BusRepresentations;
28 import y.util.Maps;
29 import y.util.pq.IntObjectPQ;
30 import y.view.Graph2D;
31 import y.view.NodeRealizer;
32
33 import java.awt.Color;
34 import java.util.Random;
35
36
40 public class BusDyer implements GraphListener {
41 private final Graph2D graph;
42 private final DataProvider hubMarker;
43 private final IntObjectPQ availableColorsPQ;
44 private final int predefinedColorsCount;
45 private int eventCount;
46
47
52 public BusDyer(Graph2D graph) {
53 this.graph = graph;
54 this.hubMarker = graph.getDataProvider(BusRouterDemo.HUB_MARKER_DPKEY);
55
56 this.eventCount = 0;
57 this.predefinedColorsCount = 50;
58 DataMap backingStore = Maps.createHashedDataMap();
59 this.availableColorsPQ = new IntObjectPQ(predefinedColorsCount, backingStore, backingStore);
60 resetColors();
61 }
62
63
66 public void colorize() {
67 colorize(null);
68 }
69
70
77 public void colorize(DataProvider colorProvider) {
78 resetColors();
79
80 final NodeList isolatedHubList = new NodeList();
82 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
83 final Node node = nc.node();
84 if (node.degree() == 0 && hubMarker.getBool(node)) {
85 isolatedHubList.add(node);
86 }
87 }
88 final Node[] isolatedHubs = isolatedHubList.toNodeArray();
89
90 final EdgeList[] edgeLists = calculateBusComponents(graph);
92 final Color[] busColors = new Color[edgeLists.length + isolatedHubs.length];
93 for (int i = 0; i < edgeLists.length; i++) {
94 final EdgeList edgeList = edgeLists[i];
95 Color descriptorColor = null;
96 Color presentColor = null;
97 for (EdgeCursor ec = edgeList.edges(); ec.ok(); ec.next()) {
98 final Edge edge = ec.edge();
99 if (colorProvider != null && colorProvider.get(edge) != null) {
100 descriptorColor = (Color) colorProvider.get(edge);
101 break;
102 }
103 final Color lineColor = graph.getRealizer(edge).getLineColor();
104 if (presentColor == null && !lineColor.equals(Color.BLACK)) {
105 presentColor = lineColor;
106 }
107 Color sourceFill = graph.getRealizer(edge.source()).getFillColor();
108 if (presentColor == null && !sourceFill.equals(Color.BLACK)) {
109 presentColor = sourceFill;
110 }
111 Color targetFill = graph.getRealizer(edge.target()).getFillColor();
112 if (presentColor == null && !targetFill.equals(Color.BLACK)) {
113 presentColor = targetFill;
114 }
115 if (presentColor != null && colorProvider == null) {
116 break;
117 }
118 }
119
120 if (descriptorColor != null && isAvailable(descriptorColor)) {
121 busColors[i] = descriptorColor;
122 use(descriptorColor);
123 } else if (presentColor != null && isAvailable(presentColor)) {
124 busColors[i] = presentColor;
125 use(presentColor);
126 }
127 }
128
129 for (int i = 0; i < isolatedHubs.length; i++) {
131 final Node isolatedHub = isolatedHubs[i];
132 final Color fillColor = graph.getRealizer(isolatedHub).getFillColor();
133 if (!fillColor.equals(Color.BLACK) && isAvailable(fillColor)) {
134 busColors[edgeLists.length + i] = fillColor;
135 use(fillColor);
136 }
137 }
138
139 for (int i = 0; i < busColors.length; i++) {
141 if (busColors[i] == null) {
142 busColors[i] = useNextColor();
143 }
144 }
145
146 for (int i = 0; i < edgeLists.length; i++) {
148 final EdgeList edgeList = edgeLists[i];
149 final Color color = busColors[i];
150 for (EdgeCursor ec = edgeList.edges(); ec.ok(); ec.next()) {
151 final Edge edge = ec.edge();
152 graph.getRealizer(edge).setLineColor(color);
153 colorizeHub(edge.source(), color);
154 colorizeHub(edge.target(), color);
155 }
156 }
157
158 for (int i = 0; i < isolatedHubs.length; i++) {
160 colorizeHub(isolatedHubs[i], busColors[edgeLists.length + i]);
161 }
162 }
163
164
168 public void onGraphEvent(GraphEvent e) {
169 switch (e.getType()) {
170 case GraphEvent.PRE_EVENT:
171 eventCount++;
172 break;
173 case GraphEvent.POST_EVENT:
174 eventCount--;
175 break;
176 case GraphEvent.NODE_CREATION:
177 case GraphEvent.NODE_REINSERTION:
178 case GraphEvent.PRE_NODE_REMOVAL:
179 case GraphEvent.POST_NODE_REMOVAL:
180 return; default:
182 }
183
184 if (eventCount == 0) {
185 colorize();
186 }
187 }
188
189
192 protected EdgeList[] calculateBusComponents(LayoutGraph graph) {
193 return BusRepresentations.toEdgeLists(graph, graph.getDataProvider(BusRouterDemo.HUB_MARKER_DPKEY));
194 }
195
196
202 private void colorizeHub(Node node, Color newColor) {
203 if (!hubMarker.getBool(node)) {
204 return;
205 }
206 final NodeRealizer realizer = graph.getRealizer(node);
207 realizer.setFillColor(newColor);
208 realizer.setLineColor(newColor);
209 }
210
211
214 private void resetColors() {
215 availableColorsPQ.clear();
216
217 Color[] colors = Colors.getColors(predefinedColorsCount + 1);
218 for (int i = 1; i < colors.length; i++) { final Color color = colors[i];
220 availableColorsPQ.add(color, i - 1);
221 }
222 }
223
224
229 private Color useNextColor() {
230 if (availableColorsPQ.isEmpty()) {
231 return Colors.getRandomColor();
232 } else {
233 return (Color) availableColorsPQ.removeMin();
234 }
235 }
236
237
242 private void use(final Color color) {
243 if (isAvailable(color)) {
244 availableColorsPQ.remove(color);
245 }
246 }
247
248
254 private boolean isAvailable(final Color color) {
255 return availableColorsPQ.contains(color);
256 }
257
258
261 static class Colors {
262
263 private static final Color[] COLORS = {new Color(0x000000), new Color(0xBF0404), new Color(0x009EFF),
265 new Color(0x1B8C48), new Color(0xB300C2), new Color(0xFF6405), new Color(0x2B4BFA), new Color(0x8C6048),
266 new Color(0xFAAFE8), new Color(0xB1D95B), new Color(0xBBB082), new Color(0xFAEE00), new Color(0xAAAAAA),
267 new Color(0x00FFC9), new Color(0x5B519C), new Color(0x666666)};
268
269 private static final Random RANDOM = new Random(1234L);
270
271
274 private Colors() {
275 }
276
277
284 static Color[] getColors(int count) {
285 Color[] r = new Color[count];
286 final int numColors = COLORS.length;
287 System.arraycopy(COLORS, 0, r, 0, Math.min(count, numColors));
288 if (count > numColors) {
289 double div = Math.ceil((double) (count / numColors)) + 1.0;
290 for (int i = numColors; i < count; i++) {
291 int j = i % numColors;
292 int k = (j + 1) % numColors;
293 Color c1 = COLORS[j];
294 Color c2 = COLORS[k];
295 double f = 1.0 / div * Math.ceil((double) (i / numColors));
296 r[i] = blendColors(c1, c2, f);
297 }
298 }
299 return r;
300 }
301
302
307 static Color getRandomColor() {
308 return new Color(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat());
309 }
310
311
316 private static Color blendColors(Color c1, Color c2, double div) {
317 int dr = (int) ((double) (c2.getRed() - c1.getRed()) * div);
318 int dg = (int) ((double) (c2.getGreen() - c1.getGreen()) * div);
319 int db = (int) ((double) (c2.getBlue() - c1.getBlue()) * div);
320 return new Color(c1.getRed() + dr, c1.getGreen() + dg, c1.getBlue() + db);
321 }
322
323 }
324
325 }
326