1
14 package demo.view.application;
15
16 import demo.view.DemoBase;
17
18 import y.base.Edge;
19 import y.base.EdgeCursor;
20 import y.base.EdgeList;
21 import y.base.Node;
22 import y.base.NodeCursor;
23 import y.base.NodeList;
24 import y.base.YCursor;
25 import y.geom.YPoint;
26 import y.layout.Layouter;
27 import y.layout.LayoutOrientation;
28 import y.layout.hierarchic.incremental.EdgeLayoutDescriptor;
29 import y.layout.hierarchic.IncrementalHierarchicLayouter;
30 import y.util.GraphCopier;
31 import y.view.EditMode;
32 import y.view.Graph2D;
33 import y.view.Graph2DSelectionEvent;
34 import y.view.Graph2DSelectionListener;
35 import y.view.Graph2DView;
36 import y.view.HitInfo;
37 import y.view.LocalViewCreator.*;
38 import y.view.ViewMode;
39 import y.view.LocalViewCreator;
40 import y.view.ModelViewManager;
41 import y.view.NodeRealizer;
42 import y.view.hierarchy.GroupNodeRealizer;
43 import y.view.hierarchy.HierarchyManager;
44
45 import java.awt.BorderLayout;
46 import java.awt.CardLayout;
47 import java.awt.Dimension;
48 import java.awt.EventQueue;
49 import java.awt.FlowLayout;
50 import java.awt.GridBagConstraints;
51 import java.awt.GridBagLayout;
52 import java.awt.Insets;
53 import java.awt.geom.Point2D;
54 import java.awt.event.ActionEvent;
55 import java.awt.event.ActionListener;
56 import java.net.URL;
57 import java.util.HashSet;
58 import java.util.Iterator;
59 import java.util.Locale;
60
61 import javax.swing.AbstractAction;
62 import javax.swing.BorderFactory;
63 import javax.swing.Box;
64 import javax.swing.ButtonGroup;
65 import javax.swing.JPanel;
66 import javax.swing.JCheckBox;
67 import javax.swing.JComponent;
68 import javax.swing.JLabel;
69 import javax.swing.JRadioButton;
70 import javax.swing.JSpinner;
71 import javax.swing.JSplitPane;
72 import javax.swing.SpinnerNumberModel;
73 import javax.swing.Timer;
74 import javax.swing.Action;
75 import javax.swing.border.CompoundBorder;
76 import javax.swing.event.ChangeEvent;
77 import javax.swing.event.ChangeListener;
78
79
101 public class LocalViewDemo extends DemoBase {
102
106 private static final int TIMER_DELAY = 100;
107
108
112 private static final byte SELECTION_TRIGGER = 1;
113
117 private static final byte HOVER_TRIGGER = 2;
118
119
120 private final Graph2DView localView;
121
122 private final Neighborhood neighborhood;
124 private final CommonParentGroup commonParentGroup;
125 private final AncestorGroups ancestorGroups;
126 private final FolderContents folderContents;
127
128 private final SourceAndTarget sourceAndTarget;
130 private final EdgeGroup edgeGroup;
131
132 private final SelectedSubgraph selectedSubgraph;
134
135 private LocalViewCreator currentLocalViewCreator;
137 private AbstractLocalViewCreator nodeLocalViewCreator;
139 private AbstractLocalViewCreator edgeLocalViewCreator;
141
142
143 private final SelectionTrigger selectionTrigger;
146 private final HoverTrigger hoverTrigger;
149
150 private byte triggerType;
152
153
154 public LocalViewDemo() {
155 this(null);
156 }
157
158 public LocalViewDemo( final String helpFilePath ) {
159 final Graph2D graph = view.getGraph2D();
160 (new HierarchyManager(graph)).addHierarchyListener(
161 new GroupNodeRealizer.StateChangeListener());
162
163
164 final GraphCopier.CopyFactory factory = graph.getGraphCopyFactory();
169 final Graph2D localViewGraph = (Graph2D) factory.createGraph();
170
171 localView = new Graph2DView(localViewGraph);
172 localView.setPreferredSize(new Dimension(320, 240));
173
174 final Layouter layouter = createLayouter();
175 neighborhood = new Neighborhood(graph, factory, localViewGraph);
176 neighborhood.setLayouter(layouter);
177 commonParentGroup = new CommonParentGroup(graph, factory, localViewGraph);
178 ancestorGroups = new AncestorGroups(graph, factory, localViewGraph);
179 folderContents = new FolderContents(graph, factory, localViewGraph);
180
181 sourceAndTarget = new SourceAndTarget(graph, factory, localViewGraph);
182 sourceAndTarget.setLayouter(layouter);
183 edgeGroup = new EdgeGroup(graph, factory, localViewGraph);
184 edgeGroup.setLayouter(layouter);
185
186 selectedSubgraph = new SelectedSubgraph(graph, factory, localViewGraph);
187
188
189 setEdgeLocalViewCreator(sourceAndTarget);
190 setNodeLocalViewCreator(neighborhood);
191
192
193 loadGraph("resource/LocalViewDemo.graphml");
195
196
197 localView.addViewMode(new ViewMode() {
200 public void mouseClicked(double x, double y) {
201 if (lastClickEvent.getClickCount() == 2) {
203 final HitInfo hitInfo = getHitInfo(x, y);
204 final Graph2DView view = LocalViewDemo.this.view;
205 final Graph2D viewGraph = view.getGraph2D();
206 if (hitInfo.getHitNode() != null) {
208 final LocalViewCreator lvc = getCurrentLocalViewCreator();
210 final Node modelNode = lvc.getModelNode(hitInfo.getHitNode());
211 if (modelNode != null) {
212 if (modelNode.getGraph() == viewGraph) {
213 viewGraph.unselectAll();
215 final NodeRealizer nr = viewGraph.getRealizer(modelNode);
216 Point2D.Double center = new Point2D.Double(nr.getCenterX(), nr.getCenterY());
217 double minZoom = Math.min(view.getWidth() / (nr.getWidth() + 40),
218 view.getHeight() / (nr.getHeight() + 40));
219 view.focusView(Math.min(minZoom, view.getZoom()), center, true);
220 viewGraph.setSelected(modelNode, true);
221 viewGraph.updateViews();
222 }
223 }
224 } else if (hitInfo.getHitEdge() != null) { final LocalViewCreator lvc = getCurrentLocalViewCreator();
227 final Edge modelEdge = lvc.getModelEdge(hitInfo.getHitEdge());
228 if (modelEdge != null) {
229 if(modelEdge.getGraph() == viewGraph) {
230 final NodeRealizer snr = viewGraph.getRealizer(modelEdge.source());
232 final NodeRealizer tnr = viewGraph.getRealizer(modelEdge.target());
233 Point2D.Double sCenter = new Point2D.Double(snr.getCenterX(), snr.getCenterY());
234 Point2D.Double tCenter = new Point2D.Double(tnr.getCenterX(), tnr.getCenterY());
235 double minZoom =
236 Math.min(
237 view.getWidth()/(snr.getWidth() + tnr.getWidth() + Math.abs(sCenter.x - tCenter.x)),
238 view.getHeight() / (snr.getHeight() + tnr.getHeight() + Math.abs(sCenter.y - tCenter.y)));
239 view.focusView(Math.min(view.getZoom(), minZoom), new Point2D.Double((sCenter.x + tCenter.x) * 0.5d, (sCenter.y + tCenter.y) * 0.5d), true);
240 viewGraph.unselectAll();
241 viewGraph.setSelected(modelEdge, true);
242 viewGraph.updateViews();
243 }
244 }
245 }
246 }
247 }
248 });
249
250 localView.setFitContentOnResize(true);
251
252 selectionTrigger = new SelectionTrigger();
253 hoverTrigger = new HoverTrigger();
254
255 final JSplitPane localViewAndSettings = new JSplitPane(
256 JSplitPane.VERTICAL_SPLIT, localView, createSettingsComponent());
257 localViewAndSettings.setBorder(BorderFactory.createEmptyBorder());
258 localViewAndSettings.setResizeWeight(1);
259 final JSplitPane center = new JSplitPane(
260 JSplitPane.HORIZONTAL_SPLIT, localViewAndSettings, view);
261 center.setBorder(BorderFactory.createEmptyBorder());
262 center.setResizeWeight(0);
263
264 contentPane.add(center, BorderLayout.CENTER);
265 addHelpPane(helpFilePath);
266
267 setTrigger(SELECTION_TRIGGER);
269
270
271 if (!graph.isEmpty()) {
273 graph.unselectAll();
274 for (NodeCursor nc = graph.nodes(); nc.ok(); nc.next()) {
275 if (nc.node().inDegree() > 0 && nc.node().outDegree() > 0) {
276 graph.setSelected(nc.node(), true);
277 break;
278 }
279 }
280 if (graph.isSelectionEmpty()) {
281 graph.setSelected(graph.firstNode(), true);
282 }
283 graph.updateViews();
284 }
285 }
286
287
290 protected EditMode createEditMode() {
291 EditMode editMode = super.createEditMode();
292 editMode.allowEdgeCreation(false);
293 editMode.allowNodeCreation(false);
294 return editMode;
295 }
296
297
300 protected Action createSaveAction() {
301 return null;
302 }
303
304
307 protected void loadGraph( final URL resource ) {
308 if (resource != null && localView != null) {
309 localView.getGraph2D().clear();
310 }
311
312 super.loadGraph(resource);
313
314 if (resource != null && localView != null) {
315 localView.updateView();
316 }
317 }
318
319
328 private void setTrigger( final byte triggerType ) {
329 switch (this.triggerType) {
331 case SELECTION_TRIGGER:
332 view.getGraph2D().removeGraph2DSelectionListener(selectionTrigger);
333 break;
334 case HOVER_TRIGGER:
335 view.removeViewMode(hoverTrigger);
336 break;
337 }
338
339 this.triggerType = triggerType;
340
341 switch (this.triggerType) {
343 case SELECTION_TRIGGER:
344 view.getGraph2D().addGraph2DSelectionListener(selectionTrigger);
345 break;
346 case HOVER_TRIGGER:
347 view.addViewMode(hoverTrigger);
348 break;
349 }
350 }
351
352
353
357 private void setEdgeLocalViewCreator( final AbstractLocalViewCreator elvc ) {
358 final boolean update = currentLocalViewCreator == edgeLocalViewCreator;
359
360 edgeLocalViewCreator = elvc;
361
362 updateEdgeViewImpl(update);
364 }
365
366
370 private void updateEdgeView() {
371 updateEdgeViewImpl(currentLocalViewCreator == edgeLocalViewCreator);
372 }
373
374 private void updateEdgeViewImpl( final boolean update ) {
375 if (update) {
376 if (SELECTION_TRIGGER == triggerType) {
377 createEdgeView(view.getGraph2D().selectedEdges());
378 } else {
379 createEdgeView(new EdgeList().edges());
380 }
381 }
382 }
383
384
388 private void setNodeLocalViewCreator( final AbstractLocalViewCreator nlvc ) {
389 final boolean update = currentLocalViewCreator == nodeLocalViewCreator;
390
391 nodeLocalViewCreator = nlvc;
392
393 updateNodeViewImpl(update);
395 }
396
397
401 private void updateNodeView() {
402 updateNodeViewImpl(currentLocalViewCreator == nodeLocalViewCreator);
403 }
404
405 private void updateNodeViewImpl( final boolean update ) {
406 if (update) {
407 if (SELECTION_TRIGGER == triggerType) {
408 createNodeView(view.getGraph2D().selectedNodes());
409 } else {
410 createNodeView((new NodeList().nodes()));
411 }
412 }
413 }
414
415
420 private void createEdgeView( final YCursor edges ) {
421 currentLocalViewCreator = edgeLocalViewCreator;
424
425 edgeLocalViewCreator.clearFocusEdges();
428 for (; edges.ok(); edges.next()) {
429 edgeLocalViewCreator.addFocusEdge((Edge) edges.current());
430 }
431
432 edgeLocalViewCreator.updateViewGraph();
441 }
442
443
448 private void createNodeView( final YCursor nodes ) {
449 currentLocalViewCreator = nodeLocalViewCreator;
452
453 nodeLocalViewCreator.clearFocusNodes();
456 for (; nodes.ok(); nodes.next()) {
457 nodeLocalViewCreator.addFocusNode((Node) nodes.current());
458 }
459
460 nodeLocalViewCreator.updateViewGraph();
469 }
470
471
475 private LocalViewCreator getCurrentLocalViewCreator() {
476 return currentLocalViewCreator;
477 }
478
479
485 private JComponent createSettingsComponent() {
486 final JPanel settingsPane = new JPanel(new CardLayout());
487
488 final Box nodeStrategyButtons = Box.createVerticalBox();
489 nodeStrategyButtons.setBorder(BorderFactory.createTitledBorder("Node Strategies"));
490
491 final ButtonGroup nodeStrategiesGroup = new ButtonGroup();
492
493 addStrategy(settingsPane, nodeStrategyButtons, nodeStrategiesGroup, "Neighborhood", createNeighborhoodSettings(), neighborhood, true);
495 addStrategy(settingsPane, nodeStrategyButtons, nodeStrategiesGroup, "Common Parent Group", createCommonParentGroupSettings(), commonParentGroup, true);
496 addStrategy(settingsPane, nodeStrategyButtons, nodeStrategiesGroup, "Ancestor Groups", createAncestorGroupsSettings(), ancestorGroups, true);
497 addStrategy(settingsPane, nodeStrategyButtons, nodeStrategiesGroup, "Folder Contents", createFolderContentsSettings(), folderContents, true);
498 addStrategy(settingsPane, nodeStrategyButtons, nodeStrategiesGroup, "Selected Subgraph", null, selectedSubgraph, true);
499
500
501 final ButtonGroup edgeStrategiesGroup = new ButtonGroup();
502 final Box edgeStrategyButtons = Box.createVerticalBox();
503 edgeStrategyButtons.setBorder(BorderFactory.createTitledBorder("Edge Strategies"));
504
505 addStrategy(settingsPane, edgeStrategyButtons, edgeStrategiesGroup, "Source and Target", createSourceAndTargetSettings(), sourceAndTarget, false);
507 addStrategy(settingsPane, edgeStrategyButtons, edgeStrategiesGroup, "Edge Group", createEdgeGroupSettings(), edgeGroup, false);
508
509
510 Box container = Box.createVerticalBox();
511 container.add(createTriggerPane());
512
513 final GridBagConstraints gbc = new GridBagConstraints();
515 final JPanel strategies = new JPanel(new GridBagLayout());
516 gbc.anchor = GridBagConstraints.NORTHWEST;
517 gbc.fill = GridBagConstraints.HORIZONTAL;
518 gbc.gridx = 0;
519 gbc.weightx = 1;
520 gbc.weighty = 0;
521 strategies.add(nodeStrategyButtons, gbc);
522 strategies.add(edgeStrategyButtons, gbc);
523 gbc.fill = GridBagConstraints.BOTH;
524 gbc.weighty = 1;
525 strategies.add(Box.createGlue(), gbc);
526
527 Box strategy = Box.createHorizontalBox();
528 strategy.add(strategies);
529 strategy.add(settingsPane);
530
531 container.add(strategy);
532 return container;
533 }
534
535
541 private JComponent createSourceAndTargetSettings() {
542 final JCheckBox hierarchyAware = new JCheckBox("Hierarchy aware");
543 hierarchyAware.addActionListener(new ActionListener() {
544 public void actionPerformed(ActionEvent e) {
545 sourceAndTarget.setHierarchyAware(hierarchyAware.isSelected());
546 updateEdgeView();
547 }
548 });
549
550 final Box settings = Box.createVerticalBox();
551 settings.add(hierarchyAware);
552 settings.add(Box.createGlue());
553 return settings;
554 }
555
556
562 private JComponent createEdgeGroupSettings() {
563 final JCheckBox src = new JCheckBox("Source");
564 src.setSelected(true);
565 final JCheckBox tgt = new JCheckBox("Target");
566 tgt.setSelected(true);
567 final AbstractAction groupTypes = new AbstractAction() {
568 public void actionPerformed( final ActionEvent e ) {
569 src.setEnabled(tgt.isSelected());
570 tgt.setEnabled(src.isSelected());
571 byte types = 0;
572 if (src.isSelected()) {
573 types |= EdgeGroup.GROUP_BY_SOURCE;
574 }
575 if (tgt.isSelected()) {
576 types |= EdgeGroup.GROUP_BY_TARGET;
577 }
578 edgeGroup.setGroupByPolicy(types);
579 updateEdgeView();
580 }
581 };
582 src.addActionListener(groupTypes);
583 tgt.addActionListener(groupTypes);
584
585 final Box settings = Box.createVerticalBox();
586 settings.add(new JLabel("Group by"));
587 settings.add(src);
588 settings.add(tgt);
589 settings.add(Box.createGlue());
590 return settings;
591 }
592
593
599 private JComponent createFolderContentsSettings() {
600 final ButtonGroup includeFoldersGroup = new ButtonGroup();
601 final JRadioButton always = new JRadioButton("Always Include Folders");
602 always.addActionListener(new ActionListener() {
603 public void actionPerformed( final ActionEvent e ) {
604 folderContents.setFolderPolicy(FolderContents.FOLDER_POLICY_ALWAYS);
605 updateNodeView();
606 }
607 });
608 includeFoldersGroup.add(always);
609 final JRadioButton asNeeeded = new JRadioButton("Include Folders As Needed");
610 asNeeeded.setSelected(true);
611 asNeeeded.addActionListener(new ActionListener() {
612 public void actionPerformed( final ActionEvent e ) {
613 folderContents.setFolderPolicy(FolderContents.FOLDER_POLICY_AS_NEEDED);
614 updateNodeView();
615 }
616 });
617 includeFoldersGroup.add(asNeeeded);
618 final JRadioButton never = new JRadioButton("Never Include Folders");
619 never.addActionListener(new ActionListener() {
620 public void actionPerformed( final ActionEvent e ) {
621 folderContents.setFolderPolicy(FolderContents.FOLDER_POLICY_NEVER);
622 updateNodeView();
623 }
624 });
625 includeFoldersGroup.add(never);
626
627 final Box settings = Box.createVerticalBox();
628 settings.add(always);
629 settings.add(asNeeeded);
630 settings.add(never);
631 settings.add(Box.createGlue());
632 return settings;
633 }
634
635
641 private JComponent createAncestorGroupsSettings() {
642 final JCheckBox includeFocusNodes = new JCheckBox("Include Focus Nodes");
643 includeFocusNodes.setSelected(ancestorGroups.isIncludeFocusNodes());
644 includeFocusNodes.addActionListener(new AbstractAction() {
645 public void actionPerformed( final ActionEvent e ) {
646 ancestorGroups.setIncludeFocusNodes(includeFocusNodes.isSelected());
647 updateNodeView();
648 }
649 });
650
651 final Box settings = Box.createVerticalBox();
652 settings.add(includeFocusNodes);
653 settings.add(Box.createGlue());
654 return settings;
655 }
656
657
663 private JComponent createCommonParentGroupSettings() {
664 final JCheckBox includeDescendants = new JCheckBox("Include Descendants");
665 includeDescendants.setSelected(commonParentGroup.isIncludeDescendants());
666 includeDescendants.addActionListener(new AbstractAction() {
667 public void actionPerformed( final ActionEvent e ) {
668 commonParentGroup.setIncludeDescendants(includeDescendants.isSelected());
669 updateNodeView();
670 }
671 });
672
673 final Box settings = Box.createVerticalBox();
674 settings.add(includeDescendants);
675 settings.add(Box.createGlue());
676 return settings;
677 }
678
679
685 private JComponent createNeighborhoodSettings() {
686 final ButtonGroup nodesGroup = new ButtonGroup();
687 final JRadioButton preds = new JRadioButton("Predecessors");
688 preds.addActionListener(new ActionListener() {
689 public void actionPerformed( final ActionEvent e ) {
690 neighborhood.setNeighborhoodType(Neighborhood.NEIGHBORHOOD_TYPE_PREDECESSORS);
691 updateNodeView();
692 }
693 });
694 nodesGroup.add(preds);
695 final JRadioButton succs = new JRadioButton("Successors");
696 succs.addActionListener(new ActionListener() {
697 public void actionPerformed( final ActionEvent e ) {
698 neighborhood.setNeighborhoodType(Neighborhood.NEIGHBORHOOD_TYPE_SUCCESSORS);
699 updateNodeView();
700 }
701 });
702 nodesGroup.add(succs);
703 final JRadioButton predsSuccs = new JRadioButton("Predecessors and Successors");
704 predsSuccs.setSelected(true);
705 predsSuccs.addActionListener(new ActionListener() {
706 public void actionPerformed( final ActionEvent e ) {
707 neighborhood.setNeighborhoodType(Neighborhood.NEIGHBORHOOD_TYPE_PREDECESSORS_AND_SUCCESSORS);
708 updateNodeView();
709 }
710 });
711 nodesGroup.add(predsSuccs);
712 final JRadioButton neighbors = new JRadioButton("All Neighbors");
713 neighbors.addActionListener(new ActionListener() {
714 public void actionPerformed( final ActionEvent e ) {
715 neighborhood.setNeighborhoodType(Neighborhood.NEIGHBORHOOD_TYPE_NEIGHBORS);
716 updateNodeView();
717 }
718 });
719 nodesGroup.add(neighbors);
720
721 final JSpinner neighborhoodMGD = new JSpinner();
722 neighborhoodMGD.getModel().setValue(new Integer(neighborhood.getMaximumGraphDistance()));
723 ((SpinnerNumberModel) neighborhoodMGD.getModel()).setMinimum(new Integer(0));
724 neighborhoodMGD.addChangeListener(new ChangeListener() {
725 public void stateChanged( final ChangeEvent e ) {
726 final Object value = neighborhoodMGD.getModel().getValue();
727 if (value instanceof Integer) {
728 final int mgd = ((Integer) value).intValue();
729 if (mgd > -1) {
730 neighborhood.setMaximumGraphDistance(mgd);
731 updateNodeView();
732 }
733 }
734 }
735 });
736
737 final JCheckBox hierarchyAware = new JCheckBox("Hierarchy aware");
738 hierarchyAware.addActionListener(new ActionListener() {
739 public void actionPerformed(ActionEvent e) {
740 neighborhood.setHierarchyAware(hierarchyAware.isSelected());
741 updateNodeView();
742 }
743 });
744
745 final ButtonGroup edgesGroup = new ButtonGroup();
746 final JRadioButton none = new JRadioButton("None");
747 none.addActionListener(new ActionListener() {
748 public void actionPerformed( final ActionEvent e ) {
749 neighborhood.setEdgePolicy(Neighborhood.EDGE_POLICY_NONE);
750 updateNodeView();
751 }
752 });
753 edgesGroup.add(none);
754 final JRadioButton subgraph = new JRadioButton("Subgraph Edges");
755 subgraph.addActionListener(new ActionListener() {
756 public void actionPerformed( final ActionEvent e ) {
757 neighborhood.setEdgePolicy(Neighborhood.EDGE_POLICY_INDUCED_SUBGRAPH);
758 updateNodeView();
759 }
760 });
761 edgesGroup.add(subgraph);
762 final JRadioButton shortestPaths = new JRadioButton("Shortest Paths");
763 shortestPaths.setSelected(true);
764 shortestPaths.addActionListener(new ActionListener() {
765 public void actionPerformed( final ActionEvent e ) {
766 neighborhood.setEdgePolicy(Neighborhood.EDGE_POLICY_SHORTEST_PATHS);
767 updateNodeView();
768 }
769 });
770 edgesGroup.add(shortestPaths);
771
772
773 final Box nodeTypes = Box.createVerticalBox();
774 nodeTypes.add(preds);
775 nodeTypes.add(succs);
776 nodeTypes.add(predsSuccs);
777 nodeTypes.add(neighbors);
778
779 final GridBagConstraints gbc = new GridBagConstraints();
780 final JPanel includedNodes = new JPanel(new GridBagLayout());
781 includedNodes.setBorder(BorderFactory.createTitledBorder("Included Nodes"));
782 gbc.anchor = GridBagConstraints.NORTHWEST;
783 gbc.fill = GridBagConstraints.HORIZONTAL;
784 gbc.gridx = 0;
785 gbc.gridy = 0;
786 gbc.gridwidth = 2;
787 gbc.gridheight = 1;
788 gbc.weightx = 1;
789 gbc.weighty = 0;
790 includedNodes.add(nodeTypes, gbc);
791 gbc.fill = GridBagConstraints.NONE;
792 gbc.gridy = 1;
793 gbc.gridwidth = 1;
794 gbc.insets = new Insets(5, 0, 0, 0);
795 gbc.weightx = 0;
796 includedNodes.add(new JLabel("Maximum Graph Distance"), gbc);
797 gbc.fill = GridBagConstraints.HORIZONTAL;
798 gbc.gridx = 1;
799 gbc.insets = new Insets(5, 5, 0, 0);
800 gbc.weightx = 1;
801 includedNodes.add(neighborhoodMGD, gbc);
802 gbc.gridwidth = 2;
803 gbc.gridx = 0;
804 gbc.gridy = 2;
805 gbc.insets = new Insets(0, 0, 5, 0);
806 includedNodes.add(hierarchyAware, gbc);
807
808 final Box includedEdges = Box.createVerticalBox();
809 includedEdges.setBorder(BorderFactory.createTitledBorder("Included Edges"));
810 includedEdges.add(none);
811 includedEdges.add(subgraph);
812 includedEdges.add(shortestPaths);
813
814 final JPanel controls = new JPanel(new GridBagLayout());
815 gbc.gridx = 0;
816 gbc.gridy = 0;
817 gbc.gridwidth = 1;
818 gbc.gridheight = 1;
819 gbc.weightx = 1;
820 gbc.weighty = 0;
821 controls.add(includedNodes, gbc);
822 gbc.gridy = 1;
823 controls.add(includedEdges, gbc);
824
825 final JPanel settings = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
826 settings.add(controls);
827 return settings;
828 }
829
830
836 private JComponent createTriggerPane() {
837 final ButtonGroup updateGroup = new ButtonGroup();
838 final JRadioButton updateHover = new JRadioButton(new AbstractAction("Mouse Hover") {
839 public void actionPerformed( final ActionEvent e ) {
840 setTrigger(HOVER_TRIGGER);
841 }
842 });
843 updateGroup.add(updateHover);
844 final JRadioButton updateSelection = new JRadioButton(new AbstractAction("Selection Change") {
845 public void actionPerformed( final ActionEvent e ) {
846 setTrigger(SELECTION_TRIGGER);
847 }
848 });
849 updateSelection.setSelected(true);
850 updateGroup.add(updateSelection);
851
852 final Box updatePane = Box.createHorizontalBox();
853 updatePane.add(Box.createHorizontalStrut(5));
854 updatePane.add(new JLabel("Update Trigger: "));
855 updatePane.add(updateHover);
856 updatePane.add(updateSelection);
857 updatePane.add(Box.createGlue());
858 return updatePane;
859 }
860
861
870 private void addStrategy(
871 final JPanel settingsPane,
872 final Box strategyButtons,
873 final ButtonGroup strategiesGroup,
874 final String title,
875 JComponent settings,
876 final AbstractLocalViewCreator lvc,
877 final boolean nodeBased
878 ) {
879 if (settings == null) {
880 settings = new JPanel();
881 settings.add(new JLabel("No Settings"));
882 }
883 final JRadioButton strategyButton = new JRadioButton(new AbstractAction(title) {
884 public void actionPerformed(ActionEvent e) {
885 ((CardLayout) settingsPane.getLayout()).show(settingsPane, title);
886 if (nodeBased) {
887 setNodeLocalViewCreator(lvc);
888 } else {
889 setEdgeLocalViewCreator(lvc);
890 }
891 }
892 });
893
894 final CompoundBorder border = BorderFactory.createCompoundBorder(
895 BorderFactory.createTitledBorder(title + " Settings"),
896 BorderFactory.createEmptyBorder(5, 5, 5, 5));
897 settings.setBorder(border);
898 settingsPane.add(settings, title);
899
900 strategiesGroup.add(strategyButton);
901 if (strategiesGroup.getButtonCount() == 1) {
902 strategiesGroup.setSelected(strategyButton.getModel(), true);
903 }
904 strategyButtons.add(strategyButton);
905 }
906
907
913 private Layouter createLayouter() {
914 final IncrementalHierarchicLayouter layouter = new IncrementalHierarchicLayouter();
918 layouter.setLayoutOrientation(LayoutOrientation.BOTTOM_TO_TOP);
919
920 final EdgeLayoutDescriptor eld = layouter.getEdgeLayoutDescriptor();
923 eld.setOrthogonallyRouted(true);
924 eld.setMinimumFirstSegmentLength(25);
925 eld.setMinimumLength(35);
926 return layouter;
927 }
928
929 public static void main( String[] args ) {
930 EventQueue.invokeLater(new Runnable() {
931 public void run() {
932 Locale.setDefault(Locale.ENGLISH);
933 initLnF();
934 (new LocalViewDemo("resource/localviewhelp.html")).start();
935 }
936 });
937 }
938
939
943 private final class SelectionTrigger implements Graph2DSelectionListener {
944 private final Timer timer;
945 private Graph2DSelectionEvent lastEvent;
946
947 SelectionTrigger() {
948 timer = new Timer(TIMER_DELAY, new ActionListener() {
949 public void actionPerformed( final ActionEvent e ) {
950 if (lastEvent != null) {
951 handleEvent(lastEvent);
952 }
953 }
954
955
958 private void handleEvent( final Graph2DSelectionEvent e ) {
959 if (e.isNodeSelection()) {
960 createNodeView(e.getGraph2D().selectedNodes());
961 } else if (e.isEdgeSelection()) {
962 createEdgeView(e.getGraph2D().selectedEdges());
963 }
964 }
965 });
966 timer.setRepeats(false);
967 }
968
969 public void onGraph2DSelectionEvent( final Graph2DSelectionEvent e ) {
970 if (e.getGraph2D() == getCurrentLocalViewCreator().getModel()) {
971 if (e.isNodeSelection() || e.isEdgeSelection()) {
972 lastEvent = e;
973 timer.restart();
974 }
975 }
976 }
977 }
978
979
983 private final class HoverTrigger extends ViewMode {
984 private final Timer timer;
985 private YPoint lastPosition;
986
987 private HoverTrigger() {
988 timer = new Timer(TIMER_DELAY, new ActionListener() {
989 public void actionPerformed( ActionEvent e) {
990 if (lastPosition != null) {
991 handleHit(getHitInfo(lastPosition.x, lastPosition.y));
992 }
993 }
994
995
998 private void handleHit( final HitInfo hitInfo ) {
999 if (hitInfo.hasHitNodes()) {
1000 createNodeView(hitInfo.hitNodes());
1001 } else if (hitInfo.hasHitEdges()) {
1002 createEdgeView(hitInfo.hitEdges());
1003 }
1004 }
1005 });
1006 timer.setRepeats(false);
1007 }
1008
1009 public void mouseMoved(double x, double y) {
1010 super.mouseMoved(x, y);
1011 this.lastPosition = new YPoint(x, y);
1012 timer.restart();
1013 }
1014 }
1015
1016
1022 private static final class SelectedSubgraph extends AbstractLocalViewCreator {
1023 private final Graph2D model;
1024 private final GraphCopier.CopyFactory factory;
1025 private final Graph2D view;
1026
1027
1038 SelectedSubgraph(
1039 final Graph2D model,
1040 final GraphCopier.CopyFactory factory,
1041 final Graph2D view
1042 ) {
1043 super(AbstractLocalViewCreator.ELEMENT_TYPE_NODE);
1044 this.model = model;
1045 this.factory = factory;
1046 this.view = view;
1047
1048 final ModelViewManager mvm = ModelViewManager.getInstance(model);
1051 if (!mvm.isViewGraph(view)) {
1052 mvm.addViewGraph(view, null, false, false);
1053 mvm.setCopyFactory(view, factory);
1054 }
1055 }
1056
1057
1061 public Graph2D getModel() {
1062 return model;
1063 }
1064
1065
1069 public Graph2D getViewGraph() {
1070 return view;
1071 }
1072
1073
1080 public Node getModelNode( final Node view ) {
1081 return getManager().getModelNode(view);
1082 }
1083
1084
1093 public Node getViewNode( final Node model ) {
1094 return getManager().getViewNode(model, getViewGraph());
1095 }
1096
1097
1104 public Edge getModelEdge( final Edge view ) {
1105 return getManager().getModelEdge(view);
1106 }
1107
1108
1117 public Edge getViewEdge( final Edge model ) {
1118 return getManager().getViewEdge(model, getViewGraph());
1119 }
1120
1121
1127 protected Layouter createDefaultLayouter() {
1128 return null;
1129 }
1130
1131
1134 protected void buildViewGraph() {
1135 final Graph2D model = getModel();
1136 if (!model.isSelectionEmpty()) {
1137 final HashSet nodes = new HashSet();
1138 final HashSet edges = new HashSet();
1139
1140 for (Iterator it = focusNodes(); it.hasNext();) {
1142 final Node node = (Node) it.next();
1143 if (model.isSelected(node)) {
1144 nodes.add(node);
1145 }
1146 }
1147
1148 for (EdgeCursor ec = model.edges(); ec.ok(); ec.next()) {
1150 final Edge edge = ec.edge();
1151 if (nodes.contains(edge.source()) && nodes.contains(edge.target())) {
1152 edges.add(edge);
1153 }
1154 }
1155
1156 final Graph2D view = getViewGraph();
1158 final ModelViewManager mvm = getManager();
1159
1160 final GraphCopier.CopyFactory oldFactory = mvm.getCopyFactory(view);
1165 if (oldFactory != factory) {
1166 mvm.setCopyFactory(view, factory);
1167 }
1168 try {
1169 mvm.synchronizeModelToViewGraph(
1170 (new NodeList(nodes.iterator())).nodes(),
1171 (new EdgeList(edges.iterator())).edges(),
1172 view);
1173 } finally {
1174 if (oldFactory != factory) {
1176 mvm.setCopyFactory(view, oldFactory);
1177 }
1178 }
1179 }
1180 }
1181
1182 private ModelViewManager getManager() {
1183 return ModelViewManager.getInstance(getModel());
1184 }
1185 }
1186}
1187