< prev index next >

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

Print this page




  33 import java.util.List;
  34 
  35 import com.sun.javafx.scene.control.ControlAcceleratorSupport;
  36 import javafx.application.Application;
  37 import javafx.beans.property.ObjectProperty;
  38 import javafx.beans.property.ObjectPropertyBase;
  39 import javafx.beans.property.SimpleObjectProperty;
  40 import javafx.beans.property.StringProperty;
  41 import javafx.beans.value.WritableValue;
  42 import javafx.collections.ObservableList;
  43 import javafx.css.CssParser;
  44 import javafx.event.EventHandler;
  45 import javafx.scene.AccessibleAction;
  46 import javafx.scene.AccessibleAttribute;
  47 import javafx.scene.Node;
  48 import javafx.scene.input.ContextMenuEvent;
  49 import javafx.scene.layout.Region;
  50 import com.sun.javafx.application.PlatformImpl;
  51 import javafx.css.CssMetaData;
  52 import com.sun.javafx.css.StyleManager;


  53 import javafx.css.StyleableObjectProperty;
  54 import javafx.css.StyleableStringProperty;
  55 import javafx.css.converter.StringConverter;
  56 import com.sun.javafx.scene.control.Logging;
  57 import javafx.css.Styleable;
  58 import javafx.css.StyleableProperty;
  59 import sun.util.logging.PlatformLogger;
  60 import sun.util.logging.PlatformLogger.Level;
  61 
  62 
  63 /**
  64  * Base class for all user interface controls. A "Control" is a node in the
  65  * scene graph which can be manipulated by the user. Controls provide
  66  * additional variables and behaviors beyond those of Node to support
  67  * common user interactions in a manner which is consistent and predictable
  68  * for the user.
  69  * <p>
  70  * Additionally, controls support explicit skinning to make it easy to
  71  * leverage the functionality of a control while customizing its appearance.
  72  * <p>
  73  * See specific Control subclasses for information on how to use individual
  74  * types of controls.
  75  * <p> Most controls have their focusTraversable property set to true by default, however
  76  * read-only controls such as {@link Label} and {@link ProgressIndicator}, and some
  77  * controls that are containers {@link ScrollPane} and {@link ToolBar} do not.
  78  * Consult individual control documentation for details.
  79  * @since JavaFX 2.0
  80  */
  81 public abstract class Control extends Region implements Skinnable {
  82 
  83     static {







  84         // Ensures that the default application user agent stylesheet is loaded
  85         if (Application.getUserAgentStylesheet() == null) {
  86             PlatformImpl.setDefaultPlatformUserAgentStylesheet();
  87         }
  88     }
  89 
  90     /**
  91      * Utility for loading a class in a manner that will work with multiple
  92      * class loaders, as is typically found in OSGI modular applications.
  93      * In particular, this method will attempt to just load the class
  94      * identified by className. If that fails, it attempts to load the
  95      * class using the current thread's context class loader. If that fails,
  96      * it attempts to use the class loader of the supplied "instance", and
  97      * if it still fails it walks up the class hierarchy of the instance
  98      * and attempts to use the class loader of each class in the super-type
  99      * hierarchy.
 100      *
 101      * @param className The name of the class we want to load
 102      * @param instance An optional instance used to help find the class to load
 103      * @return The class. Cannot return null


 274                 // skin will have already configured all the children
 275                 // by the time setSkin has been called. This is because
 276                 // our Skin interface was lacking an initialize method (doh!)
 277                 // and so the Skin constructor is where it adds listeners
 278                 // and so forth. For SkinBase implementations, the
 279                 // constructor is also where it will take ownership of
 280                 // the children.
 281             } else {
 282                 final Node n = getSkinNode();
 283                 if (n != null) {
 284                     getChildren().setAll(n);
 285                 } else {
 286                     getChildren().clear();
 287                 }
 288             }
 289 
 290             // clear out the styleable properties so that the list is rebuilt
 291             // next time they are requested.
 292             styleableProperties = null;
 293 
 294             // calling impl_reapplyCSS() as the styleable properties may now
 295             // be different, as we will now be able to return styleable properties
 296             // belonging to the skin. If impl_reapplyCSS() is not called, the
 297             // getCssMetaData() method is never called, so the
 298             // skin properties are never exposed.
 299             impl_reapplyCSS();
 300 
 301             // DEBUG: Log that we've changed the skin
 302             final PlatformLogger logger = Logging.getControlsLogger();
 303             if (logger.isLoggable(Level.FINEST)) {
 304                 logger.finest("Stored skin[" + getValue() + "] on " + this);
 305             }
 306         }
 307 
 308         // This method should be CssMetaData<Control,Skin> getCssMetaData(),
 309         // but SKIN is CssMetaData<Control,String>. This does not matter to
 310         // the CSS code which doesn't care about the actual type. Hence,
 311         // we'll suppress the warnings
 312         @Override @SuppressWarnings({"unchecked", "rawtype"})
 313         public CssMetaData getCssMetaData() {
 314             return StyleableProperties.SKIN;
 315         }
 316 
 317         @Override
 318         public Object getBean() {
 319             return Control.this;


 389                 // if a context menu is set, we need to install any accelerators
 390                 // belonging to its menu items ASAP into the scene that this
 391                 // Control is in (if the control is not in a Scene, we will need
 392                 // to wait until it is and then do it).
 393                 ControlAcceleratorSupport.addAcceleratorsIntoScene(ctx.getItems(), Control.this);
 394             }
 395         }
 396     };
 397     public final ObjectProperty<ContextMenu> contextMenuProperty() { return contextMenu; }
 398     public final void setContextMenu(ContextMenu value) { contextMenu.setValue(value); }
 399     public final ContextMenu getContextMenu() { return contextMenu == null ? null : contextMenu.getValue(); }
 400 
 401 
 402 
 403     /***************************************************************************
 404      *                                                                         *
 405      * Constructors                                                            *
 406      *                                                                         *
 407      **************************************************************************/
 408 




 409     /**
 410      *  Create a new Control.
 411      */
 412     protected Control() {
 413         // focusTraversable is styleable through css. Calling setFocusTraversable
 414         // makes it look to css like the user set the value and css will not
 415         // override. Initializing focusTraversable by calling applyStyle
 416         // with null for StyleOrigin ensures that css will be able to override
 417         // the value.
 418         final StyleableProperty<Boolean> prop = (StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty();
 419         prop.applyStyle(null, Boolean.TRUE);
 420 
 421         // we add a listener for menu request events to show the context menu
 422         // that may be set on the Control
 423         this.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);
 424 
 425         // TODO re-enable when InputMap moves back to Node / Control
 426 //        // Most controls need an input map, so we set this to be non-null in
 427 //        // Control to save people from running into NPEs.
 428 //        setInputMap(new InputMap(this));


 845                 CssMetaData<? extends Styleable, ?> metaData = list.get(n);
 846                 if (metaData == null) continue;
 847 
 848                 map.put(metaData.getProperty(), metaData);
 849             }
 850 
 851             styleableProperties = new ArrayList<CssMetaData<? extends Styleable, ?>>();
 852             styleableProperties.addAll(map.values());
 853         }
 854         return styleableProperties;
 855     }
 856 
 857     /**
 858      * @return unmodifiable list of the controls css styleable properties
 859      * @since JavaFX 8.0
 860      */
 861     protected List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
 862         return getClassCssMetaData();
 863     }
 864 
 865     /**
 866      * @treatAsPrivate implementation detail
 867      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 868      */
 869     @Deprecated
 870     @Override protected void impl_processCSS() {
 871 
 872         super.impl_processCSS();
 873 
 874         if (getSkin() == null) {
 875             // try to create default skin
 876             final Skin<?> defaultSkin = createDefaultSkin();
 877             if (defaultSkin != null) {
 878                 skinProperty().set(defaultSkin);
 879                 super.impl_processCSS();
 880             } else {
 881                 final String msg = "The -fx-skin property has not been defined in CSS for " + this +
 882                                    " and createDefaultSkin() returned null.";
 883                 final List<CssParser.ParseError> errors = StyleManager.getErrors();
 884                 if (errors != null) {
 885                     CssParser.ParseError error = new CssParser.ParseError(msg);
 886                     errors.add(error); // RT-19884
 887                 }
 888                 Logging.getControlsLogger().severe(msg);
 889             }
 890         }
 891     }
 892 
 893     /**
 894      * Returns the initial focus traversable state of this control, for use
 895      * by the JavaFX CSS engine to correctly set its initial value. By default all
 896      * UI controls are focus traversable, so this method is overridden in Control
 897      * to set the initial traversable state to true.
 898      *
 899      * @since 9




  33 import java.util.List;
  34 
  35 import com.sun.javafx.scene.control.ControlAcceleratorSupport;
  36 import javafx.application.Application;
  37 import javafx.beans.property.ObjectProperty;
  38 import javafx.beans.property.ObjectPropertyBase;
  39 import javafx.beans.property.SimpleObjectProperty;
  40 import javafx.beans.property.StringProperty;
  41 import javafx.beans.value.WritableValue;
  42 import javafx.collections.ObservableList;
  43 import javafx.css.CssParser;
  44 import javafx.event.EventHandler;
  45 import javafx.scene.AccessibleAction;
  46 import javafx.scene.AccessibleAttribute;
  47 import javafx.scene.Node;
  48 import javafx.scene.input.ContextMenuEvent;
  49 import javafx.scene.layout.Region;
  50 import com.sun.javafx.application.PlatformImpl;
  51 import javafx.css.CssMetaData;
  52 import com.sun.javafx.css.StyleManager;
  53 import com.sun.javafx.scene.NodeHelper;
  54 import com.sun.javafx.scene.control.ControlHelper;
  55 import javafx.css.StyleableObjectProperty;
  56 import javafx.css.StyleableStringProperty;
  57 import javafx.css.converter.StringConverter;
  58 import com.sun.javafx.scene.control.Logging;
  59 import javafx.css.Styleable;
  60 import javafx.css.StyleableProperty;
  61 import sun.util.logging.PlatformLogger;
  62 import sun.util.logging.PlatformLogger.Level;
  63 
  64 
  65 /**
  66  * Base class for all user interface controls. A "Control" is a node in the
  67  * scene graph which can be manipulated by the user. Controls provide
  68  * additional variables and behaviors beyond those of Node to support
  69  * common user interactions in a manner which is consistent and predictable
  70  * for the user.
  71  * <p>
  72  * Additionally, controls support explicit skinning to make it easy to
  73  * leverage the functionality of a control while customizing its appearance.
  74  * <p>
  75  * See specific Control subclasses for information on how to use individual
  76  * types of controls.
  77  * <p> Most controls have their focusTraversable property set to true by default, however
  78  * read-only controls such as {@link Label} and {@link ProgressIndicator}, and some
  79  * controls that are containers {@link ScrollPane} and {@link ToolBar} do not.
  80  * Consult individual control documentation for details.
  81  * @since JavaFX 2.0
  82  */
  83 public abstract class Control extends Region implements Skinnable {
  84 
  85     static {
  86         ControlHelper.setControlAccessor(new ControlHelper.ControlAccessor() {
  87             @Override
  88             public void doProcessCSS(Node node) {
  89                 ((Control) node).doProcessCSS();
  90             }
  91         });
  92 
  93         // Ensures that the default application user agent stylesheet is loaded
  94         if (Application.getUserAgentStylesheet() == null) {
  95             PlatformImpl.setDefaultPlatformUserAgentStylesheet();
  96         }
  97     }
  98 
  99     /**
 100      * Utility for loading a class in a manner that will work with multiple
 101      * class loaders, as is typically found in OSGI modular applications.
 102      * In particular, this method will attempt to just load the class
 103      * identified by className. If that fails, it attempts to load the
 104      * class using the current thread's context class loader. If that fails,
 105      * it attempts to use the class loader of the supplied "instance", and
 106      * if it still fails it walks up the class hierarchy of the instance
 107      * and attempts to use the class loader of each class in the super-type
 108      * hierarchy.
 109      *
 110      * @param className The name of the class we want to load
 111      * @param instance An optional instance used to help find the class to load
 112      * @return The class. Cannot return null


 283                 // skin will have already configured all the children
 284                 // by the time setSkin has been called. This is because
 285                 // our Skin interface was lacking an initialize method (doh!)
 286                 // and so the Skin constructor is where it adds listeners
 287                 // and so forth. For SkinBase implementations, the
 288                 // constructor is also where it will take ownership of
 289                 // the children.
 290             } else {
 291                 final Node n = getSkinNode();
 292                 if (n != null) {
 293                     getChildren().setAll(n);
 294                 } else {
 295                     getChildren().clear();
 296                 }
 297             }
 298 
 299             // clear out the styleable properties so that the list is rebuilt
 300             // next time they are requested.
 301             styleableProperties = null;
 302 
 303             // calling NodeHelper.reapplyCSS() as the styleable properties may now
 304             // be different, as we will now be able to return styleable properties
 305             // belonging to the skin. If NodeHelper.reapplyCSS() is not called, the
 306             // getCssMetaData() method is never called, so the
 307             // skin properties are never exposed.
 308             NodeHelper.reapplyCSS(Control.this);
 309 
 310             // DEBUG: Log that we've changed the skin
 311             final PlatformLogger logger = Logging.getControlsLogger();
 312             if (logger.isLoggable(Level.FINEST)) {
 313                 logger.finest("Stored skin[" + getValue() + "] on " + this);
 314             }
 315         }
 316 
 317         // This method should be CssMetaData<Control,Skin> getCssMetaData(),
 318         // but SKIN is CssMetaData<Control,String>. This does not matter to
 319         // the CSS code which doesn't care about the actual type. Hence,
 320         // we'll suppress the warnings
 321         @Override @SuppressWarnings({"unchecked", "rawtype"})
 322         public CssMetaData getCssMetaData() {
 323             return StyleableProperties.SKIN;
 324         }
 325 
 326         @Override
 327         public Object getBean() {
 328             return Control.this;


 398                 // if a context menu is set, we need to install any accelerators
 399                 // belonging to its menu items ASAP into the scene that this
 400                 // Control is in (if the control is not in a Scene, we will need
 401                 // to wait until it is and then do it).
 402                 ControlAcceleratorSupport.addAcceleratorsIntoScene(ctx.getItems(), Control.this);
 403             }
 404         }
 405     };
 406     public final ObjectProperty<ContextMenu> contextMenuProperty() { return contextMenu; }
 407     public final void setContextMenu(ContextMenu value) { contextMenu.setValue(value); }
 408     public final ContextMenu getContextMenu() { return contextMenu == null ? null : contextMenu.getValue(); }
 409 
 410 
 411 
 412     /***************************************************************************
 413      *                                                                         *
 414      * Constructors                                                            *
 415      *                                                                         *
 416      **************************************************************************/
 417 
 418     {
 419         // To initialize the class helper at the begining each constructor of this class
 420         ControlHelper.initHelper(this);
 421     }
 422     /**
 423      *  Create a new Control.
 424      */
 425     protected Control() {
 426         // focusTraversable is styleable through css. Calling setFocusTraversable
 427         // makes it look to css like the user set the value and css will not
 428         // override. Initializing focusTraversable by calling applyStyle
 429         // with null for StyleOrigin ensures that css will be able to override
 430         // the value.
 431         final StyleableProperty<Boolean> prop = (StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty();
 432         prop.applyStyle(null, Boolean.TRUE);
 433 
 434         // we add a listener for menu request events to show the context menu
 435         // that may be set on the Control
 436         this.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);
 437 
 438         // TODO re-enable when InputMap moves back to Node / Control
 439 //        // Most controls need an input map, so we set this to be non-null in
 440 //        // Control to save people from running into NPEs.
 441 //        setInputMap(new InputMap(this));


 858                 CssMetaData<? extends Styleable, ?> metaData = list.get(n);
 859                 if (metaData == null) continue;
 860 
 861                 map.put(metaData.getProperty(), metaData);
 862             }
 863 
 864             styleableProperties = new ArrayList<CssMetaData<? extends Styleable, ?>>();
 865             styleableProperties.addAll(map.values());
 866         }
 867         return styleableProperties;
 868     }
 869 
 870     /**
 871      * @return unmodifiable list of the controls css styleable properties
 872      * @since JavaFX 8.0
 873      */
 874     protected List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
 875         return getClassCssMetaData();
 876     }
 877 
 878     /*
 879      * Note: This method MUST only be called via its accessor method.

 880      */
 881     private void doProcessCSS() {

 882 
 883         ControlHelper.superProcessCSS(this);
 884 
 885         if (getSkin() == null) {
 886             // try to create default skin
 887             final Skin<?> defaultSkin = createDefaultSkin();
 888             if (defaultSkin != null) {
 889                 skinProperty().set(defaultSkin);
 890                 ControlHelper.superProcessCSS(this);
 891             } else {
 892                 final String msg = "The -fx-skin property has not been defined in CSS for " + this +
 893                                    " and createDefaultSkin() returned null.";
 894                 final List<CssParser.ParseError> errors = StyleManager.getErrors();
 895                 if (errors != null) {
 896                     CssParser.ParseError error = new CssParser.ParseError(msg);
 897                     errors.add(error); // RT-19884
 898                 }
 899                 Logging.getControlsLogger().severe(msg);
 900             }
 901         }
 902     }
 903 
 904     /**
 905      * Returns the initial focus traversable state of this control, for use
 906      * by the JavaFX CSS engine to correctly set its initial value. By default all
 907      * UI controls are focus traversable, so this method is overridden in Control
 908      * to set the initial traversable state to true.
 909      *
 910      * @since 9


< prev index next >