1 /*
   2  * Copyright (c) 2011, 2016, 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 test.javafx.scene;
  27 
  28 import javafx.css.converter.PaintConverter;
  29 import javafx.css.converter.SizeConverter;
  30 import com.sun.javafx.geom.BaseBounds;
  31 import com.sun.javafx.geom.transform.BaseTransform;
  32 import com.sun.javafx.jmx.MXNodeAlgorithm;
  33 import com.sun.javafx.jmx.MXNodeAlgorithmContext;
  34 import com.sun.javafx.scene.NodeHelper;
  35 import com.sun.javafx.sg.prism.NGGroup;
  36 import com.sun.javafx.sg.prism.NGNode;
  37 import javafx.beans.property.*;
  38 import javafx.css.*;
  39 import javafx.scene.paint.Color;
  40 import javafx.scene.paint.Paint;
  41 
  42 import java.util.ArrayList;
  43 import java.util.List;
  44 import javafx.scene.Node;
  45 import test.com.sun.javafx.scene.CSSNodeHelper;
  46 
  47 public  class CSSNode extends Node {
  48     static {
  49         CSSNodeHelper.setCSSNodeAccessor(new CSSNodeHelper.CSSNodeAccessor() {
  50             @Override
  51             public NGNode doCreatePeer(Node node) {
  52                 return ((CSSNode) node).doCreatePeer();
  53             }
  54 
  55             @Override
  56             public BaseBounds doComputeGeomBounds(Node node,
  57             BaseBounds bounds, BaseTransform tx) {
  58                 return ((CSSNode) node).doComputeGeomBounds(bounds, tx);
  59             }
  60 
  61             @Override
  62             public boolean doComputeContains(Node node, double localX, double localY) {
  63                 return ((CSSNode) node).doComputeContains(localX, localY);
  64             }
  65 
  66             @Override
  67             public Object doProcessMXNode(Node node, MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
  68                 return ((CSSNode) node).doProcessMXNode(alg, ctx);
  69             }
  70         });
  71     }
  72 
  73     {
  74         // To initialize the class helper at the begining each constructor of this class
  75         CSSNodeHelper.initHelper(this);
  76     }
  77 
  78     public CSSNode() {
  79         setContentSize(100);
  80     }
  81 
  82     /**
  83      * This variable can be set from CSS and represents the fill
  84      */
  85     private ObjectProperty<Paint> fill;
  86     public ObjectProperty<Paint> fillProperty() {
  87         if (fill == null) {
  88             fill = new StyleableObjectProperty<Paint>(Color.BLACK) {
  89 
  90                 @Override
  91                 public Object getBean() {
  92                     return CSSNode.this;
  93                 }
  94 
  95                 @Override
  96                 public String getName() {
  97                     return "fill";
  98                 }
  99 
 100                 @Override
 101                 public CssMetaData getCssMetaData() {
 102                     return StyleableProperties.FILL;
 103                 }
 104 
 105             };
 106         }
 107         return fill;
 108     }
 109     public void setFill(Paint paint) {
 110         fillProperty().set(paint);
 111     }
 112     public Paint getFill() {
 113         return (fill == null ? Color.BLACK : fill.get());
 114     }
 115 
 116     /**
 117      * This variable can be set from CSS and represents the stroke fill
 118      */
 119     private ObjectProperty<Paint> stroke;
 120     public ObjectProperty<Paint> strokeProperty() {
 121         if (stroke == null) {
 122             stroke = new StyleableObjectProperty<Paint>(Color.BLACK) {
 123 
 124                 @Override
 125                 public Object getBean() {
 126                     return CSSNode.this;
 127                 }
 128 
 129                 @Override
 130                 public String getName() {
 131                     return "stroke";
 132                 }
 133 
 134                 @Override
 135                 public CssMetaData getCssMetaData() {
 136                     return StyleableProperties.STROKE;
 137                 }
 138 
 139             };
 140         }
 141         return stroke;
 142     }
 143     public void setStroke(Paint paint) {
 144         strokeProperty().set(paint);
 145     }
 146     public Paint getStroke() {
 147         return (stroke == null ? Color.BLACK : stroke.get());
 148     }
 149 
 150     /**
 151      * This variable can be set from CSS and is a simple number. For testing,
 152      * this can be font-based, absolute, or percentage based. The CSSNode has
 153      * a contentSize:Number variable which is used when padding is based on
 154      * a percentage
 155      */
 156     private FloatProperty padding;
 157 
 158     public final void setPadding(float value) {
 159         paddingProperty().set(value);
 160     }
 161 
 162     public final float getPadding() {
 163         return padding == null ? 0.0F : padding.get();
 164     }
 165 
 166     public FloatProperty paddingProperty() {
 167         if (padding == null) {
 168             padding = new StyleableFloatProperty() {
 169 
 170                 @Override
 171                 protected void invalidated() {
 172                     NodeHelper.geomChanged(CSSNode.this);
 173                 }
 174 
 175                 @Override
 176                 public Object getBean() {
 177                     return CSSNode.this;
 178                 }
 179 
 180                 @Override
 181                 public String getName() {
 182                     return "padding";
 183                 }
 184 
 185                 @Override
 186                 public CssMetaData getCssMetaData() {
 187                     return StyleableProperties.PADDING;
 188                 }
 189             };
 190         }
 191         return padding;
 192     }
 193 
 194     /**
 195      * Used only when padding is specified as a percentage, as it is a
 196      * percentage of the content size.
 197      */
 198     private FloatProperty contentSize;
 199 
 200     public final void setContentSize(float value) {
 201         contentSizeProperty().set(value);
 202     }
 203 
 204     public final float getContentSize() {
 205         return contentSize == null ? 0.0F : contentSize.get();
 206     }
 207 
 208     public FloatProperty contentSizeProperty() {
 209         if (contentSize == null) {
 210             contentSize = new SimpleFloatProperty() {
 211 
 212                 @Override
 213                 protected void invalidated() {
 214                     NodeHelper.geomChanged(CSSNode.this);
 215                 }
 216             };
 217         }
 218         return contentSize;
 219     }
 220 
 221     /**
 222      * A pseudoclass state for this Node. It cannot be styled, but can
 223      * be used as a pseudoclass
 224      */
 225     private PseudoClass SPECIAL_PSEUDO_CLASS = PseudoClass.getPseudoClass("special");
 226     private BooleanProperty special;
 227     public final void setSpecial(boolean value) {
 228         specialProperty().set(value);
 229     }
 230 
 231     public final boolean isSpecial() {
 232         return special == null ? false : special.get();
 233     }
 234 
 235     public BooleanProperty specialProperty() {
 236         if (special == null) {
 237             special = new SimpleBooleanProperty() {
 238 
 239                 @Override
 240                 protected void invalidated() {
 241                     pseudoClassStateChanged(SPECIAL_PSEUDO_CLASS, get());
 242                 }
 243             };
 244         }
 245         return special;
 246     }
 247 
 248     /*
 249      * These vars are used solely for the sake of testing.
 250      */
 251 
 252     public boolean reapply = false;
 253     public boolean processCalled = false;
 254     public boolean applyCalled = false;
 255 
 256     /*
 257      * Note: This method MUST only be called via its accessor method.
 258      */
 259     private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) {
 260         if (bounds != null) {
 261             bounds = bounds.deriveWithNewBounds(0, 0, 0,
 262                     getContentSize() + getPadding() + getPadding(), getContentSize() + getPadding() + getPadding(), 0);
 263         }
 264         return bounds;
 265     }
 266 
 267     /*
 268      * Note: This method MUST only be called via its accessor method.
 269      */
 270     private boolean doComputeContains(double localX, double localY) {
 271         // TODO: Missing code.
 272         return false;
 273     }
 274 
 275     private NGNode doCreatePeer() {
 276         return new NGGroup();
 277     }
 278 
 279     public static class StyleableProperties {
 280 
 281         public static final CssMetaData<CSSNode,Paint> FILL =
 282             new CssMetaData<CSSNode,Paint>("fill", PaintConverter.getInstance()) {
 283 
 284             @Override
 285             public boolean isSettable(CSSNode n) {
 286                 return n.fill == null || !n.fill.isBound();
 287             }
 288 
 289             @Override
 290             public StyleableProperty<Paint> getStyleableProperty(CSSNode n) {
 291                 return (StyleableProperty<Paint>)n.fillProperty();
 292             }
 293         };
 294 
 295         public static final CssMetaData<CSSNode,Paint> STROKE =
 296             new CssMetaData<CSSNode,Paint>("stroke", PaintConverter.getInstance()) {
 297 
 298             @Override
 299             public boolean isSettable(CSSNode n) {
 300                 return n.stroke == null || !n.stroke.isBound();
 301             }
 302 
 303             @Override
 304             public StyleableProperty<Paint> getStyleableProperty(CSSNode n) {
 305                 return (StyleableProperty<Paint>)n.strokeProperty();
 306             }
 307         };
 308 
 309         public static final CssMetaData<CSSNode,Number> PADDING =
 310             new CssMetaData<CSSNode,Number>("padding", SizeConverter.getInstance()) {
 311 
 312             @Override
 313             public boolean isSettable(CSSNode n) {
 314                 return n.padding == null || !n.padding.isBound();
 315             }
 316 
 317             @Override
 318             public StyleableProperty<Number> getStyleableProperty(CSSNode n) {
 319                 return (StyleableProperty<Number>)n.paddingProperty();
 320             }
 321         };
 322 
 323         private static List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 324         static {
 325             final List<CssMetaData<? extends Styleable, ?>> styleables =
 326                 new ArrayList<CssMetaData<? extends Styleable, ?>>(Node.getClassCssMetaData());
 327             styleables.add(FILL);
 328             styleables.add(STROKE);
 329             styleables.add(PADDING);
 330 
 331         }
 332 
 333     }
 334 
 335     /**
 336      * @return The CssMetaData associated with this class, which may include the
 337      * CssMetaData of its super classes.
 338      */
 339     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 340         return StyleableProperties.STYLEABLES;
 341     }
 342 
 343     /**
 344      * {@inheritDoc}
 345      *
 346      */
 347 
 348 
 349     @Override
 350     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 351         return getClassCssMetaData();
 352     }
 353 
 354     /*
 355      * Note: This method MUST only be called via its accessor method.
 356      */
 357     private Object doProcessMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
 358         return null;
 359     }
 360 }