modules/controls/src/main/java/javafx/scene/control/SkinBase.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization
   1 /*
   2  * Copyright (c) 2012, 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;
  27 





  28 import javafx.css.CssMetaData;
  29 import javafx.css.PseudoClass;
  30 import java.util.Collections;
  31 import java.util.List;


  32 import javafx.collections.ObservableList;
  33 import javafx.css.Styleable;
  34 import javafx.event.EventHandler;
  35 import javafx.geometry.HPos;
  36 import javafx.geometry.Insets;
  37 import javafx.geometry.VPos;
  38 import javafx.scene.AccessibleAction;
  39 import javafx.scene.AccessibleAttribute;
  40 import javafx.scene.Node;
  41 import javafx.scene.input.MouseEvent;
  42 import javafx.scene.layout.Region;
  43 
  44 /**
  45  * Base implementation class for defining the visual representation of user
  46  * interface controls by defining a scene graph of nodes to represent the
  47  * {@link Skin skin}.
  48  * A user interface control is abstracted behind the {@link Skinnable} interface.
  49  *
  50  * @since JavaFX 8.0
  51  */


  53     
  54     /***************************************************************************
  55      *                                                                         *
  56      * Private fields                                                          *
  57      *                                                                         *
  58      **************************************************************************/
  59 
  60     /**
  61      * The {@code Control} that is referencing this Skin. There is a
  62      * one-to-one relationship between a {@code Skin} and a {@code Control}.
  63      * When a {@code Skin} is set on a {@code Control}, this variable is
  64      * automatically updated.
  65      */
  66     private C control;
  67     
  68     /**
  69      * A local field that directly refers to the children list inside the Control.
  70      */
  71     private ObservableList<Node> children;
  72     







  73     
  74     
  75     /***************************************************************************
  76      *                                                                         *
  77      * Event Handlers / Listeners                                              *
  78      *                                                                         *
  79      **************************************************************************/
  80     
  81     /**
  82      * Mouse handler used for consuming all mouse events (preventing them
  83      * from bubbling up to parent)
  84      */
  85     private static final EventHandler<MouseEvent> mouseEventConsumer = event -> {
  86         /*
  87         ** we used to consume mouse wheel rotations here,
  88         ** be we've switched to ScrollEvents, and only consume those which we use.
  89         ** See RT-13995 & RT-14480
  90         */
  91         event.consume();
  92     };


 122     /***************************************************************************
 123      *                                                                         *
 124      * Public API (from Skin)                                                  *
 125      *                                                                         *
 126      **************************************************************************/    
 127 
 128     /** {@inheritDoc} */
 129     @Override public final C getSkinnable() {
 130         return control;
 131     }
 132 
 133     /** {@inheritDoc} */
 134     @Override public final Node getNode() {
 135         return control; 
 136     }
 137 
 138     /** {@inheritDoc} */
 139     @Override public void dispose() { 
 140 //        control.removeEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);
 141 





 142         this.control = null;
 143     }
 144     
 145     
 146     
 147     /***************************************************************************
 148      *                                                                         *
 149      * Public API                                                              *
 150      *                                                                         *
 151      **************************************************************************/     
 152     
 153     /**
 154      * Returns the children of the skin.
 155      */
 156     public final ObservableList<Node> getChildren() {
 157         return children;
 158     }
 159     
 160     /**
 161      * Called during the layout pass of the scenegraph. 


 166         for (int i=0, max=children.size(); i<max; i++) {
 167             Node child = children.get(i);
 168             if (child.isManaged()) {
 169                 layoutInArea(child, contentX, contentY, contentWidth, contentHeight, -1, HPos.CENTER, VPos.CENTER);
 170             }
 171         }
 172     }
 173     
 174     /**
 175      * Determines whether all mouse events should be automatically consumed.
 176      */
 177     protected final void consumeMouseEvents(boolean value) {
 178         if (value) {
 179             control.addEventHandler(MouseEvent.ANY, mouseEventConsumer);
 180         } else {
 181             control.removeEventHandler(MouseEvent.ANY, mouseEventConsumer);
 182         }
 183     }
 184     
 185     













 186     
 187     /***************************************************************************
 188      *                                                                         *
 189      * Public Layout-related API                                               *
 190      *                                                                         *
 191      **************************************************************************/
 192     
 193     /**
 194      * Computes the minimum allowable width of the Skin, based on the provided
 195      * height.
 196      *
 197      * @param height The height of the Skin, in case this value might dictate
 198      *      the minimum width.
 199      * @param topInset the pixel snapped top inset
 200      * @param rightInset the pixel snapped right inset
 201      * @param bottomInset the pixel snapped bottom inset
 202      * @param leftInset  the pixel snapped left inset
 203      * @return A double representing the minimum width of this Skin.
 204      */
 205     protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {


 704                 valignment, control.isSnapToPixel());
 705     }
 706     
 707     
 708     
 709     /***************************************************************************
 710      *                                                                         *
 711      * Private Implementation                                                  *
 712      *                                                                         *
 713      **************************************************************************/     
 714     
 715     
 716     
 717      /**************************************************************************
 718       *                                                                        *
 719       * Specialization of CSS handling code                                    *
 720       *                                                                        *
 721      **************************************************************************/
 722 
 723     private static class StyleableProperties {
 724 
 725         private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 726 
 727         static {
 728             STYLEABLES = Collections.unmodifiableList(Control.getClassCssMetaData());
 729         }
 730     }
 731 
 732     /** 
 733      * @return The CssMetaData associated with this class, which may include the
 734      * CssMetaData of its super classes.
 735      */    public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {

 736         return SkinBase.StyleableProperties.STYLEABLES;
 737     }
 738 
 739     /**
 740      * This method should delegate to {@link Node#getClassCssMetaData()} so that
 741      * a Node's CssMetaData can be accessed without the need for reflection.
 742      * @return The CssMetaData associated with this node, which may include the
 743      * CssMetaData of its super classes.
 744      */
 745     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 746         return getClassCssMetaData();
 747     }
 748     
 749     /** @see Node#pseudoClassStateChanged */





























 750     public final void pseudoClassStateChanged(PseudoClass pseudoClass, boolean active) {
 751         Control ctl = getSkinnable();
 752         if (ctl != null) {
 753             ctl.pseudoClassStateChanged(pseudoClass, active);
 754         }
 755     }
 756 
 757 
 758     /***************************************************************************
 759      *                                                                         *
 760      * Accessibility handling                                                  *
 761      *                                                                         *
 762      **************************************************************************/
 763 
 764     /** @see Node#queryAccessibleAttribute */


















 765     protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
 766         return null;
 767     }
 768 
 769     /** @see Node#executeAccessibleAction */

















 770     protected void executeAccessibleAction(AccessibleAction action, Object... parameters) {
 771     }
 772 
 773     /***************************************************************************
 774      *                                                                         *
 775      * Testing-only API                                                        *
 776      *                                                                         *
 777      **************************************************************************/
 778 
 779 }
   1 /*
   2  * Copyright (c) 2012, 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 javafx.scene.control;
  27 
  28 import com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler;
  29 import com.sun.javafx.scene.control.behavior.BehaviorBase;
  30 import javafx.application.ConditionalFeature;
  31 import javafx.application.Platform;
  32 import javafx.beans.value.ObservableValue;
  33 import javafx.css.CssMetaData;
  34 import javafx.css.PseudoClass;
  35 import java.util.Collections;
  36 import java.util.List;
  37 import java.util.function.Consumer;
  38 
  39 import javafx.collections.ObservableList;
  40 import javafx.css.Styleable;
  41 import javafx.event.EventHandler;
  42 import javafx.geometry.HPos;
  43 import javafx.geometry.Insets;
  44 import javafx.geometry.VPos;
  45 import javafx.scene.AccessibleAction;
  46 import javafx.scene.AccessibleAttribute;
  47 import javafx.scene.Node;
  48 import javafx.scene.input.MouseEvent;
  49 import javafx.scene.layout.Region;
  50 
  51 /**
  52  * Base implementation class for defining the visual representation of user
  53  * interface controls by defining a scene graph of nodes to represent the
  54  * {@link Skin skin}.
  55  * A user interface control is abstracted behind the {@link Skinnable} interface.
  56  *
  57  * @since JavaFX 8.0
  58  */


  60 
  61     /***************************************************************************
  62      *                                                                         *
  63      * Private fields                                                          *
  64      *                                                                         *
  65      **************************************************************************/
  66 
  67     /**
  68      * The {@code Control} that is referencing this Skin. There is a
  69      * one-to-one relationship between a {@code Skin} and a {@code Control}.
  70      * When a {@code Skin} is set on a {@code Control}, this variable is
  71      * automatically updated.
  72      */
  73     private C control;
  74     
  75     /**
  76      * A local field that directly refers to the children list inside the Control.
  77      */
  78     private ObservableList<Node> children;
  79 
  80     /**
  81      * This is part of the workaround introduced during delomboking. We probably will
  82      * want to adjust the way listeners are added rather than continuing to use this
  83      * map (although it doesn't really do much harm).
  84      */
  85     private LambdaMultiplePropertyChangeListenerHandler lambdaChangeListenerHandler;
  86 
  87 
  88     
  89     /***************************************************************************
  90      *                                                                         *
  91      * Event Handlers / Listeners                                              *
  92      *                                                                         *
  93      **************************************************************************/
  94     
  95     /**
  96      * Mouse handler used for consuming all mouse events (preventing them
  97      * from bubbling up to parent)
  98      */
  99     private static final EventHandler<MouseEvent> mouseEventConsumer = event -> {
 100         /*
 101         ** we used to consume mouse wheel rotations here,
 102         ** be we've switched to ScrollEvents, and only consume those which we use.
 103         ** See RT-13995 & RT-14480
 104         */
 105         event.consume();
 106     };


 136     /***************************************************************************
 137      *                                                                         *
 138      * Public API (from Skin)                                                  *
 139      *                                                                         *
 140      **************************************************************************/    
 141 
 142     /** {@inheritDoc} */
 143     @Override public final C getSkinnable() {
 144         return control;
 145     }
 146 
 147     /** {@inheritDoc} */
 148     @Override public final Node getNode() {
 149         return control; 
 150     }
 151 
 152     /** {@inheritDoc} */
 153     @Override public void dispose() { 
 154 //        control.removeEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);
 155 
 156         // unhook listeners
 157         if (lambdaChangeListenerHandler != null) {
 158             lambdaChangeListenerHandler.dispose();
 159         }
 160 
 161         this.control = null;
 162     }
 163     
 164     
 165     
 166     /***************************************************************************
 167      *                                                                         *
 168      * Public API                                                              *
 169      *                                                                         *
 170      **************************************************************************/     
 171     
 172     /**
 173      * Returns the children of the skin.
 174      */
 175     public final ObservableList<Node> getChildren() {
 176         return children;
 177     }
 178     
 179     /**
 180      * Called during the layout pass of the scenegraph. 


 185         for (int i=0, max=children.size(); i<max; i++) {
 186             Node child = children.get(i);
 187             if (child.isManaged()) {
 188                 layoutInArea(child, contentX, contentY, contentWidth, contentHeight, -1, HPos.CENTER, VPos.CENTER);
 189             }
 190         }
 191     }
 192     
 193     /**
 194      * Determines whether all mouse events should be automatically consumed.
 195      */
 196     protected final void consumeMouseEvents(boolean value) {
 197         if (value) {
 198             control.addEventHandler(MouseEvent.ANY, mouseEventConsumer);
 199         } else {
 200             control.removeEventHandler(MouseEvent.ANY, mouseEventConsumer);
 201         }
 202     }
 203 
 204 
 205     /**
 206      * Subclasses can invoke this method to register that we want to listen to
 207      * property change events for the given property.
 208      */
 209     protected final void registerChangeListener(ObservableValue<?> property, Consumer<ObservableValue<?>> consumer) {
 210         if (lambdaChangeListenerHandler == null) {
 211             lambdaChangeListenerHandler = new LambdaMultiplePropertyChangeListenerHandler();
 212         }
 213         lambdaChangeListenerHandler.registerChangeListener(property, consumer);
 214     }
 215 
 216 
 217     
 218     
 219     /***************************************************************************
 220      *                                                                         *
 221      * Public Layout-related API                                               *
 222      *                                                                         *
 223      **************************************************************************/
 224     
 225     /**
 226      * Computes the minimum allowable width of the Skin, based on the provided
 227      * height.
 228      *
 229      * @param height The height of the Skin, in case this value might dictate
 230      *      the minimum width.
 231      * @param topInset the pixel snapped top inset
 232      * @param rightInset the pixel snapped right inset
 233      * @param bottomInset the pixel snapped bottom inset
 234      * @param leftInset  the pixel snapped left inset
 235      * @return A double representing the minimum width of this Skin.
 236      */
 237     protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {


 736                 valignment, control.isSnapToPixel());
 737     }
 738     
 739     
 740     
 741     /***************************************************************************
 742      *                                                                         *
 743      * Private Implementation                                                  *
 744      *                                                                         *
 745      **************************************************************************/     
 746     
 747     
 748     
 749      /**************************************************************************
 750       *                                                                        *
 751       * Specialization of CSS handling code                                    *
 752       *                                                                        *
 753      **************************************************************************/
 754 
 755     private static class StyleableProperties {

 756         private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 757 
 758         static {
 759             STYLEABLES = Collections.unmodifiableList(Control.getClassCssMetaData());
 760         }
 761     }
 762 
 763     /** 
 764      * Returns the CssMetaData associated with this class, which may include the
 765      * CssMetaData of its super classes.
 766      */
 767     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 768         return SkinBase.StyleableProperties.STYLEABLES;
 769     }
 770 
 771     /**
 772      * This method should delegate to {@link Node#getClassCssMetaData()} so that
 773      * a Node's CssMetaData can be accessed without the need for reflection.
 774      * @return The CssMetaData associated with this node, which may include the
 775      * CssMetaData of its super classes.
 776      */
 777     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 778         return getClassCssMetaData();
 779     }
 780     
 781     /**
 782      * Used to specify that a pseudo-class of this Node has changed. If the
 783      * pseudo-class is used in a CSS selector that matches this Node, CSS will
 784      * be reapplied. Typically, this method is called from the {@code invalidated}
 785      * method of a property that is used as a pseudo-class. For example:
 786      * <code><pre>
 787      *
 788      *     private static final PseudoClass MY_PSEUDO_CLASS_STATE = PseudoClass.getPseudoClass("my-state");
 789      *
 790      *     BooleanProperty myPseudoClassState = new BooleanPropertyBase(false) {
 791      *
 792      *           {@literal @}Override public void invalidated() {
 793      *                pseudoClassStateChanged(MY_PSEUDO_CLASS_STATE, get());
 794      *           }
 795      *
 796      *           {@literal @}Override public Object getBean() {
 797      *               return MyControl.this;
 798      *           }
 799      *
 800      *           {@literal @}Override public String getName() {
 801      *               return "myPseudoClassState";
 802      *           }
 803      *       };
 804      * </pre><code>
 805      *
 806      * @see Node#pseudoClassStateChanged
 807      * @param pseudoClass the pseudo-class that has changed state
 808      * @param active whether or not the state is active
 809      * @since JavaFX 8.0
 810      */
 811     public final void pseudoClassStateChanged(PseudoClass pseudoClass, boolean active) {
 812         Control ctl = getSkinnable();
 813         if (ctl != null) {
 814             ctl.pseudoClassStateChanged(pseudoClass, active);
 815         }
 816     }
 817 
 818 
 819     /***************************************************************************
 820      *                                                                         *
 821      * Accessibility handling                                                  *
 822      *                                                                         *
 823      **************************************************************************/
 824 
 825     /**
 826      * This method is called by the assistive technology to request
 827      * the value for an attribute.
 828      * <p>
 829      * This method is commonly overridden by subclasses to implement
 830      * attributes that are required for a specific role.<br>
 831      * If a particular attribute is not handled, the super class implementation
 832      * must be called.
 833      * </p>
 834      *
 835      * @param attribute the requested attribute
 836      * @param parameters optional list of parameters
 837      * @return the value for the requested attribute
 838      *
 839      * @see AccessibleAttribute
 840      * @see Node#queryAccessibleAttribute
 841      *
 842      * @since JavaFX 8u40
 843      */
 844     protected Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) {
 845         return null;
 846     }
 847 
 848     /**
 849      * This method is called by the assistive technology to request the action
 850      * indicated by the argument should be executed.
 851      * <p>
 852      * This method is commonly overridden by subclasses to implement
 853      * action that are required for a specific role.<br>
 854      * If a particular action is not handled, the super class implementation
 855      * must be called.
 856      * </p>
 857      *
 858      * @param action the action to execute
 859      * @param parameters optional list of parameters
 860      *
 861      * @see AccessibleAction
 862      * @see Node#executeAccessibleAction
 863      *
 864      * @since JavaFX 8u40
 865      */
 866     protected void executeAccessibleAction(AccessibleAction action, Object... parameters) {
 867     }
 868 
 869     /***************************************************************************
 870      *                                                                         *
 871      * Testing-only API                                                        *
 872      *                                                                         *
 873      **************************************************************************/
 874 
 875 }