package vishnu.testvis.sammon; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.Vector; import java.util.Enumeration; import vishnu.testvis.visual.*; import vishnu.testvis.object.*; import java.awt.image.*; class ClusterPanel extends JPanel { Image offScreen=null; Dimension offScreenSize; Graphics2D offGraphics; private SammCluster currentCluster; private final int RADIUS = 30; private SammCluster drawnCluster; private GraphicalPane parentSammon; boolean firstTime = true; Graphics2D big; BufferedImage bi; Rectangle area; Dimension d = null; int locationID = -1; JPopupMenu[] popups; JPopupMenu popup; Vishnu _currentMain; DataManager dm; public ClusterPanel(Vishnu currentMain, GraphicalPane parent) { this.parentSammon = parent; _currentMain=currentMain; dm = _currentMain.dataManager; popup = new JPopupMenu(); popup.setVisible(false); add(popup); setOpaque(true); setPreferredSize(new Dimension(600,600)); setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(20,20,20,20), BorderFactory.createLoweredBevelBorder())); addComponentListener( new ComponentAdapter() { public void componentResized(ComponentEvent evt) { if( parentSammon.dataMan != null && parentSammon.dataMan.getDocCount()>0){ repaint(); } } } ); addMouseMotionListener( new MouseMotionAdapter() { public void mouseMoved(MouseEvent mouseEvent) { int docsInSelectedClusters=0; if( parentSammon.dataMan == null) return; int oldLocationID = locationID; Vector clusters = parentSammon.dataMan.getSammonClusters(); if (clusters == null) return; locationID = -1; for (int i = clusters.size()-1 ; i >= 0 ; i--) { SammCluster cluster = (SammCluster) clusters.elementAt(i); int x = (int) (cluster.getX()*(offScreenSize.width-2*RADIUS)) + RADIUS; int y = (int) (cluster.getY()*(offScreenSize.height-2*RADIUS)) +RADIUS; if (inCircle(mouseEvent,x,y,cluster.getDisplayedRadius())) { locationID = i; } if(cluster.getSelected()) docsInSelectedClusters+=cluster.documentIDs.size(); } if ((oldLocationID != locationID) && (oldLocationID != -1)) popup.setVisible(false); if (locationID != -1) { if (locationID != oldLocationID) { popup.removeAll(); String[] allWords = parentSammon.dataMan.getWords(); currentCluster = (SammCluster) clusters.elementAt(locationID); String str = currentCluster.getSize() + " documents"; JMenuItem menuItem = new JMenuItem(str); popup.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { drawnCluster = currentCluster; updateHLinkPanel(); repaint(); //update } }); popup.add(new JPopupMenu.Separator()); menuItem = new JMenuItem("Drill down"); if(!currentCluster.getSelected()) docsInSelectedClusters+=currentCluster.documentIDs.size(); if(docsInSelectedClusters<7)menuItem.setEnabled(false); else menuItem.setEnabled(true); // for drilldown menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ActionEvent) { Vector idVector; SammCluster thisCluster = getCurrentCluster(); int theIndex = thisCluster.getWords()[0]; String drillWords = new String(parentSammon.dataMan.getWords()[theIndex]); for( int i = 1; i < thisCluster.getWords().length; i++ ) { theIndex = thisCluster.getWords()[i]; drillWords += " " + parentSammon.dataMan.getWords()[theIndex]; } Vector clusterPl = parentSammon.dataMan.getSammonClusters(); Vector idVect = (Vector)thisCluster.getIDs().clone(); thisCluster.setSelected(true); for (int i = clusterPl.size()-1; i >= 0; i--) { SammCluster cluster = (SammCluster) clusterPl.elementAt(i); if (!cluster.equals(thisCluster) && cluster.getSelected()) idVect.addAll(cluster.getIDs()); } if(idVect.size()>6) { parentSammon.drillDown(idVect); currentCluster=null; drawnCluster=null; //update(); repaint(); } } }); popup.add(menuItem); if(!currentCluster.getSelected()) menuItem = new JMenuItem("Select"); else menuItem = new JMenuItem("Deselect"); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ActionEvent) { SammCluster cluster = getCurrentCluster(); cluster.setSelected(!cluster.getSelected()); //update(); repaint(); } }); popup.add(menuItem); int[] words = currentCluster.getWords(); popup.add(new JPopupMenu.Separator()); for(int c=0;c<4;c++) { int index = words[c]; if (index>= 0)menuItem = new JMenuItem(allWords[index]); popup.add(menuItem); menuItem.setEnabled(false); } popup.validate(); popup.setVisible(true); } popup.show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY()); mouseEvent.consume(); } } }); setVisible(true); } public SammCluster getCurrentCluster() {return currentCluster;} public void paint(Graphics g) { update(g); } public boolean inCircle(MouseEvent mouseEvent, int x, int y, int radius) { int dx2 = (mouseEvent.getX()-x)*(mouseEvent.getX()-x); int dy2 = (mouseEvent.getY()-y)*(mouseEvent.getY()-y); return (dx2 + dy2 < radius*radius); } private void drawFlag(Graphics g,int x, int y) { g.drawLine(x,y,x,y-12); int [] xs = new int[3]; int [] ys = new int[3]; xs[0]=x;xs[1]= x+10; xs[2]=x; ys [0]=y-12; ys[1]=y-7;ys[2]=y-2; g.fillPolygon(xs,ys,3); } public void update(Graphics g) { Graphics2D g2 = (Graphics2D)g; Dimension d = getSize(); offScreenSize = d; int w = d.width; int h = d.height; area = new Rectangle(d); bi = (BufferedImage)createImage(w, h); offGraphics = bi.createGraphics(); area.setLocation(w/2-50, h/2-25); BasicStroke myStroke = new BasicStroke(2,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER); offGraphics.setColor(Color.white); /*offGraphics.clearRect(0, 0, area.width, area.height); offGraphics.draw(area); offGraphics.fill(area);*/ offGraphics.fillRect(0,0,d.width,d.height); if( parentSammon.dataMan.getDocCount()<1) return; Vector clusters = parentSammon.dataMan.getSammonClusters(); if (clusters.size()==0) return; double minNumDocs = ((SammCluster) clusters.elementAt(0)).getSize(); double maxNumDocs = ((SammCluster) clusters.elementAt(clusters.size()-1)).getSize(); double deltaNumDocs = maxNumDocs - minNumDocs; for (int i = clusters.size()-1; i >= 0; i--) { SammCluster cluster = (SammCluster) clusters.elementAt(i); int x = (int) (cluster.getX()*(offScreenSize.width-2*RADIUS)) + RADIUS; int y = (int) (cluster.getY()*(offScreenSize.height-2*RADIUS)) + RADIUS; // Value between 0 and 1 representing the cluster (0 is the smaller cluster and 1 is the bigger one double clusterWeight = (cluster.getSize() - minNumDocs)/ deltaNumDocs; offGraphics.setColor(new Color((float)0.7, (float)0.7, (float)1)); cluster.setDisplayedRadius(RADIUS-(int)(RADIUS*(1-clusterWeight)/2)); myStroke = new BasicStroke(3,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER); offGraphics.setStroke(myStroke); offGraphics.fillOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); offGraphics.setColor(new Color((float)0,(float)0, (float)0.7)); offGraphics.drawOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); if (cluster.getSelected()) drawFlag(offGraphics,x,y-cluster.getDisplayedRadius()); if (cluster.equals(this.drawnCluster)) { offGraphics.setColor(new Color((float)0.3, (float)0.3, (float)1)); offGraphics.fillOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); offGraphics.setColor(new Color((float)0, (float)0, (float)0.7)); offGraphics.drawOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); } } int i = clusters.size(); Font normal = new Font("Courier",Font.PLAIN,16); Font bold = new Font("Courier",Font.BOLD,16); for (Enumeration enum = clusters.elements() ; enum.hasMoreElements();) { SammCluster cluster = (SammCluster) enum.nextElement(); int x = (int) (cluster.getX()*(offScreenSize.width-2*RADIUS)) + RADIUS; int y = (int) (cluster.getY()*(offScreenSize.height-2*RADIUS)) + RADIUS; offGraphics.setFont(bold); offGraphics.setColor(new Color((float)0, (float)0,(float)0.4)); FontMetrics fm = offGraphics.getFontMetrics(); int theIndex = cluster.getWords()[0]; String theWord = parentSammon.dataMan.getWords()[theIndex]; int width = fm.stringWidth(theWord); offGraphics.drawString(theWord,x-(width/2),y+5); i--; } g2.drawImage(bi,0,0,this); } public void update() { /* Dimension d = getSize(); offScreenSize = d; offScreen = createImage(d.width,d.height); offGraphics = (Graphics2D)offScreen.getGraphics(); offGraphics.setColor(Color.white); offGraphics.fillRect(0,0,d.width,d.height); if( parentSammon.dataMan.getDocCount()<1) return; Vector clusters = parentSammon.dataMan.getSammonClusters(); double minNumDocs = ((SammCluster) clusters.elementAt(0)).getSize(); double maxNumDocs = ((SammCluster) clusters.elementAt(clusters.size()-1)).getSize(); double deltaNumDocs = maxNumDocs - minNumDocs; for (int i = clusters.size()-1; i >= 0; i--) { SammCluster cluster = (SammCluster) clusters.elementAt(i); int x = (int) (cluster.getX()*(offScreenSize.width-2*RADIUS)) + RADIUS; int y = (int) (cluster.getY()*(offScreenSize.height-2*RADIUS)) + RADIUS; // Value between 0 and 1 representing the cluster (0 is the smaller cluster and 1 is the bigger one double clusterWeight = (cluster.getSize() - minNumDocs)/ deltaNumDocs; //offGraphics.setColor(new Color((float) (1 - 0.7*clusterWeight),(float) 0, (float) 0)); offGraphics.setColor(new Color((float)0.7, (float)0.7, (float)1)); cluster.setDisplayedRadius(RADIUS-(int)(RADIUS*(1-clusterWeight)/2)); BasicStroke myStroke = new BasicStroke(3,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER); offGraphics.setStroke(myStroke); offGraphics.fillOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); offGraphics.setColor(new Color((float)0,(float)0, (float)0.7)); offGraphics.drawOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); if (cluster.getSelected()) drawFlag(offGraphics,x,y-cluster.getDisplayedRadius()); if (cluster.equals(this.drawnCluster)) { offGraphics.setColor(new Color((float)0.3, (float)0.3, (float)1)); offGraphics.fillOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); offGraphics.setColor(new Color((float)0, (float)0, (float)0.7)); offGraphics.drawOval(x - cluster.getDisplayedRadius(), y - cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius(), 2*cluster.getDisplayedRadius()); } } int i = clusters.size(); Font normal = new Font("Courier",Font.PLAIN,16); Font bold = new Font("Courier",Font.BOLD,16); for (Enumeration enum = clusters.elements() ; enum.hasMoreElements();) { SammCluster cluster = (SammCluster) enum.nextElement(); int x = (int) (cluster.getX()*(offScreenSize.width-2*RADIUS)) + RADIUS; int y = (int) (cluster.getY()*(offScreenSize.height-2*RADIUS)) + RADIUS; offGraphics.setFont(bold); offGraphics.setColor(new Color((float)0, (float)0,(float)0.4)); FontMetrics fm = offGraphics.getFontMetrics(); int theIndex = cluster.getWords()[0]; String theWord = parentSammon.dataMan.getWords()[theIndex]; int width = fm.stringWidth(theWord); offGraphics.drawString(theWord,x-(width/2),y+5); i--; }*/ repaint(); } private void updateHLinkPanel() { if( parentSammon.dataMan==null) return; if (locationID != -1) { Vector clusters = parentSammon.dataMan.getSammonClusters(); SammCluster selectedCluster = (SammCluster) clusters.elementAt(locationID); ClusterObj cObj = selectedCluster.getClusterObj(); String htmlDescription = cObj.formatDocs(); parentSammon.hLinkPanel.setText(htmlDescription); parentSammon.keywordPanel.update(cObj); } } }