1 /*
   2  * Copyright (c) 2014, 2017, 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.css;
  27 
  28 import com.sun.javafx.property.PropertyReference;
  29 import javafx.scene.paint.LinearGradient;
  30 import javafx.beans.property.ReadOnlyProperty;
  31 import javafx.beans.value.ObservableValue;
  32 import javafx.geometry.Insets;
  33 import javafx.geometry.Pos;
  34 import javafx.scene.Group;
  35 import javafx.scene.Scene;
  36 import javafx.scene.effect.BlurType;
  37 import javafx.scene.effect.Effect;
  38 import javafx.scene.effect.InnerShadow;
  39 import javafx.scene.paint.Color;
  40 import javafx.scene.paint.CycleMethod;
  41 import javafx.scene.paint.Paint;
  42 import javafx.scene.paint.Stop;
  43 import javafx.scene.text.Font;
  44 import javafx.util.Duration;
  45 import org.hamcrest.BaseMatcher;
  46 import org.hamcrest.CoreMatchers;
  47 import org.hamcrest.Description;
  48 import org.hamcrest.Matcher;
  49 import org.junit.Before;
  50 import org.junit.Test;
  51 import org.junit.runner.RunWith;
  52 import org.junit.runners.Parameterized;
  53 
  54 import java.util.Arrays;
  55 import java.util.Collection;
  56 import java.util.List;
  57 import javafx.css.CssMetaData;
  58 import javafx.css.Styleable;
  59 import javafx.css.StyleableProperty;
  60 import javafx.css.StyleablePropertyFactory;
  61 
  62 import static org.junit.Assert.*;
  63 
  64 @RunWith(Parameterized.class)
  65 public class StyleablePropertyFactoryTest {
  66 
  67     private static class Data<T> {
  68 
  69         final PropertyReference propertyReference;
  70         final String style;
  71         final T value;
  72         final Matcher<T> matcher;
  73 
  74         Data(String name, String style, T value) {
  75             this(name,style,value,CoreMatchers.equalTo(value));
  76         }
  77 
  78         Data(String name, String style, T value, Matcher<T> matcher) {
  79             this.propertyReference = new PropertyReference(MyStyleable.class, name);
  80             this.style = style;
  81             this.value = value;
  82             this.matcher = matcher;
  83         }
  84     }
  85 
  86     private final Data data;
  87 
  88     public StyleablePropertyFactoryTest(Data data) {
  89         this.data = data;
  90     }
  91 
  92     @Parameterized.Parameters
  93     public static Collection<Data[]> data() {
  94 
  95         return Arrays.asList(new Data[][]{
  96                 {new Data("myBoolean", "-my-boolean: true;", Boolean.TRUE)},
  97                 {new Data("myColor", "-my-color: red;", Color.RED)},
  98                 {new Data("myDuration", "-my-duration: 30ms;", Duration.millis(30))},
  99                 {new Data("myEffect", "-my-effect: innershadow(gaussian, red, 10, .5, 1, 1);",
 100                         new InnerShadow(BlurType.GAUSSIAN, Color.RED, 10, .5, 1, 1),
 101                         new BaseMatcher<InnerShadow>() {
 102                             @Override
 103                             public boolean matches(Object o) {
 104                                 InnerShadow actual = (InnerShadow)o;
 105                                 return (actual.getBlurType() == BlurType.GAUSSIAN &&
 106                                         actual.getColor().equals(Color.RED) &&
 107                                         Double.compare(actual.getRadius(),10d) ==  0 &&
 108                                         Double.compare(actual.getChoke(),.5d) ==  0 &&
 109                                         Double.compare(actual.getOffsetX(),1d) ==  0 &&
 110                                         Double.compare(actual.getOffsetY(),1d) ==  0);
 111                             }
 112                             @Override
 113                             public void describeTo(Description description) {
 114                                 description.appendText("InnerShadow(BlurType.GAUSSIAN, Color.RED, 10, .5, 1, 1)");
 115                             }
 116                         })
 117                 },
 118                 {new Data("myPos", "-my-pos: bottom-right;", Pos.BOTTOM_RIGHT)},
 119                 {new Data("myFont", "-my-font: 18 system;", Font.font("system", 18))},
 120                 {new Data("myInsets", "-my-insets: 1 2 3 4;", new Insets(1,2,3,4))},
 121                 {new Data("myInsets", "-my-insets: 5;", new Insets(5,5,5,5))},
 122                 {new Data("myInsets", "-my-insets: 7 8;", new Insets(7,8,7,8))},
 123                 {new Data("myInsets", "-my-insets: 9 10 11;", new Insets(9,10,11,10))},
 124                 {new Data("myPaint", "-my-paint: linear-gradient(from 0% 0% to 100% 100%, red 0%, black 100%);",
 125                         new LinearGradient(0,0,1,1,true, CycleMethod.NO_CYCLE,new Stop[] { new Stop(0,Color.RED), new Stop(1,Color.BLACK) }))
 126                 },
 127                 {new Data("myNumber", "-my-number: 2em;", Font.getDefault().getSize()*2)},
 128                 {new Data("myString", "-my-string: \"yaba daba do\";", "yaba daba do")},
 129                 {new Data("myUrl", "-my-url: url('http://www.oracle.com');", "http://www.oracle.com")}
 130         });
 131 
 132     }
 133 
 134     @Test
 135     public void theTest() {
 136         MyStyleable styleable = new MyStyleable();
 137         styleable.setStyle(data.style);
 138 
 139         Scene scene = new Scene(styleable);
 140         styleable.applyCss();
 141 
 142         ReadOnlyProperty prop = data.propertyReference.getProperty(styleable);
 143         assertThat(prop.getValue(), data.matcher);
 144     }
 145 
 146     public static class MyStyleable extends Group {
 147 
 148         public MyStyleable() {
 149         }
 150 
 151         private static final StyleablePropertyFactory fac = new StyleablePropertyFactory<>(null);
 152 
 153         public ObservableValue<Boolean> myBooleanProperty () { return (ObservableValue<Boolean>) myBoolean; }
 154         public Boolean getMyBoolean() { return myBoolean.getValue(); }
 155         public void setMyBoolean(Boolean value) { myBoolean.setValue(value); }
 156         private final StyleableProperty<Boolean> myBoolean = fac.createStyleableBooleanProperty(this, "myBoolean", "-my-boolean", s -> ((MyStyleable) s).myBoolean);
 157 
 158         public ObservableValue<Color> myColorProperty () { return (ObservableValue<Color>) myColor; }
 159         public Color getMyColor() { return myColor.getValue(); }
 160         public void setMyColor(Color value) { myColor.setValue(value); }
 161         private final StyleableProperty<Color> myColor = fac.createStyleableColorProperty(this, "myColor", "-my-color", s -> ((MyStyleable) s).myColor);
 162 
 163         public ObservableValue<Duration> myDurationProperty () { return (ObservableValue<Duration>) myDuration; }
 164         public Duration getMyDuration() { return myDuration.getValue(); }
 165         public void setMyDuration(Duration value) { myDuration.setValue(value); }
 166         private final StyleableProperty<Duration> myDuration = fac.createStyleableDurationProperty(this, "myDuration", "-my-duration", s -> ((MyStyleable) s).myDuration);
 167 
 168         public ObservableValue<Effect> myEffectProperty () { return (ObservableValue<Effect>) myEffect; }
 169         public Effect getMyEffect() { return myEffect.getValue(); }
 170         public void setMyEffect(Effect value) { myEffect.setValue(value); }
 171         private final StyleableProperty<Effect> myEffect = fac.createStyleableEffectProperty(this, "myEffect", "-my-effect", s -> ((MyStyleable) s).myEffect);
 172 
 173         public ObservableValue<Pos> myPosProperty () { return (ObservableValue<Pos>) myPos; }
 174         public Pos getMyPos() { return myPos.getValue(); }
 175         public void setMyPos(Pos value) { myPos.setValue(value); }
 176         private final StyleableProperty<Pos> myPos = fac.createStyleableEnumProperty(this, "myPos", "-my-pos", s -> ((MyStyleable) s).myPos, Pos.class);
 177 
 178         public ObservableValue<Font> myFontProperty () { return (ObservableValue<Font>) myFont; }
 179         public Font getMyFont() { return myFont.getValue(); }
 180         public void setMyFont(Font value) { myFont.setValue(value); }
 181         private final StyleableProperty<Font> myFont = fac.createStyleableFontProperty(this, "myFont", "-my-font", s -> ((MyStyleable) s).myFont);
 182 
 183         public ObservableValue<Insets> myInsetsProperty () { return (ObservableValue<Insets>) myInsets; }
 184         public Insets getMyInsets() { return myInsets.getValue(); }
 185         public void setMyInsets(Insets value) { myInsets.setValue(value); }
 186         private final StyleableProperty<Insets> myInsets = fac.createStyleableInsetsProperty(this, "myInsets", "-my-insets", s -> ((MyStyleable) s).myInsets);
 187 
 188         public ObservableValue<Paint> myPaintProperty () { return (ObservableValue<Paint>) myPaint; }
 189         public Paint getMyPaint() { return myPaint.getValue(); }
 190         public void setMyPaint(Paint value) { myPaint.setValue(value); }
 191         private final StyleableProperty<Paint> myPaint = fac.createStyleablePaintProperty(this, "myPaint", "-my-paint", s -> ((MyStyleable) s).myPaint);
 192 
 193         public ObservableValue<Double> myNumberProperty () { return (ObservableValue<Double>) myNumber; }
 194         public Double getMyNumber() { return myNumber.getValue().doubleValue(); }
 195         public void setMyNumber(Double value) { myNumber.setValue(value); }
 196         private final StyleableProperty<Number> myNumber = fac.createStyleableNumberProperty(this, "myNumber", "-my-number", s -> ((MyStyleable) s).myNumber);
 197 
 198         public ObservableValue<String> myStringProperty () { return (ObservableValue<String>) myString; }
 199         public String getMyString() { return myString.getValue(); }
 200         public void setMyString(String value) { myString.setValue(value); }
 201         private final StyleableProperty<String> myString = fac.createStyleableStringProperty(this, "myString", "-my-string", s -> ((MyStyleable) s).myString);
 202 
 203         public ObservableValue<String> myUrlProperty () { return (ObservableValue<String>) myUrl; }
 204         public String getMyUrl() { return myUrl.getValue(); }
 205         public void setMyUrl(String value) { myUrl.setValue(value); }
 206         private final StyleableProperty<String> myUrl = fac.createStyleableUrlProperty(this, "myUrl", "-my-url", s -> ((MyStyleable) s).myUrl);
 207 
 208         @Override
 209         public String getTypeSelector() {
 210             return "MyStyleable";
 211         }
 212 
 213         @Override
 214         public Styleable getStyleableParent() {
 215             return null;
 216         }
 217 
 218         @Override
 219         public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 220             return fac.getCssMetaData();
 221         }
 222     }
 223 }