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 }
|