001 /* 002 * Created by IntelliJ IDEA. 003 * User: Wei Wang 004 * Date: 2002-9-6 005 * Time: 15:00:07 006 * To change template for new class use 007 * Code Style | Class Templates options (Tools | IDE Options). 008 */ 009 package EVolve.util.overlappers; 010 011 import java.awt.Color; 012 import java.awt.Component; 013 import java.awt.event.ActionEvent; 014 import java.awt.event.ActionListener; 015 import java.awt.event.KeyEvent; 016 import java.awt.event.MouseAdapter; 017 import java.awt.event.MouseEvent; 018 import java.awt.event.MouseMotionAdapter; 019 import java.awt.image.BufferedImage; 020 import java.io.File; 021 import java.io.IOException; 022 import java.util.ArrayList; 023 import java.util.HashSet; 024 025 import javax.imageio.ImageIO; 026 import javax.imageio.ImageWriter; 027 import javax.swing.JDialog; 028 import javax.swing.JFileChooser; 029 import javax.swing.JMenu; 030 import javax.swing.JMenuItem; 031 import javax.swing.JPanel; 032 import javax.swing.JPopupMenu; 033 import javax.swing.JScrollPane; 034 035 import EVolve.Scene; 036 import EVolve.data.Entity; 037 import EVolve.data.EntityComparator; 038 import EVolve.exceptions.NoDataPlotException; 039 import EVolve.util.Magnifier; 040 import EVolve.visualization.AutoImage; 041 import EVolve.visualization.AxesPanel; 042 import EVolve.visualization.Dimension; 043 import EVolve.visualization.ReferenceDimension; 044 import EVolve.visualization.Visualization; 045 046 public abstract class OverlapVisualization { 047 protected JDialog dialog; 048 protected JScrollPane panel; 049 protected AxesPanel canvas; 050 protected ArrayList visualizationList; 051 private String xAxisName,yAxisName; 052 protected EVolve.Window window; 053 protected long xMax; 054 protected ArrayList colorList; 055 protected HashSet[] fullEntitySet; 056 protected boolean noEntityAvailable; 057 058 private JPopupMenu popup; 059 private JMenu menuSort; 060 private JMenuItem[][] itemSort; 061 private JMenu[] menuDimension; 062 private JMenuItem itemSave, itemScale; 063 private ArrayList refLocation; 064 private Magnifier magnifier; 065 private AutoImage overlappedImage; 066 private boolean shift_pressed; 067 068 069 public abstract void createDialog(); 070 071 public abstract boolean isOverlapable(Visualization visualToBeOverlapped); 072 073 public abstract void overlappedVisualize(); 074 075 public OverlapVisualization() { 076 visualizationList = new ArrayList(); 077 078 fullEntitySet = new HashSet[2]; 079 fullEntitySet[0] = null; 080 fullEntitySet[1] = null; 081 noEntityAvailable = false; 082 shift_pressed = false; 083 084 panel = createPanel(); 085 addPopupTrigger(canvas); 086 } 087 088 public void showWindow() { 089 createDialog(); 090 Scene.getUIManager().showDialog(dialog, dialog.getWidth(), dialog.getHeight()); 091 } 092 093 public void newOverlappedVisualization(OverlapVisualization oVisual) { 094 Visualization visual = (Visualization)visualizationList.get(0); 095 xAxisName = visual.getDimension()[0].getName(); 096 yAxisName = visual.getDimension()[1].getName(); 097 window = Scene.getUIManager().addOverlappedVisualization(oVisual); 098 createMenu(); 099 } 100 101 public JPanel getPanel() { 102 return canvas; 103 } 104 105 private JScrollPane createPanel() { 106 canvas = new AxesPanel(AxesPanel.Axis_Enabled | AxesPanel.Flip_Image | AxesPanel.Scale_Image); 107 JScrollPane returnVal = new JScrollPane(canvas); 108 109 magnifier = new Magnifier(true); 110 canvas.addMouseMotionListener(new MouseMotionAdapter() { 111 public void mouseMoved(MouseEvent e) { 112 if (e.isShiftDown()) shift_pressed = true; 113 else shift_pressed = false; 114 115 if (e.isAltDown()) { 116 int x = canvas.getImageX(e.getX()); 117 int y = canvas.getImageY(e.getY()); 118 magnifier.convertMousePosition(canvas); 119 magnifier.showWindow(canvas.getSubImage(x,y)); 120 canvas.drawZoomingArea(e.getX(),e.getY()); 121 } 122 mMoved(e.getX(), e.getY()); 123 } 124 }); 125 126 canvas.addMouseMotionListener(new MouseMotionAdapter() { 127 public void mouseDragged(MouseEvent e) { 128 mMoved(e.getX(), e.getY()); 129 } 130 }); 131 132 return returnVal; 133 } 134 135 private void mMoved(int x, int y) { 136 int xIndex = canvas.getImageX(x); 137 int yIndex = canvas.getImageY(y); 138 139 if (noEntityAvailable) { 140 Scene.setStatus("No entity information available when temporal viz overlapped."); 141 } else { 142 try { 143 if (shift_pressed && (getOverlappedSortedColor(xIndex,yIndex)==null)) { 144 Scene.setStatus(" "); 145 return; 146 } 147 148 if (fullEntitySet[0].size() == 0) { 149 String hint = getEntityName(1,yIndex); 150 if (hint != null) { 151 Scene.setStatus(hint); 152 } 153 } else { 154 String xHint = getEntityName(0,xIndex), yHint = getEntityName(1, yIndex); 155 156 if ((xHint != null) && (yHint != null)) { 157 Scene.setStatus("X: " + xHint + " Y: " + yHint); 158 } 159 } 160 } catch (Exception e) { 161 System.out.println("Exception"); 162 } 163 } 164 } 165 166 private void createMenu() { 167 popup = new JPopupMenu(); 168 169 menuSort = new JMenu("Sort"); 170 menuSort.setMnemonic(KeyEvent.VK_S); 171 menuSort.setEnabled(false); 172 popup.add(menuSort); 173 174 ArrayList tempList = new ArrayList(); 175 Visualization visual = (Visualization)visualizationList.get(visualizationList.size()-1); 176 EVolve.visualization.Dimension [] dimension = visual.getDimension(); 177 refLocation = new ArrayList(); 178 for (int i = 0; i < dimension.length; i++) { 179 if (dimension[i] instanceof ReferenceDimension) { 180 tempList.add(new Integer(i)); 181 refLocation.add(new Integer(i)); 182 } 183 } 184 185 ReferenceDimension[] referenceDimension = new ReferenceDimension[tempList.size()]; 186 menuDimension = new JMenu[tempList.size()]; 187 itemSort = new JMenuItem[tempList.size()][]; 188 for (int i = 0; i < tempList.size(); i++) { 189 int j = ((Integer)(tempList.get(i))).intValue(); 190 referenceDimension[i] = (ReferenceDimension)(dimension[j]); 191 menuDimension[i] = new JMenu(visual.getDefinition().getDimensionDefinition()[j].getName()); 192 menuSort.add(menuDimension[i]); 193 } 194 195 for (int i = 0; i < referenceDimension.length; i++) { 196 ArrayList comparatorList = referenceDimension[i].getComparator(); 197 itemSort[i] = new JMenuItem[comparatorList.size()]; 198 menuDimension[i].removeAll(); 199 for (int j = 0; j < itemSort[i].length; j++) { 200 itemSort[i][j] = new JMenuItem(((EntityComparator)(comparatorList.get(j))).getName()); 201 itemSort[i][j].addActionListener(new ActionListener() { 202 public void actionPerformed(ActionEvent e) { 203 selectComparator(e); 204 } 205 }); 206 menuDimension[i].add(itemSort[i][j]); 207 } 208 } 209 210 itemScale = new JMenuItem("Restore"); 211 itemScale.setMnemonic(KeyEvent.VK_R); 212 itemScale.addActionListener(new ActionListener() { 213 public void actionPerformed(ActionEvent e) { 214 if (e.getActionCommand().charAt(0) == 'F') { 215 canvas.scaleImage(true); 216 itemScale.setText("Restore"); 217 itemScale.setActionCommand("Restore"); 218 itemScale.setMnemonic(KeyEvent.VK_R); 219 } else { 220 canvas.scaleImage(false); 221 itemScale.setText("Fit Window"); 222 itemScale.setActionCommand("Fit Window"); 223 itemScale.setMnemonic(KeyEvent.VK_F); 224 } 225 canvas.repaint(); 226 } 227 }); 228 itemScale.setSelected(true); 229 popup.add(itemScale); 230 231 itemSave = new JMenuItem("Save..."); 232 itemSave.setMnemonic(KeyEvent.VK_V); 233 itemSave.addActionListener(new ActionListener() { 234 public void actionPerformed(ActionEvent e) { 235 save(); 236 } 237 }); 238 popup.add(itemSave); 239 } 240 241 protected void showPopup(MouseEvent e) { 242 popup.show(e.getComponent(), e.getX(), e.getY()); 243 } 244 245 protected void addPopupTrigger(Component component) { 246 component.addMouseListener(new MouseAdapter() { 247 public void mouseReleased(MouseEvent e) { 248 if (e.isPopupTrigger()) { 249 showPopup(e); 250 } 251 } 252 253 public void mousePressed(MouseEvent e) { 254 if (e.isPopupTrigger()) { 255 showPopup(e); 256 } 257 } 258 }); 259 } 260 261 protected void enableSortMenu() { 262 menuSort.setEnabled(true); 263 Scene.getUIManager().enableFileMenus(); 264 } 265 266 protected String getColorHex(Color color) { 267 String returnVal = Integer.toHexString(color.getBlue()); 268 if (returnVal.length() < 2) { 269 returnVal = "0" + returnVal; 270 } 271 returnVal = Integer.toHexString(color.getGreen()) + returnVal; 272 if (returnVal.length() < 4) { 273 returnVal = "0" + returnVal; 274 } 275 returnVal = Integer.toHexString(color.getRed()) + returnVal; 276 if (returnVal.length() < 6) { 277 returnVal = "0" + returnVal; 278 } 279 280 return returnVal; 281 } 282 283 private void save() { 284 BufferedImage image = new BufferedImage(canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_INT_RGB); 285 canvas.paint(image.getGraphics()); 286 ImageWriter writer = (ImageWriter)(ImageIO.getImageWritersByFormatName("png").next()); 287 288 JFileChooser fc = new JFileChooser(Scene.getUIManager().getLastResultDir()); 289 290 if (fc.showSaveDialog(Scene.getFrame()) == JFileChooser.APPROVE_OPTION) { 291 File file = fc.getSelectedFile(); 292 Scene.getUIManager().setLastResultDir(file.getPath()); 293 try { 294 writer.setOutput(ImageIO.createImageOutputStream(file)); 295 writer.write(image); 296 } catch (IOException e) {} 297 } 298 299 } 300 301 public AutoImage getSortImage() { 302 Visualization visual = null; 303 overlappedImage = new AutoImage(); 304 ReferenceDimension sortedDimension[] = new ReferenceDimension[2]; 305 306 xMax = Integer.MIN_VALUE; 307 308 for (int i=0; i<visualizationList.size(); i++) { 309 AutoImage image; 310 sortedDimension[0] = null; 311 sortedDimension[1] = null; 312 313 visual = (Visualization)visualizationList.get(i); 314 315 for (int j=0; j<2; j++) { 316 Dimension dim = visual.getDimension()[j]; 317 if (dim instanceof ReferenceDimension) 318 sortedDimension[j] = (ReferenceDimension)dim; 319 } 320 image = visual.getImage().getSortedImage(sortedDimension[0],sortedDimension[1]); 321 int w = image.getW(); 322 int h = image.getH(); 323 324 for (int j=0; j<w; j++) { 325 for (int k=0; k<h; k++) { 326 if (image.getColor(j,k) == null) continue; 327 328 if (overlappedImage.getColor(j,k) == null ) 329 overlappedImage.setColor(j,k,image.getColor(j,k)); 330 else 331 overlappedImage.setColor(j,k,new Color(153,0,153)); 332 } 333 } 334 visual.visualize(); 335 if (xMax < visual.getxMax()) xMax = visual.getxMax(); 336 } 337 338 String[] comparatorName = new String[2]; 339 for (int i=0; i<2; i++) { 340 if (visual.getDimension()[i] instanceof ReferenceDimension) { 341 comparatorName[i] = ((ReferenceDimension)visual.getDimension()[i]).getSelectedComparatorName(); 342 } else { 343 comparatorName[i] = ""; 344 } 345 } 346 347 visual = (Visualization)visualizationList.get(0); 348 349 canvas.setName(timeHeader(visual.getDimension()[0]) + xAxisName + " (" + ((fullEntitySet[0].size() == 0) ? xMax : fullEntitySet[0].size())+ 350 ((comparatorName[0].length()==0) ? "" : ", "+ comparatorName[0]) + ")", 351 timeHeader(visual.getDimension()[1]) + yAxisName + " (" + fullEntitySet[1].size() + 352 ((comparatorName[1].length()==0) ? "" : ", "+ comparatorName[1]) + ")"); 353 return overlappedImage; 354 } 355 356 public void sort() { 357 try { 358 canvas.setImage(getSortImage().getImage()); 359 canvas.repaint(); 360 } catch (NoDataPlotException e) { 361 Scene.showErrorMessage(e.getMessage()); 362 } 363 } 364 365 private void selectComparator(ActionEvent e) { 366 for (int i = 0; i < itemSort.length; i++) { 367 for (int j = 0; j < itemSort[i].length; j++) { 368 if (itemSort[i][j] == e.getSource()) { 369 if (itemSort[i][j].getText().equals("Temporal")) { 370 noEntityAvailable = true; 371 } else { 372 noEntityAvailable = false; 373 } 374 for (int k=0; k<visualizationList.size(); k++) { 375 Visualization visual = (Visualization)visualizationList.get(k); 376 ReferenceDimension ref = (ReferenceDimension)visual.getDimension()[((Integer)refLocation.get(i)).intValue()]; 377 ref.selectComparator(j); 378 } 379 sort(); 380 return; 381 } 382 } 383 } 384 } 385 386 public void unregisterOverlappedVisualization(Visualization visual) { 387 for (int i=0;i<visualizationList.size();i++) { 388 if (((Visualization)visualizationList.get(i)).getVisualizationID() == visual.getVisualizationID()) { 389 visualizationList.remove(i); 390 } 391 } 392 if (visualizationList.size() ==1) visualizationList.clear(); 393 } 394 395 private String getEntityName(int dim,int index) { 396 Entity entity = null; 397 for (int i=0; i<visualizationList.size(); i++) { 398 Visualization visual = (Visualization)visualizationList.get(i); 399 if (!(visual.getDimension()[dim] instanceof ReferenceDimension)) return null; 400 ReferenceDimension ref = (ReferenceDimension)visual.getDimension()[dim]; 401 entity = ref.getEntity(index); 402 if (entity != null) { 403 break; 404 } 405 } 406 407 return (entity == null) ? null : entity.getName(); 408 } 409 410 private Color getOverlappedSortedColor(int x, int y) { 411 Color returnVal = null; 412 ReferenceDimension sortedDimension[] = new ReferenceDimension[2]; 413 for (int i=0; i<visualizationList.size(); i++) { 414 Visualization visual = (Visualization)visualizationList.get(i); 415 for (int j=0; j<2; j++) { 416 Dimension dim = visual.getDimension()[j]; 417 if (dim instanceof ReferenceDimension) 418 sortedDimension[j] = (ReferenceDimension)dim; 419 } 420 returnVal = (Color)visual.getImage().getSortedColor(sortedDimension[0],sortedDimension[1],x,y); 421 if (returnVal != null) break; 422 } 423 424 return returnVal; 425 } 426 427 private String timeHeader(Dimension dim) { 428 String property[] = dim.getDataFilter().getProperty(); 429 430 if (property == null) return ""; 431 432 for (int i=0; i<property.length; i++) { 433 if (property[i].equals("time")) 434 return "Time - "; 435 } 436 return ""; 437 } 438 439 public void cleanup() { 440 fullEntitySet = null; 441 itemSort = null; 442 menuDimension = null; 443 magnifier.cleanup(); 444 } 445 }