1 /*
   2  * Copyright (c) 2012, 2015, 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.css.CascadingStyle;
  29 import com.sun.javafx.css.ParsedValueImpl;
  30 import com.sun.javafx.css.StyleManager;
  31 import com.sun.javafx.scene.NodeHelper;
  32 import javafx.css.converter.FontConverter;
  33 import javafx.css.converter.SizeConverter;
  34 
  35 import java.util.ArrayList;
  36 import java.util.Collections;
  37 import java.util.List;
  38 import java.util.Map;
  39 
  40 import javafx.beans.property.Property;
  41 import javafx.css.CssMetaData;
  42 import javafx.css.Declaration;
  43 import javafx.css.DeclarationShim;
  44 import javafx.css.ParsedValue;
  45 import javafx.css.Rule;
  46 import javafx.css.RuleShim;
  47 import javafx.css.Selector;
  48 import javafx.css.Size;
  49 import javafx.css.SizeUnits;
  50 import javafx.css.Style;
  51 import javafx.css.StyleOrigin;
  52 import javafx.css.StyleableProperty;
  53 import javafx.css.Stylesheet;
  54 import javafx.css.StylesheetShim;
  55 import javafx.scene.Group;
  56 import javafx.scene.Node;
  57 import javafx.scene.Scene;
  58 import javafx.scene.paint.Color;
  59 import javafx.scene.shape.Rectangle;
  60 import javafx.scene.text.Font;
  61 import javafx.scene.text.Text;
  62 
  63 import static org.junit.Assert.*;
  64 
  65 import org.junit.Ignore;
  66 import org.junit.Test;
  67 
  68 @Ignore
  69 public class Node_cssStyleMap_Test {
  70 
  71     public Node_cssStyleMap_Test() {
  72     }
  73 
  74     boolean disabled = false;
  75 
  76     private void checkFoundStyle(Property<?> property, Map<StyleableProperty<?>, List<Style>> map, List<Declaration> decls) {
  77 
  78         List<Style> styles = map.get(property);
  79         assert (styles != null && !styles.isEmpty());
  80 
  81         String pname = ((StyleableProperty<?>)property).getCssMetaData().getProperty();
  82         Declaration declaration = null;
  83         for(Declaration decl : decls) {
  84             if (pname.equals(decl.getProperty())) {
  85                 declaration = decl;
  86                 break;
  87             }
  88         }
  89         assertNotNull(pname, declaration);
  90 
  91         Style style = null;
  92         for(Style s : styles) {
  93             if (pname.equals(s.getDeclaration().getProperty())) {
  94                 style = s;
  95                 break;
  96             }
  97         }
  98         assertNotNull(pname, style);
  99 
 100         assert(style.getDeclaration() == declaration);
 101 
 102     }
 103 
 104     @Test
 105     public void testStyleMap() {
 106 
 107         final List<Declaration> declsNoState = new ArrayList<Declaration>();
 108         Collections.addAll(declsNoState,
 109             DeclarationShim.getDeclaration("-fx-fill", new ParsedValueImpl<Color,Color>(Color.RED, null), false),
 110             DeclarationShim.getDeclaration("-fx-stroke", new ParsedValueImpl<Color,Color>(Color.YELLOW, null), false),
 111             DeclarationShim.getDeclaration("-fx-stroke-width", new ParsedValueImpl<ParsedValue<?,Size>,Number>(
 112                 new ParsedValueImpl<Size,Size>(new Size(3d, SizeUnits.PX), null),
 113                 SizeConverter.getInstance()), false)
 114         );
 115 
 116 
 117         final List<Selector> selsNoState = new ArrayList<Selector>();
 118         Collections.addAll(selsNoState,
 119             Selector.createSelector(".rect")
 120         );
 121 
 122         Rule rule = RuleShim.getRule(selsNoState, declsNoState);
 123 
 124         Stylesheet stylesheet = new StylesheetShim("testStyleMap");
 125         stylesheet.setOrigin(StyleOrigin.USER_AGENT);
 126         stylesheet.getRules().add(rule);
 127 
 128         final List<Declaration> declsDisabledState = new ArrayList<Declaration>();
 129         Collections.addAll(declsDisabledState,
 130             DeclarationShim.getDeclaration("-fx-fill", new ParsedValueImpl<Color,Color>(Color.GRAY, null), false),
 131             DeclarationShim.getDeclaration("-fx-stroke", new ParsedValueImpl<Color,Color>(Color.DARKGRAY, null), false)
 132         );
 133 
 134         final List<Selector> selsDisabledState = new ArrayList<Selector>();
 135         Collections.addAll(selsDisabledState,
 136             Selector.createSelector(".rect:disabled")
 137         );
 138 
 139         rule = RuleShim.getRule(selsDisabledState, declsDisabledState);
 140         stylesheet.getRules().add(rule);
 141 
 142         Rectangle rect = new Rectangle(50,50);
 143         rect.getStyleClass().add("rect");
 144 
 145         Group root = new Group();
 146         root.getChildren().add(rect);
 147         StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);
 148         Scene scene = new Scene(root);
 149 
 150         rect.applyCss();
 151 
 152         Map<StyleableProperty<?>, List<Style>> map = NodeHelper.findStyles(rect, null);
 153         assert (map != null && !map.isEmpty());
 154 
 155         checkFoundStyle(rect.fillProperty(), map, declsNoState);
 156         checkFoundStyle(rect.strokeProperty(), map, declsNoState);
 157         checkFoundStyle(rect.strokeWidthProperty(), map, declsNoState);
 158 
 159         rect.setDisable(true);
 160         rect.applyCss();
 161 
 162         map = NodeHelper.findStyles(rect, null);
 163         assert (map != null && !map.isEmpty());
 164 
 165         checkFoundStyle(rect.fillProperty(), map, declsDisabledState);
 166         checkFoundStyle(rect.strokeProperty(), map, declsDisabledState);
 167         checkFoundStyle(rect.strokeWidthProperty(), map, declsNoState);
 168 
 169     }
 170 
 171     @Test
 172     public void testStyleMapChildren() {
 173 
 174         final List<Declaration> declsNoState = new ArrayList<Declaration>();
 175         Collections.addAll(declsNoState,
 176                 DeclarationShim.getDeclaration("-fx-fill", new ParsedValueImpl<Color,Color>(Color.RED, null), false)
 177         );
 178 
 179         final List<Selector> selsNoState = new ArrayList<Selector>();
 180         Collections.addAll(selsNoState,
 181                 Selector.createSelector(".rect")
 182         );
 183 
 184         Rule rule = RuleShim.getRule(selsNoState, declsNoState);
 185 
 186         Stylesheet stylesheet = new StylesheetShim("testStyleMapChildren");
 187         stylesheet.setOrigin(StyleOrigin.USER_AGENT);
 188         stylesheet.getRules().add(rule);
 189 
 190         Rectangle rect = new Rectangle(50,50);
 191         rect.getStyleClass().add("rect");
 192 
 193         Group root = new Group();
 194         Group group = new Group();
 195         root.getChildren().add(group);
 196         group.getChildren().add(rect);
 197         StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);
 198         Scene scene = new Scene(root);
 199 
 200         root.applyCss();
 201 
 202         // Even though root and group have no styles, the styles for rect should still be found
 203         Map<StyleableProperty<?>, List<Style>> map = NodeHelper.findStyles(root, null);
 204         assert (map != null && !map.isEmpty());
 205 
 206         checkFoundStyle(rect.fillProperty(), map, declsNoState);
 207 
 208     }
 209 
 210     @Test
 211     public void testRT_21212() {
 212 
 213         final List<Declaration> rootDecls = new ArrayList<Declaration>();
 214         Collections.addAll(rootDecls,
 215             DeclarationShim.getDeclaration("-fx-font-size", new ParsedValueImpl<ParsedValue<?,Size>,Number>(
 216                 new ParsedValueImpl<Size,Size>(new Size(12, SizeUnits.PX), null),
 217                 SizeConverter.getInstance()), false)
 218         );
 219 
 220         final List<Selector> rootSels = new ArrayList<Selector>();
 221         Collections.addAll(rootSels,
 222             Selector.createSelector(".root")
 223         );
 224 
 225         Rule rootRule = RuleShim.getRule(rootSels, rootDecls);
 226 
 227         Stylesheet stylesheet = new StylesheetShim("testRT_21212");
 228         stylesheet.setOrigin(StyleOrigin.USER_AGENT);
 229         stylesheet.getRules().add(rootRule);
 230 
 231         Group group = new Group();
 232         group.getStyleClass().add("root");
 233 
 234 
 235         final ParsedValue[] fontValues = new ParsedValue[] {
 236             new ParsedValueImpl<String,String>("system", null),
 237             new ParsedValueImpl<ParsedValue<?,Size>,Number>(
 238                 new ParsedValueImpl<Size,Size>(new Size(1.5, SizeUnits.EM), null),
 239                 SizeConverter.getInstance()
 240             ),
 241             null,
 242             null
 243         };
 244         final List<Declaration> textDecls = new ArrayList<Declaration>();
 245         Collections.addAll(textDecls,
 246             DeclarationShim.getDeclaration("-fx-font", new ParsedValueImpl<ParsedValue[], Font>(
 247                 fontValues, FontConverter.getInstance()), false)
 248         );
 249 
 250         final List<Selector> textSels = new ArrayList<Selector>();
 251         Collections.addAll(textSels,
 252             Selector.createSelector(".text")
 253         );
 254 
 255         Rule textRule = RuleShim.getRule(textSels, textDecls);
 256         stylesheet.getRules().add(textRule);
 257 
 258         Text text = new Text("HelloWorld");
 259         text.getStyleClass().add("text");
 260         group.getChildren().add(text);
 261 
 262         StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);
 263         Scene scene = new Scene(group);
 264 
 265         text.applyCss();
 266 
 267         Map<StyleableProperty<?>, List<Style>> map = NodeHelper.findStyles(text, null);
 268         assert (map != null && !map.isEmpty());
 269 
 270         checkFoundStyle(text.fontProperty(), map, textDecls);
 271 
 272     }
 273 
 274     boolean containsProperty(CssMetaData key, Map<String,List<CascadingStyle>> map) {
 275 
 276         if (map.containsKey(key)) return true;
 277         List<CssMetaData> subProperties = key.getSubProperties();
 278         if (subProperties != null && !subProperties.isEmpty()) {
 279             for (CssMetaData subKey: subProperties) {
 280                 if (map.containsKey(subKey)) return true;
 281             }
 282         }
 283         return false;
 284     }
 285 
 286     @Test
 287     public void testRT_34799() {
 288 
 289         Stylesheet stylesheet = new StylesheetShim("testRT_34799");
 290         stylesheet.setOrigin(StyleOrigin.USER_AGENT);
 291 
 292         final List<Declaration> txtDecls = new ArrayList<Declaration>();
 293         Collections.addAll(txtDecls,
 294                 DeclarationShim.getDeclaration("-fx-fill", new ParsedValueImpl<Color,Color>(Color.RED, null), false)
 295         );
 296 
 297         final List<Selector> textSels = new ArrayList<Selector>();
 298         Collections.addAll(textSels,
 299                 Selector.createSelector(".rt-34799")
 300         );
 301 
 302         Rule txtRules = RuleShim.getRule(textSels, txtDecls);
 303         stylesheet.getRules().add(txtRules);
 304 
 305         final List<Style> expectedStyles = new ArrayList<>();
 306         for (Rule rule : stylesheet.getRules()) {
 307             for (Selector selector : rule.getSelectors()) {
 308                 for (Declaration declaration : RuleShim.getUnobservedDeclarationList(rule)) {
 309                     expectedStyles.add(
 310                             new Style(selector, declaration)
 311                     );
 312                 }
 313             }
 314         }
 315 
 316         Text text = new Text("HelloWorld");
 317         text.getStyleClass().add("rt-34799");
 318 
 319         Group group = new Group();
 320         group.getStyleClass().add("root");
 321 
 322         group.getChildren().add(text);
 323 
 324         StyleManager.getInstance().setDefaultUserAgentStylesheet(stylesheet);
 325         Scene scene = new Scene(group);
 326 
 327         group.applyCss(); // TODO: force StyleHelper to be created, remove pending RT-34812
 328 
 329         int nExpected = expectedStyles.size();
 330         assert(nExpected > 0);
 331 
 332         for(CssMetaData cssMetaData : text.getCssMetaData()) {
 333             List<Style> styles = NodeHelper.getMatchingStyles(cssMetaData, text);
 334             if (styles != null && !styles.isEmpty()) {
 335                 assertTrue(expectedStyles.containsAll(styles));
 336                 assertTrue(styles.containsAll(expectedStyles));
 337                 nExpected -= 1;
 338             }
 339         }
 340 
 341         assertEquals(nExpected, 0);
 342 
 343     }
 344 
 345 }