1
14 package demo.view.application;
15
16 import demo.view.DemoBase;
17 import demo.view.DemoDefaults;
18 import y.base.Node;
19 import y.geom.YInsets;
20 import y.layout.LayoutOrientation;
21 import y.layout.NodeLabelModel;
22 import y.layout.hierarchic.IncrementalHierarchicLayouter;
23 import y.layout.hierarchic.incremental.SimplexNodePlacer;
24 import y.option.RealizerCellRenderer;
25 import y.util.DataProviders;
26 import y.view.CreateEdgeMode;
27 import y.view.Drawable;
28 import y.view.DropSupport;
29 import y.view.EditMode;
30 import y.view.GenericNodeRealizer;
31 import y.view.Graph2D;
32 import y.view.Graph2DLayoutExecutor;
33 import y.view.Graph2DUndoManager;
34 import y.view.Graph2DView;
35 import y.view.Graph2DViewActions;
36 import y.view.HitInfo;
37 import y.view.LineType;
38 import y.view.MultiplexingNodeEditor;
39 import y.view.NodeRealizer;
40 import y.view.ShapeNodePainter;
41 import y.view.Graph2DListener;
42 import y.view.Graph2DEvent;
43 import y.view.NodeLabel;
44 import y.view.hierarchy.GenericGroupNodeRealizer;
45 import y.view.hierarchy.HierarchyManager;
46 import y.view.tabular.ColumnDropTargetListener;
47 import y.view.tabular.RowDropTargetListener;
48 import y.view.tabular.TableGroupNodeRealizer;
49 import y.view.tabular.TableGroupNodeRealizer.ColumnNodeLabelModel;
50 import y.view.tabular.TableGroupNodeRealizer.Column;
51 import y.view.tabular.TableGroupNodeRealizer.Row;
52 import y.view.tabular.TableGroupNodeRealizer.RowNodeLabelModel;
53 import y.view.tabular.TableLabelEditor;
54 import y.view.tabular.TableNodePainter;
55 import y.view.tabular.TableOrderEditor;
56 import y.view.tabular.TableSelectionEditor;
57 import y.view.tabular.TableSizeEditor;
58 import y.view.tabular.TableStyle;
59 import y.view.tabular.TableSupport;
60
61 import java.awt.BorderLayout;
62 import java.awt.Color;
63 import java.awt.Component;
64 import java.awt.Dimension;
65 import java.awt.EventQueue;
66 import java.awt.Graphics;
67 import java.awt.Graphics2D;
68 import java.awt.Paint;
69 import java.awt.Rectangle;
70 import java.awt.Stroke;
71 import java.awt.dnd.DnDConstants;
72 import java.awt.dnd.DragGestureEvent;
73 import java.awt.dnd.DragGestureListener;
74 import java.awt.dnd.DragSource;
75 import java.awt.event.ActionEvent;
76 import java.awt.geom.Rectangle2D;
77 import java.io.IOException;
78 import java.net.URL;
79 import java.util.Collection;
80 import java.util.Iterator;
81 import java.util.List;
82 import java.util.Map;
83 import javax.swing.AbstractAction;
84 import javax.swing.Action;
85 import javax.swing.DefaultListCellRenderer;
86 import javax.swing.Icon;
87 import javax.swing.ImageIcon;
88 import javax.swing.JButton;
89 import javax.swing.JComponent;
90 import javax.swing.JEditorPane;
91 import javax.swing.JList;
92 import javax.swing.JScrollPane;
93 import javax.swing.JToolBar;
94 import javax.swing.ListSelectionModel;
95 import javax.swing.ListCellRenderer;
96 import javax.swing.border.LineBorder;
97
98
112 public class SwimlaneDemo extends DemoBase {
113 static final String CONFIGURATION_GROUP_NODE = "CONFIGURATION_GROUP_NODE";
114 static final String CONFIGURATION_TABLE_NODE = "CONFIGURATION_TABLE_NODE";
115
116 static {
117 initConfigurations();
118 }
119
120
121 private YInsets rowInsets;
122 private YInsets columnInsets;
123 private Graph2DUndoManager undoManager;
124 protected String helpFile;
125 private MinimumSizeManager minimumSizeManager;
126
127
128 public static void main( String[] args ) {
129 EventQueue.invokeLater(new Runnable() {
130 public void run() {
131 initLnF();
132 final SwimlaneDemo demo = new SwimlaneDemo();
133 demo.setHelpFile("resource/swimlanehelp.html");
134 demo.start();
135 }
136 });
137 }
138
139 private NodeRealizer createConfiguredNormalNodeRealizer() {
140 final NodeRealizer normalNode = view.getGraph2D().getDefaultNodeRealizer().createCopy();
141 normalNode.setSize(80, 50);
142 return normalNode;
143 }
144
145 private NodeRealizer createConfiguredGroupNodeRealizer() {
146 final GenericGroupNodeRealizer ggnr = new GenericGroupNodeRealizer();
147 ggnr.setConfiguration(CONFIGURATION_GROUP_NODE);
148 ggnr.setFillColor(null);
149 ggnr.setLineType(LineType.DASHED_DOTTED_1);
150 ggnr.removeLabel(ggnr.getLabel());
151 ggnr.setGroupClosed(false);
152 ggnr.setSize(80, 50);
153 return ggnr;
154 }
155
156 private NodeRealizer createConfiguredTableNodeRealizer() {
157 final TableGroupNodeRealizer tgnr = new TableGroupNodeRealizer();
158 tgnr.setConfiguration(CONFIGURATION_TABLE_NODE);
159
160 tgnr.setFillColor(new Color(236, 245, 255));
162
163 final Color columnFillColor = new Color(113, 146, 178);
165 tgnr.setStyleProperty(
166 TableNodePainter.COLUMN_STYLE_ID,
167 new TableStyle.SimpleStyle(
168 tgnr.getLineType(),
169 tgnr.getLineColor(),
170 columnFillColor,
171 null,
172 null,
173 columnFillColor
174 )
175 );
176
177 final LineType lt = tgnr.getLineType();
178 final Color columnSelectedFillColor = new Color(55, 93, 129);
179 tgnr.setStyleProperty(
180 TableNodePainter.COLUMN_SELECTION_STYLE_ID,
181 new TableStyle.SimpleStyle(
182 LineType.getLineType((int) Math.ceil(lt.getLineWidth()) + 2, lt.getLineStyle()),
183 tgnr.getLineColor(),
184 columnSelectedFillColor,
185 null,
186 null,
187 columnSelectedFillColor
188 )
189 );
190
191 tgnr.setDefaultColumnWidth(600);
195 tgnr.setDefaultMinimumColumnWidth(200);
196 tgnr.setDefaultColumnInsets(columnInsets);
197 tgnr.setDefaultRowHeight(150);
198 tgnr.setDefaultMinimumRowHeight(50);
199 tgnr.setDefaultRowInsets(rowInsets);
200 tgnr.setAutoResize(true);
201
202 final TableGroupNodeRealizer.Table table = tgnr.getTable();
203 table.setInsets(new YInsets(30, 0, 0, 0));
204
205 tgnr.setSize(250, 200);
206 return tgnr;
207 }
208
209
213 private static void initConfigurations() {
214 final GenericNodeRealizer.Factory factory = GenericNodeRealizer.getFactory();
215
216 final Map groupMap = createGroupNodeConfiguration();
217 factory.addConfiguration(CONFIGURATION_GROUP_NODE, groupMap);
218
219 final Map tableMap = createTableNodeConfiguration();
220 factory.addConfiguration(CONFIGURATION_TABLE_NODE, tableMap);
221 }
222
223 protected void initialize() {
224 view.getGraph2D().addDataProvider(
226 EditMode.ORTHOGONAL_ROUTING_DPKEY,
227 DataProviders.createConstantDataProvider(Boolean.TRUE));
228
229 new HierarchyManager(view.getGraph2D());
231
232 minimumSizeManager = new MinimumSizeManager(view.getGraph2D());
233
234 rowInsets = new YInsets(0, 30, 0, 0);
235 columnInsets = new YInsets(30, 5, 0, 5);
236 final DropSupport dropSupport = createDropSupport(view);
237
238 contentPane.add(createDragNDropList(dropSupport), BorderLayout.WEST);
239
240 loadGraph( "resource/SwimlaneDemo.graphml" );
241
242 undoManager = new Graph2DUndoManager(view.getGraph2D());
243 undoManager.setViewContainer(view);
244
245 view.setPreferredSize(new Dimension(950, 550));
246 view.fitContent();
247 view.updateView();
248 }
249
250 protected void loadGraph( final URL resource ) {
251 minimumSizeManager.setEnabled(false);
254 try {
255 super.loadGraph(resource);
256 } finally {
257 minimumSizeManager.setEnabled(true);
258 }
259 }
260
261
269 public void setHelpFile(String helpFile) {
270 if (this.helpFile == null) {
271 this.helpFile = helpFile;
272 contentPane.add(createHelpPane(getClass().getResource(helpFile)), BorderLayout.EAST);
273 }
274 }
275
276 private static DropSupport createDropSupport(Graph2DView view) {
277 DropSupport dropSupport = new DropSupport(view) {
279
280 protected boolean dropNodeRealizer(Graph2DView view, NodeRealizer r, double worldCoordX, double worldCoordY) {
281 final HierarchyManager hm = HierarchyManager.getInstance(view.getGraph2D());
282 final HitInfo hitInfo = new HitInfo(view, worldCoordX, worldCoordY, true, HitInfo.NODE);
283 if (hm != null &&
284 hitInfo.hasHitNodes()) {
285 final Node node = (Node) hitInfo.hitNodes().current();
286 if (hm.isGroupNode(node) &&
287 ! (r instanceof TableGroupNodeRealizer)) {
288 return super.dropNodeRealizer(view, r, worldCoordX, worldCoordY);
290 }
291 } else if (r instanceof TableGroupNodeRealizer) {
292 return super.dropNodeRealizer(view, r, worldCoordX, worldCoordY);
293 }
294 return false;
295 }
296 };
297 dropSupport.setSnappingEnabled(true);
298 dropSupport.getSnapContext().setNodeToNodeDistance(30);
299 dropSupport.getSnapContext().setNodeToEdgeDistance(20);
300 dropSupport.getSnapContext().setUsingSegmentSnapLines(true);
301 dropSupport.setPreviewEnabled(true);
302 return dropSupport;
303 }
304
305 private JList createDragNDropList(final DropSupport support) {
306 final Object[] listContent = new Object[] {
307 createConfiguredTableNodeRealizer(),
308 DropItemListCellRenderer.DROP_TYPE_ROW,
309 DropItemListCellRenderer.DROP_TYPE_COLUMN,
310 createConfiguredNormalNodeRealizer(),
311 createConfiguredGroupNodeRealizer()
312 };
313
314 final Color lightBlueFillColor = new Color(126, 179, 240, 128);
315 final Color unselectedBorderColor = new Color(58, 82, 109);
316 final Stroke borderStroke = LineType.LINE_1;
317
318 final DropDrawable rowIcon = new DropDrawable(unselectedBorderColor, lightBlueFillColor, borderStroke);
320 rowIcon.insets = new YInsets(0, 15, 0, 0);
321 rowIcon.setBounds(0, 0, 80, 50);
322
323 final DropDrawable columnIcon = new DropDrawable(unselectedBorderColor, lightBlueFillColor, borderStroke);
324 columnIcon.insets = new YInsets(15, 0, 0, 0);
325 columnIcon.setBounds(0, 0, 80, 50);
326
327 final DropItemListCellRenderer cellRenderer =
328 new DropItemListCellRenderer(columnIcon, rowIcon);
329
330 final JList dropItemList = new JList(listContent);
332 dropItemList.setCellRenderer(cellRenderer);
333 dropItemList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
334 dropItemList.setSelectedIndex(0);
335 dropItemList.setFixedCellHeight(100);
336 dropItemList.setFixedCellWidth(100);
337 dropItemList.setBorder(LineBorder.createBlackLineBorder());
338
339 final DragSource dragSource = new DragSource();
340
341 final RowDropTargetListener rowListener =
343 new RowDropTargetListener(view) {
344 DropDrawable drawable = new DropDrawable(unselectedBorderColor, lightBlueFillColor, borderStroke);
345
346 protected Drawable createDrawable(Rectangle2D bounds, YInsets insets) {
347 drawable.insets = insets;
348 drawable.setBounds(bounds);
349 return drawable;
350 }
351 };
352 rowListener.setDefaultHeight(50);
353 rowListener.setDefaultMinimumHeight(30);
354 rowListener.setDrawableWidth(200);
355 rowListener.setDefaultInsets(rowInsets);
356 rowListener.setMaxLevel(2);
357
358
359 final ColumnDropTargetListener columnListener =
360 new ColumnDropTargetListener(view) {
361 DropDrawable drawable = new DropDrawable(unselectedBorderColor, lightBlueFillColor, borderStroke);
362
363 protected Drawable createDrawable(Rectangle2D bounds, YInsets insets) {
364 drawable.insets = insets;
365 drawable.setBounds(bounds);
366 return drawable;
367 }
368 };
369 columnListener.setDefaultWidth(100);
370 columnListener.setDefaultMinimumWidth(200);
371 columnListener.setDrawableHeight(180);
372 columnListener.setDefaultInsets(columnInsets);
373 columnListener.setMaxLevel(2);
374
375
376 dragSource.createDefaultDragGestureRecognizer(dropItemList, DnDConstants.ACTION_MOVE,
378 new DragGestureListener() {
379 public void dragGestureRecognized(DragGestureEvent event) {
380 final Object value = dropItemList.getSelectedValue();
381 if (value.equals(DropItemListCellRenderer.DROP_TYPE_ROW)) {
382 support.startDrag(dragSource,
383 rowListener,
384 event,
385 DragSource.DefaultMoveDrop);
386 } else if (value.equals(DropItemListCellRenderer.DROP_TYPE_COLUMN)) {
387 support.startDrag(dragSource,
388 columnListener,
389 event,
390 DragSource.DefaultMoveDrop);
391 } else if (value instanceof NodeRealizer) {
392 NodeRealizer nr = (NodeRealizer) value;
393 support.startDrag(dragSource, nr, event, DragSource.DefaultMoveDrop);
394 }
395 }
396 });
397 return dropItemList;
398 }
399
400
403 JComponent createHelpPane(URL helpURL) {
404 try {
405 JEditorPane editorPane = new JEditorPane(helpURL);
406 editorPane.setEditable(false);
407 editorPane.setPreferredSize(new Dimension(250, 250));
408 return new JScrollPane(editorPane);
409 } catch (IOException e) {
410 e.printStackTrace();
411 }
412 return null;
413 }
414
415
416
421 protected EditMode createEditMode() {
422 final EditMode editMode = super.createEditMode();
423
424 editMode.getMouseInputMode().setNodeSearchingEnabled(true);
426
427 editMode.allowNodeCreation(false);
429
430 editMode.setSnappingEnabled(true);
432
433 editMode.setOrthogonalEdgeRouting(true);
435
436 final CreateEdgeMode cem = new CreateEdgeMode();
438 cem.setFuzzyTargetPortDetermination(true);
439 cem.setSnapToOrthogonalSegmentsDistance(5);
440 cem.setUsingNodeCenterSnapping(true);
441 cem.setSnappingOrthogonalSegments(true);
442 cem.setIndicatingTargetNode(true);
443 cem.setRemovingInnerBends(true);
444 cem.setOrthogonalEdgeCreation(true);
445 editMode.setCreateEdgeMode(cem);
446
447 return editMode;
448 }
449
450
454 protected JToolBar createToolBar() {
455 final JToolBar toolBar = super.createToolBar();
456 toolBar.addSeparator();
457 final Action undoAction = undoManager.getUndoAction();
458 final URL undoIconUrl = DemoBase.class.getResource("resource/undo.png");
459 if (undoIconUrl != null) {
460 undoAction.putValue(Action.SMALL_ICON, new ImageIcon(undoIconUrl));
461 undoAction.putValue(Action.SHORT_DESCRIPTION, "Undo");
462 }
463 toolBar.add(createActionControl(undoAction, false));
464 final Action redoAction = undoManager.getRedoAction();
465 final URL redoIconUrl = DemoBase.class.getResource("resource/redo.png");
466 if (redoIconUrl != null) {
467 redoAction.putValue(Action.SMALL_ICON, new ImageIcon(redoIconUrl));
468 redoAction.putValue(Action.SHORT_DESCRIPTION, "Redo");
469 }
470 toolBar.add(createActionControl(redoAction, false));
471
472 toolBar.addSeparator();
473
474 final AbstractAction layoutAction = new AbstractAction("Layout") {
475 public void actionPerformed( ActionEvent e ) {
476 layout(view.getGraph2D());
477 view.updateView();
478 }
479 };
480 final URL resource = DemoBase.class.getResource("resource/layout.png");
481 if (resource != null) {
482 layoutAction.putValue(Action.SMALL_ICON, new ImageIcon(resource));
483 layoutAction.putValue(Action.SHORT_DESCRIPTION, "Layout");
484 }
485
486 toolBar.add(createActionControl(layoutAction, true));
487
488 return toolBar;
489 }
490
491
501 private JComponent createActionControl(
502 final Action action,
503 final boolean showActionText
504 ) {
505 final JButton jb = new JButton();
506 if (action.getValue(Action.SMALL_ICON) != null) {
507 jb.putClientProperty("hideActionText", showActionText ? Boolean.FALSE : Boolean.TRUE);
508 }
509 jb.setAction(action);
510 return jb;
511 }
512
513
519 protected Action createLoadAction() {
520 final Action action = super.createLoadAction();
521 return new AbstractAction((String) action.getValue(Action.NAME)) {
522 public void actionPerformed( final ActionEvent e ) {
523 action.actionPerformed(e);
524 undoManager.resetQueue();
525 }
526 };
527 }
528
529
532 private void layout( final Graph2D graph ) {
533 graph.firePreEvent();
534 try {
535 graph.backupRealizers();
537
538 final IncrementalHierarchicLayouter ihl = new IncrementalHierarchicLayouter();
539 ihl.setLayoutOrientation(LayoutOrientation.LEFT_TO_RIGHT);
540 ihl.setOrthogonallyRouted(true);
541 ihl.setRecursiveGroupLayeringEnabled(false);
542 ((SimplexNodePlacer) ihl.getNodePlacer()).setBaryCenterModeEnabled(true);
543
544 final Graph2DLayoutExecutor layoutExecutor = new Graph2DLayoutExecutor(Graph2DLayoutExecutor.BUFFERED);
545 layoutExecutor.setConfiguringTableNodeRealizers(true);
546 layoutExecutor.getTableLayoutConfigurator().setCompactionEnabled(false);
547 layoutExecutor.getTableLayoutConfigurator().setHorizontalLayoutConfiguration(true);
548 layoutExecutor.doLayout(graph, ihl);
549 view.fitContent();
550 view.updateView();
551 } finally {
552 graph.firePostEvent();
553 }
554 }
555
556 protected Action createDeleteSelectionAction() {
557 final Graph2DViewActions.DeleteSelectionAction action =
558 new Graph2DViewActions.DeleteSelectionAction(view);
559 action.setDeletionMask(Graph2DViewActions.DeleteSelectionAction.ALL_TYPES_MASK);
560 action.setKeepingTableNodesOnTableContentDeletion(true);
561 final URL deleteIconUrl = DemoBase.class.getResource("resource/delete.png");
562 if (deleteIconUrl != null) {
563 action.putValue(Action.SMALL_ICON, new ImageIcon(deleteIconUrl));
564 }
565 action.putValue(Action.SHORT_DESCRIPTION, "Delete Selection");
566 return action;
567 }
568
569 private static Map createGroupNodeConfiguration() {
570 final Map map = GenericGroupNodeRealizer.createDefaultConfigurationMap();
571 final ShapeNodePainter painter = new ShapeNodePainter(ShapeNodePainter.ROUND_RECT);
572 map.put(GenericNodeRealizer.ContainsTest.class, painter);
573 map.put(GenericNodeRealizer.Painter.class, painter);
574 map.put(GenericNodeRealizer.GenericMouseInputEditorProvider.class, null);
575 return map;
576 }
577
578 private static Map createTableNodeConfiguration() {
579 final Map map = TableGroupNodeRealizer.createDefaultConfigurationMap();
580
581 final AlternatingPainter rowPainter = new AlternatingPainter();
583 final TableNodePainter tableNodePainter = TableNodePainter.newDefaultInstance();
584 tableNodePainter.setSubPainter(TableNodePainter.PAINTER_ROW_BACKGROUND, rowPainter);
585 map.put(GenericNodeRealizer.Painter.class, tableNodePainter);
586
587 final MultiplexingNodeEditor editor = new MultiplexingNodeEditor();
589 final TableLabelEditor editLabelEditor = new TableLabelEditor();
590 editor.addNodeEditor(editLabelEditor);
591 final TableSelectionEditor tableSelectionEditor = new TableSelectionEditor();
592 tableSelectionEditor.setSelectionPolicy(TableSelectionEditor.RELATE_TO_NODE_SELECTION);
593 editor.addNodeEditor(tableSelectionEditor);
594 final TableSizeEditor resizeEditor = new TableSizeEditor();
595 editor.addNodeEditor(resizeEditor);
596 final TableOrderEditor tableOrderEditor = new TableOrderEditor();
597 tableOrderEditor.setMaxColumnLevel(2);
598 tableOrderEditor.setMaxRowLevel(2);
599 editor.addNodeEditor(tableOrderEditor);
600 map.put(GenericNodeRealizer.GenericMouseInputEditorProvider.class, editor);
601
602 return map;
603 }
604
605
613 private static final class MinimumSizeManager implements Graph2DListener {
614 private boolean enabled;
615
616 MinimumSizeManager( final Graph2D graph ) {
617 graph.addGraph2DListener(this);
618 enabled = true;
619 }
620
621 public boolean isEnabled() {
622 return enabled;
623 }
624
625 public void setEnabled( final boolean enabled ) {
626 this.enabled = enabled;
627 }
628
629 public void onGraph2DEvent( final Graph2DEvent e ) {
630 if (isEnabled()) {
631 if ("text".equals(e.getPropertyName())) {
632 final Object subject = e.getSubject();
633 if (subject instanceof NodeLabel) {
634 final NodeLabel label = (NodeLabel) subject;
635 final NodeLabelModel model = label.getLabelModel();
636 if (model instanceof ColumnNodeLabelModel) {
637 handleColumnLabelEvent(label);
638 } else if (model instanceof RowNodeLabelModel) {
639 handleRowLabelEvent(label);
640 }
641 }
642 }
643 }
644 }
645
646 private void handleRowLabelEvent( final NodeLabel label ) {
647 final Row row = RowNodeLabelModel.getRow(label);
648 if (row != null) {
649 final double h = label.getHeight() + 8;
650 if (h > row.getHeight()) {
651 (new TableSupport()).setHeight(row, h, false);
652 }
653 row.setMinimumHeight(Math.max(
654 h, ((TableGroupNodeRealizer) label.getRealizer())
655 .getDefaultMinimumRowHeight()));
656 }
657 }
658
659 private void handleColumnLabelEvent( final NodeLabel label ) {
660 final Column column = ColumnNodeLabelModel.getColumn(label);
661 if (column != null) {
662 final double w = label.getWidth() + 8;
663 if (w > column.getWidth()) {
664 (new TableSupport()).setWidth(column, w, false);
665 }
666 column.setMinimumWidth(Math.max(
667 w, ((TableGroupNodeRealizer) label.getRealizer())
668 .getDefaultMinimumColumnWidth()));
669 }
670 }
671 }
672 }
673
674
678
685 final class AlternatingPainter extends ShapeNodePainter {
686 private static final Color PARENT_ROW_COLOR = new Color(113, 146, 178);
687 private static final Color EVEN_ROW_COLOR = new Color(196, 215, 237);
688 private static final Color ODD_ROW_COLOR = new Color(171, 200, 226);
689 private static final Color SELECTED_ROW_COLOR = new Color(55, 93, 129);
690
691 AlternatingPainter() {
692 super(ShapeNodePainter.RECT);
693 }
694
695 protected Paint getFillPaint( final NodeRealizer context, final boolean selected ) {
696 return getFillColor(context, selected);
697 }
698
699
707 protected Color getFillColor( final NodeRealizer context, final boolean selected ) {
708 final Row row = TableNodePainter.getRow(context);
709 if (row.isSelected()) {
710 return SELECTED_ROW_COLOR;
711 }
712
713 if (row.getRows().isEmpty()) {
714 if (indexOf(row, TableNodePainter.getTable(context).getRows(), new int[]{-1}) % 2 == 0) {
715 return EVEN_ROW_COLOR;
716 } else {
717 return ODD_ROW_COLOR;
718 }
719 } else {
720 return PARENT_ROW_COLOR;
721 }
722 }
723
724
727 public void paint(NodeRealizer context, Graphics2D graphics) {
728 if (!context.isVisible()){
729 return;
730 }
731 backupGraphics(graphics);
732 try {
733 paintNode(context, graphics, false);
734 } finally {
735 restoreGraphics(graphics);
736 }
737 }
738
739
746 private int indexOf( final Row row, final Collection rows, final int[] i ) {
747 for (Iterator it = rows.iterator(); it.hasNext();) {
748 final Row r = (Row) it.next();
749 final List children = r.getRows();
750 if (children.isEmpty()) {
751 ++i[0];
752 if (r.equals(row)) {
753 return i[0];
754 }
755 } else {
756 final int idx = indexOf(row, children, i);
757 if (idx > -1) {
758 return idx;
759 }
760 }
761 }
762
763 return -1;
764 }
765 }
766
767
771
775 class DropDrawable implements Drawable, Icon {
776 Rectangle bounds;
777 YInsets insets;
778
779 Color borderColor;
780 Color fillColor;
781 Stroke stroke;
782
783
790 DropDrawable(Color borderColor, Color fillColor, Stroke stroke) {
791 this.borderColor = borderColor;
792 this.fillColor = fillColor;
793 this.stroke = stroke;
794 }
795
796
802 public void paint(Graphics2D g) {
803 g.setStroke(stroke);
804 paintIcon(null, g, bounds.x, bounds.y);
805 }
806
807
815 public void paintIcon(Component c, Graphics g, int x, int y) {
816 if (bounds == null ||
818 bounds.getX() != x ||
819 bounds.getY() != y) {
820 int newWidth = (bounds == null) ? 0 : bounds.width;
821 int newHeight = (bounds == null) ? 0 : bounds.height;
822 bounds = new Rectangle(x, y, newWidth, newHeight);
823 }
824
825 int cWidth = 0;
827 if (c != null) {
828 cWidth = c.getWidth() - 2;
829 }
830 int offX = (cWidth > getIconWidth()) ? (cWidth - getIconWidth())/2 : 0;
831
832 g.setColor(fillColor);
833 g.fillRect(bounds.x + offX, bounds.y, bounds.width, bounds.height);
834
835 g.setColor(borderColor);
836 g.drawRect(bounds.x + offX, bounds.y, bounds.width, bounds.height);
837
838 if (insets != null &&
839 (insets.top + insets.bottom < bounds.height &&
840 insets.left + insets.right < bounds.width)) {
841 g.setColor(fillColor);
842 g.fillRect((int) (bounds.x + offX + insets.left),
843 (int) (bounds.y + insets.top),
844 (int) (bounds.width - insets.left - insets.right),
845 (int) (bounds.height - insets.top - insets.bottom));
846 g.setColor(borderColor);
847 g.drawRect((int) (bounds.x + offX + insets.left),
848 (int) (bounds.y + insets.top),
849 (int) (bounds.width - insets.left - insets.right),
850 (int) (bounds.height - insets.top - insets.bottom));
851 }
852 }
853
854 public Rectangle getBounds() {
855 return bounds;
856 }
857
858
862 public void setBounds(Rectangle2D bounds) {
863 this.bounds = new Rectangle((int) bounds.getX(), (int) bounds.getY(),
864 (int) Math.ceil(bounds.getWidth()), (int) Math.ceil(bounds.getHeight()));
865 }
866
867
874 public void setBounds(int x, int y, int width, int height) {
875 this.bounds = new Rectangle(x, y, width, height);
876 }
877
878 public int getIconWidth() {
879 return bounds != null ? bounds.width : 0;
880 }
881
882 public int getIconHeight() {
883 return bounds != null ? bounds.height : 0;
884 }
885 }
886
887
891 class DropItemListCellRenderer implements ListCellRenderer {
892
895 static final Object DROP_TYPE_ROW = "DROP_TYPE_ROW";
896
899 static final Object DROP_TYPE_COLUMN = "DROP_TYPE_COLUMN";
900
901
902 private static final Dimension PREFERRED_SIZE = new Dimension(100, 100);
903
904 private final DefaultListCellRenderer dlcr;
905 private final RealizerCellRenderer realizerRenderer;
906
907 private final Icon rowIcon;
908 private final Icon columnIcon;
909
910
916 DropItemListCellRenderer(
917 final Icon columnIcon,
918 final Icon rowIcon
919 ) {
920 this.columnIcon = columnIcon;
921 this.rowIcon = rowIcon;
922
923 realizerRenderer = new RealizerCellRenderer(
924 PREFERRED_SIZE.width, PREFERRED_SIZE.height);
925 dlcr = new DefaultListCellRenderer();
926 }
927
928 public Component getListCellRendererComponent(
929 JList list,
930 Object value,
931 int index,
932 boolean isSelected,
933 boolean cellHasFocus
934 ) {
935 if (value instanceof NodeRealizer) {
936 final Component c = realizerRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
937 if (c instanceof JComponent) {
938 if (value instanceof GenericNodeRealizer) {
939 final String configuration = ((GenericNodeRealizer) value).getConfiguration();
940 if (SwimlaneDemo.CONFIGURATION_GROUP_NODE.equals(configuration)) {
941 ((JComponent) c).setToolTipText("Create new group node");
942 }
943 if (SwimlaneDemo.CONFIGURATION_TABLE_NODE.equals(configuration)) {
944 ((JComponent) c).setToolTipText("Create new table node");
945 }
946 if (DemoDefaults.NODE_CONFIGURATION.equals(configuration)) {
947 ((JComponent) c).setToolTipText("Create new child node");
948 }
949 } else {
950 ((JComponent) c).setToolTipText("Create new node");
951 }
952 }
953 return c;
954 } else {
955 dlcr.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
956 dlcr.setText("");
957 dlcr.setPreferredSize(PREFERRED_SIZE);
958 if (DROP_TYPE_COLUMN.equals(value)) {
959 dlcr.setIcon(columnIcon);
960 dlcr.setToolTipText("Create new column");
961 } else if (DROP_TYPE_ROW.equals(value)) {
962 dlcr.setIcon(rowIcon);
963 dlcr.setToolTipText("Create new row");
964 } else {
965 dlcr.setIcon(null);
966 dlcr.setToolTipText(null);
967 }
968 return dlcr;
969 }
970 }
971 }
972