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