1 /* 2 * Copyright (c) 2011, 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 com.sun.javafx.scene.layout.region; 27 28 import javafx.scene.text.Font; 29 30 import com.sun.javafx.css.Size; 31 import com.sun.javafx.css.SizeUnits; 32 import com.sun.javafx.css.StyleConverterImpl; 33 import javafx.css.ParsedValue; 34 import sun.util.logging.PlatformLogger; 35 import sun.util.logging.PlatformLogger.Level; 36 37 /** 38 * Similar to Insets but with flag denoting values are proportional. 39 * If proportional is true, then the values represent fractions or percentages 40 * and are in the range 0..1, although this is not enforced. 41 */ 42 public class Margins { 43 44 // lazy, thread-safe instantiation 45 private static class Holder { 46 static Converter CONVERTER_INSTANCE = new Converter(); 47 static SequenceConverter SEQUENCE_CONVERTER_INSTANCE = new SequenceConverter(); 48 } 49 50 final double top; 51 public final double getTop() { return top; } 52 53 final double right; 54 public final double getRight() { return right; } 55 56 final double bottom; 57 public final double getBottom() { return bottom; } 58 59 final double left; 60 public final double getLeft() { return left; } 61 62 final boolean proportional; 63 public final boolean isProportional() { return proportional; } 64 65 public Margins(double top, double right, double bottom, double left, boolean proportional) { 66 this.top = top; 67 this.right = right; 68 this.bottom = bottom; 69 this.left = left; 70 this.proportional = proportional; 71 } 72 73 @Override 74 public String toString() { 75 return "top: "+top+"\nright: "+right+"\nbottom: "+bottom+"\nleft: "+left; 76 } 77 78 /** 79 * Convert a sequence of sizes to an Margins 80 */ 81 public static final class Converter extends StyleConverterImpl<ParsedValue[], Margins> { 82 83 public static Converter getInstance() { 84 return Holder.CONVERTER_INSTANCE; 85 } 86 87 private Converter() { 88 super(); 89 } 90 91 @Override 92 public Margins convert(ParsedValue<ParsedValue[], Margins> value, Font font) { 93 ParsedValue<?, Size>[] sides = value.getValue(); 94 Size topSz = (sides.length > 0) ? sides[0].convert(font) : new Size(0.0F, SizeUnits.PX); 95 Size rightSz = (sides.length > 1) ? sides[1].convert(font) : topSz; 96 Size bottomSz = (sides.length > 2) ? sides[2].convert(font) : topSz; 97 Size leftSz = (sides.length > 3) ? sides[3].convert(font) : rightSz; 98 99 // assume proportional if any units are percent 100 boolean proportional = 101 (topSz.getUnits() == SizeUnits.PERCENT) || 102 (rightSz.getUnits() == SizeUnits.PERCENT) || 103 (bottomSz.getUnits() == SizeUnits.PERCENT) || 104 (leftSz.getUnits() == SizeUnits.PERCENT); 105 106 // if any of the units is percent, then make sure they all are. 107 boolean unitsMatch = 108 !proportional || 109 ((topSz.getUnits() == SizeUnits.PERCENT) && 110 (rightSz.getUnits() == SizeUnits.PERCENT) && 111 (bottomSz.getUnits() == SizeUnits.PERCENT) && 112 (leftSz.getUnits() == SizeUnits.PERCENT)); 113 114 // unitsMatch will only be false if proportional is true and 115 // not all of the units are percent. 116 if (unitsMatch == false) { 117 final PlatformLogger LOGGER = com.sun.javafx.util.Logging.getCSSLogger(); 118 if (LOGGER.isLoggable(Level.WARNING)) { 119 final String msg = 120 new StringBuilder("units do no match: ") 121 .append(topSz.toString()) 122 .append(" ,").append(rightSz.toString()) 123 .append(" ,").append(bottomSz.toString()) 124 .append(" ,").append(leftSz.toString()) 125 .toString(); 126 LOGGER.warning(msg); 127 } 128 } 129 130 proportional = proportional && unitsMatch; 131 132 double top = topSz.pixels(font); 133 double right = rightSz.pixels(font); 134 double bottom = bottomSz.pixels(font); 135 double left = leftSz.pixels(font); 136 return new Margins(top, right, bottom, left, proportional); 137 } 138 139 @Override 140 public String toString() { 141 return "MarginsConverter"; 142 } 143 } 144 145 /** 146 * Convert a sequence of sizes to an Insets 147 */ 148 public static final class SequenceConverter extends StyleConverterImpl<ParsedValue<ParsedValue[], Margins>[], Margins[]> { 149 150 public static SequenceConverter getInstance() { 151 return Holder.SEQUENCE_CONVERTER_INSTANCE; 152 } 153 154 private SequenceConverter() { 155 super(); 156 } 157 158 @Override 159 public Margins[] convert(ParsedValue<ParsedValue<ParsedValue[], Margins>[], Margins[]> value, Font font) { 160 ParsedValue<ParsedValue[], Margins>[] layers = value.getValue(); 161 Margins[] margins = new Margins[layers.length]; 162 for (int layer = 0; layer < layers.length; layer++) { 163 margins[layer] = Converter.getInstance().convert(layers[layer], font); 164 } 165 return margins; 166 } 167 168 @Override 169 public String toString() { 170 return "MarginsSequenceConverter"; 171 } 172 } 173 174 }