001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.canvas; 020 021import java.awt.BorderLayout; 022import java.awt.Component; 023import java.awt.Graphics2D; 024import java.awt.Point; 025import java.awt.event.KeyEvent; 026import java.awt.event.KeyListener; 027import java.awt.event.MouseEvent; 028import java.awt.event.MouseWheelEvent; 029import java.awt.image.BufferedImage; 030import java.lang.reflect.Constructor; 031import java.util.ArrayList; 032import java.util.Collections; 033import java.util.Comparator; 034import java.util.HashMap; 035import java.util.HashSet; 036import java.util.List; 037import java.util.Map; 038import java.util.Set; 039 040import javax.swing.JPanel; 041import javax.swing.JToolBar; 042import javax.swing.event.ChangeEvent; 043 044import icy.action.CanvasActions; 045import icy.action.GeneralActions; 046import icy.action.RoiActions; 047import icy.action.WindowActions; 048import icy.canvas.CanvasLayerEvent.LayersEventType; 049import icy.canvas.IcyCanvasEvent.IcyCanvasEventType; 050import icy.canvas.Layer.LayerListener; 051import icy.common.CollapsibleEvent; 052import icy.common.UpdateEventHandler; 053import icy.common.listener.ChangeListener; 054import icy.common.listener.ProgressListener; 055import icy.gui.util.GuiUtil; 056import icy.gui.viewer.MouseImageInfosPanel; 057import icy.gui.viewer.TNavigationPanel; 058import icy.gui.viewer.Viewer; 059import icy.gui.viewer.ViewerEvent; 060import icy.gui.viewer.ViewerListener; 061import icy.gui.viewer.ZNavigationPanel; 062import icy.image.IcyBufferedImage; 063import icy.image.colormodel.IcyColorModel; 064import icy.image.lut.LUT; 065import icy.image.lut.LUTEvent; 066import icy.image.lut.LUTEvent.LUTEventType; 067import icy.image.lut.LUTListener; 068import icy.main.Icy; 069import icy.painter.Overlay; 070import icy.painter.OverlayWrapper; 071import icy.painter.Painter; 072import icy.plugin.PluginDescriptor; 073import icy.plugin.PluginLoader; 074import icy.plugin.interface_.PluginCanvas; 075import icy.roi.ROI; 076import icy.sequence.DimensionId; 077import icy.sequence.Sequence; 078import icy.sequence.SequenceEvent; 079import icy.sequence.SequenceEvent.SequenceEventType; 080import icy.sequence.SequenceListener; 081import icy.system.IcyExceptionHandler; 082import icy.system.thread.ThreadUtil; 083import icy.type.point.Point5D; 084import icy.util.ClassUtil; 085import icy.util.EventUtil; 086import icy.util.OMEUtil; 087import plugins.kernel.canvas.Canvas2DPlugin; 088import plugins.kernel.canvas.VtkCanvasPlugin; 089 090/** 091 * @author Fabrice de Chaumont & Stephane Dallongeville<br> 092 * <br> 093 * An IcyCanvas is a basic Canvas used into the viewer. It contains a visual representation 094 * of the sequence and provides some facilities as basic transformation and view 095 * synchronization.<br> 096 * Also IcyCanvas receives key events from Viewer when they are not consumed.<br> 097 * <br> 098 * By default transformations are applied in following order :<br> 099 * Rotation, Translation then Scaling.<br> 100 * The rotation transformation is relative to canvas center.<br> 101 * <br> 102 * Free feel to implement and override this design or not. <br> 103 * <br> 104 * (Canvas2D and Canvas3D derives from IcyCanvas)<br> 105 */ 106public abstract class IcyCanvas extends JPanel 107 implements KeyListener, ViewerListener, SequenceListener, LUTListener, ChangeListener, LayerListener 108{ 109 protected class IcyCanvasImageOverlay extends Overlay 110 { 111 public IcyCanvasImageOverlay() 112 { 113 super((getSequence() == null) ? "Image" : getSequence().getName(), OverlayPriority.IMAGE_NORMAL); 114 115 // we fix the image overlay 116 canBeRemoved = false; 117 readOnly = false; 118 } 119 120 @Override 121 public void paint(Graphics2D g, Sequence sequence, IcyCanvas canvas) 122 { 123 // default lazy implementation (very slow) 124 if (g != null) 125 g.drawImage(getCurrentImage(), null, 0, 0); 126 } 127 } 128 129 /** 130 * Returns all {@link PluginCanvas} plugins (kernel plugin are returned first). 131 */ 132 public static List<PluginDescriptor> getCanvasPlugins() 133 { 134 // get all canvas plugins 135 final List<PluginDescriptor> result = PluginLoader.getPlugins(PluginCanvas.class); 136 137 // VTK is not loaded ? 138 if (!Icy.isVtkLibraryLoaded()) 139 { 140 // remove VtkCanvas 141 final int ind = PluginDescriptor.getIndex(result, VtkCanvasPlugin.class.getName()); 142 if (ind != -1) 143 result.remove(ind); 144 } 145 146 // sort plugins list 147 Collections.sort(result, new Comparator<PluginDescriptor>() 148 { 149 @Override 150 public int compare(PluginDescriptor o1, PluginDescriptor o2) 151 { 152 return Integer.valueOf(getOrder(o1)).compareTo(Integer.valueOf(getOrder(o2))); 153 } 154 155 int getOrder(PluginDescriptor p) 156 { 157 if (p.getClassName().equals(Canvas2DPlugin.class.getName())) 158 return 0; 159 if (p.getClassName().equals(VtkCanvasPlugin.class.getName())) 160 return 1; 161 162 return 10; 163 } 164 }); 165 166 return result; 167 } 168 169 /** 170 * Returns all {@link PluginCanvas} plugins class name (kernel plugin are returned first). 171 */ 172 public static List<String> getCanvasPluginNames() 173 { 174 // get all canvas plugins 175 final List<PluginDescriptor> plugins = getCanvasPlugins(); 176 final List<String> result = new ArrayList<String>(); 177 178 for (PluginDescriptor plugin : plugins) 179 result.add(plugin.getClassName()); 180 181 return result; 182 } 183 184 /** 185 * Returns the plugin class name corresponding to the specified Canvas class name.<br> 186 * Returns <code>null</code> if we can't find a corresponding plugin. 187 */ 188 public static String getPluginClassName(String canvasClassName) 189 { 190 for (PluginDescriptor plugin : IcyCanvas.getCanvasPlugins()) 191 { 192 final String className = getCanvasClassName(plugin); 193 194 // we found the corresponding plugin 195 if (canvasClassName.equals(className)) 196 // get plugin class name 197 return plugin.getClassName(); 198 } 199 200 return null; 201 } 202 203 /** 204 * Returns the canvas class name corresponding to the specified {@link PluginCanvas} plugin.<br> 205 * Returns <code>null</code> if we can't retrieve the corresponding canvas class name. 206 */ 207 public static String getCanvasClassName(PluginDescriptor plugin) 208 { 209 try 210 { 211 if (plugin != null) 212 { 213 final PluginCanvas pluginCanvas = (PluginCanvas) plugin.getPluginClass().newInstance(); 214 // return canvas class name 215 return pluginCanvas.getCanvasClassName(); 216 } 217 } 218 catch (Exception e) 219 { 220 IcyExceptionHandler.showErrorMessage(e, true); 221 } 222 223 return null; 224 } 225 226 /** 227 * Returns the canvas class name corresponding to the specified {@link PluginCanvas} class name. <br> 228 * Returns <code>null</code> if we can't find retrieve the corresponding canvas class name. 229 */ 230 public static String getCanvasClassName(String pluginClassName) 231 { 232 return getCanvasClassName(PluginLoader.getPlugin(pluginClassName)); 233 } 234 235 // /** 236 // * Return the class name of all {@link PluginCanvas}. 237 // */ 238 // public static List<String> getCanvasPlugins() 239 // { 240 // // get all canvas plugins 241 // final List<PluginDescriptor> plugins = PluginLoader.getPlugins(PluginCanvas.class); 242 // final List<String> result = new ArrayList<String>(); 243 // 244 // // we want the default 2D and 3D canvas to be first 245 // result.add(Canvas2DPlugin.class.getName()); 246 // if (Icy.isVtkLibraryLoaded()) 247 // result.add(VtkCanvasPlugin.class.getName()); 248 // 249 // for (PluginDescriptor plugin : plugins) 250 // { 251 // final String className = plugin.getClassName(); 252 // 253 // // ignore default canvas as they have been already added 254 // if (Canvas2DPlugin.class.getName().equals(className)) 255 // continue; 256 // if (VtkCanvasPlugin.class.getName().equals(className)) 257 // continue; 258 // 259 // CollectionUtil.addUniq(result, plugin.getClassName()); 260 // } 261 // 262 // return result; 263 // } 264 265 /** 266 * Create a {@link IcyCanvas} object from its class name or {@link PluginCanvas} class name.<br> 267 * Throws an exception if an error occurred (canvas class was not found or it could not be 268 * creatd). 269 * 270 * @param viewer 271 * {@link Viewer} to which to canvas is attached. 272 * @throws ClassCastException 273 * if the specified class name is not a canvas plugin or canvas class name 274 * @throws Exception 275 * if the specified canvas cannot be created for some reasons 276 */ 277 public static IcyCanvas create(String className, Viewer viewer) throws ClassCastException, Exception 278 { 279 // search for the specified className 280 final Class<?> clazz = ClassUtil.findClass(className); 281 final Class<? extends PluginCanvas> pluginCanvasClazz; 282 283 try 284 { 285 // we first check if we have a IcyCanvas Plugin class here 286 pluginCanvasClazz = clazz.asSubclass(PluginCanvas.class); 287 } 288 catch (ClassCastException e0) 289 { 290 // check if this is a IcyCanvas class 291 final Class<? extends IcyCanvas> canvasClazz = clazz.asSubclass(IcyCanvas.class); 292 293 // get constructor (Viewer) 294 final Constructor<? extends IcyCanvas> constructor = canvasClazz.getConstructor(new Class[] {Viewer.class}); 295 // build canvas 296 return constructor.newInstance(new Object[] {viewer}); 297 } 298 299 // create canvas from plugin 300 return pluginCanvasClazz.newInstance().createCanvas(viewer); 301 } 302 303 public static void addVisibleLayerToList(final Layer layer, ArrayList<Layer> list) 304 { 305 if ((layer != null) && (layer.isVisible())) 306 list.add(layer); 307 } 308 309 private static final long serialVersionUID = -8461229450296203011L; 310 311 public static final String PROPERTY_LAYERS_VISIBLE = "layersVisible"; 312 313 /** 314 * Navigations bar 315 */ 316 final protected ZNavigationPanel zNav; 317 final protected TNavigationPanel tNav; 318 319 /** 320 * The panel where mouse informations are displayed 321 */ 322 protected final MouseImageInfosPanel mouseInfPanel; 323 324 /** 325 * The panel contains all settings and informations data such as<br> 326 * scale factor, rendering mode... 327 * Will be retrieved by the inspector to get information on the current canvas. 328 */ 329 protected JPanel panel; 330 331 /** 332 * attached viewer 333 */ 334 protected final Viewer viewer; 335 /** 336 * layers visible flag 337 */ 338 protected boolean layersVisible; 339 /** 340 * synchronization group :<br> 341 * 0 = unsynchronized 342 * 1 = full synchronization group 1 343 * 2 = full synchronization group 2 344 * 3 = view synchronization group (T and Z navigation are not synchronized) 345 * 4 = slice synchronization group (only T and Z navigation are synchronized) 346 */ 347 protected int syncId; 348 349 /** 350 * Overlay/Layer used to display sequence image 351 */ 352 protected final Overlay imageOverlay; 353 protected final Layer imageLayer; 354 355 /** 356 * Layers attached to canvas<br> 357 * There are representing sequence overlays with some visualization properties 358 */ 359 protected final Map<Overlay, Layer> layers; 360 /** 361 * Priority ordered layers. 362 */ 363 protected List<Layer> orderedLayers; 364 365 /** 366 * internal updater 367 */ 368 protected final UpdateEventHandler updater; 369 /** 370 * listeners 371 */ 372 protected final List<IcyCanvasListener> listeners; 373 protected final List<CanvasLayerListener> layerListeners; 374 375 /** 376 * Current X position (should be -1 when canvas handle multi X dimension view). 377 */ 378 protected int posX; 379 /** 380 * Current Y position (should be -1 when canvas handle multi Y dimension view). 381 */ 382 protected int posY; 383 /** 384 * Current Z position (should be -1 when canvas handle multi Z dimension view). 385 */ 386 protected int posZ; 387 /** 388 * Current T position (should be -1 when canvas handle multi T dimension view). 389 */ 390 protected int posT; 391 /** 392 * Current C position (should be -1 when canvas handle multi C dimension view). 393 */ 394 protected int posC; 395 396 /** 397 * Current mouse position (canvas coordinate space) 398 */ 399 protected Point mousePos; 400 401 /** 402 * internals 403 */ 404 protected LUT lut; 405 protected boolean synchMaster; 406 protected boolean orderedLayersOutdated; 407 private Runnable guiUpdater; 408 409 /** 410 * Constructor 411 * 412 * @param viewer 413 */ 414 public IcyCanvas(Viewer viewer) 415 { 416 super(); 417 418 // default 419 this.viewer = viewer; 420 421 layersVisible = true; 422 layers = new HashMap<Overlay, Layer>(); 423 orderedLayers = new ArrayList<Layer>(); 424 syncId = 0; 425 synchMaster = false; 426 orderedLayersOutdated = false; 427 updater = new UpdateEventHandler(this, false); 428 429 // default position 430 mousePos = new Point(0, 0); 431 posX = -1; 432 posY = -1; 433 posZ = -1; 434 posT = -1; 435 posC = -1; 436 437 // GUI stuff 438 panel = new JPanel(); 439 440 listeners = new ArrayList<IcyCanvasListener>(); 441 layerListeners = new ArrayList<CanvasLayerListener>(); 442 443 // Z navigation 444 zNav = new ZNavigationPanel(); 445 zNav.addChangeListener(new javax.swing.event.ChangeListener() 446 { 447 @Override 448 public void stateChanged(ChangeEvent e) 449 { 450 // set the new Z position 451 setPositionZ(zNav.getValue()); 452 } 453 }); 454 455 // T navigation 456 tNav = new TNavigationPanel(); 457 tNav.addChangeListener(new javax.swing.event.ChangeListener() 458 { 459 @Override 460 public void stateChanged(ChangeEvent e) 461 { 462 // set the new T position 463 setPositionT(tNav.getValue()); 464 } 465 }); 466 467 // mouse info panel 468 mouseInfPanel = new MouseImageInfosPanel(); 469 470 // default canvas layout 471 setLayout(new BorderLayout()); 472 473 add(zNav, BorderLayout.WEST); 474 add(GuiUtil.createPageBoxPanel(tNav, mouseInfPanel), BorderLayout.SOUTH); 475 476 // asynchronous updater for GUI 477 guiUpdater = new Runnable() 478 { 479 @Override 480 public void run() 481 { 482 ThreadUtil.invokeNow(new Runnable() 483 { 484 @Override 485 public void run() 486 { 487 // update sliders bounds if needed 488 updateZNav(); 489 updateTNav(); 490 491 // adjust X position if needed 492 final int maxX = getMaxPositionX(); 493 final int curX = getPositionX(); 494 if ((curX != -1) && (curX > maxX)) 495 setPositionX(maxX); 496 497 // adjust Y position if needed 498 final int maxY = getMaxPositionY(); 499 final int curY = getPositionY(); 500 if ((curY != -1) && (curY > maxY)) 501 setPositionY(maxY); 502 503 // adjust C position if needed 504 final int maxC = getMaxPositionC(); 505 final int curC = getPositionC(); 506 if ((curC != -1) && (curC > maxC)) 507 setPositionC(maxC); 508 509 // adjust Z position if needed 510 final int maxZ = getMaxPositionZ(); 511 final int curZ = getPositionZ(); 512 if ((curZ != -1) && (curZ > maxZ)) 513 setPositionZ(maxZ); 514 515 // adjust T position if needed 516 final int maxT = getMaxPositionT(); 517 final int curT = getPositionT(); 518 if ((curT != -1) && (curT > maxT)) 519 setPositionT(maxT); 520 521 // refresh mouse panel informations (data values can have changed) 522 mouseInfPanel.updateInfos(IcyCanvas.this); 523 } 524 }); 525 } 526 }; 527 528 // create image overlay 529 imageOverlay = createImageOverlay(); 530 531 // create layers from overlays 532 beginUpdate(); 533 try 534 { 535 // first add image layer 536 imageLayer = addLayer(getImageOverlay()); 537 538 final Sequence sequence = getSequence(); 539 540 if (sequence != null) 541 { 542 // then add sequence overlays to layer list 543 for (Overlay overlay : sequence.getOverlays()) 544 addLayer(overlay); 545 } 546 else 547 System.err.println("Sequence null when canvas created"); 548 } 549 finally 550 { 551 endUpdate(); 552 } 553 554 // add listeners 555 viewer.addListener(this); 556 final Sequence seq = getSequence(); 557 if (seq != null) 558 seq.addListener(this); 559 560 // set lut (no event wanted here) 561 lut = null; 562 setLut(viewer.getLut(), false); 563 } 564 565 /** 566 * Called by the viewer when canvas is closed to release some resources.<br/> 567 * Be careful to not restore previous state here (as the colormap) because generally <code>shutdown</code> is called 568 * <b>after</b> the creation of the other canvas. 569 */ 570 public void shutDown() 571 { 572 // remove navigation panel listener 573 zNav.removeAllChangeListener(); 574 tNav.removeAllChangeListener(); 575 576 // remove listeners 577 if (lut != null) 578 lut.removeListener(this); 579 final Sequence seq = getSequence(); 580 if (seq != null) 581 seq.removeListener(this); 582 viewer.removeListener(this); 583 584 // remove all layers 585 beginUpdate(); 586 try 587 { 588 for (Layer layer : getLayers()) 589 removeLayer(layer); 590 } 591 finally 592 { 593 endUpdate(); 594 } 595 596 // release layers 597 synchronized (orderedLayers) 598 { 599 orderedLayers.clear(); 600 } 601 602 // remove all IcyCanvas & Layer listeners 603 synchronized (listeners) 604 { 605 listeners.clear(); 606 } 607 synchronized (layerListeners) 608 { 609 layerListeners.clear(); 610 } 611 } 612 613 /** 614 * Force canvas refresh 615 */ 616 public abstract void refresh(); 617 618 protected Overlay createImageOverlay() 619 { 620 // default image overlay 621 return new IcyCanvasImageOverlay(); 622 } 623 624 /** 625 * Returns the {@link Overlay} used to display the current sequence image 626 */ 627 public Overlay getImageOverlay() 628 { 629 return imageOverlay; 630 } 631 632 /** 633 * Returns the {@link Layer} object used to display the current sequence image 634 */ 635 public Layer getImageLayer() 636 { 637 return imageLayer; 638 } 639 640 /** 641 * @deprecated Use {@link #isLayersVisible()} instead. 642 */ 643 @Deprecated 644 public boolean getDrawLayers() 645 { 646 return isLayersVisible(); 647 } 648 649 /** 650 * @deprecated Use {@link #setLayersVisible(boolean)} instead. 651 */ 652 @Deprecated 653 public void setDrawLayers(boolean value) 654 { 655 setLayersVisible(value); 656 } 657 658 /** 659 * Return true if layers are visible on the canvas. 660 */ 661 public boolean isLayersVisible() 662 { 663 return layersVisible; 664 } 665 666 /** 667 * Make layers visible on this canvas (default = true). 668 */ 669 public void setLayersVisible(boolean value) 670 { 671 if (layersVisible != value) 672 { 673 layersVisible = value; 674 layersVisibleChanged(); 675 firePropertyChange(PROPERTY_LAYERS_VISIBLE, !value, value); 676 } 677 } 678 679 /** 680 * Global layers visibility changed 681 */ 682 protected void layersVisibleChanged() 683 { 684 final Component comp = getViewComponent(); 685 686 if (comp != null) 687 comp.repaint(); 688 } 689 690 /** 691 * @return the viewer 692 */ 693 public Viewer getViewer() 694 { 695 return viewer; 696 } 697 698 /** 699 * @return the sequence 700 */ 701 public Sequence getSequence() 702 { 703 return viewer.getSequence(); 704 } 705 706 /** 707 * @return the main view component 708 */ 709 public abstract Component getViewComponent(); 710 711 /** 712 * @return the Z navigation bar panel 713 */ 714 public ZNavigationPanel getZNavigationPanel() 715 { 716 return zNav; 717 } 718 719 /** 720 * @return the T navigation bar panel 721 */ 722 public TNavigationPanel getTNavigationPanel() 723 { 724 return tNav; 725 } 726 727 /** 728 * @return the mouse image informations panel 729 */ 730 public MouseImageInfosPanel getMouseImageInfosPanel() 731 { 732 return mouseInfPanel; 733 } 734 735 /** 736 * @return the LUT 737 */ 738 public LUT getLut() 739 { 740 // ensure we have the good lut 741 setLut(viewer.getLut(), true); 742 743 return lut; 744 } 745 746 /** 747 * set canvas LUT 748 */ 749 private void setLut(LUT lut, boolean event) 750 { 751 if (this.lut != lut) 752 { 753 if (this.lut != null) 754 this.lut.removeListener(this); 755 756 this.lut = lut; 757 758 // add listener to the new lut 759 if (lut != null) 760 lut.addListener(this); 761 762 // launch a lutChanged event if wanted 763 if (event) 764 lutChanged(new LUTEvent(lut, -1, LUTEventType.COLORMAP_CHANGED)); 765 } 766 } 767 768 /** 769 * @deprecated Use {@link #customizeToolbar(JToolBar)} instead. 770 */ 771 @SuppressWarnings("unused") 772 @Deprecated 773 public void addViewerToolbarComponents(JToolBar toolBar) 774 { 775 776 } 777 778 /** 779 * Called by the parent viewer when building the toolbar.<br> 780 * This way the canvas can customize it by adding specific command for instance.<br> 781 * 782 * @param toolBar 783 * the parent toolbar to customize 784 */ 785 public void customizeToolbar(JToolBar toolBar) 786 { 787 addViewerToolbarComponents(toolBar); 788 } 789 790 /** 791 * Returns the setting panel of this canvas.<br> 792 * The setting panel is displayed in the inspector so user can change canvas parameters. 793 */ 794 public JPanel getPanel() 795 { 796 return panel; 797 } 798 799 /** 800 * Returns all layers attached to this canvas.<br/> 801 * 802 * @param sorted 803 * If <code>true</code> the returned list is sorted on the layer priority.<br> 804 * Sort operation is cached so the method could take sometime when sort cache need to be 805 * rebuild. 806 */ 807 public List<Layer> getLayers(boolean sorted) 808 { 809 if (sorted) 810 { 811 // need to rebuild sorted layer list ? 812 if (orderedLayersOutdated) 813 { 814 // build and sort the list 815 synchronized (layers) 816 { 817 orderedLayers = new ArrayList<Layer>(layers.values()); 818 } 819 820 try 821 { 822 Collections.sort(orderedLayers); 823 } 824 catch (Exception e) 825 { 826 // catch exceptions here as some we can have "IllegalArgumentException: Comparison method violates 827 // its general contract!" 828 } 829 830 orderedLayersOutdated = false; 831 } 832 833 return new ArrayList<Layer>(orderedLayers); 834 } 835 836 synchronized (layers) 837 { 838 return new ArrayList<Layer>(layers.values()); 839 } 840 } 841 842 /** 843 * Returns all layers attached to this canvas.<br/> 844 * The returned list is sorted on the layer priority.<br> 845 * Sort operation is cached so the method could take sometime when cache need to be rebuild. 846 */ 847 public List<Layer> getLayers() 848 { 849 return getLayers(true); 850 } 851 852 /** 853 * Returns all visible layers (visible property set to <code>true</code>) attached to this 854 * canvas. 855 * 856 * @param sorted 857 * If <code>true</code> the returned list is sorted on the layer priority.<br> 858 * Sort operation is cached so the method could take sometime when sort cache need to be 859 * rebuild. 860 */ 861 public List<Layer> getVisibleLayers(boolean sorted) 862 { 863 final List<Layer> olayers = getLayers(sorted); 864 final List<Layer> result = new ArrayList<Layer>(olayers.size()); 865 866 for (Layer l : olayers) 867 if (l.isVisible()) 868 result.add(l); 869 870 return result; 871 } 872 873 /** 874 * Returns all visible layers (visible property set to <code>true</code>) attached to this 875 * canvas.<br/> 876 * The list is sorted on the layer priority. 877 */ 878 public ArrayList<Layer> getVisibleLayers() 879 { 880 return (ArrayList<Layer>) getVisibleLayers(true); 881 } 882 883 /** 884 * @deprecated Use {@link #getLayers()} instead (sorted on Layer priority). 885 */ 886 @Deprecated 887 public List<Layer> getOrderedLayersForEvent() 888 { 889 return getLayers(); 890 } 891 892 /** 893 * @deprecated Use {@link #getVisibleLayers()} instead (sorted on Layer priority). 894 */ 895 @Deprecated 896 public List<Layer> getVisibleOrderedLayersForEvent() 897 { 898 return getVisibleLayers(); 899 } 900 901 /** 902 * @deprecated Use {@link #getOverlays()} instead. 903 */ 904 @Deprecated 905 public List<Painter> getLayersPainter() 906 { 907 final ArrayList<Painter> result = new ArrayList<Painter>(); 908 909 for (Overlay overlay : getOverlays()) 910 { 911 if (overlay instanceof OverlayWrapper) 912 result.add(((OverlayWrapper) overlay).getPainter()); 913 else 914 result.add(overlay); 915 } 916 917 return result; 918 } 919 920 /** 921 * Directly returns a {@link Set} of all Overlay displayed by this canvas. 922 */ 923 public Set<Overlay> getOverlays() 924 { 925 synchronized (layers) 926 { 927 return new HashSet<Overlay>(layers.keySet()); 928 } 929 } 930 931 /** 932 * @return the SyncId 933 */ 934 public int getSyncId() 935 { 936 return syncId; 937 } 938 939 /** 940 * Set the synchronization group id (0 means unsynchronized).<br> 941 * 942 * @return <code>false</code> if the canvas do not support synchronization group. 943 * @param id 944 * the syncId to set 945 */ 946 public boolean setSyncId(int id) 947 { 948 if (!isSynchronizationSupported()) 949 return false; 950 951 if (this.syncId != id) 952 { 953 this.syncId = id; 954 955 // notify sync has changed 956 updater.changed(new IcyCanvasEvent(this, IcyCanvasEventType.SYNC_CHANGED)); 957 } 958 959 return true; 960 } 961 962 /** 963 * Return true if this canvas support synchronization 964 */ 965 public boolean isSynchronizationSupported() 966 { 967 // default (override it when supported) 968 return false; 969 } 970 971 /** 972 * Return true if this canvas is synchronized 973 */ 974 public boolean isSynchronized() 975 { 976 return syncId > 0; 977 } 978 979 /** 980 * Return true if current canvas is synchronized and is currently the synchronize leader. 981 */ 982 public boolean isSynchMaster() 983 { 984 return synchMaster; 985 } 986 987 /** 988 * @deprecated Use {@link #isSynchMaster()} instead. 989 */ 990 @Deprecated 991 public boolean isSynchHeader() 992 { 993 return isSynchMaster(); 994 } 995 996 /** 997 * Return true if current canvas is synchronized and it's not the synchronize master 998 */ 999 public boolean isSynchSlave() 1000 { 1001 if (isSynchronized()) 1002 { 1003 if (isSynchMaster()) 1004 return false; 1005 1006 // search for a master in synchronized canvas 1007 for (IcyCanvas cnv : getSynchronizedCanvas()) 1008 if (cnv.isSynchMaster()) 1009 return true; 1010 } 1011 1012 return false; 1013 } 1014 1015 /** 1016 * Return true if this canvas is synchronized on view (offset, zoom and rotation). 1017 */ 1018 public boolean isSynchOnView() 1019 { 1020 return (syncId == 1) || (syncId == 2) || (syncId == 3); 1021 } 1022 1023 /** 1024 * Return true if this canvas is synchronized on slice (T and Z position) 1025 */ 1026 public boolean isSynchOnSlice() 1027 { 1028 return (syncId == 1) || (syncId == 2) || (syncId == 4); 1029 } 1030 1031 /** 1032 * Return true if this canvas is synchronized on cursor (mouse cursor) 1033 */ 1034 public boolean isSynchOnCursor() 1035 { 1036 return (syncId > 0); 1037 } 1038 1039 /** 1040 * Return true if we get the synchronizer master from synchronized canvas 1041 */ 1042 protected boolean getSynchMaster() 1043 { 1044 return getSynchMaster(getSynchronizedCanvas()); 1045 } 1046 1047 /** 1048 * @deprecated Use {@link #getSynchMaster()} instead. 1049 */ 1050 @Deprecated 1051 protected boolean getSynchHeader() 1052 { 1053 return getSynchMaster(); 1054 } 1055 1056 /** 1057 * Return true if we get the synchronizer master from specified canvas list. 1058 */ 1059 protected boolean getSynchMaster(List<IcyCanvas> canvasList) 1060 { 1061 for (IcyCanvas canvas : canvasList) 1062 if (canvas.isSynchMaster()) 1063 return canvas == this; 1064 1065 // no master found so we are master 1066 synchMaster = true; 1067 1068 return true; 1069 } 1070 1071 /** 1072 * @deprecated Use {@link #getSynchMaster(List)} instead. 1073 */ 1074 @Deprecated 1075 protected boolean getSynchHeader(List<IcyCanvas> canvasList) 1076 { 1077 return getSynchMaster(canvasList); 1078 } 1079 1080 /** 1081 * Release synchronizer master 1082 */ 1083 protected void releaseSynchMaster() 1084 { 1085 synchMaster = false; 1086 } 1087 1088 /** 1089 * @deprecated Use {@link #releaseSynchMaster()} instead. 1090 */ 1091 @Deprecated 1092 protected void releaseSynchHeader() 1093 { 1094 releaseSynchMaster(); 1095 } 1096 1097 /** 1098 * Return the list of canvas which are synchronized with the current one 1099 */ 1100 private List<IcyCanvas> getSynchronizedCanvas() 1101 { 1102 final List<IcyCanvas> result = new ArrayList<IcyCanvas>(); 1103 1104 if (isSynchronized()) 1105 { 1106 final List<Viewer> viewers = Icy.getMainInterface().getViewers(); 1107 1108 for (int i = viewers.size() - 1; i >= 0; i--) 1109 { 1110 final IcyCanvas cnv = viewers.get(i).getCanvas(); 1111 1112 if ((cnv == this) || (cnv.getSyncId() != syncId)) 1113 viewers.remove(i); 1114 } 1115 1116 for (Viewer v : viewers) 1117 { 1118 final IcyCanvas cnv = v.getCanvas(); 1119 1120 // only permit same class 1121 if (cnv.getClass().isInstance(this)) 1122 result.add(cnv); 1123 } 1124 } 1125 1126 return result; 1127 } 1128 1129 /** 1130 * Synchronize views of specified list of canvas 1131 */ 1132 protected void synchronizeCanvas(List<IcyCanvas> canvasList, IcyCanvasEvent event, boolean processAll) 1133 { 1134 final IcyCanvasEventType type = event.getType(); 1135 final DimensionId dim = event.getDim(); 1136 1137 // position synchronization 1138 if (isSynchOnSlice()) 1139 { 1140 if (processAll || (type == IcyCanvasEventType.POSITION_CHANGED)) 1141 { 1142 // no information about dimension --> set all 1143 if (processAll || (dim == DimensionId.NULL)) 1144 { 1145 final int x = getPositionX(); 1146 final int y = getPositionY(); 1147 final int z = getPositionZ(); 1148 final int t = getPositionT(); 1149 final int c = getPositionC(); 1150 1151 for (IcyCanvas cnv : canvasList) 1152 { 1153 if (x != -1) 1154 cnv.setPositionX(x); 1155 if (y != -1) 1156 cnv.setPositionY(y); 1157 if (z != -1) 1158 cnv.setPositionZ(z); 1159 if (t != -1) 1160 cnv.setPositionT(t); 1161 if (c != -1) 1162 cnv.setPositionC(c); 1163 } 1164 } 1165 else 1166 { 1167 for (IcyCanvas cnv : canvasList) 1168 { 1169 final int pos = getPosition(dim); 1170 if (pos != -1) 1171 cnv.setPosition(dim, pos); 1172 } 1173 } 1174 } 1175 } 1176 1177 // view synchronization 1178 if (isSynchOnView()) 1179 { 1180 if (processAll || (type == IcyCanvasEventType.SCALE_CHANGED)) 1181 { 1182 // no information about dimension --> set all 1183 if (processAll || (dim == DimensionId.NULL)) 1184 { 1185 final double sX = getScaleX(); 1186 final double sY = getScaleY(); 1187 final double sZ = getScaleZ(); 1188 final double sT = getScaleT(); 1189 final double sC = getScaleC(); 1190 1191 for (IcyCanvas cnv : canvasList) 1192 { 1193 cnv.setScaleX(sX); 1194 cnv.setScaleY(sY); 1195 cnv.setScaleZ(sZ); 1196 cnv.setScaleT(sT); 1197 cnv.setScaleC(sC); 1198 } 1199 } 1200 else 1201 { 1202 for (IcyCanvas cnv : canvasList) 1203 cnv.setScale(dim, getScale(dim)); 1204 } 1205 } 1206 1207 if (processAll || (type == IcyCanvasEventType.ROTATION_CHANGED)) 1208 { 1209 // no information about dimension --> set all 1210 if (processAll || (dim == DimensionId.NULL)) 1211 { 1212 final double rotX = getRotationX(); 1213 final double rotY = getRotationY(); 1214 final double rotZ = getRotationZ(); 1215 final double rotT = getRotationT(); 1216 final double rotC = getRotationC(); 1217 1218 for (IcyCanvas cnv : canvasList) 1219 { 1220 cnv.setRotationX(rotX); 1221 cnv.setRotationY(rotY); 1222 cnv.setRotationZ(rotZ); 1223 cnv.setRotationT(rotT); 1224 cnv.setRotationC(rotC); 1225 } 1226 } 1227 else 1228 { 1229 for (IcyCanvas cnv : canvasList) 1230 cnv.setRotation(dim, getRotation(dim)); 1231 } 1232 } 1233 1234 // process offset in last as it can be limited depending destination scale value 1235 if (processAll || (type == IcyCanvasEventType.OFFSET_CHANGED)) 1236 { 1237 // no information about dimension --> set all 1238 if (processAll || (dim == DimensionId.NULL)) 1239 { 1240 final int offX = getOffsetX(); 1241 final int offY = getOffsetY(); 1242 final int offZ = getOffsetZ(); 1243 final int offT = getOffsetT(); 1244 final int offC = getOffsetC(); 1245 1246 for (IcyCanvas cnv : canvasList) 1247 { 1248 cnv.setOffsetX(offX); 1249 cnv.setOffsetY(offY); 1250 cnv.setOffsetZ(offZ); 1251 cnv.setOffsetT(offT); 1252 cnv.setOffsetC(offC); 1253 } 1254 } 1255 else 1256 { 1257 for (IcyCanvas cnv : canvasList) 1258 cnv.setOffset(dim, getOffset(dim)); 1259 } 1260 } 1261 } 1262 1263 // cursor synchronization 1264 if (isSynchOnCursor()) 1265 { 1266 // mouse synchronization 1267 if (processAll || (type == IcyCanvasEventType.MOUSE_IMAGE_POSITION_CHANGED)) 1268 { 1269 // no information about dimension --> set all 1270 if (processAll || (dim == DimensionId.NULL)) 1271 { 1272 final double mipX = getMouseImagePosX(); 1273 final double mipY = getMouseImagePosY(); 1274 final double mipZ = getMouseImagePosZ(); 1275 final double mipT = getMouseImagePosT(); 1276 final double mipC = getMouseImagePosC(); 1277 1278 for (IcyCanvas cnv : canvasList) 1279 { 1280 cnv.setMouseImagePosX(mipX); 1281 cnv.setMouseImagePosY(mipY); 1282 cnv.setMouseImagePosZ(mipZ); 1283 cnv.setMouseImagePosT(mipT); 1284 cnv.setMouseImagePosC(mipC); 1285 } 1286 } 1287 else 1288 { 1289 for (IcyCanvas cnv : canvasList) 1290 cnv.setMouseImagePos(dim, getMouseImagePos(dim)); 1291 } 1292 } 1293 } 1294 } 1295 1296 /** 1297 * Get position for specified dimension 1298 */ 1299 public int getPosition(DimensionId dim) 1300 { 1301 switch (dim) 1302 { 1303 case X: 1304 return getPositionX(); 1305 case Y: 1306 return getPositionY(); 1307 case Z: 1308 return getPositionZ(); 1309 case T: 1310 return getPositionT(); 1311 case C: 1312 return getPositionC(); 1313 } 1314 1315 return 0; 1316 } 1317 1318 /** 1319 * @return current X (-1 if all selected) 1320 */ 1321 public int getPositionX() 1322 { 1323 return -1; 1324 } 1325 1326 /** 1327 * @return current Y (-1 if all selected) 1328 */ 1329 public int getPositionY() 1330 { 1331 return -1; 1332 } 1333 1334 /** 1335 * @return current Z (-1 if all selected) 1336 */ 1337 public int getPositionZ() 1338 { 1339 return posZ; 1340 } 1341 1342 /** 1343 * @return current T (-1 if all selected) 1344 */ 1345 public int getPositionT() 1346 { 1347 return posT; 1348 } 1349 1350 /** 1351 * @return current C (-1 if all selected) 1352 */ 1353 public int getPositionC() 1354 { 1355 return posC; 1356 } 1357 1358 /** 1359 * Returns the 5D canvas position (-1 mean that the complete dimension is selected) 1360 */ 1361 public Point5D.Integer getPosition5D() 1362 { 1363 return new Point5D.Integer(getPositionX(), getPositionY(), getPositionZ(), getPositionT(), getPositionC()); 1364 } 1365 1366 /** 1367 * @return current Z (-1 if all selected) 1368 * @deprecated uses getPositionZ() instead 1369 */ 1370 @Deprecated 1371 public int getZ() 1372 { 1373 return getPositionZ(); 1374 } 1375 1376 /** 1377 * @return current T (-1 if all selected) 1378 * @deprecated uses getPositionT() instead 1379 */ 1380 @Deprecated 1381 public int getT() 1382 { 1383 return getPositionT(); 1384 } 1385 1386 /** 1387 * @return current C (-1 if all selected) 1388 * @deprecated uses getPositionC() instead 1389 */ 1390 @Deprecated 1391 public int getC() 1392 { 1393 return getPositionC(); 1394 } 1395 1396 /** 1397 * Get maximum position for specified dimension 1398 */ 1399 public double getMaxPosition(DimensionId dim) 1400 { 1401 switch (dim) 1402 { 1403 case X: 1404 return getMaxPositionX(); 1405 case Y: 1406 return getMaxPositionY(); 1407 case Z: 1408 return getMaxPositionZ(); 1409 case T: 1410 return getMaxPositionT(); 1411 case C: 1412 return getMaxPositionC(); 1413 } 1414 1415 return 0; 1416 } 1417 1418 /** 1419 * Get maximum X value 1420 */ 1421 public int getMaxPositionX() 1422 { 1423 final Sequence sequence = getSequence(); 1424 1425 // have to test this as we release sequence reference on closed 1426 if (sequence == null) 1427 return 0; 1428 1429 return Math.max(0, getImageSizeX() - 1); 1430 } 1431 1432 /** 1433 * Get maximum Y value 1434 */ 1435 public int getMaxPositionY() 1436 { 1437 final Sequence sequence = getSequence(); 1438 1439 // have to test this as we release sequence reference on closed 1440 if (sequence == null) 1441 return 0; 1442 1443 return Math.max(0, getImageSizeY() - 1); 1444 } 1445 1446 /** 1447 * Get maximum Z value 1448 */ 1449 public int getMaxPositionZ() 1450 { 1451 final Sequence sequence = getSequence(); 1452 1453 // have to test this as we release sequence reference on closed 1454 if (sequence == null) 1455 return 0; 1456 1457 return Math.max(0, getImageSizeZ() - 1); 1458 } 1459 1460 /** 1461 * Get maximum T value 1462 */ 1463 public int getMaxPositionT() 1464 { 1465 final Sequence sequence = getSequence(); 1466 1467 // have to test this as we release sequence reference on closed 1468 if (sequence == null) 1469 return 0; 1470 1471 return Math.max(0, getImageSizeT() - 1); 1472 } 1473 1474 /** 1475 * Get maximum C value 1476 */ 1477 public int getMaxPositionC() 1478 { 1479 final Sequence sequence = getSequence(); 1480 1481 // have to test this as we release sequence reference on closed 1482 if (sequence == null) 1483 return 0; 1484 1485 return Math.max(0, getImageSizeC() - 1); 1486 } 1487 1488 /** 1489 * Get the maximum 5D position for the canvas. 1490 * 1491 * @see #getPosition5D() 1492 */ 1493 public Point5D.Integer getMaxPosition5D() 1494 { 1495 return new Point5D.Integer(getMaxPositionX(), getMaxPositionY(), getMaxPositionZ(), getMaxPositionT(), 1496 getMaxPositionC()); 1497 } 1498 1499 /** 1500 * @deprecated Use {@link #getMaxPosition(DimensionId)} instead 1501 */ 1502 @Deprecated 1503 public double getMax(DimensionId dim) 1504 { 1505 return getMaxPosition(dim); 1506 } 1507 1508 /** 1509 * @deprecated Use {@link #getMaxPositionX()} instead 1510 */ 1511 @Deprecated 1512 public int getMaxX() 1513 { 1514 return getMaxPositionX(); 1515 } 1516 1517 /** 1518 * @deprecated Use {@link #getMaxPositionY()} instead 1519 */ 1520 @Deprecated 1521 public int getMaxY() 1522 { 1523 return getMaxPositionY(); 1524 } 1525 1526 /** 1527 * @deprecated Use {@link #getMaxPositionZ()} instead 1528 */ 1529 @Deprecated 1530 public int getMaxZ() 1531 { 1532 return getMaxPositionZ(); 1533 } 1534 1535 /** 1536 * @deprecated Use {@link #getMaxPositionT()} instead 1537 */ 1538 @Deprecated 1539 public int getMaxT() 1540 { 1541 return getMaxPositionT(); 1542 } 1543 1544 /** 1545 * @deprecated Use {@link #getMaxPositionC()} instead 1546 */ 1547 @Deprecated 1548 public int getMaxC() 1549 { 1550 return getMaxPositionC(); 1551 } 1552 1553 /** 1554 * Get canvas view size for specified Dimension 1555 */ 1556 public int getCanvasSize(DimensionId dim) 1557 { 1558 switch (dim) 1559 { 1560 case X: 1561 return getCanvasSizeX(); 1562 case Y: 1563 return getCanvasSizeY(); 1564 case Z: 1565 return getCanvasSizeZ(); 1566 case T: 1567 return getCanvasSizeT(); 1568 case C: 1569 return getCanvasSizeC(); 1570 } 1571 1572 // size not supported 1573 return -1; 1574 } 1575 1576 /** 1577 * Returns the canvas view size X. 1578 */ 1579 public int getCanvasSizeX() 1580 { 1581 final Component comp = getViewComponent(); 1582 int res = 0; 1583 1584 if (comp != null) 1585 { 1586 // by default we use view component width 1587 res = comp.getWidth(); 1588 // preferred width if size not yet set 1589 if (res == 0) 1590 res = comp.getPreferredSize().width; 1591 } 1592 1593 return res; 1594 } 1595 1596 /** 1597 * Returns the canvas view size Y. 1598 */ 1599 public int getCanvasSizeY() 1600 { 1601 final Component comp = getViewComponent(); 1602 int res = 0; 1603 1604 if (comp != null) 1605 { 1606 // by default we use view component width 1607 res = comp.getHeight(); 1608 // preferred width if size not yet set 1609 if (res == 0) 1610 res = comp.getPreferredSize().height; 1611 } 1612 1613 return res; 1614 } 1615 1616 /** 1617 * Returns the canvas view size Z. 1618 */ 1619 public int getCanvasSizeZ() 1620 { 1621 // by default : no Z dimension 1622 return 1; 1623 } 1624 1625 /** 1626 * Returns the canvas view size T. 1627 */ 1628 public int getCanvasSizeT() 1629 { 1630 // by default : no T dimension 1631 return 1; 1632 } 1633 1634 /** 1635 * Returns the canvas view size C. 1636 */ 1637 public int getCanvasSizeC() 1638 { 1639 // by default : no C dimension 1640 return 1; 1641 } 1642 1643 /** 1644 * Returns the mouse position (in canvas coordinate space). 1645 */ 1646 public Point getMousePos() 1647 { 1648 return (Point) mousePos.clone(); 1649 } 1650 1651 /** 1652 * Get mouse image position for specified Dimension 1653 */ 1654 public double getMouseImagePos(DimensionId dim) 1655 { 1656 switch (dim) 1657 { 1658 case X: 1659 return getMouseImagePosX(); 1660 case Y: 1661 return getMouseImagePosY(); 1662 case Z: 1663 return getMouseImagePosZ(); 1664 case T: 1665 return getMouseImagePosT(); 1666 case C: 1667 return getMouseImagePosC(); 1668 } 1669 1670 return 0; 1671 } 1672 1673 /** 1674 * mouse X image position 1675 */ 1676 public double getMouseImagePosX() 1677 { 1678 // default implementation 1679 return getPositionX(); 1680 } 1681 1682 /** 1683 * mouse Y image position 1684 */ 1685 public double getMouseImagePosY() 1686 { 1687 // default implementation 1688 return getPositionY(); 1689 } 1690 1691 /** 1692 * mouse Z image position 1693 */ 1694 public double getMouseImagePosZ() 1695 { 1696 // default implementation 1697 return getPositionZ(); 1698 } 1699 1700 /** 1701 * mouse T image position 1702 */ 1703 public double getMouseImagePosT() 1704 { 1705 // default implementation 1706 return getPositionT(); 1707 } 1708 1709 /** 1710 * mouse C image position 1711 */ 1712 public double getMouseImagePosC() 1713 { 1714 // default implementation 1715 return getPositionC(); 1716 } 1717 1718 /** 1719 * Returns the 5D mouse image position 1720 */ 1721 public Point5D.Double getMouseImagePos5D() 1722 { 1723 return new Point5D.Double(getMouseImagePosX(), getMouseImagePosY(), getMouseImagePosZ(), getMouseImagePosT(), 1724 getMouseImagePosC()); 1725 } 1726 1727 /** 1728 * Get offset for specified Dimension 1729 */ 1730 public int getOffset(DimensionId dim) 1731 { 1732 switch (dim) 1733 { 1734 case X: 1735 return getOffsetX(); 1736 case Y: 1737 return getOffsetY(); 1738 case Z: 1739 return getOffsetZ(); 1740 case T: 1741 return getOffsetT(); 1742 case C: 1743 return getOffsetC(); 1744 } 1745 1746 return 0; 1747 } 1748 1749 /** 1750 * X offset 1751 */ 1752 public int getOffsetX() 1753 { 1754 return 0; 1755 } 1756 1757 /** 1758 * Y offset 1759 */ 1760 public int getOffsetY() 1761 { 1762 return 0; 1763 } 1764 1765 /** 1766 * Z offset 1767 */ 1768 public int getOffsetZ() 1769 { 1770 return 0; 1771 } 1772 1773 /** 1774 * T offset 1775 */ 1776 public int getOffsetT() 1777 { 1778 return 0; 1779 } 1780 1781 /** 1782 * C offset 1783 */ 1784 public int getOffsetC() 1785 { 1786 return 0; 1787 } 1788 1789 /** 1790 * Returns the 5D offset. 1791 */ 1792 public Point5D.Integer getOffset5D() 1793 { 1794 return new Point5D.Integer(getOffsetX(), getOffsetY(), getOffsetZ(), getOffsetT(), getOffsetC()); 1795 } 1796 1797 /** 1798 * X image offset 1799 * 1800 * @deprecated use getOffsetX() instead 1801 */ 1802 @Deprecated 1803 public int getImageOffsetX() 1804 { 1805 return 0; 1806 } 1807 1808 /** 1809 * Y image offset 1810 * 1811 * @deprecated use getOffsetY() instead 1812 */ 1813 @Deprecated 1814 public int getImageOffsetY() 1815 { 1816 return 0; 1817 } 1818 1819 /** 1820 * Z image offset 1821 * 1822 * @deprecated use getOffsetZ() instead 1823 */ 1824 @Deprecated 1825 public int getImageOffsetZ() 1826 { 1827 return 0; 1828 } 1829 1830 /** 1831 * T image offset 1832 * 1833 * @deprecated use getOffsetT() instead 1834 */ 1835 @Deprecated 1836 public int getImageOffsetT() 1837 { 1838 return 0; 1839 } 1840 1841 /** 1842 * C image offset 1843 * 1844 * @deprecated use getOffsetC() instead 1845 */ 1846 @Deprecated 1847 public int getImageOffsetC() 1848 { 1849 return 0; 1850 } 1851 1852 /** 1853 * X canvas offset 1854 * 1855 * @deprecated use getOffsetX() instead 1856 */ 1857 @Deprecated 1858 public int getCanvasOffsetX() 1859 { 1860 return 0; 1861 } 1862 1863 /** 1864 * Y canvas offset 1865 * 1866 * @deprecated use getOffsetY() instead 1867 */ 1868 @Deprecated 1869 public int getCanvasOffsetY() 1870 { 1871 return 0; 1872 } 1873 1874 /** 1875 * Z canvas offset 1876 * 1877 * @deprecated use getOffsetZ() instead 1878 */ 1879 @Deprecated 1880 public int getCanvasOffsetZ() 1881 { 1882 return 0; 1883 } 1884 1885 /** 1886 * T canvas offset 1887 * 1888 * @deprecated use getOffsetT() instead 1889 */ 1890 @Deprecated 1891 public int getCanvasOffsetT() 1892 { 1893 return 0; 1894 } 1895 1896 /** 1897 * C canvas offset 1898 * 1899 * @deprecated use getOffsetC() instead 1900 */ 1901 @Deprecated 1902 public int getCanvasOffsetC() 1903 { 1904 return 0; 1905 } 1906 1907 /** 1908 * X scale factor 1909 * 1910 * @deprecated use getScaleX() instead 1911 */ 1912 @Deprecated 1913 public double getScaleFactorX() 1914 { 1915 return getScaleX(); 1916 } 1917 1918 /** 1919 * Y scale factor 1920 * 1921 * @deprecated use getScaleY() instead 1922 */ 1923 @Deprecated 1924 public double getScaleFactorY() 1925 { 1926 return getScaleY(); 1927 } 1928 1929 /** 1930 * Z scale factor 1931 * 1932 * @deprecated use getScaleZ() instead 1933 */ 1934 @Deprecated 1935 public double getScaleFactorZ() 1936 { 1937 return getScaleZ(); 1938 } 1939 1940 /** 1941 * T scale factor 1942 * 1943 * @deprecated use getScaleT() instead 1944 */ 1945 @Deprecated 1946 public double getScaleFactorT() 1947 { 1948 return getScaleT(); 1949 } 1950 1951 /** 1952 * C scale factor 1953 * 1954 * @deprecated use getScaleC() instead 1955 */ 1956 @Deprecated 1957 public double getScaleFactorC() 1958 { 1959 return getScaleC(); 1960 } 1961 1962 /** 1963 * Get scale factor for specified Dimension 1964 */ 1965 public double getScale(DimensionId dim) 1966 { 1967 switch (dim) 1968 { 1969 case X: 1970 return getScaleX(); 1971 case Y: 1972 return getScaleY(); 1973 case Z: 1974 return getScaleZ(); 1975 case T: 1976 return getScaleT(); 1977 case C: 1978 return getScaleC(); 1979 } 1980 1981 return 1d; 1982 } 1983 1984 /** 1985 * X scale factor 1986 */ 1987 public double getScaleX() 1988 { 1989 return 1d; 1990 } 1991 1992 /** 1993 * Y scale factor 1994 */ 1995 public double getScaleY() 1996 { 1997 return 1d; 1998 } 1999 2000 /** 2001 * Z scale factor 2002 */ 2003 public double getScaleZ() 2004 { 2005 return 1d; 2006 } 2007 2008 /** 2009 * T scale factor 2010 */ 2011 public double getScaleT() 2012 { 2013 return 1d; 2014 } 2015 2016 /** 2017 * C scale factor 2018 */ 2019 public double getScaleC() 2020 { 2021 return 1d; 2022 } 2023 2024 /** 2025 * Get rotation angle (radian) for specified Dimension 2026 */ 2027 public double getRotation(DimensionId dim) 2028 { 2029 switch (dim) 2030 { 2031 case X: 2032 return getRotationX(); 2033 case Y: 2034 return getRotationY(); 2035 case Z: 2036 return getRotationZ(); 2037 case T: 2038 return getRotationT(); 2039 case C: 2040 return getRotationC(); 2041 } 2042 2043 return 1d; 2044 } 2045 2046 /** 2047 * X rotation angle (radian) 2048 */ 2049 public double getRotationX() 2050 { 2051 return 0d; 2052 } 2053 2054 /** 2055 * Y rotation angle (radian) 2056 */ 2057 public double getRotationY() 2058 { 2059 return 0d; 2060 } 2061 2062 /** 2063 * Z rotation angle (radian) 2064 */ 2065 public double getRotationZ() 2066 { 2067 return 0d; 2068 } 2069 2070 /** 2071 * T rotation angle (radian) 2072 */ 2073 public double getRotationT() 2074 { 2075 return 0d; 2076 } 2077 2078 /** 2079 * C rotation angle (radian) 2080 */ 2081 public double getRotationC() 2082 { 2083 return 0d; 2084 } 2085 2086 /** 2087 * Get image size for specified Dimension 2088 */ 2089 public int getImageSize(DimensionId dim) 2090 { 2091 switch (dim) 2092 { 2093 case X: 2094 return getImageSizeX(); 2095 case Y: 2096 return getImageSizeY(); 2097 case Z: 2098 return getImageSizeZ(); 2099 case T: 2100 return getImageSizeT(); 2101 case C: 2102 return getImageSizeC(); 2103 } 2104 2105 return 0; 2106 } 2107 2108 /** 2109 * Get image size X 2110 */ 2111 public int getImageSizeX() 2112 { 2113 final Sequence seq = getSequence(); 2114 2115 if (seq != null) 2116 return seq.getSizeX(); 2117 2118 return 0; 2119 } 2120 2121 /** 2122 * Get image size Y 2123 */ 2124 public int getImageSizeY() 2125 { 2126 final Sequence seq = getSequence(); 2127 2128 if (seq != null) 2129 return seq.getSizeY(); 2130 2131 return 0; 2132 } 2133 2134 /** 2135 * Get image size Z 2136 */ 2137 public int getImageSizeZ() 2138 { 2139 final Sequence seq = getSequence(); 2140 2141 if (seq != null) 2142 return seq.getSizeZ(); 2143 2144 return 0; 2145 } 2146 2147 /** 2148 * Get image size T 2149 */ 2150 public int getImageSizeT() 2151 { 2152 final Sequence seq = getSequence(); 2153 2154 if (seq != null) 2155 return seq.getSizeT(); 2156 2157 return 0; 2158 } 2159 2160 /** 2161 * Get image size C 2162 */ 2163 public int getImageSizeC() 2164 { 2165 final Sequence seq = getSequence(); 2166 2167 if (seq != null) 2168 return seq.getSizeC(); 2169 2170 return 0; 2171 } 2172 2173 /** 2174 * Get image size in canvas pixel coordinate for specified Dimension 2175 * 2176 * @deprecated doesn't take rotation transformation in account.<br> 2177 * Use IcyCanvasXD.getImageCanvasSize(..) instead 2178 */ 2179 @Deprecated 2180 public int getImageCanvasSize(DimensionId dim) 2181 { 2182 switch (dim) 2183 { 2184 case X: 2185 return getImageCanvasSizeX(); 2186 case Y: 2187 return getImageCanvasSizeY(); 2188 case Z: 2189 return getImageCanvasSizeZ(); 2190 case T: 2191 return getImageCanvasSizeT(); 2192 case C: 2193 return getImageCanvasSizeC(); 2194 } 2195 2196 return 0; 2197 } 2198 2199 /** 2200 * Get image size X in canvas pixel coordinate 2201 * 2202 * @deprecated doesn't take rotation transformation in account.<br> 2203 * Use IcyCanvasXD.getImageCanvasSize(..) instead 2204 */ 2205 @Deprecated 2206 public int getImageCanvasSizeX() 2207 { 2208 return imageToCanvasDeltaX(getImageSizeX()); 2209 } 2210 2211 /** 2212 * Get image size Y in canvas pixel coordinate 2213 * 2214 * @deprecated doesn't take rotation transformation in account.<br> 2215 * Use IcyCanvasXD.getImageCanvasSize(..) instead 2216 */ 2217 @Deprecated 2218 public int getImageCanvasSizeY() 2219 { 2220 return imageToCanvasDeltaY(getImageSizeY()); 2221 } 2222 2223 /** 2224 * Get image size Z in canvas pixel coordinate 2225 * 2226 * @deprecated doesn't take rotation transformation in account.<br> 2227 * Use IcyCanvasXD.getImageCanvasSize(..) instead 2228 */ 2229 @Deprecated 2230 public int getImageCanvasSizeZ() 2231 { 2232 return imageToCanvasDeltaZ(getImageSizeZ()); 2233 } 2234 2235 /** 2236 * Get image size T in canvas pixel coordinate 2237 * 2238 * @deprecated doesn't take rotation transformation in account.<br> 2239 * Use IcyCanvasXD.getImageCanvasSize(..) instead 2240 */ 2241 @Deprecated 2242 public int getImageCanvasSizeT() 2243 { 2244 return imageToCanvasDeltaT(getImageSizeT()); 2245 } 2246 2247 /** 2248 * Get image size C in canvas pixel coordinate 2249 * 2250 * @deprecated doesn't take rotation transformation in account.<br> 2251 * Use IcyCanvasXD.getImageCanvasSize(..) instead 2252 */ 2253 @Deprecated 2254 public int getImageCanvasSizeC() 2255 { 2256 return imageToCanvasDeltaC(getImageSizeC()); 2257 } 2258 2259 /** 2260 * Set position for specified dimension 2261 */ 2262 public void setPosition(DimensionId dim, int value) 2263 { 2264 switch (dim) 2265 { 2266 case X: 2267 setPositionX(value); 2268 break; 2269 case Y: 2270 setPositionY(value); 2271 break; 2272 case Z: 2273 setPositionZ(value); 2274 break; 2275 case T: 2276 setPositionT(value); 2277 break; 2278 case C: 2279 setPositionC(value); 2280 break; 2281 } 2282 } 2283 2284 /** 2285 * Set Z position 2286 * 2287 * @deprecated uses setPositionZ(int) instead 2288 */ 2289 @Deprecated 2290 public void setZ(int z) 2291 { 2292 setPositionZ(z); 2293 } 2294 2295 /** 2296 * Set T position 2297 * 2298 * @deprecated uses setPositionT(int) instead 2299 */ 2300 @Deprecated 2301 public void setT(int t) 2302 { 2303 setPositionT(t); 2304 } 2305 2306 /** 2307 * Set C position 2308 * 2309 * @deprecated uses setPositionC(int) instead 2310 */ 2311 @Deprecated 2312 public void setC(int c) 2313 { 2314 setPositionC(c); 2315 } 2316 2317 /** 2318 * Set X position 2319 */ 2320 public void setPositionX(int x) 2321 { 2322 final int adjX = Math.max(-1, Math.min(x, getMaxPositionX())); 2323 2324 if (getPositionX() != adjX) 2325 setPositionXInternal(adjX); 2326 } 2327 2328 /** 2329 * Set Y position 2330 */ 2331 public void setPositionY(int y) 2332 { 2333 final int adjY = Math.max(-1, Math.min(y, getMaxPositionY())); 2334 2335 if (getPositionY() != adjY) 2336 setPositionYInternal(adjY); 2337 } 2338 2339 /** 2340 * Set Z position 2341 */ 2342 public void setPositionZ(int z) 2343 { 2344 final int adjZ = Math.max(-1, Math.min(z, getMaxPositionZ())); 2345 2346 if (getPositionZ() != adjZ) 2347 setPositionZInternal(adjZ); 2348 } 2349 2350 /** 2351 * Set T position 2352 */ 2353 public void setPositionT(int t) 2354 { 2355 final int adjT = Math.max(-1, Math.min(t, getMaxPositionT())); 2356 2357 if (getPositionT() != adjT) 2358 setPositionTInternal(adjT); 2359 } 2360 2361 /** 2362 * Set C position 2363 */ 2364 public void setPositionC(int c) 2365 { 2366 final int adjC = Math.max(-1, Math.min(c, getMaxPositionC())); 2367 2368 if (getPositionC() != adjC) 2369 setPositionCInternal(adjC); 2370 } 2371 2372 /** 2373 * Set X position internal 2374 */ 2375 protected void setPositionXInternal(int x) 2376 { 2377 posX = x; 2378 // common process on position change 2379 positionChanged(DimensionId.X); 2380 } 2381 2382 /** 2383 * Set Y position internal 2384 */ 2385 protected void setPositionYInternal(int y) 2386 { 2387 posY = y; 2388 // common process on position change 2389 positionChanged(DimensionId.Y); 2390 } 2391 2392 /** 2393 * Set Z position internal 2394 */ 2395 protected void setPositionZInternal(int z) 2396 { 2397 posZ = z; 2398 // common process on position change 2399 positionChanged(DimensionId.Z); 2400 } 2401 2402 /** 2403 * Set T position internal 2404 */ 2405 protected void setPositionTInternal(int t) 2406 { 2407 posT = t; 2408 // common process on position change 2409 positionChanged(DimensionId.T); 2410 } 2411 2412 /** 2413 * Set C position internal 2414 */ 2415 protected void setPositionCInternal(int c) 2416 { 2417 posC = c; 2418 // common process on position change 2419 positionChanged(DimensionId.C); 2420 } 2421 2422 /** 2423 * Set mouse position (in canvas coordinate space).<br> 2424 * The method returns <code>true</code> if the mouse position actually changed. 2425 */ 2426 public boolean setMousePos(int x, int y) 2427 { 2428 if ((mousePos.x != x) || (mousePos.y != y)) 2429 { 2430 mousePos.x = x; 2431 mousePos.y = y; 2432 2433 // mouse image position probably changed so this method should be overridden 2434 // to implement the correct calculation for the mouse image position change 2435 2436 return true; 2437 } 2438 2439 return false; 2440 } 2441 2442 /** 2443 * Set mouse position (in canvas coordinate space) 2444 */ 2445 public void setMousePos(Point point) 2446 { 2447 setMousePos(point.x, point.y); 2448 } 2449 2450 /** 2451 * Set mouse image position for specified dimension (required for synchronization) 2452 */ 2453 public void setMouseImagePos(DimensionId dim, double value) 2454 { 2455 switch (dim) 2456 { 2457 case X: 2458 setMouseImagePosX(value); 2459 break; 2460 case Y: 2461 setMouseImagePosY(value); 2462 break; 2463 case Z: 2464 setMouseImagePosZ(value); 2465 break; 2466 case T: 2467 setMouseImagePosT(value); 2468 break; 2469 case C: 2470 setMouseImagePosC(value); 2471 break; 2472 } 2473 } 2474 2475 /** 2476 * Set mouse X image position 2477 */ 2478 public void setMouseImagePosX(double value) 2479 { 2480 if (getMouseImagePosX() != value) 2481 // internal set 2482 setMouseImagePosXInternal(value); 2483 } 2484 2485 /** 2486 * Set mouse Y image position 2487 */ 2488 public void setMouseImagePosY(double value) 2489 { 2490 if (getMouseImagePosY() != value) 2491 // internal set 2492 setMouseImagePosYInternal(value); 2493 } 2494 2495 /** 2496 * Set mouse Z image position 2497 */ 2498 public void setMouseImagePosZ(double value) 2499 { 2500 if (getMouseImagePosZ() != value) 2501 // internal set 2502 setMouseImagePosZInternal(value); 2503 } 2504 2505 /** 2506 * Set mouse T image position 2507 */ 2508 public void setMouseImagePosT(double value) 2509 { 2510 if (getMouseImagePosT() != value) 2511 // internal set 2512 setMouseImagePosTInternal(value); 2513 } 2514 2515 /** 2516 * Set mouse C image position 2517 */ 2518 public void setMouseImagePosC(double value) 2519 { 2520 if (getMouseImagePosC() != value) 2521 // internal set 2522 setMouseImagePosCInternal(value); 2523 } 2524 2525 /** 2526 * Set offset X internal 2527 */ 2528 protected void setMouseImagePosXInternal(double value) 2529 { 2530 // notify change 2531 mouseImagePositionChanged(DimensionId.X); 2532 } 2533 2534 /** 2535 * Set offset Y internal 2536 */ 2537 protected void setMouseImagePosYInternal(double value) 2538 { 2539 // notify change 2540 mouseImagePositionChanged(DimensionId.Y); 2541 } 2542 2543 /** 2544 * Set offset Z internal 2545 */ 2546 protected void setMouseImagePosZInternal(double value) 2547 { 2548 // notify change 2549 mouseImagePositionChanged(DimensionId.Z); 2550 } 2551 2552 /** 2553 * Set offset T internal 2554 */ 2555 protected void setMouseImagePosTInternal(double value) 2556 { 2557 // notify change 2558 mouseImagePositionChanged(DimensionId.T); 2559 } 2560 2561 /** 2562 * Set offset C internal 2563 */ 2564 protected void setMouseImagePosCInternal(double value) 2565 { 2566 // notify change 2567 mouseImagePositionChanged(DimensionId.C); 2568 } 2569 2570 /** 2571 * Set offset for specified dimension 2572 */ 2573 public void setOffset(DimensionId dim, int value) 2574 { 2575 switch (dim) 2576 { 2577 case X: 2578 setOffsetX(value); 2579 break; 2580 case Y: 2581 setOffsetY(value); 2582 break; 2583 case Z: 2584 setOffsetZ(value); 2585 break; 2586 case T: 2587 setOffsetT(value); 2588 break; 2589 case C: 2590 setOffsetC(value); 2591 break; 2592 } 2593 } 2594 2595 /** 2596 * Set offset X 2597 */ 2598 public void setOffsetX(int value) 2599 { 2600 if (getOffsetX() != value) 2601 // internal set 2602 setOffsetXInternal(value); 2603 } 2604 2605 /** 2606 * Set offset Y 2607 */ 2608 public void setOffsetY(int value) 2609 { 2610 if (getOffsetY() != value) 2611 // internal set 2612 setOffsetYInternal(value); 2613 } 2614 2615 /** 2616 * Set offset Z 2617 */ 2618 public void setOffsetZ(int value) 2619 { 2620 if (getOffsetZ() != value) 2621 // internal set 2622 setOffsetZInternal(value); 2623 } 2624 2625 /** 2626 * Set offset T 2627 */ 2628 public void setOffsetT(int value) 2629 { 2630 if (getOffsetT() != value) 2631 // internal set 2632 setOffsetTInternal(value); 2633 } 2634 2635 /** 2636 * Set offset C 2637 */ 2638 public void setOffsetC(int value) 2639 { 2640 if (getOffsetC() != value) 2641 // internal set 2642 setOffsetCInternal(value); 2643 } 2644 2645 /** 2646 * Set offset X internal 2647 */ 2648 protected void setOffsetXInternal(int value) 2649 { 2650 // notify change 2651 offsetChanged(DimensionId.X); 2652 } 2653 2654 /** 2655 * Set offset Y internal 2656 */ 2657 protected void setOffsetYInternal(int value) 2658 { 2659 // notify change 2660 offsetChanged(DimensionId.Y); 2661 } 2662 2663 /** 2664 * Set offset Z internal 2665 */ 2666 protected void setOffsetZInternal(int value) 2667 { 2668 // notify change 2669 offsetChanged(DimensionId.Z); 2670 } 2671 2672 /** 2673 * Set offset T internal 2674 */ 2675 protected void setOffsetTInternal(int value) 2676 { 2677 // notify change 2678 offsetChanged(DimensionId.T); 2679 } 2680 2681 /** 2682 * Set offset C internal 2683 */ 2684 protected void setOffsetCInternal(int value) 2685 { 2686 // notify change 2687 offsetChanged(DimensionId.C); 2688 } 2689 2690 /** 2691 * Set scale factor for specified dimension 2692 */ 2693 public void setScale(DimensionId dim, double value) 2694 { 2695 switch (dim) 2696 { 2697 case X: 2698 setScaleX(value); 2699 break; 2700 case Y: 2701 setScaleY(value); 2702 break; 2703 case Z: 2704 setScaleZ(value); 2705 break; 2706 case T: 2707 setScaleT(value); 2708 break; 2709 case C: 2710 setScaleC(value); 2711 break; 2712 } 2713 } 2714 2715 /** 2716 * Set scale factor X 2717 */ 2718 public void setScaleX(double value) 2719 { 2720 if (getScaleX() != value) 2721 // internal set 2722 setScaleXInternal(value); 2723 } 2724 2725 /** 2726 * Set scale factor Y 2727 */ 2728 public void setScaleY(double value) 2729 { 2730 if (getScaleY() != value) 2731 // internal set 2732 setScaleYInternal(value); 2733 } 2734 2735 /** 2736 * Set scale factor Z 2737 */ 2738 public void setScaleZ(double value) 2739 { 2740 if (getScaleZ() != value) 2741 // internal set 2742 setScaleZInternal(value); 2743 } 2744 2745 /** 2746 * Set scale factor T 2747 */ 2748 public void setScaleT(double value) 2749 { 2750 if (getScaleT() != value) 2751 // internal set 2752 setScaleTInternal(value); 2753 } 2754 2755 /** 2756 * Set scale factor C 2757 */ 2758 public void setScaleC(double value) 2759 { 2760 if (getScaleC() != value) 2761 // internal set 2762 setScaleCInternal(value); 2763 } 2764 2765 /** 2766 * Set scale factor X internal 2767 */ 2768 protected void setScaleXInternal(double value) 2769 { 2770 // notify change 2771 scaleChanged(DimensionId.X); 2772 } 2773 2774 /** 2775 * Set scale factor Y internal 2776 */ 2777 protected void setScaleYInternal(double value) 2778 { 2779 // notify change 2780 scaleChanged(DimensionId.Y); 2781 } 2782 2783 /** 2784 * Set scale factor Z internal 2785 */ 2786 protected void setScaleZInternal(double value) 2787 { 2788 // notify change 2789 scaleChanged(DimensionId.Z); 2790 } 2791 2792 /** 2793 * Set scale factor T internal 2794 */ 2795 protected void setScaleTInternal(double value) 2796 { 2797 // notify change 2798 scaleChanged(DimensionId.T); 2799 } 2800 2801 /** 2802 * Set scale factor C internal 2803 */ 2804 protected void setScaleCInternal(double value) 2805 { 2806 // notify change 2807 scaleChanged(DimensionId.C); 2808 } 2809 2810 /** 2811 * Set rotation angle (radian) for specified dimension 2812 */ 2813 public void setRotation(DimensionId dim, double value) 2814 { 2815 switch (dim) 2816 { 2817 case X: 2818 setRotationX(value); 2819 break; 2820 case Y: 2821 setRotationY(value); 2822 break; 2823 case Z: 2824 setRotationZ(value); 2825 break; 2826 case T: 2827 setRotationT(value); 2828 break; 2829 case C: 2830 setRotationC(value); 2831 break; 2832 } 2833 } 2834 2835 /** 2836 * Set X rotation angle (radian) 2837 */ 2838 public void setRotationX(double value) 2839 { 2840 if (getRotationX() != value) 2841 // internal set 2842 setRotationXInternal(value); 2843 } 2844 2845 /** 2846 * Set Y rotation angle (radian) 2847 */ 2848 public void setRotationY(double value) 2849 { 2850 if (getRotationY() != value) 2851 // internal set 2852 setRotationYInternal(value); 2853 } 2854 2855 /** 2856 * Set Z rotation angle (radian) 2857 */ 2858 public void setRotationZ(double value) 2859 { 2860 if (getRotationZ() != value) 2861 // internal set 2862 setRotationZInternal(value); 2863 } 2864 2865 /** 2866 * Set T rotation angle (radian) 2867 */ 2868 public void setRotationT(double value) 2869 { 2870 if (getRotationT() != value) 2871 // internal set 2872 setRotationTInternal(value); 2873 } 2874 2875 /** 2876 * Set C rotation angle (radian) 2877 */ 2878 public void setRotationC(double value) 2879 { 2880 if (getRotationC() != value) 2881 // internal set 2882 setRotationCInternal(value); 2883 } 2884 2885 /** 2886 * Set X rotation angle internal 2887 */ 2888 protected void setRotationXInternal(double value) 2889 { 2890 // notify change 2891 rotationChanged(DimensionId.X); 2892 } 2893 2894 /** 2895 * Set Y rotation angle internal 2896 */ 2897 protected void setRotationYInternal(double value) 2898 { 2899 // notify change 2900 rotationChanged(DimensionId.Y); 2901 } 2902 2903 /** 2904 * Set Z rotation angle internal 2905 */ 2906 protected void setRotationZInternal(double value) 2907 { 2908 // notify change 2909 rotationChanged(DimensionId.Z); 2910 } 2911 2912 /** 2913 * Set T rotation angle internal 2914 */ 2915 protected void setRotationTInternal(double value) 2916 { 2917 // notify change 2918 rotationChanged(DimensionId.T); 2919 } 2920 2921 /** 2922 * Set C rotation angle internal 2923 */ 2924 protected void setRotationCInternal(double value) 2925 { 2926 // notify change 2927 rotationChanged(DimensionId.C); 2928 } 2929 2930 /** 2931 * Called when mouse image position changed 2932 */ 2933 public void mouseImagePositionChanged(DimensionId dim) 2934 { 2935 // handle with updater 2936 updater.changed(new IcyCanvasEvent(this, IcyCanvasEventType.MOUSE_IMAGE_POSITION_CHANGED, dim)); 2937 } 2938 2939 /** 2940 * Called when canvas offset changed 2941 */ 2942 public void offsetChanged(DimensionId dim) 2943 { 2944 // handle with updater 2945 updater.changed(new IcyCanvasEvent(this, IcyCanvasEventType.OFFSET_CHANGED, dim)); 2946 } 2947 2948 /** 2949 * Called when scale factor changed 2950 */ 2951 public void scaleChanged(DimensionId dim) 2952 { 2953 // handle with updater 2954 updater.changed(new IcyCanvasEvent(this, IcyCanvasEventType.SCALE_CHANGED, dim)); 2955 } 2956 2957 /** 2958 * Called when rotation angle changed 2959 */ 2960 public void rotationChanged(DimensionId dim) 2961 { 2962 // handle with updater 2963 updater.changed(new IcyCanvasEvent(this, IcyCanvasEventType.ROTATION_CHANGED, dim)); 2964 } 2965 2966 /** 2967 * Convert specified canvas delta X to image delta X.<br> 2968 * WARNING: Does not take in account the rotation transformation.<br> 2969 * Use the IcyCanvasXD.canvasToImageDelta(...) method instead for rotation transformed delta. 2970 */ 2971 public double canvasToImageDeltaX(int value) 2972 { 2973 return value / getScaleX(); 2974 } 2975 2976 /** 2977 * Convert specified canvas delta Y to image delta Y.<br> 2978 * WARNING: Does not take in account the rotation transformation.<br> 2979 * Use the IcyCanvasXD.canvasToImageDelta(...) method instead for rotation transformed delta. 2980 */ 2981 public double canvasToImageDeltaY(int value) 2982 { 2983 return value / getScaleY(); 2984 } 2985 2986 /** 2987 * Convert specified canvas delta Z to image delta Z.<br> 2988 * WARNING: Does not take in account the rotation transformation.<br> 2989 * Use the IcyCanvasXD.canvasToImageDelta(...) method instead for rotation transformed delta. 2990 */ 2991 public double canvasToImageDeltaZ(int value) 2992 { 2993 return value / getScaleZ(); 2994 } 2995 2996 /** 2997 * Convert specified canvas delta T to image delta T.<br> 2998 * WARNING: Does not take in account the rotation transformation.<br> 2999 * Use the IcyCanvasXD.canvasToImageDelta(...) method instead for rotation transformed delta. 3000 */ 3001 public double canvasToImageDeltaT(int value) 3002 { 3003 return value / getScaleT(); 3004 } 3005 3006 /** 3007 * Convert specified canvas delta C to image delta C.<br> 3008 * WARNING: Does not take in account the rotation transformation.<br> 3009 * Use the IcyCanvasXD.canvasToImageDelta(...) method instead for rotation transformed delta. 3010 */ 3011 public double canvasToImageDeltaC(int value) 3012 { 3013 return value / getScaleC(); 3014 } 3015 3016 /** 3017 * Convert specified canvas delta X to log image delta X.<br> 3018 * The conversion is still affected by zoom ratio but with specified logarithm form.<br> 3019 * WARNING: Does not take in account the rotation transformation.<br> 3020 * Use the IcyCanvasXD.canvasToImageLogDelta(...) method instead for rotation transformed delta. 3021 */ 3022 public double canvasToImageLogDeltaX(int value, double logFactor) 3023 { 3024 final double scaleFactor = getScaleX(); 3025 // keep the zoom ratio but in a log perspective 3026 return value / (scaleFactor / Math.pow(10, Math.log10(scaleFactor) / logFactor)); 3027 } 3028 3029 /** 3030 * Convert specified canvas delta X to log image delta X.<br> 3031 * The conversion is still affected by zoom ratio but with logarithm form.<br> 3032 * WARNING: Does not take in account the rotation transformation.<br> 3033 * Use the IcyCanvasXD.canvasToImageLogDelta(...) method instead for rotation transformed delta. 3034 */ 3035 public double canvasToImageLogDeltaX(int value) 3036 { 3037 return canvasToImageLogDeltaX(value, 5d); 3038 } 3039 3040 /** 3041 * Convert specified canvas delta Y to log image delta Y.<br> 3042 * The conversion is still affected by zoom ratio but with specified logarithm form.<br> 3043 * WARNING: Does not take in account the rotation transformation.<br> 3044 * Use the IcyCanvasXD.canvasToImageLogDelta(...) method instead for rotation transformed delta. 3045 */ 3046 public double canvasToImageLogDeltaY(int value, double logFactor) 3047 { 3048 final double scaleFactor = getScaleY(); 3049 // keep the zoom ratio but in a log perspective 3050 return value / (scaleFactor / Math.pow(10, Math.log10(scaleFactor) / logFactor)); 3051 } 3052 3053 /** 3054 * Convert specified canvas delta Y to log image delta Y.<br> 3055 * The conversion is still affected by zoom ratio but with logarithm form.<br> 3056 * WARNING: Does not take in account the rotation transformation.<br> 3057 * Use the IcyCanvasXD.canvasToImageLogDelta(...) method instead for rotation transformed delta. 3058 */ 3059 public double canvasToImageLogDeltaY(int value) 3060 { 3061 return canvasToImageLogDeltaY(value, 5d); 3062 } 3063 3064 /** 3065 * Convert specified canvas delta Z to log image delta Z.<br> 3066 * The conversion is still affected by zoom ratio but with specified logarithm form.<br> 3067 * WARNING: Does not take in account the rotation transformation.<br> 3068 * Use the IcyCanvasXD.canvasToImageLogDelta(...) method instead for rotation transformed delta. 3069 */ 3070 public double canvasToImageLogDeltaZ(int value, double logFactor) 3071 { 3072 final double scaleFactor = getScaleZ(); 3073 // keep the zoom ratio but in a log perspective 3074 return value / (scaleFactor / Math.pow(10, Math.log10(scaleFactor) / logFactor)); 3075 } 3076 3077 /** 3078 * Convert specified canvas delta Z to log image delta Z.<br> 3079 * The conversion is still affected by zoom ratio but with logarithm form.<br> 3080 * WARNING: Does not take in account the rotation transformation.<br> 3081 * Use the IcyCanvasXD.canvasToImageLogDelta(...) method instead for rotation transformed delta. 3082 */ 3083 public double canvasToImageLogDeltaZ(int value) 3084 { 3085 return canvasToImageLogDeltaZ(value, 5d); 3086 } 3087 3088 /** 3089 * Convert specified canvas X coordinate to image X coordinate 3090 * 3091 * @deprecated Cannot give correct result if rotation is applied so use 3092 * IcyCanvasXD.canvasToImage(...) instead 3093 */ 3094 @Deprecated 3095 public double canvasToImageX(int value) 3096 { 3097 return canvasToImageDeltaX(value - getOffsetX()); 3098 } 3099 3100 /** 3101 * Convert specified canvas Y coordinate to image Y coordinate 3102 * 3103 * @deprecated Cannot give correct result if rotation is applied so use 3104 * IcyCanvasXD.canvasToImage(...) instead 3105 */ 3106 @Deprecated 3107 public double canvasToImageY(int value) 3108 { 3109 return canvasToImageDeltaY(value - getOffsetY()); 3110 } 3111 3112 /** 3113 * Convert specified canvas Z coordinate to image Z coordinate 3114 * 3115 * @deprecated Cannot give correct result if rotation is applied so use 3116 * IcyCanvasXD.canvasToImage(...) instead 3117 */ 3118 @Deprecated 3119 public double canvasToImageZ(int value) 3120 { 3121 return canvasToImageDeltaZ(value - getOffsetZ()); 3122 } 3123 3124 /** 3125 * Convert specified canvas T coordinate to image T coordinate 3126 * 3127 * @deprecated Cannot give correct result if rotation is applied so use 3128 * IcyCanvasXD.canvasToImage(...) instead 3129 */ 3130 @Deprecated 3131 public double canvasToImageT(int value) 3132 { 3133 return canvasToImageDeltaT(value - getOffsetT()); 3134 } 3135 3136 /** 3137 * Convert specified canvas C coordinate to image C coordinate 3138 * 3139 * @deprecated Cannot give correct result if rotation is applied so use 3140 * IcyCanvasXD.canvasToImage(...) instead 3141 */ 3142 @Deprecated 3143 public double canvasToImageC(int value) 3144 { 3145 return canvasToImageDeltaC(value - getOffsetC()); 3146 } 3147 3148 /** 3149 * Convert specified image delta X to canvas delta X.<br> 3150 * WARNING: Does not take in account the rotation transformation.<br> 3151 * Use the IcyCanvasXD.imageToCanvasDelta(...) method instead for rotation transformed delta. 3152 */ 3153 public int imageToCanvasDeltaX(double value) 3154 { 3155 return (int) (value * getScaleX()); 3156 } 3157 3158 /** 3159 * Convert specified image delta Y to canvas delta Y.<br> 3160 * WARNING: Does not take in account the rotation transformation.<br> 3161 * Use the IcyCanvasXD.imageToCanvasDelta(...) method instead for rotation transformed delta. 3162 */ 3163 public int imageToCanvasDeltaY(double value) 3164 { 3165 return (int) (value * getScaleY()); 3166 } 3167 3168 /** 3169 * Convert specified image delta Z to canvas delta Z.<br> 3170 * WARNING: Does not take in account the rotation transformation.<br> 3171 * Use the IcyCanvasXD.imageToCanvasDelta(...) method instead for rotation transformed delta. 3172 */ 3173 public int imageToCanvasDeltaZ(double value) 3174 { 3175 return (int) (value * getScaleZ()); 3176 } 3177 3178 /** 3179 * Convert specified image delta T to canvas delta T.<br> 3180 * WARNING: Does not take in account the rotation transformation.<br> 3181 * Use the IcyCanvasXD.imageToCanvasDelta(...) method instead for rotation transformed delta. 3182 */ 3183 public int imageToCanvasDeltaT(double value) 3184 { 3185 return (int) (value * getScaleT()); 3186 } 3187 3188 /** 3189 * Convert specified image delta C to canvas delta C.<br> 3190 * WARNING: Does not take in account the rotation transformation.<br> 3191 * Use the IcyCanvasXD.imageToCanvasDelta(...) method instead for rotation transformed delta. 3192 */ 3193 public int imageToCanvasDeltaC(double value) 3194 { 3195 return (int) (value * getScaleC()); 3196 } 3197 3198 /** 3199 * Convert specified image X coordinate to canvas X coordinate 3200 * 3201 * @deprecated Cannot give correct result if rotation is applied so use 3202 * IcyCanvasXD.imageToCanvas(...) instead 3203 */ 3204 @Deprecated 3205 public int imageToCanvasX(double value) 3206 { 3207 return imageToCanvasDeltaX(value) + getOffsetX(); 3208 } 3209 3210 /** 3211 * Convert specified image Y coordinate to canvas Y coordinate 3212 * 3213 * @deprecated Cannot give correct result if rotation is applied so use 3214 * IcyCanvasXD.imageToCanvas(...) instead 3215 */ 3216 @Deprecated 3217 public int imageToCanvasY(double value) 3218 { 3219 return imageToCanvasDeltaY(value) + getOffsetY(); 3220 } 3221 3222 /** 3223 * Convert specified image Z coordinate to canvas Z coordinate 3224 * 3225 * @deprecated Cannot give correct result if rotation is applied so use 3226 * IcyCanvasXD.imageToCanvas(...) instead 3227 */ 3228 @Deprecated 3229 public int imageToCanvasZ(double value) 3230 { 3231 return imageToCanvasDeltaZ(value) + getOffsetZ(); 3232 } 3233 3234 /** 3235 * Convert specified image T coordinate to canvas T coordinate 3236 * 3237 * @deprecated Cannot give correct result if rotation is applied so use 3238 * IcyCanvasXD.imageToCanvas(...) instead 3239 */ 3240 @Deprecated 3241 public int imageToCanvasT(double value) 3242 { 3243 return imageToCanvasDeltaT(value) + getOffsetT(); 3244 } 3245 3246 /** 3247 * Convert specified image C coordinate to canvas C coordinate 3248 * 3249 * @deprecated Cannot give correct result if rotation is applied so use 3250 * IcyCanvasXD.imageToCanvas(...) instead 3251 */ 3252 @Deprecated 3253 public int imageToCanvasC(double value) 3254 { 3255 return imageToCanvasDeltaC(value) + getOffsetC(); 3256 } 3257 3258 /** 3259 * Helper to forward mouse press event to the overlays. 3260 * 3261 * @param event 3262 * original mouse event 3263 * @param pt 3264 * mouse image position 3265 */ 3266 public void mousePressed(MouseEvent event, Point5D.Double pt) 3267 { 3268 final boolean globalVisible = isLayersVisible(); 3269 3270 // send mouse event to overlays after so mouse canvas position is ok 3271 for (Layer layer : getLayers(true)) 3272 { 3273 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3274 layer.getOverlay().mousePressed(event, pt, this); 3275 } 3276 } 3277 3278 /** 3279 * Helper to forward mouse press event to the overlays. 3280 * 3281 * @param event 3282 * original mouse event 3283 */ 3284 public void mousePressed(MouseEvent event) 3285 { 3286 mousePressed(event, getMouseImagePos5D()); 3287 } 3288 3289 /** 3290 * Helper to forward mouse release event to the overlays. 3291 * 3292 * @param event 3293 * original mouse event 3294 * @param pt 3295 * mouse image position 3296 */ 3297 public void mouseReleased(MouseEvent event, Point5D.Double pt) 3298 { 3299 final boolean globalVisible = isLayersVisible(); 3300 3301 // send mouse event to overlays after so mouse canvas position is ok 3302 for (Layer layer : getLayers(true)) 3303 { 3304 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3305 layer.getOverlay().mouseReleased(event, pt, this); 3306 } 3307 } 3308 3309 /** 3310 * Helper to forward mouse release event to the overlays. 3311 * 3312 * @param event 3313 * original mouse event 3314 */ 3315 public void mouseReleased(MouseEvent event) 3316 { 3317 mouseReleased(event, getMouseImagePos5D()); 3318 } 3319 3320 /** 3321 * Helper to forward mouse click event to the overlays. 3322 * 3323 * @param event 3324 * original mouse event 3325 * @param pt 3326 * mouse image position 3327 */ 3328 public void mouseClick(MouseEvent event, Point5D.Double pt) 3329 { 3330 final boolean globalVisible = isLayersVisible(); 3331 3332 // send mouse event to overlays after so mouse canvas position is ok 3333 for (Layer layer : getLayers(true)) 3334 { 3335 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3336 layer.getOverlay().mouseClick(event, pt, this); 3337 } 3338 } 3339 3340 /** 3341 * Helper to forward mouse click event to the overlays. 3342 * 3343 * @param event 3344 * original mouse event 3345 */ 3346 public void mouseClick(MouseEvent event) 3347 { 3348 mouseClick(event, getMouseImagePos5D()); 3349 } 3350 3351 /** 3352 * Helper to forward mouse move event to the overlays. 3353 * 3354 * @param event 3355 * original mouse event 3356 * @param pt 3357 * mouse image position 3358 */ 3359 public void mouseMove(MouseEvent event, Point5D.Double pt) 3360 { 3361 final boolean globalVisible = isLayersVisible(); 3362 3363 // send mouse event to overlays after so mouse canvas position is ok 3364 for (Layer layer : getLayers(true)) 3365 { 3366 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3367 layer.getOverlay().mouseMove(event, pt, this); 3368 } 3369 } 3370 3371 /** 3372 * Helper to forward mouse mouse event to the overlays. 3373 * 3374 * @param event 3375 * original mouse event 3376 */ 3377 public void mouseMove(MouseEvent event) 3378 { 3379 mouseMove(event, getMouseImagePos5D()); 3380 } 3381 3382 /** 3383 * Helper to forward mouse drag event to the overlays. 3384 * 3385 * @param event 3386 * original mouse event 3387 * @param pt 3388 * mouse image position 3389 */ 3390 public void mouseDrag(MouseEvent event, Point5D.Double pt) 3391 { 3392 final boolean globalVisible = isLayersVisible(); 3393 3394 // send mouse event to overlays after so mouse canvas position is ok 3395 for (Layer layer : getLayers(true)) 3396 { 3397 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3398 layer.getOverlay().mouseDrag(event, pt, this); 3399 } 3400 } 3401 3402 /** 3403 * Helper to forward mouse drag event to the overlays. 3404 * 3405 * @param event 3406 * original mouse event 3407 */ 3408 public void mouseDrag(MouseEvent event) 3409 { 3410 mouseDrag(event, getMouseImagePos5D()); 3411 } 3412 3413 /** 3414 * Helper to forward mouse enter event to the overlays. 3415 * 3416 * @param event 3417 * original mouse event 3418 * @param pt 3419 * mouse image position 3420 */ 3421 public void mouseEntered(MouseEvent event, Point5D.Double pt) 3422 { 3423 final boolean globalVisible = isLayersVisible(); 3424 3425 // send mouse event to overlays after so mouse canvas position is ok 3426 for (Layer layer : getLayers(true)) 3427 { 3428 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3429 layer.getOverlay().mouseEntered(event, pt, this); 3430 } 3431 } 3432 3433 /** 3434 * Helper to forward mouse entered event to the overlays. 3435 * 3436 * @param event 3437 * original mouse event 3438 */ 3439 public void mouseEntered(MouseEvent event) 3440 { 3441 mouseEntered(event, getMouseImagePos5D()); 3442 } 3443 3444 /** 3445 * Helper to forward mouse exit event to the overlays. 3446 * 3447 * @param event 3448 * original mouse event 3449 * @param pt 3450 * mouse image position 3451 */ 3452 public void mouseExited(MouseEvent event, Point5D.Double pt) 3453 { 3454 final boolean globalVisible = isLayersVisible(); 3455 3456 // send mouse event to overlays after so mouse canvas position is ok 3457 for (Layer layer : getLayers(true)) 3458 { 3459 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3460 layer.getOverlay().mouseExited(event, pt, this); 3461 } 3462 } 3463 3464 /** 3465 * Helper to forward mouse exited event to the overlays. 3466 * 3467 * @param event 3468 * original mouse event 3469 */ 3470 public void mouseExited(MouseEvent event) 3471 { 3472 mouseExited(event, getMouseImagePos5D()); 3473 } 3474 3475 /** 3476 * Helper to forward mouse wheel event to the overlays. 3477 * 3478 * @param event 3479 * original mouse event 3480 * @param pt 3481 * mouse image position 3482 */ 3483 public void mouseWheelMoved(MouseWheelEvent event, Point5D.Double pt) 3484 { 3485 final boolean globalVisible = isLayersVisible(); 3486 3487 // send mouse event to overlays after so mouse canvas position is ok 3488 for (Layer layer : getLayers(true)) 3489 { 3490 if ((globalVisible && layer.isVisible()) || layer.getReceiveMouseEventOnHidden()) 3491 layer.getOverlay().mouseWheelMoved(event, pt, this); 3492 } 3493 } 3494 3495 /** 3496 * Helper to forward mouse wheel event to the overlays. 3497 * 3498 * @param event 3499 * original mouse event 3500 */ 3501 public void mouseWheelMoved(MouseWheelEvent event) 3502 { 3503 mouseWheelMoved(event, getMouseImagePos5D()); 3504 } 3505 3506 @Override 3507 public void keyPressed(KeyEvent e) 3508 { 3509 final boolean globalVisible = isLayersVisible(); 3510 final Point5D.Double pt = getMouseImagePos5D(); 3511 3512 // forward event to overlays 3513 for (Layer layer : getLayers(true)) 3514 { 3515 if ((globalVisible && layer.isVisible()) || layer.getReceiveKeyEventOnHidden()) 3516 layer.getOverlay().keyPressed(e, pt, this); 3517 } 3518 3519 if (!e.isConsumed()) 3520 { 3521 switch (e.getKeyCode()) 3522 { 3523 case KeyEvent.VK_0: 3524 if (EventUtil.isShiftDown(e, true)) 3525 { 3526 if (CanvasActions.globalDisableSyncAction.isEnabled()) 3527 { 3528 CanvasActions.globalDisableSyncAction.execute(); 3529 e.consume(); 3530 } 3531 } 3532 else if (EventUtil.isNoModifier(e)) 3533 { 3534 if (CanvasActions.disableSyncAction.isEnabled()) 3535 { 3536 CanvasActions.disableSyncAction.execute(); 3537 e.consume(); 3538 } 3539 } 3540 break; 3541 3542 case KeyEvent.VK_1: 3543 if (EventUtil.isShiftDown(e, true)) 3544 { 3545 if (CanvasActions.globalSyncGroup1Action.isEnabled()) 3546 { 3547 CanvasActions.globalSyncGroup1Action.execute(); 3548 e.consume(); 3549 } 3550 } 3551 else if (EventUtil.isNoModifier(e)) 3552 { 3553 if (CanvasActions.syncGroup1Action.isEnabled()) 3554 { 3555 CanvasActions.syncGroup1Action.execute(); 3556 e.consume(); 3557 } 3558 } 3559 break; 3560 3561 case KeyEvent.VK_2: 3562 if (EventUtil.isShiftDown(e, true)) 3563 { 3564 if (CanvasActions.globalSyncGroup2Action.isEnabled()) 3565 { 3566 CanvasActions.globalSyncGroup2Action.execute(); 3567 e.consume(); 3568 } 3569 } 3570 else if (EventUtil.isNoModifier(e)) 3571 { 3572 if (CanvasActions.syncGroup2Action.isEnabled()) 3573 { 3574 CanvasActions.syncGroup2Action.execute(); 3575 e.consume(); 3576 } 3577 } 3578 break; 3579 3580 case KeyEvent.VK_3: 3581 if (EventUtil.isShiftDown(e, true)) 3582 { 3583 if (CanvasActions.globalSyncGroup3Action.isEnabled()) 3584 { 3585 CanvasActions.globalSyncGroup3Action.execute(); 3586 e.consume(); 3587 } 3588 } 3589 else if (EventUtil.isNoModifier(e)) 3590 { 3591 if (CanvasActions.syncGroup3Action.isEnabled()) 3592 { 3593 CanvasActions.syncGroup3Action.execute(); 3594 e.consume(); 3595 } 3596 } 3597 break; 3598 3599 case KeyEvent.VK_4: 3600 if (EventUtil.isShiftDown(e, true)) 3601 { 3602 if (CanvasActions.globalSyncGroup4Action.isEnabled()) 3603 { 3604 CanvasActions.globalSyncGroup4Action.execute(); 3605 e.consume(); 3606 } 3607 } 3608 else if (EventUtil.isNoModifier(e)) 3609 { 3610 if (CanvasActions.syncGroup4Action.isEnabled()) 3611 { 3612 CanvasActions.syncGroup4Action.execute(); 3613 e.consume(); 3614 } 3615 } 3616 break; 3617 3618 case KeyEvent.VK_G: 3619 if (EventUtil.isShiftDown(e, true)) 3620 { 3621 if (WindowActions.gridTileAction.isEnabled()) 3622 { 3623 WindowActions.gridTileAction.execute(); 3624 e.consume(); 3625 } 3626 } 3627 break; 3628 3629 case KeyEvent.VK_H: 3630 if (EventUtil.isShiftDown(e, true)) 3631 { 3632 if (WindowActions.horizontalTileAction.isEnabled()) 3633 { 3634 WindowActions.horizontalTileAction.execute(); 3635 e.consume(); 3636 } 3637 } 3638 break; 3639 3640 case KeyEvent.VK_A: 3641 if (EventUtil.isMenuControlDown(e, true)) 3642 { 3643 if (RoiActions.selectAllAction.isEnabled()) 3644 { 3645 RoiActions.selectAllAction.execute(); 3646 e.consume(); 3647 } 3648 } 3649 break; 3650 3651 case KeyEvent.VK_V: 3652 if (EventUtil.isShiftDown(e, true)) 3653 { 3654 if (WindowActions.verticalTileAction.isEnabled()) 3655 { 3656 WindowActions.verticalTileAction.execute(); 3657 e.consume(); 3658 } 3659 } 3660 else if (EventUtil.isMenuControlDown(e, true)) 3661 { 3662 if (GeneralActions.pasteImageAction.isEnabled()) 3663 { 3664 GeneralActions.pasteImageAction.execute(); 3665 e.consume(); 3666 } 3667 else if (RoiActions.pasteAction.isEnabled()) 3668 { 3669 RoiActions.pasteAction.execute(); 3670 e.consume(); 3671 } 3672 } 3673 else if (EventUtil.isAltDown(e, true)) 3674 { 3675 if (RoiActions.pasteLinkAction.isEnabled()) 3676 { 3677 RoiActions.pasteLinkAction.execute(); 3678 e.consume(); 3679 } 3680 } 3681 break; 3682 3683 case KeyEvent.VK_C: 3684 if (EventUtil.isMenuControlDown(e, true)) 3685 { 3686 // do this one first else copyImage hide it 3687 if (RoiActions.copyAction.isEnabled()) 3688 { 3689 // copy them to icy clipboard 3690 RoiActions.copyAction.execute(); 3691 e.consume(); 3692 } 3693 else if (GeneralActions.copyImageAction.isEnabled()) 3694 { 3695 // copy image to system clipboard 3696 GeneralActions.copyImageAction.execute(); 3697 e.consume(); 3698 } 3699 } 3700 else if (EventUtil.isAltDown(e, true)) 3701 { 3702 if (RoiActions.copyLinkAction.isEnabled()) 3703 { 3704 // copy link of selected ROI to clipboard 3705 RoiActions.copyLinkAction.execute(); 3706 e.consume(); 3707 } 3708 } 3709 break; 3710 3711 case KeyEvent.VK_SPACE: 3712 if (tNav.isPlaying()) 3713 tNav.stopPlay(); 3714 else 3715 tNav.startPlay(); 3716 e.consume(); 3717 break; 3718 } 3719 } 3720 } 3721 3722 @Override 3723 public void keyReleased(KeyEvent e) 3724 { 3725 final boolean globalVisible = isLayersVisible(); 3726 final Point5D.Double pt = getMouseImagePos5D(); 3727 3728 // forward event to overlays 3729 for (Layer layer : getLayers(true)) 3730 { 3731 if ((globalVisible && layer.isVisible()) || layer.getReceiveKeyEventOnHidden()) 3732 layer.getOverlay().keyReleased(e, pt, this); 3733 } 3734 } 3735 3736 @Override 3737 public void keyTyped(KeyEvent e) 3738 { 3739 // nothing to do by default 3740 } 3741 3742 /** 3743 * Gets the image at position (t, z, c). 3744 */ 3745 public IcyBufferedImage getImage(int t, int z, int c) 3746 { 3747 if ((t == -1) || (z == -1)) 3748 return null; 3749 3750 final Sequence sequence = getSequence(); 3751 3752 // have to test this as sequence reference can be release in viewer 3753 if (sequence != null) 3754 return sequence.getImage(t, z, c); 3755 3756 return null; 3757 } 3758 3759 /** 3760 * @deprecated Use {@link #getImage(int, int, int)} with C = -1 instead. 3761 */ 3762 @Deprecated 3763 public IcyBufferedImage getImage(int t, int z) 3764 { 3765 return getImage(t, z, -1); 3766 } 3767 3768 /** 3769 * Get the current image. 3770 */ 3771 public IcyBufferedImage getCurrentImage() 3772 { 3773 return getImage(getPositionT(), getPositionZ(), getPositionC()); 3774 } 3775 3776 /** 3777 * @deprecated use {@link #getRenderedImage(int, int, int, boolean)} instead 3778 */ 3779 @Deprecated 3780 public final BufferedImage getRenderedImage(int t, int z, int c, int imageType, boolean canvasView) 3781 { 3782 return getRenderedImage(t, z, c, canvasView); 3783 } 3784 3785 /** 3786 * @deprecated use {@link #getRenderedSequence(boolean)} instead 3787 */ 3788 @Deprecated 3789 public final Sequence getRenderedSequence(int imageType, boolean canvasView) 3790 { 3791 return getRenderedSequence(canvasView); 3792 } 3793 3794 /** 3795 * Returns a RGB or ARGB (depending support) BufferedImage representing the canvas view for 3796 * image at position (t, z, c).<br> 3797 * Free feel to the canvas to handle or not a specific dimension. 3798 * 3799 * @param t 3800 * T position of wanted image (-1 for complete sequence) 3801 * @param z 3802 * Z position of wanted image (-1 for complete stack) 3803 * @param c 3804 * C position of wanted image (-1 for all channels) 3805 * @param canvasView 3806 * render with canvas view if true else use default sequence dimension 3807 */ 3808 public abstract BufferedImage getRenderedImage(int t, int z, int c, boolean canvasView); 3809 3810 /** 3811 * @deprecated Use {@link #getRenderedImage(int, int, int, boolean)} instead. 3812 */ 3813 @Deprecated 3814 public BufferedImage getRenderedImage(int t, int z, int c) 3815 { 3816 return getRenderedImage(t, z, c, true); 3817 } 3818 3819 /** 3820 * Return a sequence which contains rendered images.<br> 3821 * Default implementation, override it if needed in your canvas. 3822 * 3823 * @param canvasView 3824 * render with canvas view if true else use default sequence dimension 3825 * @param progressListener 3826 * progress listener which receive notifications about progression 3827 */ 3828 public Sequence getRenderedSequence(boolean canvasView, ProgressListener progressListener) 3829 { 3830 final Sequence seqIn = getSequence(); 3831 // create output sequence 3832 final Sequence result = new Sequence(); 3833 3834 if (seqIn != null) 3835 { 3836 // derive original metadata 3837 result.setMetaData(OMEUtil.createOMEXMLMetadata(seqIn.getOMEXMLMetadata())); 3838 3839 int t = getPositionT(); 3840 int z = getPositionZ(); 3841 int c = getPositionC(); 3842 final int sizeT = getImageSizeT(); 3843 final int sizeZ = getImageSizeZ(); 3844 final int sizeC = getImageSizeC(); 3845 3846 int pos = 0; 3847 int len = 1; 3848 if (t != -1) 3849 len *= sizeT; 3850 if (z != -1) 3851 len *= sizeZ; 3852 if (c != -1) 3853 len *= sizeC; 3854 3855 result.beginUpdate(); 3856 // This cause position changed event to not be sent during rendering. 3857 // Painters have to take care of that, they should check the canvas position 3858 // in the paint() method 3859 beginUpdate(); 3860 try 3861 { 3862 if (t != -1) 3863 { 3864 for (t = 0; t < sizeT; t++) 3865 { 3866 if (z != -1) 3867 { 3868 for (z = 0; z < sizeZ; z++) 3869 { 3870 if (c != -1) 3871 { 3872 final List<BufferedImage> images = new ArrayList<BufferedImage>(); 3873 3874 for (c = 0; c < sizeC; c++) 3875 { 3876 images.add(getRenderedImage(t, z, c, canvasView)); 3877 pos++; 3878 if (progressListener != null) 3879 progressListener.notifyProgress(pos, len); 3880 } 3881 3882 result.setImage(t, z, IcyBufferedImage.createFrom(images)); 3883 } 3884 else 3885 { 3886 result.setImage(t, z, getRenderedImage(t, z, -1, canvasView)); 3887 pos++; 3888 if (progressListener != null) 3889 progressListener.notifyProgress(pos, len); 3890 } 3891 } 3892 } 3893 else 3894 { 3895 result.setImage(t, 0, getRenderedImage(t, -1, -1, canvasView)); 3896 pos++; 3897 if (progressListener != null) 3898 progressListener.notifyProgress(pos, len); 3899 } 3900 } 3901 } 3902 else 3903 { 3904 if (z != -1) 3905 { 3906 for (z = 0; z < sizeZ; z++) 3907 { 3908 if (c != -1) 3909 { 3910 final ArrayList<BufferedImage> images = new ArrayList<BufferedImage>(); 3911 3912 for (c = 0; c < sizeC; c++) 3913 { 3914 images.add(getRenderedImage(-1, z, c, canvasView)); 3915 pos++; 3916 if (progressListener != null) 3917 progressListener.notifyProgress(pos, len); 3918 } 3919 3920 result.setImage(0, z, IcyBufferedImage.createFrom(images)); 3921 } 3922 else 3923 { 3924 result.setImage(0, z, getRenderedImage(-1, z, -1, canvasView)); 3925 pos++; 3926 if (progressListener != null) 3927 progressListener.notifyProgress(pos, len); 3928 } 3929 } 3930 } 3931 else 3932 { 3933 if (c != -1) 3934 { 3935 final ArrayList<BufferedImage> images = new ArrayList<BufferedImage>(); 3936 3937 for (c = 0; c < sizeC; c++) 3938 { 3939 images.add(getRenderedImage(-1, -1, c, canvasView)); 3940 pos++; 3941 if (progressListener != null) 3942 progressListener.notifyProgress(pos, len); 3943 } 3944 3945 result.setImage(0, 0, IcyBufferedImage.createFrom(images)); 3946 } 3947 else 3948 { 3949 result.setImage(0, 0, getRenderedImage(-1, -1, -1, canvasView)); 3950 pos++; 3951 if (progressListener != null) 3952 progressListener.notifyProgress(pos, len); 3953 } 3954 } 3955 } 3956 } 3957 finally 3958 { 3959 endUpdate(); 3960 result.endUpdate(); 3961 } 3962 } 3963 3964 return result; 3965 } 3966 3967 /** 3968 * @deprecated Use {@link #getRenderedSequence(boolean, ProgressListener)} instead. 3969 */ 3970 @Deprecated 3971 public Sequence getRenderedSequence(boolean canvasView) 3972 { 3973 return getRenderedSequence(canvasView, null); 3974 } 3975 3976 /** 3977 * @deprecated Use {@link #getRenderedSequence(boolean, ProgressListener)} instead. 3978 */ 3979 @Deprecated 3980 public Sequence getRenderedSequence() 3981 { 3982 return getRenderedSequence(true, null); 3983 } 3984 3985 /** 3986 * Return the number of "selected" samples 3987 */ 3988 public int getNumSelectedSamples() 3989 { 3990 final Sequence sequence = getSequence(); 3991 3992 // have to test this as we release sequence reference on closed 3993 if (sequence == null) 3994 return 0; 3995 3996 final int base_len = getImageSizeX() * getImageSizeY() * getImageSizeC(); 3997 3998 if (getPositionT() == -1) 3999 { 4000 if (getPositionZ() == -1) 4001 return base_len * getImageSizeZ() * getImageSizeT(); 4002 4003 return base_len * getImageSizeT(); 4004 } 4005 4006 if (getPositionZ() == -1) 4007 return base_len * getImageSizeZ(); 4008 4009 return base_len; 4010 } 4011 4012 /** 4013 * Returns the frame rate (given in frame per second) for play command (T navigation panel). 4014 */ 4015 public int getFrameRate() 4016 { 4017 return tNav.getFrameRate(); 4018 } 4019 4020 /** 4021 * Sets the frame rate (given in frame per second) for play command (T navigation panel). 4022 */ 4023 public void setFrameRate(int fps) 4024 { 4025 tNav.setFrameRate(fps); 4026 } 4027 4028 /** 4029 * update Z slider state 4030 */ 4031 protected void updateZNav() 4032 { 4033 final int maxZ = getMaxPositionZ(); 4034 final int z = getPositionZ(); 4035 4036 zNav.setMaximum(maxZ); 4037 if (z != -1) 4038 { 4039 zNav.setValue(z); 4040 zNav.setVisible(maxZ > 0); 4041 } 4042 else 4043 zNav.setVisible(false); 4044 } 4045 4046 /** 4047 * update T slider state 4048 */ 4049 protected void updateTNav() 4050 { 4051 final int maxT = getMaxPositionT(); 4052 final int t = getPositionT(); 4053 4054 tNav.setMaximum(maxT); 4055 if (t != -1) 4056 { 4057 tNav.setValue(t); 4058 tNav.setVisible(maxT > 0); 4059 } 4060 else 4061 tNav.setVisible(false); 4062 } 4063 4064 /** 4065 * @deprecated Use {@link #getLayer(Overlay)} instead. 4066 */ 4067 @Deprecated 4068 public Layer getLayer(Painter painter) 4069 { 4070 for (Layer layer : getLayers(false)) 4071 if (layer.getPainter() == painter) 4072 return layer; 4073 4074 return null; 4075 } 4076 4077 /** 4078 * Find the layer corresponding to the specified Overlay 4079 */ 4080 public Layer getLayer(Overlay overlay) 4081 { 4082 return layers.get(overlay); 4083 } 4084 4085 /** 4086 * Find the layer corresponding to the specified ROI (use the ROI overlay internally). 4087 */ 4088 public Layer getLayer(ROI roi) 4089 { 4090 return getLayer(roi.getOverlay()); 4091 } 4092 4093 /** 4094 * @deprecated Use {@link #hasLayer(Overlay)} instead. 4095 */ 4096 @Deprecated 4097 public boolean hasLayer(Painter painter) 4098 { 4099 return getLayer(painter) != null; 4100 } 4101 4102 /** 4103 * Returns true if the canvas contains a layer for the specified {@link Overlay}. 4104 */ 4105 public boolean hasLayer(Overlay overlay) 4106 { 4107 synchronized (layers) 4108 { 4109 return layers.containsKey(overlay); 4110 } 4111 } 4112 4113 public boolean hasLayer(Layer layer) 4114 { 4115 final Overlay overlay = layer.getOverlay(); 4116 4117 // faster to test from overlay 4118 if (overlay != null) 4119 return hasLayer(overlay); 4120 4121 synchronized (layers) 4122 { 4123 return layers.containsValue(layer); 4124 } 4125 } 4126 4127 /** 4128 * @deprecated Use {@link #addLayer(Overlay)} instead. 4129 */ 4130 @Deprecated 4131 public void addLayer(Painter painter) 4132 { 4133 if (!hasLayer(painter)) 4134 addLayer(new Layer(painter)); 4135 } 4136 4137 public Layer addLayer(Overlay overlay) 4138 { 4139 if (!hasLayer(overlay)) 4140 return addLayer(new Layer(overlay)); 4141 4142 return null; 4143 } 4144 4145 protected Layer addLayer(Layer layer) 4146 { 4147 if (layer != null) 4148 { 4149 // listen layer 4150 layer.addListener(this); 4151 4152 // add to list 4153 synchronized (layers) 4154 { 4155 layers.put(layer.getOverlay(), layer); 4156 if (Layer.DEFAULT_NAME.equals(layer)) 4157 layer.setName("layer " + layers.size()); 4158 } 4159 4160 // added 4161 layerAdded(layer); 4162 } 4163 4164 return layer; 4165 } 4166 4167 /** 4168 * @deprecated Use {@link #removeLayer(Overlay)} instead. 4169 */ 4170 @Deprecated 4171 public void removeLayer(Painter painter) 4172 { 4173 removeLayer(getLayer(painter)); 4174 } 4175 4176 /** 4177 * Remove the layer for the specified {@link Overlay} from the canvas.<br/> 4178 * Returns <code>true</code> if the method succeed. 4179 */ 4180 public boolean removeLayer(Overlay overlay) 4181 { 4182 final Layer layer; 4183 4184 // remove from list 4185 synchronized (layers) 4186 { 4187 layer = layers.remove(overlay); 4188 } 4189 4190 if (layer != null) 4191 { 4192 // stop listening layer 4193 layer.removeListener(this); 4194 // notify remove 4195 layerRemoved(layer); 4196 4197 return true; 4198 } 4199 4200 return false; 4201 } 4202 4203 /** 4204 * Remove the specified layer from the canvas. 4205 */ 4206 public void removeLayer(Layer layer) 4207 { 4208 removeLayer(layer.getOverlay()); 4209 } 4210 4211 /** 4212 * Returns <code>true</code> if the specified overlay is visible in the canvas.<br> 4213 */ 4214 public boolean isVisible(Overlay overlay) 4215 { 4216 final Layer layer = getLayer(overlay); 4217 4218 if (layer != null) 4219 return layer.isVisible(); 4220 4221 return false; 4222 } 4223 4224 /** 4225 * @deprecated Use {@link #addLayerListener(CanvasLayerListener)} instead. 4226 */ 4227 @Deprecated 4228 public void addLayersListener(CanvasLayerListener listener) 4229 { 4230 addLayerListener(listener); 4231 } 4232 4233 /** 4234 * @deprecated Use {@link #removeLayerListener(CanvasLayerListener)} instead. 4235 */ 4236 @Deprecated 4237 public void removeLayersListener(CanvasLayerListener listener) 4238 { 4239 removeLayerListener(listener); 4240 } 4241 4242 /** 4243 * Returns all canvas layer listener 4244 */ 4245 public List<CanvasLayerListener> getLayerListeners() 4246 { 4247 synchronized (layerListeners) 4248 { 4249 return new ArrayList<CanvasLayerListener>(layerListeners); 4250 } 4251 } 4252 4253 /** 4254 * Add a layer listener 4255 * 4256 * @param listener 4257 */ 4258 public void addLayerListener(CanvasLayerListener listener) 4259 { 4260 synchronized (layerListeners) 4261 { 4262 if (listener != null) 4263 layerListeners.add(listener); 4264 } 4265 } 4266 4267 /** 4268 * Remove a layer listener 4269 * 4270 * @param listener 4271 */ 4272 public void removeLayerListener(CanvasLayerListener listener) 4273 { 4274 synchronized (layerListeners) 4275 { 4276 layerListeners.remove(listener); 4277 } 4278 } 4279 4280 protected void fireLayerChangedEvent(CanvasLayerEvent event) 4281 { 4282 for (CanvasLayerListener listener : getLayerListeners()) 4283 listener.canvasLayerChanged(event); 4284 } 4285 4286 /** 4287 * Returns all canvas listener 4288 */ 4289 public List<IcyCanvasListener> getListeners() 4290 { 4291 synchronized (listeners) 4292 { 4293 return new ArrayList<IcyCanvasListener>(listeners); 4294 } 4295 } 4296 4297 /** 4298 * Add a IcyCanvas listener 4299 * 4300 * @param listener 4301 */ 4302 public void addCanvasListener(IcyCanvasListener listener) 4303 { 4304 synchronized (listeners) 4305 { 4306 listeners.add(listener); 4307 } 4308 } 4309 4310 /** 4311 * Remove a IcyCanvas listener 4312 * 4313 * @param listener 4314 */ 4315 public void removeCanvasListener(IcyCanvasListener listener) 4316 { 4317 synchronized (listeners) 4318 { 4319 listeners.remove(listener); 4320 } 4321 } 4322 4323 protected void fireCanvasChangedEvent(IcyCanvasEvent event) 4324 { 4325 for (IcyCanvasListener listener : getListeners()) 4326 listener.canvasChanged(event); 4327 } 4328 4329 public void beginUpdate() 4330 { 4331 updater.beginUpdate(); 4332 } 4333 4334 public void endUpdate() 4335 { 4336 updater.endUpdate(); 4337 } 4338 4339 public boolean isUpdating() 4340 { 4341 return updater.isUpdating(); 4342 } 4343 4344 /** 4345 * layer added 4346 * 4347 * @param layer 4348 */ 4349 protected void layerAdded(Layer layer) 4350 { 4351 // handle with updater 4352 updater.changed(new CanvasLayerEvent(layer, LayersEventType.ADDED)); 4353 } 4354 4355 /** 4356 * layer removed 4357 * 4358 * @param layer 4359 */ 4360 protected void layerRemoved(Layer layer) 4361 { 4362 // handle with updater 4363 updater.changed(new CanvasLayerEvent(layer, LayersEventType.REMOVED)); 4364 } 4365 4366 /** 4367 * layer has changed 4368 */ 4369 @Override 4370 public void layerChanged(Layer layer, String propertyName) 4371 { 4372 // handle with updater 4373 updater.changed(new CanvasLayerEvent(layer, LayersEventType.CHANGED, propertyName)); 4374 } 4375 4376 /** 4377 * canvas changed (packed event).<br> 4378 * do global changes processing here 4379 */ 4380 public void changed(IcyCanvasEvent event) 4381 { 4382 final IcyCanvasEventType eventType = event.getType(); 4383 4384 // handle synchronized canvas 4385 if (isSynchronized()) 4386 { 4387 final List<IcyCanvas> synchCanvasList = getSynchronizedCanvas(); 4388 4389 // this is the synchronizer master so dispatch view changes to others canvas 4390 if (getSynchMaster(synchCanvasList)) 4391 { 4392 try 4393 { 4394 // synchronize all events when the view has just been synchronized 4395 final boolean synchAll = (eventType == IcyCanvasEventType.SYNC_CHANGED); 4396 synchronizeCanvas(synchCanvasList, event, synchAll); 4397 } 4398 finally 4399 { 4400 releaseSynchMaster(); 4401 } 4402 } 4403 } 4404 4405 switch (eventType) 4406 { 4407 case POSITION_CHANGED: 4408 final int curZ = getPositionZ(); 4409 final int curT = getPositionT(); 4410 final int curC = getPositionC(); 4411 4412 switch (event.getDim()) 4413 { 4414 case Z: 4415 // ensure Z slider position 4416 if (curZ != -1) 4417 zNav.setValue(curZ); 4418 break; 4419 4420 case T: 4421 // ensure T slider position 4422 if (curT != -1) 4423 tNav.setValue(curT); 4424 break; 4425 4426 case C: 4427 // single channel mode 4428 final int maxC = getMaxPositionC(); 4429 4430 // disabled others channels 4431 for (int c = 0; c <= maxC; c++) 4432 getLut().getLutChannel(c).setEnabled((curC == -1) || (curC == c)); 4433 break; 4434 4435 case NULL: 4436 // ensure Z slider position 4437 if (curZ != -1) 4438 zNav.setValue(curZ); 4439 // ensure T slider position 4440 if (curT != -1) 4441 tNav.setValue(curT); 4442 break; 4443 } 4444 // refresh mouse panel informations 4445 mouseInfPanel.updateInfos(this); 4446 break; 4447 4448 case MOUSE_IMAGE_POSITION_CHANGED: 4449 // refresh mouse panel informations 4450 mouseInfPanel.updateInfos(this); 4451 break; 4452 } 4453 4454 // notify listeners that canvas have changed 4455 fireCanvasChangedEvent(event); 4456 } 4457 4458 /** 4459 * layer property has changed (packed event) 4460 */ 4461 protected void layerChanged(CanvasLayerEvent event) 4462 { 4463 final String property = event.getProperty(); 4464 4465 // we need to rebuild sorted layer list 4466 if ((event.getType() != LayersEventType.CHANGED) || (property == null) || (property == Layer.PROPERTY_PRIORITY)) 4467 orderedLayersOutdated = true; 4468 4469 // notify listeners that layers have changed 4470 fireLayerChangedEvent(event); 4471 } 4472 4473 /** 4474 * position has changed<br> 4475 * 4476 * @param dim 4477 * define the position which has changed 4478 */ 4479 protected void positionChanged(DimensionId dim) 4480 { 4481 // handle with updater 4482 updater.changed(new IcyCanvasEvent(this, IcyCanvasEventType.POSITION_CHANGED, dim)); 4483 } 4484 4485 @Override 4486 public void lutChanged(LUTEvent event) 4487 { 4488 final int curC = getPositionC(); 4489 4490 // single channel mode ? 4491 if (curC != -1) 4492 { 4493 final int channel = event.getComponent(); 4494 4495 // channel is enabled --> change C position 4496 if ((channel != -1) && getLut().getLutChannel(channel).isEnabled()) 4497 setPositionC(channel); 4498 else 4499 // ensure we have 1 channel enable 4500 getLut().getLutChannel(curC).setEnabled(true); 4501 } 4502 4503 lutChanged(event.getComponent()); 4504 } 4505 4506 /** 4507 * lut changed 4508 * 4509 * @param component 4510 */ 4511 protected void lutChanged(int component) 4512 { 4513 // nothing to do by default 4514 } 4515 4516 /** 4517 * sequence meta data has changed 4518 */ 4519 protected void sequenceMetaChanged(String metadataName) 4520 { 4521 // nothing to do by default 4522 } 4523 4524 /** 4525 * sequence type has changed 4526 */ 4527 protected void sequenceTypeChanged() 4528 { 4529 // nothing to do by default 4530 } 4531 4532 /** 4533 * sequence component bounds has changed 4534 * 4535 * @param colorModel 4536 * @param component 4537 */ 4538 protected void sequenceComponentBoundsChanged(IcyColorModel colorModel, int component) 4539 { 4540 // nothing to do by default 4541 } 4542 4543 /** 4544 * sequence component bounds has changed 4545 * 4546 * @param colorModel 4547 * @param component 4548 */ 4549 protected void sequenceColorMapChanged(IcyColorModel colorModel, int component) 4550 { 4551 // nothing to do by default 4552 } 4553 4554 /** 4555 * sequence data has changed 4556 * 4557 * @param image 4558 * image which has changed (null if global data changed) 4559 * @param type 4560 * event type 4561 */ 4562 protected void sequenceDataChanged(IcyBufferedImage image, SequenceEventType type) 4563 { 4564 ThreadUtil.runSingle(guiUpdater); 4565 } 4566 4567 /** 4568 * @deprecated Use {@link #sequenceOverlayChanged(Overlay, SequenceEventType)} instead. 4569 */ 4570 @Deprecated 4571 protected void sequencePainterChanged(Painter painter, SequenceEventType type) 4572 { 4573 // no more stuff here 4574 } 4575 4576 /** 4577 * Sequence overlay has changed 4578 * 4579 * @param overlay 4580 * overlay which has changed 4581 * @param type 4582 * event type 4583 */ 4584 protected void sequenceOverlayChanged(Overlay overlay, SequenceEventType type) 4585 { 4586 switch (type) 4587 { 4588 case ADDED: 4589 addLayer(overlay); 4590 break; 4591 4592 case REMOVED: 4593 removeLayer(overlay); 4594 break; 4595 4596 case CHANGED: 4597 // nothing to do here 4598 break; 4599 } 4600 } 4601 4602 /** 4603 * sequence roi has changed 4604 * 4605 * @param roi 4606 * roi which has changed (null if global roi changed) 4607 * @param type 4608 * event type 4609 */ 4610 protected void sequenceROIChanged(ROI roi, SequenceEventType type) 4611 { 4612 // nothing here 4613 4614 } 4615 4616 @Override 4617 public void viewerChanged(ViewerEvent event) 4618 { 4619 switch (event.getType()) 4620 { 4621 case POSITION_CHANGED: 4622 // ignore this event as we are launching it 4623 break; 4624 4625 case LUT_CHANGED: 4626 // set new lut 4627 setLut(viewer.getLut(), true); 4628 break; 4629 4630 case CANVAS_CHANGED: 4631 // nothing to do 4632 break; 4633 } 4634 } 4635 4636 @Override 4637 public void viewerClosed(Viewer viewer) 4638 { 4639 // nothing to do here 4640 } 4641 4642 @Override 4643 public final void sequenceChanged(SequenceEvent event) 4644 { 4645 switch (event.getSourceType()) 4646 { 4647 case SEQUENCE_META: 4648 sequenceMetaChanged((String) event.getSource()); 4649 break; 4650 4651 case SEQUENCE_TYPE: 4652 sequenceTypeChanged(); 4653 break; 4654 4655 case SEQUENCE_COMPONENTBOUNDS: 4656 sequenceComponentBoundsChanged((IcyColorModel) event.getSource(), event.getParam()); 4657 break; 4658 4659 case SEQUENCE_COLORMAP: 4660 sequenceColorMapChanged((IcyColorModel) event.getSource(), event.getParam()); 4661 break; 4662 4663 case SEQUENCE_DATA: 4664 sequenceDataChanged((IcyBufferedImage) event.getSource(), event.getType()); 4665 break; 4666 4667 case SEQUENCE_OVERLAY: 4668 final Overlay overlay = (Overlay) event.getSource(); 4669 4670 sequenceOverlayChanged(overlay, event.getType()); 4671 4672 // backward compatibility 4673 @SuppressWarnings("deprecation") 4674 final Painter painter; 4675 4676 if (overlay instanceof OverlayWrapper) 4677 painter = ((OverlayWrapper) overlay).getPainter(); 4678 else 4679 painter = overlay; 4680 4681 sequencePainterChanged(painter, event.getType()); 4682 break; 4683 4684 case SEQUENCE_ROI: 4685 sequenceROIChanged((ROI) event.getSource(), event.getType()); 4686 break; 4687 } 4688 } 4689 4690 @Override 4691 public void sequenceClosed(Sequence sequence) 4692 { 4693 // nothing to do here 4694 } 4695 4696 @Override 4697 public void onChanged(CollapsibleEvent event) 4698 { 4699 if (event instanceof CanvasLayerEvent) 4700 layerChanged((CanvasLayerEvent) event); 4701 4702 if (event instanceof IcyCanvasEvent) 4703 changed((IcyCanvasEvent) event); 4704 } 4705}