OSDN Git Service

merge revision 116: mds mapping enabled
authortama3 <tama3@acee48c3-7b26-0410-bdac-b3d0e5314bbc>
Tue, 22 May 2007 08:56:53 +0000 (08:56 +0000)
committertama3 <tama3@acee48c3-7b26-0410-bdac-b3d0e5314bbc>
Tue, 22 May 2007 08:56:53 +0000 (08:56 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/stigmata/trunk@117 acee48c3-7b26-0410-bdac-b3d0e5314bbc

19 files changed:
pom.xml
src/main/java/jp/naist/se/stigmata/CertainPairComparisonResultSet.java
src/main/java/jp/naist/se/stigmata/ComparisonResultSet.java
src/main/java/jp/naist/se/stigmata/RoundRobinComparisonResultSet.java
src/main/java/jp/naist/se/stigmata/filter/FilteredComparisonResultSet.java
src/main/java/jp/naist/se/stigmata/ui/swing/BirthmarkExtractionResultPane.java
src/main/java/jp/naist/se/stigmata/ui/swing/ChangeColorAction.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/ui/swing/ControlPane.java
src/main/java/jp/naist/se/stigmata/ui/swing/PopupButton.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/ui/swing/RoundRobinComparisonResultPane.java
src/main/java/jp/naist/se/stigmata/ui/swing/SimilarityDistributionGraphPane.java
src/main/java/jp/naist/se/stigmata/ui/swing/StigmataFrame.java
src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingMethod.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingViewer.java [new file with mode: 0755]
src/main/java/jp/naist/se/stigmata/ui/swing/graph/PointComponent.java [new file with mode: 0755]
src/main/resources/resources/images/map.png [new file with mode: 0755]
src/main/resources/resources/messages.properties
src/test/java/jp/naist/se/stigmata/birthmarks/smc/SmcBirthmarkExtractorTest.java
src/test/java/jp/naist/se/stigmata/birthmarks/uc/UCBirthmarkExtractorTest.java

diff --git a/pom.xml b/pom.xml
index 6536719..6d51260 100755 (executable)
--- a/pom.xml
+++ b/pom.xml
       <scope>compile</scope>
     </dependency>
     <dependency>
+      <groupId>Jama</groupId>
+      <artifactId>Jama</artifactId>
+      <version>1.0.2</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.1</version>
index 77c3910..61dd523 100755 (executable)
@@ -4,7 +4,9 @@ package jp.naist.se.stigmata;
  * $Id$\r
  */\r
 \r
+import java.net.URL;\r
 import java.util.ArrayList;\r
+import java.util.HashMap;\r
 import java.util.Iterator;\r
 import java.util.List;\r
 import java.util.Map;\r
@@ -20,6 +22,7 @@ import java.util.Map;
 public class CertainPairComparisonResultSet implements ComparisonResultSet{\r
     private BirthmarkContext context;\r
     private List<ComparisonPair> pairList = new ArrayList<ComparisonPair>();\r
+    private Map<URL, BirthmarkSet> sources = new HashMap<URL, BirthmarkSet>();\r
 \r
     /**\r
      * This constructor is the comparison pair list is specified.\r
@@ -28,6 +31,8 @@ public class CertainPairComparisonResultSet implements ComparisonResultSet{
         this.context = context;\r
         for(int i = 0; i < pairs.length; i++){\r
             pairList.add(pairs[i]);\r
+            sources.put(pairs[i].getTarget1().getLocation(), pairs[i].getTarget1());\r
+            sources.put(pairs[i].getTarget2().getLocation(), pairs[i].getTarget2());\r
         }\r
     }\r
 \r
@@ -43,6 +48,8 @@ public class CertainPairComparisonResultSet implements ComparisonResultSet{
                 pairList.add(new ComparisonPair(targetX[i], target2, context));\r
             }\r
         }\r
+        addSources(targetX);\r
+        addSources(targetY);\r
     }\r
 \r
     /**\r
@@ -67,6 +74,8 @@ public class CertainPairComparisonResultSet implements ComparisonResultSet{
                 pairList.add(new ComparisonPair(target1, target2, context));\r
             }\r
         }\r
+        addSources(targetX);\r
+        addSources(targetY);\r
     }\r
 \r
     /**\r
@@ -90,6 +99,16 @@ public class CertainPairComparisonResultSet implements ComparisonResultSet{
         return pairList.iterator();\r
     }\r
 \r
+    public BirthmarkSet[] getComparisonSources(){\r
+        BirthmarkSet[] entries = new BirthmarkSet[sources.size()];\r
+        int index = 0;\r
+        for(Map.Entry<URL, BirthmarkSet> entry: sources.entrySet()){\r
+            entries[index] = entry.getValue();\r
+            index++;\r
+        }\r
+        return entries;\r
+    }\r
+\r
     /**\r
      * find BirthmarkSet from given array by given class name.\r
      */\r
@@ -101,4 +120,10 @@ public class CertainPairComparisonResultSet implements ComparisonResultSet{
         }\r
         return null;\r
     }\r
+\r
+    private void addSources(BirthmarkSet[] bs){\r
+        for(BirthmarkSet s: bs){\r
+            sources.put(s.getLocation(), s);\r
+        }\r
+    }\r
 }\r
index a9b0967..0fa1f81 100755 (executable)
@@ -24,4 +24,6 @@ public interface ComparisonResultSet extends Iterable<ComparisonPair>{
     public Iterator<ComparisonPair> iterator();\r
 \r
     public int getComparisonCount();\r
+\r
+    public BirthmarkSet[] getComparisonSources();\r
 }\r
index 0e21b15..d9940cc 100755 (executable)
@@ -4,9 +4,12 @@ package jp.naist.se.stigmata;
  * $Id$\r
  */\r
 \r
+import java.net.URL;\r
 import java.util.Arrays;\r
+import java.util.HashMap;\r
 import java.util.Iterator;\r
 import java.util.List;\r
+import java.util.Map;\r
 \r
 /**\r
  * Concrete class for ComparisonResultSet. This instance compare class files by round robin.\r
@@ -35,7 +38,7 @@ public class RoundRobinComparisonResultSet implements ComparisonResultSet{
     /**\r
      * constructor.  if user gives { a, b, c, } as holders1, then the\r
      * instance (created by this constructor when samePair is true)\r
-     * compares { a<->a, a<->b, a<->c, b<->b, b<->c, c<->c, }.\r
+     * compares { a<->a, b<->a, b<->b, c<->a, c<->b, c<->c, }.\r
      * Otherwise, the instance compares { a<->b, a<->c, b<->c, } when\r
      * samePair is false.\r
      */\r
@@ -102,14 +105,31 @@ public class RoundRobinComparisonResultSet implements ComparisonResultSet{
         return new ComparisonIterator();\r
     }\r
 \r
+    public BirthmarkSet[] getComparisonSources(){\r
+        Map<URL, BirthmarkSet> map = new HashMap<URL, BirthmarkSet>();\r
+        for(BirthmarkSet set: holders1){\r
+            map.put(set.getLocation(), set);\r
+        }\r
+        for(BirthmarkSet set: holders2){\r
+            map.put(set.getLocation(), set);\r
+        }\r
+\r
+        BirthmarkSet[] entries = new BirthmarkSet[map.size()];\r
+        int index = 0;\r
+        for(Map.Entry<URL, BirthmarkSet> entry: map.entrySet()){\r
+            entries[index] = entry.getValue();\r
+            index++;\r
+        }\r
+\r
+        return entries;\r
+    }\r
+\r
     /**\r
      * iterator class.\r
      */\r
     private class ComparisonIterator implements Iterator<ComparisonPair>{\r
         private int i = 0;\r
-\r
         private int j = 0;\r
-\r
         private int count = 0;\r
 \r
         public boolean hasNext(){\r
@@ -117,8 +137,9 @@ public class RoundRobinComparisonResultSet implements ComparisonResultSet{
         }\r
 \r
         public ComparisonPair next(){\r
-            if((tablePair && i == holders1.size()) || (!tablePair && !samePair && i == j)\r
-                    || (!tablePair && samePair && i > j)){\r
+            if((tablePair  && i == holders1.size()) || \r
+               (!tablePair && !samePair && i == j) ||\r
+               (!tablePair && samePair && i > j)){\r
                 i = 0;\r
                 j++;\r
             }\r
index d788721..abd3c98 100755 (executable)
@@ -9,6 +9,7 @@ import java.util.Iterator;
 import java.util.List;\r
 \r
 import jp.naist.se.stigmata.BirthmarkContext;\r
+import jp.naist.se.stigmata.BirthmarkSet;\r
 import jp.naist.se.stigmata.ComparisonPair;\r
 import jp.naist.se.stigmata.ComparisonPairFilterSet;\r
 import jp.naist.se.stigmata.ComparisonResultSet;\r
@@ -64,6 +65,10 @@ public class FilteredComparisonResultSet implements ComparisonResultSet{
         return new FilteredIterator(resultset.iterator());\r
     }\r
 \r
+    public BirthmarkSet[] getComparisonSources(){\r
+        return resultset.getComparisonSources();\r
+    }\r
+\r
     private class FilteredIterator implements Iterator<ComparisonPair>{\r
         private Iterator<ComparisonPair> iterator;\r
         private ComparisonPair next;\r
index 81f07f5..6ecf57f 100755 (executable)
@@ -37,7 +37,6 @@ public class BirthmarkExtractionResultPane extends JPanel implements BirthmarkDa
         this.birthmarks = Arrays.asList(sets);\r
 \r
         JComponent southPanel = Box.createHorizontalBox(); \r
-        // JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));\r
         JButton saveButton = Utility.createButton("savebirthmark");\r
         JScrollPane scroll = new JScrollPane();\r
 \r
diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/ChangeColorAction.java b/src/main/java/jp/naist/se/stigmata/ui/swing/ChangeColorAction.java
new file mode 100755 (executable)
index 0000000..5c8bdb1
--- /dev/null
@@ -0,0 +1,64 @@
+package jp.naist.se.stigmata.ui.swing;\r
+\r
+import java.awt.Color;\r
+import java.awt.Component;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+\r
+import javax.swing.AbstractAction;\r
+import javax.swing.JColorChooser;\r
+import javax.swing.JDialog;\r
+\r
+public class ChangeColorAction extends AbstractAction{\r
+    private static final long serialVersionUID = -7617597154707466764L;\r
+\r
+    private Color color = Color.RED;\r
+    private JColorChooser chooser;\r
+    private Component component;\r
+    private boolean colorSelected = false;\r
+    private ActionListener listener;\r
+\r
+    public ChangeColorAction(Component component, Color color, ActionListener listener){\r
+        super(Messages.getString("changecolor.button.label"),\r
+                Utility.getIcon("changecolor.button.icon"));\r
+        this.component = component;\r
+        this.listener = listener;\r
+        this.color = color;\r
+\r
+        chooser = new JColorChooser();\r
+        chooser.setColor(color);\r
+    }\r
+\r
+    public ChangeColorAction(Component component, ActionListener listener){\r
+        this(component, Color.RED, listener);\r
+    }\r
+\r
+    public boolean isColorSelected(){\r
+        return colorSelected;\r
+    }\r
+\r
+    public Color getColor(){\r
+        return color;\r
+    }\r
+\r
+    public void actionPerformed(ActionEvent e){\r
+        chooser.setColor(color);\r
+        JDialog dialog = JColorChooser.createDialog(\r
+            component, Messages.getString("changecolor.title"), \r
+            true, chooser,\r
+            new ActionListener(){ // ok\r
+                public void actionPerformed(ActionEvent e){\r
+                    color = chooser.getColor();\r
+                    colorSelected = true;\r
+                    listener.actionPerformed(new ActionEvent(ChangeColorAction.this, e.getID(), e.getActionCommand(), e.getWhen(), e.getModifiers()));\r
+                }\r
+            },\r
+            new ActionListener(){ // cancel\r
+                public void actionPerformed(ActionEvent e){\r
+                    colorSelected = false;\r
+                }\r
+            }\r
+        );\r
+        dialog.setVisible(true);\r
+    }\r
+}\r
index 4956bad..5793c8a 100755 (executable)
@@ -17,8 +17,8 @@ import java.util.Set;
 import javax.swing.Box;\r
 import javax.swing.BoxLayout;\r
 import javax.swing.JButton;\r
-import javax.swing.JComboBox;\r
 import javax.swing.JComponent;\r
+import javax.swing.JMenuItem;\r
 import javax.swing.JOptionPane;\r
 import javax.swing.JPanel;\r
 import javax.swing.JTabbedPane;\r
@@ -50,7 +50,7 @@ public class ControlPane extends JPanel{
     private JButton compareButton;\r
     private JButton extractButton;\r
     private JButton resetButton;\r
-    private JComboBox comparisonMethods;\r
+    private PopupButton comparePopup;\r
     private boolean expertmode = false;\r
 \r
     public ControlPane(StigmataFrame stigmata){\r
@@ -205,13 +205,16 @@ public class ControlPane extends JPanel{
         String[] valueY = targetY.getValues();\r
         String[] targets = birthmarks.getSelectedServices();\r
 \r
-        extractButton\r
-                .setEnabled(((valueX != null && valueX.length > 0) || (valueY != null && valueY.length > 0))\r
-                        && (targets != null && targets.length > 0));\r
+        extractButton.setEnabled(\r
+            ((valueX != null && valueX.length > 0) || (valueY != null && valueY.length > 0))\r
+            && (targets != null && targets.length > 0)\r
+        );\r
 \r
-        compareButton.setEnabled((valueX != null && valueX.length > 0)\r
-                && (valueY != null && valueY.length > 0)\r
-                && (targets != null && targets.length > 0));\r
+        comparePopup.setEnabled(\r
+            (valueX != null && valueX.length > 0) &&\r
+            (valueY != null && valueY.length > 0) &&\r
+            (targets != null && targets.length > 0)\r
+        );\r
     }\r
 \r
     private void extractButtonActionPerformed(ActionEvent e){\r
@@ -257,8 +260,10 @@ public class ControlPane extends JPanel{
     private void compareRoundRobin(){\r
         BirthmarkContext context = generateContext();\r
 \r
-        stigmata.compareRoundRobin(birthmarks.getSelectedServices(), targetX\r
-                .getValues(), targetY.getValues(), context);\r
+        stigmata.compareRoundRobin(\r
+            birthmarks.getSelectedServices(), targetX.getValues(), \r
+            targetY.getValues(), context\r
+        );\r
     }\r
 \r
     private void compareSpecifiedPair(){\r
@@ -297,13 +302,8 @@ public class ControlPane extends JPanel{
         controlTab = new JTabbedPane();\r
         resetButton = Utility.createButton("reset");\r
         extractButton = Utility.createButton("extract");\r
-        compareButton = Utility.createButton("compare");\r
-        comparisonMethods = new JComboBox();\r
-\r
-        String[] items = Messages.getStringArray("comparison.methods");\r
-        for(int i = 0; i < items.length; i++){\r
-            comparisonMethods.addItem(items[i]);\r
-        }\r
+        compareButton = Utility.createButton("roundrobin");\r
+        comparePopup = new PopupButton(compareButton);\r
 \r
         Box south = Box.createHorizontalBox();\r
         south.add(Box.createHorizontalGlue());\r
@@ -311,9 +311,7 @@ public class ControlPane extends JPanel{
         south.add(Box.createHorizontalGlue());\r
         south.add(extractButton);\r
         south.add(Box.createHorizontalGlue());\r
-        south.add(compareButton);\r
-        south.add(Box.createHorizontalGlue());\r
-        south.add(comparisonMethods);\r
+        south.add(comparePopup);\r
         south.add(Box.createHorizontalGlue());\r
 \r
         setLayout(new BorderLayout());\r
@@ -321,7 +319,7 @@ public class ControlPane extends JPanel{
         add(controlTab, BorderLayout.CENTER);\r
 \r
         extractButton.setEnabled(false);\r
-        compareButton.setEnabled(false);\r
+        comparePopup.setEnabled(false);\r
 \r
         resetButton.addActionListener(new ActionListener(){\r
             public void actionPerformed(ActionEvent e){\r
@@ -335,23 +333,31 @@ public class ControlPane extends JPanel{
             }\r
         });\r
 \r
-        compareButton.addActionListener(new ActionListener(){\r
+        ActionListener compareListener = new ActionListener(){\r
             public void actionPerformed(ActionEvent e){\r
-                String item = (String)comparisonMethods.getSelectedItem();\r
-                if(item.equals(Messages.getString("roundrobin.label"))){\r
+                String command = e.getActionCommand();\r
+\r
+                if(command.equals("roundrobin")){\r
                     compareRoundRobin();\r
                 }\r
-                else if(item.equals(Messages.getString("guessedpair.label"))){\r
+                else if(command.equals("guessedpair")){\r
                     compareGuessedPair();\r
                 }\r
-                else if(item.equals(Messages.getString("specifiedpair.label"))){\r
+                else if(command.equals("specifiedpair")){\r
                     compareSpecifiedPair();\r
                 }\r
-                else if(item.equals(Messages\r
-                        .getString("roundrobin.filtering.label"))){\r
+                else if(command.equals("roundrobin.filtering")){\r
                     compareRoundRobinWithFiltering();\r
                 }\r
             }\r
-        });\r
+        };\r
+        compareButton.addActionListener(compareListener);\r
+\r
+        String[] items = Messages.getStringArray("comparison.methods");\r
+        for(int i = 1; i < items.length; i++){\r
+            JMenuItem item = Utility.createJMenuItem(items[i]);\r
+            comparePopup.addMenuItem(item);\r
+            item.addActionListener(compareListener);\r
+        }\r
     }\r
 }\r
diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/PopupButton.java b/src/main/java/jp/naist/se/stigmata/ui/swing/PopupButton.java
new file mode 100755 (executable)
index 0000000..3de7e43
--- /dev/null
@@ -0,0 +1,97 @@
+package jp.naist.se.stigmata.ui.swing;\r
+\r
+/*\r
+ * $Id$\r
+ */\r
+\r
+import java.awt.Color;\r
+import java.awt.Dimension;\r
+import java.awt.FlowLayout;\r
+import java.awt.Graphics2D;\r
+import java.awt.Point;\r
+import java.awt.Polygon;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.image.BufferedImage;\r
+\r
+import javax.swing.Icon;\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JButton;\r
+import javax.swing.JMenuItem;\r
+import javax.swing.JPanel;\r
+import javax.swing.JPopupMenu;\r
+\r
+/**\r
+ * Popup button.\r
+ * \r
+ * @author tamada\r
+ * @version $Revision$ $Date$\r
+ */\r
+public class PopupButton extends JPanel{\r
+    private static final long serialVersionUID = -4428839967597028837L;\r
+\r
+    private JButton button;\r
+    private JPopupMenu popup;\r
+    private JButton arrowButton;\r
+\r
+    public PopupButton(JButton initButton){\r
+        this.button = initButton;\r
+\r
+        Icon icon = createIcon();\r
+        arrowButton = new JButton(icon);\r
+        popup = new JPopupMenu();\r
+        add(button);\r
+        add(arrowButton);\r
+\r
+        setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));\r
+        Dimension prefferedSize = button.getPreferredSize();\r
+\r
+        arrowButton.setPreferredSize(new Dimension(icon.getIconWidth() + 2, prefferedSize.height));\r
+        setPreferredSize(new Dimension(prefferedSize.width + icon.getIconWidth() + 2, prefferedSize.height));\r
+\r
+        Dimension maxSize = button.getMaximumSize();\r
+        arrowButton.setMaximumSize(new Dimension(icon.getIconWidth() + 2, maxSize.height));\r
+        setMaximumSize(new Dimension(maxSize.width + icon.getIconWidth() + 2, maxSize.height));\r
+\r
+        Dimension minSize = button.getMinimumSize();\r
+        arrowButton.setMaximumSize(new Dimension(icon.getIconWidth() + 2, minSize.height));\r
+        setMinimumSize(new Dimension(minSize.width + icon.getIconWidth() + 2, minSize.height));\r
+\r
+        arrowButton.setSize(arrowButton.getPreferredSize());\r
+        setSize(getPreferredSize());\r
+        \r
+        arrowButton.addActionListener(new ActionListener(){\r
+            public void actionPerformed(ActionEvent e){\r
+                Point p = button.getLocation();\r
+                popup.show(PopupButton.this, p.x, button.getHeight());\r
+            }\r
+        });\r
+    }\r
+\r
+    @Override\r
+    public void setEnabled(boolean enabled){\r
+        super.setEnabled(enabled);\r
+        button.setEnabled(enabled);\r
+        arrowButton.setEnabled(enabled);\r
+    }\r
+\r
+    public JButton getButton(){\r
+        return button;\r
+    }\r
+\r
+    private Icon createIcon(){\r
+        BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);\r
+        Graphics2D g = image.createGraphics();\r
+        int[] x = new int[] { 0, 5, 10, };\r
+        int[] y = new int[] { 3, 8, 3, };\r
+        Polygon polygon = new Polygon(x, y, x.length);\r
+        g.setColor(Color.black);\r
+        g.fill(polygon);\r
+\r
+        return new ImageIcon(image);\r
+    }\r
+\r
+    public JMenuItem addMenuItem(JMenuItem menuItem){\r
+        return popup.add(menuItem);\r
+    }\r
+}\r
index 4024d04..f1ceeee 100755 (executable)
@@ -14,6 +14,7 @@ import java.awt.event.MouseEvent;
 import java.io.File;\r
 import java.io.IOException;\r
 import java.io.PrintWriter;\r
+import java.net.URL;\r
 import java.util.Arrays;\r
 import java.util.HashMap;\r
 import java.util.List;\r
@@ -21,9 +22,9 @@ import java.util.Map;
 \r
 import javax.swing.Box;\r
 import javax.swing.JButton;\r
-import javax.swing.JComboBox;\r
 import javax.swing.JComponent;\r
 import javax.swing.JLabel;\r
+import javax.swing.JMenuItem;\r
 import javax.swing.JOptionPane;\r
 import javax.swing.JPanel;\r
 import javax.swing.JScrollPane;\r
@@ -38,6 +39,7 @@ import jp.naist.se.stigmata.BirthmarkSet;
 import jp.naist.se.stigmata.CertainPairComparisonResultSet;\r
 import jp.naist.se.stigmata.ComparisonResultSet;\r
 import jp.naist.se.stigmata.RoundRobinComparisonResultSet;\r
+import jp.naist.se.stigmata.filter.FilteredComparisonResultSet;\r
 import jp.naist.se.stigmata.spi.ResultFormatSpi;\r
 \r
 /**\r
@@ -192,6 +194,24 @@ public class RoundRobinComparisonResultPane extends JPanel implements BirthmarkD
         stigmataFrame.saveAction(this);\r
     }\r
 \r
+    private void mdsButtonActionPerformed(ActionEvent e){\r
+        Map<URL, BirthmarkSet> map = new HashMap<URL, BirthmarkSet>();\r
+        for(BirthmarkSet bs: birthmarksX){\r
+            map.put(bs.getLocation(), bs);\r
+        }\r
+        for(BirthmarkSet bs: birthmarksY){\r
+            map.put(bs.getLocation(), bs);\r
+        }\r
+        int index = 0;\r
+        BirthmarkSet[] set = new BirthmarkSet[map.size()];\r
+        for(Map.Entry<URL, BirthmarkSet> entry: map.entrySet()){\r
+            set[index] = entry.getValue();\r
+            index++;\r
+        }\r
+\r
+        stigmataFrame.showMDSGraph(set);\r
+    }\r
+\r
     private void graphButtonActionPerformed(ActionEvent e){\r
         Map<Integer, Integer> values = new HashMap<Integer, Integer>();\r
         for(int i = 0; i < table.getRowCount(); i++){\r
@@ -213,14 +233,13 @@ public class RoundRobinComparisonResultPane extends JPanel implements BirthmarkD
         JButton save = Utility.createButton("savecomparison"); //$NON-NLS-1$\r
         JButton graph = Utility.createButton("showgraph"); //$NON-NLS-1$\r
         JButton obfuscate = Utility.createButton("obfuscate"); //$NON-NLS-1$\r
-        JButton compare = Utility.createButton("compare"); //$NON-NLS-1$\r
-        final JComboBox combo = new JComboBox();\r
-        JComponent southPanel = Box.createHorizontalBox();\r
+        JButton compare = Utility.createButton("guessedpair"); //$NON-NLS-1$\r
+        JMenuItem mdsMenu = Utility.createJMenuItem("mdsmap");\r
 \r
-        String[] comparisonMethods = Messages.getStringArray("comparison.methods.inroundrobinresult");\r
-        for(int i = 0; i < comparisonMethods.length; i++){\r
-            combo.addItem(comparisonMethods[i]);\r
-        }\r
+        PopupButton comparePopup = new PopupButton(compare);\r
+        PopupButton graphPopup = new PopupButton(graph);\r
+\r
+        JComponent southPanel = Box.createHorizontalBox();\r
 \r
         setLayout(new BorderLayout());\r
         add(getMainPane(), BorderLayout.CENTER);\r
@@ -228,13 +247,11 @@ public class RoundRobinComparisonResultPane extends JPanel implements BirthmarkD
         southPanel.add(Box.createHorizontalGlue());\r
         southPanel.add(save);\r
         southPanel.add(Box.createHorizontalGlue());\r
-        southPanel.add(graph);\r
+        southPanel.add(graphPopup);\r
         southPanel.add(Box.createHorizontalGlue());\r
         southPanel.add(obfuscate);\r
         southPanel.add(Box.createHorizontalGlue());\r
-        southPanel.add(compare);\r
-        southPanel.add(Box.createHorizontalGlue());\r
-        southPanel.add(combo);\r
+        southPanel.add(comparePopup);\r
         southPanel.add(Box.createHorizontalGlue());\r
 \r
         save.addActionListener(new ActionListener(){\r
@@ -248,23 +265,67 @@ public class RoundRobinComparisonResultPane extends JPanel implements BirthmarkD
                 graphButtonActionPerformed(e);\r
             }\r
         });\r
+        mdsMenu.addActionListener(new ActionListener(){\r
+            public void actionPerformed(ActionEvent e){\r
+                mdsButtonActionPerformed(e);\r
+            }\r
+        });\r
+\r
         obfuscate.addActionListener(new ActionListener(){\r
             public void actionPerformed(ActionEvent e){\r
                 obfuscateClassNames();\r
             }\r
         });\r
 \r
-        compare.addActionListener(new ActionListener(){\r
+        ActionListener compareListener = new ActionListener(){\r
             public void actionPerformed(ActionEvent e){\r
-                String item = (String)combo.getSelectedItem();\r
-                if(item.equals(Messages.getString("guessedpair.label"))){\r
+                String item = e.getActionCommand();\r
+                if(item.equals("guessedpair")){\r
                     compareGuessedPair();\r
                 }\r
-                else if(item.equals(Messages.getString("specifiedpair.label"))){\r
+                else if(item.equals("specifiedpair")){\r
                     compareSpecifiedPair();\r
                 }\r
+                else if(item.equals("roundrobin.filtering")){\r
+                    compareRoundRobinWithFiltering();\r
+                }\r
             }\r
-        });\r
+        };\r
+\r
+        compare.addActionListener(compareListener);\r
+        String[] comparisonMethods = Messages.getStringArray("comparison.methods.inroundrobinresult");\r
+        for(int i = 1; i < comparisonMethods.length; i++){\r
+            JMenuItem item = Utility.createJMenuItem(comparisonMethods[i]);\r
+            comparePopup.addMenuItem(item);\r
+            item.addActionListener(compareListener);\r
+        }\r
+        graphPopup.addMenuItem(mdsMenu);\r
+    }\r
+\r
+    private void compareRoundRobinWithFiltering(){\r
+        FilterSelectionPane pane = new FilterSelectionPane(\r
+            context.getFilterManager()\r
+        );\r
+        int returnValue = JOptionPane.showConfirmDialog(\r
+            stigmataFrame, pane, Messages.getString("filterselection.dialog.title"),\r
+            JOptionPane.OK_CANCEL_OPTION,\r
+            JOptionPane.QUESTION_MESSAGE\r
+        );\r
+        if(returnValue == JOptionPane.OK_OPTION){\r
+            String[] filterSetList = pane.getSelectedFilters();\r
+\r
+            ComparisonResultSet resultset = new RoundRobinComparisonResultSet(\r
+                birthmarksX.toArray(new BirthmarkSet[birthmarksX.size()]),\r
+                birthmarksY.toArray(new BirthmarkSet[birthmarksY.size()]),\r
+                context\r
+            );\r
+            \r
+            ComparisonResultSet filterResultSet = new FilteredComparisonResultSet(\r
+                resultset,\r
+                context.getFilterManager().getFilterSets(filterSetList)\r
+            );\r
+            stigmataFrame.showComparisonResultSet(filterResultSet);\r
+        }\r
     }\r
 \r
     private void compareGuessedPair(){\r
index 6be8fdd..5b5d5e5 100644 (file)
@@ -24,8 +24,6 @@ import javax.imageio.ImageIO;
 import javax.swing.Box;\r
 import javax.swing.ImageIcon;\r
 import javax.swing.JButton;\r
-import javax.swing.JColorChooser;\r
-import javax.swing.JDialog;\r
 import javax.swing.JLabel;\r
 import javax.swing.JOptionPane;\r
 import javax.swing.JPanel;\r
@@ -44,8 +42,6 @@ public class SimilarityDistributionGraphPane extends JPanel{
     private int maxFrequency = 0;\r
     private JLabel iconLabel;\r
     private BufferedImage image;\r
-    private Color color = Color.RED;\r
-    private JColorChooser chooser;\r
 \r
     public SimilarityDistributionGraphPane(StigmataFrame stigmata, Map<Integer, Integer> distributions){\r
         this.stigmata = stigmata;\r
@@ -54,7 +50,7 @@ public class SimilarityDistributionGraphPane extends JPanel{
         initializeLayouts();\r
         initializeData();\r
 \r
-        drawGraph();\r
+        drawGraph(Color.RED);\r
     }\r
 \r
     public String[] getSupportedFormats(){\r
@@ -68,7 +64,7 @@ public class SimilarityDistributionGraphPane extends JPanel{
         return set.toArray(new String[set.size()]);\r
     }\r
 \r
-    private void drawGraph(){\r
+    private void drawGraph(Color color){\r
         Graphics2D g = image.createGraphics();\r
         g.setColor(getBackground());\r
         g.fillRect(0, 0, image.getWidth(), image.getHeight());\r
@@ -142,23 +138,23 @@ public class SimilarityDistributionGraphPane extends JPanel{
     }\r
 \r
     private void initializeLayouts(){\r
-        chooser = new JColorChooser();\r
-        chooser.setColor(Color.RED);\r
         image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_ARGB);\r
 \r
         JPanel center = new JPanel(new FlowLayout(FlowLayout.CENTER));\r
         iconLabel = new JLabel();\r
         Box south = Box.createHorizontalBox();\r
         JButton storeImageButton = Utility.createButton("savegraph");\r
-        JButton switchColorButton = Utility.createButton("changecolor");\r
-        storeImageButton.addActionListener(new ActionListener(){\r
+        JButton switchColorButton = new JButton(new ChangeColorAction(stigmata, new ActionListener(){\r
             public void actionPerformed(ActionEvent e){\r
-                storeGraphImage();\r
+                ChangeColorAction action = (ChangeColorAction)e.getSource();\r
+                if(action.isColorSelected()){\r
+                    drawGraph(action.getColor());\r
+                }\r
             }\r
-        });\r
-        switchColorButton.addActionListener(new ActionListener(){\r
+        }));\r
+        storeImageButton.addActionListener(new ActionListener(){\r
             public void actionPerformed(ActionEvent e){\r
-                switchColor();\r
+                storeGraphImage();\r
             }\r
         });\r
 \r
@@ -174,25 +170,6 @@ public class SimilarityDistributionGraphPane extends JPanel{
         add(south, BorderLayout.SOUTH);\r
     }\r
 \r
-    private void switchColor(){\r
-        chooser.setColor(color);\r
-        JDialog dialog = JColorChooser.createDialog(\r
-            stigmata, Messages.getString("changecolor.title"), \r
-            true, chooser, \r
-            new ActionListener(){ // ok\r
-                public void actionPerformed(ActionEvent e){\r
-                    color = chooser.getColor();\r
-                    drawGraph();\r
-                }\r
-            },\r
-            new ActionListener(){ // cancel\r
-                public void actionPerformed(ActionEvent e){\r
-                }\r
-            }\r
-        );\r
-        dialog.setVisible(true);\r
-    }\r
-\r
     private void storeGraphImage(){\r
         String[] exts = getSupportedFormats();\r
         File file = stigmata.getSaveFile(\r
index b825a3b..2f598a5 100755 (executable)
@@ -5,6 +5,7 @@ package jp.naist.se.stigmata.ui.swing;
  */\r
 \r
 import java.awt.BorderLayout;\r
+import java.awt.Color;\r
 import java.awt.Dimension;\r
 import java.awt.Font;\r
 import java.awt.event.ActionEvent;\r
@@ -26,6 +27,9 @@ import java.util.HashMap;
 import java.util.List;\r
 import java.util.Map;\r
 \r
+import javax.swing.Box;\r
+import javax.swing.JButton;\r
+import javax.swing.JCheckBox;\r
 import javax.swing.JCheckBoxMenuItem;\r
 import javax.swing.JFileChooser;\r
 import javax.swing.JFrame;\r
@@ -58,6 +62,9 @@ import jp.naist.se.stigmata.Stigmata;
 import jp.naist.se.stigmata.filter.FilteredComparisonResultSet;\r
 import jp.naist.se.stigmata.format.FormatManager;\r
 import jp.naist.se.stigmata.spi.ResultFormatSpi;\r
+import jp.naist.se.stigmata.ui.swing.graph.MultiDimensionalScalingMethod;\r
+import jp.naist.se.stigmata.ui.swing.graph.MultiDimensionalScalingViewer;\r
+import Jama.Matrix;\r
 \r
 \r
 /**\r
@@ -79,7 +86,8 @@ public class StigmataFrame extends JFrame implements CurrentDirectoryHolder{
     private int extractCount = 0;\r
     private int compareCount = 0;\r
     private int compareDetail = 0;\r
-    private int graphCount = 0;\r
+    private int similarityGraphCount = 0;\r
+    private int mappingGraphCount = 0;\r
     private int comparePair = 0;\r
 \r
     public StigmataFrame(){\r
@@ -295,11 +303,56 @@ public class StigmataFrame extends JFrame implements CurrentDirectoryHolder{
         tabPane.setSelectedIndex(tabPane.getTabCount() - 1);\r
     }\r
 \r
+    public void showMDSGraph(BirthmarkSet[] set){\r
+        double[][] matrix = new double[set.length][set.length];\r
+\r
+        String[] labels = new String[set.length];\r
+        for(int i = 0; i < set.length; i++){\r
+            for(int j = 0; j <= i; j++){\r
+                ComparisonPair pair = new ComparisonPair(set[i], set[j], context);\r
+                matrix[i][j] = 1d - pair.calculateSimilarity();\r
+                if(i != j){\r
+                    matrix[j][i] = matrix[i][j];\r
+                }\r
+            }\r
+            labels[i] = set[i].getClassName();\r
+        }\r
+        final MultiDimensionalScalingViewer viewer = new MultiDimensionalScalingViewer(new MultiDimensionalScalingMethod(new Matrix(matrix)), labels);\r
+        viewer.setShowLabel(true);\r
+\r
+        JPanel panel = new JPanel(new BorderLayout());\r
+        Box south = Box.createHorizontalBox();\r
+        JButton colorButton = new JButton(new ChangeColorAction(this, Color.BLUE, new ActionListener(){\r
+            public void actionPerformed(ActionEvent e){\r
+                ChangeColorAction action = (ChangeColorAction)e.getSource();\r
+                viewer.setOverColor(action.getColor());\r
+            }\r
+        }));\r
+        final JCheckBox check = new JCheckBox(Messages.getString("showlabel.button.label"), true);\r
+        check.addActionListener(new ActionListener(){\r
+            public void actionPerformed(ActionEvent e){\r
+                viewer.setShowLabel(check.isSelected());\r
+            }\r
+        });\r
+\r
+        south.add(Box.createHorizontalGlue());\r
+        south.add(colorButton);\r
+        south.add(Box.createHorizontalGlue());\r
+        south.add(check);\r
+        south.add(Box.createHorizontalGlue());\r
+        panel.add(viewer, BorderLayout.CENTER);\r
+        panel.add(south, BorderLayout.SOUTH);\r
+\r
+        mappingGraphCount++;\r
+        Utility.addNewTab("mappinggraph", tabPane, panel, new Object[] { new Integer(mappingGraphCount), }, null);\r
+        tabPane.setSelectedIndex(tabPane.getTabCount() - 1);\r
+    }\r
+\r
     public void showSimilarityDistributionGraph(Map<Integer, Integer> distributions){\r
         SimilarityDistributionGraphPane graph = new SimilarityDistributionGraphPane(this, distributions);\r
 \r
-        graphCount++;\r
-        Utility.addNewTab("graph", tabPane, graph, new Object[] { new Integer(graphCount), }, null);\r
+        similarityGraphCount++;\r
+        Utility.addNewTab("similaritygraph", tabPane, graph, new Object[] { new Integer(similarityGraphCount), }, null);\r
         tabPane.setSelectedIndex(tabPane.getTabCount() - 1);\r
     }\r
 \r
diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingMethod.java b/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingMethod.java
new file mode 100755 (executable)
index 0000000..2c00cb1
--- /dev/null
@@ -0,0 +1,101 @@
+package jp.naist.se.stigmata.ui.swing.graph;\r
+\r
+import Jama.EigenvalueDecomposition;\r
+import Jama.Matrix;\r
+\r
+public class MultiDimensionalScalingMethod{\r
+    private Matrix target;\r
+    private Matrix coordinate;\r
+    private int[] indexes;\r
+\r
+    public MultiDimensionalScalingMethod(Matrix matrix){\r
+        this.target = matrix;\r
+    }\r
+\r
+    protected Matrix getCenteredInnerProductMatrix(){\r
+        Matrix centering = getCenteringMatrix(target.getColumnDimension());\r
+        Matrix trans = centering.transpose();\r
+\r
+        return centering.times(target).times(trans).times(-1);\r
+    }\r
+\r
+    public double[] getCoordinate(int axis){\r
+        if(coordinate == null){\r
+            getCoordinateMatrix();\r
+        }\r
+        double[] v = new double[coordinate.getRowDimension()];\r
+        for(int i = 0; i < v.length; i++){\r
+            v[i] = coordinate.get(i, indexes[axis]);\r
+        }\r
+        return v;\r
+    }\r
+\r
+    public Matrix getCoordinateMatrix(){\r
+        Matrix mat = getCenteredInnerProductMatrix();\r
+        EigenvalueDecomposition eigen = mat.eig();\r
+        Matrix eigenVectors = eigen.getV();\r
+        Matrix eigenValues  = eigen.getD();\r
+\r
+        for(int i = 0; i < mat.getRowDimension(); i++){\r
+            for(int j = 0; j < mat.getColumnDimension(); j++){\r
+                double v = eigenVectors.get(i, j);\r
+                v = v * Math.sqrt(eigenValues.get(j, j));\r
+                eigenVectors.set(i, j, v);\r
+            }\r
+        }\r
+        sortValues(eigenVectors);\r
+        this.coordinate = eigenVectors;\r
+\r
+        return eigenVectors;\r
+    }\r
+\r
+    protected static Matrix getCenteringMatrix(int n){\r
+        Matrix matrix = Matrix.identity(n, n);\r
+        for(int i = 0; i < n; i++){\r
+            for(int j = 0; j < n; j++){\r
+                matrix.set(i, j, matrix.get(i, j) - (1d / n));\r
+            }\r
+        }\r
+        return matrix;\r
+    }\r
+\r
+    private void sortValues(Matrix m){\r
+        double[] v = new double[m.getColumnDimension()];\r
+        int[] index = new int[v.length];\r
+        for(int i = 0; i < v.length; i++){\r
+            v[i] = m.get(i, i);\r
+            index[i] = i;\r
+        }\r
+\r
+        for(int i = 0; i < v.length; i++){\r
+            for(int j = i + 1; j < v.length; j++){\r
+                if(v[i] < v[j]){\r
+                    double tmpValue = v[j];\r
+                    v[j] = v[i];\r
+                    v[i] = tmpValue;\r
+                    int tmpIndex = index[j];\r
+                    index[j] = index[i];\r
+                    index[i] = tmpIndex;\r
+                }\r
+            }\r
+        }\r
+        indexes = index;\r
+    }\r
+\r
+    public static void main(String[] args){\r
+        Matrix matrix = new Matrix(new double[][]{\r
+            {    0,  587, 1212,  701, 1936,  604,  748, 2139, 2182,  543, },\r
+            {  587,    0,  920,  940, 1745, 1188,  713, 1858, 1737,  597, },\r
+            { 1212,  920,    0,  879,  831, 1726, 1631,  949, 1021, 1494, },\r
+            {  701,  940,  879,    0, 1374,  968, 1420, 1645, 1891, 1220, },\r
+            { 1936, 1745,  831, 1374,    0, 2339, 2451,  347,  959, 2300, },\r
+            {  604, 1188, 1726,  968, 2339,    0, 1092, 2592, 2734,  923, },\r
+            {  748,  713, 1631, 1420, 2451, 1092,    0, 2571, 2408,  205, },\r
+            { 2139, 1858,  949, 1645,  347, 2594, 2571,    0,  678, 2442, },\r
+            { 2182, 1737, 1021, 1891,  959, 2734, 2408,  678,    0, 2329, },\r
+            {  543,  597, 1494, 1220, 2300,  923,  205, 2442, 2329,    0, },\r
+        });\r
+        MultiDimensionalScalingMethod mds = new MultiDimensionalScalingMethod(matrix);\r
+        System.out.println(mds.getCoordinateMatrix());\r
+    }\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingViewer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingViewer.java
new file mode 100755 (executable)
index 0000000..7070f61
--- /dev/null
@@ -0,0 +1,209 @@
+package jp.naist.se.stigmata.ui.swing.graph;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Color;\r
+import java.awt.Component;\r
+import java.awt.Dimension;\r
+import java.awt.Graphics;\r
+import java.awt.Point;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.swing.JFrame;\r
+import javax.swing.JLabel;\r
+import javax.swing.JLayeredPane;\r
+\r
+import Jama.Matrix;\r
+\r
+public class MultiDimensionalScalingViewer extends JLayeredPane{\r
+    private static final long serialVersionUID = -9196070059428975126L;\r
+    private static final int POINT_LAYER = DEFAULT_LAYER;\r
+    private static final int LABEL_LAYER = DEFAULT_LAYER;\r
+\r
+    private MultiDimensionalScalingMethod mds;\r
+    private List<double[]> list = new ArrayList<double[]>();\r
+    private Color overColor = PointComponent.DEFAULT_OVER_COLOR;\r
+    private Color pointColor = getForeground();\r
+    private boolean sameAspect = false;\r
+    private boolean showLabel = false;\r
+    private List<PointComponent> points = new ArrayList<PointComponent>();\r
+    private List<JLabel> labellist = new ArrayList<JLabel>();\r
+\r
+    public MultiDimensionalScalingViewer(MultiDimensionalScalingMethod mds){\r
+        this(mds, null);\r
+    }\r
+\r
+    public MultiDimensionalScalingViewer(MultiDimensionalScalingMethod mds, String[] labels){\r
+        this.mds = mds;\r
+\r
+        setSize(300, 300);\r
+        setMinimumSize(getSize());\r
+        setPreferredSize(getSize());\r
+        initLayouts(labels);\r
+    }\r
+\r
+    public boolean isShowLabel(){\r
+        return showLabel;\r
+    }\r
+\r
+    public void setShowLabel(boolean showLabel){\r
+        this.showLabel = showLabel;\r
+        repaint();\r
+    }\r
+\r
+    public boolean isSameAspect(){\r
+        return sameAspect;\r
+    }\r
+\r
+    public void setSameAspect(boolean sameAspect){\r
+        this.sameAspect = sameAspect;\r
+        repaint();\r
+    }\r
+\r
+    public Color getOverColor(){\r
+        return overColor;\r
+    }\r
+\r
+    public void setOverColor(Color color){\r
+        this.overColor = color;\r
+        for(int i = 0; i < getComponentCount(); i++){\r
+            Component c = getComponent(i);\r
+            if(c instanceof PointComponent){\r
+                ((PointComponent)c).setOverColor(color);\r
+            }\r
+        }\r
+    }\r
+\r
+    public Color getPointColor(){\r
+        return pointColor;\r
+    }\r
+\r
+    public void setPointColor(Color color){\r
+        this.pointColor = color;\r
+        for(int i = 0; i < getComponentCount(); i++){\r
+            Component c = getComponent(i);\r
+            if(c instanceof PointComponent){\r
+                ((PointComponent)c).setForeground(color);\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void paintComponent(Graphics g){\r
+        super.paintComponent(g);\r
+\r
+        Dimension d = getSize();\r
+\r
+        g.setColor(Color.GRAY);\r
+        g.drawLine(d.width / 2, d.height, d.width / 2, 0);\r
+        g.drawLine(0, d.height / 2, d.width, d.height / 2);\r
+\r
+        updateComponents(d);\r
+    }\r
+\r
+    private void initLayouts(String[] labels){\r
+        double[] x = mds.getCoordinate(0);\r
+        double[] y = mds.getCoordinate(1);\r
+\r
+        double xmax = 0d;\r
+        double ymax = 0d;\r
+        for(int i = 0; i < x.length; i++){\r
+            if(xmax < Math.abs(x[i])) xmax = Math.abs(x[i]);\r
+        }\r
+        for(int i = 0; i < y.length; i++){\r
+            if(ymax < Math.abs(y[i])) ymax = Math.abs(y[i]);\r
+        }\r
+        if(sameAspect){\r
+            if(ymax > xmax) xmax = ymax;\r
+            else            ymax = xmax;\r
+        }\r
+\r
+        int w = getWidth();\r
+        int h = getHeight();\r
+\r
+        int ww = w - 20;\r
+        int hh = h - 20;\r
+\r
+        for(int i = 0; i < x.length; i++){\r
+            double[] xy = new double[] { x[i] / xmax, - y[i] / ymax, };\r
+            list.add(xy);\r
+            double xx = xy[0] * ww / 2 + (w / 2);\r
+            double yy = xy[1] * hh / 2 + (h / 2);\r
+            String label = String.valueOf(i);\r
+            if(labels != null && labels.length > i){\r
+                label = labels[i];\r
+            }\r
+\r
+            PointComponent p = new PointComponent(label, x[i], y[i]);\r
+            add(p, POINT_LAYER);\r
+            Dimension size = p.getSize();\r
+            p.setLocation(\r
+                new Point((int)(xx - (size.getWidth() / 2d)), (int)(yy - (size.getHeight() / 2)))\r
+            );\r
+            points.add(p);\r
+\r
+            JLabel l = new JLabel(p.getLabel());\r
+            add(l, LABEL_LAYER);\r
+            l.setSize(l.getPreferredSize());\r
+            Point pcp = p.getLocation();\r
+            Dimension dsize = l.getSize();\r
+            l.setLocation(new Point(pcp.x - (dsize.width / 2), pcp.y - 15));\r
+            l.setVisible(isShowLabel());\r
+            labellist.add(l);\r
+        }\r
+    }\r
+\r
+    private void updateComponents(Dimension d){\r
+        int index = 0;\r
+        for(PointComponent pc: points){\r
+            updateLocation(pc, list.get(index), d);\r
+            JLabel label = labellist.get(index);\r
+            Point pcp = pc.getLocation();\r
+            Dimension dsize = label.getSize();\r
+            label.setLocation(new Point(pcp.x - (dsize.width / 2), pcp.y - 15));\r
+            label.setVisible(isShowLabel());\r
+            index++;\r
+        }\r
+    }\r
+\r
+    private void updateLocation(PointComponent c, double[] xy, Dimension d){\r
+        double xx = xy[0] * (d.width - 20) / 2 + (d.width / 2);\r
+        double yy = xy[1] * (d.height - 20) / 2 + (d.height / 2);\r
+        Dimension size = c.getSize();\r
+        c.setLocation(\r
+            new Point((int)(xx - (size.getWidth() / 2d)), (int)(yy - (size.getHeight() / 2)))\r
+        );\r
+    }\r
+\r
+    public static void main(String[] args) throws Exception{\r
+        MultiDimensionalScalingMethod mds;\r
+        String[] labels = null;\r
+\r
+        labels = new String[] { \r
+            "Atlanta", "Chicago", "Denver", "Houston", "Los Angeles", "Miami",\r
+            "New York", "San Francisco", "Seattle", "Washington D.C.",\r
+        };\r
+        Matrix matrix = new Matrix(new double[][]{\r
+            {    0,  587, 1212,  701, 1936,  604,  748, 2139, 2182,  543, },\r
+            {  587,    0,  920,  940, 1745, 1188,  713, 1858, 1737,  597, },\r
+            { 1212,  920,    0,  879,  831, 1726, 1631,  949, 1021, 1494, },\r
+            {  701,  940,  879,    0, 1374,  968, 1420, 1645, 1891, 1220, },\r
+            { 1936, 1745,  831, 1374,    0, 2339, 2451,  347,  959, 2300, },\r
+            {  604, 1188, 1726,  968, 2339,    0, 1092, 2592, 2734,  923, },\r
+            {  748,  713, 1631, 1420, 2451, 1092,    0, 2571, 2408,  205, },\r
+            { 2139, 1858,  949, 1645,  347, 2594, 2571,    0,  678, 2442, },\r
+            { 2182, 1737, 1021, 1891,  959, 2734, 2408,  678,    0, 2329, },\r
+            {  543,  597, 1494, 1220, 2300,  923,  205, 2442, 2329,    0, },\r
+        });\r
+        mds = new MultiDimensionalScalingMethod(matrix);\r
+\r
+        mds.getCoordinateMatrix().print(8, 4);\r
+        MultiDimensionalScalingViewer viewer = new MultiDimensionalScalingViewer(mds, labels);\r
+        viewer.setShowLabel(true);\r
+        JFrame f = new JFrame();\r
+        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\r
+        f.getContentPane().add(viewer, BorderLayout.CENTER);\r
+        f.pack();\r
+        f.setVisible(true);\r
+    }\r
+}\r
diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/PointComponent.java b/src/main/java/jp/naist/se/stigmata/ui/swing/graph/PointComponent.java
new file mode 100755 (executable)
index 0000000..f08884c
--- /dev/null
@@ -0,0 +1,70 @@
+package jp.naist.se.stigmata.ui.swing.graph;\r
+\r
+import java.awt.Color;\r
+import java.awt.Graphics;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+\r
+import javax.swing.JLabel;\r
+\r
+class PointComponent extends JLabel{\r
+    private static final long serialVersionUID = 6945871049990818511L;\r
+    public static final Color DEFAULT_OVER_COLOR = Color.BLUE;\r
+    private String label;\r
+    private boolean entered = false;\r
+    private Color overColor = DEFAULT_OVER_COLOR;\r
+\r
+    public PointComponent(String label, double x, double y){\r
+        this(label);\r
+\r
+        setToolTipText(String.format("%s [%g, %g]", label, x, y));\r
+    }\r
+\r
+    public PointComponent(String label){\r
+        this.label = label;\r
+        setSize(10, 10);\r
+        setMinimumSize(getSize());\r
+        setMaximumSize(getSize());\r
+        setPreferredSize(getSize());\r
+\r
+        addMouseListener(new MouseAdapter(){\r
+            @Override\r
+            public void mouseEntered(MouseEvent e){\r
+                entered = true;\r
+                updateUI();\r
+            }\r
+\r
+            @Override\r
+            public void mouseExited(MouseEvent e){\r
+                entered = false;\r
+                updateUI();\r
+            }\r
+        });\r
+        setToolTipText(this.label);\r
+    }\r
+\r
+    public String getLabel(){\r
+        return label;\r
+    }\r
+\r
+    @Override\r
+    public void paintComponent(Graphics g){\r
+        super.paintComponent(g);\r
+        if(entered){\r
+            g.setColor(getOverColor());\r
+            g.fillOval(0, 0, 10, 10);\r
+        }\r
+        else{\r
+            g.setColor(getForeground());\r
+            g.fillOval(4, 4, 3, 3);\r
+        }\r
+    }\r
+\r
+    public Color getOverColor(){\r
+        return overColor;\r
+    }\r
+\r
+    public void setOverColor(Color overColor){\r
+        this.overColor = overColor;\r
+    }\r
+}\r
diff --git a/src/main/resources/resources/images/map.png b/src/main/resources/resources/images/map.png
new file mode 100755 (executable)
index 0000000..f90ef25
Binary files /dev/null and b/src/main/resources/resources/images/map.png differ
index 61422fb..5ad623f 100755 (executable)
@@ -22,8 +22,11 @@ compare.tab.tooltip=Compare birthmarks <{1}> and <{2}> by {0}.
 comparedetail.tab.label=Compare Detail {0}\r
 comparedetail.tab.tooltip=Compare birthmarks between {1} and {2} by {0}.\r
 \r
-graph.tab.label=Similarity Graph {0}\r
-graph.tab.tooltip=Similarity distribution graph.\r
+similaritygraph.tab.label=Similarity Graph {0}\r
+similaritygraph.tab.tooltip=Similarity distribution graph.\r
+\r
+mappinggraph.tab.label=MDS Graph {0}\r
+mappinggraph.tab.tooltip=Plot classes based on MDS\r
 \r
 store.extensions=xml, csv\r
 store.description=Sotre birthmarks as {0}\r
@@ -150,7 +153,7 @@ extract.button.tooltip=Extract birthmarks from class files in specified jar file
 extract.button.icon=arrow_out.png\r
 \r
 compare.button.label=Compare\r
-compare.button.tooltip=Compare class files in jar files by specified comparison method with selected birthmarks\r
+compare.button.tooltip=Compare class files in jar files by round robin comparison with selected birthmarks\r
 compare.button.icon=arrow_right_left.png\r
 \r
 #compareguess.button.label=Compare Pair (guess)\r
@@ -213,6 +216,13 @@ savecomparison.button.icon=disk.png
 showgraph.button.label=Graph\r
 showgraph.button.tooltip=Show distribution graph of birthmark similarity.\r
 showgraph.button.icon=chart_curve.png\r
+showgraph.menu.label=Graph\r
+showgraph.menu.tooltip=Show distribution graph of birthmark similarity.\r
+showgraph.menu.icon=chart_curve.png\r
+\r
+mdsmap.menuitem.label=Distance Mapping\r
+mdsmap.menuitem.tooltip=Mapping all classes into 2-d plane.\r
+mdsmap.menuitem.icon=map.png\r
 \r
 ################################################\r
 #BirthmarksViewPane\r
@@ -248,6 +258,8 @@ changecolor.button.label=Change Color...
 changecolor.button.icon=color_swatch.png\r
 changecolor.title=Switch Color\r
 \r
+showlabel.button.label=Show label\r
+\r
 comparepair.tab.label=Compare Pair {0}\r
 comparepair.tab.tooltip=Compare pair between {1} and {2} by {0} birthmark.\r
 comparepair.target1.label=Target 1\r
@@ -260,10 +272,25 @@ guessedpair.label=Guessed pair
 specifiedpair.label=Specified pair...\r
 roundrobin.filtering.label=Filtering round robin...\r
 \r
-comparison.methods=${roundrobin.label},${guessedpair.label},${specifiedpair.label},${roundrobin.filtering.label}\r
+roundrobin.button.label=Compare round robin\r
+roundrobin.button.tooltip=Compare birthmarks by round robin comparison from selected files\r
+roundrobin.button.icon=arrow_right_left.png\r
+\r
+guessedpair.button.label=Compare guessed pair\r
+guessedpair.button.tooltip=Compare birthmarks by guessed pair\r
+guessedpair.button.icon=arrow_right_left.png\r
+\r
+roundrobin.menuitem.label=${roundrobin.button.label}\r
+guessedpair.menuitem.label=${guessedpair.button.label}\r
+specifiedpair.menuitem.label=Comparing specified pair...\r
+roundrobin.filtering.menuitem.label=Filtering round robin comparison pair...\r
+\r
+comparison.methods=roundrobin,guessedpair,specifiedpair,roundrobin.filtering\r
+comparison.methods.inroundrobinresult=guessedpair,specifiedpair,roundrobin.filtering\r
+\r
 result.border=Comparison Result\r
 eachbirthmarksimilarity.border=Each birthmark similarities\r
-comparison.methods.inroundrobinresult=${guessedpair.label},${specifiedpair.label}\r
+\r
 comparisonresultset.tab.label=Compare Pair {0}\r
 comparisonresultset.tab.tooltip=Comparison pair.\r
 \r
index 8e83b2b..72a1c01 100755 (executable)
@@ -142,7 +142,7 @@ public class SmcBirthmarkExtractorTest{
 \r
         Birthmark birthmark = array[0].getBirthmark("smc");\r
         Assert.assertEquals("smc", birthmark.getType());\r
-        Assert.assertEquals(10, birthmark.getElementCount());\r
+        Assert.assertEquals(25, birthmark.getElementCount());\r
 \r
         BirthmarkElement[] elements = birthmark.getElements();\r
         for(int i = 0; i < elements.length; i++){\r
@@ -151,15 +151,37 @@ public class SmcBirthmarkExtractorTest{
                 elements[i].getClass().getName()\r
             );\r
         }\r
-        Assert.assertEquals("java.lang.Object#<init>", elements[0].toString());\r
-        Assert.assertEquals("java.util.Arrays#asList", elements[1].toString());\r
-        Assert.assertEquals("java.util.Arrays#asList", elements[2].toString());\r
-        Assert.assertEquals("java.lang.Object#<init>", elements[3].toString());\r
-        Assert.assertEquals("java.util.Arrays#asList", elements[4].toString());\r
-        Assert.assertEquals("java.util.Arrays#asList", elements[5].toString());\r
-        Assert.assertEquals("java.util.List#size",     elements[6].toString());\r
-        Assert.assertEquals("java.util.List#size",     elements[7].toString());\r
-        Assert.assertEquals("java.util.List#size",     elements[8].toString());\r
-        Assert.assertEquals("java.util.List#size",     elements[9].toString());\r
+        // <init>(BirthmarkSet[], BirthmarkContext, boolean)\r
+        Assert.assertEquals("java.lang.Object#<init>",      elements[ 0].toString());\r
+        Assert.assertEquals("java.util.Arrays#asList",      elements[ 1].toString());\r
+        Assert.assertEquals("java.util.Arrays#asList",      elements[ 2].toString());\r
+        Assert.assertEquals("java.lang.Object#<init>",      elements[ 3].toString());\r
+\r
+        // <init>(BirthmarkSet[], BirthmarkSet[], BirthmarkContext, boolean)\r
+        Assert.assertEquals("java.util.Arrays#asList",      elements[ 4].toString());\r
+        Assert.assertEquals("java.util.Arrays#asList",      elements[ 5].toString());\r
+\r
+        // setCompareSamePair\r
+        Assert.assertEquals("java.util.List#size",          elements[ 6].toString());\r
+        Assert.assertEquals("java.util.List#size",          elements[ 7].toString());\r
+        Assert.assertEquals("java.util.List#size",          elements[ 8].toString());\r
+        Assert.assertEquals("java.util.List#size",          elements[ 9].toString());\r
+\r
+        // getComparisonSources\r
+        Assert.assertEquals("java.util.HashMap#<init>",     elements[10].toString());\r
+        Assert.assertEquals("java.util.List#iterator",      elements[11].toString());\r
+        Assert.assertEquals("java.util.Iterator#next",      elements[12].toString());\r
+        Assert.assertEquals("java.util.Map#put",            elements[13].toString());\r
+        Assert.assertEquals("java.util.Iterator#hasNext",   elements[14].toString());\r
+        Assert.assertEquals("java.util.List#iterator",      elements[15].toString());\r
+        Assert.assertEquals("java.util.Iterator#next",      elements[16].toString());\r
+        Assert.assertEquals("java.util.Map#put",            elements[17].toString());\r
+        Assert.assertEquals("java.util.Iterator#hasNext",   elements[18].toString());\r
+        Assert.assertEquals("java.util.Map#size",           elements[19].toString());\r
+        Assert.assertEquals("java.util.Map#entrySet",       elements[20].toString());\r
+        Assert.assertEquals("java.util.Set#iterator",       elements[21].toString());\r
+        Assert.assertEquals("java.util.Iterator#next",      elements[22].toString());\r
+        Assert.assertEquals("java.util.Map$Entry#getValue", elements[23].toString());\r
+        Assert.assertEquals("java.util.Iterator#hasNext",   elements[24].toString());\r
     }\r
 }\r
index de304fe..99a22ea 100755 (executable)
@@ -76,12 +76,17 @@ public class UCBirthmarkExtractorTest{
 \r
         Birthmark birthmark = array[0].getBirthmark("uc");\r
         Assert.assertEquals("uc", birthmark.getType());\r
-        Assert.assertEquals(4, birthmark.getElementCount());\r
+        Assert.assertEquals(9, birthmark.getElementCount());\r
 \r
         BirthmarkElement[] elements = birthmark.getElements();\r
-        Assert.assertEquals("java.lang.Object",   elements[0].getValue());\r
-        Assert.assertEquals("java.util.Arrays",   elements[1].getValue());\r
-        Assert.assertEquals("java.util.Iterator", elements[2].getValue());\r
-        Assert.assertEquals("java.util.List",     elements[3].getValue());\r
+        Assert.assertEquals("java.lang.Object",    elements[0].getValue());\r
+        Assert.assertEquals("java.net.URL",        elements[1].getValue());\r
+        Assert.assertEquals("java.util.Arrays",    elements[2].getValue());\r
+        Assert.assertEquals("java.util.HashMap",   elements[3].getValue());\r
+        Assert.assertEquals("java.util.Iterator",  elements[4].getValue());\r
+        Assert.assertEquals("java.util.List",      elements[5].getValue());\r
+        Assert.assertEquals("java.util.Map",       elements[6].getValue());\r
+        Assert.assertEquals("java.util.Map$Entry", elements[7].getValue());\r
+        Assert.assertEquals("java.util.Set",       elements[8].getValue());\r
     }\r
 }\r