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