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 com.sun.javafx.scene.control.skin; 27 28 import javafx.geometry.Orientation; 29 import javafx.scene.control.Separator; 30 import javafx.scene.layout.Region; 31 32 import java.util.Collections; 33 import com.sun.javafx.scene.control.behavior.BehaviorBase; 34 35 /** 36 * 37 */ 38 public class SeparatorSkin extends BehaviorSkinBase<Separator, BehaviorBase<Separator>> { 39 40 /** 41 * Separator's have no intrinsic length, so we need to hard code some sort 42 * of default preferred size when a separator is not otherwise being resized. 43 * This is the default length to use (height when vertical, width when horizontal) 44 * for computing the preferred width/height. 45 */ 46 private static final double DEFAULT_LENGTH = 10; 47 48 /** 49 * The region to use for rendering the line. The line is specified via 50 * CSS. By default we use a single stroke to render the line, but the 51 * programmer could use images or whatnot from CSS instead. 52 */ 53 private final Region line; 54 55 /** 56 * Create a new SeparatorSkin. Just specify the separator, thanks very much. 57 * @param separator not null 58 */ 59 public SeparatorSkin(Separator separator) { 60 // There is no behavior for the separator, so we just create a 61 // dummy behavior base instead, since SkinBase will complain 62 // about it being null. 63 super(separator, new BehaviorBase<>(separator, Collections.emptyList())); 64 65 line = new Region(); 66 line.getStyleClass().setAll("line"); 67 68 getChildren().add(line); 69 registerChangeListener(separator.orientationProperty(), "ORIENTATION"); 70 registerChangeListener(separator.halignmentProperty(), "HALIGNMENT"); 71 registerChangeListener(separator.valignmentProperty(), "VALIGNMENT"); 72 } 73 74 @Override protected void handleControlPropertyChanged(String p) { 75 super.handleControlPropertyChanged(p); 76 if ("ORIENTATION".equals(p) || "HALIGNMENT".equals(p) || "VALIGNMENT".equals(p)) { 77 getSkinnable().requestLayout(); 78 } 79 } 80 81 /** 82 * We only need to deal with the single "line" child region. The important 83 * thing here is that we want a horizontal separator to have a line which is 84 * as wide as the separator (less the left/right padding), but as thin as 85 * it can be (based on its own pref height). The same idea for a vertical 86 * separator. It should be as tall as the separator (less the top and 87 * bottom padding) but as thin as can be (the pref width of the line). 88 * <p> 89 * Then position the line within the separator such that the alignment 90 * properties are honored. 91 */ 92 @Override protected void layoutChildren(final double x, final double y, 93 final double w, final double h) { 94 final Separator sep = getSkinnable(); 95 96 if (sep.getOrientation() == Orientation.HORIZONTAL) { 97 // Resize to the content width, and the pref height of the line. 98 line.resize(w, line.prefHeight(-1)); 99 } else { 100 // Resize to the pref width of the line and the content height. 101 line.resize(line.prefWidth(-1), h); 102 } 103 104 // Now that the line has been sized, simply position it 105 positionInArea(line, x, y, w, h, 0, sep.getHalignment(), sep.getValignment()); 106 } 107 108 @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { 109 return computePrefWidth(height, topInset, rightInset, bottomInset, leftInset); 110 } 111 112 @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { 113 return computePrefHeight(width, topInset, rightInset, bottomInset, leftInset); 114 } 115 116 @Override protected double computePrefWidth(double h, double topInset, double rightInset, double bottomInset, double leftInset) { 117 final Separator sep = getSkinnable(); 118 double w = sep.getOrientation() == Orientation.VERTICAL ? line.prefWidth(-1) : DEFAULT_LENGTH; 119 return w + leftInset + rightInset; 120 } 121 122 @Override protected double computePrefHeight(double w, double topInset, double rightInset, double bottomInset, double leftInset) { 123 final Separator sep = getSkinnable(); 124 double h = sep.getOrientation() == Orientation.VERTICAL ? DEFAULT_LENGTH : line.prefHeight(-1); 125 return h + topInset + bottomInset; 126 } 127 128 @Override protected double computeMaxWidth(double h, double topInset, double rightInset, double bottomInset, double leftInset) { 129 final Separator sep = getSkinnable(); 130 return sep.getOrientation() == Orientation.VERTICAL ? sep.prefWidth(h) : Double.MAX_VALUE; 131 } 132 133 @Override protected double computeMaxHeight(double w, double topInset, double rightInset, double bottomInset, double leftInset) { 134 final Separator sep = getSkinnable(); 135 return sep.getOrientation() == Orientation.VERTICAL ? Double.MAX_VALUE : sep.prefHeight(w); 136 } 137 }