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