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