1 19 package org.lucane.applications.whiteboard.gui; 20 21 import java.awt.event.ActionEvent ; 22 import java.awt.image.BufferedImage ; 23 import java.io.File ; 24 import java.io.IOException ; 25 import java.net.URL ; 26 import java.util.ArrayList ; 27 import java.util.Date ; 28 import java.util.Hashtable ; 29 import java.util.Iterator ; 30 import java.util.Map ; 31 32 import javax.imageio.ImageIO ; 33 import javax.swing.AbstractAction ; 34 import javax.swing.Action ; 35 import javax.swing.JButton ; 36 import javax.swing.JFileChooser ; 37 import javax.swing.JToolBar ; 38 import javax.swing.event.UndoableEditListener ; 39 import javax.swing.filechooser.FileFilter ; 40 41 import org.jgraph.JGraph; 42 import org.jgraph.event.GraphModelListener; 43 import org.jgraph.graph.AttributeMap; 44 import org.jgraph.graph.DefaultGraphCell; 45 import org.jgraph.graph.DefaultGraphModel; 46 import org.jgraph.graph.GraphModel; 47 import org.jgraph.graph.ParentMap; 48 import org.jgraph.util.JGraphUtilities; 49 import org.lucane.applications.whiteboard.WhiteBoard; 50 import org.lucane.applications.whiteboard.graph.DefaultGraphModelFileFormatXML; 51 import org.lucane.applications.whiteboard.graph.ModelUtils; 52 import org.lucane.applications.whiteboard.graph.MyGraph; 53 import org.lucane.applications.whiteboard.operations.GraphLayoutEdit; 54 import org.lucane.client.Client; 55 import org.lucane.client.widgets.DialogBox; 56 57 public class ActionToolBar extends JToolBar 58 { 59 private WhiteBoard plugin; 60 61 private ArrayList buttons; 62 63 public ActionToolBar(WhiteBoard plugin) 64 { 65 this.plugin = plugin; 66 this.buttons = new ArrayList (); 67 this.setFloatable(false); 68 69 addButton(new JButton (new FileOpenAction())); 70 addButton(true, new JButton (new FileSaveAction())); 71 addButton(true, new JButton (new ExportPngAction())); 72 addSeparator(); 73 74 addButton(new JButton (new BringToFrontAction())); 75 addButton(new JButton (new BringToBackAction())); 76 addSeparator(); 77 78 addButton(new JButton (new GroupAction())); 79 addButton(new JButton (new UnGroupAction())); 80 addSeparator(); 81 82 addButton(true, new JButton (new ZoomInAction())); 83 addButton(true, new JButton (new ZoomOutAction())); 84 addButton(true, new JButton (new ZoomDefaultAction())); 85 addSeparator(); 86 87 addButton(new JButton (new UndoAction())); 88 addButton(new JButton (new RedoAction())); 89 addSeparator(); 90 96 addButton(new JButton (new EditTextAction())); 97 addButton(new JButton (new DeleteAction())); 98 addSeparator(); 99 100 addButton(new LineWidthButton(plugin)); 101 addButton(new LinePatternButton(plugin)); 102 addButton(new ColorButton(plugin)); 103 addSeparator(); 104 } 105 106 private void addButton(JButton button) 107 { 108 addButton(false, button); 109 } 110 111 private void addButton(boolean stayEnabled, JButton button) 112 { 113 if(!stayEnabled) 114 this.buttons.add(button); 115 116 button.setFocusable(false); 117 add(button); 118 } 119 120 public void setEnabled(boolean enabled) 121 { 122 super.setEnabled(enabled); 123 124 Iterator i = buttons.iterator(); 125 while(i.hasNext()) 126 ((JButton )i.next()).setEnabled(enabled); 127 } 128 129 public String tr(String s) 130 { 131 return plugin.tr(s); 132 } 133 134 135 class FileOpenAction extends AbstractAction 136 { 137 public FileOpenAction() 138 { 139 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_open.png")); 140 putValue(Action.SHORT_DESCRIPTION, tr("tip.openFile")); 141 } 142 143 public void actionPerformed(ActionEvent ae) 144 { 145 final JFileChooser jfc = new JFileChooser (); 146 int returnVal = jfc.showOpenDialog(null); 147 if(returnVal == JFileChooser.APPROVE_OPTION) 148 { 149 150 final DefaultGraphModelFileFormatXML graphModelFileFormat = 151 DefaultGraphModelFileFormatXML.instance(); 152 153 Thread t = new Thread ("Read File Thread") { 154 155 public void run() { 156 try { 158 URL url = jfc.getSelectedFile().toURL(); 159 JGraph graph = new JGraph(new DefaultGraphModel()); 160 GraphModel model = graphModelFileFormat.read( 161 url, null, graph); 162 plugin.setGraphModel(model); 163 } catch (Exception e) { 164 DialogBox.error(tr("err.unableToOpenFile") + e); 165 e.printStackTrace(); 166 return; 167 } 168 } 169 }; 170 t.start(); 171 } 172 } 173 } 174 175 class FileSaveAction extends AbstractAction 176 { 177 public FileSaveAction() 178 { 179 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_save.png")); 180 putValue(Action.SHORT_DESCRIPTION, tr("tip.saveFile")); 181 } 182 183 public void actionPerformed(ActionEvent ae) 184 { 185 JFileChooser jfc = new JFileChooser (); 186 int returnVal = jfc.showSaveDialog(null); 187 if(returnVal == JFileChooser.APPROVE_OPTION) 188 { 189 MyGraph graph = plugin.getGraph(); 190 DefaultGraphModelFileFormatXML graphModelFileFormat = 191 DefaultGraphModelFileFormatXML.instance(); 192 193 try { 194 URL url = jfc.getSelectedFile().toURL(); 195 graphModelFileFormat.write(url, graph, graph.getModel()); 196 } catch (Exception e) { 197 DialogBox.error(tr("err.unableToSaveFile") + e); 198 e.printStackTrace(); 199 } 200 } 201 } 202 } 203 204 class ExportPngAction extends AbstractAction 205 { 206 public ExportPngAction() 207 { 208 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_save-png.png")); 209 putValue(Action.SHORT_DESCRIPTION, tr("tip.exportPng")); 210 } 211 212 public void actionPerformed(ActionEvent ae) 213 { 214 if(plugin.getGraphModel().getRootCount() == 0) 215 return; 216 217 JFileChooser jfc = new JFileChooser (); 218 jfc.setFileFilter(new FileFilter () { 219 public boolean accept(File f) { 220 return f.isDirectory() || f.getName().toLowerCase().endsWith(".png"); 221 } 222 223 public String getDescription() { 224 return "PNG images (*.png)"; 225 } 226 }); 227 int returnVal = jfc.showSaveDialog(null); 228 if(returnVal == JFileChooser.APPROVE_OPTION) 229 { 230 BufferedImage img = JGraphUtilities.toImage(plugin.getGraph(), 5); 231 try { 232 ImageIO.write(img, "png", jfc.getSelectedFile()); 233 } catch (IOException ioe) { 234 DialogBox.error(tr("err.unableToSaveFile") + ioe); 235 } 236 } 237 } 238 } 239 240 class EditTextAction extends AbstractAction 241 { 242 public EditTextAction() 243 { 244 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_edit.png")); 245 putValue(Action.SHORT_DESCRIPTION, tr("tip.editText")); 246 } 247 248 public void actionPerformed(ActionEvent ae) 249 { 250 MyGraph graph = plugin.getGraph(); 251 graph.startEditingAtCell(graph.getSelectionCell()); 252 } 253 } 254 255 class UndoAction extends AbstractAction 256 { 257 public UndoAction() 258 { 259 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_undo.png")); 260 putValue(Action.SHORT_DESCRIPTION, tr("tip.undo")); 261 } 262 263 public void actionPerformed(ActionEvent ae) 264 { 265 DefaultGraphModel model = (DefaultGraphModel)plugin.getGraphModel(); 266 synchronized(model) 267 { 268 GraphModelListener[] graphs = model.getGraphModelListeners(); 269 UndoableEditListener [] undos = model.getUndoableEditListeners(); 270 ModelUtils.removeListeners(model, graphs, undos); 271 272 if(plugin.getGraph().undo()) 273 { 274 try { 275 plugin.getClient().broadcastModel(Client.getInstance().getMyInfos().getName(), 276 plugin.getGraphModel()); 277 } catch (IOException e) { 278 DialogBox.error(tr("err.unableToBroadcastOperation") + e); 279 e.printStackTrace(); 280 } 281 } 282 283 ModelUtils.addListeners(model, graphs, undos); 284 } 285 } 286 } 287 288 class RedoAction extends AbstractAction 289 { 290 public RedoAction() 291 { 292 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_redo.png")); 293 putValue(Action.SHORT_DESCRIPTION, tr("tip.redo")); 294 } 295 296 public void actionPerformed(ActionEvent ae) 297 { 298 DefaultGraphModel model = (DefaultGraphModel)plugin.getGraphModel(); 299 synchronized(model) 300 { 301 GraphModelListener[] graphs = model.getGraphModelListeners(); 302 UndoableEditListener [] undos = model.getUndoableEditListeners(); 303 ModelUtils.removeListeners(model, graphs, undos); 304 305 if(plugin.getGraph().redo()) 306 { 307 try { 308 plugin.getClient().broadcastModel(Client.getInstance().getMyInfos().getName(), 309 plugin.getGraphModel()); 310 } catch (IOException e) { 311 DialogBox.error(tr("err.unableToBroadcastOperation") + e); 312 e.printStackTrace(); 313 } 314 } 315 316 ModelUtils.addListeners(model, graphs, undos); 317 } 318 } 319 } 320 321 class DeleteAction extends AbstractAction 322 { 323 public DeleteAction() 324 { 325 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_delete-16.png")); 326 putValue(Action.SHORT_DESCRIPTION, tr("tip.delete")); 327 } 328 329 public void actionPerformed(ActionEvent ae) 330 { 331 MyGraph graph = plugin.getGraph(); 332 Object [] cells = graph.getSelectionCells(); 333 if (cells != null) 334 { 335 cells = DefaultGraphModel.getDescendants(graph.getModel(), cells).toArray(); 336 graph.getModel().remove(cells); 337 } 338 } 339 } 340 341 class CutAction extends AbstractAction 342 { 343 public CutAction() 344 { 345 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_cut.png")); 346 putValue(Action.SHORT_DESCRIPTION, tr("tip.cut")); 347 } 348 349 public void actionPerformed(ActionEvent ae) 350 { 351 MyGraph graph = plugin.getGraph(); 352 graph.cut(); 353 } 354 } 355 356 class CopyAction extends AbstractAction 357 { 358 public CopyAction() 359 { 360 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_copy.png")); 361 putValue(Action.SHORT_DESCRIPTION, tr("tip.copy")); 362 } 363 364 public void actionPerformed(ActionEvent ae) 365 { 366 MyGraph graph = plugin.getGraph(); 367 graph.copy(); 368 } 369 } 370 371 class PasteAction extends AbstractAction 372 { 373 public PasteAction() 374 { 375 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_paste.png")); 376 putValue(Action.SHORT_DESCRIPTION, tr("tip.paste")); 377 } 378 379 public void actionPerformed(ActionEvent ae) 380 { 381 MyGraph graph = plugin.getGraph(); 382 graph.paste(); 383 } 384 } 385 386 class BringToFrontAction extends AbstractAction 387 { 388 public BringToFrontAction() 389 { 390 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_bring-forward.png")); 391 putValue(Action.SHORT_DESCRIPTION, tr("tip.bringToFront")); 392 } 393 394 public void actionPerformed(ActionEvent ae) 395 { 396 Object [] cells = plugin.getGraph().getSelectionCells(); 397 plugin.getGraph().getGraphLayoutCache().toFront(cells); 398 399 GraphLayoutEdit op = new GraphLayoutEdit(); 400 op.init(cells, GraphLayoutEdit.BRING_TO_FRONT); 401 try { 402 plugin.getClient().broadcastOperation(Client.getInstance().getMyInfos().getName(), op); 403 } catch (IOException e) { 404 DialogBox.error(tr("err.unableToBroadcastOperation") + e); 405 e.printStackTrace(); 406 } 407 } 408 } 409 410 class BringToBackAction extends AbstractAction 411 { 412 public BringToBackAction() 413 { 414 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_bring-backward.png")); 415 putValue(Action.SHORT_DESCRIPTION, tr("tip.bringToBack")); 416 } 417 418 public void actionPerformed(ActionEvent ae) 419 { 420 Object [] cells = plugin.getGraph().getSelectionCells(); 421 plugin.getGraph().getGraphLayoutCache().toBack(cells); 422 423 GraphLayoutEdit op = new GraphLayoutEdit(); 424 op.init(cells, GraphLayoutEdit.BRING_TO_BACK); 425 try { 426 plugin.getClient().broadcastOperation(Client.getInstance().getMyInfos().getName(), op); 427 } catch (IOException e) { 428 DialogBox.error(tr("err.unableToBroadcastOperation") + e); 429 e.printStackTrace(); 430 } 431 } 432 } 433 434 class GroupAction extends AbstractAction 435 { 436 public GroupAction() 437 { 438 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_group-16.png")); 439 putValue(Action.SHORT_DESCRIPTION, tr("tip.groupCells")); 440 } 441 442 public void actionPerformed(ActionEvent ae) 443 { 444 Object [] cells = plugin.getGraph().getSelectionCells(); 445 if (cells != null && cells.length > 1) 446 { 447 DefaultGraphCell group = new DefaultGraphCell("Group"); 448 Date timestamp = new Date (); 449 AttributeMap attrs = new AttributeMap(); 450 attrs.put("timestamp", timestamp); 451 Map attributes = new Hashtable (); 452 attributes.put(group, attrs); 453 454 ParentMap map = new ParentMap(); 455 for (int i = cells.length-1; i >=0; i--) 456 map.addEntry(cells[i], group); 457 458 459 DefaultGraphModel model = plugin.getGraphModel(); 460 synchronized(model) 461 { 462 GraphModelListener[] graphs = model.getGraphModelListeners(); 463 UndoableEditListener [] undos = model.getUndoableEditListeners(); 464 ModelUtils.removeListeners(model, graphs, undos); 465 466 plugin.getGraph().getModel().insert( 467 new Object [] {group}, attributes, null, map, null); 468 469 ModelUtils.addListeners(model, graphs, undos); 470 } 471 472 GraphLayoutEdit op = new GraphLayoutEdit(); 473 op.init(cells, GraphLayoutEdit.GROUP, timestamp); 474 try { 475 plugin.getClient().broadcastOperation(Client.getInstance().getMyInfos().getName(), op); 476 } catch (IOException e) { 477 DialogBox.error(tr("err.unableToBroadcastOperation") + e); 478 e.printStackTrace(); 479 } 480 481 plugin.getGraph().setSelectionCell(group); 482 } 483 } 484 } 485 486 class UnGroupAction extends AbstractAction 487 { 488 public UnGroupAction() 489 { 490 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_ungroup-16.png")); 491 putValue(Action.SHORT_DESCRIPTION, tr("tip.ungroupCells")); 492 } 493 494 public void actionPerformed(ActionEvent ae) 495 { 496 MyGraph graph = plugin.getGraph(); 497 GraphModel model = graph.getModel(); 498 499 Object [] cells = graph.getSelectionCells(); 500 if (cells != null) 501 { 502 ArrayList groups = new ArrayList (); 503 ArrayList children = new ArrayList (); 504 for (int i = 0; i < cells.length; i++) 505 { 506 if(graph.isGroup(cells[i])) 507 { 508 groups.add(cells[i]); 509 for (int j=0;j<model.getChildCount(cells[i]);j++) 510 { 511 Object child = model.getChild(cells[i], j); 512 if (!model.isPort(child)) 513 children.add(child); 514 } 515 } 516 } 517 model.remove(groups.toArray()); 518 graph.setSelectionCells(children.toArray()); 519 } 520 } 521 } 522 523 524 abstract class AbstractScaleAction extends AbstractAction 525 { 526 public abstract double getScale(); 527 public void actionPerformed(ActionEvent ae) 528 { 529 MyGraph graph = plugin.getGraph(); 530 double scale = getScale(); 531 graph.setScale(scale); 532 if (graph.getSelectionCell() != null) 533 graph.scrollCellToVisible(graph.getSelectionCell()); 534 } 535 } 536 537 class ZoomInAction extends AbstractScaleAction 538 { 539 public ZoomInAction() 540 { 541 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_zoom-in.png")); 542 putValue(Action.SHORT_DESCRIPTION, tr("tip.zoomIn")); 543 } 544 545 public double getScale() 546 { 547 MyGraph graph = plugin.getGraph(); 548 return graph.getScale() < 3 ? graph.getScale()*1.25 : graph.getScale(); 549 } 550 } 551 552 class ZoomOutAction extends AbstractScaleAction 553 { 554 public ZoomOutAction() 555 { 556 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_zoom-out.png")); 557 putValue(Action.SHORT_DESCRIPTION, tr("tip.zoomOut")); 558 } 559 560 public double getScale() 561 { 562 MyGraph graph = plugin.getGraph(); 563 return graph.getScale() > 0.2 ? graph.getScale()*0.75 : graph.getScale(); 564 } 565 } 566 567 class ZoomDefaultAction extends AbstractScaleAction 568 { 569 public ZoomDefaultAction() 570 { 571 putValue(Action.SMALL_ICON, plugin.getImageIcon("stock_zoom-1.png")); 572 putValue(Action.SHORT_DESCRIPTION, tr("tip.zoomDefault")); 573 } 574 575 public double getScale() 576 { 577 return 1; 578 } 579 } 580 } 581 582 | Popular Tags |