1 /* 2 * Copyright (c) 2010, 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 javafx.scene.control.skin; 27 28 import javafx.geometry.Orientation; 29 import javafx.scene.Node; 30 import javafx.scene.control.Accordion; 31 import javafx.scene.control.Control; 32 import javafx.scene.control.Separator; 33 import javafx.scene.control.SkinBase; 34 import javafx.scene.layout.Region; 35 36 import java.util.Collections; 37 38 /** 39 * Default skin implementation for the {@link Separator} control. 40 * 41 * @see Separator 42 * @since 9 43 */ 44 public class SeparatorSkin extends SkinBase<Separator> { 45 46 /*************************************************************************** 47 * * 48 * Static fields * 49 * * 50 **************************************************************************/ 51 52 /** 53 * Separator's have no intrinsic length, so we need to hard code some sort 54 * of default preferred size when a separator is not otherwise being resized. 55 * This is the default length to use (height when vertical, width when horizontal) 56 * for computing the preferred width/height. 57 */ 58 private static final double DEFAULT_LENGTH = 10; 59 60 61 62 /*************************************************************************** 63 * * 64 * Private fields * 65 * * 66 **************************************************************************/ 67 68 /** 69 * The region to use for rendering the line. The line is specified via 70 * CSS. By default we use a single stroke to render the line, but the 71 * programmer could use images or whatnot from CSS instead. 72 */ 73 private final Region line; 74 75 76 77 /*************************************************************************** 78 * * 79 * Constructors * 80 * * 81 **************************************************************************/ 82 83 /** 84 * Creates a new SeparatorSkin instance, installing the necessary child 85 * nodes into the Control {@link Control#getChildren() children} list, as 86 * well as the necessary {@link Node#getInputMap() input mappings} for 87 * handling key, mouse, etc events. 88 * 89 * @param control The control that this skin should be installed onto. 90 */ 91 public SeparatorSkin(Separator control) { 92 // There is no behavior for the separator, so we just create a 93 // dummy behavior base instead, since SkinBase will complain 94 // about it being null. 95 super(control); 96 97 line = new Region(); 98 line.getStyleClass().setAll("line"); 99 100 getChildren().add(line); 101 registerChangeListener(control.orientationProperty(), e -> getSkinnable().requestLayout()); 102 registerChangeListener(control.halignmentProperty(), e -> getSkinnable().requestLayout()); 103 registerChangeListener(control.valignmentProperty(), e -> getSkinnable().requestLayout()); 104 } 105 106 107 108 /*************************************************************************** 109 * * 110 * Public API * 111 * * 112 **************************************************************************/ 113 114 /** 115 * We only need to deal with the single "line" child region. The important 116 * thing here is that we want a horizontal separator to have a line which is 117 * as wide as the separator (less the left/right padding), but as thin as 118 * it can be (based on its own pref height). The same idea for a vertical 119 * separator. It should be as tall as the separator (less the top and 120 * bottom padding) but as thin as can be (the pref width of the line). 121 * <p> 122 * Then position the line within the separator such that the alignment 123 * properties are honored. 124 */ 125 @Override protected void layoutChildren(final double x, final double y, 126 final double w, final double h) { 127 final Separator sep = getSkinnable(); 128 129 if (sep.getOrientation() == Orientation.HORIZONTAL) { 130 // Resize to the content width, and the pref height of the line. 131 line.resize(w, line.prefHeight(-1)); 132 } else { 133 // Resize to the pref width of the line and the content height. 134 line.resize(line.prefWidth(-1), h); 135 } 136 137 // Now that the line has been sized, simply position it 138 positionInArea(line, x, y, w, h, 0, sep.getHalignment(), sep.getValignment()); 139 } 140 141 /** {@inheritDoc} */ 142 @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { 143 return computePrefWidth(height, topInset, rightInset, bottomInset, leftInset); 144 } 145 146 /** {@inheritDoc} */ 147 @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { 148 return computePrefHeight(width, topInset, rightInset, bottomInset, leftInset); 149 } 150 151 /** {@inheritDoc} */ 152 @Override protected double computePrefWidth(double h, double topInset, double rightInset, double bottomInset, double leftInset) { 153 final Separator sep = getSkinnable(); 154 double w = sep.getOrientation() == Orientation.VERTICAL ? line.prefWidth(-1) : DEFAULT_LENGTH; 155 return w + leftInset + rightInset; 156 } 157 158 /** {@inheritDoc} */ 159 @Override protected double computePrefHeight(double w, double topInset, double rightInset, double bottomInset, double leftInset) { 160 final Separator sep = getSkinnable(); 161 double h = sep.getOrientation() == Orientation.VERTICAL ? DEFAULT_LENGTH : line.prefHeight(-1); 162 return h + topInset + bottomInset; 163 } 164 165 /** {@inheritDoc} */ 166 @Override protected double computeMaxWidth(double h, double topInset, double rightInset, double bottomInset, double leftInset) { 167 final Separator sep = getSkinnable(); 168 return sep.getOrientation() == Orientation.VERTICAL ? sep.prefWidth(h) : Double.MAX_VALUE; 169 } 170 171 /** {@inheritDoc} */ 172 @Override protected double computeMaxHeight(double w, double topInset, double rightInset, double bottomInset, double leftInset) { 173 final Separator sep = getSkinnable(); 174 return sep.getOrientation() == Orientation.VERTICAL ? Double.MAX_VALUE : sep.prefHeight(w); 175 } 176 }