1 /* 2 * Copyright (c) 2010, 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 javafx.scene.control; 27 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.List; 31 32 import javafx.beans.property.ObjectProperty; 33 import javafx.beans.value.WritableValue; 34 import javafx.geometry.HPos; 35 import javafx.geometry.Orientation; 36 import javafx.geometry.VPos; 37 import javafx.css.StyleableObjectProperty; 38 import javafx.css.CssMetaData; 39 import javafx.css.PseudoClass; 40 41 import javafx.css.converter.EnumConverter; 42 import javafx.scene.control.skin.SeparatorSkin; 43 44 import javafx.css.Styleable; 45 import javafx.css.StyleableProperty; 46 47 /** 48 * A horizontal or vertical separator line. The visual appearance of this 49 * separator can be controlled via CSS. A horizontal separator occupies the 50 * full horizontal space allocated to it (less padding), and a vertical 51 * separator occupies the full vertical space allocated to it (less padding). 52 * The {@link #halignment} and {@link #valignment} properties determine how the 53 * separator is positioned in the other dimension, for example, how a horizontal 54 * separator is positioned vertically within its allocated space. 55 * <p> 56 * The separator is horizontal (i.e. <code>isVertical() == false</code>) by default. 57 * <p> 58 * The style-class for this control is "separator". 59 * <p> 60 * The separator provides two pseudo-classes "horizontal" and "vertical" which 61 * are mutually exclusive. The "horizontal" pseudo-class applies if the 62 * separator is horizontal, and the "vertical" pseudo-class applies if the 63 * separator is vertical. 64 * 65 * <p> 66 * Separator sets focusTraversable to false. 67 * </p> 68 * @since JavaFX 2.0 69 */ 70 public class Separator extends Control { 71 72 /*************************************************************************** 73 * * 74 * Constructors * 75 * * 76 **************************************************************************/ 77 78 /** 79 * Creates a new horizontal separator with halignment and valignment set to their 80 * respective CENTER values. 81 */ 82 public Separator() { 83 this(Orientation.HORIZONTAL); 84 } 85 86 /** 87 * Creates a new separator with halignment and valignment set to their respective CENTER 88 * values. The direction of the separator is specified by the vertical property. 89 * 90 * @param orientation Specifies whether the Separator instance is initially 91 * vertical or horizontal. 92 */ 93 public Separator(Orientation orientation) { 94 95 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 96 97 // focusTraversable is styleable through css. Calling setFocusTraversable 98 // makes it look to css like the user set the value and css will not 99 // override. Initializing focusTraversable by calling applyStyle with null 100 // StyleOrigin ensures that css will be able to override the value. 101 ((StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty()).applyStyle(null, Boolean.FALSE); 102 103 // initialize pseudo-class state 104 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, orientation != Orientation.VERTICAL); 105 pseudoClassStateChanged(VERTICAL_PSEUDOCLASS_STATE, orientation == Orientation.VERTICAL); 106 107 ((StyleableProperty<Orientation>)(WritableValue<Orientation>)orientationProperty()) 108 .applyStyle(null, orientation != null ? orientation : Orientation.HORIZONTAL); 109 } 110 111 /*************************************************************************** 112 * * 113 * Properties * 114 * * 115 **************************************************************************/ 116 117 /** 118 * The orientation of the {@code Separator} can either be horizontal 119 * or vertical. 120 */ 121 private ObjectProperty<Orientation> orientation = 122 new StyleableObjectProperty<Orientation>(Orientation.HORIZONTAL) { 123 124 @Override protected void invalidated() { 125 final boolean isVertical = (get() == Orientation.VERTICAL); 126 pseudoClassStateChanged(VERTICAL_PSEUDOCLASS_STATE, isVertical); 127 pseudoClassStateChanged(HORIZONTAL_PSEUDOCLASS_STATE, !isVertical); 128 } 129 130 @Override 131 public CssMetaData<Separator,Orientation> getCssMetaData() { 132 return StyleableProperties.ORIENTATION; 133 } 134 135 @Override 136 public Object getBean() { 137 return Separator.this; 138 } 139 140 @Override 141 public String getName() { 142 return "orientation"; 143 } 144 }; 145 public final void setOrientation(Orientation value) { orientation.set(value); } 146 public final Orientation getOrientation() { return orientation.get(); } 147 public final ObjectProperty<Orientation> orientationProperty() { return orientation; } 148 149 /** 150 * For vertical separators, specifies the horizontal position of the 151 * separator line within the separator control's space. Ignored for 152 * horizontal separators. 153 */ 154 private ObjectProperty<HPos> halignment; 155 156 public final void setHalignment(HPos value) { 157 halignmentProperty().set(value); 158 } 159 160 public final HPos getHalignment() { 161 return halignment == null ? HPos.CENTER : halignment.get(); 162 } 163 164 public final ObjectProperty<HPos> halignmentProperty() { 165 if (halignment == null) { 166 halignment = new StyleableObjectProperty<HPos>(HPos.CENTER) { 167 168 @Override 169 public Object getBean() { 170 return Separator.this; 171 } 172 173 @Override 174 public String getName() { 175 return "halignment"; 176 } 177 178 @Override 179 public CssMetaData<Separator,HPos> getCssMetaData() { 180 return StyleableProperties.HALIGNMENT; 181 } 182 183 }; 184 } 185 return halignment; 186 } 187 188 /** 189 * For horizontal separators, specifies the vertical alignment of the 190 * separator line within the separator control's space. Ignored for 191 * vertical separators. 192 */ 193 private ObjectProperty<VPos> valignment; 194 public final void setValignment(VPos value) { 195 valignmentProperty().set(value); 196 } 197 198 public final VPos getValignment() { 199 return valignment == null ? VPos.CENTER : valignment.get(); 200 } 201 202 public final ObjectProperty<VPos> valignmentProperty() { 203 if (valignment == null) { 204 valignment = new StyleableObjectProperty<VPos>(VPos.CENTER) { 205 206 @Override 207 public Object getBean() { 208 return Separator.this; 209 } 210 211 @Override 212 public String getName() { 213 return "valignment"; 214 } 215 216 @Override 217 public CssMetaData<Separator,VPos> getCssMetaData() { 218 return StyleableProperties.VALIGNMENT; 219 } 220 221 }; 222 } 223 return valignment; 224 } 225 226 /** {@inheritDoc} */ 227 @Override protected Skin<?> createDefaultSkin() { 228 return new SeparatorSkin(this); 229 } 230 231 /*************************************************************************** 232 * * 233 * Stylesheet Handling * 234 * * 235 **************************************************************************/ 236 237 private static final String DEFAULT_STYLE_CLASS = "separator"; 238 239 private static class StyleableProperties { 240 private static final CssMetaData<Separator,Orientation> ORIENTATION = 241 new CssMetaData<Separator,Orientation>("-fx-orientation", 242 new EnumConverter<Orientation>(Orientation.class), 243 Orientation.HORIZONTAL) { 244 245 @Override 246 public Orientation getInitialValue(Separator node) { 247 // A vertical Separator should remain vertical 248 return node.getOrientation(); 249 } 250 251 @Override 252 public boolean isSettable(Separator n) { 253 return n.orientation == null || !n.orientation.isBound(); 254 } 255 256 @Override 257 public StyleableProperty<Orientation> getStyleableProperty(Separator n) { 258 return (StyleableProperty<Orientation>)(WritableValue<Orientation>)n.orientationProperty(); 259 } 260 }; 261 262 private static final CssMetaData<Separator,HPos> HALIGNMENT = 263 new CssMetaData<Separator,HPos>("-fx-halignment", 264 new EnumConverter<HPos>(HPos.class), 265 HPos.CENTER) { 266 267 @Override 268 public boolean isSettable(Separator n) { 269 return n.halignment == null || !n.halignment.isBound(); 270 } 271 272 @Override 273 public StyleableProperty<HPos> getStyleableProperty(Separator n) { 274 return (StyleableProperty<HPos>)(WritableValue<HPos>)n.halignmentProperty(); 275 } 276 }; 277 278 private static final CssMetaData<Separator,VPos> VALIGNMENT = 279 new CssMetaData<Separator,VPos>("-fx-valignment", 280 new EnumConverter<VPos>(VPos.class), 281 VPos.CENTER){ 282 283 @Override 284 public boolean isSettable(Separator n) { 285 return n.valignment == null || !n.valignment.isBound(); 286 } 287 288 @Override 289 public StyleableProperty<VPos> getStyleableProperty(Separator n) { 290 return (StyleableProperty<VPos>)(WritableValue<VPos>)n.valignmentProperty(); 291 } 292 }; 293 294 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; 295 static { 296 final List<CssMetaData<? extends Styleable, ?>> styleables = 297 new ArrayList<CssMetaData<? extends Styleable, ?>>(Control.getClassCssMetaData()); 298 styleables.add(ORIENTATION); 299 styleables.add(HALIGNMENT); 300 styleables.add(VALIGNMENT); 301 STYLEABLES = Collections.unmodifiableList(styleables); 302 } 303 } 304 305 /** 306 * @return The CssMetaData associated with this class, which may include the 307 * CssMetaData of its superclasses. 308 * @since JavaFX 8.0 309 */ 310 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { 311 return Separator.StyleableProperties.STYLEABLES; 312 } 313 314 /** 315 * {@inheritDoc} 316 * @since JavaFX 8.0 317 */ 318 @Override protected List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { 319 return getClassCssMetaData(); 320 } 321 322 private static final PseudoClass VERTICAL_PSEUDOCLASS_STATE = PseudoClass.getPseudoClass("vertical"); 323 private static final PseudoClass HORIZONTAL_PSEUDOCLASS_STATE = PseudoClass.getPseudoClass("horizontal"); 324 325 /** 326 * Returns the initial focus traversable state of this control, for use 327 * by the JavaFX CSS engine to correctly set its initial value. This method 328 * is overridden as by default UI controls have focus traversable set to true, 329 * but that is not appropriate for this control. 330 * 331 * @since 9 332 */ 333 @Override protected Boolean getInitialFocusTraversable() { 334 return Boolean.FALSE; 335 } 336 337 }