32 import javafx.application.Application; 33 import javafx.beans.property.DoubleProperty; 34 import javafx.beans.property.DoublePropertyBase; 35 import javafx.beans.property.ObjectProperty; 36 import javafx.beans.property.ObjectPropertyBase; 37 import javafx.beans.property.StringProperty; 38 import javafx.beans.value.WritableValue; 39 import javafx.collections.FXCollections; 40 import javafx.collections.ObservableList; 41 import javafx.collections.ObservableSet; 42 import javafx.css.CssParser; 43 import javafx.scene.Node; 44 import javafx.scene.Parent; 45 import javafx.scene.Scene; 46 import javafx.scene.layout.Pane; 47 import javafx.stage.PopupWindow; 48 import com.sun.javafx.application.PlatformImpl; 49 import javafx.css.CssMetaData; 50 import javafx.css.PseudoClass; 51 import com.sun.javafx.css.StyleManager; 52 import javafx.css.Styleable; 53 import javafx.css.StyleableStringProperty; 54 import javafx.css.converter.StringConverter; 55 import com.sun.javafx.scene.control.Logging; 56 import com.sun.javafx.stage.PopupWindowHelper; 57 import javafx.css.StyleableProperty; 58 import javafx.stage.Window; 59 import sun.util.logging.PlatformLogger; 60 import sun.util.logging.PlatformLogger.Level; 61 62 /** 63 * An extension of PopupWindow that allows for CSS styling. 64 * @since JavaFX 2.0 65 */ 66 public class PopupControl extends PopupWindow implements Skinnable, Styleable { 67 68 /** 69 * Sentinel value which can be passed to a control's setMinWidth(), setMinHeight(), 70 * setMaxWidth() or setMaxHeight() methods to indicate that the preferred dimension 71 * should be used for that max and/or min constraint. 72 */ 73 public static final double USE_PREF_SIZE = Double.NEGATIVE_INFINITY; 74 75 /** 76 * Sentinel value which can be passed to a control's setMinWidth(), setMinHeight(), 253 } 254 255 // Get the new value, and save it off as the new oldValue 256 oldValue = getValue(); 257 258 prefWidthCache = -1; 259 prefHeightCache = -1; 260 minWidthCache = -1; 261 minHeightCache = -1; 262 maxWidthCache = -1; 263 maxHeightCache = -1; 264 skinSizeComputed = false; 265 266 final Node n = getSkinNode(); 267 if (n != null) { 268 bridge.getChildren().setAll(n); 269 } else { 270 bridge.getChildren().clear(); 271 } 272 273 // calling impl_reapplyCSS() as the styleable properties may now 274 // be different, as we will now be able to return styleable properties 275 // belonging to the skin. If impl_reapplyCSS() is not called, the 276 // getCssMetaData() method is never called, so the 277 // skin properties are never exposed. 278 bridge.impl_reapplyCSS(); 279 280 // DEBUG: Log that we've changed the skin 281 final PlatformLogger logger = Logging.getControlsLogger(); 282 if (logger.isLoggable(Level.FINEST)) { 283 logger.finest("Stored skin[" + getValue() + "] on " + this); 284 } 285 } 286 287 @Override 288 public Object getBean() { 289 return PopupControl.this; 290 } 291 292 @Override 293 public String getName() { 294 return "skin"; 295 } 296 }; 297 /** 298 * Keeps a reference to the name of the class currently acting as the skin. 1091 * @since JavaFX 8.0 1092 */ 1093 public final ObservableSet<PseudoClass> getPseudoClassStates() { 1094 return FXCollections.emptyObservableSet(); 1095 } 1096 1097 /** {@inheritDoc} */ 1098 @Override public Node getStyleableNode() { 1099 return bridge; 1100 } 1101 1102 /** 1103 * The link between the popup window and the scenegraph. 1104 * 1105 * @since JavaFX 2.1 1106 */ 1107 protected class CSSBridge extends Pane { 1108 1109 private final PopupControl popupControl = PopupControl.this; 1110 1111 /** 1112 * Requests a layout pass to be performed before the next scene is 1113 * rendered. This is batched up asynchronously to happen once per 1114 * "pulse", or frame of animation. 1115 * <p/> 1116 * If this parent is either a layout root or unmanaged, then it will be 1117 * added directly to the scene's dirty layout list, otherwise requestLayout 1118 * will be invoked on its parent. 1119 */ 1120 @Override public void requestLayout() { 1121 prefWidthCache = -1; 1122 prefHeightCache = -1; 1123 minWidthCache = -1; 1124 minHeightCache = -1; 1125 maxWidthCache = -1; 1126 maxHeightCache = -1; 1127 //skinSizeComputed = false; -- RT-33073 disabled this 1128 super.requestLayout(); 1129 } 1130 1131 /** 1132 * This method should be treated as final and should not be overridden by any subclasses of CSSBridge. 1133 */ 1134 @Override 1135 public Styleable getStyleableParent() { 1136 return PopupControl.this.getStyleableParent(); 1137 } 1138 1139 /** 1140 * @treatAsPrivate implementation detail 1141 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 1142 */ 1143 @Deprecated 1144 protected void setSkinClassName(String skinClassName) { /* no-op - retain for binary compatibility */ } 1145 1146 @Override 1147 public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() { 1148 return PopupControl.this.getCssMetaData(); 1149 } 1150 1151 /** 1152 * @treatAsPrivate implementation detail 1153 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 1154 */ 1155 @Deprecated 1156 @Override public List<String> impl_getAllParentStylesheets() { 1157 Styleable styleable = getStyleableParent(); 1158 if (styleable instanceof Parent) { 1159 return ((Parent)styleable).impl_getAllParentStylesheets(); 1160 } 1161 return null; 1162 } 1163 1164 /** 1165 * @treatAsPrivate implementation detail 1166 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 1167 */ 1168 @Deprecated 1169 @Override protected void impl_processCSS() { 1170 super.impl_processCSS(); 1171 1172 if (getSkin() == null) { 1173 // try to create default skin 1174 final Skin<?> defaultSkin = createDefaultSkin(); 1175 if (defaultSkin != null) { 1176 skinProperty().set(defaultSkin); 1177 super.impl_processCSS(); 1178 } else { 1179 final String msg = "The -fx-skin property has not been defined in CSS for " + this + 1180 " and createDefaultSkin() returned null."; 1181 final List<CssParser.ParseError> errors = StyleManager.getErrors(); 1182 if (errors != null) { 1183 CssParser.ParseError error = new CssParser.ParseError(msg); 1184 errors.add(error); // RT-19884 1185 } 1186 Logging.getControlsLogger().severe(msg); 1187 } 1188 } 1189 } 1190 1191 } 1192 1193 } | 32 import javafx.application.Application; 33 import javafx.beans.property.DoubleProperty; 34 import javafx.beans.property.DoublePropertyBase; 35 import javafx.beans.property.ObjectProperty; 36 import javafx.beans.property.ObjectPropertyBase; 37 import javafx.beans.property.StringProperty; 38 import javafx.beans.value.WritableValue; 39 import javafx.collections.FXCollections; 40 import javafx.collections.ObservableList; 41 import javafx.collections.ObservableSet; 42 import javafx.css.CssParser; 43 import javafx.scene.Node; 44 import javafx.scene.Parent; 45 import javafx.scene.Scene; 46 import javafx.scene.layout.Pane; 47 import javafx.stage.PopupWindow; 48 import com.sun.javafx.application.PlatformImpl; 49 import javafx.css.CssMetaData; 50 import javafx.css.PseudoClass; 51 import com.sun.javafx.css.StyleManager; 52 import com.sun.javafx.scene.NodeHelper; 53 import com.sun.javafx.scene.ParentHelper; 54 import javafx.css.Styleable; 55 import javafx.css.StyleableStringProperty; 56 import javafx.css.converter.StringConverter; 57 import com.sun.javafx.scene.control.Logging; 58 import com.sun.javafx.scene.layout.PaneHelper; 59 import com.sun.javafx.stage.PopupWindowHelper; 60 import com.sun.javafx.util.Utils; 61 import javafx.css.StyleableProperty; 62 import javafx.stage.Window; 63 import sun.util.logging.PlatformLogger; 64 import sun.util.logging.PlatformLogger.Level; 65 66 /** 67 * An extension of PopupWindow that allows for CSS styling. 68 * @since JavaFX 2.0 69 */ 70 public class PopupControl extends PopupWindow implements Skinnable, Styleable { 71 72 /** 73 * Sentinel value which can be passed to a control's setMinWidth(), setMinHeight(), 74 * setMaxWidth() or setMaxHeight() methods to indicate that the preferred dimension 75 * should be used for that max and/or min constraint. 76 */ 77 public static final double USE_PREF_SIZE = Double.NEGATIVE_INFINITY; 78 79 /** 80 * Sentinel value which can be passed to a control's setMinWidth(), setMinHeight(), 257 } 258 259 // Get the new value, and save it off as the new oldValue 260 oldValue = getValue(); 261 262 prefWidthCache = -1; 263 prefHeightCache = -1; 264 minWidthCache = -1; 265 minHeightCache = -1; 266 maxWidthCache = -1; 267 maxHeightCache = -1; 268 skinSizeComputed = false; 269 270 final Node n = getSkinNode(); 271 if (n != null) { 272 bridge.getChildren().setAll(n); 273 } else { 274 bridge.getChildren().clear(); 275 } 276 277 // calling NodeHelper.reapplyCSS() as the styleable properties may now 278 // be different, as we will now be able to return styleable properties 279 // belonging to the skin. If NodeHelper.reapplyCSS() is not called, the 280 // getCssMetaData() method is never called, so the 281 // skin properties are never exposed. 282 NodeHelper.reapplyCSS(bridge); 283 284 // DEBUG: Log that we've changed the skin 285 final PlatformLogger logger = Logging.getControlsLogger(); 286 if (logger.isLoggable(Level.FINEST)) { 287 logger.finest("Stored skin[" + getValue() + "] on " + this); 288 } 289 } 290 291 @Override 292 public Object getBean() { 293 return PopupControl.this; 294 } 295 296 @Override 297 public String getName() { 298 return "skin"; 299 } 300 }; 301 /** 302 * Keeps a reference to the name of the class currently acting as the skin. 1095 * @since JavaFX 8.0 1096 */ 1097 public final ObservableSet<PseudoClass> getPseudoClassStates() { 1098 return FXCollections.emptyObservableSet(); 1099 } 1100 1101 /** {@inheritDoc} */ 1102 @Override public Node getStyleableNode() { 1103 return bridge; 1104 } 1105 1106 /** 1107 * The link between the popup window and the scenegraph. 1108 * 1109 * @since JavaFX 2.1 1110 */ 1111 protected class CSSBridge extends Pane { 1112 1113 private final PopupControl popupControl = PopupControl.this; 1114 1115 { 1116 // To initialize the class helper at the begining each constructor of this class 1117 CSSBridgeHelper.initHelper(this); 1118 } 1119 1120 /** 1121 * Requests a layout pass to be performed before the next scene is 1122 * rendered. This is batched up asynchronously to happen once per 1123 * "pulse", or frame of animation. 1124 * <p/> 1125 * If this parent is either a layout root or unmanaged, then it will be 1126 * added directly to the scene's dirty layout list, otherwise requestLayout 1127 * will be invoked on its parent. 1128 */ 1129 @Override public void requestLayout() { 1130 prefWidthCache = -1; 1131 prefHeightCache = -1; 1132 minWidthCache = -1; 1133 minHeightCache = -1; 1134 maxWidthCache = -1; 1135 maxHeightCache = -1; 1136 //skinSizeComputed = false; -- RT-33073 disabled this 1137 super.requestLayout(); 1138 } 1139 1140 /** 1141 * This method should be treated as final and should not be overridden by any subclasses of CSSBridge. 1142 */ 1143 @Override 1144 public Styleable getStyleableParent() { 1145 return PopupControl.this.getStyleableParent(); 1146 } 1147 1148 @Override 1149 public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() { 1150 return PopupControl.this.getCssMetaData(); 1151 } 1152 1153 List<String> getAllParentStylesheets() { 1154 Styleable styleable = getStyleableParent(); 1155 if (styleable instanceof Parent) { 1156 return ParentHelper.getAllParentStylesheets((Parent)styleable); 1157 } 1158 return null; 1159 } 1160 1161 /* 1162 * Note: This method MUST only be called via its accessor method. 1163 */ 1164 private void doProcessCSS() { 1165 CSSBridgeHelper.superProcessCSS(this); 1166 1167 if (getSkin() == null) { 1168 // try to create default skin 1169 final Skin<?> defaultSkin = createDefaultSkin(); 1170 if (defaultSkin != null) { 1171 skinProperty().set(defaultSkin); 1172 CSSBridgeHelper.superProcessCSS(this); 1173 } else { 1174 final String msg = "The -fx-skin property has not been defined in CSS for " + this + 1175 " and createDefaultSkin() returned null."; 1176 final List<CssParser.ParseError> errors = StyleManager.getErrors(); 1177 if (errors != null) { 1178 CssParser.ParseError error = new CssParser.ParseError(msg); 1179 errors.add(error); // RT-19884 1180 } 1181 Logging.getControlsLogger().severe(msg); 1182 } 1183 } 1184 } 1185 1186 } 1187 1188 /* 1189 * Used to access internal methods of CSSBridge. 1190 */ 1191 static final class CSSBridgeHelper extends PaneHelper { 1192 private static final CSSBridgeHelper theInstance; 1193 1194 static { 1195 theInstance = new CSSBridgeHelper(); 1196 } 1197 1198 private static CSSBridgeHelper getInstance() { 1199 return theInstance; 1200 } 1201 1202 public static void initHelper(CSSBridge cssBridge) { 1203 setHelper(cssBridge, getInstance()); 1204 } 1205 1206 public static void superProcessCSS(Node node) { 1207 ((CSSBridgeHelper) getHelper(node)).superProcessCSSImpl(node); 1208 } 1209 1210 void superProcessCSSImpl(Node node) { 1211 super.processCSSImpl(node); 1212 } 1213 1214 protected void processCSSImpl(Node node) { 1215 ((CSSBridge) node).doProcessCSS(); 1216 } 1217 1218 } 1219 1220 } |