# HG changeset patch # User Thomas Wuerthinger # Date 1327965790 -3600 # Node ID aae5b3773e6384a28fc3e0b929d7bbae83089b84 # Parent f3cc08cb211dc163dc90033d6c14e2601b89dc2e Added CFG editor from c1visualizer. diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 77 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor +END +manifest.mf +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/manifest.mf +END +build.xml +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/c1visualizer~svn/!svn/ver/186/trunk/C1Visualizer/Control%20Flow%20Editor/build.xml +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/dir-prop-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/dir-prop-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 6 +build + +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,105 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor +https://svn.java.net/svn/c1visualizer~svn + + + +2011-06-30T16:41:14.883751Z +201 +christianw +has-props + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +test +dir + +nbproject +dir + +src +dir + +manifest.mf +file + + + + +2012-01-28T15:08:37.661161Z +7b79e34dd7d10a5f3217846992d92313 +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + + + + + + + + +237 + +build.xml +file + + + + +2012-01-28T15:08:37.665161Z +80dff6a001f91e7db91fb56c0277fc5b +2010-07-16T01:08:34.138866Z +186 +ChristianW + + + + + + + + + + + + + + + + + + + + + +497 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/text-base/manifest.mf.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/.svn/text-base/manifest.mf.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: at.ssw.visualizer.cfg +OpenIDE-Module-Layer: at/ssw/visualizer/cfg/layer.xml +OpenIDE-Module-Localizing-Bundle: at/ssw/visualizer/cfg/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/manifest.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/manifest.mf Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: at.ssw.visualizer.cfg +OpenIDE-Module-Layer: at/ssw/visualizer/cfg/layer.xml +OpenIDE-Module-Localizing-Bundle: at/ssw/visualizer/cfg/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 81 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor/src +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src +https://svn.java.net/svn/c1visualizer~svn + + + +2011-06-30T16:41:14.883751Z +201 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +at +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor/src/at +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at +https://svn.java.net/svn/c1visualizer~svn + + + +2011-06-30T16:41:14.883751Z +201 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +ssw +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw +https://svn.java.net/svn/c1visualizer~svn + + + +2011-06-30T16:41:14.883751Z +201 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +visualizer +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer +https://svn.java.net/svn/c1visualizer~svn + + + +2011-06-30T16:41:14.883751Z +201 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +cfg +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg +END +Bundle.properties +K 25 +svn:wc:ra_dav:version-url +V 119 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/Bundle.properties +END +CfgEditorContext.java +K 25 +svn:wc:ra_dav:version-url +V 125 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/CfgEditorContext.java +END +layer.xml +K 25 +svn:wc:ra_dav:version-url +V 113 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/layer.xml +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,151 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg +https://svn.java.net/svn/c1visualizer~svn + + + +2011-06-30T16:41:14.883751Z +201 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +model +dir + +graph +dir + +preferences +dir + +visual +dir + +Bundle.properties +file + + + + +2012-01-28T15:08:37.595157Z +3f4c420dd550e890a0f701e56f75f511 +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + + + + + + + + +41 + +editor +dir + +icons +dir + +CfgEditorContext.java +file + + + + +2012-01-28T15:08:37.598157Z +45786941b665b0c2ed7840e406f6664c +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +395 + +layer.xml +file + + + + +2012-01-28T15:08:37.602158Z +d141d34a275fa304984415b3da57158d +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +3449 + +action +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/Bundle.properties.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/Bundle.properties.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Control Flow Editor diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/CfgEditorContext.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/CfgEditorContext.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,13 @@ + +package at.ssw.visualizer.cfg; + +public abstract class CfgEditorContext { + + public static final int LAYOUT_HIERARCHICALNODELAYOUT = 1; + public static final int LAYOUT_HIERARCHICALCOMPOUNDLAYOUT = 2; + + public static final int ROUTING_DIRECTLINES = 1; + public static final int ROUTING_BEZIER = 2; + + public static final int MAX_AUTOEDGESVISIBLE = 8; +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/CfgEditorContext.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/CfgEditorContext.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,13 @@ + +package at.ssw.visualizer.cfg; + +public abstract class CfgEditorContext { + + public static final int LAYOUT_HIERARCHICALNODELAYOUT = 1; + public static final int LAYOUT_HIERARCHICALCOMPOUNDLAYOUT = 2; + + public static final int ROUTING_DIRECTLINES = 1; + public static final int ROUTING_BEZIER = 2; + + public static final int MAX_AUTOEDGESVISIBLE = 8; +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/layer.xml.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/layer.xml.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/layer.xml.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/.svn/text-base/layer.xml.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/Bundle.properties Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Control Flow Editor diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgEditorContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgEditorContext.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,13 @@ + +package at.ssw.visualizer.cfg; + +public abstract class CfgEditorContext { + + public static final int LAYOUT_HIERARCHICALNODELAYOUT = 1; + public static final int LAYOUT_HIERARCHICALCOMPOUNDLAYOUT = 2; + + public static final int ROUTING_DIRECTLINES = 1; + public static final int ROUTING_BEZIER = 2; + + public static final int MAX_AUTOEDGESVISIBLE = 8; +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,95 @@ +K 25 +svn:wc:ra_dav:version-url +V 110 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action +END +AbstractRouterAction.java +K 25 +svn:wc:ra_dav:version-url +V 136 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/AbstractRouterAction.java +END +ShowCFGEditorAction.java +K 25 +svn:wc:ra_dav:version-url +V 135 +/svn/c1visualizer~svn/!svn/ver/201/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/ShowCFGEditorAction.java +END +ShowAllAction.java +K 25 +svn:wc:ra_dav:version-url +V 129 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/ShowAllAction.java +END +ZoominAction.java +K 25 +svn:wc:ra_dav:version-url +V 128 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/ZoominAction.java +END +ZoomoutAction.java +K 25 +svn:wc:ra_dav:version-url +V 129 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/ZoomoutAction.java +END +ColorAction.java +K 25 +svn:wc:ra_dav:version-url +V 127 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/ColorAction.java +END +SwitchLoopClustersAction.java +K 25 +svn:wc:ra_dav:version-url +V 140 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/SwitchLoopClustersAction.java +END +HierarchicalCompoundLayoutAction.java +K 25 +svn:wc:ra_dav:version-url +V 148 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/HierarchicalCompoundLayoutAction.java +END +HideEdgesAction.java +K 25 +svn:wc:ra_dav:version-url +V 131 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/HideEdgesAction.java +END +ExportAction.java +K 25 +svn:wc:ra_dav:version-url +V 128 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/ExportAction.java +END +HierarchicalNodeLayoutAction.java +K 25 +svn:wc:ra_dav:version-url +V 144 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/HierarchicalNodeLayoutAction.java +END +ShowEdgesAction.java +K 25 +svn:wc:ra_dav:version-url +V 131 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/ShowEdgesAction.java +END +AbstractCfgEditorAction.java +K 25 +svn:wc:ra_dav:version-url +V 139 +/svn/c1visualizer~svn/!svn/ver/176/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/AbstractCfgEditorAction.java +END +UseBezierRouterAction.java +K 25 +svn:wc:ra_dav:version-url +V 137 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/UseBezierRouterAction.java +END +UseDirectLineRouterAction.java +K 25 +svn:wc:ra_dav:version-url +V 141 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action/UseDirectLineRouterAction.java +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,538 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/action +https://svn.java.net/svn/c1visualizer~svn + + + +2011-06-30T16:41:14.883751Z +201 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +AbstractRouterAction.java +file + + + + +2012-01-28T15:08:37.556155Z +42afb619f7ba5d324d3107936493ad1d +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1654 + +ShowCFGEditorAction.java +file + + + + +2012-01-28T15:08:37.558155Z +cd7f997fae54355e1dbada2a098d2d97 +2011-06-30T16:41:14.883751Z +201 +christianw + + + + + + + + + + + + + + + + + + + + + +1744 + +ShowAllAction.java +file + + + + +2012-01-28T15:08:37.564155Z +8f2325ed63e26c0f99c128bdb36923df +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +939 + +ZoominAction.java +file + + + + +2012-01-28T15:08:37.569156Z +fa1162a9dea5c9b3bfb2d0a781bd6e1c +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +773 + +ZoomoutAction.java +file + + + + +2012-01-28T15:08:37.572156Z +7f7548f29c1c61c67ecfc9b677e8ecfc +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +772 + +ColorAction.java +file + + + + +2012-01-28T15:08:37.575156Z +5303aa59adafad9f5d3f3207ac4965f1 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +6857 + +SwitchLoopClustersAction.java +file + + + + +2012-01-28T15:08:37.581156Z +641610ab201caca1fe6ed29c0764be90 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1982 + +HierarchicalCompoundLayoutAction.java +file + + + + +2012-01-28T15:08:37.551155Z +dbdf7875372c99ca2d5055141062e1e2 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +925 + +HideEdgesAction.java +file + + + + +2012-01-28T15:08:37.545154Z +3e6c126b2295f249079935ed75ac7240 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1402 + +ExportAction.java +file + + + + +2012-01-28T15:08:37.542154Z +3079f7f72c690ab5dc58263c1563e611 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +4965 + +HierarchicalNodeLayoutAction.java +file + + + + +2012-01-28T15:08:37.553155Z +8f31ba1ad062695831415e36975aecb6 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +921 + +ShowEdgesAction.java +file + + + + +2012-01-28T15:08:37.561155Z +5c854df85b17867c6c6af584db789629 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1390 + +AbstractCfgEditorAction.java +file + + + + +2012-01-28T15:08:37.567156Z +9a38ec0e94b0b73cdcefef510d3b1711 +2009-06-28T16:17:48.993548Z +176 +ChristianW + + + + + + + + + + + + + + + + + + + + + +2712 + +UseBezierRouterAction.java +file + + + + +2012-01-28T15:08:37.578156Z +fd43f4b983ef815407772ff3e072cde4 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +715 + +UseDirectLineRouterAction.java +file + + + + +2012-01-28T15:08:37.583156Z +faf0fac73f13cf313b5386e9bff0cce2 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +710 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/AbstractCfgEditorAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/AbstractCfgEditorAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,94 @@ +package at.ssw.visualizer.cfg.action; + + +import at.ssw.visualizer.cfg.graph.CfgEventListener; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import org.openide.util.actions.CallableSystemAction; +import org.openide.windows.TopComponent; + +/** + * The common superclass of all concrete actions related to the CFG visualizer. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public abstract class AbstractCfgEditorAction extends CallableSystemAction implements CfgEventListener , PropertyChangeListener { + + CfgEditorTopComponent topComponent = null; + + public AbstractCfgEditorAction() { + TopComponent.getRegistry().addPropertyChangeListener(this); + setEnabled(false); + + } + + protected CfgEditorTopComponent getEditor() { + return topComponent; + } + + protected void setEditor(CfgEditorTopComponent newTopComponent) { + CfgEditorTopComponent oldTopComponent = getEditor(); + if(newTopComponent != oldTopComponent){ + if(oldTopComponent != null) { + oldTopComponent.getCfgScene().removeCfgEventListener(this); + } + this.topComponent = newTopComponent; + if (newTopComponent != null) { + newTopComponent.getCfgScene().addCfgEventListener(this); + selectionChanged(newTopComponent.getCfgScene()); + } + this.setEnabled(newTopComponent!=null); + } + } + + + @Override + public JMenuItem getMenuPresenter() { + return new JMenuItem(this); + } + + + @Override + public JComponent getToolbarPresenter() { + JButton b = new JButton(this); + if (getIcon() != null) { + b.setText(null); + b.setToolTipText(getName()); + } + return b; + } + + + @Override + public JMenuItem getPopupPresenter() { + return new JMenuItem(this); + } + + + @Override + protected boolean asynchronous() { + return false; + } + + + public void propertyChange(PropertyChangeEvent e) { + if ( e.getPropertyName().equals(TopComponent.Registry.PROP_ACTIVATED)) { + if(e.getNewValue() instanceof CfgEditorTopComponent){ + CfgEditorTopComponent tc = (CfgEditorTopComponent)e.getNewValue(); + setEditor(tc); + selectionChanged(tc.getCfgScene()); + } + } + } + + + public void selectionChanged(CfgScene scene) { + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/AbstractRouterAction.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/AbstractRouterAction.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,61 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JToggleButton; +import org.openide.util.actions.Presenter; + +/** + * Common superclass for all actions which set the link router. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public abstract class AbstractRouterAction extends AbstractCfgEditorAction implements Presenter.Menu, Presenter.Popup, Presenter.Toolbar { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + setLinkRouter(tc); + } + } + + protected abstract void setLinkRouter(CfgEditorTopComponent editor); + + @Override + public JMenuItem getMenuPresenter() { + JMenuItem presenter = new MenuPresenter(); + presenter.setToolTipText(getName()); + return presenter; + } + + @Override + public JMenuItem getPopupPresenter() { + return getMenuPresenter(); + } + + @Override + public JComponent getToolbarPresenter() { + ToolbarPresenter presenter = new ToolbarPresenter(); + presenter.setToolTipText(getName()); + return presenter; + } + + class MenuPresenter extends JRadioButtonMenuItem { + + public MenuPresenter() { + super(AbstractRouterAction.this); + setIcon(null); + } + } + + class ToolbarPresenter extends JToggleButton { + + public ToolbarPresenter() { + super(AbstractRouterAction.this); + setText(null); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/AbstractRouterAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/AbstractRouterAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,61 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JToggleButton; +import org.openide.util.actions.Presenter; + +/** + * Common superclass for all actions which set the link router. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public abstract class AbstractRouterAction extends AbstractCfgEditorAction implements Presenter.Menu, Presenter.Popup, Presenter.Toolbar { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + setLinkRouter(tc); + } + } + + protected abstract void setLinkRouter(CfgEditorTopComponent editor); + + @Override + public JMenuItem getMenuPresenter() { + JMenuItem presenter = new MenuPresenter(); + presenter.setToolTipText(getName()); + return presenter; + } + + @Override + public JMenuItem getPopupPresenter() { + return getMenuPresenter(); + } + + @Override + public JComponent getToolbarPresenter() { + ToolbarPresenter presenter = new ToolbarPresenter(); + presenter.setToolTipText(getName()); + return presenter; + } + + class MenuPresenter extends JRadioButtonMenuItem { + + public MenuPresenter() { + super(AbstractRouterAction.this); + setIcon(null); + } + } + + class ToolbarPresenter extends JToggleButton { + + public ToolbarPresenter() { + super(AbstractRouterAction.this); + setText(null); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ColorAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ColorAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,226 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.graph.CfgEventListener; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.image.BufferedImage; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.SwingConstants; +import javax.swing.plaf.basic.BasicArrowButton; +import org.openide.util.HelpCtx; +import org.openide.util.actions.Presenter; + +/** + * Changes the background color of a node. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class ColorAction extends AbstractCfgEditorAction implements Presenter.Menu, Presenter.Popup, Presenter.Toolbar { + + public static final int IMAGE_WIDTH = 16; + public static final int IMAGE_HEIGHT = 16; + + + /** Names of colors shown in color select lists. */ + private static final String[] COLOR_NAMES = {"White", "Light Gray", "Dark Gray", "Light Yellow", "Dark Yellow", "Light Green", "Dark Green", "Light Cyan", "Dark Cyan", "Light Blue", "Dark Blue", "Light Magenta", "Dark Magenta", "Light Red", "Dark Red"}; + + /** Values of colors shown in color select lists. */ + private static final Color[] COLORS = { + new Color(0xFFFFFF), new Color(0xD4D0C8), new Color(0xA4A098), new Color(0xF0F0B0), new Color(0xE0E040), + new Color(0xB0F0B0), new Color(0x40E040), new Color(0xB0F0F0), new Color(0x40E0E0), new Color(0xB0B0F0), + new Color(0x4040E0), new Color(0xF0B0F0), new Color(0xE040E0), new Color(0xF0B0B0), new Color(0xE04040) + }; + + public void performAction() { + // nothing to do here, the presenters are supposed to call + // performAction(Color) + } + + protected void performAction(Color color) { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + tc.getCfgScene().setSelectedNodesColor(color); + } + } + + public String getName() { + return "Change NodeColor"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/color.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public JMenuItem getMenuPresenter() { + return new MenuPresenter(); + } + + @Override + public JMenuItem getPopupPresenter() { + return new MenuPresenter(); + } + + @Override + public JComponent getToolbarPresenter() { + return new ToolbarPresenter(); + } + + class MenuPresenter extends JMenu { + + public MenuPresenter() { + super(ColorAction.this); + initGUI(); + } + + protected void initGUI() { + CfgEditorTopComponent tc = getEditor(); + if( tc != null && tc.getCfgScene().getSelectedNodes().size()==0) { + //no node selected + setEnabled(false); + } else { + add(new SetColorAction(null, "Automatic")); + for (int i = 0; i < COLORS.length; i++) { + add(new SetColorAction(COLORS[i], COLOR_NAMES[i])); + } + } + } + } + + class ToolbarPresenter extends JButton implements CfgEventListener, MouseListener { + + final int arrowSize = 5; + final int arrowMargin = 3; + JPopupMenu popup; + + public ToolbarPresenter() { + setIcon(createIcon()); + setToolTipText(ColorAction.this.getName()); + + popup = new JPopupMenu(); + popup.add(new SetColorAction(null, "Automatic")); + for (int i = 0; i < COLORS.length; i++) { + popup.add(new SetColorAction(COLORS[i], COLOR_NAMES[i])); + } + addMouseListener(this); + } + + public Icon createIcon() { + BasicArrowButton arrow = new BasicArrowButton(SwingConstants.SOUTH); + BufferedImage img = new BufferedImage(IMAGE_WIDTH + arrowSize + 2 * arrowMargin, IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB); + Graphics g = img.getGraphics(); + ColorAction.this.getIcon().paintIcon(this, g, 0, 0); + arrow.paintTriangle(g, IMAGE_WIDTH + arrowMargin + arrowSize / 2, IMAGE_HEIGHT / 2 - arrowSize / 2, arrowSize, SwingConstants.SOUTH, true); + return new ImageIcon(img); + } + + + public void selectionChanged(CfgScene scene) { + Set nodes = scene.getSelectedNodes(); + setEnabled(nodes.size() > 0); + } + + public void mouseClicked(MouseEvent e) { + if (e.getX() < getInsets().left + IMAGE_WIDTH + arrowMargin) { + performAction(null); + } else { + popup.show(this, 0, getSize().height); + } + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseReleased(MouseEvent e) { + } + } + + protected Icon createIcon(Color color) { + if (color == null) { + return ColorAction.this.getIcon(); + } else { + return new ColorIcon(color); + } + } + + class ColorIcon implements Icon { + + Color color; + + public ColorIcon(Color color) { + this.color = color; + } + + public int getIconWidth() { + return IMAGE_WIDTH; + } + + public int getIconHeight() { + return IMAGE_HEIGHT; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Color oldColor = g.getColor(); + g.setColor(color); + g.fillRect(x, y, IMAGE_WIDTH, IMAGE_HEIGHT); + g.setColor(oldColor); + } + } + + class SetColorAction extends AbstractAction { + + Color color; + String name; + Icon icon; + + public SetColorAction(Color color, String name) { + super(name, createIcon(color)); + this.color = color; + this.name = name; + icon = (Icon) getValue(AbstractAction.SMALL_ICON); + } + + public Color getColor() { + return color; + } + + public String getName() { + return name; + } + + public Icon getIcon() { + return icon; + } + + public void actionPerformed(ActionEvent e) { + performAction(color); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ExportAction.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ExportAction.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,124 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.io.File; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileNameExtensionFilter; +import org.freehep.graphicsio.emf.EMFGraphics2D; +import org.freehep.graphicsio.gif.GIFGraphics2D; +import org.freehep.graphicsio.svg.SVGGraphics2D; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.util.HelpCtx; + +/** + * Exports Scene to various Graphics Formats + * + * @author Rumpfhuber Stefan + */ +public class ExportAction extends AbstractCfgEditorAction { + + public static final String DESCRIPTION_SVG = "Scaleable Vector Format (.svg)"; + public static final String DESCRIPTION_EMF = "Extended Meta File (.emf)"; + public static final String DESCRIPTION_GIF = "Graphics Interchange Format (.gif)"; + public static final String EXT_GIF = "gif", EXT_EMF = "emf", EXT_SVG = "svg"; + + String lastDirectory = null; + + @Override + public void performAction() { + CfgEditorTopComponent tc = this.getEditor(); + CfgScene scene = tc.getCfgScene(); + JComponent view = scene.getView(); + + JFileChooser chooser = new JFileChooser (); + chooser.setAcceptAllFileFilterUsed(false); + chooser.setDialogTitle (getName()); + chooser.setDialogType (JFileChooser.SAVE_DIALOG); + chooser.setMultiSelectionEnabled (false); + chooser.setFileSelectionMode (JFileChooser.FILES_ONLY); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_SVG, EXT_SVG)); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_EMF, EXT_EMF)); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_GIF, EXT_GIF)); + if(lastDirectory != null) + chooser.setCurrentDirectory(new File(lastDirectory)); + chooser.setSelectedFile(new File(tc.getName())); + + + if (chooser.showSaveDialog (tc) != JFileChooser.APPROVE_OPTION) + return; + + File file = chooser.getSelectedFile (); + + if(file == null) + return; + + FileNameExtensionFilter filter = (FileNameExtensionFilter) chooser.getFileFilter(); + String fn = file.getAbsolutePath().toLowerCase(); + String ext = filter.getExtensions()[0]; + if(!fn.endsWith("." + ext)){ + file = new File( file.getParentFile(), file.getName() + "." + ext); + } + + if (file.exists ()) { + DialogDescriptor descriptor = new DialogDescriptor ( + "File (" + file.getAbsolutePath () + ") already exists. Do you want to overwrite it?", + "File Exists", true, DialogDescriptor.YES_NO_OPTION, DialogDescriptor.NO_OPTION, null); + DialogDisplayer.getDefault ().createDialog (descriptor).setVisible (true); + if (descriptor.getValue () != DialogDescriptor.YES_OPTION) + return; + } + + lastDirectory = chooser.getCurrentDirectory().getAbsolutePath(); + + if(ext.equals(EXT_SVG)){ + SVGGraphics2D g; + try { + g = new SVGGraphics2D(file, scene.getBounds().getSize()); + g.startExport(); + scene.paint(g); + g.endExport(); + } catch(Exception ex){ + } + } else if (ext.equals(EXT_EMF)) { + EMFGraphics2D g; + try { + g = new EMFGraphics2D(file, scene.getBounds().getSize()); + g.startExport(); + scene.paint(g); + g.endExport(); + } catch(Exception ex){ + } + } else if (ext.equals(EXT_GIF)) { + GIFGraphics2D g; + try { + //use the view as image source to get a image with the current zoomfactor + //using the scene.paint() would always return a image with zoomfactor 1.0 + g = new GIFGraphics2D(file, view); + g.startExport(); + view.print(g); + g.endExport(); + } catch(Exception ex){ + } + } + } + + + @Override + public String getName() { + return "Export CFG"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/disk.gif"; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ExportAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ExportAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,124 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.io.File; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileNameExtensionFilter; +import org.freehep.graphicsio.emf.EMFGraphics2D; +import org.freehep.graphicsio.gif.GIFGraphics2D; +import org.freehep.graphicsio.svg.SVGGraphics2D; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.util.HelpCtx; + +/** + * Exports Scene to various Graphics Formats + * + * @author Rumpfhuber Stefan + */ +public class ExportAction extends AbstractCfgEditorAction { + + public static final String DESCRIPTION_SVG = "Scaleable Vector Format (.svg)"; + public static final String DESCRIPTION_EMF = "Extended Meta File (.emf)"; + public static final String DESCRIPTION_GIF = "Graphics Interchange Format (.gif)"; + public static final String EXT_GIF = "gif", EXT_EMF = "emf", EXT_SVG = "svg"; + + String lastDirectory = null; + + @Override + public void performAction() { + CfgEditorTopComponent tc = this.getEditor(); + CfgScene scene = tc.getCfgScene(); + JComponent view = scene.getView(); + + JFileChooser chooser = new JFileChooser (); + chooser.setAcceptAllFileFilterUsed(false); + chooser.setDialogTitle (getName()); + chooser.setDialogType (JFileChooser.SAVE_DIALOG); + chooser.setMultiSelectionEnabled (false); + chooser.setFileSelectionMode (JFileChooser.FILES_ONLY); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_SVG, EXT_SVG)); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_EMF, EXT_EMF)); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_GIF, EXT_GIF)); + if(lastDirectory != null) + chooser.setCurrentDirectory(new File(lastDirectory)); + chooser.setSelectedFile(new File(tc.getName())); + + + if (chooser.showSaveDialog (tc) != JFileChooser.APPROVE_OPTION) + return; + + File file = chooser.getSelectedFile (); + + if(file == null) + return; + + FileNameExtensionFilter filter = (FileNameExtensionFilter) chooser.getFileFilter(); + String fn = file.getAbsolutePath().toLowerCase(); + String ext = filter.getExtensions()[0]; + if(!fn.endsWith("." + ext)){ + file = new File( file.getParentFile(), file.getName() + "." + ext); + } + + if (file.exists ()) { + DialogDescriptor descriptor = new DialogDescriptor ( + "File (" + file.getAbsolutePath () + ") already exists. Do you want to overwrite it?", + "File Exists", true, DialogDescriptor.YES_NO_OPTION, DialogDescriptor.NO_OPTION, null); + DialogDisplayer.getDefault ().createDialog (descriptor).setVisible (true); + if (descriptor.getValue () != DialogDescriptor.YES_OPTION) + return; + } + + lastDirectory = chooser.getCurrentDirectory().getAbsolutePath(); + + if(ext.equals(EXT_SVG)){ + SVGGraphics2D g; + try { + g = new SVGGraphics2D(file, scene.getBounds().getSize()); + g.startExport(); + scene.paint(g); + g.endExport(); + } catch(Exception ex){ + } + } else if (ext.equals(EXT_EMF)) { + EMFGraphics2D g; + try { + g = new EMFGraphics2D(file, scene.getBounds().getSize()); + g.startExport(); + scene.paint(g); + g.endExport(); + } catch(Exception ex){ + } + } else if (ext.equals(EXT_GIF)) { + GIFGraphics2D g; + try { + //use the view as image source to get a image with the current zoomfactor + //using the scene.paint() would always return a image with zoomfactor 1.0 + g = new GIFGraphics2D(file, view); + g.startExport(); + view.print(g); + g.endExport(); + } catch(Exception ex){ + } + } + } + + + @Override + public String getName() { + return "Export CFG"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/disk.gif"; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/HideEdgesAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/HideEdgesAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,52 @@ +package at.ssw.visualizer.cfg.action; + + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import org.openide.util.HelpCtx; + +/** + * Hides all edges connected to the selected node. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class HideEdgesAction extends AbstractCfgEditorAction { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + tc.getCfgScene().setSelectedEdgesVisibility(false); + } + } + + public String getName() { + return "Hide Edges"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/hideedges.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public void selectionChanged(CfgScene scene) { + for (CfgNode n : scene.getSelectedNodes()) { + for (CfgEdge e : scene.findNodeEdges(n, true, true) ){ + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(ew.isVisible()) { + setEnabled(true); + return; + } + } + } + setEnabled(false); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/HierarchicalCompoundLayoutAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/HierarchicalCompoundLayoutAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,35 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +public class HierarchicalCompoundLayoutAction extends AbstractCfgEditorAction { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT); + scene.applyLayout(); + } + } + + public String getName() { + return "Hierarchical Compound Layout"; + } + + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/arrangeloop.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/HierarchicalNodeLayoutAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/HierarchicalNodeLayoutAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,35 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +public class HierarchicalNodeLayoutAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT); + scene.applyLayout(); + } + } + + public String getName() { + return "Hierarchical Node Layout"; + } + + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/arrangehier.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowAllAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowAllAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,40 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +/** + * Adjusts the Zoom factor of the Scene to the bounds of Scroll panel + * to get a clean view on the whole graph. + * + */ +public class ShowAllAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.zoomScene(); + + } + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public String getName() { + return "Fit Scene to Window"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/autosize.gif"; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowCFGEditorAction.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowCFGEditorAction.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,62 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorSupport; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.icons.Icons; +import at.ssw.visualizer.core.focus.Focus; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CookieAction; + +/** + * Shows the CFG visualizer for the currently selected compilation. + * + * @author Bernhard Stiftner + * @author Christian Wimmer + */ +public final class ShowCFGEditorAction extends CookieAction { + + protected void performAction(Node[] activatedNodes) { + ControlFlowGraph cfg = activatedNodes[0].getLookup().lookup(ControlFlowGraph.class); + if (!Focus.findEditor(CfgEditorTopComponent.class, cfg)) { + CfgEditorSupport editor = new CfgEditorSupport(cfg); + editor.open(); + } + } + + @Override + protected boolean enable(Node[] activatedNodes) { + if (!super.enable(activatedNodes)) { + return false; + } + ControlFlowGraph cfg = activatedNodes[0].getLookup().lookup(ControlFlowGraph.class); + return cfg.getBasicBlocks().size() > 0; + } + + public String getName() { + return "Open Control Flow Graph"; + } + + @Override + protected String iconResource() { + return Icons.CFG; + } + + protected int mode() { + return CookieAction.MODE_EXACTLY_ONE; + } + + protected Class[] cookieClasses() { + return new Class[]{ControlFlowGraph.class}; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowCFGEditorAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowCFGEditorAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,62 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorSupport; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.icons.Icons; +import at.ssw.visualizer.core.focus.Focus; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CookieAction; + +/** + * Shows the CFG visualizer for the currently selected compilation. + * + * @author Bernhard Stiftner + * @author Christian Wimmer + */ +public final class ShowCFGEditorAction extends CookieAction { + + protected void performAction(Node[] activatedNodes) { + ControlFlowGraph cfg = activatedNodes[0].getLookup().lookup(ControlFlowGraph.class); + if (!Focus.findEditor(CfgEditorTopComponent.class, cfg)) { + CfgEditorSupport editor = new CfgEditorSupport(cfg); + editor.open(); + } + } + + @Override + protected boolean enable(Node[] activatedNodes) { + if (!super.enable(activatedNodes)) { + return false; + } + ControlFlowGraph cfg = activatedNodes[0].getLookup().lookup(ControlFlowGraph.class); + return cfg.getBasicBlocks().size() > 0; + } + + public String getName() { + return "Open Control Flow Graph"; + } + + @Override + protected String iconResource() { + return Icons.CFG; + } + + protected int mode() { + return CookieAction.MODE_EXACTLY_ONE; + } + + protected Class[] cookieClasses() { + return new Class[]{ControlFlowGraph.class}; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowEdgesAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ShowEdgesAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,52 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import org.openide.util.HelpCtx; + +/** + * Shows all edges connected to the selected node. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class ShowEdgesAction extends AbstractCfgEditorAction { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + tc.getCfgScene().setSelectedEdgesVisibility(true); + } + } + + public String getName() { + return "Show edges"; + } + + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/showedges.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public void selectionChanged(CfgScene scene) { + for (CfgNode n : scene.getSelectedNodes()) { + for (CfgEdge e : scene.findNodeEdges(n, true, true) ){ + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!ew.isVisible()) { + setEnabled(true); + return; + } + } + } + setEnabled(false); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/SwitchLoopClustersAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/SwitchLoopClustersAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,66 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import javax.swing.JComponent; +import javax.swing.JToggleButton; +import org.openide.util.HelpCtx; +import org.openide.util.actions.Presenter; + +public class SwitchLoopClustersAction extends AbstractCfgEditorAction implements Presenter.Toolbar { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + boolean visible = scene.isLoopClusterVisible(); + scene.setLoopWidgets(!visible); + } + } + + @Override + public String getName() { + return "Enable/Disable Loop Clusters"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/cluster.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + + @Override + public JComponent getToolbarPresenter() { + return new ToolbarPresenter(); + } + + class ToolbarPresenter extends JToggleButton { + private static final String TOOLTIP_ENABLE = "Enable LoopClusters"; + private static final String TOOLTIP_DISABLE = "Disable LoopClusters"; + + public ToolbarPresenter() { + super(SwitchLoopClustersAction.this); + setText(null); + this.setToolTipText(TOOLTIP_DISABLE); + this.setSelected(true); + + this.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if(isSelected()){ + setToolTipText(TOOLTIP_DISABLE); + } else { + setToolTipText(TOOLTIP_ENABLE); + } + } + }); + } + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/UseBezierRouterAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/UseBezierRouterAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,29 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import org.openide.util.HelpCtx; + + +public class UseBezierRouterAction extends AbstractRouterAction { + + @Override + protected void setLinkRouter(CfgEditorTopComponent editor) { + editor.getCfgScene().setRouter(CfgEditorContext.ROUTING_BEZIER); + } + + @Override + public String getName() { + return "Use Bezier Router"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/bezierrouter.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/UseDirectLineRouterAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/UseDirectLineRouterAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,28 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import org.openide.util.HelpCtx; + + +public class UseDirectLineRouterAction extends AbstractRouterAction { + + @Override + protected void setLinkRouter(CfgEditorTopComponent editor) { + editor.getCfgScene().setRouter(CfgEditorContext.ROUTING_DIRECTLINES); + } + + @Override + public String getName() { + return "User Direct Router"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/fanrouter.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ZoominAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ZoominAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,33 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +public class ZoominAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.animateZoom(1.1); + } + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/zoomin.gif"; + } + + @Override + public String getName() { + return "Zoomin"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ZoomoutAction.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/.svn/text-base/ZoomoutAction.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,33 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + +public class ZoomoutAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.animateZoom(0.9); + } + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/zoomout.gif"; + } + + @Override + public String getName() { + return "Zoomout"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractCfgEditorAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractCfgEditorAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,94 @@ +package at.ssw.visualizer.cfg.action; + + +import at.ssw.visualizer.cfg.graph.CfgEventListener; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import org.openide.util.actions.CallableSystemAction; +import org.openide.windows.TopComponent; + +/** + * The common superclass of all concrete actions related to the CFG visualizer. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public abstract class AbstractCfgEditorAction extends CallableSystemAction implements CfgEventListener , PropertyChangeListener { + + CfgEditorTopComponent topComponent = null; + + public AbstractCfgEditorAction() { + TopComponent.getRegistry().addPropertyChangeListener(this); + setEnabled(false); + + } + + protected CfgEditorTopComponent getEditor() { + return topComponent; + } + + protected void setEditor(CfgEditorTopComponent newTopComponent) { + CfgEditorTopComponent oldTopComponent = getEditor(); + if(newTopComponent != oldTopComponent){ + if(oldTopComponent != null) { + oldTopComponent.getCfgScene().removeCfgEventListener(this); + } + this.topComponent = newTopComponent; + if (newTopComponent != null) { + newTopComponent.getCfgScene().addCfgEventListener(this); + selectionChanged(newTopComponent.getCfgScene()); + } + this.setEnabled(newTopComponent!=null); + } + } + + + @Override + public JMenuItem getMenuPresenter() { + return new JMenuItem(this); + } + + + @Override + public JComponent getToolbarPresenter() { + JButton b = new JButton(this); + if (getIcon() != null) { + b.setText(null); + b.setToolTipText(getName()); + } + return b; + } + + + @Override + public JMenuItem getPopupPresenter() { + return new JMenuItem(this); + } + + + @Override + protected boolean asynchronous() { + return false; + } + + + public void propertyChange(PropertyChangeEvent e) { + if ( e.getPropertyName().equals(TopComponent.Registry.PROP_ACTIVATED)) { + if(e.getNewValue() instanceof CfgEditorTopComponent){ + CfgEditorTopComponent tc = (CfgEditorTopComponent)e.getNewValue(); + setEditor(tc); + selectionChanged(tc.getCfgScene()); + } + } + } + + + public void selectionChanged(CfgScene scene) { + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractRouterAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractRouterAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,61 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JToggleButton; +import org.openide.util.actions.Presenter; + +/** + * Common superclass for all actions which set the link router. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public abstract class AbstractRouterAction extends AbstractCfgEditorAction implements Presenter.Menu, Presenter.Popup, Presenter.Toolbar { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + setLinkRouter(tc); + } + } + + protected abstract void setLinkRouter(CfgEditorTopComponent editor); + + @Override + public JMenuItem getMenuPresenter() { + JMenuItem presenter = new MenuPresenter(); + presenter.setToolTipText(getName()); + return presenter; + } + + @Override + public JMenuItem getPopupPresenter() { + return getMenuPresenter(); + } + + @Override + public JComponent getToolbarPresenter() { + ToolbarPresenter presenter = new ToolbarPresenter(); + presenter.setToolTipText(getName()); + return presenter; + } + + class MenuPresenter extends JRadioButtonMenuItem { + + public MenuPresenter() { + super(AbstractRouterAction.this); + setIcon(null); + } + } + + class ToolbarPresenter extends JToggleButton { + + public ToolbarPresenter() { + super(AbstractRouterAction.this); + setText(null); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ColorAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ColorAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,226 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.graph.CfgEventListener; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.image.BufferedImage; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.SwingConstants; +import javax.swing.plaf.basic.BasicArrowButton; +import org.openide.util.HelpCtx; +import org.openide.util.actions.Presenter; + +/** + * Changes the background color of a node. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class ColorAction extends AbstractCfgEditorAction implements Presenter.Menu, Presenter.Popup, Presenter.Toolbar { + + public static final int IMAGE_WIDTH = 16; + public static final int IMAGE_HEIGHT = 16; + + + /** Names of colors shown in color select lists. */ + private static final String[] COLOR_NAMES = {"White", "Light Gray", "Dark Gray", "Light Yellow", "Dark Yellow", "Light Green", "Dark Green", "Light Cyan", "Dark Cyan", "Light Blue", "Dark Blue", "Light Magenta", "Dark Magenta", "Light Red", "Dark Red"}; + + /** Values of colors shown in color select lists. */ + private static final Color[] COLORS = { + new Color(0xFFFFFF), new Color(0xD4D0C8), new Color(0xA4A098), new Color(0xF0F0B0), new Color(0xE0E040), + new Color(0xB0F0B0), new Color(0x40E040), new Color(0xB0F0F0), new Color(0x40E0E0), new Color(0xB0B0F0), + new Color(0x4040E0), new Color(0xF0B0F0), new Color(0xE040E0), new Color(0xF0B0B0), new Color(0xE04040) + }; + + public void performAction() { + // nothing to do here, the presenters are supposed to call + // performAction(Color) + } + + protected void performAction(Color color) { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + tc.getCfgScene().setSelectedNodesColor(color); + } + } + + public String getName() { + return "Change NodeColor"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/color.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public JMenuItem getMenuPresenter() { + return new MenuPresenter(); + } + + @Override + public JMenuItem getPopupPresenter() { + return new MenuPresenter(); + } + + @Override + public JComponent getToolbarPresenter() { + return new ToolbarPresenter(); + } + + class MenuPresenter extends JMenu { + + public MenuPresenter() { + super(ColorAction.this); + initGUI(); + } + + protected void initGUI() { + CfgEditorTopComponent tc = getEditor(); + if( tc != null && tc.getCfgScene().getSelectedNodes().size()==0) { + //no node selected + setEnabled(false); + } else { + add(new SetColorAction(null, "Automatic")); + for (int i = 0; i < COLORS.length; i++) { + add(new SetColorAction(COLORS[i], COLOR_NAMES[i])); + } + } + } + } + + class ToolbarPresenter extends JButton implements CfgEventListener, MouseListener { + + final int arrowSize = 5; + final int arrowMargin = 3; + JPopupMenu popup; + + public ToolbarPresenter() { + setIcon(createIcon()); + setToolTipText(ColorAction.this.getName()); + + popup = new JPopupMenu(); + popup.add(new SetColorAction(null, "Automatic")); + for (int i = 0; i < COLORS.length; i++) { + popup.add(new SetColorAction(COLORS[i], COLOR_NAMES[i])); + } + addMouseListener(this); + } + + public Icon createIcon() { + BasicArrowButton arrow = new BasicArrowButton(SwingConstants.SOUTH); + BufferedImage img = new BufferedImage(IMAGE_WIDTH + arrowSize + 2 * arrowMargin, IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB); + Graphics g = img.getGraphics(); + ColorAction.this.getIcon().paintIcon(this, g, 0, 0); + arrow.paintTriangle(g, IMAGE_WIDTH + arrowMargin + arrowSize / 2, IMAGE_HEIGHT / 2 - arrowSize / 2, arrowSize, SwingConstants.SOUTH, true); + return new ImageIcon(img); + } + + + public void selectionChanged(CfgScene scene) { + Set nodes = scene.getSelectedNodes(); + setEnabled(nodes.size() > 0); + } + + public void mouseClicked(MouseEvent e) { + if (e.getX() < getInsets().left + IMAGE_WIDTH + arrowMargin) { + performAction(null); + } else { + popup.show(this, 0, getSize().height); + } + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseReleased(MouseEvent e) { + } + } + + protected Icon createIcon(Color color) { + if (color == null) { + return ColorAction.this.getIcon(); + } else { + return new ColorIcon(color); + } + } + + class ColorIcon implements Icon { + + Color color; + + public ColorIcon(Color color) { + this.color = color; + } + + public int getIconWidth() { + return IMAGE_WIDTH; + } + + public int getIconHeight() { + return IMAGE_HEIGHT; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Color oldColor = g.getColor(); + g.setColor(color); + g.fillRect(x, y, IMAGE_WIDTH, IMAGE_HEIGHT); + g.setColor(oldColor); + } + } + + class SetColorAction extends AbstractAction { + + Color color; + String name; + Icon icon; + + public SetColorAction(Color color, String name) { + super(name, createIcon(color)); + this.color = color; + this.name = name; + icon = (Icon) getValue(AbstractAction.SMALL_ICON); + } + + public Color getColor() { + return color; + } + + public String getName() { + return name; + } + + public Icon getIcon() { + return icon; + } + + public void actionPerformed(ActionEvent e) { + performAction(color); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ExportAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ExportAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,122 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.io.File; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileNameExtensionFilter; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.util.HelpCtx; + +/** + * Exports Scene to various Graphics Formats + * + * @author Rumpfhuber Stefan + */ +public class ExportAction extends AbstractCfgEditorAction { + + public static final String DESCRIPTION_SVG = "Scaleable Vector Format (.svg)"; + public static final String DESCRIPTION_EMF = "Extended Meta File (.emf)"; + public static final String DESCRIPTION_GIF = "Graphics Interchange Format (.gif)"; + public static final String EXT_GIF = "gif", EXT_EMF = "emf", EXT_SVG = "svg"; + + String lastDirectory = null; + + @Override + public void performAction() { + CfgEditorTopComponent tc = this.getEditor(); + CfgScene scene = tc.getCfgScene(); + JComponent view = scene.getView(); + + JFileChooser chooser = new JFileChooser (); + chooser.setAcceptAllFileFilterUsed(false); + chooser.setDialogTitle (getName()); + chooser.setDialogType (JFileChooser.SAVE_DIALOG); + chooser.setMultiSelectionEnabled (false); + chooser.setFileSelectionMode (JFileChooser.FILES_ONLY); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_SVG, EXT_SVG)); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_EMF, EXT_EMF)); + chooser.addChoosableFileFilter(new FileNameExtensionFilter(DESCRIPTION_GIF, EXT_GIF)); + if(lastDirectory != null) + chooser.setCurrentDirectory(new File(lastDirectory)); + chooser.setSelectedFile(new File(tc.getName())); + + + if (chooser.showSaveDialog (tc) != JFileChooser.APPROVE_OPTION) + return; + + File file = chooser.getSelectedFile (); + + if(file == null) + return; + + FileNameExtensionFilter filter = (FileNameExtensionFilter) chooser.getFileFilter(); + String fn = file.getAbsolutePath().toLowerCase(); + String ext = filter.getExtensions()[0]; + if(!fn.endsWith("." + ext)){ + file = new File( file.getParentFile(), file.getName() + "." + ext); + } + + if (file.exists ()) { + DialogDescriptor descriptor = new DialogDescriptor ( + "File (" + file.getAbsolutePath () + ") already exists. Do you want to overwrite it?", + "File Exists", true, DialogDescriptor.YES_NO_OPTION, DialogDescriptor.NO_OPTION, null); + DialogDisplayer.getDefault ().createDialog (descriptor).setVisible (true); + if (descriptor.getValue () != DialogDescriptor.YES_OPTION) + return; + } + + lastDirectory = chooser.getCurrentDirectory().getAbsolutePath(); + + /*if(ext.equals(EXT_SVG)){ + SVGGraphics2D g; + try { + g = new SVGGraphics2D(file, scene.getBounds().getSize()); + g.startExport(); + scene.paint(g); + g.endExport(); + } catch(Exception ex){ + } + } else if (ext.equals(EXT_EMF)) { + EMFGraphics2D g; + try { + g = new EMFGraphics2D(file, scene.getBounds().getSize()); + g.startExport(); + scene.paint(g); + g.endExport(); + } catch(Exception ex){ + } + } else if (ext.equals(EXT_GIF)) { + GIFGraphics2D g; + try { + //use the view as image source to get a image with the current zoomfactor + //using the scene.paint() would always return a image with zoomfactor 1.0 + g = new GIFGraphics2D(file, view); + g.startExport(); + view.print(g); + g.endExport(); + } catch(Exception ex){ + } + } */ + // TODO(tw): Add SVG export. + } + + + @Override + public String getName() { + return "Export CFG"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/disk.gif"; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HideEdgesAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HideEdgesAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,52 @@ +package at.ssw.visualizer.cfg.action; + + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import org.openide.util.HelpCtx; + +/** + * Hides all edges connected to the selected node. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class HideEdgesAction extends AbstractCfgEditorAction { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + tc.getCfgScene().setSelectedEdgesVisibility(false); + } + } + + public String getName() { + return "Hide Edges"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/hideedges.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public void selectionChanged(CfgScene scene) { + for (CfgNode n : scene.getSelectedNodes()) { + for (CfgEdge e : scene.findNodeEdges(n, true, true) ){ + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(ew.isVisible()) { + setEnabled(true); + return; + } + } + } + setEnabled(false); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalCompoundLayoutAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalCompoundLayoutAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,35 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +public class HierarchicalCompoundLayoutAction extends AbstractCfgEditorAction { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT); + scene.applyLayout(); + } + } + + public String getName() { + return "Hierarchical Compound Layout"; + } + + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/arrangeloop.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalNodeLayoutAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalNodeLayoutAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,35 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +public class HierarchicalNodeLayoutAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT); + scene.applyLayout(); + } + } + + public String getName() { + return "Hierarchical Node Layout"; + } + + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/arrangehier.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowAllAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowAllAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,40 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +/** + * Adjusts the Zoom factor of the Scene to the bounds of Scroll panel + * to get a clean view on the whole graph. + * + */ +public class ShowAllAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.zoomScene(); + + } + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public String getName() { + return "Fit Scene to Window"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/autosize.gif"; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowCFGEditorAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowCFGEditorAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,60 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorSupport; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.icons.Icons; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.actions.CookieAction; +import org.openide.windows.TopComponent; + +/** + * Shows the CFG visualizer for the currently selected compilation. + * + * @author Bernhard Stiftner + * @author Christian Wimmer + */ +public final class ShowCFGEditorAction extends CookieAction { + + protected void performAction(Node[] activatedNodes) { + ControlFlowGraph cfg = activatedNodes[0].getLookup().lookup(ControlFlowGraph.class); + CfgEditorSupport editor = new CfgEditorSupport(cfg); + editor.open(); + } + + @Override + protected boolean enable(Node[] activatedNodes) { + if (!super.enable(activatedNodes)) { + return false; + } + ControlFlowGraph cfg = activatedNodes[0].getLookup().lookup(ControlFlowGraph.class); + return cfg.getBasicBlocks().size() > 0; + } + + public String getName() { + return "Open Control Flow Graph"; + } + + @Override + protected String iconResource() { + return Icons.CFG; + } + + protected int mode() { + return CookieAction.MODE_EXACTLY_ONE; + } + + protected Class[] cookieClasses() { + return new Class[]{ControlFlowGraph.class}; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + protected boolean asynchronous() { + return false; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowEdgesAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowEdgesAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,52 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import org.openide.util.HelpCtx; + +/** + * Shows all edges connected to the selected node. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class ShowEdgesAction extends AbstractCfgEditorAction { + + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + tc.getCfgScene().setSelectedEdgesVisibility(true); + } + } + + public String getName() { + return "Show edges"; + } + + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/showedges.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + @Override + public void selectionChanged(CfgScene scene) { + for (CfgNode n : scene.getSelectedNodes()) { + for (CfgEdge e : scene.findNodeEdges(n, true, true) ){ + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!ew.isVisible()) { + setEnabled(true); + return; + } + } + } + setEnabled(false); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/SwitchLoopClustersAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/SwitchLoopClustersAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,66 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import javax.swing.JComponent; +import javax.swing.JToggleButton; +import org.openide.util.HelpCtx; +import org.openide.util.actions.Presenter; + +public class SwitchLoopClustersAction extends AbstractCfgEditorAction implements Presenter.Toolbar { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + boolean visible = scene.isLoopClusterVisible(); + scene.setLoopWidgets(!visible); + } + } + + @Override + public String getName() { + return "Enable/Disable Loop Clusters"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/cluster.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + + @Override + public JComponent getToolbarPresenter() { + return new ToolbarPresenter(); + } + + class ToolbarPresenter extends JToggleButton { + private static final String TOOLTIP_ENABLE = "Enable LoopClusters"; + private static final String TOOLTIP_DISABLE = "Disable LoopClusters"; + + public ToolbarPresenter() { + super(SwitchLoopClustersAction.this); + setText(null); + this.setToolTipText(TOOLTIP_DISABLE); + this.setSelected(true); + + this.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if(isSelected()){ + setToolTipText(TOOLTIP_DISABLE); + } else { + setToolTipText(TOOLTIP_ENABLE); + } + } + }); + } + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/UseBezierRouterAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/UseBezierRouterAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,29 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import org.openide.util.HelpCtx; + + +public class UseBezierRouterAction extends AbstractRouterAction { + + @Override + protected void setLinkRouter(CfgEditorTopComponent editor) { + editor.getCfgScene().setRouter(CfgEditorContext.ROUTING_BEZIER); + } + + @Override + public String getName() { + return "Use Bezier Router"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/bezierrouter.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/UseDirectLineRouterAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/UseDirectLineRouterAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,28 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import org.openide.util.HelpCtx; + + +public class UseDirectLineRouterAction extends AbstractRouterAction { + + @Override + protected void setLinkRouter(CfgEditorTopComponent editor) { + editor.getCfgScene().setRouter(CfgEditorContext.ROUTING_DIRECTLINES); + } + + @Override + public String getName() { + return "User Direct Router"; + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/fanrouter.gif"; + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ZoominAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ZoominAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,33 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + + +public class ZoominAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.animateZoom(1.1); + } + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/zoomin.gif"; + } + + @Override + public String getName() { + return "Zoomin"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ZoomoutAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ZoomoutAction.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,33 @@ +package at.ssw.visualizer.cfg.action; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.CfgScene; +import org.openide.util.HelpCtx; + +public class ZoomoutAction extends AbstractCfgEditorAction { + + @Override + public void performAction() { + CfgEditorTopComponent tc = getEditor(); + if (tc != null) { + CfgScene scene = tc.getCfgScene(); + scene.animateZoom(0.9); + } + } + + @Override + protected String iconResource() { + return "at/ssw/visualizer/cfg/icons/zoomout.gif"; + } + + @Override + public String getName() { + return "Zoomout"; + } + + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 110 +/svn/c1visualizer~svn/!svn/ver/184/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/editor +END +CfgEditorSupport.java +K 25 +svn:wc:ra_dav:version-url +V 132 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/editor/CfgEditorSupport.java +END +CfgEditorTopComponent.java +K 25 +svn:wc:ra_dav:version-url +V 137 +/svn/c1visualizer~svn/!svn/ver/184/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/editor/CfgEditorTopComponent.java +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,96 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/editor +https://svn.java.net/svn/c1visualizer~svn + + + +2010-06-09T00:03:59.100332Z +184 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +CfgEditorSupport.java +file + + + + +2012-01-28T15:08:36.568098Z +456c7bd648c4eb8469736f062aa84589 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +2372 + +CfgEditorTopComponent.java +file + + + + +2012-01-28T15:08:36.570098Z +df7b7480f08c83b8c322972f004f04dd +2010-06-09T00:03:59.100332Z +184 +ChristianW + + + + + + + + + + + + + + + + + + + + + +10693 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorSupport.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorSupport.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,77 @@ +package at.ssw.visualizer.cfg.editor; + +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; +import java.io.IOException; +import org.openide.cookies.OpenCookie; +import org.openide.windows.CloneableOpenSupport; +import org.openide.windows.CloneableTopComponent; + + +public class CfgEditorSupport extends CloneableOpenSupport implements OpenCookie { + private ControlFlowGraph cfg; + + public CfgEditorSupport(ControlFlowGraph cfg) { + super(new Env()); + ((Env) env).editorSupport = this; + this.cfg = cfg; + } + + protected CloneableTopComponent createCloneableTopComponent() { + return new CfgEditorTopComponent(cfg); + } + + public String messageOpened() { + return "Opened " + cfg.getCompilation().getMethod() + " - " + cfg.getName(); + } + + public String messageOpening() { + return "Opening " + cfg.getCompilation().getMethod() + " - " + cfg.getName(); + } + + + public static class Env implements CloneableOpenSupport.Env { + private PropertyChangeSupport prop = new PropertyChangeSupport(this); + private VetoableChangeSupport veto = new VetoableChangeSupport(this); + private CfgEditorSupport editorSupport; + + public boolean isValid() { + return true; + } + + public boolean isModified() { + return false; + } + + public void markModified() throws IOException { + throw new IOException("Editor is readonly"); + } + + public void unmarkModified() { + // Nothing to do. + } + + public CloneableOpenSupport findCloneableOpenSupport() { + return editorSupport; + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + prop.addPropertyChangeListener(l); + } + + public void removePropertyChangeListener(PropertyChangeListener l) { + prop.removePropertyChangeListener(l); + } + + public void addVetoableChangeListener(VetoableChangeListener l) { + veto.addVetoableChangeListener(l); + } + + public void removeVetoableChangeListener(VetoableChangeListener l) { + veto.removeVetoableChangeListener(l); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorSupport.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorSupport.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,77 @@ +package at.ssw.visualizer.cfg.editor; + +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; +import java.io.IOException; +import org.openide.cookies.OpenCookie; +import org.openide.windows.CloneableOpenSupport; +import org.openide.windows.CloneableTopComponent; + + +public class CfgEditorSupport extends CloneableOpenSupport implements OpenCookie { + private ControlFlowGraph cfg; + + public CfgEditorSupport(ControlFlowGraph cfg) { + super(new Env()); + ((Env) env).editorSupport = this; + this.cfg = cfg; + } + + protected CloneableTopComponent createCloneableTopComponent() { + return new CfgEditorTopComponent(cfg); + } + + public String messageOpened() { + return "Opened " + cfg.getCompilation().getMethod() + " - " + cfg.getName(); + } + + public String messageOpening() { + return "Opening " + cfg.getCompilation().getMethod() + " - " + cfg.getName(); + } + + + public static class Env implements CloneableOpenSupport.Env { + private PropertyChangeSupport prop = new PropertyChangeSupport(this); + private VetoableChangeSupport veto = new VetoableChangeSupport(this); + private CfgEditorSupport editorSupport; + + public boolean isValid() { + return true; + } + + public boolean isModified() { + return false; + } + + public void markModified() throws IOException { + throw new IOException("Editor is readonly"); + } + + public void unmarkModified() { + // Nothing to do. + } + + public CloneableOpenSupport findCloneableOpenSupport() { + return editorSupport; + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + prop.addPropertyChangeListener(l); + } + + public void removePropertyChangeListener(PropertyChangeListener l) { + prop.removePropertyChangeListener(l); + } + + public void addVetoableChangeListener(VetoableChangeListener l) { + veto.addVetoableChangeListener(l); + } + + public void removeVetoableChangeListener(VetoableChangeListener l) { + veto.removeVetoableChangeListener(l); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorTopComponent.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorTopComponent.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,260 @@ +package at.ssw.visualizer.cfg.editor; + +import at.ssw.visualizer.cfg.action.ShowAllAction; +import at.ssw.visualizer.cfg.action.ColorAction; +import at.ssw.visualizer.cfg.action.ExportAction; +import at.ssw.visualizer.cfg.action.HideEdgesAction; +import at.ssw.visualizer.cfg.action.HierarchicalCompoundLayoutAction; +import at.ssw.visualizer.cfg.action.HierarchicalNodeLayoutAction; +import at.ssw.visualizer.cfg.action.ShowEdgesAction; +import at.ssw.visualizer.cfg.action.SwitchLoopClustersAction; +import at.ssw.visualizer.cfg.action.UseBezierRouterAction; +import at.ssw.visualizer.cfg.action.UseDirectLineRouterAction; +import at.ssw.visualizer.cfg.action.ZoominAction; +import at.ssw.visualizer.cfg.action.ZoomoutAction; +import at.ssw.visualizer.cfg.graph.CfgEventListener; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.graph.NodeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.preferences.FlagsSetting; +import javax.swing.ScrollPaneConstants; +import at.ssw.visualizer.core.selection.Selection; +import at.ssw.visualizer.core.selection.SelectionManager; +import at.ssw.visualizer.core.selection.SelectionProvider; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.awt.BorderLayout; +import java.awt.Color; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JToggleButton; +import javax.swing.UIManager; +import javax.swing.border.Border; +import org.netbeans.api.visual.widget.Widget; +import org.openide.awt.Toolbar; +import org.openide.util.ImageUtilities; +import org.openide.windows.CloneableTopComponent; +import org.openide.windows.TopComponent; +import org.openide.util.actions.SystemAction; + +public class CfgEditorTopComponent extends CloneableTopComponent implements PropertyChangeListener, SelectionProvider { + + private CfgScene scene; + private JScrollPane jScrollPane; + private ControlFlowGraph cfg; + private JComponent myView; + private Selection selection; + + public CfgEditorTopComponent(ControlFlowGraph cfg) { + this.cfg = cfg; + + setIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg.gif")); + setName(cfg.getParent().getShortName()); + setToolTipText(cfg.getCompilation().getMethod() + " - " + cfg.getName()); + + //panel setup + this.jScrollPane = new JScrollPane(); + this.jScrollPane.setOpaque(true); + this.jScrollPane.setBorder(BorderFactory.createEmptyBorder()); + this.jScrollPane.setViewportBorder(BorderFactory.createEmptyBorder()); + this.scene = new CfgScene(this); + this.myView = scene.createView(); + this.jScrollPane.setViewportView(myView); + this.setLayout(new BorderLayout()); + this.add(createToolbar(), BorderLayout.NORTH); + this.add(jScrollPane, BorderLayout.CENTER); + jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + jScrollPane.getVerticalScrollBar().setEnabled(true); + jScrollPane.getHorizontalScrollBar().setEnabled(true); + + //setup enviroment,register listeners + selection = new Selection(); + selection.put(cfg); + selection.put(scene); + selection.addChangeListener(scene); + + scene.validate(); + scene.applyLayout(); + } + + public Selection getSelection() { + return selection; + } + + public ControlFlowGraph getCfg() { + return cfg; + } + + public JScrollPane getJScrollPanel() { + return jScrollPane; + } + + public CfgScene getCfgScene() { + return scene; + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER; + } + + @Override + protected void componentOpened() { + super.componentOpened(); + CfgPreferences.getInstance().addPropertyChangeListener(this); + } + + @Override + protected void componentActivated() { + super.componentActivated(); + SelectionManager.getDefault().setSelection(selection); + this.getCfgScene().updateGlobalSelection(); + this.getCfgScene().fireSelectionChanged(); + } + + @Override + protected void componentClosed() { + super.componentClosed(); + SelectionManager.getDefault().removeSelection(selection); + CfgPreferences.getInstance().removePropertyChangeListener(this); + } + + @Override + protected CloneableTopComponent createClonedObject() { + CfgEditorTopComponent component = new CfgEditorTopComponent(cfg); + component.setActivatedNodes(getActivatedNodes()); + return component; + } + + public void propertyChange(PropertyChangeEvent evt) { + if (this.scene != null) { + + String propName = evt.getPropertyName(); + CfgPreferences prefs = CfgPreferences.getInstance(); + if (propName.equals(CfgPreferences.PROP_BACKGROUND_COLOR)) { + scene.setBackground(prefs.getBackgroundColor()); + scene.revalidate(); + } else if (propName.equals(CfgPreferences.PROP_NODE_COLOR)) { + for (NodeWidget nw : scene.getNodeWidgets()) { + //only change the node color if its not a custom color + if (!nw.isNodeColorCustomized()) { + nw.setNodeColor(prefs.getNodeColor(), false); + } + } + } else if (propName.equals(CfgPreferences.PROP_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (!e.isBackEdge() && !e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getEdgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_BACK_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (e.isBackEdge()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getBackedgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getExceptionEdgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_BORDER_COLOR)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setBorderColor(prefs.getBorderColor()); + } + } else if (propName.equals(CfgPreferences.PROP_TEXT_FONT)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.adjustFont(prefs.getTextFont()); + } + } else if (propName.equals(CfgPreferences.PROP_TEXT_COLOR)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setForeground(prefs.getTextColor()); + } + } else if (propName.equals(CfgPreferences.PROP_FLAGS)) { + FlagsSetting fs = CfgPreferences.getInstance().getFlagsSetting(); + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + Color nodeColor = fs.getColor(n.getBasicBlock().getFlags()); + if (nodeColor != null) { + nw.setNodeColor(nodeColor, true); + } else { + nw.setNodeColor(CfgPreferences.getInstance().getNodeColor(), false); + } + } + } else if (propName.equals(CfgPreferences.PROP_SELECTION_COLOR_BG) || propName.equals(CfgPreferences.PROP_SELECTION_COLOR_FG)) { + for (CfgNode n : scene.getNodes()) { + Widget w = scene.findWidget(n); + w.revalidate(); + } + } + scene.validate(); + } + + } + + private Toolbar createToolbar() { + Toolbar tb = new Toolbar("CfgToolbar"); + + tb.setBorder((Border) UIManager.get("Nb.Editor.Toolbar.border")); + + //zoomin/zoomout buttons + tb.add(SystemAction.get(ZoominAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(ZoomoutAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //router buttons + ButtonGroup routerButtons = new ButtonGroup(); + UseDirectLineRouterAction direct = SystemAction.get(UseDirectLineRouterAction.class); + UseBezierRouterAction bezier = SystemAction.get(UseBezierRouterAction.class); + JToggleButton button = (JToggleButton) direct.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + button.setSelected(true); + tb.add(button); + button = (JToggleButton) bezier.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + tb.add(button); + tb.addSeparator(); + + //layout buttons + tb.add(SystemAction.get(HierarchicalNodeLayoutAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HierarchicalCompoundLayoutAction.class).getToolbarPresenter()); + + tb.addSeparator(); + tb.add(SystemAction.get(ShowAllAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //cluster button + tb.add(SystemAction.get(SwitchLoopClustersAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //show/hide edge button + tb.add(SystemAction.get(ShowEdgesAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HideEdgesAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //color button + JComponent colorButton = SystemAction.get(ColorAction.class).getToolbarPresenter(); + getCfgScene().addCfgEventListener((CfgEventListener) colorButton); + tb.add(colorButton); + + //export button + tb.add(SystemAction.get(ExportAction.class).getToolbarPresenter()); + tb.doLayout(); + + return tb; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorTopComponent.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/.svn/text-base/CfgEditorTopComponent.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,260 @@ +package at.ssw.visualizer.cfg.editor; + +import at.ssw.visualizer.cfg.action.ShowAllAction; +import at.ssw.visualizer.cfg.action.ColorAction; +import at.ssw.visualizer.cfg.action.ExportAction; +import at.ssw.visualizer.cfg.action.HideEdgesAction; +import at.ssw.visualizer.cfg.action.HierarchicalCompoundLayoutAction; +import at.ssw.visualizer.cfg.action.HierarchicalNodeLayoutAction; +import at.ssw.visualizer.cfg.action.ShowEdgesAction; +import at.ssw.visualizer.cfg.action.SwitchLoopClustersAction; +import at.ssw.visualizer.cfg.action.UseBezierRouterAction; +import at.ssw.visualizer.cfg.action.UseDirectLineRouterAction; +import at.ssw.visualizer.cfg.action.ZoominAction; +import at.ssw.visualizer.cfg.action.ZoomoutAction; +import at.ssw.visualizer.cfg.graph.CfgEventListener; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.graph.NodeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.preferences.FlagsSetting; +import javax.swing.ScrollPaneConstants; +import at.ssw.visualizer.core.selection.Selection; +import at.ssw.visualizer.core.selection.SelectionManager; +import at.ssw.visualizer.core.selection.SelectionProvider; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.awt.BorderLayout; +import java.awt.Color; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JToggleButton; +import javax.swing.UIManager; +import javax.swing.border.Border; +import org.netbeans.api.visual.widget.Widget; +import org.openide.awt.Toolbar; +import org.openide.util.ImageUtilities; +import org.openide.windows.CloneableTopComponent; +import org.openide.windows.TopComponent; +import org.openide.util.actions.SystemAction; + +public class CfgEditorTopComponent extends CloneableTopComponent implements PropertyChangeListener, SelectionProvider { + + private CfgScene scene; + private JScrollPane jScrollPane; + private ControlFlowGraph cfg; + private JComponent myView; + private Selection selection; + + public CfgEditorTopComponent(ControlFlowGraph cfg) { + this.cfg = cfg; + + setIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg.gif")); + setName(cfg.getParent().getShortName()); + setToolTipText(cfg.getCompilation().getMethod() + " - " + cfg.getName()); + + //panel setup + this.jScrollPane = new JScrollPane(); + this.jScrollPane.setOpaque(true); + this.jScrollPane.setBorder(BorderFactory.createEmptyBorder()); + this.jScrollPane.setViewportBorder(BorderFactory.createEmptyBorder()); + this.scene = new CfgScene(this); + this.myView = scene.createView(); + this.jScrollPane.setViewportView(myView); + this.setLayout(new BorderLayout()); + this.add(createToolbar(), BorderLayout.NORTH); + this.add(jScrollPane, BorderLayout.CENTER); + jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + jScrollPane.getVerticalScrollBar().setEnabled(true); + jScrollPane.getHorizontalScrollBar().setEnabled(true); + + //setup enviroment,register listeners + selection = new Selection(); + selection.put(cfg); + selection.put(scene); + selection.addChangeListener(scene); + + scene.validate(); + scene.applyLayout(); + } + + public Selection getSelection() { + return selection; + } + + public ControlFlowGraph getCfg() { + return cfg; + } + + public JScrollPane getJScrollPanel() { + return jScrollPane; + } + + public CfgScene getCfgScene() { + return scene; + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER; + } + + @Override + protected void componentOpened() { + super.componentOpened(); + CfgPreferences.getInstance().addPropertyChangeListener(this); + } + + @Override + protected void componentActivated() { + super.componentActivated(); + SelectionManager.getDefault().setSelection(selection); + this.getCfgScene().updateGlobalSelection(); + this.getCfgScene().fireSelectionChanged(); + } + + @Override + protected void componentClosed() { + super.componentClosed(); + SelectionManager.getDefault().removeSelection(selection); + CfgPreferences.getInstance().removePropertyChangeListener(this); + } + + @Override + protected CloneableTopComponent createClonedObject() { + CfgEditorTopComponent component = new CfgEditorTopComponent(cfg); + component.setActivatedNodes(getActivatedNodes()); + return component; + } + + public void propertyChange(PropertyChangeEvent evt) { + if (this.scene != null) { + + String propName = evt.getPropertyName(); + CfgPreferences prefs = CfgPreferences.getInstance(); + if (propName.equals(CfgPreferences.PROP_BACKGROUND_COLOR)) { + scene.setBackground(prefs.getBackgroundColor()); + scene.revalidate(); + } else if (propName.equals(CfgPreferences.PROP_NODE_COLOR)) { + for (NodeWidget nw : scene.getNodeWidgets()) { + //only change the node color if its not a custom color + if (!nw.isNodeColorCustomized()) { + nw.setNodeColor(prefs.getNodeColor(), false); + } + } + } else if (propName.equals(CfgPreferences.PROP_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (!e.isBackEdge() && !e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getEdgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_BACK_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (e.isBackEdge()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getBackedgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getExceptionEdgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_BORDER_COLOR)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setBorderColor(prefs.getBorderColor()); + } + } else if (propName.equals(CfgPreferences.PROP_TEXT_FONT)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.adjustFont(prefs.getTextFont()); + } + } else if (propName.equals(CfgPreferences.PROP_TEXT_COLOR)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setForeground(prefs.getTextColor()); + } + } else if (propName.equals(CfgPreferences.PROP_FLAGS)) { + FlagsSetting fs = CfgPreferences.getInstance().getFlagsSetting(); + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + Color nodeColor = fs.getColor(n.getBasicBlock().getFlags()); + if (nodeColor != null) { + nw.setNodeColor(nodeColor, true); + } else { + nw.setNodeColor(CfgPreferences.getInstance().getNodeColor(), false); + } + } + } else if (propName.equals(CfgPreferences.PROP_SELECTION_COLOR_BG) || propName.equals(CfgPreferences.PROP_SELECTION_COLOR_FG)) { + for (CfgNode n : scene.getNodes()) { + Widget w = scene.findWidget(n); + w.revalidate(); + } + } + scene.validate(); + } + + } + + private Toolbar createToolbar() { + Toolbar tb = new Toolbar("CfgToolbar"); + + tb.setBorder((Border) UIManager.get("Nb.Editor.Toolbar.border")); + + //zoomin/zoomout buttons + tb.add(SystemAction.get(ZoominAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(ZoomoutAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //router buttons + ButtonGroup routerButtons = new ButtonGroup(); + UseDirectLineRouterAction direct = SystemAction.get(UseDirectLineRouterAction.class); + UseBezierRouterAction bezier = SystemAction.get(UseBezierRouterAction.class); + JToggleButton button = (JToggleButton) direct.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + button.setSelected(true); + tb.add(button); + button = (JToggleButton) bezier.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + tb.add(button); + tb.addSeparator(); + + //layout buttons + tb.add(SystemAction.get(HierarchicalNodeLayoutAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HierarchicalCompoundLayoutAction.class).getToolbarPresenter()); + + tb.addSeparator(); + tb.add(SystemAction.get(ShowAllAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //cluster button + tb.add(SystemAction.get(SwitchLoopClustersAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //show/hide edge button + tb.add(SystemAction.get(ShowEdgesAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HideEdgesAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //color button + JComponent colorButton = SystemAction.get(ColorAction.class).getToolbarPresenter(); + getCfgScene().addCfgEventListener((CfgEventListener) colorButton); + tb.add(colorButton); + + //export button + tb.add(SystemAction.get(ExportAction.class).getToolbarPresenter()); + tb.doLayout(); + + return tb; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/CfgEditorSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/CfgEditorSupport.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,77 @@ +package at.ssw.visualizer.cfg.editor; + +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; +import java.io.IOException; +import org.openide.cookies.OpenCookie; +import org.openide.windows.CloneableOpenSupport; +import org.openide.windows.CloneableTopComponent; + + +public class CfgEditorSupport extends CloneableOpenSupport implements OpenCookie { + private ControlFlowGraph cfg; + + public CfgEditorSupport(ControlFlowGraph cfg) { + super(new Env()); + ((Env) env).editorSupport = this; + this.cfg = cfg; + } + + protected CloneableTopComponent createCloneableTopComponent() { + return new CfgEditorTopComponent(cfg); + } + + public String messageOpened() { + return "Opened " + cfg.getName(); + } + + public String messageOpening() { + return "Opening " + cfg.getName(); + } + + + public static class Env implements CloneableOpenSupport.Env { + private PropertyChangeSupport prop = new PropertyChangeSupport(this); + private VetoableChangeSupport veto = new VetoableChangeSupport(this); + private CfgEditorSupport editorSupport; + + public boolean isValid() { + return true; + } + + public boolean isModified() { + return false; + } + + public void markModified() throws IOException { + throw new IOException("Editor is readonly"); + } + + public void unmarkModified() { + // Nothing to do. + } + + public CloneableOpenSupport findCloneableOpenSupport() { + return editorSupport; + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + prop.addPropertyChangeListener(l); + } + + public void removePropertyChangeListener(PropertyChangeListener l) { + prop.removePropertyChangeListener(l); + } + + public void addVetoableChangeListener(VetoableChangeListener l) { + veto.addVetoableChangeListener(l); + } + + public void removeVetoableChangeListener(VetoableChangeListener l) { + veto.removeVetoableChangeListener(l); + } + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/CfgEditorTopComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/editor/CfgEditorTopComponent.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,254 @@ +package at.ssw.visualizer.cfg.editor; + +import at.ssw.visualizer.cfg.action.ShowAllAction; +import at.ssw.visualizer.cfg.action.ColorAction; +import at.ssw.visualizer.cfg.action.ExportAction; +import at.ssw.visualizer.cfg.action.HideEdgesAction; +import at.ssw.visualizer.cfg.action.HierarchicalCompoundLayoutAction; +import at.ssw.visualizer.cfg.action.HierarchicalNodeLayoutAction; +import at.ssw.visualizer.cfg.action.ShowEdgesAction; +import at.ssw.visualizer.cfg.action.SwitchLoopClustersAction; +import at.ssw.visualizer.cfg.action.UseBezierRouterAction; +import at.ssw.visualizer.cfg.action.UseDirectLineRouterAction; +import at.ssw.visualizer.cfg.action.ZoominAction; +import at.ssw.visualizer.cfg.action.ZoomoutAction; +import at.ssw.visualizer.cfg.graph.CfgEventListener; +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.graph.EdgeWidget; +import at.ssw.visualizer.cfg.graph.NodeWidget; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.preferences.FlagsSetting; +import javax.swing.ScrollPaneConstants; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.awt.BorderLayout; +import java.awt.Color; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JToggleButton; +import javax.swing.UIManager; +import javax.swing.border.Border; +import org.netbeans.api.visual.widget.Widget; +import org.openide.awt.Toolbar; +import org.openide.util.ImageUtilities; +import org.openide.windows.CloneableTopComponent; +import org.openide.windows.TopComponent; +import org.openide.util.actions.SystemAction; + +public class CfgEditorTopComponent extends CloneableTopComponent implements PropertyChangeListener { + + private CfgScene scene; + private JScrollPane jScrollPane; + private ControlFlowGraph cfg; + private JComponent myView; + + public CfgEditorTopComponent(ControlFlowGraph cfg) { + this.cfg = cfg; + + setIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg.gif")); +// setName(cfg.getParent().getShortName()); +// setToolTipText(cfg.getCompilation().getMethod() + " - " + cfg.getName()); + // TODO(tw): Add title. + + //panel setup + this.jScrollPane = new JScrollPane(); + this.jScrollPane.setOpaque(true); + this.jScrollPane.setBorder(BorderFactory.createEmptyBorder()); + this.jScrollPane.setViewportBorder(BorderFactory.createEmptyBorder()); + this.scene = new CfgScene(this); + this.myView = scene.createView(); + this.jScrollPane.setViewportView(myView); + this.setLayout(new BorderLayout()); + this.add(createToolbar(), BorderLayout.NORTH); + this.add(jScrollPane, BorderLayout.CENTER); + jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + jScrollPane.getVerticalScrollBar().setEnabled(true); + jScrollPane.getHorizontalScrollBar().setEnabled(true); + + //setup enviroment,register listeners + // TODO(tw): Add to lookup. +// selection = new Selection(); +// selection.put(cfg); +// selection.put(scene); +// selection.addChangeListener(scene); + + scene.validate(); + scene.applyLayout(); + } + + public ControlFlowGraph getCfg() { + return cfg; + } + + public JScrollPane getJScrollPanel() { + return jScrollPane; + } + + public CfgScene getCfgScene() { + return scene; + } + + @Override + public int getPersistenceType() { + return TopComponent.PERSISTENCE_NEVER; + } + + @Override + protected void componentOpened() { + super.componentOpened(); + CfgPreferences.getInstance().addPropertyChangeListener(this); + } + + @Override + protected void componentActivated() { + super.componentActivated(); +// SelectionManager.getDefault().setSelection(selection); + this.getCfgScene().updateGlobalSelection(); + this.getCfgScene().fireSelectionChanged(); + } + + @Override + protected void componentClosed() { + super.componentClosed(); +// SelectionManager.getDefault().removeSelection(selection); + CfgPreferences.getInstance().removePropertyChangeListener(this); + } + + @Override + protected CloneableTopComponent createClonedObject() { + CfgEditorTopComponent component = new CfgEditorTopComponent(cfg); + component.setActivatedNodes(getActivatedNodes()); + return component; + } + + public void propertyChange(PropertyChangeEvent evt) { + if (this.scene != null) { + + String propName = evt.getPropertyName(); + CfgPreferences prefs = CfgPreferences.getInstance(); + if (propName.equals(CfgPreferences.PROP_BACKGROUND_COLOR)) { + scene.setBackground(prefs.getBackgroundColor()); + scene.revalidate(); + } else if (propName.equals(CfgPreferences.PROP_NODE_COLOR)) { + for (NodeWidget nw : scene.getNodeWidgets()) { + //only change the node color if its not a custom color + if (!nw.isNodeColorCustomized()) { + nw.setNodeColor(prefs.getNodeColor(), false); + } + } + } else if (propName.equals(CfgPreferences.PROP_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (!e.isBackEdge() && !e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getEdgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_BACK_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (e.isBackEdge()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getBackedgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR)) { + for (CfgEdge e : scene.getEdges()) { + if (e.isXhandler()) { + EdgeWidget w = (EdgeWidget) scene.findWidget(e); + w.setLineColor(prefs.getExceptionEdgeColor()); + } + } + } else if (propName.equals(CfgPreferences.PROP_BORDER_COLOR)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setBorderColor(prefs.getBorderColor()); + } + } else if (propName.equals(CfgPreferences.PROP_TEXT_FONT)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.adjustFont(prefs.getTextFont()); + } + } else if (propName.equals(CfgPreferences.PROP_TEXT_COLOR)) { + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + nw.setForeground(prefs.getTextColor()); + } + } else if (propName.equals(CfgPreferences.PROP_FLAGS)) { + FlagsSetting fs = CfgPreferences.getInstance().getFlagsSetting(); + for (CfgNode n : scene.getNodes()) { + NodeWidget nw = (NodeWidget) scene.findWidget(n); + Color nodeColor = fs.getColor(n.getBasicBlock().getFlags()); + if (nodeColor != null) { + nw.setNodeColor(nodeColor, true); + } else { + nw.setNodeColor(CfgPreferences.getInstance().getNodeColor(), false); + } + } + } else if (propName.equals(CfgPreferences.PROP_SELECTION_COLOR_BG) || propName.equals(CfgPreferences.PROP_SELECTION_COLOR_FG)) { + for (CfgNode n : scene.getNodes()) { + Widget w = scene.findWidget(n); + w.revalidate(); + } + } + scene.validate(); + } + + } + + private Toolbar createToolbar() { + Toolbar tb = new Toolbar("CfgToolbar"); + + tb.setBorder((Border) UIManager.get("Nb.Editor.Toolbar.border")); + + //zoomin/zoomout buttons + tb.add(SystemAction.get(ZoominAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(ZoomoutAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //router buttons + ButtonGroup routerButtons = new ButtonGroup(); + UseDirectLineRouterAction direct = SystemAction.get(UseDirectLineRouterAction.class); + UseBezierRouterAction bezier = SystemAction.get(UseBezierRouterAction.class); + JToggleButton button = (JToggleButton) direct.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + button.setSelected(true); + tb.add(button); + button = (JToggleButton) bezier.getToolbarPresenter(); + button.getModel().setGroup(routerButtons); + tb.add(button); + tb.addSeparator(); + + //layout buttons + tb.add(SystemAction.get(HierarchicalNodeLayoutAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HierarchicalCompoundLayoutAction.class).getToolbarPresenter()); + + tb.addSeparator(); + tb.add(SystemAction.get(ShowAllAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //cluster button + tb.add(SystemAction.get(SwitchLoopClustersAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //show/hide edge button + tb.add(SystemAction.get(ShowEdgesAction.class).getToolbarPresenter()); + tb.add(SystemAction.get(HideEdgesAction.class).getToolbarPresenter()); + tb.addSeparator(); + + //color button + JComponent colorButton = SystemAction.get(ColorAction.class).getToolbarPresenter(); + getCfgScene().addCfgEventListener((CfgEventListener) colorButton); + tb.add(colorButton); + + //export button + tb.add(SystemAction.get(ExportAction.class).getToolbarPresenter()); + tb.doLayout(); + + return tb; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,53 @@ +K 25 +svn:wc:ra_dav:version-url +V 109 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph +END +LoopClusterWidget.java +K 25 +svn:wc:ra_dav:version-url +V 132 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/LoopClusterWidget.java +END +CfgEventListener.java +K 25 +svn:wc:ra_dav:version-url +V 131 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/CfgEventListener.java +END +SymmetricAnchor.java +K 25 +svn:wc:ra_dav:version-url +V 130 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/SymmetricAnchor.java +END +EdgeWidget.java +K 25 +svn:wc:ra_dav:version-url +V 125 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/EdgeWidget.java +END +NodeWidget.java +K 25 +svn:wc:ra_dav:version-url +V 125 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/NodeWidget.java +END +SelectionWidget.java +K 25 +svn:wc:ra_dav:version-url +V 130 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/SelectionWidget.java +END +EdgeSwitchWidget.java +K 25 +svn:wc:ra_dav:version-url +V 131 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/EdgeSwitchWidget.java +END +CfgScene.java +K 25 +svn:wc:ra_dav:version-url +V 123 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/CfgScene.java +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,303 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph +https://svn.java.net/svn/c1visualizer~svn + + + +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +LoopClusterWidget.java +file + + + + +2012-01-28T15:08:36.049069Z +e959236dd4c38ba2cbcd39e3a180f0f3 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +3737 + +CfgEventListener.java +file + + + + +2012-01-28T15:08:36.052069Z +d6db075ad1e2ebb55ade2090130bcf30 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +261 + +SymmetricAnchor.java +file + + + + +2012-01-28T15:08:36.054069Z +f0fcc98a2e965834f80f13a6a41ce2d3 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +5545 + +EdgeWidget.java +file + + + + +2012-01-28T15:08:36.058069Z +ec8f2b7aaf91dd475b49c238ec1aa2ee +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +3286 + +NodeWidget.java +file + + + + +2012-01-28T15:08:36.060069Z +5d0a9294e18dbb15f9574a6026474a7e +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +6146 + +SelectionWidget.java +file + + + + +2012-01-28T15:08:36.063069Z +a384eb02341d2abf5b1e158cdd15583e +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1253 + +EdgeSwitchWidget.java +file + + + + +2012-01-28T15:08:36.066070Z +78914ff73d8d1d77436b2393bdcd3956 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +10335 + +layout +dir + +CfgScene.java +file + + + + +2012-01-28T15:08:36.069070Z +67afed83a8d263b695e7875d21c8a59c +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +33480 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/CfgEventListener.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/CfgEventListener.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,13 @@ +package at.ssw.visualizer.cfg.graph; + +import java.util.EventListener; + + +public interface CfgEventListener extends EventListener { + + /** + * the node or the edge selection got changed + */ + public void selectionChanged(CfgScene scene); + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/CfgScene.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/CfgScene.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,834 @@ +package at.ssw.visualizer.cfg.graph; + + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.action.ColorAction; +import at.ssw.visualizer.cfg.action.HideEdgesAction; +import at.ssw.visualizer.cfg.action.ShowEdgesAction; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalCompoundLayout; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalNodeLayout; +import at.ssw.visualizer.cfg.model.CfgEnv; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.visual.PolylineRouter; +import at.ssw.visualizer.cfg.visual.PolylineRouterV2; +import at.ssw.visualizer.cfg.visual.WidgetCollisionCollector; +import at.ssw.visualizer.core.selection.Selection; +import at.ssw.visualizer.core.selection.SelectionManager; +import at.ssw.visualizer.model.cfg.BasicBlock; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.MoveProvider; +import org.netbeans.api.visual.action.PopupMenuProvider; +import org.netbeans.api.visual.action.RectangularSelectDecorator; +import org.netbeans.api.visual.action.RectangularSelectProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.anchor.AnchorFactory; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.layout.LayoutFactory; +import org.netbeans.api.visual.layout.SceneLayout; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.router.Router.*; +import org.netbeans.api.visual.router.RouterFactory; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.LayerWidget; +import org.netbeans.api.visual.widget.Widget; +import org.openide.util.actions.SystemAction; + + +public class CfgScene extends GraphScene implements ChangeListener { + private LayerWidget mainLayer = new LayerWidget(this); + private LayerWidget connectionLayer = new LayerWidget(this); + private LayerWidget interractionLayer = new LayerWidget(this); + private LayerWidget clusterLayer = new LayerWidget(this); + private Set selectedNodes = Collections.emptySet(); + private Map loopidx2clusterwidget = new HashMap(); + private Map inputSwitches = new HashMap(); + private Map outputSwitches = new HashMap(); + private WidgetAction moveAction = ActionFactory.createMoveAction (ActionFactory.createFreeMoveStrategy(), this.createMoveProvider()); + private SceneLayout sceneLayout; + private CfgEnv env; + private int currentLayout=-1; + private int currentRouter=-1; + private CfgEditorTopComponent cfgtc; + private EventListenerList listenerList = new EventListenerList(); + private WidgetAction contextPopupAction = this.createContextMenuAction(this); + private List nodeWidgets=null; + private boolean loopClustersVisible = true; + + + public CfgScene(final CfgEditorTopComponent cfgtc){ + addChild(clusterLayer); + addChild(mainLayer); + addChild(interractionLayer); + addChild(connectionLayer); + this.loadDefaults(); + this.cfgtc=cfgtc; + this.loadModel(new CfgEnv(cfgtc.getCfg())); + this.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT);//default + this.getInputBindings().setZoomActionModifiers(0); + this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1)); + this.getActions().addAction(ActionFactory.createPanAction()); + this.getActions().addAction(ActionFactory.createRectangularSelectAction( + this.createSelectDecorator(this), + interractionLayer, + this.createRectangularSelectProvider()) + ); + this.getActions().addAction(this.contextPopupAction); + this.addSceneListener(createSceneListener(this)); + this.validate(); + } + + private void loadModel(CfgEnv cfgenv) { + this.env = cfgenv; + for(CfgNode n : env.getNodes()) { + addNode(n); + } + for(CfgEdge e : env.getEdges()) { + addEdge(e); + setEdgeSource(e, e.getSourceNode()); + setEdgeTarget(e, e.getTargetNode()); + } + this.stackLoops(cfgenv.getLoopMap()); + this.autoHideEdges(); + } + + public void loadDefaults() { + this.setRouter(CfgEditorContext.ROUTING_DIRECTLINES); + CfgPreferences prefs = CfgPreferences.getInstance(); + this.setBackground(prefs.getBackgroundColor()); + } + + //sets the parent Widget of all LoopClusterWidgets + private void stackLoops(Map map) { + this.clusterLayer.removeChildren(); + + Set cache = new HashSet(); + for(LoopInfo info : map.values()){ + if(cache.contains(info)) continue; + LoopClusterWidget widget = this.loopidx2clusterwidget.get(info.getLoopIndex()); + LoopInfo parent = info.getParent(); + while(parent != null){ + LoopClusterWidget parentWidget = this.loopidx2clusterwidget.get(parent.getLoopIndex()); + assert parentWidget != null; + if(widget.getParentWidget()!=null) + widget.removeFromParent(); + parentWidget.addChild(widget); + widget=parentWidget; + parent = parent.getParent(); + } + widget.removeFromParent(); + this.clusterLayer.addChild(widget);//parent == null => parent is clusterlayer + } + } + + //hide in|output edges + private void autoHideEdges(){ + for(CfgNode n : this.getNodes()){ + int fanin = n.getInputEdges().length; + int fanout = n.getOutputEdges().length; + if (fanin > CfgEditorContext.MAX_AUTOEDGESVISIBLE){ + assert(inputSwitches.containsKey(n)); + if(this.inputSwitches.containsKey(n)){ + EdgeSwitchWidget esw = this.inputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + if(fanout > CfgEditorContext.MAX_AUTOEDGESVISIBLE){ + if(this.outputSwitches.containsKey(n)){ + EdgeSwitchWidget esw = this.outputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + } + + } + + //apply current cfggraphscene layout + public void applyLayout(){ + this.sceneLayout.invokeLayoutImmediately(); + } + + //returns a Set with the currently selected Nodes + public Set getSelectedNodes() { + return Collections.unmodifiableSet(selectedNodes); + } + + + public Map getLoopidx2clusterwidget() { + return loopidx2clusterwidget; + } + + /** + * Sets the color of the currently selected Nodes + * If the supplied color is null the default color will be used + */ + public void setSelectedNodesColor(Color color) { + if(color == null) { //set default color + CfgPreferences prefs = CfgPreferences.getInstance(); + boolean customized=false; + for(CfgNode n : this.selectedNodes){ + color=null; + color = prefs.getFlagsSetting().getColor(n.getBasicBlock().getFlags()); + customized = (color!=null); + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor((customized) ? color : prefs.getNodeColor(), customized); + } + } else { + for(CfgNode n : this.selectedNodes){ + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor(color, true); + } + } + this.validate(); + } + + public void setSelectedEdgesVisibility(boolean visible) { + for(CfgNode n : this.selectedNodes){ + EdgeSwitchWidget in = this.inputSwitches.get(n); + EdgeSwitchWidget out = this.outputSwitches.get(n); + if(in != null) in.changeEdgeVisibility(visible); + if(out != null) out.changeEdgeVisibility(visible); + } + this.fireSelectionChanged(); + this.validate(); + } + + public EdgeSwitchWidget getInputSwitch(CfgNode n){ + return this.inputSwitches.get(n); + } + public EdgeSwitchWidget getOutputSwitch(CfgNode n){ + return this.outputSwitches.get(n); + } + + public CfgEnv getCfgEnv() { + return env; + } + + public boolean isLoopClusterVisible() { + return loopClustersVisible; + } + + public void setLoopWidgets(boolean visible) { + for(Widget w : this.loopidx2clusterwidget.values()){ + w.setVisible(visible); + w.revalidate(); + } + this.loopClustersVisible=visible; + this.validate(); + } + + public void setRouter(int newRouter){ + if(newRouter == this.currentRouter) return; + + this.currentRouter=newRouter; + + Router router; + + switch (newRouter) { + case CfgEditorContext.ROUTING_BEZIER: + router = new PolylineRouterV2(new WidgetCollisionCollector() { + public void collectCollisions(List collisions) { + collisions.addAll(getNodeWidgets()); + } + }); + break; + case CfgEditorContext.ROUTING_DIRECTLINES: + router = RouterFactory.createDirectRouter(); + break; + default: + throw new IllegalStateException ("Unknown Router ID: " + newRouter); // NOI18N + } + + for(CfgEdge e : this.getEdges()){ + EdgeWidget ew = (EdgeWidget) this.findWidget(e); + ew.setRouter(router); + } + this.validate(); + } + + + + public Collection getNodeWidgets() { + if(nodeWidgets != null && nodeWidgets.size()==this.getNodes().size()) return nodeWidgets; + + List widgets = new ArrayList(); + for(CfgNode n : this.getNodes()){ + NodeWidget w = (NodeWidget) this.findWidget(n); + widgets.add(w); + } + + nodeWidgets = Collections.unmodifiableList(widgets); + return widgets; + } + + + + public void setSceneLayout(int newLayout){ + + if(currentLayout == newLayout) return; + + GraphLayout graphLayout=null; + + switch (newLayout) { + case CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT: + graphLayout = new HierarchicalNodeLayout(this); + break; + + case CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT: + graphLayout = new HierarchicalCompoundLayout(this); + break; + } + + this.currentLayout=newLayout; + if(graphLayout != null) + this.sceneLayout=LayoutFactory.createSceneGraphLayout(this, graphLayout); + } + + + @Override + protected void attachEdgeSourceAnchor(CfgEdge edge, CfgNode oldSourceNode, CfgNode sourceNode) { + Anchor sourceAnchor; + EdgeWidget edgeWidget = (EdgeWidget) findWidget (edge); + Widget sourceWidget = findWidget(sourceNode); + + if (edge.isSymmetric()) { + sourceAnchor = new SymmetricAnchor(sourceWidget, true, true); + } else { + sourceAnchor = AnchorFactory.createRectangularAnchor(sourceWidget); + } + edgeWidget.setSourceAnchor (sourceAnchor); + } + + @Override + protected void attachEdgeTargetAnchor(CfgEdge edge, CfgNode oldtarget, CfgNode targetNode) { + Anchor targetAnchor; + ConnectionWidget edgeWidget = (ConnectionWidget) findWidget (edge); + Widget targetWidget = findWidget(targetNode); + + if (edge.isSymmetric()) { + targetAnchor = new SymmetricAnchor(targetWidget, true, false); + } else { + targetAnchor = AnchorFactory.createRectangularAnchor(targetWidget); + } + edgeWidget.setTargetAnchor (targetAnchor); + } + + + @Override + protected Widget attachEdgeWidget(CfgEdge edge) { + EdgeWidget widget = new EdgeWidget(this, edge); + connectionLayer.addChild(widget); + attachSourceSwitchWidget(edge); + attachTargetSwitchWidget(edge); + return widget; + } + + + + @Override + protected Widget attachNodeWidget(CfgNode node) { + this.nodeWidgets = null; + + NodeWidget nw = new NodeWidget(this,node); + WidgetAction.Chain actions = nw.getActions(); + actions.addAction(this.contextPopupAction); + actions.addAction(this.moveAction); + actions.addAction(this.createObjectHoverAction()); + + if ( node.isLoopMember() ) { + LoopClusterWidget loopWidget = this.attachLoopMember(node); + loopWidget.addMember(nw); + } + mainLayer.addChild(nw); + return nw; + } + + + private LoopClusterWidget attachLoopMember(CfgNode node) { + LoopClusterWidget lw = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if(lw == null) { + lw = new LoopClusterWidget(this, node.getLoopDepth(), node.getLoopIndex()); + this.loopidx2clusterwidget.put(node.getLoopIndex(), lw); + this.clusterLayer.addChild(lw); + } + return lw; + } + + + private boolean detachLoopMember(CfgNode node, NodeWidget nodeWidget) { + LoopClusterWidget rm = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if( rm == null) return false;//not added + + if ( rm.removeMember(nodeWidget) ) { + if(rm.getMembers().size() == 0){ + this.loopidx2clusterwidget.remove(rm.getLoopIndex()); + List childs = new ArrayList(rm.getChildren()); + for (Widget w : childs){//append stacked loopwidgets + w.removeFromParent(); + rm.getParentWidget().addChild(w); + } + rm.removeFromParent(); + } + return true; + } + return false; + } + + //this function is not invoked by any class of the module + //however to ensure that the edge switches are treatet corretly + //when a future version removes nodes it was implemented too. + + @Override + protected void detachNodeWidget(CfgNode node, Widget nodeWidget) { + if(node.isLoopMember() && nodeWidget instanceof NodeWidget ) { + this.detachLoopMember(node,(NodeWidget)nodeWidget); + } + super.detachNodeWidget(node, nodeWidget); + assert nodeWidget.getParentWidget()== null; + if(this.inputSwitches.containsKey(node)) { + EdgeSwitchWidget esw = this.inputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + if(this.outputSwitches.containsKey(node)){ + EdgeSwitchWidget esw = this.outputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + } + + protected EdgeSwitchWidget attachSourceSwitchWidget(CfgEdge e){ + CfgNode sourceNode = e.getSourceNode(); + NodeWidget sourceWidget = (NodeWidget) this.findWidget(sourceNode); + EdgeSwitchWidget out = outputSwitches.get(sourceNode); + if (out==null) { + out = new EdgeSwitchWidget(this, sourceWidget, true); + this.connectionLayer.addChild(out); + outputSwitches.put(sourceNode, out); + } + return out; + } + + + protected EdgeSwitchWidget attachTargetSwitchWidget(CfgEdge e){ + CfgNode targetNode = e.getTargetNode(); + NodeWidget targetWidget = (NodeWidget) this.findWidget(targetNode); + EdgeSwitchWidget in = inputSwitches.get(targetNode); + if (in==null) { + in = new EdgeSwitchWidget(this, targetWidget, false); + this.connectionLayer.addChild(in); + inputSwitches.put(targetNode, in); + } + return in; + } + + //resets the selection state of all NodeWidgets + private void cleanNodeSelection(){ + if( this.selectedNodes.size() != 0) { + this.userSelectionSuggested(Collections.emptySet(), false); + this.selectedNodes = Collections.emptySet(); + this.fireSelectionChanged(); + this.validate(); + } + } + + + //sets the scene & global node selection + public void setNodeSelection(Set newSelection){ + this.setSceneSelection(newSelection); + this.updateGlobalSelection(); + } + + //sets the scene selection + private void setSceneSelection(Set newSelection){ + if(newSelection.equals(selectedNodes)) return; + + this.selectedNodes=newSelection; + + Set selectedObjects = new HashSet(); + + for(CfgNode n : newSelection){ + selectedObjects.addAll(this.findNodeEdges(n, true, true)); + } + selectedObjects.addAll(newSelection); + + //if the selection gets updated from a change in the block view + //the scene will be centered + if(selectionUpdating) + this.centerSelection(); + + this.userSelectionSuggested(selectedObjects, false); + this.fireSelectionChanged(); + this.validate(); + } + + //updates selection of Block View + public void updateGlobalSelection() { + Selection selection = SelectionManager.getDefault().getCurSelection(); + ArrayList newBlocks = new ArrayList(); + for (CfgNode n : this.selectedNodes) { + newBlocks.add(n.getBasicBlock()); + } + BasicBlock[] curBlocks = newBlocks.toArray(new BasicBlock[newBlocks.size()]); + selection.put(curBlocks); + } + + private boolean selectionUpdating = false; + + //change of blockview selection + public void stateChanged(ChangeEvent event) { + if (selectionUpdating) { + return; + } + + selectionUpdating = true; + + Object source = event.getSource(); + if(source instanceof Selection){ + Selection selection=(Selection) source; + Set newSelection = new HashSet(); + BasicBlock[] newBlocks = selection.get(BasicBlock[].class); + if (newBlocks != null) { + for(BasicBlock b : newBlocks){ + for(CfgNode n : this.getNodes()){ + if(n.getBasicBlock() == b) newSelection.add(n); + } + } + this.setSceneSelection(newSelection); + } + } + selectionUpdating = false; + } + + //centers the viewport on the currently selected nodewidgets + private void centerSelection(){ + Point sceneCenter = null; + Collection nodes = this.selectedNodes; + if(nodes.size()==0) { + nodes = this.getNodes(); + } + + for(CfgNode n : nodes) { + if(sceneCenter==null) { + sceneCenter = this.findWidget(n).getLocation(); + continue; + } + Point location = this.findWidget(n).getLocation(); + sceneCenter.x = (location.x+sceneCenter.x)/2; + sceneCenter.y = (location.y+sceneCenter.y)/2; + } + + JComponent view = this.getView (); + if (view != null) { + Rectangle viewBounds = view.getVisibleRect (); + + Point viewCenter = this.convertSceneToView (sceneCenter); + + view.scrollRectToVisible (new Rectangle ( + viewCenter.x - viewBounds.width / 2, + viewCenter.y - viewBounds.height / 2, + viewBounds.width, + viewBounds.height + )); + } + } + + //animated scene Zoom to the max bounds of current viewport + public void zoomScene(){ + JScrollPane pane = this.cfgtc.getJScrollPanel(); + + Rectangle prefBounds = this.getPreferredBounds(); + Dimension viewDim = pane.getViewportBorderBounds().getSize(); + + double realwidth = (double)prefBounds.width*this.getZoomFactor(); + double realheight = (double)prefBounds.height*this.getZoomFactor(); + + double zoomX = (double)viewDim.width / realwidth; + double zoomY = (double)viewDim.height / realheight; + double zoomFactor = Math.min(zoomX, zoomY); + + this.animateZoom(zoomFactor*0.9); + } + + + //animated animateZoom function for scene animateZoom factor + public void animateZoom(double zoomfactor) { + this.getSceneAnimator().animateZoomFactor(this.getZoomFactor() * zoomfactor); + } + + public void addCfgEventListener(CfgEventListener l) { + listenerList.add(CfgEventListener.class, l); + } + + public void removeCfgEventListener(CfgEventListener l) { + listenerList.remove(CfgEventListener.class, l); + } + + public void fireSelectionChanged() { + Object[] listeners = listenerList.getListenerList(); + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==CfgEventListener.class) { + ((CfgEventListener)listeners[i+1]).selectionChanged(this); + } + } + } + + + //Enables Antialiasing + @Override + public void paintChildren () { + Object anti = getGraphics ().getRenderingHint (RenderingHints.KEY_ANTIALIASING); + Object textAnti = getGraphics ().getRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING); + + getGraphics ().setRenderingHint ( + RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + getGraphics ().setRenderingHint ( + RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + super.paintChildren (); + + getGraphics ().setRenderingHint (RenderingHints.KEY_ANTIALIASING, anti); + getGraphics ().setRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING, textAnti); + } + + + //select provider for node selection + private RectangularSelectProvider createRectangularSelectProvider() { + return new RectangularSelectProvider() { + public void performSelection(Rectangle rectangle) { + HashSet set=new HashSet(); + + //change to a rectangle with (x,offsetY) at the top left + if(rectangle.width < 0){ + rectangle.x=rectangle.x+rectangle.width; + rectangle.width*=-1; + } + if(rectangle.height < 0){ + rectangle.y=rectangle.y+rectangle.height; + rectangle.height*=-1; + } + + for(NodeWidget n: getNodeWidgets()) { + Point p = n.getLocation(); + if (p != null && rectangle.contains(p)) { + set.add(n.getNodeModel()); + } + } + setNodeSelection(set); + } + }; + } + + //select decorator for node selection + private RectangularSelectDecorator createSelectDecorator(final CfgScene scene){ + return new RectangularSelectDecorator() { + public Widget createSelectionWidget() { + scene.cleanNodeSelection();//unselected all nodes + scene.revalidate(); + return new SelectionWidget(getScene()); + } + }; + } + + + private MoveProvider createMoveProvider() { + return new MoveProvider(){ + private HashMap originals = new HashMap(); + + private Point original=null; + + public void movementStarted(Widget widget) { + originals.clear(); + NodeWidget nw = (NodeWidget) widget; + if(selectedNodes.contains(nw.getNodeModel())) {//move current selection + for(CfgNode n : selectedNodes){ + Widget w = findWidget(n); + originals.put(w, w.getLocation()); + } + } else {//a newly-selected node will be moved + CfgNode n = nw.getNodeModel(); + HashSet selectedNode = new HashSet(1); + selectedNode.add(n); + setNodeSelection(selectedNode); + originals.put(widget, widget.getPreferredLocation()); + widget.revalidate(); + validate(); + + } + } + + public void movementFinished(Widget widget) { + NodeWidget nw = (NodeWidget) widget; + if(selectedNodes.contains(nw.getNodeModel())) { + return;//to be able to move the current selection + } + + HashSet selectedNode = new HashSet(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + originals.clear (); + original = null; + + } + + public Point getOriginalLocation(Widget widget) { + if(original==null) + original = widget.getLocation(); + + return original; + } + //todo : find a cache algorithm which only routes edges + //which are intersected by bounds of the moved rectangle + public void setNewLocation(Widget widget, Point location) { + Point org = getOriginalLocation(widget); + int dx = location.x - org.x; + int dy = location.y - org.y; + for (Map.Entry entry : originals.entrySet ()) { + Point point = entry.getValue (); + entry.getKey ().setPreferredLocation (new Point (point.x + dx, point.y + dy)); + } + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) findWidget(e); + if(ew.isVisible()) + ew.reroute(); + } + } + }; + } + + + private WidgetAction createContextMenuAction(final CfgScene scene) { + return ActionFactory.createPopupMenuAction(new PopupMenuProvider() { + public JPopupMenu getPopupMenu(Widget widget, Point point) { + JPopupMenu menu = new JPopupMenu(); + NodeWidget nw = null; + if(widget instanceof NodeWidget) { + nw = (NodeWidget) widget; + if(!selectedNodes.contains(nw.getNodeModel())){ + HashSet selectedNode = new HashSet(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + } + } else if (scene.getSelectedNodes().size() == 1) { + nw = (NodeWidget) scene.findWidget(scene.getSelectedNodes().iterator().next()); + } + + if(nw != null){ + CfgNode node = nw.getNodeModel(); + ArrayList successors = new ArrayList(); + ArrayList predecessors = new ArrayList(); + for(CfgEdge e : node.getOutputEdges()){ + successors.add(e.getTargetNode()); + } + for(CfgEdge e : node.getInputEdges()){ + predecessors.add(e.getSourceNode()); + } + + if(predecessors.size()>0){ + Collections.sort(predecessors, new NodeNameComparator()); + JMenu predmenu = new JMenu("Go to predecessor"); + for (CfgNode n : predecessors) { + GotoNodeAction action = new GotoNodeAction(n); + predmenu.add(action); + } + menu.add(predmenu); + } + if(successors.size()>0){ + Collections.sort(successors, new NodeNameComparator()); + JMenu succmenu = new JMenu("Go to successor"); + for (CfgNode n : successors) { + GotoNodeAction action = new GotoNodeAction(n); + succmenu.add(action); + } + menu.add(succmenu); + } + if ( successors.size() > 0 || predecessors.size() > 0) + menu.addSeparator(); + } + + menu.add(SystemAction.get(ShowEdgesAction.class)); + menu.add(SystemAction.get(HideEdgesAction.class)); + menu.addSeparator(); + menu.add(SystemAction.get(ColorAction.class).getPopupPresenter()); + return menu; + } + }); + } + + private class NodeNameComparator implements Comparator { + public int compare(CfgNode node1, CfgNode node2) { + String name1 = node1.getBasicBlock().getName().substring(1); + String name2 = node2.getBasicBlock().getName().substring(1); + Integer blocknum1 = Integer.parseInt(name1); + Integer blocknum2 = Integer.parseInt(name2); + return blocknum1.compareTo(blocknum2); + } + } + + private class GotoNodeAction extends AbstractAction { + CfgNode node ; + + GotoNodeAction(CfgNode node){ + super(node.getBasicBlock().getName()); + this.node = node; + } + public void actionPerformed(ActionEvent e) { + Set nodes = new HashSet(1); + nodes.add(node); + setNodeSelection(nodes); + centerSelection(); + } + } + + private SceneListener createSceneListener(final CfgScene scene){ + return new SceneListener() { + + public void sceneRepaint() { + } + + public void sceneValidating() { + } + + public void sceneValidated() { + if (scene.isLoopClusterVisible()){ //update only if visible + for(LoopClusterWidget cw : getLoopidx2clusterwidget().values()){ + cw.updateClusterBounds(); + } + } + for(EdgeSwitchWidget esw : inputSwitches.values()){ + esw.updatePosition(); + } + + for(EdgeSwitchWidget esw : outputSwitches.values()){ + esw.updatePosition(); + } + } + }; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/CfgScene.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/CfgScene.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,834 @@ +package at.ssw.visualizer.cfg.graph; + + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.action.ColorAction; +import at.ssw.visualizer.cfg.action.HideEdgesAction; +import at.ssw.visualizer.cfg.action.ShowEdgesAction; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalCompoundLayout; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalNodeLayout; +import at.ssw.visualizer.cfg.model.CfgEnv; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.visual.PolylineRouter; +import at.ssw.visualizer.cfg.visual.PolylineRouterV2; +import at.ssw.visualizer.cfg.visual.WidgetCollisionCollector; +import at.ssw.visualizer.core.selection.Selection; +import at.ssw.visualizer.core.selection.SelectionManager; +import at.ssw.visualizer.model.cfg.BasicBlock; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.MoveProvider; +import org.netbeans.api.visual.action.PopupMenuProvider; +import org.netbeans.api.visual.action.RectangularSelectDecorator; +import org.netbeans.api.visual.action.RectangularSelectProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.anchor.AnchorFactory; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.layout.LayoutFactory; +import org.netbeans.api.visual.layout.SceneLayout; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.router.Router.*; +import org.netbeans.api.visual.router.RouterFactory; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.LayerWidget; +import org.netbeans.api.visual.widget.Widget; +import org.openide.util.actions.SystemAction; + + +public class CfgScene extends GraphScene implements ChangeListener { + private LayerWidget mainLayer = new LayerWidget(this); + private LayerWidget connectionLayer = new LayerWidget(this); + private LayerWidget interractionLayer = new LayerWidget(this); + private LayerWidget clusterLayer = new LayerWidget(this); + private Set selectedNodes = Collections.emptySet(); + private Map loopidx2clusterwidget = new HashMap(); + private Map inputSwitches = new HashMap(); + private Map outputSwitches = new HashMap(); + private WidgetAction moveAction = ActionFactory.createMoveAction (ActionFactory.createFreeMoveStrategy(), this.createMoveProvider()); + private SceneLayout sceneLayout; + private CfgEnv env; + private int currentLayout=-1; + private int currentRouter=-1; + private CfgEditorTopComponent cfgtc; + private EventListenerList listenerList = new EventListenerList(); + private WidgetAction contextPopupAction = this.createContextMenuAction(this); + private List nodeWidgets=null; + private boolean loopClustersVisible = true; + + + public CfgScene(final CfgEditorTopComponent cfgtc){ + addChild(clusterLayer); + addChild(mainLayer); + addChild(interractionLayer); + addChild(connectionLayer); + this.loadDefaults(); + this.cfgtc=cfgtc; + this.loadModel(new CfgEnv(cfgtc.getCfg())); + this.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT);//default + this.getInputBindings().setZoomActionModifiers(0); + this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1)); + this.getActions().addAction(ActionFactory.createPanAction()); + this.getActions().addAction(ActionFactory.createRectangularSelectAction( + this.createSelectDecorator(this), + interractionLayer, + this.createRectangularSelectProvider()) + ); + this.getActions().addAction(this.contextPopupAction); + this.addSceneListener(createSceneListener(this)); + this.validate(); + } + + private void loadModel(CfgEnv cfgenv) { + this.env = cfgenv; + for(CfgNode n : env.getNodes()) { + addNode(n); + } + for(CfgEdge e : env.getEdges()) { + addEdge(e); + setEdgeSource(e, e.getSourceNode()); + setEdgeTarget(e, e.getTargetNode()); + } + this.stackLoops(cfgenv.getLoopMap()); + this.autoHideEdges(); + } + + public void loadDefaults() { + this.setRouter(CfgEditorContext.ROUTING_DIRECTLINES); + CfgPreferences prefs = CfgPreferences.getInstance(); + this.setBackground(prefs.getBackgroundColor()); + } + + //sets the parent Widget of all LoopClusterWidgets + private void stackLoops(Map map) { + this.clusterLayer.removeChildren(); + + Set cache = new HashSet(); + for(LoopInfo info : map.values()){ + if(cache.contains(info)) continue; + LoopClusterWidget widget = this.loopidx2clusterwidget.get(info.getLoopIndex()); + LoopInfo parent = info.getParent(); + while(parent != null){ + LoopClusterWidget parentWidget = this.loopidx2clusterwidget.get(parent.getLoopIndex()); + assert parentWidget != null; + if(widget.getParentWidget()!=null) + widget.removeFromParent(); + parentWidget.addChild(widget); + widget=parentWidget; + parent = parent.getParent(); + } + widget.removeFromParent(); + this.clusterLayer.addChild(widget);//parent == null => parent is clusterlayer + } + } + + //hide in|output edges + private void autoHideEdges(){ + for(CfgNode n : this.getNodes()){ + int fanin = n.getInputEdges().length; + int fanout = n.getOutputEdges().length; + if (fanin > CfgEditorContext.MAX_AUTOEDGESVISIBLE){ + assert(inputSwitches.containsKey(n)); + if(this.inputSwitches.containsKey(n)){ + EdgeSwitchWidget esw = this.inputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + if(fanout > CfgEditorContext.MAX_AUTOEDGESVISIBLE){ + if(this.outputSwitches.containsKey(n)){ + EdgeSwitchWidget esw = this.outputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + } + + } + + //apply current cfggraphscene layout + public void applyLayout(){ + this.sceneLayout.invokeLayoutImmediately(); + } + + //returns a Set with the currently selected Nodes + public Set getSelectedNodes() { + return Collections.unmodifiableSet(selectedNodes); + } + + + public Map getLoopidx2clusterwidget() { + return loopidx2clusterwidget; + } + + /** + * Sets the color of the currently selected Nodes + * If the supplied color is null the default color will be used + */ + public void setSelectedNodesColor(Color color) { + if(color == null) { //set default color + CfgPreferences prefs = CfgPreferences.getInstance(); + boolean customized=false; + for(CfgNode n : this.selectedNodes){ + color=null; + color = prefs.getFlagsSetting().getColor(n.getBasicBlock().getFlags()); + customized = (color!=null); + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor((customized) ? color : prefs.getNodeColor(), customized); + } + } else { + for(CfgNode n : this.selectedNodes){ + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor(color, true); + } + } + this.validate(); + } + + public void setSelectedEdgesVisibility(boolean visible) { + for(CfgNode n : this.selectedNodes){ + EdgeSwitchWidget in = this.inputSwitches.get(n); + EdgeSwitchWidget out = this.outputSwitches.get(n); + if(in != null) in.changeEdgeVisibility(visible); + if(out != null) out.changeEdgeVisibility(visible); + } + this.fireSelectionChanged(); + this.validate(); + } + + public EdgeSwitchWidget getInputSwitch(CfgNode n){ + return this.inputSwitches.get(n); + } + public EdgeSwitchWidget getOutputSwitch(CfgNode n){ + return this.outputSwitches.get(n); + } + + public CfgEnv getCfgEnv() { + return env; + } + + public boolean isLoopClusterVisible() { + return loopClustersVisible; + } + + public void setLoopWidgets(boolean visible) { + for(Widget w : this.loopidx2clusterwidget.values()){ + w.setVisible(visible); + w.revalidate(); + } + this.loopClustersVisible=visible; + this.validate(); + } + + public void setRouter(int newRouter){ + if(newRouter == this.currentRouter) return; + + this.currentRouter=newRouter; + + Router router; + + switch (newRouter) { + case CfgEditorContext.ROUTING_BEZIER: + router = new PolylineRouterV2(new WidgetCollisionCollector() { + public void collectCollisions(List collisions) { + collisions.addAll(getNodeWidgets()); + } + }); + break; + case CfgEditorContext.ROUTING_DIRECTLINES: + router = RouterFactory.createDirectRouter(); + break; + default: + throw new IllegalStateException ("Unknown Router ID: " + newRouter); // NOI18N + } + + for(CfgEdge e : this.getEdges()){ + EdgeWidget ew = (EdgeWidget) this.findWidget(e); + ew.setRouter(router); + } + this.validate(); + } + + + + public Collection getNodeWidgets() { + if(nodeWidgets != null && nodeWidgets.size()==this.getNodes().size()) return nodeWidgets; + + List widgets = new ArrayList(); + for(CfgNode n : this.getNodes()){ + NodeWidget w = (NodeWidget) this.findWidget(n); + widgets.add(w); + } + + nodeWidgets = Collections.unmodifiableList(widgets); + return widgets; + } + + + + public void setSceneLayout(int newLayout){ + + if(currentLayout == newLayout) return; + + GraphLayout graphLayout=null; + + switch (newLayout) { + case CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT: + graphLayout = new HierarchicalNodeLayout(this); + break; + + case CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT: + graphLayout = new HierarchicalCompoundLayout(this); + break; + } + + this.currentLayout=newLayout; + if(graphLayout != null) + this.sceneLayout=LayoutFactory.createSceneGraphLayout(this, graphLayout); + } + + + @Override + protected void attachEdgeSourceAnchor(CfgEdge edge, CfgNode oldSourceNode, CfgNode sourceNode) { + Anchor sourceAnchor; + EdgeWidget edgeWidget = (EdgeWidget) findWidget (edge); + Widget sourceWidget = findWidget(sourceNode); + + if (edge.isSymmetric()) { + sourceAnchor = new SymmetricAnchor(sourceWidget, true, true); + } else { + sourceAnchor = AnchorFactory.createRectangularAnchor(sourceWidget); + } + edgeWidget.setSourceAnchor (sourceAnchor); + } + + @Override + protected void attachEdgeTargetAnchor(CfgEdge edge, CfgNode oldtarget, CfgNode targetNode) { + Anchor targetAnchor; + ConnectionWidget edgeWidget = (ConnectionWidget) findWidget (edge); + Widget targetWidget = findWidget(targetNode); + + if (edge.isSymmetric()) { + targetAnchor = new SymmetricAnchor(targetWidget, true, false); + } else { + targetAnchor = AnchorFactory.createRectangularAnchor(targetWidget); + } + edgeWidget.setTargetAnchor (targetAnchor); + } + + + @Override + protected Widget attachEdgeWidget(CfgEdge edge) { + EdgeWidget widget = new EdgeWidget(this, edge); + connectionLayer.addChild(widget); + attachSourceSwitchWidget(edge); + attachTargetSwitchWidget(edge); + return widget; + } + + + + @Override + protected Widget attachNodeWidget(CfgNode node) { + this.nodeWidgets = null; + + NodeWidget nw = new NodeWidget(this,node); + WidgetAction.Chain actions = nw.getActions(); + actions.addAction(this.contextPopupAction); + actions.addAction(this.moveAction); + actions.addAction(this.createObjectHoverAction()); + + if ( node.isLoopMember() ) { + LoopClusterWidget loopWidget = this.attachLoopMember(node); + loopWidget.addMember(nw); + } + mainLayer.addChild(nw); + return nw; + } + + + private LoopClusterWidget attachLoopMember(CfgNode node) { + LoopClusterWidget lw = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if(lw == null) { + lw = new LoopClusterWidget(this, node.getLoopDepth(), node.getLoopIndex()); + this.loopidx2clusterwidget.put(node.getLoopIndex(), lw); + this.clusterLayer.addChild(lw); + } + return lw; + } + + + private boolean detachLoopMember(CfgNode node, NodeWidget nodeWidget) { + LoopClusterWidget rm = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if( rm == null) return false;//not added + + if ( rm.removeMember(nodeWidget) ) { + if(rm.getMembers().size() == 0){ + this.loopidx2clusterwidget.remove(rm.getLoopIndex()); + List childs = new ArrayList(rm.getChildren()); + for (Widget w : childs){//append stacked loopwidgets + w.removeFromParent(); + rm.getParentWidget().addChild(w); + } + rm.removeFromParent(); + } + return true; + } + return false; + } + + //this function is not invoked by any class of the module + //however to ensure that the edge switches are treatet corretly + //when a future version removes nodes it was implemented too. + + @Override + protected void detachNodeWidget(CfgNode node, Widget nodeWidget) { + if(node.isLoopMember() && nodeWidget instanceof NodeWidget ) { + this.detachLoopMember(node,(NodeWidget)nodeWidget); + } + super.detachNodeWidget(node, nodeWidget); + assert nodeWidget.getParentWidget()== null; + if(this.inputSwitches.containsKey(node)) { + EdgeSwitchWidget esw = this.inputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + if(this.outputSwitches.containsKey(node)){ + EdgeSwitchWidget esw = this.outputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + } + + protected EdgeSwitchWidget attachSourceSwitchWidget(CfgEdge e){ + CfgNode sourceNode = e.getSourceNode(); + NodeWidget sourceWidget = (NodeWidget) this.findWidget(sourceNode); + EdgeSwitchWidget out = outputSwitches.get(sourceNode); + if (out==null) { + out = new EdgeSwitchWidget(this, sourceWidget, true); + this.connectionLayer.addChild(out); + outputSwitches.put(sourceNode, out); + } + return out; + } + + + protected EdgeSwitchWidget attachTargetSwitchWidget(CfgEdge e){ + CfgNode targetNode = e.getTargetNode(); + NodeWidget targetWidget = (NodeWidget) this.findWidget(targetNode); + EdgeSwitchWidget in = inputSwitches.get(targetNode); + if (in==null) { + in = new EdgeSwitchWidget(this, targetWidget, false); + this.connectionLayer.addChild(in); + inputSwitches.put(targetNode, in); + } + return in; + } + + //resets the selection state of all NodeWidgets + private void cleanNodeSelection(){ + if( this.selectedNodes.size() != 0) { + this.userSelectionSuggested(Collections.emptySet(), false); + this.selectedNodes = Collections.emptySet(); + this.fireSelectionChanged(); + this.validate(); + } + } + + + //sets the scene & global node selection + public void setNodeSelection(Set newSelection){ + this.setSceneSelection(newSelection); + this.updateGlobalSelection(); + } + + //sets the scene selection + private void setSceneSelection(Set newSelection){ + if(newSelection.equals(selectedNodes)) return; + + this.selectedNodes=newSelection; + + Set selectedObjects = new HashSet(); + + for(CfgNode n : newSelection){ + selectedObjects.addAll(this.findNodeEdges(n, true, true)); + } + selectedObjects.addAll(newSelection); + + //if the selection gets updated from a change in the block view + //the scene will be centered + if(selectionUpdating) + this.centerSelection(); + + this.userSelectionSuggested(selectedObjects, false); + this.fireSelectionChanged(); + this.validate(); + } + + //updates selection of Block View + public void updateGlobalSelection() { + Selection selection = SelectionManager.getDefault().getCurSelection(); + ArrayList newBlocks = new ArrayList(); + for (CfgNode n : this.selectedNodes) { + newBlocks.add(n.getBasicBlock()); + } + BasicBlock[] curBlocks = newBlocks.toArray(new BasicBlock[newBlocks.size()]); + selection.put(curBlocks); + } + + private boolean selectionUpdating = false; + + //change of blockview selection + public void stateChanged(ChangeEvent event) { + if (selectionUpdating) { + return; + } + + selectionUpdating = true; + + Object source = event.getSource(); + if(source instanceof Selection){ + Selection selection=(Selection) source; + Set newSelection = new HashSet(); + BasicBlock[] newBlocks = selection.get(BasicBlock[].class); + if (newBlocks != null) { + for(BasicBlock b : newBlocks){ + for(CfgNode n : this.getNodes()){ + if(n.getBasicBlock() == b) newSelection.add(n); + } + } + this.setSceneSelection(newSelection); + } + } + selectionUpdating = false; + } + + //centers the viewport on the currently selected nodewidgets + private void centerSelection(){ + Point sceneCenter = null; + Collection nodes = this.selectedNodes; + if(nodes.size()==0) { + nodes = this.getNodes(); + } + + for(CfgNode n : nodes) { + if(sceneCenter==null) { + sceneCenter = this.findWidget(n).getLocation(); + continue; + } + Point location = this.findWidget(n).getLocation(); + sceneCenter.x = (location.x+sceneCenter.x)/2; + sceneCenter.y = (location.y+sceneCenter.y)/2; + } + + JComponent view = this.getView (); + if (view != null) { + Rectangle viewBounds = view.getVisibleRect (); + + Point viewCenter = this.convertSceneToView (sceneCenter); + + view.scrollRectToVisible (new Rectangle ( + viewCenter.x - viewBounds.width / 2, + viewCenter.y - viewBounds.height / 2, + viewBounds.width, + viewBounds.height + )); + } + } + + //animated scene Zoom to the max bounds of current viewport + public void zoomScene(){ + JScrollPane pane = this.cfgtc.getJScrollPanel(); + + Rectangle prefBounds = this.getPreferredBounds(); + Dimension viewDim = pane.getViewportBorderBounds().getSize(); + + double realwidth = (double)prefBounds.width*this.getZoomFactor(); + double realheight = (double)prefBounds.height*this.getZoomFactor(); + + double zoomX = (double)viewDim.width / realwidth; + double zoomY = (double)viewDim.height / realheight; + double zoomFactor = Math.min(zoomX, zoomY); + + this.animateZoom(zoomFactor*0.9); + } + + + //animated animateZoom function for scene animateZoom factor + public void animateZoom(double zoomfactor) { + this.getSceneAnimator().animateZoomFactor(this.getZoomFactor() * zoomfactor); + } + + public void addCfgEventListener(CfgEventListener l) { + listenerList.add(CfgEventListener.class, l); + } + + public void removeCfgEventListener(CfgEventListener l) { + listenerList.remove(CfgEventListener.class, l); + } + + public void fireSelectionChanged() { + Object[] listeners = listenerList.getListenerList(); + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==CfgEventListener.class) { + ((CfgEventListener)listeners[i+1]).selectionChanged(this); + } + } + } + + + //Enables Antialiasing + @Override + public void paintChildren () { + Object anti = getGraphics ().getRenderingHint (RenderingHints.KEY_ANTIALIASING); + Object textAnti = getGraphics ().getRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING); + + getGraphics ().setRenderingHint ( + RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + getGraphics ().setRenderingHint ( + RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + super.paintChildren (); + + getGraphics ().setRenderingHint (RenderingHints.KEY_ANTIALIASING, anti); + getGraphics ().setRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING, textAnti); + } + + + //select provider for node selection + private RectangularSelectProvider createRectangularSelectProvider() { + return new RectangularSelectProvider() { + public void performSelection(Rectangle rectangle) { + HashSet set=new HashSet(); + + //change to a rectangle with (x,offsetY) at the top left + if(rectangle.width < 0){ + rectangle.x=rectangle.x+rectangle.width; + rectangle.width*=-1; + } + if(rectangle.height < 0){ + rectangle.y=rectangle.y+rectangle.height; + rectangle.height*=-1; + } + + for(NodeWidget n: getNodeWidgets()) { + Point p = n.getLocation(); + if (p != null && rectangle.contains(p)) { + set.add(n.getNodeModel()); + } + } + setNodeSelection(set); + } + }; + } + + //select decorator for node selection + private RectangularSelectDecorator createSelectDecorator(final CfgScene scene){ + return new RectangularSelectDecorator() { + public Widget createSelectionWidget() { + scene.cleanNodeSelection();//unselected all nodes + scene.revalidate(); + return new SelectionWidget(getScene()); + } + }; + } + + + private MoveProvider createMoveProvider() { + return new MoveProvider(){ + private HashMap originals = new HashMap(); + + private Point original=null; + + public void movementStarted(Widget widget) { + originals.clear(); + NodeWidget nw = (NodeWidget) widget; + if(selectedNodes.contains(nw.getNodeModel())) {//move current selection + for(CfgNode n : selectedNodes){ + Widget w = findWidget(n); + originals.put(w, w.getLocation()); + } + } else {//a newly-selected node will be moved + CfgNode n = nw.getNodeModel(); + HashSet selectedNode = new HashSet(1); + selectedNode.add(n); + setNodeSelection(selectedNode); + originals.put(widget, widget.getPreferredLocation()); + widget.revalidate(); + validate(); + + } + } + + public void movementFinished(Widget widget) { + NodeWidget nw = (NodeWidget) widget; + if(selectedNodes.contains(nw.getNodeModel())) { + return;//to be able to move the current selection + } + + HashSet selectedNode = new HashSet(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + originals.clear (); + original = null; + + } + + public Point getOriginalLocation(Widget widget) { + if(original==null) + original = widget.getLocation(); + + return original; + } + //todo : find a cache algorithm which only routes edges + //which are intersected by bounds of the moved rectangle + public void setNewLocation(Widget widget, Point location) { + Point org = getOriginalLocation(widget); + int dx = location.x - org.x; + int dy = location.y - org.y; + for (Map.Entry entry : originals.entrySet ()) { + Point point = entry.getValue (); + entry.getKey ().setPreferredLocation (new Point (point.x + dx, point.y + dy)); + } + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) findWidget(e); + if(ew.isVisible()) + ew.reroute(); + } + } + }; + } + + + private WidgetAction createContextMenuAction(final CfgScene scene) { + return ActionFactory.createPopupMenuAction(new PopupMenuProvider() { + public JPopupMenu getPopupMenu(Widget widget, Point point) { + JPopupMenu menu = new JPopupMenu(); + NodeWidget nw = null; + if(widget instanceof NodeWidget) { + nw = (NodeWidget) widget; + if(!selectedNodes.contains(nw.getNodeModel())){ + HashSet selectedNode = new HashSet(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + } + } else if (scene.getSelectedNodes().size() == 1) { + nw = (NodeWidget) scene.findWidget(scene.getSelectedNodes().iterator().next()); + } + + if(nw != null){ + CfgNode node = nw.getNodeModel(); + ArrayList successors = new ArrayList(); + ArrayList predecessors = new ArrayList(); + for(CfgEdge e : node.getOutputEdges()){ + successors.add(e.getTargetNode()); + } + for(CfgEdge e : node.getInputEdges()){ + predecessors.add(e.getSourceNode()); + } + + if(predecessors.size()>0){ + Collections.sort(predecessors, new NodeNameComparator()); + JMenu predmenu = new JMenu("Go to predecessor"); + for (CfgNode n : predecessors) { + GotoNodeAction action = new GotoNodeAction(n); + predmenu.add(action); + } + menu.add(predmenu); + } + if(successors.size()>0){ + Collections.sort(successors, new NodeNameComparator()); + JMenu succmenu = new JMenu("Go to successor"); + for (CfgNode n : successors) { + GotoNodeAction action = new GotoNodeAction(n); + succmenu.add(action); + } + menu.add(succmenu); + } + if ( successors.size() > 0 || predecessors.size() > 0) + menu.addSeparator(); + } + + menu.add(SystemAction.get(ShowEdgesAction.class)); + menu.add(SystemAction.get(HideEdgesAction.class)); + menu.addSeparator(); + menu.add(SystemAction.get(ColorAction.class).getPopupPresenter()); + return menu; + } + }); + } + + private class NodeNameComparator implements Comparator { + public int compare(CfgNode node1, CfgNode node2) { + String name1 = node1.getBasicBlock().getName().substring(1); + String name2 = node2.getBasicBlock().getName().substring(1); + Integer blocknum1 = Integer.parseInt(name1); + Integer blocknum2 = Integer.parseInt(name2); + return blocknum1.compareTo(blocknum2); + } + } + + private class GotoNodeAction extends AbstractAction { + CfgNode node ; + + GotoNodeAction(CfgNode node){ + super(node.getBasicBlock().getName()); + this.node = node; + } + public void actionPerformed(ActionEvent e) { + Set nodes = new HashSet(1); + nodes.add(node); + setNodeSelection(nodes); + centerSelection(); + } + } + + private SceneListener createSceneListener(final CfgScene scene){ + return new SceneListener() { + + public void sceneRepaint() { + } + + public void sceneValidating() { + } + + public void sceneValidated() { + if (scene.isLoopClusterVisible()){ //update only if visible + for(LoopClusterWidget cw : getLoopidx2clusterwidget().values()){ + cw.updateClusterBounds(); + } + } + for(EdgeSwitchWidget esw : inputSwitches.values()){ + esw.updatePosition(); + } + + for(EdgeSwitchWidget esw : outputSwitches.values()){ + esw.updatePosition(); + } + } + }; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/EdgeSwitchWidget.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/EdgeSwitchWidget.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,291 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; +import java.util.Collection; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.SelectProvider; +import org.netbeans.api.visual.action.TwoStateHoverProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + + +public class EdgeSwitchWidget extends Widget { + private final static Color color_enabled = Color.gray; + private final static Color color_hover = Color.lightGray; + private float width=1; + private float height=1; + private CfgScene scene; + private NodeWidget nodeWidget; + private boolean output; + private WidgetAction hoverAction; + private static final String TT_HIDE_EDGES = "Hide Edges"; + private static final String TT_SHOW_EDGES = "Show Edges"; + private static SelectProvider selectProvider = createSelectProvider(); + + + public EdgeSwitchWidget(final CfgScene scene, NodeWidget nodeWidget, boolean output) { + super(scene); + this.scene = scene; + this.output = output; + this.nodeWidget = nodeWidget; + + this.getActions().addAction(ActionFactory.createSelectAction(selectProvider)); + TwoStateHoverProvider ts = new TsHover(this); + WidgetAction wa = ActionFactory.createHoverAction(ts); + this.hoverAction = wa; + this.getActions().addAction(wa); + scene.getActions().addAction(wa); + this.setToolTipText(TT_HIDE_EDGES); + this.setForeground(color_enabled); + this.setState(ObjectState.createNormal()); + } + + + @Override + protected Rectangle calculateClientArea() { + if (this.nodeWidget.getBounds() == null) return new Rectangle(0, 0, 1, 1); + int hw = (int) (this.width / 2); + int hh = (int) (this.height /2); + + return new Rectangle(-hw, -hh, 2*hw, 2*hh); + } + + + public void updatePosition() { + if (this.nodeWidget.getBounds() != null) { + this.width = nodeWidget.getBounds().width*9; + this.width /=10; + this.height = nodeWidget.getBounds().height/4; + int offset=(int)(2 * (height / 3)); + + Rectangle bounds = nodeWidget.getBounds(); + Point location = nodeWidget.getLocation(); + + Point newLoc = new Point(); + newLoc.x = location.x; + + if(output) { + newLoc.y = +location.y + bounds.height/2+offset; + }else { + newLoc.y = location.y - bounds.height/2-offset; + } + this.setPreferredLocation(newLoc); + } + } + + private Collection getEdges(){ + Collection edges; + CfgNode node = nodeWidget.getNodeModel(); + if (output) { + edges = scene.findNodeEdges(node, true, false); + } else { + edges = scene.findNodeEdges(node, false, true); + } + return edges; + } + + //change visibility for all Edges + public void changeEdgeVisibility(boolean visible){ + Collection edges = this.getEdges(); + + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(visible != ew.isEdgeVisible()){ + ew.setEdgeVisible(visible); + if(output){ + scene.getInputSwitch(e.getTargetNode()).updateStatus(); + } else { + scene.getOutputSwitch(e.getSourceNode()).updateStatus(); + } + } + } + if(visible) + this.setToolTipText(TT_HIDE_EDGES); + else + this.setToolTipText(TT_SHOW_EDGES); + + this.setForeground(color_enabled); + this.bringToBack(); + ObjectState os = this.getState(); + this.setState(os.deriveSelected(!visible)); + } + + /** + * Update the status of the switch to the current state of the edges + * usually needed when the opposit switch changes the state + */ + private void updateStatus(){ + Collection edges = this.getEdges(); + boolean hiddenFound=false; + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!ew.isVisible()) { + hiddenFound=true; + break; + } + } + ObjectState os = this.getState(); + if(os.isSelected() && !hiddenFound) { + this.setState(os.deriveSelected(false)); + setToolTipText(TT_HIDE_EDGES); + } else if (!os.isSelected() && hiddenFound) { + this.setState(os.deriveSelected(true)); + setToolTipText(TT_SHOW_EDGES); + } + this.revalidate(); + } + + + public void startPreview() { + ObjectState os = this.getState(); + + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!os.isSelected() || !ew.isVisible()){ + ObjectState edgeState = ew.getState(); + ew.setState(edgeState.deriveHighlighted(true)); + } + } + } + + public void endPreview(){ + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + ObjectState os = ew.getState(); + ew.setState(os.deriveHighlighted(false)); + } + } + + /** + * shows or hides the edges of the switch + */ + public void switchEdges() { + endPreview(); + ObjectState os = this.getState(); + Collection edges = this.getEdges(); + ArrayList updates = new ArrayList(); + boolean visible=os.isSelected(); + this.setState(os.deriveSelected(!visible)); + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(ew.isEdgeVisible() != visible){ + updates.add(e); + ew.setEdgeVisible(visible); + if(output){ + scene.getInputSwitch(e.getTargetNode()).updateStatus(); + } else { + scene.getOutputSwitch(e.getSourceNode()).updateStatus(); + } + } + } + if(visible) + this.setToolTipText(TT_HIDE_EDGES); + else + this.setToolTipText(TT_SHOW_EDGES); + + scene.fireSelectionChanged();//updates Edge visibility for context action + revalidate(); + } + + + + + private class TsHover implements TwoStateHoverProvider { + EdgeSwitchWidget tw; + + TsHover(EdgeSwitchWidget tw) { + this.tw = tw; + } + + public void unsetHovering(Widget w) { + w.setForeground(color_enabled); + ObjectState state = w.getState(); + w.setState(state.deriveWidgetHovered(false)); + w.bringToBack(); + endPreview(); + } + + public void setHovering(Widget w) { + ObjectState state = w.getState(); + w.setState(state.deriveWidgetHovered(true)); + w.setForeground(color_hover); + w.bringToFront(); + nodeWidget.bringToFront(); + startPreview(); + } + } + + @Override + public void paintWidget() { + ObjectState os = this.getState(); + if(!os.isHovered() && !os.isSelected()) return; //all previewEdges visible and not hovering, + //no need to paint the switch + float hw = width/2; + Polygon pol = new Polygon(); + pol.addPoint(0,(int) -height/2); + pol.addPoint((int)hw,(int) height/2); + pol.addPoint((int)-hw,(int) height/2); + Graphics2D gr = getGraphics(); + gr.setColor(this.getForeground()); + BasicStroke bs = new BasicStroke(2.0f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND); + gr.setStroke(bs); + AffineTransform previousTransform; + previousTransform = gr.getTransform (); + if(output) { + if(os.isSelected() ){//hidden + gr.scale(1.0, -1.0); + } + } else { //input switch + if(os.isHovered() && !os.isSelected()){ + gr.scale(1.0, -1.0); + } + } + gr.fillPolygon(pol); + gr.setTransform(previousTransform); + + } + + + + //the constructor adds the hover WidgetAction to the scene + //the action is removed from the scene when the object gets destroyed + @Override + protected void finalize() throws Throwable { + this.getScene().getActions().removeAction(hoverAction); + this.getActions().removeAction(hoverAction); + } + + @Override + public String toString(){ + return "EDGESWITCH("+this.nodeWidget.getNodeModel().toString()+")"; + } + + private static SelectProvider createSelectProvider() { + return new SelectProvider(){ + public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) { + return false; + } + + public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) { + return true; + } + + public void select(Widget w, Point arg1, boolean arg2) { + if(w instanceof EdgeSwitchWidget){ + EdgeSwitchWidget tw = (EdgeSwitchWidget) w; + tw.switchEdges(); + } + } + }; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/EdgeWidget.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/EdgeWidget.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,97 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.visual.BezierWidget; +import at.ssw.visualizer.cfg.visual.SplineConnectionWidget; +import org.netbeans.api.visual.anchor.AnchorShapeFactory; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Stroke; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.model.ObjectState; + +//public class EdgeWidget extends BezierWidget { +public class EdgeWidget extends SplineConnectionWidget { + + private boolean visible=true;//to store the visible state when entering the preview + protected static final Stroke selectedStroke = new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + protected static final Stroke defaultStroke = new BasicStroke(1.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + protected static final Stroke previewStroke = new BasicStroke( + 0.5f, // Width + BasicStroke.CAP_SQUARE, // End cap + BasicStroke.JOIN_MITER, // Join style + 10.0f, // Miter limit + new float[] {5.0f, 5.0f}, // Dash pattern + 0.0f); + + + + public EdgeWidget(CfgScene scene, CfgEdge edge) { + super(scene); + Color lineColor; + CfgPreferences prefs = CfgPreferences.getInstance(); + + if(edge.isBackEdge()) + lineColor = prefs.getBackedgeColor(); + else if (edge.isXhandler()) + lineColor = prefs.getExceptionEdgeColor(); + else + lineColor = prefs.getEdgeColor(); + + setLineColor(lineColor); + AnchorShape as; + if(edge.isReflexive())//small Arrow + as = AnchorShapeFactory.createTriangleAnchorShape(6, true, false, 5); + else + as =AnchorShapeFactory.createTriangleAnchorShape(10, true, false, 9); + + setTargetAnchorShape(as); + setToolTipText(edge.toString()); + } + + public CfgEdge getEdgeModel() { + CfgScene scene = (CfgScene) this.getScene(); + return (CfgEdge) scene.findObject(this); + } + + public void setEdgeVisible(boolean visible) { + this.visible=visible; + this.setVisible(visible); + this.reroute(); + this.revalidate(); + } + + + public boolean isEdgeVisible(){ + return visible; + } + + + @Override + public void notifyStateChanged(ObjectState oldState, ObjectState newState) { + setForeground (getLineColor()); + + if(newState.isHighlighted() && !oldState.isHighlighted()){ + this.setStroke(previewStroke); + this.setVisible(true); + } else { + if(newState.isSelected()){ + this.setStroke(selectedStroke); + } else { + this.setStroke(defaultStroke); + } + if(this.isEdgeVisible()){ + this.setVisible(true); + } else { + this.setVisible(false); + } + } + } + + + @Override + public String toString(){ + return "EdgeWidget[" + getEdgeModel().toString() + "]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/LoopClusterWidget.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/LoopClusterWidget.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,107 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Color; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.EditProvider; +import org.netbeans.api.visual.border.BorderFactory; +import org.netbeans.api.visual.widget.Widget; + +public class LoopClusterWidget extends Widget implements Comparable { + private static final int INSET = 10;//min space between node members and cluster border + private static final int DASHSIZE = 10; + private Color color = Color.BLUE; + private int loopIndex; + private int loopDepth; + private CfgScene cfgscene; + private ArrayList members = new ArrayList(); + + public LoopClusterWidget(CfgScene scene, int loopdepth, final int loopindex) { + super(scene); + this.cfgscene = scene; + this.loopIndex = loopindex; + this.loopDepth = loopdepth; + this.setBorder(BorderFactory.createDashedBorder(color, DASHSIZE, DASHSIZE/2, true)); + this.getActions().addAction(ActionFactory.createEditAction( new EditProvider() { //double click action + public void edit(Widget w) { + if(w instanceof LoopClusterWidget){ + for(LoopInfo info : cfgscene.getCfgEnv().getLoopMap().values()){ + if(info.getLoopIndex() == loopindex){ + cfgscene.setNodeSelection(info.getMembers()); + break; + } + } + } + } + })); + + } + + public List getMembers() { + return members; + } + + public int getLoopIndex() { + return loopIndex; + } + + public void addMember(NodeWidget nw) { + assert(!this.members.contains(nw)); + members.add(nw); + } + + public boolean removeMember(NodeWidget nw) { + if(this.members.contains(nw)){ + members.remove(nw); + return true; + } + return false; + } + + public void setrandomColor(){ + if(this.loopDepth == 0 ) return; + Random rand = new Random(); + Color randColor = Color.getHSBColor(rand.nextFloat()%360,0.1f,1.0f); + this.setBackground(randColor); + } + + //updates the bounds of the widget, + //and revalidates the widget if a membernode changed the scene position + public void updateClusterBounds(){ + Rectangle boundRect=null; + + for(NodeWidget nw : this.members){ + if(boundRect==null){ + boundRect = nw.convertLocalToScene(nw.getBounds()); + } else { + boundRect = boundRect.union(nw.convertLocalToScene(nw.getBounds())); + } + } + if(boundRect==null) return; + for(Widget w : this.getChildren()) { + if(w instanceof LoopClusterWidget) { + LoopClusterWidget lc = (LoopClusterWidget)w; + lc.updateClusterBounds(); + boundRect = boundRect.union(w.convertLocalToScene(w.getBounds())); + } + } + + boundRect.grow(INSET, INSET); + this.setPreferredBounds(boundRect); + } + + + public int compareTo(LoopClusterWidget o) { + return new Integer(this.loopDepth).compareTo(o.loopDepth); + } + + + @Override + public String toString(){ + return "LoopCluster: [DEPTH "+this.loopDepth+ "] [INDEX "+this.loopIndex+"]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/LoopClusterWidget.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/LoopClusterWidget.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,107 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Color; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.EditProvider; +import org.netbeans.api.visual.border.BorderFactory; +import org.netbeans.api.visual.widget.Widget; + +public class LoopClusterWidget extends Widget implements Comparable { + private static final int INSET = 10;//min space between node members and cluster border + private static final int DASHSIZE = 10; + private Color color = Color.BLUE; + private int loopIndex; + private int loopDepth; + private CfgScene cfgscene; + private ArrayList members = new ArrayList(); + + public LoopClusterWidget(CfgScene scene, int loopdepth, final int loopindex) { + super(scene); + this.cfgscene = scene; + this.loopIndex = loopindex; + this.loopDepth = loopdepth; + this.setBorder(BorderFactory.createDashedBorder(color, DASHSIZE, DASHSIZE/2, true)); + this.getActions().addAction(ActionFactory.createEditAction( new EditProvider() { //double click action + public void edit(Widget w) { + if(w instanceof LoopClusterWidget){ + for(LoopInfo info : cfgscene.getCfgEnv().getLoopMap().values()){ + if(info.getLoopIndex() == loopindex){ + cfgscene.setNodeSelection(info.getMembers()); + break; + } + } + } + } + })); + + } + + public List getMembers() { + return members; + } + + public int getLoopIndex() { + return loopIndex; + } + + public void addMember(NodeWidget nw) { + assert(!this.members.contains(nw)); + members.add(nw); + } + + public boolean removeMember(NodeWidget nw) { + if(this.members.contains(nw)){ + members.remove(nw); + return true; + } + return false; + } + + public void setrandomColor(){ + if(this.loopDepth == 0 ) return; + Random rand = new Random(); + Color randColor = Color.getHSBColor(rand.nextFloat()%360,0.1f,1.0f); + this.setBackground(randColor); + } + + //updates the bounds of the widget, + //and revalidates the widget if a membernode changed the scene position + public void updateClusterBounds(){ + Rectangle boundRect=null; + + for(NodeWidget nw : this.members){ + if(boundRect==null){ + boundRect = nw.convertLocalToScene(nw.getBounds()); + } else { + boundRect = boundRect.union(nw.convertLocalToScene(nw.getBounds())); + } + } + if(boundRect==null) return; + for(Widget w : this.getChildren()) { + if(w instanceof LoopClusterWidget) { + LoopClusterWidget lc = (LoopClusterWidget)w; + lc.updateClusterBounds(); + boundRect = boundRect.union(w.convertLocalToScene(w.getBounds())); + } + } + + boundRect.grow(INSET, INSET); + this.setPreferredBounds(boundRect); + } + + + public int compareTo(LoopClusterWidget o) { + return new Integer(this.loopDepth).compareTo(o.loopDepth); + } + + + @Override + public String toString(){ + return "LoopCluster: [DEPTH "+this.loopDepth+ "] [INDEX "+this.loopIndex+"]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/NodeWidget.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/NodeWidget.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,155 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import org.netbeans.api.visual.border.BorderFactory; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + + +public class NodeWidget extends Widget { + + + //basic block node dimension + private final int halfheight=12; + private final int halfwidth=17; + + private final int height=halfheight*2+1; + private final int width=halfwidth*2+1; + private final int arcHeight=(halfheight/4)*3; + private final int arcWidth = arcHeight; + private final int FONT_MAXSIZE=18; + + private int borderWidth; + private boolean selected=false; + private boolean nodeColorCustomized; + private String text; + private Rectangle2D fontRect; + private Color nodeColor; + + protected static final Color HOVER_BACKGROUND = new Color(0xEEEEEE); + protected static final Color HOVER_FOREGROUND = new Color(0xCDCDCD); + + public NodeWidget(CfgScene scene, CfgNode nodeModel ){ + super(scene); + this.setToolTipText("" + nodeModel.getDescription().replaceAll("\n", "
") + ""); + this.selected=false; + this.text = nodeModel.getBasicBlock().getName(); + this.borderWidth = nodeModel.getLoopDepth()+1; + this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, Color.BLACK, Color.BLACK)); + CfgPreferences prefs = CfgPreferences.getInstance(); + Color color = prefs.getFlagsSetting().getColor(nodeModel.getBasicBlock().getFlags()); + this.nodeColorCustomized = (color!=null); + this.nodeColor = (nodeColorCustomized) ? color : prefs.getNodeColor(); + this.adjustFont(null); + } + + public void setBorderColor(Color color){ + this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, color, color)); + } + + public boolean isNodeColorCustomized() { + return nodeColorCustomized; + } + + //sets a customColor node color + public void setNodeColor(Color color, boolean customColor) { + this.nodeColorCustomized=customColor; + this.nodeColor=color; + this.revalidate(); + } + + public Color getNodeColor() { + return this.nodeColor; + } + + public CfgNode getNodeModel() { + CfgScene scene = (CfgScene) this.getScene(); + return (CfgNode) scene.findObject(this); + } + + + @Override + public void notifyStateChanged(ObjectState oldState, ObjectState newState) { + if(!oldState.equals(newState)) + this.revalidate(); + if(!oldState.isSelected() && newState.isSelected()) + this.bringToFront(); + } + + @Override + protected Rectangle calculateClientArea() { + return new Rectangle(-(halfwidth+1), -(1+halfheight), width+1, height+1);//add border + } + + public void adjustFont(Font font){ + if(font==null) + font = CfgPreferences.getInstance().getTextFont(); + if(font.getSize()>FONT_MAXSIZE){ + font = new Font(font.getFamily(), font.getStyle(), FONT_MAXSIZE); + } + int size=font.getSize(); + int fontStyle = font.getStyle(); + String fontName = font.getFamily(); + FontRenderContext frc = new FontRenderContext(new AffineTransform(), false, false); + Rectangle2D bounds = font.getStringBounds(text, frc); + while(size > 1 && bounds.getWidth() > width) { + font = new Font(fontName, fontStyle, --size); + bounds = font.getStringBounds(text, frc); + } + this.fontRect=bounds; + this.setFont(font); + } + + @Override + protected void paintWidget() { + Graphics2D gr = getGraphics(); + gr.setColor(nodeColor); + Insets borderInsets = this.getBorder().getInsets(); + RoundRectangle2D.Float innerRect = new RoundRectangle2D.Float(-(halfwidth+1), -(halfheight+1), width+1, height+1,arcWidth-1, arcHeight-1); + gr.fill(innerRect); + gr.setColor(getForeground()); + gr.setFont(getFont()); + float textX = (float)( - fontRect.getCenterX()); + float textY = (float)( - fontRect.getCenterY()); + gr.drawString(text, textX, textY); + + RoundRectangle2D.Float outerRect = new RoundRectangle2D.Float(-(halfwidth+borderInsets.left + 1), -(halfheight+borderInsets.top + 1), + width+borderInsets.left + borderInsets.right + 1, height + borderInsets.top + borderInsets.bottom + 1, + arcWidth + borderWidth, arcHeight + borderWidth); + + ObjectState os =this.getState(); + if(os.isSelected()){ + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); + gr.fill(outerRect); + gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); + gr.setComposite(composite); + } + if(os.isHovered()){ + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + gr.setColor(HOVER_FOREGROUND); + gr.fill(outerRect); + gr.setColor(HOVER_BACKGROUND); + gr.setComposite(composite); + } + } + + @Override + public String toString() { + return "NodeWidget[" + getNodeModel().getBasicBlock().getName() + "]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/SelectionWidget.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/SelectionWidget.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,39 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +public class SelectionWidget extends Widget { + public SelectionWidget(Scene scene) { + super(scene); + } + + public static void renderSelectedRect(Graphics2D gr, Rectangle rect) { + if (rect == null) { + return; + } + gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); + gr.fillRect(rect.x, rect.y, rect.width, rect.height); + gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); + } + + public void renderSelectionRectangle(Graphics2D gr, Rectangle selectionRectangle) { + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + + renderSelectedRect(gr, selectionRectangle); + gr.setComposite(composite); + } + + @Override + public void paintWidget(){ + this.renderSelectionRectangle(this.getGraphics(), this.getBounds()); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/SelectionWidget.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/SelectionWidget.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,39 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +public class SelectionWidget extends Widget { + public SelectionWidget(Scene scene) { + super(scene); + } + + public static void renderSelectedRect(Graphics2D gr, Rectangle rect) { + if (rect == null) { + return; + } + gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); + gr.fillRect(rect.x, rect.y, rect.width, rect.height); + gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); + } + + public void renderSelectionRectangle(Graphics2D gr, Rectangle selectionRectangle) { + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + + renderSelectedRect(gr, selectionRectangle); + gr.setComposite(composite); + } + + @Override + public void paintWidget(){ + this.renderSelectionRectangle(this.getGraphics(), this.getBounds()); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/SymmetricAnchor.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/.svn/text-base/SymmetricAnchor.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,157 @@ +package at.ssw.visualizer.cfg.graph; + +import org.netbeans.api.visual.widget.Widget; +import org.netbeans.api.visual.anchor.Anchor; +import java.awt.*; + + +/** + * This Anchor can be used with symmetric edges to create parallel Edges. + * Two Directed Edges are symmetric if they are connecting the same Nodes in different directions. + * e.g. Nodes (1, 2) Edges(a , b) with (1)-a->(2) , (2)-b->(1) + * Start-/End positions are calculated with a fixed offset to prevent edges from overlapping. + * If the edges are drawn as straight lines they will appear as parallel edges. + */ + +public final class SymmetricAnchor extends Anchor { + + private final static int OFFSET = 10; + private boolean includeBorders; + private int offx; + private int offy; + + public SymmetricAnchor (Widget widget, boolean includeBorders, boolean source) { + super (widget); + this.includeBorders = includeBorders; + if (source) { + offx = OFFSET; + offy = OFFSET; + } + else { + offx = -OFFSET; + offy = -OFFSET; + } + } + + public Result compute (Entry entry) { + Point relatedLocation = //center of the widget + getRelatedSceneLocation (); + Point oppositeLocation = //center of the widget + getOppositeSceneLocation (entry); + + Widget widget = getRelatedWidget (); + Rectangle bounds = widget.getBounds (); + if (! includeBorders) { + Insets insets = widget.getBorder ().getInsets (); + bounds.x += insets.left; + bounds.y += insets.top; + bounds.width -= insets.left + insets.right; + bounds.height -= insets.top + insets.bottom; + } + + bounds = widget.convertLocalToScene (bounds); + + if (bounds.isEmpty () || relatedLocation.equals (oppositeLocation)) + return new Anchor.Result (relatedLocation, Anchor.DIRECTION_ANY); + + float dx //distance x-axis + = oppositeLocation.x - relatedLocation.x; + float dy //distance y-axis + = oppositeLocation.y - relatedLocation.y; + + + float ddx + = Math.abs (dx) / (float) bounds.width; + float ddy = + Math.abs (dy) / (float) bounds.height; + + Anchor.Direction direction; + + + if (ddx >= ddy) { + if(dx >= 0.0f){ + direction = Direction.RIGHT; + relatedLocation.y -= offy; + } else { + direction = Direction.LEFT; + relatedLocation.y += offy; + } + } else { + if(dy >= 0.0f){ + direction = Direction.BOTTOM; + relatedLocation.x += offx; + } else { + direction = Direction.TOP; + relatedLocation.x -= offx; + } + } + + + float scale = 0.5f / Math.max (ddx, ddy); + + float ex = scale * dx; + float ey = scale * dy; + + Point point = new Point (Math.round (relatedLocation.x + ex), Math.round (relatedLocation.y + ey)); + + if(direction == Direction.RIGHT) { + int top = bounds.y;//-bounds.height;// left y of the widget + int bottom = bounds.y + bounds.height;// right y of the widget + if(point.y < top) {//above the widget + int cor = top-point.y; + point.x -= cor; + point.y += cor; + } else if ( point.y > bottom) { + int cor = point.y-bottom; + point.x -= cor; + point.y -= cor; + } + + } else if (direction == Direction.LEFT) { + int top = bounds.y;//-bounds.height;// left y of the widget + int bottom = bounds.y + bounds.height;// right y of the widget + + + + if(point.y < top) {//above the widget + int cor = top-point.y; + point.x += cor; + point.y += cor; + } else if ( point.y > bottom) { + int cor = bottom-point.y; + point.x -= cor; + point.y += cor; + } + + + } else if (direction == Direction.BOTTOM) { + int left = bounds.x;//-bounds.height;// left y of the widget + int right = bounds.x + bounds.width;// right y of the widget + if(point.x < left) {//above the widget + int cor = left-point.x; + point.x += cor; + point.y -= cor; + } else if ( point.x > right) { + int cor = point.x- right; + point.x -= cor; + point.y -= cor; + } + + } else if (direction == Direction.TOP) { + int left = bounds.x;//-bounds.height;// left y of the widget + int right = bounds.x + bounds.width;// right y of the widget + if(point.x < left) {//above the widget + int cor = left-point.x; + point.x += cor; + point.y += cor; + } else if ( point.x > right) { + int cor = point.x - right; + point.x -= cor; + point.y += cor; + } + + } + + return new Anchor.Result (point, direction); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgEventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgEventListener.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,13 @@ +package at.ssw.visualizer.cfg.graph; + +import java.util.EventListener; + + +public interface CfgEventListener extends EventListener { + + /** + * the node or the edge selection got changed + */ + public void selectionChanged(CfgScene scene); + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgScene.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgScene.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,834 @@ +package at.ssw.visualizer.cfg.graph; + + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.CfgEditorContext; +import at.ssw.visualizer.cfg.action.ColorAction; +import at.ssw.visualizer.cfg.action.HideEdgesAction; +import at.ssw.visualizer.cfg.action.ShowEdgesAction; +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalCompoundLayout; +import at.ssw.visualizer.cfg.graph.layout.HierarchicalNodeLayout; +import at.ssw.visualizer.cfg.model.CfgEnv; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.visual.PolylineRouter; +import at.ssw.visualizer.cfg.visual.PolylineRouterV2; +import at.ssw.visualizer.cfg.visual.WidgetCollisionCollector; +import at.ssw.visualizer.model.cfg.BasicBlock; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.MoveProvider; +import org.netbeans.api.visual.action.PopupMenuProvider; +import org.netbeans.api.visual.action.RectangularSelectDecorator; +import org.netbeans.api.visual.action.RectangularSelectProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.anchor.AnchorFactory; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.layout.LayoutFactory; +import org.netbeans.api.visual.layout.SceneLayout; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.router.Router.*; +import org.netbeans.api.visual.router.RouterFactory; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.LayerWidget; +import org.netbeans.api.visual.widget.Widget; +import org.openide.util.actions.SystemAction; + + +public class CfgScene extends GraphScene implements ChangeListener { + private LayerWidget mainLayer = new LayerWidget(this); + private LayerWidget connectionLayer = new LayerWidget(this); + private LayerWidget interractionLayer = new LayerWidget(this); + private LayerWidget clusterLayer = new LayerWidget(this); + private Set selectedNodes = Collections.emptySet(); + private Map loopidx2clusterwidget = new HashMap(); + private Map inputSwitches = new HashMap(); + private Map outputSwitches = new HashMap(); + private WidgetAction moveAction = ActionFactory.createMoveAction (ActionFactory.createFreeMoveStrategy(), this.createMoveProvider()); + private SceneLayout sceneLayout; + private CfgEnv env; + private int currentLayout=-1; + private int currentRouter=-1; + private CfgEditorTopComponent cfgtc; + private EventListenerList listenerList = new EventListenerList(); + private WidgetAction contextPopupAction = this.createContextMenuAction(this); + private List nodeWidgets=null; + private boolean loopClustersVisible = true; + + + public CfgScene(final CfgEditorTopComponent cfgtc){ + addChild(clusterLayer); + addChild(mainLayer); + addChild(interractionLayer); + addChild(connectionLayer); + this.loadDefaults(); + this.cfgtc=cfgtc; + this.loadModel(new CfgEnv(cfgtc.getCfg())); + this.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT);//default + this.getInputBindings().setZoomActionModifiers(0); + this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1)); + this.getActions().addAction(ActionFactory.createPanAction()); + this.getActions().addAction(ActionFactory.createRectangularSelectAction( + this.createSelectDecorator(this), + interractionLayer, + this.createRectangularSelectProvider()) + ); + this.getActions().addAction(this.contextPopupAction); + this.addSceneListener(createSceneListener(this)); + this.validate(); + } + + private void loadModel(CfgEnv cfgenv) { + this.env = cfgenv; + for(CfgNode n : env.getNodes()) { + addNode(n); + } + for(CfgEdge e : env.getEdges()) { + addEdge(e); + setEdgeSource(e, e.getSourceNode()); + setEdgeTarget(e, e.getTargetNode()); + } + this.stackLoops(cfgenv.getLoopMap()); + this.autoHideEdges(); + } + + public void loadDefaults() { + this.setRouter(CfgEditorContext.ROUTING_DIRECTLINES); + CfgPreferences prefs = CfgPreferences.getInstance(); + this.setBackground(prefs.getBackgroundColor()); + } + + //sets the parent Widget of all LoopClusterWidgets + private void stackLoops(Map map) { + this.clusterLayer.removeChildren(); + + Set cache = new HashSet(); + for(LoopInfo info : map.values()){ + if(cache.contains(info)) continue; + LoopClusterWidget widget = this.loopidx2clusterwidget.get(info.getLoopIndex()); + LoopInfo parent = info.getParent(); + while(parent != null){ + LoopClusterWidget parentWidget = this.loopidx2clusterwidget.get(parent.getLoopIndex()); + assert parentWidget != null; + if(widget.getParentWidget()!=null) + widget.removeFromParent(); + parentWidget.addChild(widget); + widget=parentWidget; + parent = parent.getParent(); + } + widget.removeFromParent(); + this.clusterLayer.addChild(widget);//parent == null => parent is clusterlayer + } + } + + //hide in|output edges + private void autoHideEdges(){ + for(CfgNode n : this.getNodes()){ + int fanin = n.getInputEdges().length; + int fanout = n.getOutputEdges().length; + if (fanin > CfgEditorContext.MAX_AUTOEDGESVISIBLE){ + assert(inputSwitches.containsKey(n)); + if(this.inputSwitches.containsKey(n)){ + EdgeSwitchWidget esw = this.inputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + if(fanout > CfgEditorContext.MAX_AUTOEDGESVISIBLE){ + if(this.outputSwitches.containsKey(n)){ + EdgeSwitchWidget esw = this.outputSwitches.get(n); + esw.changeEdgeVisibility(false); + } + } + } + + } + + //apply current cfggraphscene layout + public void applyLayout(){ + this.sceneLayout.invokeLayoutImmediately(); + } + + //returns a Set with the currently selected Nodes + public Set getSelectedNodes() { + return Collections.unmodifiableSet(selectedNodes); + } + + + public Map getLoopidx2clusterwidget() { + return loopidx2clusterwidget; + } + + /** + * Sets the color of the currently selected Nodes + * If the supplied color is null the default color will be used + */ + public void setSelectedNodesColor(Color color) { + if(color == null) { //set default color + CfgPreferences prefs = CfgPreferences.getInstance(); + boolean customized=false; + for(CfgNode n : this.selectedNodes){ + color=null; + color = prefs.getFlagsSetting().getColor(n.getBasicBlock().getFlags()); + customized = (color!=null); + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor((customized) ? color : prefs.getNodeColor(), customized); + } + } else { + for(CfgNode n : this.selectedNodes){ + NodeWidget nw = (NodeWidget) this.findWidget(n); + nw.setNodeColor(color, true); + } + } + this.validate(); + } + + public void setSelectedEdgesVisibility(boolean visible) { + for(CfgNode n : this.selectedNodes){ + EdgeSwitchWidget in = this.inputSwitches.get(n); + EdgeSwitchWidget out = this.outputSwitches.get(n); + if(in != null) in.changeEdgeVisibility(visible); + if(out != null) out.changeEdgeVisibility(visible); + } + this.fireSelectionChanged(); + this.validate(); + } + + public EdgeSwitchWidget getInputSwitch(CfgNode n){ + return this.inputSwitches.get(n); + } + public EdgeSwitchWidget getOutputSwitch(CfgNode n){ + return this.outputSwitches.get(n); + } + + public CfgEnv getCfgEnv() { + return env; + } + + public boolean isLoopClusterVisible() { + return loopClustersVisible; + } + + public void setLoopWidgets(boolean visible) { + for(Widget w : this.loopidx2clusterwidget.values()){ + w.setVisible(visible); + w.revalidate(); + } + this.loopClustersVisible=visible; + this.validate(); + } + + public void setRouter(int newRouter){ + if(newRouter == this.currentRouter) return; + + this.currentRouter=newRouter; + + Router router; + + switch (newRouter) { + case CfgEditorContext.ROUTING_BEZIER: + router = new PolylineRouterV2(new WidgetCollisionCollector() { + public void collectCollisions(List collisions) { + collisions.addAll(getNodeWidgets()); + } + }); + break; + case CfgEditorContext.ROUTING_DIRECTLINES: + router = RouterFactory.createDirectRouter(); + break; + default: + throw new IllegalStateException ("Unknown Router ID: " + newRouter); // NOI18N + } + + for(CfgEdge e : this.getEdges()){ + EdgeWidget ew = (EdgeWidget) this.findWidget(e); + ew.setRouter(router); + } + this.validate(); + } + + + + public Collection getNodeWidgets() { + if(nodeWidgets != null && nodeWidgets.size()==this.getNodes().size()) return nodeWidgets; + + List widgets = new ArrayList(); + for(CfgNode n : this.getNodes()){ + NodeWidget w = (NodeWidget) this.findWidget(n); + widgets.add(w); + } + + nodeWidgets = Collections.unmodifiableList(widgets); + return widgets; + } + + + + public void setSceneLayout(int newLayout){ + + if(currentLayout == newLayout) return; + + GraphLayout graphLayout=null; + + switch (newLayout) { + case CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT: + graphLayout = new HierarchicalNodeLayout(this); + break; + + case CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT: + graphLayout = new HierarchicalCompoundLayout(this); + break; + } + + this.currentLayout=newLayout; + if(graphLayout != null) + this.sceneLayout=LayoutFactory.createSceneGraphLayout(this, graphLayout); + } + + + @Override + protected void attachEdgeSourceAnchor(CfgEdge edge, CfgNode oldSourceNode, CfgNode sourceNode) { + Anchor sourceAnchor; + EdgeWidget edgeWidget = (EdgeWidget) findWidget (edge); + Widget sourceWidget = findWidget(sourceNode); + + if (edge.isSymmetric()) { + sourceAnchor = new SymmetricAnchor(sourceWidget, true, true); + } else { + sourceAnchor = AnchorFactory.createRectangularAnchor(sourceWidget); + } + edgeWidget.setSourceAnchor (sourceAnchor); + } + + @Override + protected void attachEdgeTargetAnchor(CfgEdge edge, CfgNode oldtarget, CfgNode targetNode) { + Anchor targetAnchor; + ConnectionWidget edgeWidget = (ConnectionWidget) findWidget (edge); + Widget targetWidget = findWidget(targetNode); + + if (edge.isSymmetric()) { + targetAnchor = new SymmetricAnchor(targetWidget, true, false); + } else { + targetAnchor = AnchorFactory.createRectangularAnchor(targetWidget); + } + edgeWidget.setTargetAnchor (targetAnchor); + } + + + @Override + protected Widget attachEdgeWidget(CfgEdge edge) { + EdgeWidget widget = new EdgeWidget(this, edge); + connectionLayer.addChild(widget); + attachSourceSwitchWidget(edge); + attachTargetSwitchWidget(edge); + return widget; + } + + + + @Override + protected Widget attachNodeWidget(CfgNode node) { + this.nodeWidgets = null; + + NodeWidget nw = new NodeWidget(this,node); + WidgetAction.Chain actions = nw.getActions(); + actions.addAction(this.contextPopupAction); + actions.addAction(this.moveAction); + actions.addAction(this.createObjectHoverAction()); + + if ( node.isLoopMember() ) { + LoopClusterWidget loopWidget = this.attachLoopMember(node); + loopWidget.addMember(nw); + } + mainLayer.addChild(nw); + return nw; + } + + + private LoopClusterWidget attachLoopMember(CfgNode node) { + LoopClusterWidget lw = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if(lw == null) { + lw = new LoopClusterWidget(this, node.getLoopDepth(), node.getLoopIndex()); + this.loopidx2clusterwidget.put(node.getLoopIndex(), lw); + this.clusterLayer.addChild(lw); + } + return lw; + } + + + private boolean detachLoopMember(CfgNode node, NodeWidget nodeWidget) { + LoopClusterWidget rm = this.loopidx2clusterwidget.get(node.getLoopIndex()); + if( rm == null) return false;//not added + + if ( rm.removeMember(nodeWidget) ) { + if(rm.getMembers().size() == 0){ + this.loopidx2clusterwidget.remove(rm.getLoopIndex()); + List childs = new ArrayList(rm.getChildren()); + for (Widget w : childs){//append stacked loopwidgets + w.removeFromParent(); + rm.getParentWidget().addChild(w); + } + rm.removeFromParent(); + } + return true; + } + return false; + } + + //this function is not invoked by any class of the module + //however to ensure that the edge switches are treatet corretly + //when a future version removes nodes it was implemented too. + + @Override + protected void detachNodeWidget(CfgNode node, Widget nodeWidget) { + if(node.isLoopMember() && nodeWidget instanceof NodeWidget ) { + this.detachLoopMember(node,(NodeWidget)nodeWidget); + } + super.detachNodeWidget(node, nodeWidget); + assert nodeWidget.getParentWidget()== null; + if(this.inputSwitches.containsKey(node)) { + EdgeSwitchWidget esw = this.inputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + if(this.outputSwitches.containsKey(node)){ + EdgeSwitchWidget esw = this.outputSwitches.remove(node); + this.connectionLayer.removeChild(esw); + } + } + + protected EdgeSwitchWidget attachSourceSwitchWidget(CfgEdge e){ + CfgNode sourceNode = e.getSourceNode(); + NodeWidget sourceWidget = (NodeWidget) this.findWidget(sourceNode); + EdgeSwitchWidget out = outputSwitches.get(sourceNode); + if (out==null) { + out = new EdgeSwitchWidget(this, sourceWidget, true); + this.connectionLayer.addChild(out); + outputSwitches.put(sourceNode, out); + } + return out; + } + + + protected EdgeSwitchWidget attachTargetSwitchWidget(CfgEdge e){ + CfgNode targetNode = e.getTargetNode(); + NodeWidget targetWidget = (NodeWidget) this.findWidget(targetNode); + EdgeSwitchWidget in = inputSwitches.get(targetNode); + if (in==null) { + in = new EdgeSwitchWidget(this, targetWidget, false); + this.connectionLayer.addChild(in); + inputSwitches.put(targetNode, in); + } + return in; + } + + //resets the selection state of all NodeWidgets + private void cleanNodeSelection(){ + if( this.selectedNodes.size() != 0) { + this.userSelectionSuggested(Collections.emptySet(), false); + this.selectedNodes = Collections.emptySet(); + this.fireSelectionChanged(); + this.validate(); + } + } + + + //sets the scene & global node selection + public void setNodeSelection(Set newSelection){ + this.setSceneSelection(newSelection); + this.updateGlobalSelection(); + } + + //sets the scene selection + private void setSceneSelection(Set newSelection){ + if(newSelection.equals(selectedNodes)) return; + + this.selectedNodes=newSelection; + + Set selectedObjects = new HashSet(); + + for(CfgNode n : newSelection){ + selectedObjects.addAll(this.findNodeEdges(n, true, true)); + } + selectedObjects.addAll(newSelection); + + //if the selection gets updated from a change in the block view + //the scene will be centered + if(selectionUpdating) + this.centerSelection(); + + this.userSelectionSuggested(selectedObjects, false); + this.fireSelectionChanged(); + this.validate(); + } + + //updates selection of Block View + public void updateGlobalSelection() { + // TODO(tw): Add selection management. +// Selection selection = SelectionManager.getDefault().getCurSelection(); +// ArrayList newBlocks = new ArrayList(); +// for (CfgNode n : this.selectedNodes) { +// newBlocks.add(n.getBasicBlock()); +// } +// BasicBlock[] curBlocks = newBlocks.toArray(new BasicBlock[newBlocks.size()]); +// selection.put(curBlocks); + } + + private boolean selectionUpdating = false; + + //change of blockview selection + public void stateChanged(ChangeEvent event) { + if (selectionUpdating) { + return; + } + + selectionUpdating = true; + + Object source = event.getSource(); +// if(source instanceof Selection){ +// Selection selection=(Selection) source; +// Set newSelection = new HashSet(); +// BasicBlock[] newBlocks = selection.get(BasicBlock[].class); +// if (newBlocks != null) { +// for(BasicBlock b : newBlocks){ +// for(CfgNode n : this.getNodes()){ +// if(n.getBasicBlock() == b) newSelection.add(n); +// } +// } +// this.setSceneSelection(newSelection); +// } +// } + selectionUpdating = false; + // TODO(tw): Add selection management. + } + + //centers the viewport on the currently selected nodewidgets + private void centerSelection(){ + Point sceneCenter = null; + Collection nodes = this.selectedNodes; + if(nodes.size()==0) { + nodes = this.getNodes(); + } + + for(CfgNode n : nodes) { + if(sceneCenter==null) { + sceneCenter = this.findWidget(n).getLocation(); + continue; + } + Point location = this.findWidget(n).getLocation(); + sceneCenter.x = (location.x+sceneCenter.x)/2; + sceneCenter.y = (location.y+sceneCenter.y)/2; + } + + JComponent view = this.getView (); + if (view != null) { + Rectangle viewBounds = view.getVisibleRect (); + + Point viewCenter = this.convertSceneToView (sceneCenter); + + view.scrollRectToVisible (new Rectangle ( + viewCenter.x - viewBounds.width / 2, + viewCenter.y - viewBounds.height / 2, + viewBounds.width, + viewBounds.height + )); + } + } + + //animated scene Zoom to the max bounds of current viewport + public void zoomScene(){ + JScrollPane pane = this.cfgtc.getJScrollPanel(); + + Rectangle prefBounds = this.getPreferredBounds(); + Dimension viewDim = pane.getViewportBorderBounds().getSize(); + + double realwidth = (double)prefBounds.width*this.getZoomFactor(); + double realheight = (double)prefBounds.height*this.getZoomFactor(); + + double zoomX = (double)viewDim.width / realwidth; + double zoomY = (double)viewDim.height / realheight; + double zoomFactor = Math.min(zoomX, zoomY); + + this.animateZoom(zoomFactor*0.9); + } + + + //animated animateZoom function for scene animateZoom factor + public void animateZoom(double zoomfactor) { + this.getSceneAnimator().animateZoomFactor(this.getZoomFactor() * zoomfactor); + } + + public void addCfgEventListener(CfgEventListener l) { + listenerList.add(CfgEventListener.class, l); + } + + public void removeCfgEventListener(CfgEventListener l) { + listenerList.remove(CfgEventListener.class, l); + } + + public void fireSelectionChanged() { + Object[] listeners = listenerList.getListenerList(); + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==CfgEventListener.class) { + ((CfgEventListener)listeners[i+1]).selectionChanged(this); + } + } + } + + + //Enables Antialiasing + @Override + public void paintChildren () { + Object anti = getGraphics ().getRenderingHint (RenderingHints.KEY_ANTIALIASING); + Object textAnti = getGraphics ().getRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING); + + getGraphics ().setRenderingHint ( + RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + getGraphics ().setRenderingHint ( + RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + super.paintChildren (); + + getGraphics ().setRenderingHint (RenderingHints.KEY_ANTIALIASING, anti); + getGraphics ().setRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING, textAnti); + } + + + //select provider for node selection + private RectangularSelectProvider createRectangularSelectProvider() { + return new RectangularSelectProvider() { + public void performSelection(Rectangle rectangle) { + HashSet set=new HashSet(); + + //change to a rectangle with (x,offsetY) at the top left + if(rectangle.width < 0){ + rectangle.x=rectangle.x+rectangle.width; + rectangle.width*=-1; + } + if(rectangle.height < 0){ + rectangle.y=rectangle.y+rectangle.height; + rectangle.height*=-1; + } + + for(NodeWidget n: getNodeWidgets()) { + Point p = n.getLocation(); + if (p != null && rectangle.contains(p)) { + set.add(n.getNodeModel()); + } + } + setNodeSelection(set); + } + }; + } + + //select decorator for node selection + private RectangularSelectDecorator createSelectDecorator(final CfgScene scene){ + return new RectangularSelectDecorator() { + public Widget createSelectionWidget() { + scene.cleanNodeSelection();//unselected all nodes + scene.revalidate(); + return new SelectionWidget(getScene()); + } + }; + } + + + private MoveProvider createMoveProvider() { + return new MoveProvider(){ + private HashMap originals = new HashMap(); + + private Point original=null; + + public void movementStarted(Widget widget) { + originals.clear(); + NodeWidget nw = (NodeWidget) widget; + if(selectedNodes.contains(nw.getNodeModel())) {//move current selection + for(CfgNode n : selectedNodes){ + Widget w = findWidget(n); + originals.put(w, w.getLocation()); + } + } else {//a newly-selected node will be moved + CfgNode n = nw.getNodeModel(); + HashSet selectedNode = new HashSet(1); + selectedNode.add(n); + setNodeSelection(selectedNode); + originals.put(widget, widget.getPreferredLocation()); + widget.revalidate(); + validate(); + + } + } + + public void movementFinished(Widget widget) { + NodeWidget nw = (NodeWidget) widget; + if(selectedNodes.contains(nw.getNodeModel())) { + return;//to be able to move the current selection + } + + HashSet selectedNode = new HashSet(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + originals.clear (); + original = null; + + } + + public Point getOriginalLocation(Widget widget) { + if(original==null) + original = widget.getLocation(); + + return original; + } + //todo : find a cache algorithm which only routes edges + //which are intersected by bounds of the moved rectangle + public void setNewLocation(Widget widget, Point location) { + Point org = getOriginalLocation(widget); + int dx = location.x - org.x; + int dy = location.y - org.y; + for (Map.Entry entry : originals.entrySet ()) { + Point point = entry.getValue (); + entry.getKey ().setPreferredLocation (new Point (point.x + dx, point.y + dy)); + } + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) findWidget(e); + if(ew.isVisible()) + ew.reroute(); + } + } + }; + } + + + private WidgetAction createContextMenuAction(final CfgScene scene) { + return ActionFactory.createPopupMenuAction(new PopupMenuProvider() { + public JPopupMenu getPopupMenu(Widget widget, Point point) { + JPopupMenu menu = new JPopupMenu(); + NodeWidget nw = null; + if(widget instanceof NodeWidget) { + nw = (NodeWidget) widget; + if(!selectedNodes.contains(nw.getNodeModel())){ + HashSet selectedNode = new HashSet(1); + selectedNode.add(nw.getNodeModel()); + setNodeSelection(selectedNode); + } + } else if (scene.getSelectedNodes().size() == 1) { + nw = (NodeWidget) scene.findWidget(scene.getSelectedNodes().iterator().next()); + } + + if(nw != null){ + CfgNode node = nw.getNodeModel(); + ArrayList successors = new ArrayList(); + ArrayList predecessors = new ArrayList(); + for(CfgEdge e : node.getOutputEdges()){ + successors.add(e.getTargetNode()); + } + for(CfgEdge e : node.getInputEdges()){ + predecessors.add(e.getSourceNode()); + } + + if(predecessors.size()>0){ + Collections.sort(predecessors, new NodeNameComparator()); + JMenu predmenu = new JMenu("Go to predecessor"); + for (CfgNode n : predecessors) { + GotoNodeAction action = new GotoNodeAction(n); + predmenu.add(action); + } + menu.add(predmenu); + } + if(successors.size()>0){ + Collections.sort(successors, new NodeNameComparator()); + JMenu succmenu = new JMenu("Go to successor"); + for (CfgNode n : successors) { + GotoNodeAction action = new GotoNodeAction(n); + succmenu.add(action); + } + menu.add(succmenu); + } + if ( successors.size() > 0 || predecessors.size() > 0) + menu.addSeparator(); + } + + menu.add(SystemAction.get(ShowEdgesAction.class)); + menu.add(SystemAction.get(HideEdgesAction.class)); + menu.addSeparator(); + menu.add(SystemAction.get(ColorAction.class).getPopupPresenter()); + return menu; + } + }); + } + + private class NodeNameComparator implements Comparator { + public int compare(CfgNode node1, CfgNode node2) { + String name1 = node1.getBasicBlock().getName().substring(1); + String name2 = node2.getBasicBlock().getName().substring(1); + Integer blocknum1 = Integer.parseInt(name1); + Integer blocknum2 = Integer.parseInt(name2); + return blocknum1.compareTo(blocknum2); + } + } + + private class GotoNodeAction extends AbstractAction { + CfgNode node ; + + GotoNodeAction(CfgNode node){ + super(node.getBasicBlock().getName()); + this.node = node; + } + public void actionPerformed(ActionEvent e) { + Set nodes = new HashSet(1); + nodes.add(node); + setNodeSelection(nodes); + centerSelection(); + } + } + + private SceneListener createSceneListener(final CfgScene scene){ + return new SceneListener() { + + public void sceneRepaint() { + } + + public void sceneValidating() { + } + + public void sceneValidated() { + if (scene.isLoopClusterVisible()){ //update only if visible + for(LoopClusterWidget cw : getLoopidx2clusterwidget().values()){ + cw.updateClusterBounds(); + } + } + for(EdgeSwitchWidget esw : inputSwitches.values()){ + esw.updatePosition(); + } + + for(EdgeSwitchWidget esw : outputSwitches.values()){ + esw.updatePosition(); + } + } + }; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeSwitchWidget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeSwitchWidget.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,291 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; +import java.util.Collection; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.SelectProvider; +import org.netbeans.api.visual.action.TwoStateHoverProvider; +import org.netbeans.api.visual.action.WidgetAction; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + + +public class EdgeSwitchWidget extends Widget { + private final static Color color_enabled = Color.gray; + private final static Color color_hover = Color.lightGray; + private float width=1; + private float height=1; + private CfgScene scene; + private NodeWidget nodeWidget; + private boolean output; + private WidgetAction hoverAction; + private static final String TT_HIDE_EDGES = "Hide Edges"; + private static final String TT_SHOW_EDGES = "Show Edges"; + private static SelectProvider selectProvider = createSelectProvider(); + + + public EdgeSwitchWidget(final CfgScene scene, NodeWidget nodeWidget, boolean output) { + super(scene); + this.scene = scene; + this.output = output; + this.nodeWidget = nodeWidget; + + this.getActions().addAction(ActionFactory.createSelectAction(selectProvider)); + TwoStateHoverProvider ts = new TsHover(this); + WidgetAction wa = ActionFactory.createHoverAction(ts); + this.hoverAction = wa; + this.getActions().addAction(wa); + scene.getActions().addAction(wa); + this.setToolTipText(TT_HIDE_EDGES); + this.setForeground(color_enabled); + this.setState(ObjectState.createNormal()); + } + + + @Override + protected Rectangle calculateClientArea() { + if (this.nodeWidget.getBounds() == null) return new Rectangle(0, 0, 1, 1); + int hw = (int) (this.width / 2); + int hh = (int) (this.height /2); + + return new Rectangle(-hw, -hh, 2*hw, 2*hh); + } + + + public void updatePosition() { + if (this.nodeWidget.getBounds() != null) { + this.width = nodeWidget.getBounds().width*9; + this.width /=10; + this.height = nodeWidget.getBounds().height/4; + int offset=(int)(2 * (height / 3)); + + Rectangle bounds = nodeWidget.getBounds(); + Point location = nodeWidget.getLocation(); + + Point newLoc = new Point(); + newLoc.x = location.x; + + if(output) { + newLoc.y = +location.y + bounds.height/2+offset; + }else { + newLoc.y = location.y - bounds.height/2-offset; + } + this.setPreferredLocation(newLoc); + } + } + + private Collection getEdges(){ + Collection edges; + CfgNode node = nodeWidget.getNodeModel(); + if (output) { + edges = scene.findNodeEdges(node, true, false); + } else { + edges = scene.findNodeEdges(node, false, true); + } + return edges; + } + + //change visibility for all Edges + public void changeEdgeVisibility(boolean visible){ + Collection edges = this.getEdges(); + + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(visible != ew.isEdgeVisible()){ + ew.setEdgeVisible(visible); + if(output){ + scene.getInputSwitch(e.getTargetNode()).updateStatus(); + } else { + scene.getOutputSwitch(e.getSourceNode()).updateStatus(); + } + } + } + if(visible) + this.setToolTipText(TT_HIDE_EDGES); + else + this.setToolTipText(TT_SHOW_EDGES); + + this.setForeground(color_enabled); + this.bringToBack(); + ObjectState os = this.getState(); + this.setState(os.deriveSelected(!visible)); + } + + /** + * Update the status of the switch to the current state of the edges + * usually needed when the opposit switch changes the state + */ + private void updateStatus(){ + Collection edges = this.getEdges(); + boolean hiddenFound=false; + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!ew.isVisible()) { + hiddenFound=true; + break; + } + } + ObjectState os = this.getState(); + if(os.isSelected() && !hiddenFound) { + this.setState(os.deriveSelected(false)); + setToolTipText(TT_HIDE_EDGES); + } else if (!os.isSelected() && hiddenFound) { + this.setState(os.deriveSelected(true)); + setToolTipText(TT_SHOW_EDGES); + } + this.revalidate(); + } + + + public void startPreview() { + ObjectState os = this.getState(); + + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(!os.isSelected() || !ew.isVisible()){ + ObjectState edgeState = ew.getState(); + ew.setState(edgeState.deriveHighlighted(true)); + } + } + } + + public void endPreview(){ + for(CfgEdge e : getEdges()) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + ObjectState os = ew.getState(); + ew.setState(os.deriveHighlighted(false)); + } + } + + /** + * shows or hides the edges of the switch + */ + public void switchEdges() { + endPreview(); + ObjectState os = this.getState(); + Collection edges = this.getEdges(); + ArrayList updates = new ArrayList(); + boolean visible=os.isSelected(); + this.setState(os.deriveSelected(!visible)); + for(CfgEdge e: edges) { + EdgeWidget ew = (EdgeWidget) scene.findWidget(e); + if(ew.isEdgeVisible() != visible){ + updates.add(e); + ew.setEdgeVisible(visible); + if(output){ + scene.getInputSwitch(e.getTargetNode()).updateStatus(); + } else { + scene.getOutputSwitch(e.getSourceNode()).updateStatus(); + } + } + } + if(visible) + this.setToolTipText(TT_HIDE_EDGES); + else + this.setToolTipText(TT_SHOW_EDGES); + + scene.fireSelectionChanged();//updates Edge visibility for context action + revalidate(); + } + + + + + private class TsHover implements TwoStateHoverProvider { + EdgeSwitchWidget tw; + + TsHover(EdgeSwitchWidget tw) { + this.tw = tw; + } + + public void unsetHovering(Widget w) { + w.setForeground(color_enabled); + ObjectState state = w.getState(); + w.setState(state.deriveWidgetHovered(false)); + w.bringToBack(); + endPreview(); + } + + public void setHovering(Widget w) { + ObjectState state = w.getState(); + w.setState(state.deriveWidgetHovered(true)); + w.setForeground(color_hover); + w.bringToFront(); + nodeWidget.bringToFront(); + startPreview(); + } + } + + @Override + public void paintWidget() { + ObjectState os = this.getState(); + if(!os.isHovered() && !os.isSelected()) return; //all previewEdges visible and not hovering, + //no need to paint the switch + float hw = width/2; + Polygon pol = new Polygon(); + pol.addPoint(0,(int) -height/2); + pol.addPoint((int)hw,(int) height/2); + pol.addPoint((int)-hw,(int) height/2); + Graphics2D gr = getGraphics(); + gr.setColor(this.getForeground()); + BasicStroke bs = new BasicStroke(2.0f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND); + gr.setStroke(bs); + AffineTransform previousTransform; + previousTransform = gr.getTransform (); + if(output) { + if(os.isSelected() ){//hidden + gr.scale(1.0, -1.0); + } + } else { //input switch + if(os.isHovered() && !os.isSelected()){ + gr.scale(1.0, -1.0); + } + } + gr.fillPolygon(pol); + gr.setTransform(previousTransform); + + } + + + + //the constructor adds the hover WidgetAction to the scene + //the action is removed from the scene when the object gets destroyed + @Override + protected void finalize() throws Throwable { + this.getScene().getActions().removeAction(hoverAction); + this.getActions().removeAction(hoverAction); + } + + @Override + public String toString(){ + return "EDGESWITCH("+this.nodeWidget.getNodeModel().toString()+")"; + } + + private static SelectProvider createSelectProvider() { + return new SelectProvider(){ + public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) { + return false; + } + + public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) { + return true; + } + + public void select(Widget w, Point arg1, boolean arg2) { + if(w instanceof EdgeSwitchWidget){ + EdgeSwitchWidget tw = (EdgeSwitchWidget) w; + tw.switchEdges(); + } + } + }; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeWidget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeWidget.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,97 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import at.ssw.visualizer.cfg.visual.BezierWidget; +import at.ssw.visualizer.cfg.visual.SplineConnectionWidget; +import org.netbeans.api.visual.anchor.AnchorShapeFactory; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Stroke; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.model.ObjectState; + +//public class EdgeWidget extends BezierWidget { +public class EdgeWidget extends SplineConnectionWidget { + + private boolean visible=true;//to store the visible state when entering the preview + protected static final Stroke selectedStroke = new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + protected static final Stroke defaultStroke = new BasicStroke(1.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + protected static final Stroke previewStroke = new BasicStroke( + 0.5f, // Width + BasicStroke.CAP_SQUARE, // End cap + BasicStroke.JOIN_MITER, // Join style + 10.0f, // Miter limit + new float[] {5.0f, 5.0f}, // Dash pattern + 0.0f); + + + + public EdgeWidget(CfgScene scene, CfgEdge edge) { + super(scene); + Color lineColor; + CfgPreferences prefs = CfgPreferences.getInstance(); + + if(edge.isBackEdge()) + lineColor = prefs.getBackedgeColor(); + else if (edge.isXhandler()) + lineColor = prefs.getExceptionEdgeColor(); + else + lineColor = prefs.getEdgeColor(); + + setLineColor(lineColor); + AnchorShape as; + if(edge.isReflexive())//small Arrow + as = AnchorShapeFactory.createTriangleAnchorShape(6, true, false, 5); + else + as =AnchorShapeFactory.createTriangleAnchorShape(10, true, false, 9); + + setTargetAnchorShape(as); + setToolTipText(edge.toString()); + } + + public CfgEdge getEdgeModel() { + CfgScene scene = (CfgScene) this.getScene(); + return (CfgEdge) scene.findObject(this); + } + + public void setEdgeVisible(boolean visible) { + this.visible=visible; + this.setVisible(visible); + this.reroute(); + this.revalidate(); + } + + + public boolean isEdgeVisible(){ + return visible; + } + + + @Override + public void notifyStateChanged(ObjectState oldState, ObjectState newState) { + setForeground (getLineColor()); + + if(newState.isHighlighted() && !oldState.isHighlighted()){ + this.setStroke(previewStroke); + this.setVisible(true); + } else { + if(newState.isSelected()){ + this.setStroke(selectedStroke); + } else { + this.setStroke(defaultStroke); + } + if(this.isEdgeVisible()){ + this.setVisible(true); + } else { + this.setVisible(false); + } + } + } + + + @Override + public String toString(){ + return "EdgeWidget[" + getEdgeModel().toString() + "]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/LoopClusterWidget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/LoopClusterWidget.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,107 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Color; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.action.EditProvider; +import org.netbeans.api.visual.border.BorderFactory; +import org.netbeans.api.visual.widget.Widget; + +public class LoopClusterWidget extends Widget implements Comparable { + private static final int INSET = 10;//min space between node members and cluster border + private static final int DASHSIZE = 10; + private Color color = Color.BLUE; + private int loopIndex; + private int loopDepth; + private CfgScene cfgscene; + private ArrayList members = new ArrayList(); + + public LoopClusterWidget(CfgScene scene, int loopdepth, final int loopindex) { + super(scene); + this.cfgscene = scene; + this.loopIndex = loopindex; + this.loopDepth = loopdepth; + this.setBorder(BorderFactory.createDashedBorder(color, DASHSIZE, DASHSIZE/2, true)); + this.getActions().addAction(ActionFactory.createEditAction( new EditProvider() { //double click action + public void edit(Widget w) { + if(w instanceof LoopClusterWidget){ + for(LoopInfo info : cfgscene.getCfgEnv().getLoopMap().values()){ + if(info.getLoopIndex() == loopindex){ + cfgscene.setNodeSelection(info.getMembers()); + break; + } + } + } + } + })); + + } + + public List getMembers() { + return members; + } + + public int getLoopIndex() { + return loopIndex; + } + + public void addMember(NodeWidget nw) { + assert(!this.members.contains(nw)); + members.add(nw); + } + + public boolean removeMember(NodeWidget nw) { + if(this.members.contains(nw)){ + members.remove(nw); + return true; + } + return false; + } + + public void setrandomColor(){ + if(this.loopDepth == 0 ) return; + Random rand = new Random(); + Color randColor = Color.getHSBColor(rand.nextFloat()%360,0.1f,1.0f); + this.setBackground(randColor); + } + + //updates the bounds of the widget, + //and revalidates the widget if a membernode changed the scene position + public void updateClusterBounds(){ + Rectangle boundRect=null; + + for(NodeWidget nw : this.members){ + if(boundRect==null){ + boundRect = nw.convertLocalToScene(nw.getBounds()); + } else { + boundRect = boundRect.union(nw.convertLocalToScene(nw.getBounds())); + } + } + if(boundRect==null) return; + for(Widget w : this.getChildren()) { + if(w instanceof LoopClusterWidget) { + LoopClusterWidget lc = (LoopClusterWidget)w; + lc.updateClusterBounds(); + boundRect = boundRect.union(w.convertLocalToScene(w.getBounds())); + } + } + + boundRect.grow(INSET, INSET); + this.setPreferredBounds(boundRect); + } + + + public int compareTo(LoopClusterWidget o) { + return new Integer(this.loopDepth).compareTo(o.loopDepth); + } + + + @Override + public String toString(){ + return "LoopCluster: [DEPTH "+this.loopDepth+ "] [INDEX "+this.loopIndex+"]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/NodeWidget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/NodeWidget.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,155 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; +import org.netbeans.api.visual.border.BorderFactory; +import org.netbeans.api.visual.model.ObjectState; +import org.netbeans.api.visual.widget.Widget; + + +public class NodeWidget extends Widget { + + + //basic block node dimension + private final int halfheight=12; + private final int halfwidth=17; + + private final int height=halfheight*2+1; + private final int width=halfwidth*2+1; + private final int arcHeight=(halfheight/4)*3; + private final int arcWidth = arcHeight; + private final int FONT_MAXSIZE=18; + + private int borderWidth; + private boolean selected=false; + private boolean nodeColorCustomized; + private String text; + private Rectangle2D fontRect; + private Color nodeColor; + + protected static final Color HOVER_BACKGROUND = new Color(0xEEEEEE); + protected static final Color HOVER_FOREGROUND = new Color(0xCDCDCD); + + public NodeWidget(CfgScene scene, CfgNode nodeModel ){ + super(scene); + this.setToolTipText("" + nodeModel.getDescription().replaceAll("\n", "
") + ""); + this.selected=false; + this.text = nodeModel.getBasicBlock().getName(); + this.borderWidth = nodeModel.getLoopDepth()+1; + this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, Color.BLACK, Color.BLACK)); + CfgPreferences prefs = CfgPreferences.getInstance(); + Color color = prefs.getFlagsSetting().getColor(nodeModel.getBasicBlock().getFlags()); + this.nodeColorCustomized = (color!=null); + this.nodeColor = (nodeColorCustomized) ? color : prefs.getNodeColor(); + this.adjustFont(null); + } + + public void setBorderColor(Color color){ + this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, color, color)); + } + + public boolean isNodeColorCustomized() { + return nodeColorCustomized; + } + + //sets a customColor node color + public void setNodeColor(Color color, boolean customColor) { + this.nodeColorCustomized=customColor; + this.nodeColor=color; + this.revalidate(); + } + + public Color getNodeColor() { + return this.nodeColor; + } + + public CfgNode getNodeModel() { + CfgScene scene = (CfgScene) this.getScene(); + return (CfgNode) scene.findObject(this); + } + + + @Override + public void notifyStateChanged(ObjectState oldState, ObjectState newState) { + if(!oldState.equals(newState)) + this.revalidate(); + if(!oldState.isSelected() && newState.isSelected()) + this.bringToFront(); + } + + @Override + protected Rectangle calculateClientArea() { + return new Rectangle(-(halfwidth+1), -(1+halfheight), width+1, height+1);//add border + } + + public void adjustFont(Font font){ + if(font==null) + font = CfgPreferences.getInstance().getTextFont(); + if(font.getSize()>FONT_MAXSIZE){ + font = new Font(font.getFamily(), font.getStyle(), FONT_MAXSIZE); + } + int size=font.getSize(); + int fontStyle = font.getStyle(); + String fontName = font.getFamily(); + FontRenderContext frc = new FontRenderContext(new AffineTransform(), false, false); + Rectangle2D bounds = font.getStringBounds(text, frc); + while(size > 1 && bounds.getWidth() > width) { + font = new Font(fontName, fontStyle, --size); + bounds = font.getStringBounds(text, frc); + } + this.fontRect=bounds; + this.setFont(font); + } + + @Override + protected void paintWidget() { + Graphics2D gr = getGraphics(); + gr.setColor(nodeColor); + Insets borderInsets = this.getBorder().getInsets(); + RoundRectangle2D.Float innerRect = new RoundRectangle2D.Float(-(halfwidth+1), -(halfheight+1), width+1, height+1,arcWidth-1, arcHeight-1); + gr.fill(innerRect); + gr.setColor(getForeground()); + gr.setFont(getFont()); + float textX = (float)( - fontRect.getCenterX()); + float textY = (float)( - fontRect.getCenterY()); + gr.drawString(text, textX, textY); + + RoundRectangle2D.Float outerRect = new RoundRectangle2D.Float(-(halfwidth+borderInsets.left + 1), -(halfheight+borderInsets.top + 1), + width+borderInsets.left + borderInsets.right + 1, height + borderInsets.top + borderInsets.bottom + 1, + arcWidth + borderWidth, arcHeight + borderWidth); + + ObjectState os =this.getState(); + if(os.isSelected()){ + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); + gr.fill(outerRect); + gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); + gr.setComposite(composite); + } + if(os.isHovered()){ + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + gr.setColor(HOVER_FOREGROUND); + gr.fill(outerRect); + gr.setColor(HOVER_BACKGROUND); + gr.setComposite(composite); + } + } + + @Override + public String toString() { + return "NodeWidget[" + getNodeModel().getBasicBlock().getName() + "]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SelectionWidget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SelectionWidget.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,39 @@ +package at.ssw.visualizer.cfg.graph; + +import at.ssw.visualizer.cfg.preferences.CfgPreferences; +import java.awt.AlphaComposite; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +public class SelectionWidget extends Widget { + public SelectionWidget(Scene scene) { + super(scene); + } + + public static void renderSelectedRect(Graphics2D gr, Rectangle rect) { + if (rect == null) { + return; + } + gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); + gr.fillRect(rect.x, rect.y, rect.width, rect.height); + gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); + } + + public void renderSelectionRectangle(Graphics2D gr, Rectangle selectionRectangle) { + Composite composite = gr.getComposite(); + gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); + + renderSelectedRect(gr, selectionRectangle); + gr.setComposite(composite); + } + + @Override + public void paintWidget(){ + this.renderSelectionRectangle(this.getGraphics(), this.getBounds()); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SymmetricAnchor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SymmetricAnchor.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,157 @@ +package at.ssw.visualizer.cfg.graph; + +import org.netbeans.api.visual.widget.Widget; +import org.netbeans.api.visual.anchor.Anchor; +import java.awt.*; + + +/** + * This Anchor can be used with symmetric edges to create parallel Edges. + * Two Directed Edges are symmetric if they are connecting the same Nodes in different directions. + * e.g. Nodes (1, 2) Edges(a , b) with (1)-a->(2) , (2)-b->(1) + * Start-/End positions are calculated with a fixed offset to prevent edges from overlapping. + * If the edges are drawn as straight lines they will appear as parallel edges. + */ + +public final class SymmetricAnchor extends Anchor { + + private final static int OFFSET = 10; + private boolean includeBorders; + private int offx; + private int offy; + + public SymmetricAnchor (Widget widget, boolean includeBorders, boolean source) { + super (widget); + this.includeBorders = includeBorders; + if (source) { + offx = OFFSET; + offy = OFFSET; + } + else { + offx = -OFFSET; + offy = -OFFSET; + } + } + + public Result compute (Entry entry) { + Point relatedLocation = //center of the widget + getRelatedSceneLocation (); + Point oppositeLocation = //center of the widget + getOppositeSceneLocation (entry); + + Widget widget = getRelatedWidget (); + Rectangle bounds = widget.getBounds (); + if (! includeBorders) { + Insets insets = widget.getBorder ().getInsets (); + bounds.x += insets.left; + bounds.y += insets.top; + bounds.width -= insets.left + insets.right; + bounds.height -= insets.top + insets.bottom; + } + + bounds = widget.convertLocalToScene (bounds); + + if (bounds.isEmpty () || relatedLocation.equals (oppositeLocation)) + return new Anchor.Result (relatedLocation, Anchor.DIRECTION_ANY); + + float dx //distance x-axis + = oppositeLocation.x - relatedLocation.x; + float dy //distance y-axis + = oppositeLocation.y - relatedLocation.y; + + + float ddx + = Math.abs (dx) / (float) bounds.width; + float ddy = + Math.abs (dy) / (float) bounds.height; + + Anchor.Direction direction; + + + if (ddx >= ddy) { + if(dx >= 0.0f){ + direction = Direction.RIGHT; + relatedLocation.y -= offy; + } else { + direction = Direction.LEFT; + relatedLocation.y += offy; + } + } else { + if(dy >= 0.0f){ + direction = Direction.BOTTOM; + relatedLocation.x += offx; + } else { + direction = Direction.TOP; + relatedLocation.x -= offx; + } + } + + + float scale = 0.5f / Math.max (ddx, ddy); + + float ex = scale * dx; + float ey = scale * dy; + + Point point = new Point (Math.round (relatedLocation.x + ex), Math.round (relatedLocation.y + ey)); + + if(direction == Direction.RIGHT) { + int top = bounds.y;//-bounds.height;// left y of the widget + int bottom = bounds.y + bounds.height;// right y of the widget + if(point.y < top) {//above the widget + int cor = top-point.y; + point.x -= cor; + point.y += cor; + } else if ( point.y > bottom) { + int cor = point.y-bottom; + point.x -= cor; + point.y -= cor; + } + + } else if (direction == Direction.LEFT) { + int top = bounds.y;//-bounds.height;// left y of the widget + int bottom = bounds.y + bounds.height;// right y of the widget + + + + if(point.y < top) {//above the widget + int cor = top-point.y; + point.x += cor; + point.y += cor; + } else if ( point.y > bottom) { + int cor = bottom-point.y; + point.x -= cor; + point.y += cor; + } + + + } else if (direction == Direction.BOTTOM) { + int left = bounds.x;//-bounds.height;// left y of the widget + int right = bounds.x + bounds.width;// right y of the widget + if(point.x < left) {//above the widget + int cor = left-point.x; + point.x += cor; + point.y -= cor; + } else if ( point.x > right) { + int cor = point.x- right; + point.x -= cor; + point.y -= cor; + } + + } else if (direction == Direction.TOP) { + int left = bounds.x;//-bounds.height;// left y of the widget + int right = bounds.x + bounds.width;// right y of the widget + if(point.x < left) {//above the widget + int cor = left-point.x; + point.x += cor; + point.y += cor; + } else if ( point.x > right) { + int cor = point.x - right; + point.x -= cor; + point.y += cor; + } + + } + + return new Anchor.Result (point, direction); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 116 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/layout +END +HierarchicalCompoundLayout.java +K 25 +svn:wc:ra_dav:version-url +V 148 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalCompoundLayout.java +END +HierarchicalNodeLayout.java +K 25 +svn:wc:ra_dav:version-url +V 144 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalNodeLayout.java +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,96 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/graph/layout +https://svn.java.net/svn/c1visualizer~svn + + + +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +HierarchicalCompoundLayout.java +file + + + + +2012-01-28T15:08:36.035068Z +baeefee9e71c26c6f461d3f9080da09d +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +4208 + +HierarchicalNodeLayout.java +file + + + + +2012-01-28T15:08:36.037068Z +cd96afa50874e43acc4983a3d4d1ed7e +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +2458 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalCompoundLayout.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalCompoundLayout.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,102 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Point; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.draw2d.geometry.Insets; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.eclipse.draw2d.graph.Subgraph; +import org.netbeans.api.visual.widget.Widget; + +public class HierarchicalCompoundLayout extends GraphLayout { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 20; + private int PADDING = 20; + private static final int INSET = 20; + private CfgScene scene; + + public HierarchicalCompoundLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph ug) { + CompoundDirectedGraph dg = new CompoundDirectedGraph(); + CompoundDirectedGraphLayout layout = new CompoundDirectedGraphLayout(); + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + Map idx2graph = new HashMap(); + Subgraph base = new Subgraph(0); + idx2graph.put(0, base); + base.insets=getInsets(); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = new Subgraph(info.getLoopIndex()); + subg.insets=getInsets(); + idx2graph.put(info.getLoopIndex(), subg); + } + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + node.setPadding(new Insets(PADDING, PADDING, PADDING, PADDING)); + Subgraph subg = idx2graph.get(n.getLoopIndex()); + assert(subg != null); + node.setParent(subg); + subg.addMember(node); + nodeList.add(node); + + } + nodeList.addAll(idx2graph.values()); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = idx2graph.get(info.getLoopIndex()); + if(info.getParent() != null){ + Subgraph parentsubg = idx2graph.get(info.getParent().getLoopIndex()); + Edge edge = new Edge(parentsubg, subg); + parentsubg.addMember(subg); + subg.setParent(parentsubg); + edgeList.add(edge); + } + } + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + if(n.data instanceof CfgNode){ + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER, n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + this.setResolvedNodeLocation(ug, cfgNode, scenepos); + } + } + } + + @Override + protected void performNodesLayout(UniversalGraph ug, Collection collection) { + } + + private Insets getInsets(){ + return new Insets(INSET, INSET, INSET, INSET); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalCompoundLayout.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalCompoundLayout.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,102 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Point; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.draw2d.geometry.Insets; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.eclipse.draw2d.graph.Subgraph; +import org.netbeans.api.visual.widget.Widget; + +public class HierarchicalCompoundLayout extends GraphLayout { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 20; + private int PADDING = 20; + private static final int INSET = 20; + private CfgScene scene; + + public HierarchicalCompoundLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph ug) { + CompoundDirectedGraph dg = new CompoundDirectedGraph(); + CompoundDirectedGraphLayout layout = new CompoundDirectedGraphLayout(); + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + Map idx2graph = new HashMap(); + Subgraph base = new Subgraph(0); + idx2graph.put(0, base); + base.insets=getInsets(); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = new Subgraph(info.getLoopIndex()); + subg.insets=getInsets(); + idx2graph.put(info.getLoopIndex(), subg); + } + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + node.setPadding(new Insets(PADDING, PADDING, PADDING, PADDING)); + Subgraph subg = idx2graph.get(n.getLoopIndex()); + assert(subg != null); + node.setParent(subg); + subg.addMember(node); + nodeList.add(node); + + } + nodeList.addAll(idx2graph.values()); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = idx2graph.get(info.getLoopIndex()); + if(info.getParent() != null){ + Subgraph parentsubg = idx2graph.get(info.getParent().getLoopIndex()); + Edge edge = new Edge(parentsubg, subg); + parentsubg.addMember(subg); + subg.setParent(parentsubg); + edgeList.add(edge); + } + } + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + if(n.data instanceof CfgNode){ + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER, n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + this.setResolvedNodeLocation(ug, cfgNode, scenepos); + } + } + } + + @Override + protected void performNodesLayout(UniversalGraph ug, Collection collection) { + } + + private Insets getInsets(){ + return new Insets(INSET, INSET, INSET, INSET); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalNodeLayout.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalNodeLayout.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,69 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.Point; +import java.util.Collection; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.DirectedGraph; +import org.eclipse.draw2d.graph.DirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.netbeans.api.visual.widget.Widget; + + +public class HierarchicalNodeLayout extends GraphLayout { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 40; + + private CfgScene scene; + + public HierarchicalNodeLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph ug) { + DirectedGraph dg = new DirectedGraph(); + DirectedGraphLayout layout = new DirectedGraphLayout(); + + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + nodeList.add(node); + } + + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), + nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER , n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + setResolvedNodeLocation(ug, cfgNode, scenepos); + } + + } + + @Override + protected void performNodesLayout(UniversalGraph ug, Collection collection) { + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalNodeLayout.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/.svn/text-base/HierarchicalNodeLayout.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,69 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.Point; +import java.util.Collection; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.DirectedGraph; +import org.eclipse.draw2d.graph.DirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.netbeans.api.visual.widget.Widget; + + +public class HierarchicalNodeLayout extends GraphLayout { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 40; + + private CfgScene scene; + + public HierarchicalNodeLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph ug) { + DirectedGraph dg = new DirectedGraph(); + DirectedGraphLayout layout = new DirectedGraphLayout(); + + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + nodeList.add(node); + } + + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), + nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER , n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + setResolvedNodeLocation(ug, cfgNode, scenepos); + } + + } + + @Override + protected void performNodesLayout(UniversalGraph ug, Collection collection) { + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalCompoundLayout.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalCompoundLayout.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,102 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import at.ssw.visualizer.cfg.model.LoopInfo; +import java.awt.Point; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.draw2d.geometry.Insets; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraph; +import org.eclipse.draw2d.graph.CompoundDirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.eclipse.draw2d.graph.Subgraph; +import org.netbeans.api.visual.widget.Widget; + +public class HierarchicalCompoundLayout extends GraphLayout { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 20; + private int PADDING = 20; + private static final int INSET = 20; + private CfgScene scene; + + public HierarchicalCompoundLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph ug) { + CompoundDirectedGraph dg = new CompoundDirectedGraph(); + CompoundDirectedGraphLayout layout = new CompoundDirectedGraphLayout(); + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + Map idx2graph = new HashMap(); + Subgraph base = new Subgraph(0); + idx2graph.put(0, base); + base.insets=getInsets(); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = new Subgraph(info.getLoopIndex()); + subg.insets=getInsets(); + idx2graph.put(info.getLoopIndex(), subg); + } + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + node.setPadding(new Insets(PADDING, PADDING, PADDING, PADDING)); + Subgraph subg = idx2graph.get(n.getLoopIndex()); + assert(subg != null); + node.setParent(subg); + subg.addMember(node); + nodeList.add(node); + + } + nodeList.addAll(idx2graph.values()); + for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ + Subgraph subg = idx2graph.get(info.getLoopIndex()); + if(info.getParent() != null){ + Subgraph parentsubg = idx2graph.get(info.getParent().getLoopIndex()); + Edge edge = new Edge(parentsubg, subg); + parentsubg.addMember(subg); + subg.setParent(parentsubg); + edgeList.add(edge); + } + } + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + if(n.data instanceof CfgNode){ + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER, n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + this.setResolvedNodeLocation(ug, cfgNode, scenepos); + } + } + } + + @Override + protected void performNodesLayout(UniversalGraph ug, Collection collection) { + } + + private Insets getInsets(){ + return new Insets(INSET, INSET, INSET, INSET); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalNodeLayout.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalNodeLayout.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,69 @@ +package at.ssw.visualizer.cfg.graph.layout; + +import at.ssw.visualizer.cfg.graph.CfgScene; +import at.ssw.visualizer.cfg.model.CfgEdge; +import at.ssw.visualizer.cfg.model.CfgNode; +import java.awt.Point; +import java.util.Collection; +import org.netbeans.api.visual.graph.layout.GraphLayout; +import org.netbeans.api.visual.graph.layout.UniversalGraph; +import org.eclipse.draw2d.graph.DirectedGraph; +import org.eclipse.draw2d.graph.DirectedGraphLayout; +import org.eclipse.draw2d.graph.Edge; +import org.eclipse.draw2d.graph.EdgeList; +import org.eclipse.draw2d.graph.Node; +import org.eclipse.draw2d.graph.NodeList; +import org.netbeans.api.visual.widget.Widget; + + +public class HierarchicalNodeLayout extends GraphLayout { + + private static final int TOP_BORDER = 20; + private static final int LEFT_BORDER = 40; + + private CfgScene scene; + + public HierarchicalNodeLayout(CfgScene scene){ + this.scene = scene; + } + + @Override + protected void performGraphLayout(UniversalGraph ug) { + DirectedGraph dg = new DirectedGraph(); + DirectedGraphLayout layout = new DirectedGraphLayout(); + + NodeList nodeList = dg.nodes; + EdgeList edgeList = dg.edges; + + for(CfgNode n : scene.getCfgEnv().getNodes() ) { + Widget nodeWidget = scene.findWidget(n); + Node node = new Node(n); + node.width=nodeWidget.getBounds().width; + node.height = nodeWidget.getBounds().height; + nodeList.add(node); + } + + for(CfgEdge e : scene.getCfgEnv().getEdges() ) { + if(e.isBackEdge()) continue; + Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), + nodeList.getNode(e.getTargetNode().getNodeIndex())); + edgeList.add(edge); + } + + layout.visit(dg); + + for(Object obj : dg.nodes){ + Node n = (Node) obj; + CfgNode cfgNode = (CfgNode) n.data; + Point pos = new Point(n.x + LEFT_BORDER , n.y + TOP_BORDER); + Point scenepos = scene.convertLocalToScene(pos); + setResolvedNodeLocation(ug, cfgNode, scenepos); + } + + } + + @Override + protected void performNodesLayout(UniversalGraph ug, Collection collection) { + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,149 @@ +K 25 +svn:wc:ra_dav:version-url +V 109 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons +END +zoomin.gif +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/zoomin.gif +END +combine.gif +K 25 +svn:wc:ra_dav:version-url +V 119 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/combine.gif +END +manhattanrouter.gif +K 25 +svn:wc:ra_dav:version-url +V 127 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/manhattanrouter.gif +END +zoomout.gif +K 25 +svn:wc:ra_dav:version-url +V 119 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/zoomout.gif +END +color.gif +K 25 +svn:wc:ra_dav:version-url +V 117 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/color.gif +END +showedges_disabled.gif +K 25 +svn:wc:ra_dav:version-url +V 130 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/showedges_disabled.gif +END +hideedges.gif +K 25 +svn:wc:ra_dav:version-url +V 121 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/hideedges.gif +END +cluster.gif +K 25 +svn:wc:ra_dav:version-url +V 121 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/cluster.gif +END +bezierrouter.gif +K 25 +svn:wc:ra_dav:version-url +V 126 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/bezierrouter.gif +END +split_disabled.gif +K 25 +svn:wc:ra_dav:version-url +V 126 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/split_disabled.gif +END +arrangehier.gif +K 25 +svn:wc:ra_dav:version-url +V 123 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/arrangehier.gif +END +Icons.java +K 25 +svn:wc:ra_dav:version-url +V 120 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/Icons.java +END +showedges.gif +K 25 +svn:wc:ra_dav:version-url +V 121 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/showedges.gif +END +disk.gif +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/disk.gif +END +split.gif +K 25 +svn:wc:ra_dav:version-url +V 117 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/split.gif +END +cfg.gif +K 25 +svn:wc:ra_dav:version-url +V 115 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/cfg.gif +END +combine_disabled.gif +K 25 +svn:wc:ra_dav:version-url +V 128 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/combine_disabled.gif +END +autosize.gif +K 25 +svn:wc:ra_dav:version-url +V 122 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/autosize.gif +END +cfg32.gif +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/c1visualizer~svn/!svn/ver/24/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/cfg32.gif +END +fanrouter.gif +K 25 +svn:wc:ra_dav:version-url +V 121 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/fanrouter.gif +END +autosize_selection.gif +K 25 +svn:wc:ra_dav:version-url +V 132 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/autosize_selection.gif +END +hideedges_disabled.gif +K 25 +svn:wc:ra_dav:version-url +V 130 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/hideedges_disabled.gif +END +arrangeloop.gif +K 25 +svn:wc:ra_dav:version-url +V 123 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/arrangeloop.gif +END +arrangebfs.gif +K 25 +svn:wc:ra_dav:version-url +V 122 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons/arrangebfs.gif +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,844 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/icons +https://svn.java.net/svn/c1visualizer~svn + + + +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +zoomin.gif +file + + + + +2012-01-28T15:08:37.070127Z +acca51678195687dd676fd23eddb08b0 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +923 + +combine.gif +file + + + + +2012-01-28T15:08:37.086128Z +ca7d78e384d40e0f3f13c1f89f1f2932 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +200 + +manhattanrouter.gif +file + + + + +2012-01-28T15:08:37.080128Z +bf9efd64e16fc4b57c325c80ab22c4bf +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +214 + +zoomout.gif +file + + + + +2012-01-28T15:08:37.075127Z +a2035b99dde636f259717c0d58ca5a01 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +924 + +color.gif +file + + + + +2012-01-28T15:08:37.092128Z +1818d80c1b2654f102b1fd6bc84766fb +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +959 + +showedges_disabled.gif +file + + + + +2012-01-28T15:08:37.097129Z +21de88513ab89ddbb035879d6b71fe8a +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +153 + +hideedges.gif +file + + + + +2012-01-28T15:08:37.115130Z +a81414bbdf48d73eb6113482ce128b41 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +146 + +cluster.gif +file + + + + +2012-01-28T15:08:37.109129Z +2bde205dbd138beb07208320069969f7 +2009-06-28T16:09:31.412666Z +174 +ChristianW +has-props + + + + + + + + + + + + + + + + + + + + +171 + +bezierrouter.gif +file + + + + +2012-01-28T15:08:37.102129Z +d6483bc426b5e66287d957096cd7cc85 +2009-06-28T16:09:31.412666Z +174 +ChristianW +has-props + + + + + + + + + + + + + + + + + + + + +193 + +split_disabled.gif +file + + + + +2012-01-28T15:08:37.120130Z +36f923e7153211954f705270078c4951 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +136 + +arrangehier.gif +file + + + + +2012-01-28T15:08:37.128130Z +f47b634779a9aef6ae39c14e1122d6cd +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +341 + +Icons.java +file + + + + +2012-01-28T15:08:37.123130Z +09d10c910a6366189dd12feef86413f3 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +470 + +showedges.gif +file + + + + +2012-01-28T15:08:37.133131Z +41f8f5eecd058a5724581b5cf43c615e +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +153 + +disk.gif +file + + + + +2012-01-28T15:08:37.138131Z +795a2c5aab6c5d9eb079ca455265582c +2009-06-28T16:09:31.412666Z +174 +ChristianW +has-props + + + + + + + + + + + + + + + + + + + + +1057 + +split.gif +file + + + + +2012-01-28T15:08:37.143131Z +0b62b3b222878c6e4b782f019065d504 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +204 + +cfg.gif +file + + + + +2012-01-28T15:08:37.149132Z +943fb84a81cab141650bb796ac79fbc1 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +209 + +combine_disabled.gif +file + + + + +2012-01-28T15:08:37.154132Z +cdf59080f8617d98ea947f7f987acebf +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +135 + +autosize.gif +file + + + + +2012-01-28T15:08:37.160132Z +934a8893858aa7d8428e50c2aec4a5c5 +2009-06-28T16:09:31.412666Z +174 +ChristianW +has-props + + + + + + + + + + + + + + + + + + + + +186 + +cfg32.gif +file + + + + +2012-01-28T15:08:37.165133Z +d3f7c06ed4252392e11990109a1e43bd +2007-08-30T17:00:39.754814Z +24 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +577 + +fanrouter.gif +file + + + + +2012-01-28T15:08:37.172133Z +8a6b7ccaa6f72cc99c7f1954a4b25f72 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +224 + +autosize_selection.gif +file + + + + +2012-01-28T15:08:37.178133Z +3c754ad2b69b48b2b89dc087ccba78e9 +2009-06-28T16:09:31.412666Z +174 +ChristianW +has-props + + + + + + + + + + + + + + + + + + + + +194 + +hideedges_disabled.gif +file + + + + +2012-01-28T15:08:37.184134Z +834f68baee8d2025f20b4aa4dc4d3ebb +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +146 + +arrangeloop.gif +file + + + + +2012-01-28T15:08:37.190134Z +79ceb843cf6c93c05f1b0ad6125b51d3 +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +337 + +arrangebfs.gif +file + + + + +2012-01-28T15:08:37.196134Z +f326537bfabcaa7cdb72e4fa7f2f897f +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +338 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/arrangebfs.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/arrangebfs.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/arrangehier.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/arrangehier.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/arrangeloop.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/arrangeloop.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/autosize.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/autosize.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/autosize_selection.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/autosize_selection.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/bezierrouter.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/bezierrouter.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/cfg.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/cfg.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/cfg32.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/cfg32.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/cluster.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/cluster.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/color.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/color.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/combine.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/combine.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/combine_disabled.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/combine_disabled.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/disk.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/disk.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/fanrouter.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/fanrouter.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/hideedges.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/hideedges.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/hideedges_disabled.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/hideedges_disabled.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/manhattanrouter.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/manhattanrouter.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/showedges.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/showedges.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/showedges_disabled.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/showedges_disabled.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/split.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/split.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/split_disabled.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/split_disabled.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/zoomin.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/zoomin.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/zoomout.gif.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/prop-base/zoomout.gif.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/Icons.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/Icons.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,18 @@ +package at.ssw.visualizer.cfg.icons; + +/** + * + * @author Christian Wimmer + */ +public class Icons { + private static final String PATH = "at/ssw/visualizer/cfg/icons/"; + + public static final String CFG = PATH + "cfg.gif"; + + public static final String ICON_ZOOMIN = PATH + "zoomin.gif"; + public static final String ICON_ZOOMOUT = PATH + "zoomout.gif"; + public static final String ICON_DEFAULT = PATH + "arrangebfs.gif"; + + private Icons() { + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/arrangebfs.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/arrangebfs.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/arrangehier.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/arrangehier.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/arrangeloop.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/arrangeloop.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/autosize.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/autosize.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/autosize_selection.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/autosize_selection.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/bezierrouter.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/bezierrouter.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/cfg.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/cfg.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/cfg32.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/cfg32.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/cluster.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/cluster.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/color.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/color.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/combine.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/combine.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/combine_disabled.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/combine_disabled.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/disk.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/disk.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/fanrouter.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/fanrouter.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/hideedges.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/hideedges.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/hideedges_disabled.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/hideedges_disabled.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/manhattanrouter.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/manhattanrouter.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/showedges.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/showedges.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/showedges_disabled.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/showedges_disabled.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/split.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/split.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/split_disabled.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/split_disabled.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/zoomin.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/zoomin.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/zoomout.gif.svn-base Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/.svn/text-base/zoomout.gif.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/Icons.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/Icons.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,18 @@ +package at.ssw.visualizer.cfg.icons; + +/** + * + * @author Christian Wimmer + */ +public class Icons { + private static final String PATH = "at/ssw/visualizer/cfg/icons/"; + + public static final String CFG = PATH + "cfg.gif"; + + public static final String ICON_ZOOMIN = PATH + "zoomin.gif"; + public static final String ICON_ZOOMOUT = PATH + "zoomout.gif"; + public static final String ICON_DEFAULT = PATH + "arrangebfs.gif"; + + private Icons() { + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangebfs.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangebfs.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangehier.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangehier.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangeloop.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangeloop.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize_selection.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize_selection.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/bezierrouter.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/bezierrouter.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg32.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg32.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cluster.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cluster.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/color.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/color.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine_disabled.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine_disabled.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/disk.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/disk.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/fanrouter.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/fanrouter.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges_disabled.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges_disabled.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/manhattanrouter.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/manhattanrouter.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges_disabled.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges_disabled.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split_disabled.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split_disabled.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/zoomin.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/zoomin.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/zoomout.gif Binary file src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/zoomout.gif has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/layer.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/layer.xml Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,41 @@ +K 25 +svn:wc:ra_dav:version-url +V 109 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model +END +CfgEdge.java +K 25 +svn:wc:ra_dav:version-url +V 122 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model/CfgEdge.java +END +CfgNode.java +K 25 +svn:wc:ra_dav:version-url +V 122 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model/CfgNode.java +END +LoopInfo.java +K 25 +svn:wc:ra_dav:version-url +V 123 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model/LoopInfo.java +END +CfgEdgeImpl.java +K 25 +svn:wc:ra_dav:version-url +V 126 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model/CfgEdgeImpl.java +END +CfgNodeImpl.java +K 25 +svn:wc:ra_dav:version-url +V 126 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model/CfgNodeImpl.java +END +CfgEnv.java +K 25 +svn:wc:ra_dav:version-url +V 121 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model/CfgEnv.java +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,232 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/model +https://svn.java.net/svn/c1visualizer~svn + + + +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +CfgEdge.java +file + + + + +2012-01-28T15:08:35.757052Z +d1293dcaf933d2eb8294d51fadf69960 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +273 + +CfgNode.java +file + + + + +2012-01-28T15:08:35.760052Z +5b0da0a0221d22320e6acb1e468e0e1e +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +559 + +LoopInfo.java +file + + + + +2012-01-28T15:08:35.763052Z +62d18c5717e662e9267e8ffafc9fe5bf +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1450 + +CfgEdgeImpl.java +file + + + + +2012-01-28T15:08:35.766052Z +bebb3e91e7cf4c5c8d94f3e725522173 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1236 + +CfgNodeImpl.java +file + + + + +2012-01-28T15:08:35.768053Z +b236f07906a057f6a010abcab3883fc4 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +2995 + +CfgEnv.java +file + + + + +2012-01-28T15:08:35.771053Z +406a5d4af2286ecba6c02ebab0565c9e +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +11002 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdge.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdge.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,10 @@ +package at.ssw.visualizer.cfg.model; + +public interface CfgEdge { + public CfgNode getSourceNode(); + public CfgNode getTargetNode(); + public boolean isXhandler(); + public boolean isBackEdge(); + public boolean isSymmetric(); + public boolean isReflexive(); +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdge.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdge.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,10 @@ +package at.ssw.visualizer.cfg.model; + +public interface CfgEdge { + public CfgNode getSourceNode(); + public CfgNode getTargetNode(); + public boolean isXhandler(); + public boolean isBackEdge(); + public boolean isSymmetric(); + public boolean isReflexive(); +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdgeImpl.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdgeImpl.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,50 @@ +package at.ssw.visualizer.cfg.model; + +public class CfgEdgeImpl implements CfgEdge { + private CfgNodeImpl sourceNode; + private CfgNodeImpl targetNode; + private boolean symmetric; + private boolean backedge; + + public CfgEdgeImpl(CfgNodeImpl sourceNode, CfgNodeImpl targetNode) { + this.sourceNode = sourceNode; + this.targetNode = targetNode; + } + + public void setSymmetric(boolean symmetric){ + this.symmetric = symmetric; + } + + public void setBackEdge(boolean isBackedge){ + this.backedge = isBackedge; + } + + public CfgNode getSourceNode() { + return sourceNode; + } + + public CfgNode getTargetNode() { + return targetNode; + } + + public boolean isBackEdge() { + return this.backedge; + } + + public boolean isSymmetric() { + return symmetric; + } + + public boolean isReflexive() { + return sourceNode==targetNode; + } + + public boolean isXhandler() { + return sourceNode.getBasicBlock().getXhandlers().contains(targetNode.getBasicBlock()); + } + + @Override + public String toString(){ + return this.sourceNode.getBasicBlock().getName() + "->" + targetNode.getBasicBlock().getName(); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdgeImpl.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEdgeImpl.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,50 @@ +package at.ssw.visualizer.cfg.model; + +public class CfgEdgeImpl implements CfgEdge { + private CfgNodeImpl sourceNode; + private CfgNodeImpl targetNode; + private boolean symmetric; + private boolean backedge; + + public CfgEdgeImpl(CfgNodeImpl sourceNode, CfgNodeImpl targetNode) { + this.sourceNode = sourceNode; + this.targetNode = targetNode; + } + + public void setSymmetric(boolean symmetric){ + this.symmetric = symmetric; + } + + public void setBackEdge(boolean isBackedge){ + this.backedge = isBackedge; + } + + public CfgNode getSourceNode() { + return sourceNode; + } + + public CfgNode getTargetNode() { + return targetNode; + } + + public boolean isBackEdge() { + return this.backedge; + } + + public boolean isSymmetric() { + return symmetric; + } + + public boolean isReflexive() { + return sourceNode==targetNode; + } + + public boolean isXhandler() { + return sourceNode.getBasicBlock().getXhandlers().contains(targetNode.getBasicBlock()); + } + + @Override + public String toString(){ + return this.sourceNode.getBasicBlock().getName() + "->" + targetNode.getBasicBlock().getName(); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEnv.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEnv.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,297 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + + +/** + * This is the container class for the data model, + * it prepares creates nodes and edges for the CfgScene + * from a ControlFlowGraph of the Compilation Model + */ +public class CfgEnv { + private ControlFlowGraph cfg; + private Map loopMap;//maps: LoopHeader --> LoopInfo + private CfgNodeImpl[] nodeArr; + private CfgEdgeImpl[] edgeArr; + + public CfgEnv(ControlFlowGraph cfg) { + this.cfg = cfg; + int blockCount = cfg.getBasicBlocks().size(); + CfgNodeImpl[] nodes = new CfgNodeImpl[blockCount]; + Map block2nodeMap = new HashMap(); + Map> inputMap = new HashMap>(); + ArrayList allEdges = new ArrayList(); + List blocks = cfg.getBasicBlocks(); + //create nodes + for(int idx=0 ; idx < blockCount ; idx++) { + BasicBlock b = blocks.get(idx); + + String description = "Name: " + b.getName() + "\n"; + description += "BCI: [" + b.getFromBci() + "," + b.getToBci() + "]\n"; + if (b.getLoopDepth() > 0) { + description += "Loop " + b.getLoopIndex() + " Depth " + b.getLoopDepth() + "\n"; + } + description += "Predecessors: " + getBlockList(b.getPredecessors()) + "\n"; + description += "Successors: " + getBlockList(b.getSuccessors()) + "\n"; + description += "XHandlers: " + getBlockList(b.getXhandlers()); + if (b.getDominator() != null) { + description += "\nDominator: " + b.getDominator().getName(); + } + nodes[idx] = new CfgNodeImpl(b, idx, description); + block2nodeMap.put(b, nodes[idx]); + } + + + //create edges + Set cache = new HashSet();//avoids identical edges with same source and same target + for(int i = 0 ; i < blockCount ; i++) { + BasicBlock b = blocks.get(i); + List outputEdges = new ArrayList(); + + Set successors = new HashSet(); + successors.addAll(b.getSuccessors()); + successors.addAll(b.getXhandlers()); + for(BasicBlock sb : successors) { + CfgNodeImpl succNode = block2nodeMap.get(sb); + CfgEdgeImpl edge = new CfgEdgeImpl(nodes[i], succNode); + if(cache.contains(edge.toString())) + continue; + cache.add(edge.toString()); + //check for symtric edges + if(sb.getXhandlers().contains(b) || sb.getSuccessors().contains(b)) + edge.setSymmetric(true); + outputEdges.add(edge); + } + allEdges.addAll(outputEdges); + nodes[i].setOutputEdges(outputEdges.toArray(new CfgEdgeImpl[outputEdges.size()])); + } + + for(CfgEdgeImpl e: allEdges) { + //CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + CfgNodeImpl tar = (CfgNodeImpl) e.getTargetNode(); + Set set = inputMap.get(tar); + if( set == null) { + set = new HashSet(); + set.add(e); + inputMap.put(tar, set); + } + set.add(e); + } + for(CfgNodeImpl n : nodes){ + Set inputEdges = inputMap.get(n); + if(inputEdges == null) continue; + n.setInputEdges(inputEdges.toArray(new CfgEdgeImpl[inputEdges.size()])); + } + CfgEdgeImpl[] edges = allEdges.toArray(new CfgEdgeImpl[allEdges.size()]); + this.edgeArr=edges; + this.nodeArr=nodes; + CfgNodeImpl rootNode = nodeArr[0]; + setNodeLevels(rootNode); + indexLoops(rootNode); + + } + + + private String getBlockList(List blocks) { + if (blocks.size() == 0) { + return "None"; + } + StringBuilder sb = new StringBuilder(); + String prefix = ""; + for (BasicBlock b : blocks) { + sb.append(prefix).append(b.getName()); + prefix = ", "; + } + return sb.toString(); + } + + + public CfgNode[] getNodes(){ + return this.nodeArr; + } + + public CfgEdge[] getEdges(){ + return this.edgeArr; + } + + public Map getLoopMap() { + return loopMap; + } + + public void setLoopMap(Map loopMap) { + this.loopMap = loopMap; + } + + private void indexLoops(CfgNodeImpl rootNode){ + LoopEnv env = new LoopEnv(Arrays.asList(nodeArr)); + loopDetection(env, rootNode); + calcLoopDepth(env); + + int loopIndex=1; + + for(LoopInfo info : env.loopMap.values()) { + info.setLoopIndex(loopIndex++); + info.setLoopDepth(info.getHeader().getLoopDepth()); + for(CfgNode n : info.getMembers()){ + if(n.getLoopDepth()>info.getLoopDepth()) continue; + CfgNodeImpl ni = (CfgNodeImpl) n; + ni.setLoopDepth(info.getLoopDepth()); + ni.setLoopIndex(info.getLoopIndex()); + } + } + + for(LoopInfo info : env.loopMap.values()) { + HashSet members = new HashSet(info.getMembers()); + members.remove(info.getHeader());//remove own header + for(CfgNode n: members){ + if(n.isLoopHeader()) { + LoopInfo memberInfo = env.loopMap.get(n); + if (info.getLoopDepth() == memberInfo.getLoopDepth()-1) + memberInfo.setParent(info); + } + } + } + this.loopMap = env.loopMap; + } + + + private class LoopEnv { + Set allNodes; + Set activeNodes; + Set visitedNodes; + Map loopMap; + private int loopIndex=0; + + public LoopEnv(Collection nodes){ + allNodes = new HashSet(nodes); + activeNodes = new HashSet(2 * allNodes.size()); + visitedNodes = new HashSet(2 * allNodes.size()); + loopMap = new HashMap(); + } + + public int getLoopIndex(){ + return ++loopIndex; + } + } + + + private void loopDetection(LoopEnv env, CfgNodeImpl root) { + for (CfgNodeImpl n : env.allNodes) { + n.setLoopHeader(false); + for (CfgEdge e : n.getInputEdges()) { + CfgEdgeImpl ei = (CfgEdgeImpl) e; + ei.setBackEdge(false); + } + } + visit(env, root, null); + } + + + + private void visit(LoopEnv env, CfgNodeImpl n, CfgEdgeImpl e) { + if (env.activeNodes.contains(n)) { + // This node is b loop header! + n.setLoopHeader(true); + e.setBackEdge(true); + } else if (!env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + env.activeNodes.add(n); + + for (CfgEdge edge : n.getOutputEdges()) { + if(!edge.getTargetNode().isOSR()) { + CfgEdgeImpl ei = (CfgEdgeImpl) edge; + CfgNodeImpl ni = (CfgNodeImpl) edge.getTargetNode(); + visit(env, ni, ei); + } + } + env.activeNodes.remove(n); + } + } + + + + private void calcLoopDepth(LoopEnv env) { + for (CfgNodeImpl n : env.allNodes) { + env.visitedNodes.clear(); + + if (n.isLoopHeader()) { + LoopInfo loop = new LoopInfo(); + loop.setHeader(n); + n.setLoopIndex(env.getLoopIndex()); + HashSet members = new HashSet(); + loop.setMembers(members); + members.add(n); + env.loopMap.put(loop.getHeader(), loop); + int loopDepth = n.getLoopDepth() + 1; + loop.setLoopDepth(loopDepth); + n.setLoopDepth(loopDepth); + for (CfgEdge e : n.getInputEdges()) { + if (e.isBackEdge() && !e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, n, src, loop); + loop.getBackEdges().add(e); + } + } + } + } + } + + + private void backwardIteration(LoopEnv env, CfgNodeImpl endNode, CfgNodeImpl n, LoopInfo loop) { + if (endNode != n && !env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + + for (CfgEdge e : n.getInputEdges()) { + if (!e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, endNode, src, loop); + } + } + loop.getMembers().add(n); + n.setLoopDepth(n.getLoopDepth() + 1); + } + } + + private void setNodeLevels(CfgNode rootNode){ + Set cache = new HashSet(); + Queue queue = new LinkedList(); + queue.add(rootNode); + cache.add(rootNode); + int level=0; + int[] nodeCount = new int[2]; + nodeCount[0]=1; + while(!queue.isEmpty()){ + CfgNodeImpl curNode = (CfgNodeImpl) queue.poll(); + curNode.setLevel(level); + nodeCount[0]--; + for(CfgEdge outEdge : curNode.getOutputEdges()) { + CfgNode succNode = outEdge.getTargetNode(); + if(cache.contains(succNode)) continue; + cache.add(succNode); + queue.add(succNode); + nodeCount[1]++; + } + if(nodeCount[0]==0){ + nodeCount[0]=nodeCount[1]; + nodeCount[1]=0; + level++; + } + } + } + + public ControlFlowGraph getCfg() { + return cfg; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEnv.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgEnv.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,297 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + + +/** + * This is the container class for the data model, + * it prepares creates nodes and edges for the CfgScene + * from a ControlFlowGraph of the Compilation Model + */ +public class CfgEnv { + private ControlFlowGraph cfg; + private Map loopMap;//maps: LoopHeader --> LoopInfo + private CfgNodeImpl[] nodeArr; + private CfgEdgeImpl[] edgeArr; + + public CfgEnv(ControlFlowGraph cfg) { + this.cfg = cfg; + int blockCount = cfg.getBasicBlocks().size(); + CfgNodeImpl[] nodes = new CfgNodeImpl[blockCount]; + Map block2nodeMap = new HashMap(); + Map> inputMap = new HashMap>(); + ArrayList allEdges = new ArrayList(); + List blocks = cfg.getBasicBlocks(); + //create nodes + for(int idx=0 ; idx < blockCount ; idx++) { + BasicBlock b = blocks.get(idx); + + String description = "Name: " + b.getName() + "\n"; + description += "BCI: [" + b.getFromBci() + "," + b.getToBci() + "]\n"; + if (b.getLoopDepth() > 0) { + description += "Loop " + b.getLoopIndex() + " Depth " + b.getLoopDepth() + "\n"; + } + description += "Predecessors: " + getBlockList(b.getPredecessors()) + "\n"; + description += "Successors: " + getBlockList(b.getSuccessors()) + "\n"; + description += "XHandlers: " + getBlockList(b.getXhandlers()); + if (b.getDominator() != null) { + description += "\nDominator: " + b.getDominator().getName(); + } + nodes[idx] = new CfgNodeImpl(b, idx, description); + block2nodeMap.put(b, nodes[idx]); + } + + + //create edges + Set cache = new HashSet();//avoids identical edges with same source and same target + for(int i = 0 ; i < blockCount ; i++) { + BasicBlock b = blocks.get(i); + List outputEdges = new ArrayList(); + + Set successors = new HashSet(); + successors.addAll(b.getSuccessors()); + successors.addAll(b.getXhandlers()); + for(BasicBlock sb : successors) { + CfgNodeImpl succNode = block2nodeMap.get(sb); + CfgEdgeImpl edge = new CfgEdgeImpl(nodes[i], succNode); + if(cache.contains(edge.toString())) + continue; + cache.add(edge.toString()); + //check for symtric edges + if(sb.getXhandlers().contains(b) || sb.getSuccessors().contains(b)) + edge.setSymmetric(true); + outputEdges.add(edge); + } + allEdges.addAll(outputEdges); + nodes[i].setOutputEdges(outputEdges.toArray(new CfgEdgeImpl[outputEdges.size()])); + } + + for(CfgEdgeImpl e: allEdges) { + //CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + CfgNodeImpl tar = (CfgNodeImpl) e.getTargetNode(); + Set set = inputMap.get(tar); + if( set == null) { + set = new HashSet(); + set.add(e); + inputMap.put(tar, set); + } + set.add(e); + } + for(CfgNodeImpl n : nodes){ + Set inputEdges = inputMap.get(n); + if(inputEdges == null) continue; + n.setInputEdges(inputEdges.toArray(new CfgEdgeImpl[inputEdges.size()])); + } + CfgEdgeImpl[] edges = allEdges.toArray(new CfgEdgeImpl[allEdges.size()]); + this.edgeArr=edges; + this.nodeArr=nodes; + CfgNodeImpl rootNode = nodeArr[0]; + setNodeLevels(rootNode); + indexLoops(rootNode); + + } + + + private String getBlockList(List blocks) { + if (blocks.size() == 0) { + return "None"; + } + StringBuilder sb = new StringBuilder(); + String prefix = ""; + for (BasicBlock b : blocks) { + sb.append(prefix).append(b.getName()); + prefix = ", "; + } + return sb.toString(); + } + + + public CfgNode[] getNodes(){ + return this.nodeArr; + } + + public CfgEdge[] getEdges(){ + return this.edgeArr; + } + + public Map getLoopMap() { + return loopMap; + } + + public void setLoopMap(Map loopMap) { + this.loopMap = loopMap; + } + + private void indexLoops(CfgNodeImpl rootNode){ + LoopEnv env = new LoopEnv(Arrays.asList(nodeArr)); + loopDetection(env, rootNode); + calcLoopDepth(env); + + int loopIndex=1; + + for(LoopInfo info : env.loopMap.values()) { + info.setLoopIndex(loopIndex++); + info.setLoopDepth(info.getHeader().getLoopDepth()); + for(CfgNode n : info.getMembers()){ + if(n.getLoopDepth()>info.getLoopDepth()) continue; + CfgNodeImpl ni = (CfgNodeImpl) n; + ni.setLoopDepth(info.getLoopDepth()); + ni.setLoopIndex(info.getLoopIndex()); + } + } + + for(LoopInfo info : env.loopMap.values()) { + HashSet members = new HashSet(info.getMembers()); + members.remove(info.getHeader());//remove own header + for(CfgNode n: members){ + if(n.isLoopHeader()) { + LoopInfo memberInfo = env.loopMap.get(n); + if (info.getLoopDepth() == memberInfo.getLoopDepth()-1) + memberInfo.setParent(info); + } + } + } + this.loopMap = env.loopMap; + } + + + private class LoopEnv { + Set allNodes; + Set activeNodes; + Set visitedNodes; + Map loopMap; + private int loopIndex=0; + + public LoopEnv(Collection nodes){ + allNodes = new HashSet(nodes); + activeNodes = new HashSet(2 * allNodes.size()); + visitedNodes = new HashSet(2 * allNodes.size()); + loopMap = new HashMap(); + } + + public int getLoopIndex(){ + return ++loopIndex; + } + } + + + private void loopDetection(LoopEnv env, CfgNodeImpl root) { + for (CfgNodeImpl n : env.allNodes) { + n.setLoopHeader(false); + for (CfgEdge e : n.getInputEdges()) { + CfgEdgeImpl ei = (CfgEdgeImpl) e; + ei.setBackEdge(false); + } + } + visit(env, root, null); + } + + + + private void visit(LoopEnv env, CfgNodeImpl n, CfgEdgeImpl e) { + if (env.activeNodes.contains(n)) { + // This node is b loop header! + n.setLoopHeader(true); + e.setBackEdge(true); + } else if (!env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + env.activeNodes.add(n); + + for (CfgEdge edge : n.getOutputEdges()) { + if(!edge.getTargetNode().isOSR()) { + CfgEdgeImpl ei = (CfgEdgeImpl) edge; + CfgNodeImpl ni = (CfgNodeImpl) edge.getTargetNode(); + visit(env, ni, ei); + } + } + env.activeNodes.remove(n); + } + } + + + + private void calcLoopDepth(LoopEnv env) { + for (CfgNodeImpl n : env.allNodes) { + env.visitedNodes.clear(); + + if (n.isLoopHeader()) { + LoopInfo loop = new LoopInfo(); + loop.setHeader(n); + n.setLoopIndex(env.getLoopIndex()); + HashSet members = new HashSet(); + loop.setMembers(members); + members.add(n); + env.loopMap.put(loop.getHeader(), loop); + int loopDepth = n.getLoopDepth() + 1; + loop.setLoopDepth(loopDepth); + n.setLoopDepth(loopDepth); + for (CfgEdge e : n.getInputEdges()) { + if (e.isBackEdge() && !e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, n, src, loop); + loop.getBackEdges().add(e); + } + } + } + } + } + + + private void backwardIteration(LoopEnv env, CfgNodeImpl endNode, CfgNodeImpl n, LoopInfo loop) { + if (endNode != n && !env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + + for (CfgEdge e : n.getInputEdges()) { + if (!e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, endNode, src, loop); + } + } + loop.getMembers().add(n); + n.setLoopDepth(n.getLoopDepth() + 1); + } + } + + private void setNodeLevels(CfgNode rootNode){ + Set cache = new HashSet(); + Queue queue = new LinkedList(); + queue.add(rootNode); + cache.add(rootNode); + int level=0; + int[] nodeCount = new int[2]; + nodeCount[0]=1; + while(!queue.isEmpty()){ + CfgNodeImpl curNode = (CfgNodeImpl) queue.poll(); + curNode.setLevel(level); + nodeCount[0]--; + for(CfgEdge outEdge : curNode.getOutputEdges()) { + CfgNode succNode = outEdge.getTargetNode(); + if(cache.contains(succNode)) continue; + cache.add(succNode); + queue.add(succNode); + nodeCount[1]++; + } + if(nodeCount[0]==0){ + nodeCount[0]=nodeCount[1]; + nodeCount[1]=0; + level++; + } + } + } + + public ControlFlowGraph getCfg() { + return cfg; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgNode.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgNode.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,23 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; + + +public interface CfgNode { + //testers + public boolean isOSR(); + public boolean isRoot(); + public boolean isLoopHeader(); + public boolean isLoopMember(); + + //getters + public int getLevel(); + public int getLoopDepth(); + public int getLoopIndex(); + public int getNodeIndex(); + public CfgEdge[] getInputEdges(); + public CfgEdge[] getOutputEdges(); + public BasicBlock getBasicBlock(); + public String getDescription(); + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgNode.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgNode.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,23 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; + + +public interface CfgNode { + //testers + public boolean isOSR(); + public boolean isRoot(); + public boolean isLoopHeader(); + public boolean isLoopMember(); + + //getters + public int getLevel(); + public int getLoopDepth(); + public int getLoopIndex(); + public int getNodeIndex(); + public CfgEdge[] getInputEdges(); + public CfgEdge[] getOutputEdges(); + public BasicBlock getBasicBlock(); + public String getDescription(); + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgNodeImpl.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/CfgNodeImpl.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,133 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import java.awt.Color; + + + +public class CfgNodeImpl implements CfgNode { + private int nodeIndex; + private BasicBlock basicBlock; + private int level; + private int loopDepth=0; + private int loopIndex=0; + private boolean osr=false; + private CfgNodeImpl dominator=null; + private CfgEdgeImpl[] inputEdges = new CfgEdgeImpl[0]; + private CfgEdgeImpl[] outputEdges = new CfgEdgeImpl[0]; + private String description; + private Color customColor=null; + private boolean loopHeader; + + public CfgNodeImpl(BasicBlock bb, int nodeIndex, String description) { + this.basicBlock = bb; + this.nodeIndex = nodeIndex; + this.description = description; + + if (bb.getPredecessors().size() == 1) { + BasicBlock pred = bb.getPredecessors().get(0); + boolean isStd = pred.getPredecessors().size() == 0; + if (isStd) { + for (String s : bb.getFlags()) { + if (s.equals("osr")) { + osr = true; + break; + } + } + } + } + } + + public int getNodeIndex() { + return nodeIndex; + } + + + public void setDominator(CfgNodeImpl dominator) { + this.dominator = dominator; + } + + public void setLevel(int level) { + this.level = level; + } + + public void setLoopDepth(int loopDepth) { + this.loopDepth = loopDepth; + } + + public void setLoopHeader(boolean loopHeader) { + this.loopHeader = loopHeader; + } + + public void setLoopIndex(int loopIndex) { + this.loopIndex = loopIndex; + } + + public void setNodeIndex(int nodeIndex) { + this.nodeIndex = nodeIndex; + } + + public boolean isRoot() { + return nodeIndex==0; + } + + public boolean isLoopHeader() { + return loopHeader; + } + + public boolean isLoopMember() { + return loopIndex > 0; + } + + public int getLevel() { + return level; + } + + public BasicBlock getBasicBlock() { + return basicBlock; + } + + public int getLoopDepth() { + return loopDepth; + } + + public int getLoopIndex() { + return loopIndex; + } + + public boolean isOSR() { + return osr; + } + + @Override + public String toString(){ + return basicBlock.getName(); + } + + public void setInputEdges(CfgEdgeImpl[] inputEdges){ + this.inputEdges = inputEdges; + } + + + public void setOutputEdges(CfgEdgeImpl[] outputEdges){ + this.outputEdges = outputEdges; + } + + public CfgEdge[] getInputEdges() { + return this.inputEdges; + } + + public CfgEdge[] getOutputEdges() { + return outputEdges; + } + + public String getDescription() { + return description; + } + + public void setColor(Color color) { + this.customColor=color; + } + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/LoopInfo.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/.svn/text-base/LoopInfo.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,67 @@ +package at.ssw.visualizer.cfg.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + + +public class LoopInfo { + private CfgNode header;//the target node of the backedge + private int loopIndex; //index of the min cycleSet + private int loopDepth; //nested depth >=1 + private LoopInfo parent=null; + private Set members; + private List backEdges = new ArrayList();//dfs backEdge + + protected void setLoopDepth(int depth) { + this.loopDepth=depth; + } + + protected void setLoopIndex(int loopIndex) { + this.loopIndex = loopIndex; + } + + public int getLoopDepth() { + return loopDepth; + } + + public Set getMembers() { + return members; + } + + protected void setMembers(Set members) { + this.members = members; + } + + public int getLoopIndex() { + return loopIndex; + } + + protected void setParent(LoopInfo parent) { + this.parent = parent; + } + + public LoopInfo getParent(){ + return parent; + } + + public List getBackEdges() { + return backEdges; + } + + public CfgNode getHeader() { + return header; + } + + protected void setHeader(CfgNode header) { + this.header = header; + } + + @Override + public String toString(){ + return "Loop(" + header.toString()+ ")-->" + members.toString(); + } + + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdge.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdge.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,10 @@ +package at.ssw.visualizer.cfg.model; + +public interface CfgEdge { + public CfgNode getSourceNode(); + public CfgNode getTargetNode(); + public boolean isXhandler(); + public boolean isBackEdge(); + public boolean isSymmetric(); + public boolean isReflexive(); +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdgeImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdgeImpl.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,50 @@ +package at.ssw.visualizer.cfg.model; + +public class CfgEdgeImpl implements CfgEdge { + private CfgNodeImpl sourceNode; + private CfgNodeImpl targetNode; + private boolean symmetric; + private boolean backedge; + + public CfgEdgeImpl(CfgNodeImpl sourceNode, CfgNodeImpl targetNode) { + this.sourceNode = sourceNode; + this.targetNode = targetNode; + } + + public void setSymmetric(boolean symmetric){ + this.symmetric = symmetric; + } + + public void setBackEdge(boolean isBackedge){ + this.backedge = isBackedge; + } + + public CfgNode getSourceNode() { + return sourceNode; + } + + public CfgNode getTargetNode() { + return targetNode; + } + + public boolean isBackEdge() { + return this.backedge; + } + + public boolean isSymmetric() { + return symmetric; + } + + public boolean isReflexive() { + return sourceNode==targetNode; + } + + public boolean isXhandler() { + return sourceNode.getBasicBlock().getXhandlers().contains(targetNode.getBasicBlock()); + } + + @Override + public String toString(){ + return this.sourceNode.getBasicBlock().getName() + "->" + targetNode.getBasicBlock().getName(); + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEnv.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEnv.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,297 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + + +/** + * This is the container class for the data model, + * it prepares creates nodes and edges for the CfgScene + * from a ControlFlowGraph of the Compilation Model + */ +public class CfgEnv { + private ControlFlowGraph cfg; + private Map loopMap;//maps: LoopHeader --> LoopInfo + private CfgNodeImpl[] nodeArr; + private CfgEdgeImpl[] edgeArr; + + public CfgEnv(ControlFlowGraph cfg) { + this.cfg = cfg; + int blockCount = cfg.getBasicBlocks().size(); + CfgNodeImpl[] nodes = new CfgNodeImpl[blockCount]; + Map block2nodeMap = new HashMap(); + Map> inputMap = new HashMap>(); + ArrayList allEdges = new ArrayList(); + List blocks = cfg.getBasicBlocks(); + //create nodes + for(int idx=0 ; idx < blockCount ; idx++) { + BasicBlock b = blocks.get(idx); + + String description = "Name: " + b.getName() + "\n"; + description += "BCI: [" + b.getFromBci() + "," + b.getToBci() + "]\n"; + if (b.getLoopDepth() > 0) { + description += "Loop " + b.getLoopIndex() + " Depth " + b.getLoopDepth() + "\n"; + } + description += "Predecessors: " + getBlockList(b.getPredecessors()) + "\n"; + description += "Successors: " + getBlockList(b.getSuccessors()) + "\n"; + description += "XHandlers: " + getBlockList(b.getXhandlers()); + if (b.getDominator() != null) { + description += "\nDominator: " + b.getDominator().getName(); + } + nodes[idx] = new CfgNodeImpl(b, idx, description); + block2nodeMap.put(b, nodes[idx]); + } + + + //create edges + Set cache = new HashSet();//avoids identical edges with same source and same target + for(int i = 0 ; i < blockCount ; i++) { + BasicBlock b = blocks.get(i); + List outputEdges = new ArrayList(); + + Set successors = new HashSet(); + successors.addAll(b.getSuccessors()); + successors.addAll(b.getXhandlers()); + for(BasicBlock sb : successors) { + CfgNodeImpl succNode = block2nodeMap.get(sb); + CfgEdgeImpl edge = new CfgEdgeImpl(nodes[i], succNode); + if(cache.contains(edge.toString())) + continue; + cache.add(edge.toString()); + //check for symtric edges + if(sb.getXhandlers().contains(b) || sb.getSuccessors().contains(b)) + edge.setSymmetric(true); + outputEdges.add(edge); + } + allEdges.addAll(outputEdges); + nodes[i].setOutputEdges(outputEdges.toArray(new CfgEdgeImpl[outputEdges.size()])); + } + + for(CfgEdgeImpl e: allEdges) { + //CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + CfgNodeImpl tar = (CfgNodeImpl) e.getTargetNode(); + Set set = inputMap.get(tar); + if( set == null) { + set = new HashSet(); + set.add(e); + inputMap.put(tar, set); + } + set.add(e); + } + for(CfgNodeImpl n : nodes){ + Set inputEdges = inputMap.get(n); + if(inputEdges == null) continue; + n.setInputEdges(inputEdges.toArray(new CfgEdgeImpl[inputEdges.size()])); + } + CfgEdgeImpl[] edges = allEdges.toArray(new CfgEdgeImpl[allEdges.size()]); + this.edgeArr=edges; + this.nodeArr=nodes; + CfgNodeImpl rootNode = nodeArr[0]; + setNodeLevels(rootNode); + indexLoops(rootNode); + + } + + + private String getBlockList(List blocks) { + if (blocks.size() == 0) { + return "None"; + } + StringBuilder sb = new StringBuilder(); + String prefix = ""; + for (BasicBlock b : blocks) { + sb.append(prefix).append(b.getName()); + prefix = ", "; + } + return sb.toString(); + } + + + public CfgNode[] getNodes(){ + return this.nodeArr; + } + + public CfgEdge[] getEdges(){ + return this.edgeArr; + } + + public Map getLoopMap() { + return loopMap; + } + + public void setLoopMap(Map loopMap) { + this.loopMap = loopMap; + } + + private void indexLoops(CfgNodeImpl rootNode){ + LoopEnv env = new LoopEnv(Arrays.asList(nodeArr)); + loopDetection(env, rootNode); + calcLoopDepth(env); + + int loopIndex=1; + + for(LoopInfo info : env.loopMap.values()) { + info.setLoopIndex(loopIndex++); + info.setLoopDepth(info.getHeader().getLoopDepth()); + for(CfgNode n : info.getMembers()){ + if(n.getLoopDepth()>info.getLoopDepth()) continue; + CfgNodeImpl ni = (CfgNodeImpl) n; + ni.setLoopDepth(info.getLoopDepth()); + ni.setLoopIndex(info.getLoopIndex()); + } + } + + for(LoopInfo info : env.loopMap.values()) { + HashSet members = new HashSet(info.getMembers()); + members.remove(info.getHeader());//remove own header + for(CfgNode n: members){ + if(n.isLoopHeader()) { + LoopInfo memberInfo = env.loopMap.get(n); + if (info.getLoopDepth() == memberInfo.getLoopDepth()-1) + memberInfo.setParent(info); + } + } + } + this.loopMap = env.loopMap; + } + + + private class LoopEnv { + Set allNodes; + Set activeNodes; + Set visitedNodes; + Map loopMap; + private int loopIndex=0; + + public LoopEnv(Collection nodes){ + allNodes = new HashSet(nodes); + activeNodes = new HashSet(2 * allNodes.size()); + visitedNodes = new HashSet(2 * allNodes.size()); + loopMap = new HashMap(); + } + + public int getLoopIndex(){ + return ++loopIndex; + } + } + + + private void loopDetection(LoopEnv env, CfgNodeImpl root) { + for (CfgNodeImpl n : env.allNodes) { + n.setLoopHeader(false); + for (CfgEdge e : n.getInputEdges()) { + CfgEdgeImpl ei = (CfgEdgeImpl) e; + ei.setBackEdge(false); + } + } + visit(env, root, null); + } + + + + private void visit(LoopEnv env, CfgNodeImpl n, CfgEdgeImpl e) { + if (env.activeNodes.contains(n)) { + // This node is b loop header! + n.setLoopHeader(true); + e.setBackEdge(true); + } else if (!env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + env.activeNodes.add(n); + + for (CfgEdge edge : n.getOutputEdges()) { + if(!edge.getTargetNode().isOSR()) { + CfgEdgeImpl ei = (CfgEdgeImpl) edge; + CfgNodeImpl ni = (CfgNodeImpl) edge.getTargetNode(); + visit(env, ni, ei); + } + } + env.activeNodes.remove(n); + } + } + + + + private void calcLoopDepth(LoopEnv env) { + for (CfgNodeImpl n : env.allNodes) { + env.visitedNodes.clear(); + + if (n.isLoopHeader()) { + LoopInfo loop = new LoopInfo(); + loop.setHeader(n); + n.setLoopIndex(env.getLoopIndex()); + HashSet members = new HashSet(); + loop.setMembers(members); + members.add(n); + env.loopMap.put(loop.getHeader(), loop); + int loopDepth = n.getLoopDepth() + 1; + loop.setLoopDepth(loopDepth); + n.setLoopDepth(loopDepth); + for (CfgEdge e : n.getInputEdges()) { + if (e.isBackEdge() && !e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, n, src, loop); + loop.getBackEdges().add(e); + } + } + } + } + } + + + private void backwardIteration(LoopEnv env, CfgNodeImpl endNode, CfgNodeImpl n, LoopInfo loop) { + if (endNode != n && !env.visitedNodes.contains(n)) { + env.visitedNodes.add(n); + + for (CfgEdge e : n.getInputEdges()) { + if (!e.getSourceNode().isOSR()) { + CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); + backwardIteration(env, endNode, src, loop); + } + } + loop.getMembers().add(n); + n.setLoopDepth(n.getLoopDepth() + 1); + } + } + + private void setNodeLevels(CfgNode rootNode){ + Set cache = new HashSet(); + Queue queue = new LinkedList(); + queue.add(rootNode); + cache.add(rootNode); + int level=0; + int[] nodeCount = new int[2]; + nodeCount[0]=1; + while(!queue.isEmpty()){ + CfgNodeImpl curNode = (CfgNodeImpl) queue.poll(); + curNode.setLevel(level); + nodeCount[0]--; + for(CfgEdge outEdge : curNode.getOutputEdges()) { + CfgNode succNode = outEdge.getTargetNode(); + if(cache.contains(succNode)) continue; + cache.add(succNode); + queue.add(succNode); + nodeCount[1]++; + } + if(nodeCount[0]==0){ + nodeCount[0]=nodeCount[1]; + nodeCount[1]=0; + level++; + } + } + } + + public ControlFlowGraph getCfg() { + return cfg; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNode.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,23 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; + + +public interface CfgNode { + //testers + public boolean isOSR(); + public boolean isRoot(); + public boolean isLoopHeader(); + public boolean isLoopMember(); + + //getters + public int getLevel(); + public int getLoopDepth(); + public int getLoopIndex(); + public int getNodeIndex(); + public CfgEdge[] getInputEdges(); + public CfgEdge[] getOutputEdges(); + public BasicBlock getBasicBlock(); + public String getDescription(); + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNodeImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNodeImpl.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,133 @@ +package at.ssw.visualizer.cfg.model; + +import at.ssw.visualizer.model.cfg.BasicBlock; +import java.awt.Color; + + + +public class CfgNodeImpl implements CfgNode { + private int nodeIndex; + private BasicBlock basicBlock; + private int level; + private int loopDepth=0; + private int loopIndex=0; + private boolean osr=false; + private CfgNodeImpl dominator=null; + private CfgEdgeImpl[] inputEdges = new CfgEdgeImpl[0]; + private CfgEdgeImpl[] outputEdges = new CfgEdgeImpl[0]; + private String description; + private Color customColor=null; + private boolean loopHeader; + + public CfgNodeImpl(BasicBlock bb, int nodeIndex, String description) { + this.basicBlock = bb; + this.nodeIndex = nodeIndex; + this.description = description; + + if (bb.getPredecessors().size() == 1) { + BasicBlock pred = bb.getPredecessors().get(0); + boolean isStd = pred.getPredecessors().size() == 0; + if (isStd) { + for (String s : bb.getFlags()) { + if (s.equals("osr")) { + osr = true; + break; + } + } + } + } + } + + public int getNodeIndex() { + return nodeIndex; + } + + + public void setDominator(CfgNodeImpl dominator) { + this.dominator = dominator; + } + + public void setLevel(int level) { + this.level = level; + } + + public void setLoopDepth(int loopDepth) { + this.loopDepth = loopDepth; + } + + public void setLoopHeader(boolean loopHeader) { + this.loopHeader = loopHeader; + } + + public void setLoopIndex(int loopIndex) { + this.loopIndex = loopIndex; + } + + public void setNodeIndex(int nodeIndex) { + this.nodeIndex = nodeIndex; + } + + public boolean isRoot() { + return nodeIndex==0; + } + + public boolean isLoopHeader() { + return loopHeader; + } + + public boolean isLoopMember() { + return loopIndex > 0; + } + + public int getLevel() { + return level; + } + + public BasicBlock getBasicBlock() { + return basicBlock; + } + + public int getLoopDepth() { + return loopDepth; + } + + public int getLoopIndex() { + return loopIndex; + } + + public boolean isOSR() { + return osr; + } + + @Override + public String toString(){ + return basicBlock.getName(); + } + + public void setInputEdges(CfgEdgeImpl[] inputEdges){ + this.inputEdges = inputEdges; + } + + + public void setOutputEdges(CfgEdgeImpl[] outputEdges){ + this.outputEdges = outputEdges; + } + + public CfgEdge[] getInputEdges() { + return this.inputEdges; + } + + public CfgEdge[] getOutputEdges() { + return outputEdges; + } + + public String getDescription() { + return description; + } + + public void setColor(Color color) { + this.customColor=color; + } + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/LoopInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/LoopInfo.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,67 @@ +package at.ssw.visualizer.cfg.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + + +public class LoopInfo { + private CfgNode header;//the target node of the backedge + private int loopIndex; //index of the min cycleSet + private int loopDepth; //nested depth >=1 + private LoopInfo parent=null; + private Set members; + private List backEdges = new ArrayList();//dfs backEdge + + protected void setLoopDepth(int depth) { + this.loopDepth=depth; + } + + protected void setLoopIndex(int loopIndex) { + this.loopIndex = loopIndex; + } + + public int getLoopDepth() { + return loopDepth; + } + + public Set getMembers() { + return members; + } + + protected void setMembers(Set members) { + this.members = members; + } + + public int getLoopIndex() { + return loopIndex; + } + + protected void setParent(LoopInfo parent) { + this.parent = parent; + } + + public LoopInfo getParent(){ + return parent; + } + + public List getBackEdges() { + return backEdges; + } + + public CfgNode getHeader() { + return header; + } + + protected void setHeader(CfgNode header) { + this.header = header; + } + + @Override + public String toString(){ + return "Loop(" + header.toString()+ ")-->" + members.toString(); + } + + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,59 @@ +K 25 +svn:wc:ra_dav:version-url +V 115 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences +END +CFGOptionsPanelController.java +K 25 +svn:wc:ra_dav:version-url +V 146 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanelController.java +END +CfgPreferences.java +K 25 +svn:wc:ra_dav:version-url +V 135 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/CfgPreferences.java +END +FlagsEditorPanel.java +K 25 +svn:wc:ra_dav:version-url +V 137 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/FlagsEditorPanel.java +END +CFGOptionsCategory.java +K 25 +svn:wc:ra_dav:version-url +V 139 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsCategory.java +END +CfgPreferencesDefaults.java +K 25 +svn:wc:ra_dav:version-url +V 143 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/CfgPreferencesDefaults.java +END +FontChooserDialog.java +K 25 +svn:wc:ra_dav:version-url +V 137 +/svn/c1visualizer~svn/!svn/ver/24/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/FontChooserDialog.java +END +FlagsSetting.java +K 25 +svn:wc:ra_dav:version-url +V 133 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/FlagsSetting.java +END +CFGOptionsPanel.java +K 25 +svn:wc:ra_dav:version-url +V 136 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanel.java +END +ColorChooserButton.java +K 25 +svn:wc:ra_dav:version-url +V 138 +/svn/c1visualizer~svn/!svn/ver/24/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences/ColorChooserButton.java +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,334 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/preferences +https://svn.java.net/svn/c1visualizer~svn + + + +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +CFGOptionsPanelController.java +file + + + + +2012-01-28T15:08:36.290082Z +573461c90737329ba80c1638c43068d7 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1556 + +CfgPreferences.java +file + + + + +2012-01-28T15:08:36.293083Z +720311b2fbbd48a5956268f6114c1145 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +10143 + +FlagsEditorPanel.java +file + + + + +2012-01-28T15:08:36.296083Z +0cd8acb620de0ae1b03022fc8b2cd77a +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +7980 + +CFGOptionsCategory.java +file + + + + +2012-01-28T15:08:36.299083Z +695cc91295d14a26338eb977df606f2a +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +817 + +CfgPreferencesDefaults.java +file + + + + +2012-01-28T15:08:36.301083Z +feaef9d2584b1906ab4a716f48196018 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +1201 + +FontChooserDialog.java +file + + + + +2012-01-28T15:08:36.305083Z +8f9e2683c3230399e4e04d63b2850c7b +2007-08-30T17:00:39.754814Z +24 +christianw + + + + + + + + + + + + + + + + + + + + + +1073 + +FlagsSetting.java +file + + + + +2012-01-28T15:08:36.308083Z +a7d685d555836231fab1ec9f5ebfd73f +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +2328 + +CFGOptionsPanel.java +file + + + + +2012-01-28T15:08:36.310084Z +5531fd12ca7f27f82b0e7097119676ae +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +15478 + +ColorChooserButton.java +file + + + + +2012-01-28T15:08:36.313084Z +17a5d974e436f1e22f3223b51c0be8d6 +2007-08-30T17:00:39.754814Z +24 +christianw + + + + + + + + + + + + + + + + + + + + + +2415 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CFGOptionsCategory.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CFGOptionsCategory.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,32 @@ +package at.ssw.visualizer.cfg.preferences; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import org.netbeans.spi.options.OptionsCategory; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.ImageUtilities; + +/** + * Descriptor for the settings page displayed in the options dialog. + * + * @author Bernhard Stiftner + */ +public class CFGOptionsCategory extends OptionsCategory { + + public OptionsPanelController create() { + return new CFGOptionsPanelController(); + } + + public String getCategoryName() { + return "Control Flow Graph"; + } + + @Override + public Icon getIcon() { + return new ImageIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg32.gif")); + } + + public String getTitle() { + return "CFG Visualizer"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CFGOptionsPanel.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CFGOptionsPanel.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,482 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + +/** + * The actual component for changing the CFG visualizer settings. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class CFGOptionsPanel extends JPanel { + + List elements = new ArrayList(); + + /** Creates a new instance of CFGOptionsPanel */ + public CFGOptionsPanel() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + JPanel cfgPanel = new JPanel(new GridBagLayout()); + + // color/font settings + addColorChooser(cfgPanel, "Background color: ", new ColorChooser(CfgPreferences.PROP_BACKGROUND_COLOR){ + @Override + public void apply() { + CfgPreferences.getInstance().setBackgroundColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBackgroundColor(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); + } + + + + }); + addColorChooser(cfgPanel, "Back edge color: ", new ColorChooser(CfgPreferences.PROP_BACK_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setBackedgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBackedgeColor(); + this.setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); + } + }); + addColorChooser(cfgPanel, "Edge color: ", new ColorChooser(CfgPreferences.PROP_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setEdgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getEdgeColor(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); + } + + }); + addColorChooser(cfgPanel, "Exception edge color: ", new ColorChooser(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setExceptionEdgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getExceptionEdgeColor(); + setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); + } + }); + addColorChooser(cfgPanel, "Node color: ", new ColorChooser(CfgPreferences.PROP_NODE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setNodeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getNodeColor(); + setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAUT_NODE_COLOR); + } + }); + addColorChooser(cfgPanel, "Text color: ", new ColorChooser(CfgPreferences.PROP_TEXT_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setTextColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getTextColor(); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); + } + }); + addColorChooser(cfgPanel, "Border color: ", new ColorChooser(CfgPreferences.PROP_BORDER_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setBorderColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBorderColor(); + setColor(this.originalColor); + + } + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); + } + }); + addColorChooser(cfgPanel, "Selected Nodes color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_FG){ + + @Override + public void apply() { + CfgPreferences.getInstance().setSelectionColorForeground(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getSelectionColorForeground(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + } + }); + addColorChooser(cfgPanel, "Selection Rect color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_BG){ + + @Override + public void apply() { + CfgPreferences.getInstance().setSelectionColorBackground(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getSelectionColorBackground(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); + } + }); + addFontChooser(cfgPanel, "Text font: ", new FontChooser(CfgPreferences.PROP_TEXT_FONT){ + + @Override + public void apply() { + CfgPreferences.getInstance().setTextFont(getSelectedFont()); + } + + @Override + public void update() { + this.originalFont = CfgPreferences.getInstance().getTextFont(); + this.setSelectedFont(originalFont); + + } + + public void reset() { + this.setSelectedFont(CfgPreferencesDefaults.DEFAULT_TEXT_FONT); + } + }); + + // flags editor + addFlagsEditor(cfgPanel, "Flags: "); + add(cfgPanel); + + // add update button + Box hBox = new Box(BoxLayout.X_AXIS); + hBox.add(new JButton(new ResetAction())); + hBox.add(Box.createHorizontalGlue()); + add(hBox); + + add(Box.createVerticalGlue()); + } + + public void update() { + for (ConfigurationElement e : elements) { + e.update(); + } + } + + public void cancel() { + for (ConfigurationElement e : elements) { + e.update(); + } + } + + public void applyChanges() { + for (ConfigurationElement e : elements) { + if(e.isChanged()) + e.apply(); + } + } + + public boolean isDataValid() { + return true; + } + + public boolean isChanged() { + for (ConfigurationElement e : elements) { + if (e.isChanged()) { + return true; + } + } + return false; + } + + public void loadDefault() { + for (ConfigurationElement e : elements) { + e.reset(); + } + } + + private void addColorChooser(JComponent c, String displayName, ColorChooser chooser) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + JLabel label = new JLabel(displayName, JLabel.TRAILING); + layout.setConstraints(label, constraints); + c.add(label); + constraints.anchor = GridBagConstraints.WEST; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(chooser, constraints); + c.add(chooser); + elements.add(chooser); + label.setLabelFor(chooser); + } + + + + private void addFontChooser(JComponent c, String displayName, FontChooser chooser) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + JLabel label = new JLabel(displayName, JLabel.TRAILING); + layout.setConstraints(label, constraints); + c.add(label); + constraints.insets = new Insets(3, 3, 3, 1); + constraints.weightx = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.anchor = GridBagConstraints.CENTER; + layout.setConstraints(chooser.getPreview(), constraints); + c.add(chooser.getPreview()); + constraints.insets = new Insets(3, 1, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(chooser.getButton(), constraints); + c.add(chooser.getButton()); + elements.add(chooser); + label.setLabelFor(chooser.getButton()); + } + + private void addFlagsEditor(JComponent c, String displayName) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.NORTHEAST; + FlagsEditor flagsEditor = new FlagsEditor(); + JLabel flagsLabel = new JLabel(displayName, JLabel.TRAILING); + flagsLabel.setVerticalAlignment(SwingConstants.TOP); + layout.setConstraints(flagsLabel, constraints); + c.add(flagsLabel); + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.BOTH; + constraints.anchor = GridBagConstraints.CENTER; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(flagsEditor, constraints); + c.add(flagsEditor); + elements.add(flagsEditor); + flagsLabel.setLabelFor(flagsEditor); + } + + + + + interface ConfigurationElement { + + public boolean isChanged(); + + //apply changes to preferences + public void apply(); + + //optain current value from preferences + public void update(); + + //reset to default value + public void reset(); + + } + + abstract class ColorChooser extends ColorChooserButton implements ConfigurationElement { + + Color originalColor;//the color before any change + String propertyName; + + public ColorChooser(String propertyName) { + this.propertyName = propertyName; + } + + public boolean isChanged() { + return !originalColor.equals(getColor()); + } + + + public abstract void apply(); + public abstract void update(); + + } + + + abstract class FontChooser implements ConfigurationElement, ActionListener { + + Font originalFont; + Font selectedFont; + String propertyName; + JTextField preview; + JButton button; + + public FontChooser(String propertyName) { + this.propertyName = propertyName; + preview = new JTextField(""); + preview.setEditable(false); + button = new JButton("..."); + button.setMargin(new Insets(0, 0, 0, 0)); + button.addActionListener(this); + } + + public boolean isChanged() { + return !originalFont.equals(selectedFont); + } + + public abstract void apply(); + + public abstract void update(); + + public abstract void reset(); + + public JTextField getPreview() { + return preview; + } + + public JButton getButton() { + return button; + }; + + public Font getSelectedFont() { + return selectedFont; + } + + public void setSelectedFont(Font f) { + selectedFont = f; + preview.setText(fontToString(f)); + preview.revalidate(); + } + + public void actionPerformed(ActionEvent e) { + setSelectedFont(FontChooserDialog.show(selectedFont)); + } + + public String fontToString(Font font) { + StringBuffer sb = new StringBuffer(); + sb.append(font.getName()); + sb.append(" "); + sb.append(font.getSize()); + if (font.isBold()) { + sb.append(" bold"); + } + if (font.isItalic()) { + sb.append(" italic"); + } + return sb.toString(); + } + + } + + class FlagsEditor extends FlagsEditorPanel implements ConfigurationElement { + + FlagsSetting originalFlags; + + public FlagsEditor() { + super(null); + } + + public boolean isChanged() { + return !originalFlags.getFlagString().equals(getFlagString()); + } + + public void apply() { + CfgPreferences.getInstance().setFlagsSetting(new FlagsSetting(getFlagString())); + update(); + } + + public void update() { + originalFlags = CfgPreferences.getInstance().getFlagsSetting(); + setFlagString(originalFlags.getFlagString()); + } + + public void reset() { + FlagsSetting defaultFlags = new FlagsSetting(CfgPreferencesDefaults.DEFAULT_FLAGSTRING); + setFlagString(defaultFlags.getFlagString()); + colorButton.setColor(getParent().getBackground()); + } + + } + + class ResetAction extends AbstractAction { + + public ResetAction() { + super("Reset"); + } + + public void actionPerformed(ActionEvent e) { + CFGOptionsPanel.this.loadDefault(); + } + + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CFGOptionsPanelController.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CFGOptionsPanelController.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,63 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.beans.PropertyChangeListener; +import javax.swing.JComponent; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; + +/** + * Controller for the settings page displayed in the options dialog. + * + * @author Bernhard Stiftner + */ +public class CFGOptionsPanelController extends OptionsPanelController { + + CFGOptionsPanel optionsPanel; + + + public void update() { + getOptionsPanel().update(); + } + + public void applyChanges() { + getOptionsPanel().applyChanges(); + } + + public void cancel() { + getOptionsPanel().cancel(); + } + + public boolean isValid() { + return getOptionsPanel().isDataValid(); + } + + public boolean isChanged() { + return getOptionsPanel().isChanged(); + } + + public JComponent getComponent(Lookup masterLookup) { + return getOptionsPanel(); + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + getOptionsPanel().addPropertyChangeListener(l); + } + + //todo: investigate - who removes the changelistener ? + public void removePropertyChangeListener(PropertyChangeListener l) { + getOptionsPanel().removePropertyChangeListener(l); + } + + private CFGOptionsPanel getOptionsPanel() { + if (optionsPanel == null) { + optionsPanel = new CFGOptionsPanel(); + } + return optionsPanel; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CfgPreferences.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CfgPreferences.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,248 @@ +package at.ssw.visualizer.cfg.preferences; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import java.awt.Color; +import java.awt.Font; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.prefs.Preferences; +import javax.swing.event.EventListenerList; +import org.openide.util.NbPreferences; + +/** + * Replacement for old CFGSettings to remove dependency on deprecated SystemOption package + * + * @author Rumpfhuber Stefan + */ +public class CfgPreferences { + public static final String PROP_FLAGS = "flagsPreference"; + public static final String PROP_TEXT_FONT = "textFontPreference"; + public static final String PROP_TEXT_COLOR = "textColorPreference"; + public static final String PROP_NODE_COLOR = "nodeColorPreference"; + public static final String PROP_EDGE_COLOR = "edgeColorPreference"; + public static final String PROP_BORDER_COLOR = "borderColorPreference"; + public static final String PROP_BACK_EDGE_COLOR = "backEdgeColorPreference"; + public static final String PROP_BACKGROUND_COLOR = "backgroundColorPreference"; + public static final String PROP_SELECTION_COLOR_FG = "selectionColorFgPreference"; + public static final String PROP_SELECTION_COLOR_BG = "selectionColorBgPreference"; + public static final String PROP_EXCEPTION_EDGE_COLOR = "exceptionEdgeColorPreference"; + + private static final String PROP_FONTNAME = "_FontFamily"; + private static final String PROP_FONTSIZE = "_FontSize"; + private static final String PROP_FONTSTYLE = "_FontStyle"; + + protected static final String nodeName = "CfgPreferences"; + + private static CfgPreferences instance = new CfgPreferences(); + private EventListenerList listenerList; + + private FlagsSetting flagsSetting; + private Color node_color; + private Color background_color; + private Color backedge_color; + private Color edge_color; + private Color border_color; + private Color exceptionEdgeColor; + private Color text_color; + private Font text_font; + private Color selection_color_fg; + private Color selection_color_bg; + + + private CfgPreferences(){ + listenerList = new EventListenerList(); + init(); + } + + public static CfgPreferences getInstance(){ + return instance; + } + + public void addPropertyChangeListener(CfgEditorTopComponent listener) { + listenerList.add(PropertyChangeListener.class, listener); + } + + public void removePropertyChangeListener(CfgEditorTopComponent listener) { + listenerList.remove(PropertyChangeListener.class, listener); + } + + protected final Preferences getPreferences() { + return NbPreferences.forModule(this.getClass()).node("options").node(nodeName); + } + + + protected void init(){ + Preferences prefs = this.getPreferences(); + String flagString = prefs.get(PROP_FLAGS, CfgPreferencesDefaults.DEFAULT_FLAGSTRING); + flagsSetting = new FlagsSetting(flagString); + node_color = this.getColorProperty(PROP_NODE_COLOR, CfgPreferencesDefaults.DEFAUT_NODE_COLOR); + background_color = this.getColorProperty(PROP_BACKGROUND_COLOR, CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); + backedge_color = this.getColorProperty(PROP_BACK_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); + edge_color = this.getColorProperty(PROP_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); + selection_color_fg= this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + border_color = this.getColorProperty(PROP_BORDER_COLOR, CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); + exceptionEdgeColor = this.getColorProperty(PROP_EXCEPTION_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); + text_color= this.getColorProperty(PROP_TEXT_COLOR, CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); + selection_color_bg = this.getColorProperty(PROP_SELECTION_COLOR_BG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); + selection_color_fg = this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + text_font = this.getFontProperty(PROP_TEXT_FONT, CfgPreferencesDefaults.DEFAULT_TEXT_FONT); + } + + private void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + Object[] listeners = listenerList.getListenerList(); + + PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == PropertyChangeListener.class) { + ((PropertyChangeListener) listeners[i+1]).propertyChange(event); + } + } + } + + private Font getFontProperty(String propName, Font defaultFont){ + Preferences prefs = this.getPreferences(); + String fontName = prefs.get(propName+PROP_FONTNAME, defaultFont.getFamily()); + int fontSize = prefs.getInt(propName+PROP_FONTSIZE, defaultFont.getSize()); + int fontStyle = prefs.getInt(propName+PROP_FONTSTYLE, defaultFont.getStyle()); + return new Font(fontName, fontStyle, fontSize); + } + + private Color getColorProperty(String propName, Color defaultColor){ + Preferences prefs = this.getPreferences(); + int srgb = prefs.getInt(propName, defaultColor.getRGB()); + if(srgb == defaultColor.getRGB()) + return defaultColor; + return new Color(srgb); + } + + public Color getBackedgeColor() { + return backedge_color; + } + + public Color getBackgroundColor() { + return background_color; + } + + public Color getBorderColor() { + return border_color; + } + + public Color getEdgeColor() { + return edge_color; + } + + public Color getExceptionEdgeColor() { + return exceptionEdgeColor; + } + + public Color getNodeColor() { + return node_color; + } + + public Color getSelectionColorForeground() { + return selection_color_fg; + } + + public Color getSelectionColorBackground() { + return selection_color_bg; + } + + public Color getTextColor() { + return text_color; + } + + public Font getTextFont() { + return text_font; + } + + public FlagsSetting getFlagsSetting() { + return flagsSetting; + } + + + public void setFlagsSetting(FlagsSetting flagsSetting) { + FlagsSetting old = this.getFlagsSetting(); + this.flagsSetting = flagsSetting; + Preferences prefs = getPreferences(); + firePropertyChange(PROP_FLAGS, old, flagsSetting); + prefs.put(PROP_FLAGS, flagsSetting.getFlagString()); + } + + + public void setTextFont(Font text_font) { + Font old = this.getTextFont(); + Preferences prefs = getPreferences(); + this.text_font = text_font; + firePropertyChange(PROP_TEXT_FONT, old, text_font); + prefs.put(PROP_TEXT_FONT + PROP_FONTNAME , text_font.getFamily()); + prefs.putInt(PROP_TEXT_FONT + PROP_FONTSIZE, text_font.getSize()); + prefs.putInt(PROP_TEXT_FONT + PROP_FONTSTYLE, text_font.getStyle()); + } + + public void setBackedgeColor(Color backedge_color) { + Color old = this.getBackedgeColor(); + this.backedge_color = backedge_color; + firePropertyChange(PROP_BACK_EDGE_COLOR, old, backedge_color); + getPreferences().putInt(PROP_BACK_EDGE_COLOR, backedge_color.getRGB()); + } + + public void setBackgroundColor(Color bg_color) { + Color old = this.getBackgroundColor(); + background_color = bg_color; + firePropertyChange(PROP_BACKGROUND_COLOR, old, bg_color ); + getPreferences().putInt(PROP_BACKGROUND_COLOR, bg_color.getRGB()); + } + + public void setBorderColor(Color border_color) { + Color old = getBorderColor(); + this.border_color = border_color; + firePropertyChange(PROP_BORDER_COLOR, old, border_color ); + getPreferences().putInt(PROP_BORDER_COLOR, border_color.getRGB()); + } + + public void setEdgeColor(Color edge_color) { + Color old = getEdgeColor(); + this.edge_color = edge_color; + firePropertyChange(PROP_EDGE_COLOR, old, edge_color); + getPreferences().putInt(PROP_EDGE_COLOR, edge_color.getRGB()); + } + + public void setNodeColor(Color node_color) { + Color old = getNodeColor(); + this.node_color = node_color; + firePropertyChange(PROP_NODE_COLOR, old, node_color); + getPreferences().putInt(PROP_NODE_COLOR, node_color.getRGB()); + + } + + public void setSelectionColorForeground(Color selection_color) { + Color old = this.getSelectionColorForeground(); + this.selection_color_fg = selection_color; + firePropertyChange(PROP_SELECTION_COLOR_FG, old, selection_color); + getPreferences().putInt(PROP_SELECTION_COLOR_FG, selection_color.getRGB()); + } + + public void setSelectionColorBackground(Color selection_color) { + Color old = this.getSelectionColorBackground(); + this.selection_color_bg = selection_color; + firePropertyChange(PROP_SELECTION_COLOR_BG, old, selection_color); + getPreferences().putInt(PROP_SELECTION_COLOR_BG, selection_color.getRGB()); + } + + public void setTextColor(Color text_color) { + Color old = this.getTextColor(); + this.text_color = text_color; + firePropertyChange(PROP_TEXT_COLOR, old, text_color); + getPreferences().putInt(PROP_TEXT_COLOR, text_color.getRGB()); + } + + public void setExceptionEdgeColor(Color exceptionEdgeColor) { + Color old = this.getExceptionEdgeColor(); + this.exceptionEdgeColor = exceptionEdgeColor; + firePropertyChange(PROP_EXCEPTION_EDGE_COLOR, old, exceptionEdgeColor); + getPreferences().putInt(PROP_EXCEPTION_EDGE_COLOR, exceptionEdgeColor.getRGB()); + } + + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CfgPreferencesDefaults.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/CfgPreferencesDefaults.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,23 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Font; + +/** + * Default Configuration for options panel + * + * @author Rumpfhuber Stefan + */ +public final class CfgPreferencesDefaults { + public static final String DEFAULT_FLAGSTRING = "std(224,224,128);osr(224,224,0);ex(128,128,224);sr(128,224,128);llh(224,128,128);lle(224,192,192);plh(128,224,128);bb(160,0,0);ces(192,192,192)"; + public static final Color DEFAUT_NODE_COLOR = new Color(208, 208, 208); + public static final Color DEFAULT_BACKGROUND_COLOR = new Color(255, 255, 255); + public static final Color DEFAULT_BACKEDGE_COLOR = new Color(160, 0, 0); + public static final Color DEFAULT_EDGE_COLOR = new Color(0, 0, 0); + public static final Color DEFAULT_SELECTION_COLOR_FOREGROUND = Color.BLUE; + public static final Color DEFAULT_SELECTION_COLOR_BACKGROUND = Color.BLUE; + public static final Color DEFAULT_BORDER_COLOR = new Color(0, 0, 0); + public static final Color DEFAULT_EXCEPTIONEDGE_COLOR = new Color(0, 0, 160); + public static final Color DEFAULT_TEXT_COLOR = new Color(0, 0, 0); + public static final Font DEFAULT_TEXT_FONT = new Font("Dialog", Font.PLAIN, 18); +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/ColorChooserButton.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/ColorChooserButton.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,94 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JColorChooser; + +/** + * A color selection button. It will preview the currently selected color as + * an icon. Clicking the button will bring up the JColorChooser dialog. + * + * @author Bernhard Stiftner + */ +public class ColorChooserButton extends JButton implements ActionListener { + + public static final Dimension ICON_SIZE = new Dimension(24, 8); + + Color color; + boolean colorChooserEnabled = true; // bring up dialog when clicked? + + + public ColorChooserButton() { + this(Color.black); + } + + public ColorChooserButton(Color defaultColor) { + setIcon(new ColorBoxIcon()); + addActionListener(this); + color = defaultColor; + Dimension size = new Dimension(ICON_SIZE); + size.width += getInsets().left + getInsets().right; + size.height += getInsets().top + getInsets().bottom; + setPreferredSize(size); + } + + public void setColor(Color newColor) { + color = newColor; + repaint(); + } + + public Color getColor() { + return color; + } + + public boolean isColorChooserEnabled() { + return colorChooserEnabled; + } + + public void setColorChooserEnabled(boolean enabled) { + this.colorChooserEnabled = enabled; + } + + public void actionPerformed(ActionEvent e) { + if (!colorChooserEnabled) { + return; + } + + Color c = JColorChooser.showDialog(this, "Choose color", color); + if (c != null) { + setColor(c); + } + } + + class ColorBoxIcon implements Icon { + + public int getIconWidth() { + return ICON_SIZE.width; + } + + public int getIconHeight() { + return ICON_SIZE.height; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Color oldColor = g.getColor(); + g.translate(x, y); + + g.setColor(color); + g.fillRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); + + g.setColor(Color.black); + g.drawRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); + + g.translate(-x, -y); + g.setColor(oldColor); + } + } +} + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/FlagsEditorPanel.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/FlagsEditorPanel.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,247 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Enumeration; +import java.util.StringTokenizer; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +/** + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class FlagsEditorPanel extends JPanel implements ActionListener, + ListSelectionListener { + + FlagListModel listModel; + JList list; + ColorChooserButton colorButton; + JButton newButton; + JButton removeButton; + JButton upButton; + JButton downButton; + + + /** Creates a new instance of FlagsEditorPanel */ + public FlagsEditorPanel(String flagString) { + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + listModel = new FlagListModel(flagString); + list = new JList(listModel); + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.addListSelectionListener(this); + add(new JScrollPane(list)); + + add(Box.createHorizontalStrut(3)); + + Box buttonBox = new Box(BoxLayout.Y_AXIS); + buttonBox.add(colorButton = new ColorChooserButton()); + buttonBox.add(newButton = new JButton("New...")); + buttonBox.add(removeButton = new JButton("Remove")); + buttonBox.add(upButton = new JButton("Up")); + buttonBox.add(downButton = new JButton("Down")); + buttonBox.add(Box.createVerticalGlue()); + add(buttonBox); + layoutButtonContainer(buttonBox); + + colorButton.setColorChooserEnabled(false); + colorButton.addActionListener(this); + newButton.addActionListener(this); + removeButton.addActionListener(this); + upButton.addActionListener(this); + downButton.addActionListener(this); + + selectionChanged(-1); // no selection + } + + /** + * Ugly helper to make a nice layout for vertically aligned buttons. + */ + private static void layoutButtonContainer(JComponent buttonContainer) { + int width = 0; + int height = 0; + + for (int i=0; i= listModel.size()-1) { + return; + } + Object o = listModel.getElementAt(index); + listModel.removeElementAt(index); + listModel.insertElementAt(o, index+1); + } + } + + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) { + return; // another event will be fired soon + } + selectionChanged(list.getSelectedIndex()); + } + + protected void selectionChanged(int index) { //index is -1 if there is no selection + colorButton.setEnabled(index >= 0); + removeButton.setEnabled(index >= 0); + upButton.setEnabled(index > 0); + downButton.setEnabled(index >= 0 && index < listModel.getSize()-1); + + if (index >= 0) { + FlagListItem item = (FlagListItem)listModel.elementAt(index); + colorButton.setColor(item.getColor()); + list.setSelectedIndex(index); + } else { + colorButton.setColor(getBackground()); + } + } + + protected void changeColor() { + int selectedIndex = list.getSelectedIndex(); + FlagListItem item = (FlagListItem)listModel.elementAt(selectedIndex); + Color c = JColorChooser.showDialog(this, "Choose color", item.getColor()); + + if (c != null) { + item.setColor(c); + colorButton.setColor(c); + } + } + + class FlagListModel extends DefaultListModel { + + public FlagListModel(String flagString) { + if (flagString != null) { + setFlagString(flagString); + } + } + + public String getFlagString() { + StringBuffer sb = new StringBuffer(); + Enumeration e = elements(); + while (e.hasMoreElements()) { + FlagListItem item = (FlagListItem)e.nextElement(); + sb.append(item.getFlagString()); + Color c = item.getColor(); + sb.append("(").append(c.getRed()).append(",").append(c.getGreen()).append(",").append(c.getBlue()).append(")"); + if (e.hasMoreElements()) { + sb.append(";"); + } + } + return sb.toString(); + } + + public void setFlagString(String flagString) { + clear(); + StringTokenizer st = new StringTokenizer(flagString, ";"); + while (st.hasMoreTokens()) { + String s = st.nextToken(); + String flag = s.split("\\(")[0]; + Color color = FlagsSetting.toColor(s); + addElement(new FlagListItem(flag, color)); + } + } + + } + + class FlagListItem { + + Color color; + String flagString; + + public FlagListItem(String flagString, Color color) { + this.flagString = flagString; + this.color = color; + } + + public Color getColor() { + return color; + } + + public String getFlagString() { + return flagString; + } + + public void setColor(Color c) { + color = c; + } + + @Override + public String toString() { + return flagString; + } + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/FlagsSetting.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/FlagsSetting.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,85 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.io.Serializable; +import java.util.Hashtable; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class FlagsSetting implements Serializable { + + private Hashtable flag2color; + private Hashtable priority; + private String flagString; + + + public FlagsSetting(String flagString) { + this.flagString = flagString; + flag2color = new Hashtable(); + priority = new Hashtable(); + String[] flags = flagString.split(";"); + + int z = 0; + for(String s : flags) { + String flag = s.split("\\(")[0]; + Color c = toColor(s); + flag2color.put(flag, c); + priority.put(flag, z); + z++; + } + } + + public Color getColor(List strings) { + int minPriority = Integer.MAX_VALUE; + Color result = null; + + for(String s : strings) { + Color curColor = flag2color.get(s); + if(curColor != null) { + int curPriority = priority.get(s); + if(curPriority < minPriority) { + minPriority = curPriority; + result = curColor; + } + } + } + + return result; + } + + public static Color toColor(String s) { + String sArr[] = s.split("\\("); + String Color = sArr[1].substring(0, sArr[1].length() - 1); + String ColorArr[] = Color.split(","); + int r = Integer.parseInt(ColorArr[0]); + int g = Integer.parseInt(ColorArr[1]); + int b = Integer.parseInt(ColorArr[2]); + return new Color(r, g, b); + } + + public String getFlagString() { + return flagString; + } + + @Override + public boolean equals(Object o) { + if(o==null) + return false; + return this.toString().equals(o.toString()); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 19 * hash + (this.flagString != null ? this.flagString.hashCode() : 0); + return hash; + } + + @Override + public String toString(){ + return "FlagSetting[" + flagString + "]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/FontChooserDialog.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/.svn/text-base/FontChooserDialog.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,37 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Font; +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; + +/** + * + * @author Bernhard Stiftner + */ +public class FontChooserDialog { + + /* + * Displays a font selection dialog. + * @return The selected font, or the initial font if the user chose + * to bail out + */ + public static Font show(Font initialFont) { + PropertyEditor pe = PropertyEditorManager.findEditor(Font.class); + if (pe == null) { + throw new RuntimeException("Could not find font editor component."); + } + pe.setValue(initialFont); + DialogDescriptor dd = new DialogDescriptor( + pe.getCustomEditor(), + "Choose Font"); + DialogDisplayer.getDefault().createDialog(dd).setVisible(true); + if (dd.getValue() == DialogDescriptor.OK_OPTION) { + Font f = (Font)pe.getValue(); + return f; + } + return initialFont; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsCategory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsCategory.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,32 @@ +package at.ssw.visualizer.cfg.preferences; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import org.netbeans.spi.options.OptionsCategory; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.ImageUtilities; + +/** + * Descriptor for the settings page displayed in the options dialog. + * + * @author Bernhard Stiftner + */ +public class CFGOptionsCategory extends OptionsCategory { + + public OptionsPanelController create() { + return new CFGOptionsPanelController(); + } + + public String getCategoryName() { + return "Control Flow Graph"; + } + + @Override + public Icon getIcon() { + return new ImageIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg32.gif")); + } + + public String getTitle() { + return "CFG Visualizer"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanel.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,482 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + +/** + * The actual component for changing the CFG visualizer settings. + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class CFGOptionsPanel extends JPanel { + + List elements = new ArrayList(); + + /** Creates a new instance of CFGOptionsPanel */ + public CFGOptionsPanel() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + JPanel cfgPanel = new JPanel(new GridBagLayout()); + + // color/font settings + addColorChooser(cfgPanel, "Background color: ", new ColorChooser(CfgPreferences.PROP_BACKGROUND_COLOR){ + @Override + public void apply() { + CfgPreferences.getInstance().setBackgroundColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBackgroundColor(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); + } + + + + }); + addColorChooser(cfgPanel, "Back edge color: ", new ColorChooser(CfgPreferences.PROP_BACK_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setBackedgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBackedgeColor(); + this.setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); + } + }); + addColorChooser(cfgPanel, "Edge color: ", new ColorChooser(CfgPreferences.PROP_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setEdgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getEdgeColor(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); + } + + }); + addColorChooser(cfgPanel, "Exception edge color: ", new ColorChooser(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setExceptionEdgeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getExceptionEdgeColor(); + setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); + } + }); + addColorChooser(cfgPanel, "Node color: ", new ColorChooser(CfgPreferences.PROP_NODE_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setNodeColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getNodeColor(); + setColor(this.originalColor); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAUT_NODE_COLOR); + } + }); + addColorChooser(cfgPanel, "Text color: ", new ColorChooser(CfgPreferences.PROP_TEXT_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setTextColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getTextColor(); + + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); + } + }); + addColorChooser(cfgPanel, "Border color: ", new ColorChooser(CfgPreferences.PROP_BORDER_COLOR){ + + @Override + public void apply() { + CfgPreferences.getInstance().setBorderColor(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getBorderColor(); + setColor(this.originalColor); + + } + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); + } + }); + addColorChooser(cfgPanel, "Selected Nodes color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_FG){ + + @Override + public void apply() { + CfgPreferences.getInstance().setSelectionColorForeground(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getSelectionColorForeground(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + } + }); + addColorChooser(cfgPanel, "Selection Rect color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_BG){ + + @Override + public void apply() { + CfgPreferences.getInstance().setSelectionColorBackground(getColor()); + } + + @Override + public void update() { + this.originalColor = CfgPreferences.getInstance().getSelectionColorBackground(); + setColor(this.originalColor); + } + + public void reset() { + this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); + } + }); + addFontChooser(cfgPanel, "Text font: ", new FontChooser(CfgPreferences.PROP_TEXT_FONT){ + + @Override + public void apply() { + CfgPreferences.getInstance().setTextFont(getSelectedFont()); + } + + @Override + public void update() { + this.originalFont = CfgPreferences.getInstance().getTextFont(); + this.setSelectedFont(originalFont); + + } + + public void reset() { + this.setSelectedFont(CfgPreferencesDefaults.DEFAULT_TEXT_FONT); + } + }); + + // flags editor + addFlagsEditor(cfgPanel, "Flags: "); + add(cfgPanel); + + // add update button + Box hBox = new Box(BoxLayout.X_AXIS); + hBox.add(new JButton(new ResetAction())); + hBox.add(Box.createHorizontalGlue()); + add(hBox); + + add(Box.createVerticalGlue()); + } + + public void update() { + for (ConfigurationElement e : elements) { + e.update(); + } + } + + public void cancel() { + for (ConfigurationElement e : elements) { + e.update(); + } + } + + public void applyChanges() { + for (ConfigurationElement e : elements) { + if(e.isChanged()) + e.apply(); + } + } + + public boolean isDataValid() { + return true; + } + + public boolean isChanged() { + for (ConfigurationElement e : elements) { + if (e.isChanged()) { + return true; + } + } + return false; + } + + public void loadDefault() { + for (ConfigurationElement e : elements) { + e.reset(); + } + } + + private void addColorChooser(JComponent c, String displayName, ColorChooser chooser) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + JLabel label = new JLabel(displayName, JLabel.TRAILING); + layout.setConstraints(label, constraints); + c.add(label); + constraints.anchor = GridBagConstraints.WEST; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(chooser, constraints); + c.add(chooser); + elements.add(chooser); + label.setLabelFor(chooser); + } + + + + private void addFontChooser(JComponent c, String displayName, FontChooser chooser) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + JLabel label = new JLabel(displayName, JLabel.TRAILING); + layout.setConstraints(label, constraints); + c.add(label); + constraints.insets = new Insets(3, 3, 3, 1); + constraints.weightx = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.anchor = GridBagConstraints.CENTER; + layout.setConstraints(chooser.getPreview(), constraints); + c.add(chooser.getPreview()); + constraints.insets = new Insets(3, 1, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.EAST; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(chooser.getButton(), constraints); + c.add(chooser.getButton()); + elements.add(chooser); + label.setLabelFor(chooser.getButton()); + } + + private void addFlagsEditor(JComponent c, String displayName) { + GridBagLayout layout = (GridBagLayout)c.getLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(3, 3, 3, 3); + constraints.weightx = 0.0; + constraints.fill = GridBagConstraints.NONE; + constraints.anchor = GridBagConstraints.NORTHEAST; + FlagsEditor flagsEditor = new FlagsEditor(); + JLabel flagsLabel = new JLabel(displayName, JLabel.TRAILING); + flagsLabel.setVerticalAlignment(SwingConstants.TOP); + layout.setConstraints(flagsLabel, constraints); + c.add(flagsLabel); + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.BOTH; + constraints.anchor = GridBagConstraints.CENTER; + constraints.gridwidth = GridBagConstraints.REMAINDER; + layout.setConstraints(flagsEditor, constraints); + c.add(flagsEditor); + elements.add(flagsEditor); + flagsLabel.setLabelFor(flagsEditor); + } + + + + + interface ConfigurationElement { + + public boolean isChanged(); + + //apply changes to preferences + public void apply(); + + //optain current value from preferences + public void update(); + + //reset to default value + public void reset(); + + } + + abstract class ColorChooser extends ColorChooserButton implements ConfigurationElement { + + Color originalColor;//the color before any change + String propertyName; + + public ColorChooser(String propertyName) { + this.propertyName = propertyName; + } + + public boolean isChanged() { + return !originalColor.equals(getColor()); + } + + + public abstract void apply(); + public abstract void update(); + + } + + + abstract class FontChooser implements ConfigurationElement, ActionListener { + + Font originalFont; + Font selectedFont; + String propertyName; + JTextField preview; + JButton button; + + public FontChooser(String propertyName) { + this.propertyName = propertyName; + preview = new JTextField(""); + preview.setEditable(false); + button = new JButton("..."); + button.setMargin(new Insets(0, 0, 0, 0)); + button.addActionListener(this); + } + + public boolean isChanged() { + return !originalFont.equals(selectedFont); + } + + public abstract void apply(); + + public abstract void update(); + + public abstract void reset(); + + public JTextField getPreview() { + return preview; + } + + public JButton getButton() { + return button; + }; + + public Font getSelectedFont() { + return selectedFont; + } + + public void setSelectedFont(Font f) { + selectedFont = f; + preview.setText(fontToString(f)); + preview.revalidate(); + } + + public void actionPerformed(ActionEvent e) { + setSelectedFont(FontChooserDialog.show(selectedFont)); + } + + public String fontToString(Font font) { + StringBuffer sb = new StringBuffer(); + sb.append(font.getName()); + sb.append(" "); + sb.append(font.getSize()); + if (font.isBold()) { + sb.append(" bold"); + } + if (font.isItalic()) { + sb.append(" italic"); + } + return sb.toString(); + } + + } + + class FlagsEditor extends FlagsEditorPanel implements ConfigurationElement { + + FlagsSetting originalFlags; + + public FlagsEditor() { + super(null); + } + + public boolean isChanged() { + return !originalFlags.getFlagString().equals(getFlagString()); + } + + public void apply() { + CfgPreferences.getInstance().setFlagsSetting(new FlagsSetting(getFlagString())); + update(); + } + + public void update() { + originalFlags = CfgPreferences.getInstance().getFlagsSetting(); + setFlagString(originalFlags.getFlagString()); + } + + public void reset() { + FlagsSetting defaultFlags = new FlagsSetting(CfgPreferencesDefaults.DEFAULT_FLAGSTRING); + setFlagString(defaultFlags.getFlagString()); + colorButton.setColor(getParent().getBackground()); + } + + } + + class ResetAction extends AbstractAction { + + public ResetAction() { + super("Reset"); + } + + public void actionPerformed(ActionEvent e) { + CFGOptionsPanel.this.loadDefault(); + } + + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanelController.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanelController.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,63 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.beans.PropertyChangeListener; +import javax.swing.JComponent; +import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.HelpCtx; +import org.openide.util.Lookup; + +/** + * Controller for the settings page displayed in the options dialog. + * + * @author Bernhard Stiftner + */ +public class CFGOptionsPanelController extends OptionsPanelController { + + CFGOptionsPanel optionsPanel; + + + public void update() { + getOptionsPanel().update(); + } + + public void applyChanges() { + getOptionsPanel().applyChanges(); + } + + public void cancel() { + getOptionsPanel().cancel(); + } + + public boolean isValid() { + return getOptionsPanel().isDataValid(); + } + + public boolean isChanged() { + return getOptionsPanel().isChanged(); + } + + public JComponent getComponent(Lookup masterLookup) { + return getOptionsPanel(); + } + + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + getOptionsPanel().addPropertyChangeListener(l); + } + + //todo: investigate - who removes the changelistener ? + public void removePropertyChangeListener(PropertyChangeListener l) { + getOptionsPanel().removePropertyChangeListener(l); + } + + private CFGOptionsPanel getOptionsPanel() { + if (optionsPanel == null) { + optionsPanel = new CFGOptionsPanel(); + } + return optionsPanel; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferences.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferences.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,248 @@ +package at.ssw.visualizer.cfg.preferences; + +import at.ssw.visualizer.cfg.editor.CfgEditorTopComponent; +import java.awt.Color; +import java.awt.Font; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.prefs.Preferences; +import javax.swing.event.EventListenerList; +import org.openide.util.NbPreferences; + +/** + * Replacement for old CFGSettings to remove dependency on deprecated SystemOption package + * + * @author Rumpfhuber Stefan + */ +public class CfgPreferences { + public static final String PROP_FLAGS = "flagsPreference"; + public static final String PROP_TEXT_FONT = "textFontPreference"; + public static final String PROP_TEXT_COLOR = "textColorPreference"; + public static final String PROP_NODE_COLOR = "nodeColorPreference"; + public static final String PROP_EDGE_COLOR = "edgeColorPreference"; + public static final String PROP_BORDER_COLOR = "borderColorPreference"; + public static final String PROP_BACK_EDGE_COLOR = "backEdgeColorPreference"; + public static final String PROP_BACKGROUND_COLOR = "backgroundColorPreference"; + public static final String PROP_SELECTION_COLOR_FG = "selectionColorFgPreference"; + public static final String PROP_SELECTION_COLOR_BG = "selectionColorBgPreference"; + public static final String PROP_EXCEPTION_EDGE_COLOR = "exceptionEdgeColorPreference"; + + private static final String PROP_FONTNAME = "_FontFamily"; + private static final String PROP_FONTSIZE = "_FontSize"; + private static final String PROP_FONTSTYLE = "_FontStyle"; + + protected static final String nodeName = "CfgPreferences"; + + private static CfgPreferences instance = new CfgPreferences(); + private EventListenerList listenerList; + + private FlagsSetting flagsSetting; + private Color node_color; + private Color background_color; + private Color backedge_color; + private Color edge_color; + private Color border_color; + private Color exceptionEdgeColor; + private Color text_color; + private Font text_font; + private Color selection_color_fg; + private Color selection_color_bg; + + + private CfgPreferences(){ + listenerList = new EventListenerList(); + init(); + } + + public static CfgPreferences getInstance(){ + return instance; + } + + public void addPropertyChangeListener(CfgEditorTopComponent listener) { + listenerList.add(PropertyChangeListener.class, listener); + } + + public void removePropertyChangeListener(CfgEditorTopComponent listener) { + listenerList.remove(PropertyChangeListener.class, listener); + } + + protected final Preferences getPreferences() { + return NbPreferences.forModule(this.getClass()).node("options").node(nodeName); + } + + + protected void init(){ + Preferences prefs = this.getPreferences(); + String flagString = prefs.get(PROP_FLAGS, CfgPreferencesDefaults.DEFAULT_FLAGSTRING); + flagsSetting = new FlagsSetting(flagString); + node_color = this.getColorProperty(PROP_NODE_COLOR, CfgPreferencesDefaults.DEFAUT_NODE_COLOR); + background_color = this.getColorProperty(PROP_BACKGROUND_COLOR, CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); + backedge_color = this.getColorProperty(PROP_BACK_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); + edge_color = this.getColorProperty(PROP_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); + selection_color_fg= this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + border_color = this.getColorProperty(PROP_BORDER_COLOR, CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); + exceptionEdgeColor = this.getColorProperty(PROP_EXCEPTION_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); + text_color= this.getColorProperty(PROP_TEXT_COLOR, CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); + selection_color_bg = this.getColorProperty(PROP_SELECTION_COLOR_BG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); + selection_color_fg = this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); + text_font = this.getFontProperty(PROP_TEXT_FONT, CfgPreferencesDefaults.DEFAULT_TEXT_FONT); + } + + private void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + Object[] listeners = listenerList.getListenerList(); + + PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == PropertyChangeListener.class) { + ((PropertyChangeListener) listeners[i+1]).propertyChange(event); + } + } + } + + private Font getFontProperty(String propName, Font defaultFont){ + Preferences prefs = this.getPreferences(); + String fontName = prefs.get(propName+PROP_FONTNAME, defaultFont.getFamily()); + int fontSize = prefs.getInt(propName+PROP_FONTSIZE, defaultFont.getSize()); + int fontStyle = prefs.getInt(propName+PROP_FONTSTYLE, defaultFont.getStyle()); + return new Font(fontName, fontStyle, fontSize); + } + + private Color getColorProperty(String propName, Color defaultColor){ + Preferences prefs = this.getPreferences(); + int srgb = prefs.getInt(propName, defaultColor.getRGB()); + if(srgb == defaultColor.getRGB()) + return defaultColor; + return new Color(srgb); + } + + public Color getBackedgeColor() { + return backedge_color; + } + + public Color getBackgroundColor() { + return background_color; + } + + public Color getBorderColor() { + return border_color; + } + + public Color getEdgeColor() { + return edge_color; + } + + public Color getExceptionEdgeColor() { + return exceptionEdgeColor; + } + + public Color getNodeColor() { + return node_color; + } + + public Color getSelectionColorForeground() { + return selection_color_fg; + } + + public Color getSelectionColorBackground() { + return selection_color_bg; + } + + public Color getTextColor() { + return text_color; + } + + public Font getTextFont() { + return text_font; + } + + public FlagsSetting getFlagsSetting() { + return flagsSetting; + } + + + public void setFlagsSetting(FlagsSetting flagsSetting) { + FlagsSetting old = this.getFlagsSetting(); + this.flagsSetting = flagsSetting; + Preferences prefs = getPreferences(); + firePropertyChange(PROP_FLAGS, old, flagsSetting); + prefs.put(PROP_FLAGS, flagsSetting.getFlagString()); + } + + + public void setTextFont(Font text_font) { + Font old = this.getTextFont(); + Preferences prefs = getPreferences(); + this.text_font = text_font; + firePropertyChange(PROP_TEXT_FONT, old, text_font); + prefs.put(PROP_TEXT_FONT + PROP_FONTNAME , text_font.getFamily()); + prefs.putInt(PROP_TEXT_FONT + PROP_FONTSIZE, text_font.getSize()); + prefs.putInt(PROP_TEXT_FONT + PROP_FONTSTYLE, text_font.getStyle()); + } + + public void setBackedgeColor(Color backedge_color) { + Color old = this.getBackedgeColor(); + this.backedge_color = backedge_color; + firePropertyChange(PROP_BACK_EDGE_COLOR, old, backedge_color); + getPreferences().putInt(PROP_BACK_EDGE_COLOR, backedge_color.getRGB()); + } + + public void setBackgroundColor(Color bg_color) { + Color old = this.getBackgroundColor(); + background_color = bg_color; + firePropertyChange(PROP_BACKGROUND_COLOR, old, bg_color ); + getPreferences().putInt(PROP_BACKGROUND_COLOR, bg_color.getRGB()); + } + + public void setBorderColor(Color border_color) { + Color old = getBorderColor(); + this.border_color = border_color; + firePropertyChange(PROP_BORDER_COLOR, old, border_color ); + getPreferences().putInt(PROP_BORDER_COLOR, border_color.getRGB()); + } + + public void setEdgeColor(Color edge_color) { + Color old = getEdgeColor(); + this.edge_color = edge_color; + firePropertyChange(PROP_EDGE_COLOR, old, edge_color); + getPreferences().putInt(PROP_EDGE_COLOR, edge_color.getRGB()); + } + + public void setNodeColor(Color node_color) { + Color old = getNodeColor(); + this.node_color = node_color; + firePropertyChange(PROP_NODE_COLOR, old, node_color); + getPreferences().putInt(PROP_NODE_COLOR, node_color.getRGB()); + + } + + public void setSelectionColorForeground(Color selection_color) { + Color old = this.getSelectionColorForeground(); + this.selection_color_fg = selection_color; + firePropertyChange(PROP_SELECTION_COLOR_FG, old, selection_color); + getPreferences().putInt(PROP_SELECTION_COLOR_FG, selection_color.getRGB()); + } + + public void setSelectionColorBackground(Color selection_color) { + Color old = this.getSelectionColorBackground(); + this.selection_color_bg = selection_color; + firePropertyChange(PROP_SELECTION_COLOR_BG, old, selection_color); + getPreferences().putInt(PROP_SELECTION_COLOR_BG, selection_color.getRGB()); + } + + public void setTextColor(Color text_color) { + Color old = this.getTextColor(); + this.text_color = text_color; + firePropertyChange(PROP_TEXT_COLOR, old, text_color); + getPreferences().putInt(PROP_TEXT_COLOR, text_color.getRGB()); + } + + public void setExceptionEdgeColor(Color exceptionEdgeColor) { + Color old = this.getExceptionEdgeColor(); + this.exceptionEdgeColor = exceptionEdgeColor; + firePropertyChange(PROP_EXCEPTION_EDGE_COLOR, old, exceptionEdgeColor); + getPreferences().putInt(PROP_EXCEPTION_EDGE_COLOR, exceptionEdgeColor.getRGB()); + } + + + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferencesDefaults.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferencesDefaults.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,23 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Font; + +/** + * Default Configuration for options panel + * + * @author Rumpfhuber Stefan + */ +public final class CfgPreferencesDefaults { + public static final String DEFAULT_FLAGSTRING = "std(224,224,128);osr(224,224,0);ex(128,128,224);sr(128,224,128);llh(224,128,128);lle(224,192,192);plh(128,224,128);bb(160,0,0);ces(192,192,192)"; + public static final Color DEFAUT_NODE_COLOR = new Color(208, 208, 208); + public static final Color DEFAULT_BACKGROUND_COLOR = new Color(255, 255, 255); + public static final Color DEFAULT_BACKEDGE_COLOR = new Color(160, 0, 0); + public static final Color DEFAULT_EDGE_COLOR = new Color(0, 0, 0); + public static final Color DEFAULT_SELECTION_COLOR_FOREGROUND = Color.BLUE; + public static final Color DEFAULT_SELECTION_COLOR_BACKGROUND = Color.BLUE; + public static final Color DEFAULT_BORDER_COLOR = new Color(0, 0, 0); + public static final Color DEFAULT_EXCEPTIONEDGE_COLOR = new Color(0, 0, 160); + public static final Color DEFAULT_TEXT_COLOR = new Color(0, 0, 0); + public static final Font DEFAULT_TEXT_FONT = new Font("Dialog", Font.PLAIN, 18); +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/ColorChooserButton.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/ColorChooserButton.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,94 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JColorChooser; + +/** + * A color selection button. It will preview the currently selected color as + * an icon. Clicking the button will bring up the JColorChooser dialog. + * + * @author Bernhard Stiftner + */ +public class ColorChooserButton extends JButton implements ActionListener { + + public static final Dimension ICON_SIZE = new Dimension(24, 8); + + Color color; + boolean colorChooserEnabled = true; // bring up dialog when clicked? + + + public ColorChooserButton() { + this(Color.black); + } + + public ColorChooserButton(Color defaultColor) { + setIcon(new ColorBoxIcon()); + addActionListener(this); + color = defaultColor; + Dimension size = new Dimension(ICON_SIZE); + size.width += getInsets().left + getInsets().right; + size.height += getInsets().top + getInsets().bottom; + setPreferredSize(size); + } + + public void setColor(Color newColor) { + color = newColor; + repaint(); + } + + public Color getColor() { + return color; + } + + public boolean isColorChooserEnabled() { + return colorChooserEnabled; + } + + public void setColorChooserEnabled(boolean enabled) { + this.colorChooserEnabled = enabled; + } + + public void actionPerformed(ActionEvent e) { + if (!colorChooserEnabled) { + return; + } + + Color c = JColorChooser.showDialog(this, "Choose color", color); + if (c != null) { + setColor(c); + } + } + + class ColorBoxIcon implements Icon { + + public int getIconWidth() { + return ICON_SIZE.width; + } + + public int getIconHeight() { + return ICON_SIZE.height; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Color oldColor = g.getColor(); + g.translate(x, y); + + g.setColor(color); + g.fillRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); + + g.setColor(Color.black); + g.drawRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); + + g.translate(-x, -y); + g.setColor(oldColor); + } + } +} + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsEditorPanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsEditorPanel.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,247 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Enumeration; +import java.util.StringTokenizer; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +/** + * + * @author Bernhard Stiftner + * @author Rumpfhuber Stefan + */ +public class FlagsEditorPanel extends JPanel implements ActionListener, + ListSelectionListener { + + FlagListModel listModel; + JList list; + ColorChooserButton colorButton; + JButton newButton; + JButton removeButton; + JButton upButton; + JButton downButton; + + + /** Creates a new instance of FlagsEditorPanel */ + public FlagsEditorPanel(String flagString) { + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + listModel = new FlagListModel(flagString); + list = new JList(listModel); + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.addListSelectionListener(this); + add(new JScrollPane(list)); + + add(Box.createHorizontalStrut(3)); + + Box buttonBox = new Box(BoxLayout.Y_AXIS); + buttonBox.add(colorButton = new ColorChooserButton()); + buttonBox.add(newButton = new JButton("New...")); + buttonBox.add(removeButton = new JButton("Remove")); + buttonBox.add(upButton = new JButton("Up")); + buttonBox.add(downButton = new JButton("Down")); + buttonBox.add(Box.createVerticalGlue()); + add(buttonBox); + layoutButtonContainer(buttonBox); + + colorButton.setColorChooserEnabled(false); + colorButton.addActionListener(this); + newButton.addActionListener(this); + removeButton.addActionListener(this); + upButton.addActionListener(this); + downButton.addActionListener(this); + + selectionChanged(-1); // no selection + } + + /** + * Ugly helper to make a nice layout for vertically aligned buttons. + */ + private static void layoutButtonContainer(JComponent buttonContainer) { + int width = 0; + int height = 0; + + for (int i=0; i= listModel.size()-1) { + return; + } + Object o = listModel.getElementAt(index); + listModel.removeElementAt(index); + listModel.insertElementAt(o, index+1); + } + } + + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) { + return; // another event will be fired soon + } + selectionChanged(list.getSelectedIndex()); + } + + protected void selectionChanged(int index) { //index is -1 if there is no selection + colorButton.setEnabled(index >= 0); + removeButton.setEnabled(index >= 0); + upButton.setEnabled(index > 0); + downButton.setEnabled(index >= 0 && index < listModel.getSize()-1); + + if (index >= 0) { + FlagListItem item = (FlagListItem)listModel.elementAt(index); + colorButton.setColor(item.getColor()); + list.setSelectedIndex(index); + } else { + colorButton.setColor(getBackground()); + } + } + + protected void changeColor() { + int selectedIndex = list.getSelectedIndex(); + FlagListItem item = (FlagListItem)listModel.elementAt(selectedIndex); + Color c = JColorChooser.showDialog(this, "Choose color", item.getColor()); + + if (c != null) { + item.setColor(c); + colorButton.setColor(c); + } + } + + class FlagListModel extends DefaultListModel { + + public FlagListModel(String flagString) { + if (flagString != null) { + setFlagString(flagString); + } + } + + public String getFlagString() { + StringBuffer sb = new StringBuffer(); + Enumeration e = elements(); + while (e.hasMoreElements()) { + FlagListItem item = (FlagListItem)e.nextElement(); + sb.append(item.getFlagString()); + Color c = item.getColor(); + sb.append("(").append(c.getRed()).append(",").append(c.getGreen()).append(",").append(c.getBlue()).append(")"); + if (e.hasMoreElements()) { + sb.append(";"); + } + } + return sb.toString(); + } + + public void setFlagString(String flagString) { + clear(); + StringTokenizer st = new StringTokenizer(flagString, ";"); + while (st.hasMoreTokens()) { + String s = st.nextToken(); + String flag = s.split("\\(")[0]; + Color color = FlagsSetting.toColor(s); + addElement(new FlagListItem(flag, color)); + } + } + + } + + class FlagListItem { + + Color color; + String flagString; + + public FlagListItem(String flagString, Color color) { + this.flagString = flagString; + this.color = color; + } + + public Color getColor() { + return color; + } + + public String getFlagString() { + return flagString; + } + + public void setColor(Color c) { + color = c; + } + + @Override + public String toString() { + return flagString; + } + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsSetting.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsSetting.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,85 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Color; +import java.io.Serializable; +import java.util.Hashtable; +import java.util.List; + +/** + * + * @author Thomas Wuerthinger + */ +public class FlagsSetting implements Serializable { + + private Hashtable flag2color; + private Hashtable priority; + private String flagString; + + + public FlagsSetting(String flagString) { + this.flagString = flagString; + flag2color = new Hashtable(); + priority = new Hashtable(); + String[] flags = flagString.split(";"); + + int z = 0; + for(String s : flags) { + String flag = s.split("\\(")[0]; + Color c = toColor(s); + flag2color.put(flag, c); + priority.put(flag, z); + z++; + } + } + + public Color getColor(List strings) { + int minPriority = Integer.MAX_VALUE; + Color result = null; + + for(String s : strings) { + Color curColor = flag2color.get(s); + if(curColor != null) { + int curPriority = priority.get(s); + if(curPriority < minPriority) { + minPriority = curPriority; + result = curColor; + } + } + } + + return result; + } + + public static Color toColor(String s) { + String sArr[] = s.split("\\("); + String Color = sArr[1].substring(0, sArr[1].length() - 1); + String ColorArr[] = Color.split(","); + int r = Integer.parseInt(ColorArr[0]); + int g = Integer.parseInt(ColorArr[1]); + int b = Integer.parseInt(ColorArr[2]); + return new Color(r, g, b); + } + + public String getFlagString() { + return flagString; + } + + @Override + public boolean equals(Object o) { + if(o==null) + return false; + return this.toString().equals(o.toString()); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 19 * hash + (this.flagString != null ? this.flagString.hashCode() : 0); + return hash; + } + + @Override + public String toString(){ + return "FlagSetting[" + flagString + "]"; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FontChooserDialog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FontChooserDialog.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,37 @@ +package at.ssw.visualizer.cfg.preferences; + +import java.awt.Font; +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; + +/** + * + * @author Bernhard Stiftner + */ +public class FontChooserDialog { + + /* + * Displays a font selection dialog. + * @return The selected font, or the initial font if the user chose + * to bail out + */ + public static Font show(Font initialFont) { + PropertyEditor pe = PropertyEditorManager.findEditor(Font.class); + if (pe == null) { + throw new RuntimeException("Could not find font editor component."); + } + pe.setValue(initialFont); + DialogDescriptor dd = new DialogDescriptor( + pe.getCustomEditor(), + "Choose Font"); + DialogDisplayer.getDefault().createDialog(dd).setVisible(true); + if (dd.getValue() == DialogDescriptor.OK_OPTION) { + Font f = (Font)pe.getValue(); + return f; + } + return initialFont; + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,35 @@ +K 25 +svn:wc:ra_dav:version-url +V 110 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/visual +END +BezierWidget.java +K 25 +svn:wc:ra_dav:version-url +V 128 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/visual/BezierWidget.java +END +PolylineRouterV2.java +K 25 +svn:wc:ra_dav:version-url +V 132 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/visual/PolylineRouterV2.java +END +WidgetCollisionCollector.java +K 25 +svn:wc:ra_dav:version-url +V 140 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/visual/WidgetCollisionCollector.java +END +PolylineRouter.java +K 25 +svn:wc:ra_dav:version-url +V 130 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/visual/PolylineRouter.java +END +SplineConnectionWidget.java +K 25 +svn:wc:ra_dav:version-url +V 138 +/svn/c1visualizer~svn/!svn/ver/174/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/visual/SplineConnectionWidget.java +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,198 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/src/at/ssw/visualizer/cfg/visual +https://svn.java.net/svn/c1visualizer~svn + + + +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +BezierWidget.java +file + + + + +2012-01-28T15:08:36.450092Z +6f4652eeba91c275099c2e8ffa7dd075 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +13439 + +PolylineRouterV2.java +file + + + + +2012-01-28T15:08:36.452092Z +e558232ab712df2c002920ffa61165f7 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +16224 + +WidgetCollisionCollector.java +file + + + + +2012-01-28T15:08:36.455092Z +40ea70a042ab2829a7331c3ae8fc9091 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +290 + +PolylineRouter.java +file + + + + +2012-01-28T15:08:36.458092Z +48f40e451e5b3fc3cd68b971e21e5b1e +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +15327 + +SplineConnectionWidget.java +file + + + + +2012-01-28T15:08:36.460092Z +49fa56fda21e99b885de666fd724cc68 +2009-06-28T16:09:31.412666Z +174 +ChristianW + + + + + + + + + + + + + + + + + + + + + +21310 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/BezierWidget.java.netbeans-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/BezierWidget.java.netbeans-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,345 @@ +package at.ssw.visualizer.cfg.visual; + +import org.netbeans.api.visual.widget.ConnectionWidget; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.util.List; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +/** + * In comparison to the default ConnectionWidget this class is able to connect + * Widgets with a curve instead of a straight line sequence. Between two control + * points a curve is painted as cubic bezier curve the control points are + * calculated automaticaly they depend on the position of the prior- and the + * following control points. + * In conjunction with a suitable router the connection will be a straight line + * or a curve depending on the amount and the position of the controlpoints. + * Controlpoints supplied by the router, are treated as curve intersection points. + * For Reflexive edges the router doesn`t need to supply controlpoints, they + * get painted by this class automatically. If the router supplys more as 2 + * control points for a recursive edge the edge gets painted with the default + * curve approximation algorithm. + */ +public class BezierWidget extends ConnectionWidget { + private static final double BEZIER_SCALE = 0.3; + private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy + + private GraphScene scene=null; + + public BezierWidget(Scene scene) { + super(scene); + } + + public BezierWidget(GraphScene scene) { + super(scene); + this.scene=scene; + } + + + private boolean isReflexive(){ + return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); + } + + + @Override + protected Rectangle calculateClientArea() { + Rectangle bounds = null; + if(this.getControlPoints().size()>0){ + for(Point p : this.getControlPoints()){ + if(bounds==null) + bounds = new Rectangle(p); + else + bounds.add(p); + } + bounds.grow(5,5); + } + if(isReflexive()){ + Widget related = this.getTargetAnchor().getRelatedWidget(); + bounds = related.convertLocalToScene(related.getBounds()); + bounds.grow(10, 10); + } + if(bounds==null) + bounds = super.calculateClientArea(); + + return bounds; + } + + + + //returns prefered location for an edge -1 for left and 1 for right + private int edgeBalance(Widget nodeWidget) { + if(scene == null) + return 1; + + Point nodeLocation = nodeWidget.getLocation(); + int left = 0, right = 0; + + Object node = scene.findObject(nodeWidget); + + for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges + ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); + + if(cw != this) { + Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); + + Point location; + if(targetNodeWidget == nodeWidget) { + Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); + location = sourceNodeWidget.getLocation(); + } else { + location = targetNodeWidget.getLocation(); + } + + if(location.x < nodeLocation.x) + left++; + else + right++; + } + } + if(left < right) + return -1; + else + return 1; + } + + + + + /** + * if the edge is reflexive its painted as a cyclic edge + * if there are 2 controlpoints the connection is painted as a straight line from the source to the targetanchor + * if there are more as 2 controlpoints the connection path between 2 control points is painted as bezier curve + */ + + @Override + protected void paintWidget () { + + List contrPoints = this.getControlPoints(); + int listSize = contrPoints.size(); + + Graphics2D gr = getGraphics (); + + if (listSize <= 2) { + if(isReflexive()) { //special case for reflexive connection widgets + Widget related = this.getTargetAnchor().getRelatedWidget(); + int position = this.edgeBalance(related); + Rectangle bounds = related.convertLocalToScene(related.getBounds()); + gr.setColor (getLineColor()); + Point first = new Point(); + Point last = new Point(); + double centerX = bounds.getCenterX(); + first.x = (int) (centerX + bounds.width / 4); + first.y = bounds.y + bounds.height; + last.x = first.x; + last.y = bounds.y; + + gr.setStroke(this.getStroke()); + + double cutDistance = this.getTargetAnchorShape().getCutDistance(); + double anchorAngle = Math.PI/-3.0; + double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); + double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); + int ydiff=first.y-last.y; + int endy = -ydiff; + double height=bounds.getHeight(); + double cy = height/4.0; + double cx=bounds.getWidth()/5.0; + double dcx = cx*2; + GeneralPath gp = new GeneralPath(); + gp.moveTo(0, 0); + gp.quadTo(0, cy, cx, cy); + gp.quadTo(dcx, cy, dcx, -height/2.0); + gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); + gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); + + AffineTransform af = new AffineTransform(); + AnchorShape anchorShape = this.getTargetAnchorShape(); + + if(position < 0) { + first.x = (int) (centerX - bounds.width / 4); + af.translate(first.x, first.y); + af.scale(-1.0, 1.0); + last.x = first.x; + } else { + af.translate(first.x, first.y); + } + Shape s = gp.createTransformedShape(af); + gr.draw(s); + + if (last != null) { + AffineTransform previousTransform = gr.getTransform (); + gr.translate (last.x, last.y); + + if(position < 0) + gr.rotate(Math.PI - anchorAngle); + else + gr.rotate (anchorAngle); + + anchorShape.paint (gr, false); + gr.setTransform (previousTransform); + } + + } else { + super.paintWidget(); + } + return; + } + + //bezier curve... + GeneralPath curvePath = new GeneralPath(); + Point lastControlPoint = null; + double lastControlPointRotation = 0.0; + + Point prev = null; + for (int i = 0; i < listSize - 1; i++) { + Point cur = contrPoints.get(i); + Point next = contrPoints.get(i + 1); + Point nextnext = null; + if (i < listSize - 2) { + nextnext = contrPoints.get(i + 2); + } + + double len = cur.distance(next); + double scale = len * BEZIER_SCALE; + Point bezierFrom = null;//first ControlPoint + Point bezierTo = null;//second ControlPoint + + if (prev == null) { + //first point + curvePath.moveTo(cur.x, cur.y);//startpoint + bezierFrom = cur; + } else { + bezierFrom = new Point(next.x - prev.x, next.y - prev.y); + bezierFrom = scaleVector(bezierFrom, scale); + bezierFrom.translate(cur.x, cur.y); + } + + if (nextnext == null) {//next== last point (curve to) + lastControlPoint=next; + bezierTo = next;//set 2nd intermediate point to endpoint + GeneralPath lastseg = this.subdivide(cur, bezierFrom, bezierTo, next); + if(lastseg != null) + curvePath.append(lastseg, true); + break; + } else { + bezierTo = new Point(cur.x - nextnext.x, cur.y - nextnext.y); + bezierTo = scaleVector(bezierTo, scale); + bezierTo.translate(next.x, next.y); + } + + curvePath.curveTo( + bezierFrom.x, bezierFrom.y,//controlPoint1 + bezierTo.x, bezierTo.y,//controlPoint2 + next.x,next.y + ); + prev = cur; + } + Point2D cur = curvePath.getCurrentPoint(); + Point next = lastControlPoint; + + lastControlPointRotation = //anchor anchorAngle + Math.atan2 (cur.getY() - next.y, cur.getX() - next.x); + + Color previousColor = gr.getColor(); + gr.setColor (getLineColor()); + Stroke s = this.getStroke(); + gr.setStroke(s); + gr.setColor(this.getLineColor()); + gr.draw(curvePath); + + AffineTransform previousTransform = gr.getTransform (); + gr.translate (lastControlPoint.x, lastControlPoint.y); + gr.rotate (lastControlPointRotation); + AnchorShape targetAnchorShape = this.getTargetAnchorShape(); + targetAnchorShape.paint (gr, false); + gr.setTransform (previousTransform); + + //paint ControlPoints if enabled + if (isPaintControlPoints()) { + int last = listSize - 1; + for (int index = 0; index <= last; index ++) { + Point point = contrPoints.get (index); + previousTransform = gr.getTransform (); + gr.translate (point.x, point.y); + if (index == 0 || index == last) + getEndPointShape().paint (gr); + else + getControlPointShape().paint (gr); + gr.setTransform (previousTransform); + } + + } + gr.setColor(previousColor); + } + + + + private GeneralPath subdivide (Point b0, Point b1, Point b2, Point b3) { + double cutDistance = getTargetAnchorShape().getCutDistance(); + double minDistance = cutDistance - ENDPOINT_DEVIATION; + /** + * if the cutDistance is valid the last segment of the curve + * gets reduced by subdivision until the distance of the endpoint(epDistance) + * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) + */ + if(cutDistance > minDistance && minDistance > 0 ) { + GeneralPath path = new GeneralPath(); + + path.moveTo(b0.x, b0.y); + + CubicCurve2D.Double left = new CubicCurve2D.Double( + b0.x, b0.y, + b1.x, b1.y, + b2.x, b2.y, + b3.x, b3.y); + + CubicCurve2D right=new CubicCurve2D.Double(); + left.subdivide(left, right); + double distance = b3.distance(left.getP2()); + //if the distance is bigger as the cutDistance the left segment is added + //and the right segment is divided again + while(distance>cutDistance){ + path.append(left, true); + right.subdivide(left, right); + distance = b3.distance(left.getP2()); + //if the devision removed to much the left segment is divided + while(distance < minDistance) { + //changes the distance to ~ (distance+distance/2) + left.subdivide(left, right); + distance = b3.distance(left.getP2()); + } + } + //append the last segment with (minDistance < distance < cutDistance) + //actually we should check if the a division happend, but this is very unlikly + path.append(left, true); + return path; + } + return null; + } + + + + + + private static Point scaleVector(Point vector, double len) { + double scale = Math.sqrt(vector.x * vector.x + vector.y * vector.y); + if(scale==0.0) return vector; + scale = len / scale; + return new Point( + Math.round(vector.x * (float)scale), + Math.round(vector.y * (float)scale)); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/BezierWidget.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/BezierWidget.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,345 @@ +package at.ssw.visualizer.cfg.visual; + +import org.netbeans.api.visual.widget.ConnectionWidget; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.util.List; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +/** + * In comparison to the default ConnectionWidget this class is able to connect + * Widgets with a curve instead of a straight line sequence. Between two control + * points a curve is painted as cubic bezier curve the control points are + * calculated automaticaly they depend on the position of the prior- and the + * following control points. + * In conjunction with a suitable router the connection will be a straight line + * or a curve depending on the amount and the position of the controlpoints. + * Controlpoints supplied by the router, are treated as curve intersection points. + * For Reflexive edges the router doesn`t need to supply controlpoints, they + * get painted by this class automatically. If the router supplys more as 2 + * control points for a recursive edge the edge gets painted with the default + * curve approximation algorithm. + */ +public class BezierWidget extends ConnectionWidget { + private static final double BEZIER_SCALE = 0.3; + private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy + + private GraphScene scene=null; + + public BezierWidget(Scene scene) { + super(scene); + } + + public BezierWidget(GraphScene scene) { + super(scene); + this.scene=scene; + } + + + private boolean isReflexive(){ + return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); + } + + + @Override + protected Rectangle calculateClientArea() { + Rectangle bounds = null; + if(this.getControlPoints().size()>0){ + for(Point p : this.getControlPoints()){ + if(bounds==null) + bounds = new Rectangle(p); + else + bounds.add(p); + } + bounds.grow(5,5); + } + if(isReflexive()){ + Widget related = this.getTargetAnchor().getRelatedWidget(); + bounds = related.convertLocalToScene(related.getBounds()); + bounds.grow(10, 10); + } + if(bounds==null) + bounds = super.calculateClientArea(); + + return bounds; + } + + + + //returns prefered location for an edge -1 for left and 1 for right + private int edgeBalance(Widget nodeWidget) { + if(scene == null) + return 1; + + Point nodeLocation = nodeWidget.getLocation(); + int left = 0, right = 0; + + Object node = scene.findObject(nodeWidget); + + for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges + ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); + + if(cw != this) { + Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); + + Point location; + if(targetNodeWidget == nodeWidget) { + Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); + location = sourceNodeWidget.getLocation(); + } else { + location = targetNodeWidget.getLocation(); + } + + if(location.x < nodeLocation.x) + left++; + else + right++; + } + } + if(left < right) + return -1; + else + return 1; + } + + + + + /** + * if the edge is reflexive its painted as a cyclic edge + * if there are 2 controlpoints the connection is painted as a straight line from the source to the targetanchor + * if there are more as 2 controlpoints the connection path between 2 control points is painted as bezier curve + */ + + @Override + protected void paintWidget () { + + List contrPoints = this.getControlPoints(); + int listSize = contrPoints.size(); + + Graphics2D gr = getGraphics (); + + if (listSize <= 2) { + if(isReflexive()) { //special case for reflexive connection widgets + Widget related = this.getTargetAnchor().getRelatedWidget(); + int position = this.edgeBalance(related); + Rectangle bounds = related.convertLocalToScene(related.getBounds()); + gr.setColor (getLineColor()); + Point first = new Point(); + Point last = new Point(); + double centerX = bounds.getCenterX(); + first.x = (int) (centerX + bounds.width / 4); + first.y = bounds.y + bounds.height; + last.x = first.x; + last.y = bounds.y; + + gr.setStroke(this.getStroke()); + + double cutDistance = this.getTargetAnchorShape().getCutDistance(); + double anchorAngle = Math.PI/-3.0; + double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); + double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); + int ydiff=first.y-last.y; + int endy = -ydiff; + double height=bounds.getHeight(); + double cy = height/4.0; + double cx=bounds.getWidth()/5.0; + double dcx = cx*2; + GeneralPath gp = new GeneralPath(); + gp.moveTo(0, 0); + gp.quadTo(0, cy, cx, cy); + gp.quadTo(dcx, cy, dcx, -height/2.0); + gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); + gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); + + AffineTransform af = new AffineTransform(); + AnchorShape anchorShape = this.getTargetAnchorShape(); + + if(position < 0) { + first.x = (int) (centerX - bounds.width / 4); + af.translate(first.x, first.y); + af.scale(-1.0, 1.0); + last.x = first.x; + } else { + af.translate(first.x, first.y); + } + Shape s = gp.createTransformedShape(af); + gr.draw(s); + + if (last != null) { + AffineTransform previousTransform = gr.getTransform (); + gr.translate (last.x, last.y); + + if(position < 0) + gr.rotate(Math.PI - anchorAngle); + else + gr.rotate (anchorAngle); + + anchorShape.paint (gr, false); + gr.setTransform (previousTransform); + } + + } else { + super.paintWidget(); + } + return; + } + + //bezier curve... + GeneralPath curvePath = new GeneralPath(); + Point lastControlPoint = null; + double lastControlPointRotation = 0.0; + + Point prev = null; + for (int i = 0; i < listSize - 1; i++) { + Point cur = contrPoints.get(i); + Point next = contrPoints.get(i + 1); + Point nextnext = null; + if (i < listSize - 2) { + nextnext = contrPoints.get(i + 2); + } + + double len = cur.distance(next); + double scale = len * BEZIER_SCALE; + Point bezierFrom = null;//first ControlPoint + Point bezierTo = null;//second ControlPoint + + if (prev == null) { + //first point + curvePath.moveTo(cur.x, cur.y);//startpoint + bezierFrom = cur; + } else { + bezierFrom = new Point(next.x - prev.x, next.y - prev.y); + bezierFrom = scaleVector(bezierFrom, scale); + bezierFrom.translate(cur.x, cur.y); + } + + if (nextnext == null) {//next== last point (curve to) + lastControlPoint=next; + bezierTo = next;//set 2nd intermediate point to endpoint + GeneralPath lastseg = this.subdivide(cur, bezierFrom, bezierTo, next); + if(lastseg != null) + curvePath.append(lastseg, true); + break; + } else { + bezierTo = new Point(cur.x - nextnext.x, cur.y - nextnext.y); + bezierTo = scaleVector(bezierTo, scale); + bezierTo.translate(next.x, next.y); + } + + curvePath.curveTo( + bezierFrom.x, bezierFrom.y,//controlPoint1 + bezierTo.x, bezierTo.y,//controlPoint2 + next.x,next.y + ); + prev = cur; + } + Point2D cur = curvePath.getCurrentPoint(); + Point next = lastControlPoint; + + lastControlPointRotation = //anchor anchorAngle + Math.atan2 (cur.getY() - next.y, cur.getX() - next.x); + + Color previousColor = gr.getColor(); + gr.setColor (getLineColor()); + Stroke s = this.getStroke(); + gr.setStroke(s); + gr.setColor(this.getLineColor()); + gr.draw(curvePath); + + AffineTransform previousTransform = gr.getTransform (); + gr.translate (lastControlPoint.x, lastControlPoint.y); + gr.rotate (lastControlPointRotation); + AnchorShape targetAnchorShape = this.getTargetAnchorShape(); + targetAnchorShape.paint (gr, false); + gr.setTransform (previousTransform); + + //paint ControlPoints if enabled + if (isPaintControlPoints()) { + int last = listSize - 1; + for (int index = 0; index <= last; index ++) { + Point point = contrPoints.get (index); + previousTransform = gr.getTransform (); + gr.translate (point.x, point.y); + if (index == 0 || index == last) + getEndPointShape().paint (gr); + else + getControlPointShape().paint (gr); + gr.setTransform (previousTransform); + } + + } + gr.setColor(previousColor); + } + + + + private GeneralPath subdivide (Point b0, Point b1, Point b2, Point b3) { + double cutDistance = getTargetAnchorShape().getCutDistance(); + double minDistance = cutDistance - ENDPOINT_DEVIATION; + /** + * if the cutDistance is valid the last segment of the curve + * gets reduced by subdivision until the distance of the endpoint(epDistance) + * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) + */ + if(cutDistance > minDistance && minDistance > 0 ) { + GeneralPath path = new GeneralPath(); + + path.moveTo(b0.x, b0.y); + + CubicCurve2D.Double left = new CubicCurve2D.Double( + b0.x, b0.y, + b1.x, b1.y, + b2.x, b2.y, + b3.x, b3.y); + + CubicCurve2D right=new CubicCurve2D.Double(); + left.subdivide(left, right); + double distance = b3.distance(left.getP2()); + //if the distance is bigger as the cutDistance the left segment is added + //and the right segment is divided again + while(distance>cutDistance){ + path.append(left, true); + right.subdivide(left, right); + distance = b3.distance(left.getP2()); + //if the devision removed to much the left segment is divided + while(distance < minDistance) { + //changes the distance to ~ (distance+distance/2) + left.subdivide(left, right); + distance = b3.distance(left.getP2()); + } + } + //append the last segment with (minDistance < distance < cutDistance) + //actually we should check if the a division happend, but this is very unlikly + path.append(left, true); + return path; + } + return null; + } + + + + + + private static Point scaleVector(Point vector, double len) { + double scale = Math.sqrt(vector.x * vector.x + vector.y * vector.y); + if(scale==0.0) return vector; + scale = len / scale; + return new Point( + Math.round(vector.x * (float)scale), + Math.round(vector.y * (float)scale)); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/PolylineRouter.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/PolylineRouter.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,360 @@ +package at.ssw.visualizer.cfg.visual; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.Widget; + +/** + * Router Class with Collision Detection + * + * + * The returned path is a straight line there is no node widget between the source and the target node, + * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. + * The algorithm for the search of this path is limited by a fixed number of iterations defined in + * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the + * path returned contains at least 1 collision with a nodewidget. + */ + +public class PolylineRouter implements Router { + private static final float FACTOR = 0.70f; + + private static final int HEXPAND = 3; + private static final int VEXPAND = 3; + private static final int NUMBER_OF_ITERATIONS = 8; + + WidgetCollisionCollector collector; + + + public PolylineRouter(WidgetCollisionCollector collector){ + this.collector=collector; + } + + + public List routeConnection(final ConnectionWidget widget) { + if(!widget.isVisible()) return Collections.emptyList(); + + Anchor sourceAnchor = widget.getSourceAnchor(); + Anchor targetAnchor = widget.getTargetAnchor(); + + if(sourceAnchor == null || targetAnchor == null) + return null; + + Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); + + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + + + if(sourceWidget == targetWidget){//reflexive edges doesnt need any path + return Collections.emptyList(); + } + + List nodeWidgets = new ArrayList(); + + if(collector != null){ + collector.collectCollisions(nodeWidgets); + //source and target widget are not treatet as obstacle + nodeWidgets.remove(sourceWidget); + nodeWidgets.remove(targetWidget); + } + + List controlPoints = optimize(nodeWidgets, widget, start, end); + + //size==2 => straight line + //size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it + if(controlPoints.size() > 3) + controlPoints = simplify(nodeWidgets, controlPoints); + + return controlPoints; + } + + + private List simplify(Collection nodeWidgets, List list) { + List result = new ArrayList(); + result.add( list.get(0) );//add startpoint + for (int i = 1; i < list.size(); i++) { + Point prev = list.get(i - 1); + for (int j = i; j < list.size(); j++) { + Point cur = list.get(j); + if (!intersects(nodeWidgets, prev, cur)) { + i = j; + } + } + result.add(list.get(i)); + } + return result; + } + + /** + * Computates the Anchorposition like the Rectangular anchor for a + * given widget as source/target and a controlpoint as opposit anchorposition + */ + + private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { + Rectangle bounds = relatedWidget.getBounds(); + Point relatedLocation = relatedWidget.getLocation();//center of the widget + + if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) + return relatedLocation; + + float dx = controlPoint.x - relatedLocation.x; + float dy = controlPoint.y - relatedLocation.y; + + float ddx = Math.abs (dx) / (float) bounds.width; + float ddy = Math.abs (dy) / (float) bounds.height; + + float scale = 0.5f / Math.max (ddx, ddy); + + Point point = new Point (Math.round (relatedLocation.x + scale * dx), + Math.round (relatedLocation.y + scale * dy)); + return point; + } + + + + private List optimize(Collection nodeWidgets, ConnectionWidget connWidget, Point start, Point end) { + + List list = new ArrayList(); + list.add(start); + list.add(end); + + boolean progress = true; + + for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { + progress = false; + List newList = new ArrayList(); + for (int i = 0; i < list.size() - 1 ; i++) { + Point cur = list.get(i); + Point next = list.get(i + 1); + newList.add(cur); + List intermediate = optimizeLine(nodeWidgets, cur, next); + if (intermediate != null && intermediate.size() > 0) { + progress = true; + newList.addAll(intermediate);//insert new controlpoints between cur and next + } + } + newList.add(list.get(list.size()-1));//add endpoint of the polyline + list = newList; + + } + + if(list.size() > 2) { + Widget sourceNode = connWidget.getSourceAnchor().getRelatedWidget(); + Widget targetNode = connWidget.getTargetAnchor().getRelatedWidget(); + Rectangle sourceBounds = sourceNode.convertLocalToScene(sourceNode.getBounds()); + Rectangle targetBounds = targetNode.convertLocalToScene(targetNode.getBounds()); + sourceBounds.grow(HEXPAND, VEXPAND); + + /** + * add only points which are not intersecting the source and the target + * widget bounds caused by invalid bad anchor positions. The first + * and the last point is ignored cause the anchor is recalculated + * anyway. + */ + ArrayList tmp = new ArrayList(); + int listSize=list.size(); + tmp.add(list.get(0)); + int i=0; + while(++i < listSize-1) { + Point p = list.get(i); + if(!sourceBounds.contains(p) || !targetBounds.contains(p)) + tmp.add(p); + } + + tmp.add(list.get(i)); + if(tmp.size() < 3) + return tmp; + + list=tmp; + //calculate a proper anchor position using the second/penultimate controlpoint for start/end + start = this.computateAnchorPosition(connWidget.getSourceAnchor().getRelatedWidget(), list.get(1)); + end = this.computateAnchorPosition(connWidget.getTargetAnchor().getRelatedWidget(), list.get(list.size()-2)); + list.set(0,start); + list.set(list.size()-1, end); + } + return list; + } + + + /** + * trys to optimize a line from p1 to p2 to avoid collisions with node widgets + * returns null if the line doesn`t intersect with any nodewidget + * or a list with immediate points between p1 and p2 to avoid collisions + */ + private List optimizeLine(Collection nodeWidgets, Point p1, Point p2) { + Line2D line = new Line2D.Double(p1, p2); + + for(Widget w : nodeWidgets ) { + if( w.isVisible() ) { + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + + if (!line.intersects(r)) continue; + + Point location = w.getLocation(); + int distx = (int) (r.width * FACTOR); + int disty = (int) (r.height * FACTOR); + + int minIntersects = Integer.MAX_VALUE; + int min = Integer.MAX_VALUE; + List minSol = null; + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + if (i != 0 || j != 0) { + Point cur = new Point(location.x + i * distx, location.y + j * disty); + List list1 = new ArrayList(); + list1.add(p1); + list1.add(cur); + list1.add(p2); + int crossProd = Math.abs(crossProduct(p1, cur, p2)); + if (!intersects(w, list1)) { + Line2D line1 = new Line2D.Float(p1, cur); + Line2D line2 = new Line2D.Float(p2, cur); + int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2); + + if (curIntersects < minIntersects + || (curIntersects == minIntersects && crossProd < min)) { + minIntersects = curIntersects; + min = crossProd; + minSol = new ArrayList(); + minSol.add(cur); + } + } + + if (i == 0 || j == 0) { + Point cur1, cur2; + if (i == 0) { + cur1 = new Point(location.x + distx/2, location.y + j * disty); + cur2 = new Point(location.x - distx/2, location.y + j * disty); + } else { // (j == 0) + cur1 = new Point(location.x + i * distx, location.y + disty/2); + cur2 = new Point(location.x + i * distx, location.y - disty/2); + } + + Point vec1 = new Point(p1.x - cur1.x, p1.y - cur1.y); + int offset1 = vec1.x * vec1.x + vec1.y * vec1.y; + + Point vec2 = new Point(p1.x - cur2.x, p1.y - cur2.y); + int offset2 = vec2.x * vec2.x + vec2.y * vec2.y; + + if (offset2 < offset1) { + Point tmp = cur1; + cur1 = cur2; + cur2 = tmp; + } + + List list2 = new ArrayList(); + list2.add(p1); + list2.add(cur1); + list2.add(cur2); + list2.add(p2); + + int cross1 = crossProduct(p1, cur1, cur2); + int cross2 = crossProduct(cur1, cur2, p2); + + if (cross1 > 0) { + cross1 = 1; + } else if (cross1 < 0) { + cross1 = -1; + } + + if (cross2 > 0) { + cross2 = 1; + } else if (cross2 < 0) { + cross2 = -1; + } + if ((cross1 == cross2 || cross1 == 0 || cross2 == 0) && !intersects(w, list2)) { + Line2D line1 = new Line2D.Float(p1, cur1); + Line2D line2 = new Line2D.Float(cur1, cur2); + Line2D line3 = new Line2D.Float(p2, cur2); + int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2, line3); + + // This is a bit better + crossProd--; + + if (curIntersects < minIntersects + || (curIntersects == minIntersects && crossProd < min)) { + minIntersects = curIntersects; + min = crossProd; + minSol = new ArrayList(); + minSol.add(cur1); + minSol.add(cur2); + } + } + } + } + } + } + if (minSol != null) { + return minSol; + } + } + } + return null; + } + + + + private int countNodeIntersections(Collection nodeWidgets, Line2D... lines){ + int count=0; + for(Widget nw : nodeWidgets){ + if(nw.isVisible()) { + Rectangle bounds = nw.convertLocalToScene(nw.getBounds()); + for( Line2D line : lines){ + if(line.intersects(bounds)) + count++; + } + } + } + return count; + } + + + private boolean intersects(Collection nodeWidgets, Point start, Point end) { + List pointlist = new ArrayList(); + pointlist.add(start); + pointlist.add(end); + + for(Widget w : nodeWidgets){ + if(w.isVisible() && intersects(w, pointlist)) { + return true; + } + } + return false; + } + + + private boolean intersects(Widget w, List list) { + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + return intersects(list, r); + } + + + private boolean intersects(List list, Rectangle rect){ + for(int i=1; i < list.size(); i++) { + Point cur = list.get(i-1); + Point next = list.get(i); + if(rect.intersectsLine(cur.x, cur.y, next.x, next.y)) + return true; + } + return false; + } + + + private int crossProduct(Point p1, Point p2, Point p3) { + Point off1 = new Point(p1.x - p2.x, p1.y - p2.y); + Point off2 = new Point(p3.x - p2.x, p3.y - p2.y); + return (off1.x * off2.y - off1.y * off2.x); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/PolylineRouterV2.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/PolylineRouterV2.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,393 @@ +package at.ssw.visualizer.cfg.visual; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.Widget; + +/** + * Router Class with Collision Detection + * + * + * The returned path is a straight line there is no node widget between the source and the target node, + * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. + * The algorithm for the search of this path is limited by a fixed number of iterations defined in + * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the + * path returned contains at least 1 collision with a nodewidget. + * + * This class intend to solve the same problem as the class PolyLineRouter but + * uses slightly different methods. + * + uses another algorithm for solving the collision. + * + the obstacle bounds are calulated in advance to avoid a recalculation. + * - there is no heuristic, the shortest path around the widget is choosen asap. + * + * + * + */ + +public class PolylineRouterV2 implements Router { + private static final int HEXPAND = 3; + private static final int VEXPAND = 3; + private static final int NUMBER_OF_ITERATIONS = 8; + + WidgetCollisionCollector collector; + + + public PolylineRouterV2(WidgetCollisionCollector collector){ + this.collector=collector; + } + + + public List routeConnection(final ConnectionWidget widget) { + if(!widget.isVisible()) return Collections.emptyList(); + + Anchor sourceAnchor = widget.getSourceAnchor(); + Anchor targetAnchor = widget.getTargetAnchor(); + + if(sourceAnchor == null || targetAnchor == null) + return null; + + Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); + + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + + + if(sourceWidget == targetWidget){//reflexive edges doesnt need any path + return Collections.emptyList(); + } + + + Point srcCenter = this.getSceneLocation(sourceWidget); + Point tarCenter = this.getSceneLocation(targetWidget); + + List widgetObstacles = new ArrayList(); + + if(collector != null){ + collector.collectCollisions(widgetObstacles); + } + + List obstacles = new ArrayList(widgetObstacles.size()); + this.collectObstacles(obstacles, widgetObstacles, widget); + + + List controlPoints = optimize(obstacles, srcCenter, tarCenter); +// size==2 => straight line +// size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it + if(controlPoints.size() > 3){ + Point rstart = this.computateAnchorPosition(sourceWidget, controlPoints.get(1)); + Point rend = this.computateAnchorPosition(targetWidget, controlPoints.get(controlPoints.size()-2)); + controlPoints.set(0, rstart); + controlPoints.set(controlPoints.size()-1, rend); + controlPoints = simplify(obstacles, controlPoints); + } else if (controlPoints.size()>=2){ + //use old points + controlPoints.set(0, start); + controlPoints.set(controlPoints.size()-1, end); + + } + return controlPoints; + } + + + private int collectObstacles(List colrects, List colwidgets , ConnectionWidget cw){ + int count=0; + Anchor sourceAnchor = cw.getSourceAnchor(); + Anchor targetAnchor = cw.getTargetAnchor(); + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + Point start = sourceAnchor.compute(cw.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(cw.getTargetAnchorEntry()).getAnchorSceneLocation(); + + for(Widget w : colwidgets){ + + if(w==sourceWidget || w == targetWidget) continue; + + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + if(r.intersectsLine(start.x,start.y,end.x,end.y)) + count++; + colrects.add(r); + } + return count; + } + + + private Point center (Rectangle bounds) { + return new Point (bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); + } + + /** + * Returns the scene location of a related widget. + * bounds might be null if the widget was not added to the scene + * @return the scene location; null if no related widget is assigned + */ + public Point getSceneLocation (Widget relatedWidget) { + if (relatedWidget != null) { + Rectangle bounds = relatedWidget.getBounds (); + if(bounds != null) + return center(relatedWidget.convertLocalToScene(bounds)); + } + return null; + } + + /** + * Computates the Anchorposition like the Rectangular anchor for a + * given widget as source/target and a controlpoint as opposit anchorposition + */ + + private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { + Rectangle bounds = relatedWidget.getBounds(); + + //todo: fix, center of widget must be cacluated trough the bounds + //since there are some wheird widgets where the location is not the center of the widget + Point relatedLocation = relatedWidget.getLocation();//center of the widget + + if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) + return relatedLocation; + + float dx = controlPoint.x - relatedLocation.x; + float dy = controlPoint.y - relatedLocation.y; + + float ddx = Math.abs (dx) / (float) bounds.width; + float ddy = Math.abs (dy) / (float) bounds.height; + + float scale = 0.5f / Math.max (ddx, ddy); + + Point point = new Point (Math.round (relatedLocation.x + scale * dx), + Math.round (relatedLocation.y + scale * dy)); + return point; + } + + private List simplify(List obstacles, List list) { + List result = new ArrayList(list.size()); + result.add( list.get(0) );//add startpoint + for (int i = 1; i < list.size(); i++) { + Point prev = list.get(i - 1); + for (int j = i; j < list.size(); j++) { + Point cur = list.get(j); + if (!intersects(obstacles, prev, cur)) { + i = j; + } + } + result.add(list.get(i)); + } + return result; + } + + private List optimize(List nodeWidgets, Point start, Point end) { + + List list = new ArrayList(); + list.add(start); + list.add(end); + + boolean progress = true; + + for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { + progress = false; + List newList = new ArrayList(); + for (int i = 0; i < list.size() - 1 ; i++) { + Point cur = list.get(i); + Point next = list.get(i + 1); + newList.add(cur); + List intermediate = optimizeLine(nodeWidgets, cur, next); + if (intermediate != null && intermediate.size() > 0) { + progress = true; + newList.addAll(intermediate);//insert new controlpoints between cur and next + } + } + newList.add(list.get(list.size()-1));//add endpoint of the polyline + list = newList; + + } + + return list; + } + + + /** + * trys to optimize a line from p1 to p2 to avoid collisions with rectangles + * returns null if the line doesn`t intersect with any nodewidget or + * if the obstacles are overlapping + * ---------------------------------------------------------------------- + * if the collision is solved it returns a list with immediate points + * between p1 and p2. The points are taken from hull points of and grown + * rectangle. + */ + private List optimizeLine(List obstacles, Point p1, Point p2) { + Line2D line = new Line2D.Double(p1, p2); + boolean inbounds=false; + Rectangle ibr=null; + ArrayList sol = new ArrayList(); + boolean leftIntersection; + boolean rightIntersection; + boolean bottomIntersection; + boolean topIntersection; + Point interLeft=new Point(); + Point interRight=new Point(); + Point interBot=new Point(); + Point interTop=new Point(); + + + + for(Rectangle r : obstacles ) { + if (!line.intersects(r)) continue; + + int w=r.width+2; + int h=r.height+2; + Point topLeft = r.getLocation(); + topLeft.x-=1; + topLeft.y-=1; + Point topRight = new Point(topLeft.x+w, topLeft.y); + Point bottomLeft = new Point(topLeft.x, topLeft.y+h); + Point bottomRight = new Point(topRight.x, bottomLeft.y); + leftIntersection = findIntersectionPoint(p1, p2, topLeft, bottomLeft, interLeft); + rightIntersection = findIntersectionPoint(p1, p2, topRight, bottomRight, interRight); + bottomIntersection = findIntersectionPoint(p1, p2, bottomLeft, bottomRight, interBot); + topIntersection = findIntersectionPoint(p1, p2, topLeft, topRight, interTop); + + //Intersection points are not used yet. This could be actually a + //good approach to avoid additional collisions because it would be + //still the same vector. + + if(leftIntersection) { + if(topIntersection) {//left and top + sol.add(topLeft); + } + else if(bottomIntersection){//left and bottom + sol.add(bottomLeft); + } + else if(rightIntersection){//left and right + double disttl = topLeft.distance(p1); + double distbl = bottomLeft.distance(p1); + if(disttl > distbl){ + //pass at the bottom + double distbr = bottomRight.distance(p1); + if(distbl < distbr){ + //from the left to the right + sol.add(bottomLeft); + sol.add(bottomRight); + } else { + //from the right to the left + sol.add(bottomRight); + sol.add(bottomLeft); + } + } else { + //pass at the top + double disttr = topRight.distance(p1); + if(disttl < disttr){ + //from the left to the right + sol.add(topLeft); + sol.add(topRight); + } else { + //from the right to the left + sol.add(topRight); + sol.add(topLeft); + } + } + } else {//only left => inside bounds + inbounds=true; + } + } else if (rightIntersection) { + if(topIntersection) {//right and top + sol.add(topRight); + } + else if(bottomIntersection){//right and bottom + sol.add(bottomRight); + } else { //only right => inside the bounds + inbounds=true; + } + } else if (topIntersection && bottomIntersection) {//top and bottom + double disttop = interTop.distance(p1); + double distbot = interBot.distance(p1); + if(disttop < distbot ){ + //from the top to the bottom + double distleft = interTop.distance(topLeft); + double distright = interTop.distance(topRight); + if(distleft < distright){ + //pass left + sol.add(topLeft); + sol.add(bottomLeft); + } else { + //pass right + sol.add(topRight); + sol.add(bottomRight); + } + } else { + //from the bottom to the top + double distleft = interBot.distance(bottomLeft); + double distright = interBot.distance(bottomRight); + if(distleft < distright){ + //pass left + sol.add(bottomLeft); + sol.add(topLeft); + } else { + //pass right + sol.add(bottomRight); + sol.add(topRight); + } + } + } else {//only bottom or only top + inbounds=true; + } /* ENDIF */ + + //breakpoint <-- collision detected + + if(sol.size()>0) {//solution found + assert(!inbounds); + return sol; + } else { //no solution found=> inbounds + assert(inbounds); + assert(sol.size()==0); + //handle collision or just skip it and search for the next collisionj + ibr=r; + //jump out of the loop to able to interate over the obstacles + break; + } + }/* end foreach obstacle */ + + if(inbounds || ibr != null){ + assert(inbounds); + assert(ibr!=null); + } + return null;//no collison found + }/* end optimizeLine */ + + + + //check intersection between line p0->p1 for a given set of obstacles + private static boolean intersects(List obstacles, Point p0, Point p1) { + for(Rectangle r : obstacles){ + if(r.intersectsLine(p0.x, p0.y, p1.x, p1.y)) + return true; + } + return false; + } + + + private boolean findIntersectionPoint( + Point p0, Point p1, Point p2, Point p3, Point pI) { + float q = (p0.y - p2.y)*(p3.x - p2.x) - (p0.x - p2.x)*(p3.y - p2.y); + float d = (p1.x - p0.x)*(p3.y - p2.y) - (p1.y - p0.y)*(p3.x - p2.x); + + //parallel ? + if(d==0) return false; + + float r = q / d; + q = (p0.y - p2.y)*(p1.x - p0.x) - (p0.x - p2.x)*(p1.y - p0.y); + + float s = q / d; + if(r<0 || r>1 || s<0 || s>1) return false; + + pI.x = p0.x + (int) (0.5f + r * (p1.x - p0.x)); + pI.y = p0.y + (int) (0.5f + r * (p1.y - p0.y)); + return true; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/SplineConnectionWidget.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/SplineConnectionWidget.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,541 @@ +package at.ssw.visualizer.cfg.visual; + +import org.netbeans.api.visual.widget.ConnectionWidget; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.List; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +/** + * In comparison to the default ConnectionWidget this class is able to connect + * widgets with a curve instead of a straight line sequence. + * In conjunction with a suitable router the connection will be a straight line + * or a curve depending on the amount and the position of the controlpoints. + * Controlpoints supplied by the router, are treated as curve intersection points. + * For Reflexive edges the router doesn`t necessarily need to supply + * any controlpoints, they get painted by this automatically, this can be + * excepted if the router supplys more as 2 control points for a self edge, + * then the edge gets painted with the default curve interpolation algorithm. + * The method used for drawing curves uses a piecewise cubic interpolation + * algorithm. Between two control points a curve is painted as cubic bezier + * curve the, inner bezier points are calculated automatically with FMILL + * tangents and a chord parametrization, this interpolant is also known as + * cutmull-rom spline. The resulting spline fullfills c^1 continuity. + * The the end points the interpolation algorithm uses the bessel end condition. + */ + +public class SplineConnectionWidget extends ConnectionWidget { + private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy + private static final double HIT_DISTANCE_SQUARE = 4.0;//distance for intersection test + private GraphScene scene=null; + private Point2D [] bezierPoints = null; + + public SplineConnectionWidget(Scene scene) { + super(scene); + if(scene instanceof GraphScene) + this.scene=(GraphScene) scene; + } + + //check for self - edge + private boolean isReflexive(){ + return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); + } + + + @Override + protected Rectangle calculateClientArea() { + + Rectangle bounds = null; + + if(this.getControlPoints().size()>2){ + bezierPoints = createBezierPoints(getControlPoints()); + } + //minmax method - returns the smallest bounding rectangle + //Curves and surfaces for CAGD (3rd ed.), p.54 + //exact calculation of the bounding min rect + if(bezierPoints != null) { + Rectangle2D bounds2D = null; + for (int i = 0; i < bezierPoints.length; i++) { + Point2D point = bezierPoints[i]; + if(bounds2D==null) + bounds2D = new Rectangle2D.Double(point.getX(),point.getY(),0,0); + else + bounds2D.add(point); + } + bounds = bounds2D.getBounds(); + bounds.grow(2, 2); + + } else if (getControlPoints().size()>0){ + for(Point p : this.getControlPoints()){ + if(bounds==null) + bounds = new Rectangle(p); + else + bounds.add(p); + } + bounds.grow(5,5); + + } else if (isReflexive()) { + Widget related = this.getTargetAnchor().getRelatedWidget(); + bounds = related.convertLocalToScene(related.getBounds()); + bounds.grow(10, 10); + } + + if(bounds==null) + bounds = super.calculateClientArea(); + + return bounds; + } + + + /** + * if the edge is reflexive its painted as a cyclic self edge, if there + * are two controlpoints the connection is painted as a straight line from + * the source to the targetanchor, if there are more as 2 controlpoints the + * connection path between two control points is painted as cutmull rom + * spline with bessel end tangents. + */ + @Override + protected void paintWidget () { + List contrPoints = this.getControlPoints(); + int listSize = contrPoints.size(); + + Graphics2D gr = getGraphics (); + + if (listSize <= 2) { + this.bezierPoints=null;//set bezier Points null for calulateClientArea() + if(isReflexive()) { //special case for reflexive connection widgets + this.drawReflexive(gr); + } else { + super.paintWidget(); + } + return; + } + + //bezier curve... listSize > 2 + GeneralPath curvePath = new GeneralPath(); + double lastControlPointRotation = 0.0; + + + Point2D [] bezPoints = this.createBezierPoints(contrPoints); + curvePath.moveTo(bezPoints[0].getX(), bezPoints[0].getY());//b00 + + //last segment is added by subdivision thats why its -5 + for (int i = 1; i < bezPoints.length-5; i+=3) { + curvePath.curveTo( + bezPoints[i].getX(), bezPoints[i].getY(),//b1i + bezPoints[i+1].getX(), bezPoints[i+1].getY(),//b2i + bezPoints[i+2].getX(), bezPoints[i+2].getY());//b3i + + } + + GeneralPath lastseg = subdivide2D( + bezPoints[bezPoints.length-4], + bezPoints[bezPoints.length-3], + bezPoints[bezPoints.length-2], + bezPoints[bezPoints.length-1]); + + + if(lastseg != null) + curvePath.append(lastseg, true); + + Point2D cur = curvePath.getCurrentPoint(); + Point lastControlPoint = contrPoints.get(listSize-1); + + lastControlPointRotation = //anchor anchorAngle + Math.atan2 (cur.getY() - lastControlPoint.y, cur.getX() - lastControlPoint.x); + + gr.setStroke(getStroke()); + gr.setColor(getLineColor()); + gr.draw(curvePath); + + + AffineTransform previousTransform = gr.getTransform (); + gr.translate (lastControlPoint.x, lastControlPoint.y); + gr.rotate (lastControlPointRotation); + AnchorShape targetAnchorShape = this.getTargetAnchorShape(); + targetAnchorShape.paint (gr, false); + gr.setTransform (previousTransform); + + //paint ControlPoints if enabled + if (isPaintControlPoints()) { + int last = listSize - 1; + for (int index = 0; index <= last; index ++) { + Point point = contrPoints.get (index); + previousTransform = gr.getTransform (); + gr.translate (point.x, point.y); + if (index == 0 || index == last) + getEndPointShape().paint (gr); + else + getControlPointShape().paint (gr); + gr.setTransform (previousTransform); + } + + } + } + + private void drawReflexive(Graphics2D gr){ + Widget related = this.getTargetAnchor().getRelatedWidget(); + int position = this.edgeBalance(related); + Rectangle bounds = related.convertLocalToScene(related.getBounds()); + gr.setColor (getLineColor()); + Point first = new Point(); + Point last = new Point(); + double centerX = bounds.getCenterX(); + first.x = (int) (centerX + bounds.width / 4); + first.y = bounds.y + bounds.height; + last.x = first.x; + last.y = bounds.y; + + gr.setStroke(this.getStroke()); + + double cutDistance = this.getTargetAnchorShape().getCutDistance(); + double anchorAngle = Math.PI/-3.0; + double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); + double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); + int ydiff=first.y-last.y; + int endy = -ydiff; + double height=bounds.getHeight(); + double cy = height/4.0; + double cx=bounds.getWidth()/5.0; + double dcx = cx*2; + GeneralPath gp = new GeneralPath(); + gp.moveTo(0, 0); + gp.quadTo(0, cy, cx, cy); + gp.quadTo(dcx, cy, dcx, -height/2.0); + gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); + gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); + + AffineTransform af = new AffineTransform(); + AnchorShape anchorShape = this.getTargetAnchorShape(); + + if(position < 0) { + first.x = (int) (centerX - bounds.width / 4); + af.translate(first.x, first.y); + af.scale(-1.0, 1.0); + last.x = first.x; + } else { + af.translate(first.x, first.y); + } + Shape s = gp.createTransformedShape(af); + gr.draw(s); + + if (last != null) { + AffineTransform previousTransform = gr.getTransform (); + gr.translate (last.x, last.y); + + if(position < 0) + gr.rotate(Math.PI - anchorAngle); + else + gr.rotate (anchorAngle); + + anchorShape.paint (gr, false); + gr.setTransform (previousTransform); + } + } + + //returns prefered location for an edge -1 for left and 1 for right + private int edgeBalance(Widget nodeWidget) { + if(scene == null) + return 1; + + Point nodeLocation = nodeWidget.getLocation(); + int left = 0, right = 0; + + Object node = scene.findObject(nodeWidget); + + for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges + ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); + + if(cw != this) { + Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); + + Point location; + if(targetNodeWidget == nodeWidget) { + Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); + location = sourceNodeWidget.getLocation(); + } else { + location = targetNodeWidget.getLocation(); + } + + if(location.x < nodeLocation.x) + left++; + else + right++; + } + } + if(left < right) + return -1; + else + return 1; + } + + + private Point2D[] createBezierPoints(List list){ + if(list.size()<3) return null ; + + + int lastIdx = list.size()-1; + + + //chord length parametrization + double[] uis = new double[list.size()]; + uis[0]=0; + uis[1] = list.get(1).distance(list.get(0)); + for (int i = 1; i < uis.length; i++) { + Point cur = list.get(i); + Point prev = list.get(i-1); + uis[i]=uis[i-1]+ cur.distance(prev); + } + + + for (int i = 1; i < uis.length; i++) { + uis[i] /= uis[lastIdx]; + + } + double[] delta = new double[uis.length-1]; + for (int i = 0; i < delta.length; i++) { + double ui = uis[i]; + double uin = uis[i+1]; + delta[i] = uin-ui; + } + + + //FMILL tangent directions (chord length) + Point2D[] tangents = new Point2D[list.size()]; + + for (int i = 1; i < list.size()-1; i++) { + Point xBefore = list.get(i-1); + Point xAfter = list.get(i+1); + Point2D.Double tangent = new Point2D.Double (xAfter.x - xBefore.x, xAfter.y - xBefore.y); + tangents[i] = tangent; + } + + + Point2D [] bezPoints = new Point2D[(list.size()-1)*2+list.size()]; + //Catmull-Rom + for (int i = 1; i < list.size()-1; i++) { + Point b3i = list.get(i); + Point2D b3ib = b3iBefore(b3i, delta[i-1], delta[i], tangents[i]); + Point2D b3ia = b3iAfter(b3i, delta[i-1], delta[i], tangents[i]); + bezPoints[3*i] = b3i; + bezPoints[3*i-1] = b3ib; + bezPoints[3*i+1] = b3ia; + } + bezPoints[0] = list.get(0); + bezPoints[bezPoints.length-1] = list.get(list.size()-1); + + Point p0 = list.get(0); + Point p1 = list.get(1); + Point p2 = list.get(2); + Point pL_2 = list.get(lastIdx-2); + Point pL_1 = list.get(lastIdx-1); + Point pL = list.get(lastIdx); + + Point2D m1 = besselTangent(delta[0], delta[1], p0, p1, p2); + Point2D m0 = besselEndTangent(p0, p1, delta[0], m1); + + Point2D mLb = besselTangent(delta[delta.length-2], delta[delta.length-1], + pL_2,pL_1, pL); + Point2D mL = besselEndTangent(pL_1, pL, delta[delta.length-1], mLb); + + Point2D scaleM0 = scale(normalize(m0), p0.distance(p1));//increase distx/distxl to make curve rounder at the end + Point2D scaleML = scale(normalize(mL), pL.distance(pL_1)); + //Catmull-Rom for bessel points + Point2D b30a = b3iAfter(p0, delta[0], delta[0],scaleM0); + Point2D b33b = b3iBefore(pL, delta[delta.length-1], delta[delta.length-1],scaleML); + + bezPoints[1] = b30a; + bezPoints[bezPoints.length-2] = b33b; + + return bezPoints; + } + + + + private static Point2D besselTangent(double delta_ib, double delta_i, Point2D p0, Point2D p1 , Point2D p2){ + double alpha_i = delta_ib/(delta_ib+delta_i); + + double x = (1-alpha_i)/delta_ib * (p1.getX() - p0.getX()) + + alpha_i/delta_i * (p2.getX()-p1.getX()); + double y = (1-alpha_i)/delta_ib * (p1.getY() - p0.getY()) + + alpha_i/delta_i * (p2.getY()-p1.getY()); + + return new Point2D.Double(x,y); + } + + private static Point2D besselEndTangent(Point2D p0, Point2D p1, double delta_u, Point2D m){ + double x = 2*((p1.getX()-p0.getX())/delta_u) - m.getX(); + double y = 2*((p1.getY()-p0.getY())/delta_u) - m.getY(); + return new Point2D.Double(x,y); + } + + private static Point2D b3iBefore(Point2D b3i, double delta_ib, double delta_i, Point2D li){ + double x = b3i.getX() - (delta_ib/(3*(delta_ib+delta_i)))*li.getX(); + double y = b3i.getY() - (delta_ib/(3*(delta_ib+delta_i)))*li.getY(); + return new Point.Double(x,y); + } + + private static Point2D b3iAfter(Point2D b3i, double delta_ib,double delta_i,Point2D li){ + double x = b3i.getX() + (delta_i/(3*(delta_ib+delta_i)))*li.getX(); + double y = b3i.getY() + (delta_i/(3*(delta_ib+delta_i)))*li.getY(); + return new Point.Double(x,y); + } + + + + + //returns length of vector v + private static double norm(Point2D v){ + return Math.sqrt(v.getX()*v.getX()+v.getY()*v.getY()); + } + + //returns unity vector of vector v + private static Point2D normalize(Point2D v){ + double norm = norm(v); + if(norm==0) return new Point2D.Double(v.getX(), v.getY()); + return new Point2D.Double(v.getX()/norm , v.getY()/norm); + } + + //scale vector to size of length + private static Point2D scale(Point2D v, double length){ + Point2D tmp = normalize(v); + return new Point2D.Double(tmp.getX()*length, tmp.getY()*length); + } + + + + private GeneralPath subdivide2D (Point2D b0, Point2D b1, Point2D b2, Point2D b3) { + //set 2nd intermediate point to endpoint + //we could actually use another "better" point if we like to have a smoother curve + + double cutDistance = getTargetAnchorShape().getCutDistance(); + double minDistance = cutDistance - ENDPOINT_DEVIATION; + /** + * if the cutDistance is valid the last segment of the curve + * gets reduced by subdivision until the distance of the endpoint(epDistance) + * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) + */ + if(cutDistance > minDistance && minDistance > 0 ) { + GeneralPath path = new GeneralPath(); + + path.moveTo(b0.getX(), b0.getY()); + + CubicCurve2D.Double curve = new CubicCurve2D.Double( + b0.getX(), b0.getY(), + b1.getX(), b1.getY(), + b2.getX(), b2.getY(), + b3.getX(), b3.getY()); + + + + CubicCurve2D right=new CubicCurve2D.Double(); + CubicCurve2D left=new CubicCurve2D.Double(); + curve.subdivide(left, right); + double distance = b3.distance(left.getP2()); + //if the distance is bigger as the cutDistance the left segment is added + //and the right segment is divided again + while(distance>cutDistance){ + path.append(left, true); + right.subdivide(left, right); + distance = b3.distance(left.getP2()); + //if the devision removed to much the left segment is divided + while(distance < minDistance) { + //changes the distance to ~ (distance+distance/2) + left.subdivide(left, right); + distance = b3.distance(left.getP2()); + } + } + //append the last segment with (minDistance < distance < cutDistance) + path.append(left, true); + return path; + } + return null; + } + + + /** + * Returns whether a specified local point pL is a part of the connection + * widget. + * First it make a rough bounds check + * for Line Segments => use Super call (ConnectionWidget.isHitAt(pL)). + * for self-edges => its sufficent to return getBounds.contains(pL). + * for Splines => Interate over all Partitial segments of the curve and make + * a minmax check with the bezier points. If pL is inside the minmax + * rectangle of one segment the curve is constructed and subdivided until + * the distance d between center point pC (of the bounding rectangle) + * and pL is below HIT_DISTANCE_SQUARE, in this case it returns true. + * If no no minmax check was successful or the subdivision lead to an + * rectangle witch doesn`t contain pL return false. + * @param localLocation the local location + * @return true, if the location is a part of the connection widget + */ + @Override + public boolean isHitAt(Point localLocation) { + if(!isVisible() || !getBounds ().contains (localLocation)) + return false; + + List controlPoints = getControlPoints (); + if(controlPoints.size() <=2){ + if(isReflexive()) return true; + return super.isHitAt(localLocation); + } + + if(bezierPoints != null) { + for (int i = 0; i < bezierPoints.length-1; i+=3) { + Point2D b0 = bezierPoints[i]; + Point2D b1 = bezierPoints[i+1]; + Point2D b2 = bezierPoints[i+2]; + Point2D b3 = bezierPoints[i+3]; + + CubicCurve2D left = new CubicCurve2D.Double( + b0.getX(), b0.getY(), + b1.getX(), b1.getY(), + b2.getX(), b2.getY(), + b3.getX(), b3.getY()); + + + Rectangle2D bounds = left.getBounds2D(); + while(bounds.contains(localLocation)) { + //calculate the center and use HIT_DISTANCE_SQUARE for a range check + Point2D test = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY()); + if(test.distance(localLocation) < HIT_DISTANCE_SQUARE){ + return true; + } + + + CubicCurve2D right = new CubicCurve2D.Double(); + left.subdivide(left, right); + Rectangle2D lb2d = left.getBounds2D(); + Rectangle2D rb2d = right.getBounds2D(); + if( lb2d.contains(localLocation)){ + bounds = lb2d; + } else if (rb2d.contains(localLocation)) { + left = right; + bounds = rb2d; + } else { + return false; + } + + }//end while + }//end for + } + return false; + } + + +} + + + + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/WidgetCollisionCollector.java.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/.svn/text-base/WidgetCollisionCollector.java.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,12 @@ +package at.ssw.visualizer.cfg.visual; + +import java.util.List; +import org.netbeans.api.visual.widget.Widget; + + +public interface WidgetCollisionCollector { + + //returns a list of widgets which should be handled as obstacles + void collectCollisions(List collisions); + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/BezierWidget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/BezierWidget.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,345 @@ +package at.ssw.visualizer.cfg.visual; + +import org.netbeans.api.visual.widget.ConnectionWidget; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.util.List; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +/** + * In comparison to the default ConnectionWidget this class is able to connect + * Widgets with a curve instead of a straight line sequence. Between two control + * points a curve is painted as cubic bezier curve the control points are + * calculated automaticaly they depend on the position of the prior- and the + * following control points. + * In conjunction with a suitable router the connection will be a straight line + * or a curve depending on the amount and the position of the controlpoints. + * Controlpoints supplied by the router, are treated as curve intersection points. + * For Reflexive edges the router doesn`t need to supply controlpoints, they + * get painted by this class automatically. If the router supplys more as 2 + * control points for a recursive edge the edge gets painted with the default + * curve approximation algorithm. + */ +public class BezierWidget extends ConnectionWidget { + private static final double BEZIER_SCALE = 0.3; + private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy + + private GraphScene scene=null; + + public BezierWidget(Scene scene) { + super(scene); + } + + public BezierWidget(GraphScene scene) { + super(scene); + this.scene=scene; + } + + + private boolean isReflexive(){ + return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); + } + + + @Override + protected Rectangle calculateClientArea() { + Rectangle bounds = null; + if(this.getControlPoints().size()>0){ + for(Point p : this.getControlPoints()){ + if(bounds==null) + bounds = new Rectangle(p); + else + bounds.add(p); + } + bounds.grow(5,5); + } + if(isReflexive()){ + Widget related = this.getTargetAnchor().getRelatedWidget(); + bounds = related.convertLocalToScene(related.getBounds()); + bounds.grow(10, 10); + } + if(bounds==null) + bounds = super.calculateClientArea(); + + return bounds; + } + + + + //returns prefered location for an edge -1 for left and 1 for right + private int edgeBalance(Widget nodeWidget) { + if(scene == null) + return 1; + + Point nodeLocation = nodeWidget.getLocation(); + int left = 0, right = 0; + + Object node = scene.findObject(nodeWidget); + + for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges + ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); + + if(cw != this) { + Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); + + Point location; + if(targetNodeWidget == nodeWidget) { + Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); + location = sourceNodeWidget.getLocation(); + } else { + location = targetNodeWidget.getLocation(); + } + + if(location.x < nodeLocation.x) + left++; + else + right++; + } + } + if(left < right) + return -1; + else + return 1; + } + + + + + /** + * if the edge is reflexive its painted as a cyclic edge + * if there are 2 controlpoints the connection is painted as a straight line from the source to the targetanchor + * if there are more as 2 controlpoints the connection path between 2 control points is painted as bezier curve + */ + + @Override + protected void paintWidget () { + + List contrPoints = this.getControlPoints(); + int listSize = contrPoints.size(); + + Graphics2D gr = getGraphics (); + + if (listSize <= 2) { + if(isReflexive()) { //special case for reflexive connection widgets + Widget related = this.getTargetAnchor().getRelatedWidget(); + int position = this.edgeBalance(related); + Rectangle bounds = related.convertLocalToScene(related.getBounds()); + gr.setColor (getLineColor()); + Point first = new Point(); + Point last = new Point(); + double centerX = bounds.getCenterX(); + first.x = (int) (centerX + bounds.width / 4); + first.y = bounds.y + bounds.height; + last.x = first.x; + last.y = bounds.y; + + gr.setStroke(this.getStroke()); + + double cutDistance = this.getTargetAnchorShape().getCutDistance(); + double anchorAngle = Math.PI/-3.0; + double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); + double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); + int ydiff=first.y-last.y; + int endy = -ydiff; + double height=bounds.getHeight(); + double cy = height/4.0; + double cx=bounds.getWidth()/5.0; + double dcx = cx*2; + GeneralPath gp = new GeneralPath(); + gp.moveTo(0, 0); + gp.quadTo(0, cy, cx, cy); + gp.quadTo(dcx, cy, dcx, -height/2.0); + gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); + gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); + + AffineTransform af = new AffineTransform(); + AnchorShape anchorShape = this.getTargetAnchorShape(); + + if(position < 0) { + first.x = (int) (centerX - bounds.width / 4); + af.translate(first.x, first.y); + af.scale(-1.0, 1.0); + last.x = first.x; + } else { + af.translate(first.x, first.y); + } + Shape s = gp.createTransformedShape(af); + gr.draw(s); + + if (last != null) { + AffineTransform previousTransform = gr.getTransform (); + gr.translate (last.x, last.y); + + if(position < 0) + gr.rotate(Math.PI - anchorAngle); + else + gr.rotate (anchorAngle); + + anchorShape.paint (gr, false); + gr.setTransform (previousTransform); + } + + } else { + super.paintWidget(); + } + return; + } + + //bezier curve... + GeneralPath curvePath = new GeneralPath(); + Point lastControlPoint = null; + double lastControlPointRotation = 0.0; + + Point prev = null; + for (int i = 0; i < listSize - 1; i++) { + Point cur = contrPoints.get(i); + Point next = contrPoints.get(i + 1); + Point nextnext = null; + if (i < listSize - 2) { + nextnext = contrPoints.get(i + 2); + } + + double len = cur.distance(next); + double scale = len * BEZIER_SCALE; + Point bezierFrom = null;//first ControlPoint + Point bezierTo = null;//second ControlPoint + + if (prev == null) { + //first point + curvePath.moveTo(cur.x, cur.y);//startpoint + bezierFrom = cur; + } else { + bezierFrom = new Point(next.x - prev.x, next.y - prev.y); + bezierFrom = scaleVector(bezierFrom, scale); + bezierFrom.translate(cur.x, cur.y); + } + + if (nextnext == null) {//next== last point (curve to) + lastControlPoint=next; + bezierTo = next;//set 2nd intermediate point to endpoint + GeneralPath lastseg = this.subdivide(cur, bezierFrom, bezierTo, next); + if(lastseg != null) + curvePath.append(lastseg, true); + break; + } else { + bezierTo = new Point(cur.x - nextnext.x, cur.y - nextnext.y); + bezierTo = scaleVector(bezierTo, scale); + bezierTo.translate(next.x, next.y); + } + + curvePath.curveTo( + bezierFrom.x, bezierFrom.y,//controlPoint1 + bezierTo.x, bezierTo.y,//controlPoint2 + next.x,next.y + ); + prev = cur; + } + Point2D cur = curvePath.getCurrentPoint(); + Point next = lastControlPoint; + + lastControlPointRotation = //anchor anchorAngle + Math.atan2 (cur.getY() - next.y, cur.getX() - next.x); + + Color previousColor = gr.getColor(); + gr.setColor (getLineColor()); + Stroke s = this.getStroke(); + gr.setStroke(s); + gr.setColor(this.getLineColor()); + gr.draw(curvePath); + + AffineTransform previousTransform = gr.getTransform (); + gr.translate (lastControlPoint.x, lastControlPoint.y); + gr.rotate (lastControlPointRotation); + AnchorShape targetAnchorShape = this.getTargetAnchorShape(); + targetAnchorShape.paint (gr, false); + gr.setTransform (previousTransform); + + //paint ControlPoints if enabled + if (isPaintControlPoints()) { + int last = listSize - 1; + for (int index = 0; index <= last; index ++) { + Point point = contrPoints.get (index); + previousTransform = gr.getTransform (); + gr.translate (point.x, point.y); + if (index == 0 || index == last) + getEndPointShape().paint (gr); + else + getControlPointShape().paint (gr); + gr.setTransform (previousTransform); + } + + } + gr.setColor(previousColor); + } + + + + private GeneralPath subdivide (Point b0, Point b1, Point b2, Point b3) { + double cutDistance = getTargetAnchorShape().getCutDistance(); + double minDistance = cutDistance - ENDPOINT_DEVIATION; + /** + * if the cutDistance is valid the last segment of the curve + * gets reduced by subdivision until the distance of the endpoint(epDistance) + * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) + */ + if(cutDistance > minDistance && minDistance > 0 ) { + GeneralPath path = new GeneralPath(); + + path.moveTo(b0.x, b0.y); + + CubicCurve2D.Double left = new CubicCurve2D.Double( + b0.x, b0.y, + b1.x, b1.y, + b2.x, b2.y, + b3.x, b3.y); + + CubicCurve2D right=new CubicCurve2D.Double(); + left.subdivide(left, right); + double distance = b3.distance(left.getP2()); + //if the distance is bigger as the cutDistance the left segment is added + //and the right segment is divided again + while(distance>cutDistance){ + path.append(left, true); + right.subdivide(left, right); + distance = b3.distance(left.getP2()); + //if the devision removed to much the left segment is divided + while(distance < minDistance) { + //changes the distance to ~ (distance+distance/2) + left.subdivide(left, right); + distance = b3.distance(left.getP2()); + } + } + //append the last segment with (minDistance < distance < cutDistance) + //actually we should check if the a division happend, but this is very unlikly + path.append(left, true); + return path; + } + return null; + } + + + + + + private static Point scaleVector(Point vector, double len) { + double scale = Math.sqrt(vector.x * vector.x + vector.y * vector.y); + if(scale==0.0) return vector; + scale = len / scale; + return new Point( + Math.round(vector.x * (float)scale), + Math.round(vector.y * (float)scale)); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouter.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,360 @@ +package at.ssw.visualizer.cfg.visual; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.Widget; + +/** + * Router Class with Collision Detection + * + * + * The returned path is a straight line there is no node widget between the source and the target node, + * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. + * The algorithm for the search of this path is limited by a fixed number of iterations defined in + * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the + * path returned contains at least 1 collision with a nodewidget. + */ + +public class PolylineRouter implements Router { + private static final float FACTOR = 0.70f; + + private static final int HEXPAND = 3; + private static final int VEXPAND = 3; + private static final int NUMBER_OF_ITERATIONS = 8; + + WidgetCollisionCollector collector; + + + public PolylineRouter(WidgetCollisionCollector collector){ + this.collector=collector; + } + + + public List routeConnection(final ConnectionWidget widget) { + if(!widget.isVisible()) return Collections.emptyList(); + + Anchor sourceAnchor = widget.getSourceAnchor(); + Anchor targetAnchor = widget.getTargetAnchor(); + + if(sourceAnchor == null || targetAnchor == null) + return null; + + Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); + + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + + + if(sourceWidget == targetWidget){//reflexive edges doesnt need any path + return Collections.emptyList(); + } + + List nodeWidgets = new ArrayList(); + + if(collector != null){ + collector.collectCollisions(nodeWidgets); + //source and target widget are not treatet as obstacle + nodeWidgets.remove(sourceWidget); + nodeWidgets.remove(targetWidget); + } + + List controlPoints = optimize(nodeWidgets, widget, start, end); + + //size==2 => straight line + //size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it + if(controlPoints.size() > 3) + controlPoints = simplify(nodeWidgets, controlPoints); + + return controlPoints; + } + + + private List simplify(Collection nodeWidgets, List list) { + List result = new ArrayList(); + result.add( list.get(0) );//add startpoint + for (int i = 1; i < list.size(); i++) { + Point prev = list.get(i - 1); + for (int j = i; j < list.size(); j++) { + Point cur = list.get(j); + if (!intersects(nodeWidgets, prev, cur)) { + i = j; + } + } + result.add(list.get(i)); + } + return result; + } + + /** + * Computates the Anchorposition like the Rectangular anchor for a + * given widget as source/target and a controlpoint as opposit anchorposition + */ + + private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { + Rectangle bounds = relatedWidget.getBounds(); + Point relatedLocation = relatedWidget.getLocation();//center of the widget + + if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) + return relatedLocation; + + float dx = controlPoint.x - relatedLocation.x; + float dy = controlPoint.y - relatedLocation.y; + + float ddx = Math.abs (dx) / (float) bounds.width; + float ddy = Math.abs (dy) / (float) bounds.height; + + float scale = 0.5f / Math.max (ddx, ddy); + + Point point = new Point (Math.round (relatedLocation.x + scale * dx), + Math.round (relatedLocation.y + scale * dy)); + return point; + } + + + + private List optimize(Collection nodeWidgets, ConnectionWidget connWidget, Point start, Point end) { + + List list = new ArrayList(); + list.add(start); + list.add(end); + + boolean progress = true; + + for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { + progress = false; + List newList = new ArrayList(); + for (int i = 0; i < list.size() - 1 ; i++) { + Point cur = list.get(i); + Point next = list.get(i + 1); + newList.add(cur); + List intermediate = optimizeLine(nodeWidgets, cur, next); + if (intermediate != null && intermediate.size() > 0) { + progress = true; + newList.addAll(intermediate);//insert new controlpoints between cur and next + } + } + newList.add(list.get(list.size()-1));//add endpoint of the polyline + list = newList; + + } + + if(list.size() > 2) { + Widget sourceNode = connWidget.getSourceAnchor().getRelatedWidget(); + Widget targetNode = connWidget.getTargetAnchor().getRelatedWidget(); + Rectangle sourceBounds = sourceNode.convertLocalToScene(sourceNode.getBounds()); + Rectangle targetBounds = targetNode.convertLocalToScene(targetNode.getBounds()); + sourceBounds.grow(HEXPAND, VEXPAND); + + /** + * add only points which are not intersecting the source and the target + * widget bounds caused by invalid bad anchor positions. The first + * and the last point is ignored cause the anchor is recalculated + * anyway. + */ + ArrayList tmp = new ArrayList(); + int listSize=list.size(); + tmp.add(list.get(0)); + int i=0; + while(++i < listSize-1) { + Point p = list.get(i); + if(!sourceBounds.contains(p) || !targetBounds.contains(p)) + tmp.add(p); + } + + tmp.add(list.get(i)); + if(tmp.size() < 3) + return tmp; + + list=tmp; + //calculate a proper anchor position using the second/penultimate controlpoint for start/end + start = this.computateAnchorPosition(connWidget.getSourceAnchor().getRelatedWidget(), list.get(1)); + end = this.computateAnchorPosition(connWidget.getTargetAnchor().getRelatedWidget(), list.get(list.size()-2)); + list.set(0,start); + list.set(list.size()-1, end); + } + return list; + } + + + /** + * trys to optimize a line from p1 to p2 to avoid collisions with node widgets + * returns null if the line doesn`t intersect with any nodewidget + * or a list with immediate points between p1 and p2 to avoid collisions + */ + private List optimizeLine(Collection nodeWidgets, Point p1, Point p2) { + Line2D line = new Line2D.Double(p1, p2); + + for(Widget w : nodeWidgets ) { + if( w.isVisible() ) { + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + + if (!line.intersects(r)) continue; + + Point location = w.getLocation(); + int distx = (int) (r.width * FACTOR); + int disty = (int) (r.height * FACTOR); + + int minIntersects = Integer.MAX_VALUE; + int min = Integer.MAX_VALUE; + List minSol = null; + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + if (i != 0 || j != 0) { + Point cur = new Point(location.x + i * distx, location.y + j * disty); + List list1 = new ArrayList(); + list1.add(p1); + list1.add(cur); + list1.add(p2); + int crossProd = Math.abs(crossProduct(p1, cur, p2)); + if (!intersects(w, list1)) { + Line2D line1 = new Line2D.Float(p1, cur); + Line2D line2 = new Line2D.Float(p2, cur); + int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2); + + if (curIntersects < minIntersects + || (curIntersects == minIntersects && crossProd < min)) { + minIntersects = curIntersects; + min = crossProd; + minSol = new ArrayList(); + minSol.add(cur); + } + } + + if (i == 0 || j == 0) { + Point cur1, cur2; + if (i == 0) { + cur1 = new Point(location.x + distx/2, location.y + j * disty); + cur2 = new Point(location.x - distx/2, location.y + j * disty); + } else { // (j == 0) + cur1 = new Point(location.x + i * distx, location.y + disty/2); + cur2 = new Point(location.x + i * distx, location.y - disty/2); + } + + Point vec1 = new Point(p1.x - cur1.x, p1.y - cur1.y); + int offset1 = vec1.x * vec1.x + vec1.y * vec1.y; + + Point vec2 = new Point(p1.x - cur2.x, p1.y - cur2.y); + int offset2 = vec2.x * vec2.x + vec2.y * vec2.y; + + if (offset2 < offset1) { + Point tmp = cur1; + cur1 = cur2; + cur2 = tmp; + } + + List list2 = new ArrayList(); + list2.add(p1); + list2.add(cur1); + list2.add(cur2); + list2.add(p2); + + int cross1 = crossProduct(p1, cur1, cur2); + int cross2 = crossProduct(cur1, cur2, p2); + + if (cross1 > 0) { + cross1 = 1; + } else if (cross1 < 0) { + cross1 = -1; + } + + if (cross2 > 0) { + cross2 = 1; + } else if (cross2 < 0) { + cross2 = -1; + } + if ((cross1 == cross2 || cross1 == 0 || cross2 == 0) && !intersects(w, list2)) { + Line2D line1 = new Line2D.Float(p1, cur1); + Line2D line2 = new Line2D.Float(cur1, cur2); + Line2D line3 = new Line2D.Float(p2, cur2); + int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2, line3); + + // This is a bit better + crossProd--; + + if (curIntersects < minIntersects + || (curIntersects == minIntersects && crossProd < min)) { + minIntersects = curIntersects; + min = crossProd; + minSol = new ArrayList(); + minSol.add(cur1); + minSol.add(cur2); + } + } + } + } + } + } + if (minSol != null) { + return minSol; + } + } + } + return null; + } + + + + private int countNodeIntersections(Collection nodeWidgets, Line2D... lines){ + int count=0; + for(Widget nw : nodeWidgets){ + if(nw.isVisible()) { + Rectangle bounds = nw.convertLocalToScene(nw.getBounds()); + for( Line2D line : lines){ + if(line.intersects(bounds)) + count++; + } + } + } + return count; + } + + + private boolean intersects(Collection nodeWidgets, Point start, Point end) { + List pointlist = new ArrayList(); + pointlist.add(start); + pointlist.add(end); + + for(Widget w : nodeWidgets){ + if(w.isVisible() && intersects(w, pointlist)) { + return true; + } + } + return false; + } + + + private boolean intersects(Widget w, List list) { + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + return intersects(list, r); + } + + + private boolean intersects(List list, Rectangle rect){ + for(int i=1; i < list.size(); i++) { + Point cur = list.get(i-1); + Point next = list.get(i); + if(rect.intersectsLine(cur.x, cur.y, next.x, next.y)) + return true; + } + return false; + } + + + private int crossProduct(Point p1, Point p2, Point p3) { + Point off1 = new Point(p1.x - p2.x, p1.y - p2.y); + Point off2 = new Point(p3.x - p2.x, p3.y - p2.y); + return (off1.x * off2.y - off1.y * off2.x); + } + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouterV2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouterV2.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,393 @@ +package at.ssw.visualizer.cfg.visual; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.netbeans.api.visual.anchor.Anchor; +import org.netbeans.api.visual.router.Router; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.Widget; + +/** + * Router Class with Collision Detection + * + * + * The returned path is a straight line there is no node widget between the source and the target node, + * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. + * The algorithm for the search of this path is limited by a fixed number of iterations defined in + * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the + * path returned contains at least 1 collision with a nodewidget. + * + * This class intend to solve the same problem as the class PolyLineRouter but + * uses slightly different methods. + * + uses another algorithm for solving the collision. + * + the obstacle bounds are calulated in advance to avoid a recalculation. + * - there is no heuristic, the shortest path around the widget is choosen asap. + * + * + * + */ + +public class PolylineRouterV2 implements Router { + private static final int HEXPAND = 3; + private static final int VEXPAND = 3; + private static final int NUMBER_OF_ITERATIONS = 8; + + WidgetCollisionCollector collector; + + + public PolylineRouterV2(WidgetCollisionCollector collector){ + this.collector=collector; + } + + + public List routeConnection(final ConnectionWidget widget) { + if(!widget.isVisible()) return Collections.emptyList(); + + Anchor sourceAnchor = widget.getSourceAnchor(); + Anchor targetAnchor = widget.getTargetAnchor(); + + if(sourceAnchor == null || targetAnchor == null) + return null; + + Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); + + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + + + if(sourceWidget == targetWidget){//reflexive edges doesnt need any path + return Collections.emptyList(); + } + + + Point srcCenter = this.getSceneLocation(sourceWidget); + Point tarCenter = this.getSceneLocation(targetWidget); + + List widgetObstacles = new ArrayList(); + + if(collector != null){ + collector.collectCollisions(widgetObstacles); + } + + List obstacles = new ArrayList(widgetObstacles.size()); + this.collectObstacles(obstacles, widgetObstacles, widget); + + + List controlPoints = optimize(obstacles, srcCenter, tarCenter); +// size==2 => straight line +// size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it + if(controlPoints.size() > 3){ + Point rstart = this.computateAnchorPosition(sourceWidget, controlPoints.get(1)); + Point rend = this.computateAnchorPosition(targetWidget, controlPoints.get(controlPoints.size()-2)); + controlPoints.set(0, rstart); + controlPoints.set(controlPoints.size()-1, rend); + controlPoints = simplify(obstacles, controlPoints); + } else if (controlPoints.size()>=2){ + //use old points + controlPoints.set(0, start); + controlPoints.set(controlPoints.size()-1, end); + + } + return controlPoints; + } + + + private int collectObstacles(List colrects, List colwidgets , ConnectionWidget cw){ + int count=0; + Anchor sourceAnchor = cw.getSourceAnchor(); + Anchor targetAnchor = cw.getTargetAnchor(); + Widget sourceWidget = sourceAnchor.getRelatedWidget(); + Widget targetWidget = targetAnchor.getRelatedWidget(); + Point start = sourceAnchor.compute(cw.getSourceAnchorEntry()).getAnchorSceneLocation(); + Point end = targetAnchor.compute(cw.getTargetAnchorEntry()).getAnchorSceneLocation(); + + for(Widget w : colwidgets){ + + if(w==sourceWidget || w == targetWidget) continue; + + Rectangle r = w.convertLocalToScene(w.getBounds()); + r.grow(HEXPAND, VEXPAND); + if(r.intersectsLine(start.x,start.y,end.x,end.y)) + count++; + colrects.add(r); + } + return count; + } + + + private Point center (Rectangle bounds) { + return new Point (bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); + } + + /** + * Returns the scene location of a related widget. + * bounds might be null if the widget was not added to the scene + * @return the scene location; null if no related widget is assigned + */ + public Point getSceneLocation (Widget relatedWidget) { + if (relatedWidget != null) { + Rectangle bounds = relatedWidget.getBounds (); + if(bounds != null) + return center(relatedWidget.convertLocalToScene(bounds)); + } + return null; + } + + /** + * Computates the Anchorposition like the Rectangular anchor for a + * given widget as source/target and a controlpoint as opposit anchorposition + */ + + private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { + Rectangle bounds = relatedWidget.getBounds(); + + //todo: fix, center of widget must be cacluated trough the bounds + //since there are some wheird widgets where the location is not the center of the widget + Point relatedLocation = relatedWidget.getLocation();//center of the widget + + if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) + return relatedLocation; + + float dx = controlPoint.x - relatedLocation.x; + float dy = controlPoint.y - relatedLocation.y; + + float ddx = Math.abs (dx) / (float) bounds.width; + float ddy = Math.abs (dy) / (float) bounds.height; + + float scale = 0.5f / Math.max (ddx, ddy); + + Point point = new Point (Math.round (relatedLocation.x + scale * dx), + Math.round (relatedLocation.y + scale * dy)); + return point; + } + + private List simplify(List obstacles, List list) { + List result = new ArrayList(list.size()); + result.add( list.get(0) );//add startpoint + for (int i = 1; i < list.size(); i++) { + Point prev = list.get(i - 1); + for (int j = i; j < list.size(); j++) { + Point cur = list.get(j); + if (!intersects(obstacles, prev, cur)) { + i = j; + } + } + result.add(list.get(i)); + } + return result; + } + + private List optimize(List nodeWidgets, Point start, Point end) { + + List list = new ArrayList(); + list.add(start); + list.add(end); + + boolean progress = true; + + for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { + progress = false; + List newList = new ArrayList(); + for (int i = 0; i < list.size() - 1 ; i++) { + Point cur = list.get(i); + Point next = list.get(i + 1); + newList.add(cur); + List intermediate = optimizeLine(nodeWidgets, cur, next); + if (intermediate != null && intermediate.size() > 0) { + progress = true; + newList.addAll(intermediate);//insert new controlpoints between cur and next + } + } + newList.add(list.get(list.size()-1));//add endpoint of the polyline + list = newList; + + } + + return list; + } + + + /** + * trys to optimize a line from p1 to p2 to avoid collisions with rectangles + * returns null if the line doesn`t intersect with any nodewidget or + * if the obstacles are overlapping + * ---------------------------------------------------------------------- + * if the collision is solved it returns a list with immediate points + * between p1 and p2. The points are taken from hull points of and grown + * rectangle. + */ + private List optimizeLine(List obstacles, Point p1, Point p2) { + Line2D line = new Line2D.Double(p1, p2); + boolean inbounds=false; + Rectangle ibr=null; + ArrayList sol = new ArrayList(); + boolean leftIntersection; + boolean rightIntersection; + boolean bottomIntersection; + boolean topIntersection; + Point interLeft=new Point(); + Point interRight=new Point(); + Point interBot=new Point(); + Point interTop=new Point(); + + + + for(Rectangle r : obstacles ) { + if (!line.intersects(r)) continue; + + int w=r.width+2; + int h=r.height+2; + Point topLeft = r.getLocation(); + topLeft.x-=1; + topLeft.y-=1; + Point topRight = new Point(topLeft.x+w, topLeft.y); + Point bottomLeft = new Point(topLeft.x, topLeft.y+h); + Point bottomRight = new Point(topRight.x, bottomLeft.y); + leftIntersection = findIntersectionPoint(p1, p2, topLeft, bottomLeft, interLeft); + rightIntersection = findIntersectionPoint(p1, p2, topRight, bottomRight, interRight); + bottomIntersection = findIntersectionPoint(p1, p2, bottomLeft, bottomRight, interBot); + topIntersection = findIntersectionPoint(p1, p2, topLeft, topRight, interTop); + + //Intersection points are not used yet. This could be actually a + //good approach to avoid additional collisions because it would be + //still the same vector. + + if(leftIntersection) { + if(topIntersection) {//left and top + sol.add(topLeft); + } + else if(bottomIntersection){//left and bottom + sol.add(bottomLeft); + } + else if(rightIntersection){//left and right + double disttl = topLeft.distance(p1); + double distbl = bottomLeft.distance(p1); + if(disttl > distbl){ + //pass at the bottom + double distbr = bottomRight.distance(p1); + if(distbl < distbr){ + //from the left to the right + sol.add(bottomLeft); + sol.add(bottomRight); + } else { + //from the right to the left + sol.add(bottomRight); + sol.add(bottomLeft); + } + } else { + //pass at the top + double disttr = topRight.distance(p1); + if(disttl < disttr){ + //from the left to the right + sol.add(topLeft); + sol.add(topRight); + } else { + //from the right to the left + sol.add(topRight); + sol.add(topLeft); + } + } + } else {//only left => inside bounds + inbounds=true; + } + } else if (rightIntersection) { + if(topIntersection) {//right and top + sol.add(topRight); + } + else if(bottomIntersection){//right and bottom + sol.add(bottomRight); + } else { //only right => inside the bounds + inbounds=true; + } + } else if (topIntersection && bottomIntersection) {//top and bottom + double disttop = interTop.distance(p1); + double distbot = interBot.distance(p1); + if(disttop < distbot ){ + //from the top to the bottom + double distleft = interTop.distance(topLeft); + double distright = interTop.distance(topRight); + if(distleft < distright){ + //pass left + sol.add(topLeft); + sol.add(bottomLeft); + } else { + //pass right + sol.add(topRight); + sol.add(bottomRight); + } + } else { + //from the bottom to the top + double distleft = interBot.distance(bottomLeft); + double distright = interBot.distance(bottomRight); + if(distleft < distright){ + //pass left + sol.add(bottomLeft); + sol.add(topLeft); + } else { + //pass right + sol.add(bottomRight); + sol.add(topRight); + } + } + } else {//only bottom or only top + inbounds=true; + } /* ENDIF */ + + //breakpoint <-- collision detected + + if(sol.size()>0) {//solution found + assert(!inbounds); + return sol; + } else { //no solution found=> inbounds + assert(inbounds); + assert(sol.size()==0); + //handle collision or just skip it and search for the next collisionj + ibr=r; + //jump out of the loop to able to interate over the obstacles + break; + } + }/* end foreach obstacle */ + + if(inbounds || ibr != null){ + assert(inbounds); + assert(ibr!=null); + } + return null;//no collison found + }/* end optimizeLine */ + + + + //check intersection between line p0->p1 for a given set of obstacles + private static boolean intersects(List obstacles, Point p0, Point p1) { + for(Rectangle r : obstacles){ + if(r.intersectsLine(p0.x, p0.y, p1.x, p1.y)) + return true; + } + return false; + } + + + private boolean findIntersectionPoint( + Point p0, Point p1, Point p2, Point p3, Point pI) { + float q = (p0.y - p2.y)*(p3.x - p2.x) - (p0.x - p2.x)*(p3.y - p2.y); + float d = (p1.x - p0.x)*(p3.y - p2.y) - (p1.y - p0.y)*(p3.x - p2.x); + + //parallel ? + if(d==0) return false; + + float r = q / d; + q = (p0.y - p2.y)*(p1.x - p0.x) - (p0.x - p2.x)*(p1.y - p0.y); + + float s = q / d; + if(r<0 || r>1 || s<0 || s>1) return false; + + pI.x = p0.x + (int) (0.5f + r * (p1.x - p0.x)); + pI.y = p0.y + (int) (0.5f + r * (p1.y - p0.y)); + return true; + } +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/SplineConnectionWidget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/SplineConnectionWidget.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,541 @@ +package at.ssw.visualizer.cfg.visual; + +import org.netbeans.api.visual.widget.ConnectionWidget; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.List; +import org.netbeans.api.visual.anchor.AnchorShape; +import org.netbeans.api.visual.graph.GraphScene; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.Widget; + + +/** + * In comparison to the default ConnectionWidget this class is able to connect + * widgets with a curve instead of a straight line sequence. + * In conjunction with a suitable router the connection will be a straight line + * or a curve depending on the amount and the position of the controlpoints. + * Controlpoints supplied by the router, are treated as curve intersection points. + * For Reflexive edges the router doesn`t necessarily need to supply + * any controlpoints, they get painted by this automatically, this can be + * excepted if the router supplys more as 2 control points for a self edge, + * then the edge gets painted with the default curve interpolation algorithm. + * The method used for drawing curves uses a piecewise cubic interpolation + * algorithm. Between two control points a curve is painted as cubic bezier + * curve the, inner bezier points are calculated automatically with FMILL + * tangents and a chord parametrization, this interpolant is also known as + * cutmull-rom spline. The resulting spline fullfills c^1 continuity. + * The the end points the interpolation algorithm uses the bessel end condition. + */ + +public class SplineConnectionWidget extends ConnectionWidget { + private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy + private static final double HIT_DISTANCE_SQUARE = 4.0;//distance for intersection test + private GraphScene scene=null; + private Point2D [] bezierPoints = null; + + public SplineConnectionWidget(Scene scene) { + super(scene); + if(scene instanceof GraphScene) + this.scene=(GraphScene) scene; + } + + //check for self - edge + private boolean isReflexive(){ + return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); + } + + + @Override + protected Rectangle calculateClientArea() { + + Rectangle bounds = null; + + if(this.getControlPoints().size()>2){ + bezierPoints = createBezierPoints(getControlPoints()); + } + //minmax method - returns the smallest bounding rectangle + //Curves and surfaces for CAGD (3rd ed.), p.54 + //exact calculation of the bounding min rect + if(bezierPoints != null) { + Rectangle2D bounds2D = null; + for (int i = 0; i < bezierPoints.length; i++) { + Point2D point = bezierPoints[i]; + if(bounds2D==null) + bounds2D = new Rectangle2D.Double(point.getX(),point.getY(),0,0); + else + bounds2D.add(point); + } + bounds = bounds2D.getBounds(); + bounds.grow(2, 2); + + } else if (getControlPoints().size()>0){ + for(Point p : this.getControlPoints()){ + if(bounds==null) + bounds = new Rectangle(p); + else + bounds.add(p); + } + bounds.grow(5,5); + + } else if (isReflexive()) { + Widget related = this.getTargetAnchor().getRelatedWidget(); + bounds = related.convertLocalToScene(related.getBounds()); + bounds.grow(10, 10); + } + + if(bounds==null) + bounds = super.calculateClientArea(); + + return bounds; + } + + + /** + * if the edge is reflexive its painted as a cyclic self edge, if there + * are two controlpoints the connection is painted as a straight line from + * the source to the targetanchor, if there are more as 2 controlpoints the + * connection path between two control points is painted as cutmull rom + * spline with bessel end tangents. + */ + @Override + protected void paintWidget () { + List contrPoints = this.getControlPoints(); + int listSize = contrPoints.size(); + + Graphics2D gr = getGraphics (); + + if (listSize <= 2) { + this.bezierPoints=null;//set bezier Points null for calulateClientArea() + if(isReflexive()) { //special case for reflexive connection widgets + this.drawReflexive(gr); + } else { + super.paintWidget(); + } + return; + } + + //bezier curve... listSize > 2 + GeneralPath curvePath = new GeneralPath(); + double lastControlPointRotation = 0.0; + + + Point2D [] bezPoints = this.createBezierPoints(contrPoints); + curvePath.moveTo(bezPoints[0].getX(), bezPoints[0].getY());//b00 + + //last segment is added by subdivision thats why its -5 + for (int i = 1; i < bezPoints.length-5; i+=3) { + curvePath.curveTo( + bezPoints[i].getX(), bezPoints[i].getY(),//b1i + bezPoints[i+1].getX(), bezPoints[i+1].getY(),//b2i + bezPoints[i+2].getX(), bezPoints[i+2].getY());//b3i + + } + + GeneralPath lastseg = subdivide2D( + bezPoints[bezPoints.length-4], + bezPoints[bezPoints.length-3], + bezPoints[bezPoints.length-2], + bezPoints[bezPoints.length-1]); + + + if(lastseg != null) + curvePath.append(lastseg, true); + + Point2D cur = curvePath.getCurrentPoint(); + Point lastControlPoint = contrPoints.get(listSize-1); + + lastControlPointRotation = //anchor anchorAngle + Math.atan2 (cur.getY() - lastControlPoint.y, cur.getX() - lastControlPoint.x); + + gr.setStroke(getStroke()); + gr.setColor(getLineColor()); + gr.draw(curvePath); + + + AffineTransform previousTransform = gr.getTransform (); + gr.translate (lastControlPoint.x, lastControlPoint.y); + gr.rotate (lastControlPointRotation); + AnchorShape targetAnchorShape = this.getTargetAnchorShape(); + targetAnchorShape.paint (gr, false); + gr.setTransform (previousTransform); + + //paint ControlPoints if enabled + if (isPaintControlPoints()) { + int last = listSize - 1; + for (int index = 0; index <= last; index ++) { + Point point = contrPoints.get (index); + previousTransform = gr.getTransform (); + gr.translate (point.x, point.y); + if (index == 0 || index == last) + getEndPointShape().paint (gr); + else + getControlPointShape().paint (gr); + gr.setTransform (previousTransform); + } + + } + } + + private void drawReflexive(Graphics2D gr){ + Widget related = this.getTargetAnchor().getRelatedWidget(); + int position = this.edgeBalance(related); + Rectangle bounds = related.convertLocalToScene(related.getBounds()); + gr.setColor (getLineColor()); + Point first = new Point(); + Point last = new Point(); + double centerX = bounds.getCenterX(); + first.x = (int) (centerX + bounds.width / 4); + first.y = bounds.y + bounds.height; + last.x = first.x; + last.y = bounds.y; + + gr.setStroke(this.getStroke()); + + double cutDistance = this.getTargetAnchorShape().getCutDistance(); + double anchorAngle = Math.PI/-3.0; + double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); + double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); + int ydiff=first.y-last.y; + int endy = -ydiff; + double height=bounds.getHeight(); + double cy = height/4.0; + double cx=bounds.getWidth()/5.0; + double dcx = cx*2; + GeneralPath gp = new GeneralPath(); + gp.moveTo(0, 0); + gp.quadTo(0, cy, cx, cy); + gp.quadTo(dcx, cy, dcx, -height/2.0); + gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); + gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); + + AffineTransform af = new AffineTransform(); + AnchorShape anchorShape = this.getTargetAnchorShape(); + + if(position < 0) { + first.x = (int) (centerX - bounds.width / 4); + af.translate(first.x, first.y); + af.scale(-1.0, 1.0); + last.x = first.x; + } else { + af.translate(first.x, first.y); + } + Shape s = gp.createTransformedShape(af); + gr.draw(s); + + if (last != null) { + AffineTransform previousTransform = gr.getTransform (); + gr.translate (last.x, last.y); + + if(position < 0) + gr.rotate(Math.PI - anchorAngle); + else + gr.rotate (anchorAngle); + + anchorShape.paint (gr, false); + gr.setTransform (previousTransform); + } + } + + //returns prefered location for an edge -1 for left and 1 for right + private int edgeBalance(Widget nodeWidget) { + if(scene == null) + return 1; + + Point nodeLocation = nodeWidget.getLocation(); + int left = 0, right = 0; + + Object node = scene.findObject(nodeWidget); + + for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges + ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); + + if(cw != this) { + Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); + + Point location; + if(targetNodeWidget == nodeWidget) { + Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); + location = sourceNodeWidget.getLocation(); + } else { + location = targetNodeWidget.getLocation(); + } + + if(location.x < nodeLocation.x) + left++; + else + right++; + } + } + if(left < right) + return -1; + else + return 1; + } + + + private Point2D[] createBezierPoints(List list){ + if(list.size()<3) return null ; + + + int lastIdx = list.size()-1; + + + //chord length parametrization + double[] uis = new double[list.size()]; + uis[0]=0; + uis[1] = list.get(1).distance(list.get(0)); + for (int i = 1; i < uis.length; i++) { + Point cur = list.get(i); + Point prev = list.get(i-1); + uis[i]=uis[i-1]+ cur.distance(prev); + } + + + for (int i = 1; i < uis.length; i++) { + uis[i] /= uis[lastIdx]; + + } + double[] delta = new double[uis.length-1]; + for (int i = 0; i < delta.length; i++) { + double ui = uis[i]; + double uin = uis[i+1]; + delta[i] = uin-ui; + } + + + //FMILL tangent directions (chord length) + Point2D[] tangents = new Point2D[list.size()]; + + for (int i = 1; i < list.size()-1; i++) { + Point xBefore = list.get(i-1); + Point xAfter = list.get(i+1); + Point2D.Double tangent = new Point2D.Double (xAfter.x - xBefore.x, xAfter.y - xBefore.y); + tangents[i] = tangent; + } + + + Point2D [] bezPoints = new Point2D[(list.size()-1)*2+list.size()]; + //Catmull-Rom + for (int i = 1; i < list.size()-1; i++) { + Point b3i = list.get(i); + Point2D b3ib = b3iBefore(b3i, delta[i-1], delta[i], tangents[i]); + Point2D b3ia = b3iAfter(b3i, delta[i-1], delta[i], tangents[i]); + bezPoints[3*i] = b3i; + bezPoints[3*i-1] = b3ib; + bezPoints[3*i+1] = b3ia; + } + bezPoints[0] = list.get(0); + bezPoints[bezPoints.length-1] = list.get(list.size()-1); + + Point p0 = list.get(0); + Point p1 = list.get(1); + Point p2 = list.get(2); + Point pL_2 = list.get(lastIdx-2); + Point pL_1 = list.get(lastIdx-1); + Point pL = list.get(lastIdx); + + Point2D m1 = besselTangent(delta[0], delta[1], p0, p1, p2); + Point2D m0 = besselEndTangent(p0, p1, delta[0], m1); + + Point2D mLb = besselTangent(delta[delta.length-2], delta[delta.length-1], + pL_2,pL_1, pL); + Point2D mL = besselEndTangent(pL_1, pL, delta[delta.length-1], mLb); + + Point2D scaleM0 = scale(normalize(m0), p0.distance(p1));//increase distx/distxl to make curve rounder at the end + Point2D scaleML = scale(normalize(mL), pL.distance(pL_1)); + //Catmull-Rom for bessel points + Point2D b30a = b3iAfter(p0, delta[0], delta[0],scaleM0); + Point2D b33b = b3iBefore(pL, delta[delta.length-1], delta[delta.length-1],scaleML); + + bezPoints[1] = b30a; + bezPoints[bezPoints.length-2] = b33b; + + return bezPoints; + } + + + + private static Point2D besselTangent(double delta_ib, double delta_i, Point2D p0, Point2D p1 , Point2D p2){ + double alpha_i = delta_ib/(delta_ib+delta_i); + + double x = (1-alpha_i)/delta_ib * (p1.getX() - p0.getX()) + + alpha_i/delta_i * (p2.getX()-p1.getX()); + double y = (1-alpha_i)/delta_ib * (p1.getY() - p0.getY()) + + alpha_i/delta_i * (p2.getY()-p1.getY()); + + return new Point2D.Double(x,y); + } + + private static Point2D besselEndTangent(Point2D p0, Point2D p1, double delta_u, Point2D m){ + double x = 2*((p1.getX()-p0.getX())/delta_u) - m.getX(); + double y = 2*((p1.getY()-p0.getY())/delta_u) - m.getY(); + return new Point2D.Double(x,y); + } + + private static Point2D b3iBefore(Point2D b3i, double delta_ib, double delta_i, Point2D li){ + double x = b3i.getX() - (delta_ib/(3*(delta_ib+delta_i)))*li.getX(); + double y = b3i.getY() - (delta_ib/(3*(delta_ib+delta_i)))*li.getY(); + return new Point.Double(x,y); + } + + private static Point2D b3iAfter(Point2D b3i, double delta_ib,double delta_i,Point2D li){ + double x = b3i.getX() + (delta_i/(3*(delta_ib+delta_i)))*li.getX(); + double y = b3i.getY() + (delta_i/(3*(delta_ib+delta_i)))*li.getY(); + return new Point.Double(x,y); + } + + + + + //returns length of vector v + private static double norm(Point2D v){ + return Math.sqrt(v.getX()*v.getX()+v.getY()*v.getY()); + } + + //returns unity vector of vector v + private static Point2D normalize(Point2D v){ + double norm = norm(v); + if(norm==0) return new Point2D.Double(v.getX(), v.getY()); + return new Point2D.Double(v.getX()/norm , v.getY()/norm); + } + + //scale vector to size of length + private static Point2D scale(Point2D v, double length){ + Point2D tmp = normalize(v); + return new Point2D.Double(tmp.getX()*length, tmp.getY()*length); + } + + + + private GeneralPath subdivide2D (Point2D b0, Point2D b1, Point2D b2, Point2D b3) { + //set 2nd intermediate point to endpoint + //we could actually use another "better" point if we like to have a smoother curve + + double cutDistance = getTargetAnchorShape().getCutDistance(); + double minDistance = cutDistance - ENDPOINT_DEVIATION; + /** + * if the cutDistance is valid the last segment of the curve + * gets reduced by subdivision until the distance of the endpoint(epDistance) + * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) + */ + if(cutDistance > minDistance && minDistance > 0 ) { + GeneralPath path = new GeneralPath(); + + path.moveTo(b0.getX(), b0.getY()); + + CubicCurve2D.Double curve = new CubicCurve2D.Double( + b0.getX(), b0.getY(), + b1.getX(), b1.getY(), + b2.getX(), b2.getY(), + b3.getX(), b3.getY()); + + + + CubicCurve2D right=new CubicCurve2D.Double(); + CubicCurve2D left=new CubicCurve2D.Double(); + curve.subdivide(left, right); + double distance = b3.distance(left.getP2()); + //if the distance is bigger as the cutDistance the left segment is added + //and the right segment is divided again + while(distance>cutDistance){ + path.append(left, true); + right.subdivide(left, right); + distance = b3.distance(left.getP2()); + //if the devision removed to much the left segment is divided + while(distance < minDistance) { + //changes the distance to ~ (distance+distance/2) + left.subdivide(left, right); + distance = b3.distance(left.getP2()); + } + } + //append the last segment with (minDistance < distance < cutDistance) + path.append(left, true); + return path; + } + return null; + } + + + /** + * Returns whether a specified local point pL is a part of the connection + * widget. + * First it make a rough bounds check + * for Line Segments => use Super call (ConnectionWidget.isHitAt(pL)). + * for self-edges => its sufficent to return getBounds.contains(pL). + * for Splines => Interate over all Partitial segments of the curve and make + * a minmax check with the bezier points. If pL is inside the minmax + * rectangle of one segment the curve is constructed and subdivided until + * the distance d between center point pC (of the bounding rectangle) + * and pL is below HIT_DISTANCE_SQUARE, in this case it returns true. + * If no no minmax check was successful or the subdivision lead to an + * rectangle witch doesn`t contain pL return false. + * @param localLocation the local location + * @return true, if the location is a part of the connection widget + */ + @Override + public boolean isHitAt(Point localLocation) { + if(!isVisible() || !getBounds ().contains (localLocation)) + return false; + + List controlPoints = getControlPoints (); + if(controlPoints.size() <=2){ + if(isReflexive()) return true; + return super.isHitAt(localLocation); + } + + if(bezierPoints != null) { + for (int i = 0; i < bezierPoints.length-1; i+=3) { + Point2D b0 = bezierPoints[i]; + Point2D b1 = bezierPoints[i+1]; + Point2D b2 = bezierPoints[i+2]; + Point2D b3 = bezierPoints[i+3]; + + CubicCurve2D left = new CubicCurve2D.Double( + b0.getX(), b0.getY(), + b1.getX(), b1.getY(), + b2.getX(), b2.getY(), + b3.getX(), b3.getY()); + + + Rectangle2D bounds = left.getBounds2D(); + while(bounds.contains(localLocation)) { + //calculate the center and use HIT_DISTANCE_SQUARE for a range check + Point2D test = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY()); + if(test.distance(localLocation) < HIT_DISTANCE_SQUARE){ + return true; + } + + + CubicCurve2D right = new CubicCurve2D.Double(); + left.subdivide(left, right); + Rectangle2D lb2d = left.getBounds2D(); + Rectangle2D rb2d = right.getBounds2D(); + if( lb2d.contains(localLocation)){ + bounds = lb2d; + } else if (rb2d.contains(localLocation)) { + left = right; + bounds = rb2d; + } else { + return false; + } + + }//end while + }//end for + } + return false; + } + + +} + + + + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/WidgetCollisionCollector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/WidgetCollisionCollector.java Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,12 @@ +package at.ssw.visualizer.cfg.visual; + +import java.util.List; +import org.netbeans.api.visual.widget.Widget; + + +public interface WidgetCollisionCollector { + + //returns a list of widgets which should be handled as obstacles + void collectCollisions(List collisions); + +} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 82 +/svn/c1visualizer~svn/!svn/ver/186/trunk/C1Visualizer/Control%20Flow%20Editor/test +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/test +https://svn.java.net/svn/c1visualizer~svn + + + +2010-07-16T01:08:34.138866Z +186 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +unit +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/c1visualizer~svn/!svn/ver/186/trunk/C1Visualizer/Control%20Flow%20Editor/test/unit +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/test/unit +https://svn.java.net/svn/c1visualizer~svn + + + +2010-07-16T01:08:34.138866Z +186 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +src +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/src/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/src/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/c1visualizer~svn/!svn/ver/186/trunk/C1Visualizer/Control%20Flow%20Editor/test/unit/src +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/src/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/ControlFlowEditor/test/unit/src/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,28 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Control%20Flow%20Editor/test/unit/src +https://svn.java.net/svn/c1visualizer~svn + + + +2010-07-16T01:08:34.138866Z +186 +ChristianW + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml --- a/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Coordinator/nbproject/project.xml Tue Jan 31 00:23:10 2012 +0100 @@ -7,6 +7,14 @@ + at.ssw.visualizer.cfg + + + + 1.0 + + + com.sun.hotspot.igv.connection diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java --- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/actions/GraphOpenCookie.java Tue Jan 31 00:23:10 2012 +0100 @@ -23,6 +23,7 @@ */ package com.sun.hotspot.igv.coordinator.actions; +import at.ssw.visualizer.cfg.editor.CfgEditorSupport; import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.services.GraphViewer; import org.openide.cookies.OpenCookie; @@ -39,6 +40,9 @@ @Override public void open() { + CfgEditorSupport support = new CfgEditorSupport(graph); + support.open(); + viewer.view(graph); } } diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/manifest.mf --- a/src/share/tools/IdealGraphVisualizer/Data/manifest.mf Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/manifest.mf Tue Jan 31 00:23:10 2012 +0100 @@ -1,5 +1,5 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.data -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - +Manifest-Version: 1.0 +OpenIDE-Module: com.sun.hotspot.igv.data +OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml --- a/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/nbproject/project.xml Tue Jan 31 00:23:10 2012 +0100 @@ -1,29 +1,33 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.data - - - - - unit - - org.netbeans.libs.junit4 - - - - org.openide.util - - - - - - com.sun.hotspot.igv.data - com.sun.hotspot.igv.data.serialization - com.sun.hotspot.igv.data.services - - - - + + + org.netbeans.modules.apisupport.project + + + com.sun.hotspot.igv.data + + + + + unit + + org.netbeans.libs.junit4 + + + + org.openide.util + + + + + + at.ssw.visualizer.model.bc + at.ssw.visualizer.model.cfg + at.ssw.visualizer.model.interval + at.ssw.visualizer.model.nc + com.sun.hotspot.igv.data + com.sun.hotspot.igv.data.serialization + com.sun.hotspot.igv.data.services + + + + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/model/cfg/BasicBlock.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/model/cfg/BasicBlock.java Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/model/cfg/BasicBlock.java Tue Jan 31 00:23:10 2012 +0100 @@ -7,19 +7,17 @@ * @author Christian Wimmer */ public interface BasicBlock { - public ControlFlowGraph getParent(); - public String getName(); public int getFromBci(); public int getToBci(); - public List getPredecessors(); + public List getPredecessors(); - public List getSuccessors(); + public List getSuccessors(); - public List getXhandlers(); + public List getXhandlers(); public List getFlags(); @@ -29,10 +27,6 @@ public int getLoopDepth(); - public int getFirstLirId(); - - public int getLastLirId(); - public boolean hasState(); public List getStates(); diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/BasicBlockImpl.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/BasicBlockImpl.java Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/BasicBlockImpl.java Tue Jan 31 00:23:10 2012 +0100 @@ -56,7 +56,7 @@ return parent; } - protected void setParent(ControlFlowGraphImpl parent) { + protected void setParent(ControlFlowGraph parent) { this.parent = parent; } diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/ControlFlowGraphImpl.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/ControlFlowGraphImpl.java Mon Jan 30 23:11:38 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -package at.ssw.visualizer.modelimpl.cfg; - -import at.ssw.visualizer.model.bc.Bytecodes; -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import at.ssw.visualizer.model.nc.NativeMethod; -import com.sun.hotspot.igv.data.AbstractFolderElement; -import com.sun.hotspot.igv.data.FolderElement; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * - * @author Christian Wimmer - */ -public class ControlFlowGraphImpl extends AbstractFolderElement implements ControlFlowGraph { - private BasicBlock[] basicBlocks; - private Map blockNames; - private Bytecodes bytecodes; - private NativeMethod nativeMethod; - private boolean hasState; - private boolean hasHir; - private boolean hasLir; - - public ControlFlowGraphImpl(String shortName, String name, BasicBlockImpl[] basicBlocks) { - super(shortName, name); - this.basicBlocks = basicBlocks; - - blockNames = new HashMap(basicBlocks.length); - nativeMethod = null; - for (BasicBlockImpl block : basicBlocks) { - block.setParent(this); - blockNames.put(block.getName(), block); - hasState |= block.hasState(); - hasHir |= block.hasHir(); - hasLir |= block.hasLir(); - } - } - - public List getBasicBlocks() { - return Collections.unmodifiableList(Arrays.asList(basicBlocks)); - } - - public BasicBlock getBasicBlockByName(String name) { - return blockNames.get(name); - } - - public Bytecodes getBytecodes() { - return bytecodes; - } - - public void setBytecodes(Bytecodes bytecodes) { - this.bytecodes = bytecodes; - } - - public NativeMethod getNativeMethod() { - return nativeMethod; - } - - public void setNativeMethod(NativeMethod nativeMethod) { - this.nativeMethod = nativeMethod; - } - - public boolean hasState() { - return hasState; - } - - public boolean hasHir() { - return hasHir; - } - - public boolean hasLir() { - return hasLir; - } - - @Override - public String toString() { - return " CFG \"" + getName() + "\": " + basicBlocks.length + " blocks\n"; - } -} diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalListImpl.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalListImpl.java Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalListImpl.java Tue Jan 31 00:23:10 2012 +0100 @@ -27,9 +27,10 @@ interval.setParent(this); numLIROperations = Math.max(numLIROperations, interval.getTo()); } - for (BasicBlock basicBlock : controlFlowGraph.getBasicBlocks()) { - numLIROperations = Math.max(numLIROperations, basicBlock.getLastLirId() + 2); - } +// for (BasicBlock basicBlock : controlFlowGraph.getBasicBlocks()) { +// numLIROperations = Math.max(numLIROperations, basicBlock.getLastLirId() + 2); +// } + // TODO(tw): Add number of LIR operations to output. } diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Bundle.properties --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Bundle.properties Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/Bundle.properties Tue Jan 31 00:23:10 2012 +0100 @@ -1,1 +1,1 @@ -OpenIDE-Module-Name=Data +OpenIDE-Module-Name=Data diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Tue Jan 31 00:23:10 2012 +0100 @@ -23,18 +23,23 @@ */ package com.sun.hotspot.igv.data; +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.model.cfg.IRInstruction; +import at.ssw.visualizer.model.cfg.State; import java.util.*; /** * * @author Thomas Wuerthinger */ -public class InputBlock { +public class InputBlock implements BasicBlock { private List nodes; private String name; private InputGraph graph; - private Set successors; + private List successors; + private List predecessors; @Override public int hashCode() { @@ -76,7 +81,8 @@ this.graph = graph; this.name = name; nodes = new ArrayList<>(); - successors = new LinkedHashSet<>(2); + successors = new ArrayList<>(); + predecessors = new ArrayList<>(); } public String getName() { @@ -97,8 +103,9 @@ nodes.add(node); } - public Set getSuccessors() { - return Collections.unmodifiableSet(successors); + @Override + public List getSuccessors() { + return Collections.unmodifiableList(successors); } @Override @@ -109,6 +116,90 @@ void addSuccessor(InputBlock b) { if (!successors.contains(b)) { successors.add(b); + b.predecessors.add(this); } } + + @Override + public int getFromBci() { + // TODO(tw): Implement. + return -1; + } + + @Override + public int getToBci() { + // TODO(tw): Implement. + return -1; + } + + @Override + public List getPredecessors() { + return Collections.unmodifiableList(predecessors); + } + + @Override + public List getXhandlers() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public List getFlags() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public BasicBlock getDominator() { + // TODO(tw): Implement. + return null; + } + + @Override + public int getLoopIndex() { + // TODO(tw): Implement. + return -1; + } + + @Override + public int getLoopDepth() { + // TODO(tw): Implement. + return -1; + } + + @Override + public boolean hasState() { + // TODO(tw): Implement. + return false; + } + + @Override + public List getStates() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public boolean hasHir() { + // TODO(tw): Implement. + return false; + } + + @Override + public List getHirInstructions() { + // TODO(tw): Implement. + return Collections.emptyList(); + } + + @Override + public boolean hasLir() { + // TODO(tw): Implement. + return false; + } + + @Override + public List getLirOperations() { + // TODO(tw): Implement. + return Collections.emptyList(); + } } diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Tue Jan 31 00:23:10 2012 +0100 @@ -23,13 +23,17 @@ */ package com.sun.hotspot.igv.data; +import at.ssw.visualizer.model.bc.Bytecodes; +import at.ssw.visualizer.model.cfg.BasicBlock; +import at.ssw.visualizer.model.cfg.ControlFlowGraph; +import at.ssw.visualizer.model.nc.NativeMethod; import java.util.*; /** * * @author Thomas Wuerthinger */ -public class InputGraph extends Properties.Entity implements FolderElement { +public class InputGraph extends Properties.Entity implements FolderElement, ControlFlowGraph { private Map nodes; private Set edges; @@ -293,4 +297,44 @@ public Folder getParent() { return parent; } + + @Override + public List getBasicBlocks() { + return new ArrayList(blocks.values()); + } + + @Override + public BasicBlock getBasicBlockByName(String name) { + return blocks.get(name); + } + + @Override + public Bytecodes getBytecodes() { + // TODO(tw): no bytecodes + return null; + } + + @Override + public NativeMethod getNativeMethod() { + // TODO(tw): No native method. + return null; + } + + @Override + public boolean hasState() { + // TODO(tw): implement + return false; + } + + @Override + public boolean hasHir() { + // TODO(tw): Implement + return false; + } + + @Override + public boolean hasLir() { + // TODO(tw): Implement + return false; + } } diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 70 +/svn/c1visualizer~svn/!svn/ver/186/trunk/C1Visualizer/Draw2D%20Library +END +manifest.mf +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/manifest.mf +END +build.xml +K 25 +svn:wc:ra_dav:version-url +V 80 +/svn/c1visualizer~svn/!svn/ver/186/trunk/C1Visualizer/Draw2D%20Library/build.xml +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/dir-prop-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/dir-prop-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 6 +build + +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,105 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library +https://svn.java.net/svn/c1visualizer~svn + + + +2010-07-16T01:08:34.138866Z +186 +ChristianW +has-props + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +release +dir + +nbproject +dir + +src +dir + +manifest.mf +file + + + + +2012-01-28T15:08:52.956036Z +4f68a2128d841c12ec7cb72975f0303f +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + + + + + + + + +176 + +build.xml +file + + + + +2012-01-28T15:08:52.959036Z +a0539bfa153a4f107a575e843b917cc3 +2010-07-16T01:08:34.138866Z +186 +ChristianW + + + + + + + + + + + + + + + + + + + + + +491 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/text-base/manifest.mf.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/.svn/text-base/manifest.mf.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: org.eclipse.draw2d +OpenIDE-Module-Localizing-Bundle: org/eclipse/draw2d/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/manifest.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/manifest.mf Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +OpenIDE-Module: org.eclipse.draw2d +OpenIDE-Module-Localizing-Bundle: org/eclipse/draw2d/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/release +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library/release +https://svn.java.net/svn/c1visualizer~svn + + + +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +modules +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/release/modules +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library/release/modules +https://svn.java.net/svn/c1visualizer~svn + + + +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +ext +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/release/modules/ext +END +org.eclipse.draw2d_3.1.0.jar +K 25 +svn:wc:ra_dav:version-url +V 117 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/release/modules/ext/org.eclipse.draw2d_3.1.0.jar +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,62 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library/release/modules/ext +https://svn.java.net/svn/c1visualizer~svn + + + +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +org.eclipse.draw2d_3.1.0.jar +file + + + + +2012-01-28T15:08:52.668019Z +a19cb9b45001cac5c359a7ee57820ddc +2007-07-07T21:02:50.702037Z +7 +christianw +has-props + + + + + + + + + + + + + + + + + + + + +463357 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/prop-base/org.eclipse.draw2d_3.1.0.jar.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/prop-base/org.eclipse.draw2d_3.1.0.jar.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/text-base/org.eclipse.draw2d_3.1.0.jar.svn-base Binary file src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/.svn/text-base/org.eclipse.draw2d_3.1.0.jar.svn-base has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/org.eclipse.draw2d_3.1.0.jar Binary file src/share/tools/IdealGraphVisualizer/Draw2DLibrary/release/modules/ext/org.eclipse.draw2d_3.1.0.jar has changed diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 72 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/src +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library/src +https://svn.java.net/svn/c1visualizer~svn + + + +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +org +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/src/org +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library/src/org +https://svn.java.net/svn/c1visualizer~svn + + + +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +eclipse +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 84 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/src/org/eclipse +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,31 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library/src/org/eclipse +https://svn.java.net/svn/c1visualizer~svn + + + +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +draw2d +dir + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/.svn/all-wcprops --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/.svn/all-wcprops Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/src/org/eclipse/draw2d +END +Bundle.properties +K 25 +svn:wc:ra_dav:version-url +V 109 +/svn/c1visualizer~svn/!svn/ver/7/trunk/C1Visualizer/Draw2D%20Library/src/org/eclipse/draw2d/Bundle.properties +END diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/.svn/entries --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/.svn/entries Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,62 @@ +10 + +dir +206 +https://svn.java.net/svn/c1visualizer~svn/trunk/C1Visualizer/Draw2D%20Library/src/org/eclipse/draw2d +https://svn.java.net/svn/c1visualizer~svn + + + +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + +f598ca33-f47e-61e0-e023-f120d32a8e8d + +Bundle.properties +file + + + + +2012-01-28T15:08:52.903033Z +a5b70895e3d9c9fa18e1d39c4bbb32e2 +2007-07-07T21:02:50.702037Z +7 +christianw + + + + + + + + + + + + + + + + + + + + + +36 + diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/.svn/text-base/Bundle.properties.svn-base --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/.svn/text-base/Bundle.properties.svn-base Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Draw2D Library diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Draw2DLibrary/src/org/eclipse/draw2d/Bundle.properties Tue Jan 31 00:23:10 2012 +0100 @@ -0,0 +1,1 @@ +OpenIDE-Module-Name=Draw2D Library diff -r f3cc08cb211d -r aae5b3773e63 src/share/tools/IdealGraphVisualizer/nbproject/project.properties --- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Mon Jan 30 23:11:38 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Tue Jan 31 00:23:10 2012 +0100 @@ -19,7 +19,10 @@ ${project.com.sun.hotspot.igv.servercompilerscheduler}:\ ${project.com.sun.hotspot.igv.filterwindow}:\ ${project.com.sun.hotspot.igv.selectioncoordinator}:\ - ${project.com.sun.hotspot.igv.graal} + ${project.com.sun.hotspot.igv.graal}:\ + ${project.at.ssw.visualizer.cfg}:\ + ${project.org.eclipse.draw2d} +project.at.ssw.visualizer.cfg=ControlFlowEditor project.com.sun.hotspot.connection=NetworkConnection project.com.sun.hotspot.igv.bytecodes=Bytecodes project.com.sun.hotspot.igv.coordinator=Coordinator @@ -38,6 +41,7 @@ project.com.sun.hotspot.igv.view=View project.com.sun.hotspot.igv.util=Util +project.org.eclipse.draw2d=Draw2DLibrary # Disable assertions for RequestProcessor to prevent annoying messages in case # of multiple SceneAnimator update tasks in the default RequestProcessor. run.args.extra = -J-client -J-da:org.openide.util.RequestProcessor