modules/controls/src/main/java/javafx/scene/control/skin/SeparatorSkin.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization


   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 }


   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 }