1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.effect;
  27 
  28 import javafx.beans.Observable;
  29 import javafx.beans.property.DoubleProperty;
  30 import javafx.beans.property.DoublePropertyBase;
  31 import javafx.beans.property.ObjectProperty;
  32 import javafx.beans.property.ObjectPropertyBase;
  33 import javafx.scene.Node;
  34 import javafx.scene.image.Image;
  35 
  36 import com.sun.javafx.beans.event.AbstractNotifyListener;
  37 import com.sun.javafx.effect.EffectDirtyBits;
  38 import com.sun.javafx.geom.BaseBounds;
  39 import com.sun.javafx.geom.RectBounds;
  40 import com.sun.javafx.geom.transform.BaseTransform;
  41 import com.sun.javafx.scene.BoundsAccessor;
  42 import com.sun.javafx.tk.Toolkit;
  43 
  44 
  45 /**
  46  * A type of source effect that simply passes the given {@code Image}
  47  * through, unmodified, as an input to another {@code Effect}.
  48  * @since JavaFX 2.0
  49  */
  50 public class ImageInput extends Effect {
  51     /**
  52      * Creates a new instance of ImageInput with default parameters.
  53      */
  54     public ImageInput() {}
  55 
  56     /**
  57      * Creates a new instance of ImageInput with the specified source.
  58      * @param source the source {@code Image}.
  59      * @since JavaFX 2.1
  60      */
  61     public ImageInput(Image source) {
  62         setSource(source);
  63     }
  64 
  65     /**
  66      * Creates a new instance of ImageInput with the specified source, x and y.
  67      * @param source the source {@code Image}.
  68      * @param x the x location of the source image
  69      * @param y the y location of the source image
  70      * @since JavaFX 2.1
  71      */
  72     public ImageInput(Image source, double x, double y) {
  73         setSource(source);
  74         setX(x);
  75         setY(y);
  76     }
  77 
  78     @Override
  79     com.sun.scenario.effect.Identity impl_createImpl() {
  80         return new com.sun.scenario.effect.Identity(null);
  81     };
  82     /**
  83      * The source {@code Image}.
  84      */
  85     private ObjectProperty<Image> source;
  86 
  87 
  88     public final void setSource(Image value) {
  89         sourceProperty().set(value);
  90     }
  91 
  92     public final Image getSource() {
  93         return source == null ? null : source.get();
  94     }
  95 
  96     private final AbstractNotifyListener platformImageChangeListener =
  97         new AbstractNotifyListener() {
  98             @Override
  99             public void invalidated(Observable valueModel) {
 100                 markDirty(EffectDirtyBits.EFFECT_DIRTY);
 101                 effectBoundsChanged();
 102             }
 103         };
 104     private Image oldImage;
 105     public final ObjectProperty<Image> sourceProperty() {
 106         if (source == null) {
 107             source = new ObjectPropertyBase<Image>() {
 108 
 109                 private boolean needsListeners = false;
 110 
 111                 @Override
 112                 public void invalidated() {
 113                     Image _image = get();
 114 
 115                     Toolkit.ImageAccessor accessor = Toolkit.getImageAccessor();
 116 
 117                     if (needsListeners) {
 118                         accessor.getImageProperty(oldImage).
 119                                 removeListener(platformImageChangeListener.getWeakListener());
 120                     }
 121 
 122                     needsListeners = _image != null && (accessor.isAnimation(_image) ||
 123                                                         _image.getProgress() < 1);
 124                     oldImage = _image;
 125 
 126                     if (needsListeners) {
 127                         accessor.getImageProperty(_image).
 128                                 addListener(platformImageChangeListener.getWeakListener());
 129                     }
 130                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 131                     effectBoundsChanged();
 132                 }
 133 
 134                 @Override
 135                 public Object getBean() {
 136                     return ImageInput.this;
 137                 }
 138 
 139                 @Override
 140                 public String getName() {
 141                     return "source";
 142                 }
 143             };
 144         }
 145         return source;
 146     }
 147 
 148     /**
 149      * Sets the x location of the source image, relative to the
 150      * local coordinate space of the content {@code Node}.
 151      * <pre>
 152      *       Min: n/a
 153      *       Max: n/a
 154      *   Default: 0.0
 155      *  Identity: 0.0
 156      * </pre>
 157      * @defaultValue 0.0
 158      */
 159     private DoubleProperty x;
 160 
 161 
 162     public final void setX(double value) {
 163         xProperty().set(value);
 164     }
 165 
 166     public final double getX() {
 167         return x == null ? 0.0 : x.get();
 168     }
 169 
 170     public final DoubleProperty xProperty() {
 171         if (x == null) {
 172             x = new DoublePropertyBase() {
 173 
 174                 @Override
 175                 public void invalidated() {
 176                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 177                     effectBoundsChanged();
 178                 }
 179 
 180                 @Override
 181                 public Object getBean() {
 182                     return ImageInput.this;
 183                 }
 184 
 185                 @Override
 186                 public String getName() {
 187                     return "x";
 188                 }
 189             };
 190         }
 191         return x;
 192     }
 193 
 194     /**
 195      * Sets the y location of the source image, relative to the
 196      * local coordinate space of the content {@code Node}.
 197      * <pre>
 198      *       Min: n/a
 199      *       Max: n/a
 200      *   Default: 0.0
 201      *  Identity: 0.0
 202      * </pre>
 203      * @defaultValue 0.0
 204      */
 205     private DoubleProperty y;
 206 
 207 
 208     public final void setY(double value) {
 209         yProperty().set(value);
 210     }
 211 
 212     public final double getY() {
 213         return y == null ? 0.0 : y.get();
 214     }
 215 
 216     public final DoubleProperty yProperty() {
 217         if (y == null) {
 218             y = new DoublePropertyBase() {
 219 
 220                 @Override
 221                 public void invalidated() {
 222                     markDirty(EffectDirtyBits.EFFECT_DIRTY);
 223                     effectBoundsChanged();
 224                 }
 225 
 226                 @Override
 227                 public Object getBean() {
 228                     return ImageInput.this;
 229                 }
 230 
 231                 @Override
 232                 public String getName() {
 233                     return "y";
 234                 }
 235             };
 236         }
 237         return y;
 238     }
 239 
 240     @Override
 241     void impl_update() {
 242         com.sun.scenario.effect.Identity peer =
 243                 (com.sun.scenario.effect.Identity) impl_getImpl();
 244         Image localSource = getSource();
 245         if (localSource != null && localSource.impl_getPlatformImage() != null) {
 246             peer.setSource(Toolkit.getToolkit().toFilterable(localSource));
 247         } else {
 248             peer.setSource(null);
 249         }
 250         peer.setLocation(new com.sun.javafx.geom.Point2D((float)getX(), (float)getY()));
 251     }
 252 
 253     @Override
 254     boolean impl_checkChainContains(Effect e) {
 255         return false;
 256     }
 257 
 258     /**
 259      * @treatAsPrivate implementation detail
 260      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 261      */
 262     @Deprecated
 263     @Override
 264     public BaseBounds impl_getBounds(BaseBounds bounds,
 265                                      BaseTransform tx,
 266                                      Node node,
 267                                      BoundsAccessor boundsAccessor) {
 268         Image localSource = getSource();
 269         if (localSource != null && localSource.impl_getPlatformImage() != null) {
 270             float localX = (float) getX();
 271             float localY = (float) getY();
 272             float localWidth = (float) localSource.getWidth();
 273             float localHeight = (float) localSource.getHeight();
 274             BaseBounds r = new RectBounds(
 275                     localX, localY,
 276                     localX + localWidth, localY + localHeight);
 277             return transformBounds(tx, r);
 278         } else {
 279             return new RectBounds();
 280         }
 281     }
 282 
 283     /**
 284      * @treatAsPrivate implementation detail
 285      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 286      */
 287     @Deprecated
 288     @Override
 289     public Effect impl_copy() {
 290         return new ImageInput(this.getSource(), this.getX(), this.getY());
 291     }
 292 }