1
28 package demo.layout.hierarchic;
29
30 import demo.view.DemoBase;
31 import y.io.GraphMLIOHandler;
32 import y.view.EditMode;
33 import y.view.Graph2D;
34 import y.view.Graph2DView;
35 import y.view.Graph2DViewActions;
36 import y.view.MoveSelectionMode;
37 import y.view.hierarchy.HierarchyManager;
38 import y.view.tabular.TableGroupNodeRealizer;
39 import y.view.tabular.TableGroupNodeRealizer.Column;
40 import y.view.tabular.TableGroupNodeRealizer.Row;
41 import y.view.tabular.TableGroupNodeRealizer.Table;
42
43 import java.awt.Color;
44 import java.awt.EventQueue;
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.Collections;
48 import java.util.Comparator;
49 import java.util.HashMap;
50 import java.util.HashSet;
51 import java.util.Iterator;
52 import java.util.Locale;
53 import java.util.Map;
54 import javax.swing.Action;
55 import javax.swing.ActionMap;
56 import javax.swing.JMenu;
57 import javax.swing.JMenuBar;
58 import javax.swing.JToggleButton;
59 import javax.swing.JToolBar;
60
61
76 public class CellSpanLayoutDemo extends DemoBase {
77 static {
79 CellSpanRealizerFactory.initConfigurations();
80 }
81
82
86 public CellSpanLayoutDemo() {
87 this(null);
88 }
89
90
95 public CellSpanLayoutDemo( final String helpFilePath ) {
96 initGraph(view.getGraph2D());
97 addHelpPane(helpFilePath);
98 }
99
100
103 protected void initialize() {
104 new HierarchyManager(view.getGraph2D());
105 }
106
107
111 protected Action createDeleteSelectionAction() {
112 return CellSpanActionFactory.newDeleteSelection(view);
113 }
114
115
122 protected void registerViewActions() {
123 super.registerViewActions();
124
125 final ActionMap amap = view.getCanvasComponent().getActionMap();
126 if (amap != null) {
127 final Object[] keys = {
128 Graph2DViewActions.CLOSE_GROUPS,
129 Graph2DViewActions.OPEN_FOLDERS,
130 Graph2DViewActions.GROUP_SELECTION,
131 Graph2DViewActions.FOLD_SELECTION,
132 Graph2DViewActions.UNGROUP_SELECTION,
133 Graph2DViewActions.UNFOLD_SELECTION,
134 };
135 for (int i = 0; i < keys.length; ++i) {
136 amap.remove(keys[i]);
137 }
138 }
139 }
140
141
159 protected EditMode createEditMode() {
160 final EditMode editMode = configureEditMode(
161 CellSpanControllerFactory.newCellEditMode());
162
163 final MoveSelectionMode msm = new MoveSelectionMode();
165 msm.setGroupReassignmentEnabled(false);
166 editMode.setMoveSelectionMode(msm);
167
168 editMode.getMouseInputMode().setNodeSearchingEnabled(true);
170
171 editMode.setChildNodeCreationEnabled(true);
175
176 return editMode;
177 }
178
179
184 protected GraphMLIOHandler createGraphMLIOHandler() {
185 return CellSpanIoSupport.configure(super.createGraphMLIOHandler());
186 }
187
188
193 protected boolean isClipboardEnabled() {
194 return false;
195 }
196
197
200 protected JMenuBar createMenuBar() {
201 final JMenu jm = new JMenu("Samples");
202 jm.add(CellSpanActionFactory.newSampleAction(
203 "Sample 1", this, "resource/CellSpanLayoutDemoS01.graphml"));
204 jm.add(CellSpanActionFactory.newSampleAction(
205 "Sample 2", this, "resource/CellSpanLayoutDemoS02.graphml"));
206 jm.add(CellSpanActionFactory.newSampleAction(
207 "Sample 3", this, "resource/CellSpanLayoutDemoS03.graphml"));
208 jm.add(CellSpanActionFactory.newSampleAction(
209 "Sample 4", this, "resource/CellSpanLayoutDemoS04.graphml"));
210 jm.add(CellSpanActionFactory.newSampleAction(
211 "Sample 5", this, "resource/CellSpanLayoutDemoS05.graphml"));
212
213 final JMenuBar jmb = super.createMenuBar();
214 jmb.add(jm);
215 return jmb;
216 }
217
218
223 protected JToolBar createToolBar() {
224 final JToolBar jtb = super.createToolBar();
225 jtb.addSeparator();
226
227 final JToggleButton tb1 = new JToggleButton();
230 final JToggleButton tb2 = new JToggleButton();
231 tb1.setAction(CellSpanActionFactory.newSwitchViewStateAction("Diagram", view, tb2));
232 jtb.add(tb1);
233 tb2.setSelected(true);
234 tb2.setAction(CellSpanActionFactory.newSwitchViewStateAction("Design", view, tb1));
235 tb2.setEnabled(false);
236 jtb.add(tb2);
237 return jtb;
238 }
239
240
245 protected void loadGraph( final String resource ) {
246 super.loadGraph(resource);
247 }
248
249
254 protected Graph2DView getView() {
255 return view;
256 }
257
258
261 private void initGraph(final Graph2D graph) {
262 graph.clear();
263 loadGraph("resource/CellSpanLayoutDemoS01.graphml");
264 getUndoManager().resetQueue();
265 }
266
267 public static void main(String[] args) {
268 EventQueue.invokeLater(new Runnable() {
269 public void run() {
270 Locale.setDefault(Locale.ENGLISH);
271 initLnF();
272 (new CellSpanLayoutDemo("resource/cellspanlayouthelp.html")).start();
273 }
274 });
275 }
276
277
278
282 static Graph2D getGraph2D( final Table table ) {
283 return (Graph2D) table.getRealizer().getNode().getGraph();
284 }
285
286
287
305 static final class CellColorManager {
306
307 private static final Color[] COLORS = newColors();
308
309
310
316 private final Map data;
317
318
322 CellColorManager() {
323 data = new HashMap();
324 }
325
326
330 CellColorManager( final CellColorManager prototype ) {
331 data = new HashMap(prototype.data);
332 }
333
334
339 Color nextUnused() {
340 final HashSet used = new HashSet(data.values());
341 Color color = null;
342 for (int i = 0; i < COLORS.length; ++i) {
343 if (!used.contains(COLORS[i])) {
344 color = COLORS[i];
345 break;
346 }
347 }
348 return color;
349 }
350
351
358 Color getCellColor( final Column col, final Row row ) {
359 if (col != null && row != null) {
360 return (Color) data.get(new CellKey(col, row));
361 } else {
362 return null;
363 }
364 }
365
366
373 void setCellColor( final Column col, final Row row, final Color color ) {
374 if (col != null && row != null) {
375 if (color == null) {
376 data.remove(new CellKey(col, row));
377 } else {
378 data.put(new CellKey(col, row), color);
379 }
380 }
381 }
382
383
389 void setCellColor( final Span span, final Color color ) {
390 if (color == null) {
391 for (int i = span.minCol, n = span.maxCol + 1; i < n; ++i) {
392 for (int j = span.minRow, m = span.maxRow + 1; j < m; ++j) {
393 data.remove(new CellKey(i, j));
394 }
395 }
396 } else {
397 for (int i = span.minCol, n = span.maxCol + 1; i < n; ++i) {
398 for (int j = span.minRow, m = span.maxRow + 1; j < m; ++j) {
399 data.put(new CellKey(i, j), color);
400 }
401 }
402 }
403 }
404
405
412 void shift( final Column column, final boolean up ) {
413 shiftImpl(column.getIndex(), false, up);
414 }
415
416
423 void shift( final Row row, final boolean up ) {
424 shiftImpl(row.getIndex(), true, up);
425 }
426
427
437 private void shiftImpl( final int idx, final boolean row, final boolean up ) {
438 final ArrayList keys = new ArrayList(data.keySet());
439 Collections.sort(keys, new CellComparator(row, up));
440 final int offset = up ? 1 : -1;
441 for (Iterator it = keys.iterator(); it.hasNext();) {
442 final CellKey key = (CellKey) it.next();
443 final int value = row ? key.row : key.column;
444 if (value >= idx) {
445 final Object color = data.remove(key);
446 if (up || value > idx) {
447 if (row) {
448 data.put(new CellKey(key.column, key.row + offset), color);
449 } else {
450 data.put(new CellKey(key.column + offset, key.row), color);
451 }
452 }
453 }
454 }
455 }
456
457
461 static CellColorManager getInstance( final Table table ) {
462 final TableGroupNodeRealizer tgnr = table.getRealizer();
463 return (CellColorManager) tgnr.getUserData();
464 }
465
466
469 private static Color[] newColors() {
470 return new Color[] {
471 new Color(192, 0, 0),
472 new Color(255, 102, 0),
473 new Color(251, 176, 7),
474 new Color( 0, 153, 57),
475 new Color( 0, 137, 205),
476
477 new Color(238, 53, 81),
478 new Color(255, 134, 56),
479 new Color(242, 228, 21),
480 new Color(149, 209, 39),
481 new Color( 17, 175, 252),
482 };
483
484 }
496 }
497
498
501 private static final class CellComparator implements Comparator {
502 private final boolean row;
503 private final int lessThan;
504 private int greaterThan;
505
506 CellComparator( final boolean row, final boolean descending ) {
507 this.row = row;
508 lessThan = descending ? 1 : -1;
509 greaterThan = descending ? -1 : 1;
510 }
511
512 public int compare( final Object o1, final Object o2 ) {
513 final int v1 = getValue((CellKey) o1);
514 final int v2 = getValue((CellKey) o2);
515 if (v1 < v2) {
516 return lessThan;
517 } else if (v1 > v2) {
518 return greaterThan;
519 } else {
520 return 0;
521 }
522 }
523
524 int getValue( final CellKey key ) {
525 return row ? key.row : key.column;
526 }
527 }
528
529
532 private static final class CellKey {
533 private final int column;
535 private final int row;
537
538 CellKey( final Column column, final Row row ) {
539 this(column.getIndex(), row.getIndex());
540 }
541
542 CellKey( final int column, final int row ) {
543 this.column = column;
544 this.row = row;
545 }
546
547 public boolean equals( final Object o ) {
548 if (this == o) return true;
549 if (o == null || getClass() != o.getClass()) return false;
550
551 final CellKey cellKey = (CellKey) o;
552
553 if (column != cellKey.column) return false;
554 if (row != cellKey.row) return false;
555
556 return true;
557 }
558
559 public int hashCode() {
560 int result = column;
561 result = 31 * result + row;
562 return result;
563 }
564
565 public String toString() {
566 return "[c=" + column + ";" + "r=" + row + "]";
567 }
568 }
569
570
573 static final class Cell {
574 private final Column column;
576 private final Row row;
578
579 Cell( final Column column, final Row row ) {
580 this.column = column;
581 this.row = row;
582 }
583
584 public boolean equals( final Object o ) {
585 if (this == o) return true;
586 if (o == null || getClass() != o.getClass()) return false;
587
588 final Cell cell = (Cell) o;
589
590 if (!column.equals(cell.column)) return false;
591 if (!row.equals(cell.row)) return false;
592
593 return true;
594 }
595
596 public int hashCode() {
597 int result = column.hashCode();
598 result = 31 * result + row.hashCode();
599 return result;
600 }
601
602 public String toString() {
603 return "[c=" + column.getIndex() + ";" + "r=" + row.getIndex() + "]";
604 }
605 }
606
607
610 static final class Span {
611 final int minCol;
613 final int maxCol;
615 final int minRow;
617 final int maxRow;
619
620 private Span(
621 final int minCol, final int maxCol,
622 final int minRow, final int maxRow
623 ) {
624 this.minCol = minCol;
625 this.maxCol = maxCol;
626 this.minRow = minRow;
627 this.maxRow = maxRow;
628 }
629
630
637 boolean contains( final Column col, final Row row ) {
638 final int cIdx = col.getIndex();
639 final int rIdx = row.getIndex();
640 return minCol <= cIdx && cIdx <= maxCol &&
641 minRow <= rIdx && rIdx <= maxRow;
642 }
643
644
651 boolean contains( final Span span ) {
652 return minCol <= span.minCol && span.maxCol <= maxCol &&
653 minRow <= span.minRow && span.maxRow <= maxRow;
654 }
655
656
667 static Span find(
668 final Table table, final Column col, final Row row,
669 final Color color
670 ) {
671 final CellColorManager manager = CellColorManager.getInstance(table);
672
673 int minCIdx = col.getIndex();
674 int maxCIdx = minCIdx;
675 int minRIdx = row.getIndex();
676 int maxRIdx = minRIdx;
677
678 final HashSet seen = new HashSet();
685 final ArrayList stack = new ArrayList();
686 stack.add(new Cell(col, row));
687 while (!stack.isEmpty()) {
688 final Cell cell = (Cell) stack.remove(stack.size() - 1);
689 if (seen.add(cell)) {
690 final Column c = cell.column;
691 final int cIdx = c.getIndex();
692 final Row r = cell.row;
693 final int rIdx = r.getIndex();
694
695 if (rIdx > 0) {
696 final Row north = table.getRow(rIdx - 1);
697 if (color.equals(manager.getCellColor(c, north))) {
698 stack.add(new Cell(c, north));
699
700 if (minRIdx > rIdx - 1) {
701 minRIdx = rIdx - 1;
702 }
703 }
704 }
705 if (cIdx > 0) {
706 final Column west = table.getColumn(cIdx - 1);
707 if (color.equals(manager.getCellColor(west, r))) {
708 stack.add(new Cell(west, r));
709
710 if (minCIdx > cIdx - 1) {
711 minCIdx = cIdx - 1;
712 }
713 }
714 }
715 if (rIdx + 1 < table.rowCount()) {
716 final Row south = table.getRow(rIdx + 1);
717 if (color.equals(manager.getCellColor(c, south))) {
718 stack.add(new Cell(c, south));
719
720 if (maxRIdx < rIdx + 1) {
721 maxRIdx = rIdx + 1;
722 }
723 }
724 }
725 if (cIdx + 1 < table.columnCount()) {
726 final Column east = table.getColumn(cIdx + 1);
727 if (color.equals(manager.getCellColor(east, r))) {
728 stack.add(new Cell(east, r));
729
730 if (maxCIdx < cIdx + 1) {
731 maxCIdx = cIdx + 1;
732 }
733 }
734 }
735 }
736 }
737
738 return new Span(minCIdx, maxCIdx, minRIdx, maxRIdx);
739 }
740
741
746 static Span span( final Collection cells ) {
747 final Iterator it = cells.iterator();
748 final Cell first = (Cell) it.next();
749
750 int minCIdx = first.column.getIndex();
751 int maxCIdx = minCIdx;
752 int minRIdx = first.row.getIndex();
753 int maxRIdx = minRIdx;
754
755 while (it.hasNext()) {
756 final Cell cell = (Cell) it.next();
757
758 final int cIdx = cell.column.getIndex();
759 final int rIdx = cell.row.getIndex();
760 if (minCIdx > cIdx) {
761 minCIdx = cIdx;
762 }
763 if (maxCIdx < cIdx) {
764 maxCIdx = cIdx;
765 }
766 if (minRIdx > rIdx) {
767 minRIdx = rIdx;
768 }
769 if (maxRIdx < rIdx) {
770 maxRIdx = rIdx;
771 }
772 }
773
774 return new Span(minCIdx, maxCIdx, minRIdx, maxRIdx);
775 }
776
777
785 static Span manual(
786 final int minCol, final int maxCol,
787 final int minRow, final int maxRow
788 ) {
789 return new Span(minCol, maxCol, minRow, maxRow);
790 }
791 }
792 }
793