$darkmode
DENOPTIM
GraphViewerPanel.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2020 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.gui;
20
21import java.awt.BasicStroke;
22import java.awt.BorderLayout;
23import java.awt.Color;
24import java.awt.Component;
25import java.awt.Dimension;
26import java.awt.Font;
27import java.awt.Paint;
28import java.awt.Shape;
29import java.awt.Stroke;
30import java.awt.event.ActionEvent;
31import java.awt.event.ActionListener;
32import java.awt.event.MouseEvent;
33import java.awt.geom.Ellipse2D;
34import java.awt.geom.Point2D;
35import java.awt.geom.RoundRectangle2D;
36import java.util.ArrayList;
37import java.util.HashMap;
38import java.util.HashSet;
39import java.util.List;
40import java.util.Map;
41import java.util.Set;
42import java.util.concurrent.ExecutionException;
43
44import javax.swing.JMenuItem;
45import javax.swing.JPanel;
46import javax.swing.JPopupMenu;
47import javax.swing.JSeparator;
48
49import com.google.common.base.Function;
50
51import denoptim.graph.APClass;
52import denoptim.graph.AttachmentPoint;
53import denoptim.graph.DGraph;
54import denoptim.graph.Edge;
55import denoptim.graph.Ring;
56import denoptim.graph.Template;
57import denoptim.graph.Vertex;
58import edu.uci.ics.jung.graph.SparseMultigraph;
59import edu.uci.ics.jung.graph.util.EdgeType;
60import edu.uci.ics.jung.visualization.Layer;
61import edu.uci.ics.jung.visualization.VisualizationViewer;
62import edu.uci.ics.jung.visualization.control.AbstractPopupGraphMousePlugin;
63import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
64import edu.uci.ics.jung.visualization.control.GraphMouseListener;
65import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
66import edu.uci.ics.jung.visualization.decorators.EdgeShape;
67import edu.uci.ics.jung.visualization.picking.PickedInfo;
68import edu.uci.ics.jung.visualization.renderers.BasicEdgeArrowRenderingSupport;
69import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;
70
71
77public class GraphViewerPanel extends JPanel
78{
82 private static final long serialVersionUID = 2L;
83
84 edu.uci.ics.jung.graph.Graph<JVertex, JEdge> loadedGraph;
86 private double scaling = 1.0;
87 VisualizationViewer<JVertex, JEdge> viewer;
88 private DefaultModalGraphMouse<JVertex, JEdge> gm;
89
90 public enum LabelType {APC, BT, BBID, APID};
91
92 public enum JVertexType {SCAF, FRAG, CAP, RCV, AP, NONE};
93
94 // Properties fired by this class and intercepted in parent containers
95 public static final String PROPERTYNODECLICKED = "NODECLICKED";
96 public static final String PROPERTYMOUSEMODE = "SETMOUSEMODE";
97
98//------------------------------------------------------------------------------
99
104 public class JVertex
105 {
110
116
122
126 String label = "NA";
127
132 String idStr = "NA";
133
137 boolean displayBBID = false;
138
143 boolean expandable = false;
144
150
159 this.ap = ap;
160 idStr = Long.toString(ap.getOwner().getVertexId())
161 + Integer.toString(ap.getID());
162 //NB: in the GUI (like in the SDF files) we use 1-based indexing
163 label = Integer.toString(ap.getIndexInOwner()+1);
165 }
166
171 public JVertex(Vertex v) {
172 this.dnpVertex = v;
173 this.expandable = true;
174 idStr = Long.toString(v.getVertexId());
175 label = Long.toString(v.getVertexId());
176 switch (v.getBuildingBlockType())
177 {
178 case SCAFFOLD:
180 break;
181 case FRAGMENT:
183 break;
184 case CAP:
186 break;
187 default:
189 break;
190 }
191 if (v.isRCV())
193 }
194 }
195
196//------------------------------------------------------------------------------
197
203 public class JEdge
204 {
210 String id = "";
211
216 String srcAPC;
217
222 String trgAPC;
223
229 String srcAPID = "";
230
236 String trgAPID = "";
237
243 String bt = "none";
244
249 boolean toAp = false;
250
254 boolean displayAPCs = false;
255
259 boolean displayAPIDs = false;
260
264 boolean displayBndTyp = false;
265
272 public JEdge(AttachmentPoint srcAP)
273 {
274 this.id = srcAP.getOwner().getVertexId()+"_"+srcAP.getIndexInOwner();
275 if (srcAP.getAPClass() != null)
276 this.srcAPC = srcAP.getAPClass().toString();
277 else
278 this.srcAPC = "null";
279 this.trgAPC = "none";
280 this.bt = "none";
281 }
282
293 public JEdge(AttachmentPoint srcAP,
294 AttachmentPoint trgAP, String bt)
295 {
296 this.id = srcAP.getOwner().getVertexId()
297 + "-"
298 + trgAP.getOwner().getVertexId();
299 if (srcAP.getAPClass() != null)
300 this.srcAPC = srcAP.getAPClass().toString();
301 else
302 this.srcAPC = "null";
303 if (trgAP.getAPClass() != null)
304 this.trgAPC = trgAP.getAPClass().toString();
305 else
306 this.trgAPC = "null";
307 //NB: in GUI as well as in SDF files APs have 1-based index!
308 this.srcAPID = "AP" + (srcAP.getIndexInOwner()+1);
309 this.trgAPID = "AP" + (trgAP.getIndexInOwner()+1);
310 this.bt = bt;
311 }
312 }
313
314//-----------------------------------------------------------------------------
315
320 {
321 super();
322 initialize();
323 }
324
325//-----------------------------------------------------------------------------
326
330 private void initialize()
331 {
332 this.setLayout(new BorderLayout());
333 this.setBackground(Color.decode("#D9D9D9"));
334 this.setToolTipText("No graph to visualize");
335 }
336
337//-----------------------------------------------------------------------------
338
342 public void cleanup()
343 {
344 if (viewer != null)
345 {
346 viewer.removeAll();
347 }
348 for (Component c : this.getComponents())
349 {
350 this.remove(c);
351 }
352 this.repaint();
353 this.revalidate();
354 }
355
356//-----------------------------------------------------------------------------
357
362 public void loadGraphToViewer(DGraph dnGraph)
363 {
365 }
366
367//-----------------------------------------------------------------------------
368
374 public void loadGraphToViewer(Template tmpl)
375 {
376 edu.uci.ics.jung.graph.Graph<JVertex, JEdge> graph = convertDnGraphToGSGraph(
377 tmpl.getInnerGraph(), tmpl);
378 loadGraphToViewer(graph,null);
379 }
380
381//-----------------------------------------------------------------------------
382
390 public void loadGraphToViewer(DGraph dnGraph,
391 JUNGGraphSnapshot prevStatus)
392 {
393 loadGraphToViewer(convertDnGraphToGSGraph(dnGraph),prevStatus);
394 }
395
396//-----------------------------------------------------------------------------
397
404 public edu.uci.ics.jung.graph.Graph<JVertex, JEdge> convertDnGraphToGSGraph(
405 DGraph dnG)
406 {
407 return convertDnGraphToGSGraph(dnG, null);
408 }
409
410//-----------------------------------------------------------------------------
411
424 public edu.uci.ics.jung.graph.Graph<JVertex, JEdge> convertDnGraphToGSGraph(
425 DGraph dnpGraph, Template tmpl)
426 {
427 edu.uci.ics.jung.graph.Graph<JVertex, JEdge> g = new SparseMultigraph<>();
428 Map<Vertex, JVertex> vMap = new HashMap<Vertex,JVertex>();
429 for (Vertex v : dnpGraph.getVertexList())
430 {
431 JVertex jv = new JVertex(v);
432 vMap.put(v, jv);
433 g.addVertex(jv);
434
435 for (AttachmentPoint ap : v.getAttachmentPoints())
436 {
437 if (ap.isAvailableThroughout())
438 {
439 JVertex vap = new JVertex(ap);
440 g.addVertex(vap);
441 JEdge e = new JEdge(ap);
442 e.toAp = true;
443 g.addEdge(e, vMap.get(v), vap, EdgeType.DIRECTED);
444 vap.edgeToParent = e;
445 }
446 }
447 }
448 for (Edge e : dnpGraph.getEdgeList())
449 {
450 g.addEdge(new JEdge(e.getSrcAP(),
451 e.getTrgAP(),
452 e.getBondType().toString()),
453 vMap.get(e.getSrcAP().getOwner()),
454 vMap.get(e.getTrgAP().getOwner()), EdgeType.DIRECTED);
455 }
456 for (Ring r : dnpGraph.getRings())
457 {
458 g.addEdge(new JEdge(
459 r.getHeadVertex().getEdgeToParent().getSrcAP(),
460 r.getTailVertex().getEdgeToParent().getSrcAP(),
461 r.getBondType().toString()),
462 vMap.get(r.getHeadVertex()),
463 vMap.get(r.getTailVertex()), EdgeType.UNDIRECTED);
464 vMap.get(r.getHeadVertex()).vtype = JVertexType.RCV;
465 vMap.get(r.getTailVertex()).vtype = JVertexType.RCV;
466 }
467
468 if (tmpl != null)
469 {
470 renumberAPs(tmpl, g);
471 }
472 return g;
473 }
474
475//-----------------------------------------------------------------------------
476
477 private static void renumberAPs(Template tmpl,
478 edu.uci.ics.jung.graph.Graph<JVertex, JEdge> graph)
479 {
480 for (int i=0; i<tmpl.getAttachmentPoints().size(); i++)
481 {
482 AttachmentPoint outAP = tmpl.getAttachmentPoints().get(i);
483 AttachmentPoint inAP = tmpl.getInnerAPFromOuterAP(outAP);
484 for (JVertex v : graph.getVertices())
485 {
486 if (v.vtype == JVertexType.AP)
487 {
488 if (v.ap == inAP)
489 {
490 v.label = Integer.toString(i+1);
491 break;
492 }
493 }
494 }
495 }
496 }
497
498//-----------------------------------------------------------------------------
499
504 public void loadGraphToViewer(edu.uci.ics.jung.graph.Graph<JVertex, JEdge> g)
505 {
506 loadGraphToViewer(g,null);
507 }
508
509//-----------------------------------------------------------------------------
510
518 public void loadGraphToViewer(edu.uci.ics.jung.graph.Graph<JVertex, JEdge> g,
519 JUNGGraphSnapshot prevStatus)
520 {
521 loadGraphToViewer(g, prevStatus, true);
522 }
523
524//-----------------------------------------------------------------------------
525
534 public void loadGraphToViewer(edu.uci.ics.jung.graph.Graph<JVertex, JEdge> g,
535 JUNGGraphSnapshot prevStatus, boolean lock)
536 {
537 loadGraphToViewer(g, prevStatus, lock, 1.0);
538 }
539//-----------------------------------------------------------------------------
540
552 public void loadGraphToViewer(edu.uci.ics.jung.graph.Graph<JVertex, JEdge> g,
553 JUNGGraphSnapshot prevStatus, boolean lock, double reScaling)
554 {
555 loadedGraph = g;
556 scaling = scaling * reScaling;
557 layout = new DNPSpringLayout<>(g);
558
559 //NB: the size depends on where this panel is used. In GUIVertexSelector
560 // the size vanishes, so we need to set a decent value or the graph will
561 // be displayed with 0:0 dimensions, i.e., all nodes on top of each other
562 Dimension dimLayout = null;
563 Dimension dimViewer = null;
564 if (this.getSize().height<150)
565 {
566 dimLayout = new Dimension(150, 150);
567 layout.setSize(dimLayout);
568 dimViewer = new Dimension(150, 150);
569 } else {
570 double w = this.getSize().width * scaling
571 - GUIPreferences.graphNodeSize * 1.5;
572 double h = this.getSize().height * scaling
573 - GUIPreferences.graphNodeSize * 1.5;
574 dimLayout = new Dimension((int) w, (int) h);
575 layout.setSize(dimLayout);
576 dimViewer = this.getSize();
577 }
578
579 // Unless we have a snapshot from previous visualization, generate the
580 // initial layout of nodes with ISOM layout
581 if (prevStatus != null)
582 {
583 // Here we set view features according to a previous graph view
584 inheritFeatures(prevStatus, lock);
585 }
586
587 viewer = new VisualizationViewer<>(layout,dimViewer);
588
589 // Listener for clicks on the graph nodes
590 viewer.addGraphMouseListener(new GraphMouseListener<JVertex>() {
591
592 @Override
593 public void graphReleased(JVertex v, MouseEvent me)
594 {}
595
596 @Override
597 public void graphPressed(JVertex v, MouseEvent me)
598 {}
599
600 @Override
601 public void graphClicked(JVertex v, MouseEvent me)
602 {
603 if (v.expandable)
604 {
605 firePropertyChange(PROPERTYNODECLICKED, null, v);
606 } else {
607 firePropertyChange(PROPERTYNODECLICKED, null, null);
608 }
609 }
610 });
611 viewer.getRenderer().getVertexLabelRenderer().setPosition(
612 Position.CNTR);
613 viewer.getRenderContext().setVertexShapeTransformer(
615 viewer.getRenderContext().setVertexFillPaintTransformer(
616 new VertexFillPaintTransformer(viewer.getPickedVertexState()));
617 viewer.getRenderContext().setVertexLabelTransformer(
619 viewer.getRenderContext().setVertexFontTransformer(
620 new Function<JVertex, Font>(){
621 @Override
622 public Font apply(JVertex v) {
623 return new Font("Helvetica", Font.PLAIN,
625 }
626 });
627
628 viewer.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(g));
629 viewer.getRenderContext().setEdgeStrokeTransformer(
631 viewer.getRenderContext().setEdgeDrawPaintTransformer(
633 viewer.getRenderContext().setArrowFillPaintTransformer(
635 viewer.getRenderContext().setArrowDrawPaintTransformer(
637 viewer.getRenderer().getEdgeRenderer().setEdgeArrowRenderingSupport(
638 new BasicEdgeArrowRenderingSupport<JVertex, JEdge>());
639 viewer.getRenderContext().setEdgeLabelTransformer(
641 viewer.getRenderContext().setEdgeFontTransformer(
642 new Function<JEdge, Font>(){
643 @Override
644 public Font apply(JEdge e) {
645 return new Font("Helvetica", Font.PLAIN,
647 }
648 });
649
650 gm = new DefaultModalGraphMouse<JVertex, JEdge> ();
651 gm.setMode(ModalGraphMouse.Mode.PICKING);
652 gm.add(new PopupGraphMousePlugin());
653 viewer.setGraphMouse(gm);
654 viewer.addKeyListener(gm.getModeKeyListener());
655 this.add(viewer);
656
658 }
659
660//-----------------------------------------------------------------------------
661
667 {
668 firePropertyChange(PROPERTYMOUSEMODE, null, i);
669 }
670
671//-----------------------------------------------------------------------------
672
673 public void centerGraphLayout()
674 {
675 Point2D centerGraph = getLayoutCenter();
676 Point2D centerViewer = viewer.getRenderContext()
677 .getMultiLayerTransformer()
678 .inverseTransform(Layer.LAYOUT, viewer.getCenter());
679 viewer.getRenderContext().getMultiLayerTransformer()
680 .getTransformer(Layer.LAYOUT).translate(
681 -(centerGraph.getX() - centerViewer.getX()),
682 -(centerGraph.getY() - centerViewer.getY()));
683 }
684
685//-----------------------------------------------------------------------------
686
687 private Point2D getLayoutCenter()
688 {
689 double minX = Double.MAX_VALUE;
690 double minY = Double.MAX_VALUE;
691 double maxX = -Double.MAX_VALUE;
692 double maxY = -Double.MAX_VALUE;
693 for (JVertex v : loadedGraph.getVertices())
694 {
695 try
696 {
697 Point2D p = layout.getVertexPosition(v);
698 if (p.getX() < minX)
699 minX = p.getX();
700 if (p.getY() < minY)
701 minY = p.getY();
702 if (p.getX() > maxX)
703 maxX = p.getX();
704 if (p.getY() > maxY)
705 maxY = p.getY();
706 } catch (ExecutionException e)
707 {
708 //ignore it
709 }
710 }
711 return new Point2D.Double(minX + (maxX-minX)/2.0,
712 minY + (maxY-minY)/2.0);
713 }
714
715//-----------------------------------------------------------------------------
716
717 private class PopupGraphMousePlugin extends AbstractPopupGraphMousePlugin
718 {
719
720 @Override
721 protected void handlePopup(MouseEvent e)
722 {
723 GraphOptsPopup popup = new GraphOptsPopup();
724 popup.show((Component) e.getSource(), e.getX(), e.getY());
725 }
726 }
727
728//-----------------------------------------------------------------------------
729
730 @SuppressWarnings("serial")
731 private class GraphOptsPopup extends JPopupMenu
732 {
733 public GraphOptsPopup() {
734 super();
735
736 JMenuItem mnuRelax = new JMenuItem("Refine node locations");
737 mnuRelax.setToolTipText(String.format("<html><body width='%1s'>"
738 + "Relaxe the position of graph nodes as to avoid node "
739 + "overlap. Depending on the complexity of the graph, you "
740 + "might consider moving specific portions of the graph "
741 + "before attempting any refinement, or consider tunning "
742 + "this refinement multiple times</html>", 300));
743 mnuRelax.addActionListener(new ActionListener() {
744 public void actionPerformed(ActionEvent e) {
746 cleanup();
747 loadGraphToViewer(loadedGraph,snpSht,false);
748 }});
749 this.add(mnuRelax);
750
751 this.add(new JSeparator());
752
753 JMenuItem mnuShrink = new JMenuItem("Shrink Plottable Area");
754 mnuShrink.setToolTipText(String.format("<html><body width='%1s'>"
755 + "Re-plot the graph using a shrinked plottable region."
756 + "This will force nosed to fit into a smaller space."
757 + "</html>", 300));
758 mnuShrink.addActionListener(new ActionListener() {
759 public void actionPerformed(ActionEvent e) {
761 cleanup();
762 loadGraphToViewer(loadedGraph,snpSht,false,0.75);
763 }});
764 this.add(mnuShrink);
765
766 JMenuItem mnuEnlarge = new JMenuItem("Enlarge Plottable Area");
767 mnuEnlarge.setToolTipText(String.format("<html><body width='%1s'>"
768 + "Re-plot the graph using an enlarged plottable region."
769 + "This will allow nodes to be places farther apart."
770 + "</html>", 300));
771 mnuEnlarge.addActionListener(new ActionListener() {
772 public void actionPerformed(ActionEvent e) {
774 cleanup();
775 loadGraphToViewer(loadedGraph,snpSht,false,1.25);
776 }});
777 this.add(mnuEnlarge);
778
779 this.add(new JSeparator());
780
781 JMenuItem mnuCenterView = new JMenuItem("Center View");
782 mnuCenterView.setToolTipText(String.format(
783 "<html><body width='%1s'>"
784 + "Center the graph to the vindow.</html>", 300));
785 mnuCenterView.addActionListener(new ActionListener() {
786 public void actionPerformed(ActionEvent e) {
788 }
789 });
790 this.add(mnuCenterView);
791
792 JMenuItem mnuMoveMode = new JMenuItem("Mouse mode: move");
793 mnuMoveMode.setToolTipText(String.format(
794 "<html><body width='%1s'>"
795 + "Makes mouse move the graph view.</html>", 300));
796 mnuMoveMode.addActionListener(new ActionListener() {
797 public void actionPerformed(ActionEvent e) {
799 }
800 });
801 this.add(mnuMoveMode);
802
803 JMenuItem mnuPickMode = new JMenuItem("Mouse mode: pick");
804 mnuPickMode.setToolTipText(String.format(
805 "<html><body width='%1s'>"
806 + "Makes the mouse select vertex on click.</html>", 300));
807 mnuPickMode.addActionListener(new ActionListener() {
808 public void actionPerformed(ActionEvent e) {
810 }
811 });
812 this.add(mnuPickMode);
813
814 this.add(new JSeparator());
815
816 JMenuItem mnuShowAPC = new JMenuItem("Show APClasses");
817 mnuShowAPC.setToolTipText(String.format("<html><body width='%1s'>"
818 + "Add labels with "
819 + "attachment point classes on edges and attachment points "
820 + "related to "
821 + "the selected nodes.</html>", 300));
822 mnuShowAPC.addActionListener(new ActionListener() {
823 public void actionPerformed(ActionEvent e) {
825 }});
826 this.add(mnuShowAPC);
827 JMenuItem mnuHideAPC = new JMenuItem("Hide APClasses");
828 mnuHideAPC.setToolTipText(String.format("<html><body width='%1s'>"
829 + "Remove labels with "
830 + "attachment point classes from edges "
831 + "and attachment points related to "
832 + "the selected nodes.</html>", 300));
833 mnuHideAPC.addActionListener(new ActionListener() {
834 public void actionPerformed(ActionEvent e) {
835 alterLabels(LabelType.APC, false);
836 }});
837 this.add(mnuHideAPC);
838
839 this.add(new JSeparator());
840
841 JMenuItem mnuShowAPID = new JMenuItem("Show AP IDs");
842 mnuShowAPID.setToolTipText(String.format("<html><body width='%1s'>"
843 + "Add labels declaring which attachment points are used "
844 + "to form an edge. Acts on any edge related to the "
845 + "selected nodes.</html>", 300));
846 mnuShowAPID.addActionListener(new ActionListener() {
847 public void actionPerformed(ActionEvent e) {
849 }});
850 this.add(mnuShowAPID);
851 JMenuItem mnuHideAPID = new JMenuItem("Hide AP IDs");
852 mnuHideAPID.setToolTipText(String.format("<html><body width='%1s'>"
853 + "Remove labales attachment point identifiers from the "
854 + "edges related to the selecgted nodes.</html>", 300));
855 mnuHideAPID.addActionListener(new ActionListener() {
856 public void actionPerformed(ActionEvent e) {
857 alterLabels(LabelType.APID, false);
858 }});
859 this.add(mnuHideAPID);
860
861 this.add(new JSeparator());
862
863 JMenuItem mnuShowBT = new JMenuItem("Show Bond Types");
864 mnuShowBT.setToolTipText(String.format("<html><body width='%1s'>"
865 + "Add labels defining the bond type on "
866 + "the edges related to the selected nodes."
867 + "</html>", 300));
868 mnuShowBT.addActionListener(new ActionListener() {
869 public void actionPerformed(ActionEvent e) {
870 alterLabels(LabelType.BT, true);
871 }});
872 this.add(mnuShowBT);
873 JMenuItem mnuHideBT = new JMenuItem("Hide Bond Types");
874 mnuHideBT.setToolTipText(String.format("<html><body width='%1s'>"
875 + "Remove labels defining the bond type from the edges"
876 + "related to the selected nodes.</html>", 300));
877 mnuHideBT.addActionListener(new ActionListener() {
878 public void actionPerformed(ActionEvent e) {
879 alterLabels(LabelType.BT, false);
880 }});
881 this.add(mnuHideBT);
882
883 this.add(new JSeparator());
884
885 JMenuItem mnuShowBBID = new JMenuItem("Show Building Block IDs");
886 mnuShowBBID.setToolTipText(String.format("<html><body width='%1s'>"
887 + "Add labels with "
888 + "building block IDs to the selected nodes.</html>", 300));
889 mnuShowBBID.addActionListener(new ActionListener() {
890 public void actionPerformed(ActionEvent e) {
892 }});
893 this.add(mnuShowBBID);
894 JMenuItem mnuHideBBID = new JMenuItem("Hide Building Block IDs");
895 mnuHideBBID.setToolTipText(String.format("<html><body width='%1s'>"
896 + "Hide building block IDs in the selected nodes."
897 + "</html>", 300));
898 mnuHideBBID.addActionListener(new ActionListener() {
899 public void actionPerformed(ActionEvent e) {
900 alterLabels(LabelType.BBID, false);
901 }});
902 this.add(mnuHideBBID);
903
904 this.add(new JSeparator());
905
906 JMenuItem mnuHideAll = new JMenuItem("Hide All Labels");
907 mnuHideAll.setToolTipText(String.format("<html><body width='%1s'>"
908 + "Hide all labels related to the selected nodes.</html>",
909 300));
910 mnuHideAll.addActionListener(new ActionListener() {
911 public void actionPerformed(ActionEvent e) {
912 for (LabelType lt : LabelType.values())
913 alterLabels(lt, false);
914 }});
915 this.add(mnuHideAll);
916 }
917 }
918
919//-----------------------------------------------------------------------------
920
921 public void setMouseMode(ModalGraphMouse.Mode mode)
922 {
923 if (gm != null)
924 gm.setMode(mode);
925 }
926
927//-----------------------------------------------------------------------------
928
929 private void inheritFeatures(JUNGGraphSnapshot prevStatus, boolean lock)
930 {
931 // Set labels on vertexes
932 ArrayList<String> lst = prevStatus.getVertexeIDsWithLabel(
934 for(JVertex jv : loadedGraph.getVertices())
935 {
936 if (lst.contains(jv.idStr))
937 {
938 jv.displayBBID = true;
939 }
940 }
941
942 // Set labels on edges
943 ArrayList<String> lstBT = prevStatus.getEdgeIDsWithLabel(LabelType.BT);
944 ArrayList<String> lstAPC = prevStatus.getEdgeIDsWithLabel(LabelType.APC);
945 ArrayList<String> lstAPID = prevStatus.getEdgeIDsWithLabel(
947 for(JEdge je : loadedGraph.getEdges())
948 {
949 if (lstBT.contains(je.id))
950 {
951 je.displayBndTyp = true;
952 }
953 if (lstAPC.contains(je.id))
954 {
955 je.displayAPCs = true;
956 }
957 if (lstAPID.contains(je.id))
958 {
959 je.displayAPIDs = true;
960 }
961 }
962
963 // Set the positions via initialising of the layout
964 layout.setInitialLocations(prevStatus.vertexPosition, lock);
965 }
966
967//-----------------------------------------------------------------------------
968
969 private class VertexLabelTransformer implements Function<JVertex,String>
970 {
971 @Override
972 public String apply(JVertex v) {
973 String label = "";
974 if (v.vtype == JVertexType.AP)
975 {
976 label = " AP" + v.label;
977 } else {
978 label = v.label;
979 if (v.displayBBID)
980 {
981 label = "<html><body style='text-align: center'>"
982 + label + "<br>" + v.dnpVertex.getBuildingBlockId()
983 + "</body></html>";
984 }
985 }
986 return label;
987 }
988 }
989
990//-----------------------------------------------------------------------------
991
992 private class VertexShapePaintTransformer implements Function<JVertex,Shape>
993 {
997 @Override
998 public Shape apply(JVertex v) {
999 switch (v.vtype)
1000 {
1001 case CAP:
1002 return new RoundRectangle2D.Double(
1003 -szB/2, -szB/2, szB, szB, 5, 5);
1004 case RCV:
1005 return new RoundRectangle2D.Double(
1006 -szM/2, -szM/2, szM, szM, 5, 5);
1007 case AP:
1008 return new Ellipse2D.Double(-szS/2,-szS/2,szS,szS);
1009 default:
1010 return new RoundRectangle2D.Double(
1011 -szB/2, -szB/2, szB, szB, 5, 5);
1012 }
1013 }
1014 }
1015
1016//-----------------------------------------------------------------------------
1017
1018 private class VertexFillPaintTransformer implements Function<JVertex,Paint>
1019 {
1020 private final PickedInfo<JVertex> pi;
1021
1022 public VertexFillPaintTransformer(PickedInfo<JVertex> pi){
1023 this.pi = pi;
1024 }
1025
1026 @Override
1027 public Paint apply(JVertex v) {
1028 if (pi.isPicked(v))
1029 {
1030 return Color.GREEN;
1031 } else {
1032 switch (v.vtype)
1033 {
1034 case FRAG:
1035 return Color.decode("#4484CE");
1036 case SCAF:
1037 return Color.decode("#F53240");
1038 case CAP:
1039 return Color.decode("#57BC90");
1040 case RCV:
1041 return Color.decode("#F19F4D");
1042 case AP:
1043 return Color.decode("#FECE00");
1044 default:
1045 return Color.decode("#BF1EE3");
1046 }
1047 }
1048 }
1049 }
1050
1051//-----------------------------------------------------------------------------
1052
1053 private class EdgeStrokeTransformer implements Function<JEdge,Stroke>
1054 {
1055 @Override
1056 public Stroke apply(JEdge e) {
1057 return new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
1058 BasicStroke.JOIN_ROUND, 1.5f);
1059 }
1060 }
1061
1062//-----------------------------------------------------------------------------
1063
1064 private class EdgeDrawPaintTransformer implements Function<JEdge,Paint>
1065 {
1066 @Override
1067 public Paint apply(JEdge e) {
1068 if (e.toAp)
1069 return Color.decode("#FECE00");
1070 else
1071 return Color.decode("#000000");
1072 }
1073 }
1074
1075//-----------------------------------------------------------------------------
1076
1077 private class EdgeLabelTransformer implements Function<JEdge,String>
1078 {
1079 @Override
1080 public String apply(JEdge e) {
1081 if (!e.displayAPCs && !e.displayBndTyp && !e.displayAPIDs)
1082 {
1083 return null;
1084 }
1085 String label = "";
1086 if (e.toAp)
1087 {
1088 if (e.displayAPCs)
1089 {
1090 label = e.srcAPC;
1091 }
1092 } else {
1093 if (e.displayBndTyp)
1094 {
1095 label = label + e.bt;
1096 }
1097 if (e.displayAPCs)
1098 {
1099 if (!label.isEmpty()) label = label + "<br>";
1100 label = label + e.srcAPC + "<br>" + e.trgAPC;
1101 }
1102 if (e.displayAPIDs)
1103 {
1104 if (!label.isEmpty()) label = label + "<br>";
1105 label = label + e.srcAPID + ":" + e.trgAPID;
1106 }
1107 }
1108
1109 if (!label.isEmpty())
1110 {
1111 // This is to place single-line labels above/below the edge
1112 // rather than on top of it.
1113 if (!label.contains("<br>"))
1114 {
1115 label = " <br>" + label;
1116 }
1117 label = "<html><body style='text-align: center'>"
1118 + label + "</body></html>";
1119 }
1120 return label;
1121 }
1122 }
1123
1124//-----------------------------------------------------------------------------
1125
1136 public void alterLabels(LabelType labelType, boolean show)
1137 {
1138 switch (labelType)
1139 {
1140 case APC:
1141 for (JVertex v : getSelectedNodes())
1142 {
1143 for (JEdge e : loadedGraph.getIncidentEdges(v))
1144 {
1145 e.displayAPCs = show;
1146 }
1147 }
1148 break;
1149
1150 case APID:
1151 for (JVertex v : getSelectedNodes())
1152 {
1153 for (JEdge e : loadedGraph.getIncidentEdges(v))
1154 {
1155 e.displayAPIDs = show;
1156 }
1157 }
1158 break;
1159
1160 case BT:
1161 for (JVertex v : getSelectedNodes())
1162 {
1163 for (JEdge e : loadedGraph.getIncidentEdges(v))
1164 {
1165 e.displayBndTyp = show;
1166 }
1167 }
1168 break;
1169
1170 case BBID:
1171 for (JVertex v : getSelectedNodes())
1172 {
1173 v.displayBBID = show;
1174 }
1175 break;
1176 }
1177 viewer.repaint();
1178 }
1179
1180//-----------------------------------------------------------------------------
1181
1186 public Set<JEdge> getSelectedEdges()
1187 {
1188 Set<JEdge> selEdges = new HashSet<>(
1189 viewer.getPickedEdgeState().getPicked());
1190 List<JVertex> lstNodes = new ArrayList<JVertex>(
1191 viewer.getPickedVertexState().getPicked());
1192 for (int i=0; i<lstNodes.size(); i++)
1193 {
1194 for (int j=i+1; j<lstNodes.size(); j++)
1195 {
1196 JEdge e = loadedGraph.findEdge(lstNodes.get(i),
1197 lstNodes.get(j));
1198 if (e != null)
1199 {
1200 selEdges.add(e);
1201 }
1202 JEdge erev = loadedGraph.findEdge(lstNodes.get(j),
1203 lstNodes.get(i));
1204 if (erev != null)
1205 {
1206 selEdges.add(erev);
1207 }
1208 }
1209 }
1210 return selEdges;
1211 }
1212
1213//-----------------------------------------------------------------------------
1214
1219 public Set<JVertex> getSelectedNodes()
1220 {
1221 return viewer.getPickedVertexState().getPicked();
1222 }
1223
1224//-----------------------------------------------------------------------------
1225
1230 public boolean hasSelected()
1231 {
1232 return !viewer.getPickedVertexState().getPicked().isEmpty();
1233 }
1234
1235//-----------------------------------------------------------------------------
1236
1241 {
1242 JUNGGraphSnapshot snapshot = null;
1243 if (loadedGraph != null)
1244 {
1245 snapshot = new JUNGGraphSnapshot(loadedGraph,layout);
1246 }
1247 return snapshot;
1248 }
1249
1250//-----------------------------------------------------------------------------
1251
1252 public void dispose()
1253 {
1254 cleanup();
1255 }
1256
1257//-----------------------------------------------------------------------------
1258
1259}
String toString()
Do not use this to make SDF representations.
Definition: APClass.java:352
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
APClass getAPClass()
Returns the Attachment Point class.
String toString()
Produces a string with the information included in this object.
int getID()
Returns a unique integer that is used to sort list of attachment points.
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
List< Vertex > getVertexList()
Definition: DGraph.java:719
List< Ring > getRings()
Definition: DGraph.java:771
List< Edge > getEdgeList()
Definition: DGraph.java:764
This class represents the edge between two vertices.
Definition: Edge.java:38
This class represents the closure of a ring in a spanning tree.
Definition: Ring.java:40
ArrayList< AttachmentPoint > getAttachmentPoints()
Return the list of attachment points visible from outside the template, i.e., the so-called outer APs...
Definition: Template.java:458
AttachmentPoint getInnerAPFromOuterAP(AttachmentPoint outerAP)
Definition: Template.java:808
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
int getBuildingBlockId()
Returns the index of the building block that should correspond to the position of the building block ...
Definition: Vertex.java:284
Vertex.BBType getBuildingBlockType()
Definition: Vertex.java:298
This layout extends the SpringLayout to change its behaviour.
The collection of tunable preferences.
static int graphNodeSize
Graph visualization: size of nodes.
static int graphLabelFontSize
Graph visualization: font size of labels.
boolean toAp
Flag defining whether this edge is representing a AttachmentPoint.
JEdge(AttachmentPoint srcAP, AttachmentPoint trgAP, String bt)
Constructor for a JUNG edge representing a Edge or a chord that closes a Ring.
JEdge(AttachmentPoint srcAP)
Constructor for a JUNG edge representing a AttachmentPoint.
String bt
The bond type for edges that correspond to connections between Vertexs or "none" when for edges repre...
boolean displayAPCs
Flag requiring to display APClasses.
boolean displayBndTyp
Flag requiring to display Bond type.
String srcAPID
String representing the index of the source AP in the list of APs of the vertex owning the source AP.
String trgAPC
String representing the APClass on the target AP of directed edged this JUNG edge represents.
String trgAPID
String representing the index of the target AP in the list of APs of the vertex owning the source AP.
boolean displayAPIDs
Flag requiring to display APClasses.
String srcAPC
String representing the APClass on the source AP of directed edges or on the AP this edge represents.
JVertex(Vertex v)
Constructor for vertex that represents a given Vertex.
JEdge edgeToParent
Reference to the JEdge linking this vertex to its parent vertex.
boolean expandable
Flag enabling opening vertex inner view (i.e., expand templates) in graph viewer.
boolean displayBBID
Flag requiring to display building block ID.
JVertex(AttachmentPoint ap)
Constructor for vertex that represents a given AttachmentPoint.
Vertex dnpVertex
The reference to the corresponding Vertex or null.
JVertexType vtype
A shortcut to record which type of DENOPTIM object this vertex represents.
String idStr
The string used as identifier of this JVertex in different instances representing the same graph.
String label
The string used as label when graphically depicting this vertex.
AttachmentPoint ap
The reference to the corresponding AttachmentPoint or null.
A Panel that holds the JUNG representation of a graph.
VisualizationViewer< JVertex, JEdge > viewer
void loadGraphToViewer(DGraph dnGraph)
Load the given DGraph to this graph viewer.
void inheritFeatures(JUNGGraphSnapshot prevStatus, boolean lock)
JUNGGraphSnapshot getGraphStatusSnapshot()
Returns a copy of the graph loaded into the viewer.
void loadGraphToViewer(DGraph dnGraph, JUNGGraphSnapshot prevStatus)
Load the given DGraph to the graph viewer.
edu.uci.ics.jung.graph.Graph< JVertex, JEdge > convertDnGraphToGSGraph(DGraph dnpGraph, Template tmpl)
Created a JUNG graph object that represents a DGraph, and allows to load a graphical representation i...
void initialize()
Builds the initialized component.
void loadGraphToViewer(Template tmpl)
Load the DGraph contained in a Template into the graph viewer.
void loadGraphToViewer(edu.uci.ics.jung.graph.Graph< JVertex, JEdge > g)
Load the given graph to the graph viewer.
void cleanup()
Removes the currently loaded graph viewer.
DNPSpringLayout< JVertex, JEdge > layout
Set< JVertex > getSelectedNodes()
Finds selected nodes from the viewer.
edu.uci.ics.jung.graph.Graph< JVertex, JEdge > loadedGraph
void loadGraphToViewer(edu.uci.ics.jung.graph.Graph< JVertex, JEdge > g, JUNGGraphSnapshot prevStatus, boolean lock, double reScaling)
Load the given graph to the graph viewer.
void setMouseMode(ModalGraphMouse.Mode mode)
void loadGraphToViewer(edu.uci.ics.jung.graph.Graph< JVertex, JEdge > g, JUNGGraphSnapshot prevStatus, boolean lock)
Load the given graph to the graph viewer.
static final String PROPERTYMOUSEMODE
Set< JEdge > getSelectedEdges()
Finds of selected edges from the viewer.
DefaultModalGraphMouse< JVertex, JEdge > gm
static void renumberAPs(Template tmpl, edu.uci.ics.jung.graph.Graph< JVertex, JEdge > graph)
static final String PROPERTYNODECLICKED
edu.uci.ics.jung.graph.Graph< JVertex, JEdge > convertDnGraphToGSGraph(DGraph dnG)
Created a JUNG graph object that represents a DGraph, and allows to load a graphical representation i...
void alterLabels(LabelType labelType, boolean show)
Adds or removes labels from the elements selected in the graph view.
void fireMouseModePropertyChange(int i)
Files a property change relative to the mode of mouse transformation.
boolean hasSelected()
Check is there is any node selected in the viewer.
void loadGraphToViewer(edu.uci.ics.jung.graph.Graph< JVertex, JEdge > g, JUNGGraphSnapshot prevStatus)
Load the given graph to the graph viewer.
static final long serialVersionUID
Version UID.
This class collects information on how a graph was displayed in a JUNG visialisation server (i....
Map< String, Point2D > vertexPosition
Positions of nodes.
ArrayList< String > getEdgeIDsWithLabel(LabelType labelName)
ArrayList< String > getVertexeIDsWithLabel(LabelType labelName)