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 icy.main.Icy; 022import icy.painter.Overlay; 023import icy.painter.Overlay.OverlayPriority; 024import icy.painter.OverlayEvent; 025import icy.painter.OverlayEvent.OverlayEventType; 026import icy.painter.OverlayListener; 027import icy.painter.OverlayWrapper; 028import icy.painter.Painter; 029import icy.painter.WeakOverlayListener; 030import icy.roi.ROI; 031 032import java.lang.ref.WeakReference; 033import java.util.ArrayList; 034import java.util.List; 035 036/** 037 * Layer class.<br> 038 * This class encapsulate {@link Overlay} in a canvas to<br> 039 * add specific display properties (visibility, transparency...). 040 */ 041public class Layer implements OverlayListener, Comparable<Layer> 042{ 043 public interface LayerListener 044 { 045 public void layerChanged(Layer source, String propertyName); 046 } 047 048 public final static String PROPERTY_NAME = Overlay.PROPERTY_NAME; 049 public final static String PROPERTY_PRIORITY = Overlay.PROPERTY_PRIORITY; 050 public final static String PROPERTY_READONLY = Overlay.PROPERTY_READONLY; 051 public final static String PROPERTY_CANBEREMOVED = Overlay.PROPERTY_CANBEREMOVED; 052 public final static String PROPERTY_RECEIVEKEYEVENTONHIDDEN = Overlay.PROPERTY_RECEIVEKEYEVENTONHIDDEN; 053 public final static String PROPERTY_RECEIVEMOUSEEVENTONHIDDEN = Overlay.PROPERTY_RECEIVEMOUSEEVENTONHIDDEN; 054 /** 055 * @deprecated Use {@link #PROPERTY_OPACITY} instead 056 */ 057 @Deprecated 058 public final static String PROPERTY_ALPHA = "alpha"; 059 public final static String PROPERTY_OPACITY = "opacity"; 060 public final static String PROPERTY_VISIBLE = "visible"; 061 062 public final static String DEFAULT_NAME = "layer"; 063 064 /** 065 * Returns true if the Layer need to be repainted when the specified property has changed. 066 */ 067 public static boolean isPaintProperty(String propertyName) 068 { 069 if (propertyName == null) 070 return false; 071 072 return propertyName.equals(PROPERTY_OPACITY) || propertyName.equals(PROPERTY_PRIORITY) 073 || propertyName.equals(PROPERTY_VISIBLE); 074 } 075 076 static Overlay createOverlayWrapper(@SuppressWarnings("deprecation") Painter painter, String name) 077 { 078 if (painter instanceof Overlay) 079 return (Overlay) painter; 080 081 final Overlay result = new OverlayWrapper(painter, name); 082 083 if (name == null) 084 result.setName(DEFAULT_NAME); 085 086 // default priority 087 result.setPriority(OverlayPriority.SHAPE_NORMAL); 088 089 return result; 090 } 091 092 private final Overlay overlay; 093 // cache for ROI 094 private WeakReference<ROI> roi; 095 096 private boolean visible; 097 private float alpha; 098 099 /** 100 * listeners 101 */ 102 protected final List<LayerListener> listeners; 103 104 public Layer(Overlay overlay) 105 { 106 this.overlay = overlay; 107 108 overlay.addOverlayListener(new WeakOverlayListener(this)); 109 110 visible = true; 111 alpha = 1f; 112 roi = null; 113 114 listeners = new ArrayList<LayerListener>(); 115 } 116 117 /** 118 * @deprecated Use {@link #Layer(Overlay)} instead. 119 */ 120 @Deprecated 121 public Layer(Painter painter, String name) 122 { 123 this(createOverlayWrapper(painter, name)); 124 } 125 126 /** 127 * @deprecated Use {@link #Layer(Overlay)} instead. 128 */ 129 @Deprecated 130 public Layer(Painter painter) 131 { 132 this(painter, null); 133 } 134 135 /** 136 * Returns the attached {@link Overlay}. 137 */ 138 public Overlay getOverlay() 139 { 140 return overlay; 141 } 142 143 /** 144 * @deprecated Use {@link #getOverlay()} instead. 145 */ 146 @Deprecated 147 public Painter getPainter() 148 { 149 final Overlay result = getOverlay(); 150 151 if (result instanceof OverlayWrapper) 152 return ((OverlayWrapper) result).getPainter(); 153 154 return result; 155 } 156 157 /** 158 * Returns layer priority (internally use the overlay priority). 159 * 160 * @see Overlay#getPriority() 161 */ 162 public OverlayPriority getPriority() 163 { 164 return overlay.getPriority(); 165 } 166 167 /** 168 * Set the layer priority (internally set the overlay priority). 169 * 170 * @see Overlay#setPriority(OverlayPriority) 171 */ 172 public void setPriority(OverlayPriority priority) 173 { 174 overlay.setPriority(priority); 175 } 176 177 /** 178 * Returns layer name (internally use the overlay name). 179 * 180 * @see Overlay#getName() 181 */ 182 public String getName() 183 { 184 return overlay.getName(); 185 } 186 187 /** 188 * Set the layer name (internally set the overlay name) 189 * 190 * @see Overlay#setName(String) 191 */ 192 public void setName(String name) 193 { 194 overlay.setName(name); 195 } 196 197 /** 198 * Returns the read only property name (internally use the overlay read only property). 199 * 200 * @see Overlay#isReadOnly() 201 */ 202 public boolean isReadOnly() 203 { 204 return overlay.isReadOnly(); 205 } 206 207 /** 208 * Set read only property (internally set the overlay read only property). 209 * 210 * @see Overlay#setReadOnly(boolean) 211 */ 212 public void setReadOnly(boolean readOnly) 213 { 214 overlay.setReadOnly(readOnly); 215 } 216 217 /** 218 * Returns fixed property. 219 * 220 * @deprecated Use {@link #getCanBeRemoved()} instead. 221 */ 222 @Deprecated 223 public boolean isFixed() 224 { 225 return !getCanBeRemoved(); 226 } 227 228 /** 229 * @deprecated Use {@link #setCanBeRemoved(boolean)} instead. 230 */ 231 @Deprecated 232 public void setFixed(boolean value) 233 { 234 setCanBeRemoved(value); 235 } 236 237 /** 238 * Returns <code>true</code> if the layer can be freely removed from the Canvas where it 239 * appears and <code>false</code> otherwise.<br/> 240 * 241 * @see Overlay#getCanBeRemoved() 242 */ 243 public boolean getCanBeRemoved() 244 { 245 return overlay.getCanBeRemoved(); 246 } 247 248 /** 249 * Set the <code>canBeRemoved</code> property.<br/> 250 * Set it to false if you want to prevent the layer to be removed from the Canvas where it 251 * appears. 252 * 253 * @see Overlay#setCanBeRemoved(boolean) 254 */ 255 public void setCanBeRemoved(boolean value) 256 { 257 overlay.setCanBeRemoved(value); 258 } 259 260 /** 261 * @see Overlay#getReceiveKeyEventOnHidden() 262 */ 263 public boolean getReceiveKeyEventOnHidden() 264 { 265 return overlay.getReceiveKeyEventOnHidden(); 266 } 267 268 /** 269 * @see Overlay#setReceiveKeyEventOnHidden(boolean) 270 */ 271 public void setReceiveKeyEventOnHidden(boolean value) 272 { 273 overlay.setReceiveKeyEventOnHidden(value); 274 } 275 276 /** 277 * @see Overlay#getReceiveMouseEventOnHidden() 278 */ 279 public boolean getReceiveMouseEventOnHidden() 280 { 281 return overlay.getReceiveMouseEventOnHidden(); 282 } 283 284 /** 285 * @see Overlay#setReceiveMouseEventOnHidden(boolean) 286 */ 287 public void setReceiveMouseEventOnHidden(boolean value) 288 { 289 overlay.setReceiveMouseEventOnHidden(value); 290 } 291 292 /** 293 * @return the attachedROI 294 */ 295 public ROI getAttachedROI() 296 { 297 if (roi == null) 298 // search for attached ROI 299 roi = new WeakReference<ROI>(Icy.getMainInterface().getROI(overlay)); 300 301 return roi.get(); 302 } 303 304 /** 305 * @return the visible 306 */ 307 public boolean isVisible() 308 { 309 return visible; 310 } 311 312 /** 313 * @param visible 314 * the visible to set 315 */ 316 public void setVisible(boolean visible) 317 { 318 if (this.visible != visible) 319 { 320 this.visible = visible; 321 changed(PROPERTY_VISIBLE); 322 } 323 } 324 325 /** 326 * @return the layer opacity 327 */ 328 public float getOpacity() 329 { 330 return alpha; 331 } 332 333 /** 334 * Set the layer opacity 335 */ 336 public void setOpacity(float value) 337 { 338 if (alpha != value) 339 { 340 alpha = value; 341 changed(PROPERTY_OPACITY); 342 } 343 } 344 345 /** 346 * @deprecated Use {@link #getOpacity()} instead 347 */ 348 @Deprecated 349 public float getAlpha() 350 { 351 return getOpacity(); 352 } 353 354 /** 355 * @deprecated Use {@link #setOpacity(float)} instead. 356 */ 357 @Deprecated 358 public void setAlpha(float value) 359 { 360 setOpacity(value); 361 } 362 363 /** 364 * Called on layer property change 365 */ 366 protected void changed(String propertyName) 367 { 368 // notify listener 369 fireChangedEvent(propertyName); 370 } 371 372 /** 373 * fire event 374 */ 375 private void fireChangedEvent(String propertyName) 376 { 377 final List<LayerListener> list; 378 379 synchronized (listeners) 380 { 381 list = new ArrayList<Layer.LayerListener>(listeners); 382 } 383 384 for (LayerListener listener : list) 385 listener.layerChanged(this, propertyName); 386 } 387 388 /** 389 * Add a listener 390 * 391 * @param listener 392 */ 393 public void addListener(LayerListener listener) 394 { 395 synchronized (listeners) 396 { 397 listeners.add(listener); 398 } 399 } 400 401 /** 402 * Remove a listener 403 * 404 * @param listener 405 */ 406 public void removeListener(LayerListener listener) 407 { 408 synchronized (listeners) 409 { 410 listeners.remove(listener); 411 } 412 } 413 414 @Override 415 public void overlayChanged(OverlayEvent event) 416 { 417 // only interested by property change here 418 if (event.getType() == OverlayEventType.PROPERTY_CHANGED) 419 changed(event.getPropertyName()); 420 } 421 422 @Override 423 public int compareTo(Layer layer) 424 { 425 // compare with overlay 426 return getOverlay().compareTo(layer.getOverlay()); 427 } 428}