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 |