1 /* 2 * Copyright (c) 2013, 2016, 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 com.sun.javafx.scene; 27 28 import com.sun.glass.ui.Accessible; 29 import com.sun.javafx.geom.BaseBounds; 30 import com.sun.javafx.geom.PickRay; 31 import com.sun.javafx.geom.transform.BaseTransform; 32 import com.sun.javafx.jmx.MXNodeAlgorithm; 33 import com.sun.javafx.jmx.MXNodeAlgorithmContext; 34 import com.sun.javafx.scene.input.PickResultChooser; 35 import com.sun.javafx.scene.traversal.Direction; 36 import com.sun.javafx.sg.prism.NGNode; 37 import com.sun.javafx.util.Utils; 38 import java.util.List; 39 import java.util.Map; 40 import javafx.beans.binding.BooleanExpression; 41 import javafx.beans.property.BooleanProperty; 42 import javafx.css.CssMetaData; 43 import javafx.css.Style; 44 import javafx.css.Styleable; 45 import javafx.css.StyleableProperty; 46 import javafx.geometry.Bounds; 47 import javafx.scene.Node; 48 import javafx.scene.SubScene; 49 50 /** 51 * Used to access internal methods of Node. 52 */ 53 public abstract class NodeHelper { 54 private static NodeAccessor nodeAccessor; 55 56 static { 57 Utils.forceInit(Node.class); 58 } 59 60 protected NodeHelper() { 61 } 62 63 protected static NodeHelper getHelper(Node node) { 64 return nodeAccessor.getHelper(node); 65 } 66 67 protected static void setHelper(Node node, NodeHelper nodeHelper) { 68 nodeAccessor.setHelper(node, nodeHelper); 69 } 70 71 /* 72 * Static helper methods for cases where the implementation is done in an 73 * instance method that is overridden by subclasses. 74 * These methods exist in the base class only. 75 */ 76 77 public static NGNode createPeer(Node node) { 78 return getHelper(node).createPeerImpl(node); 79 } 80 81 public static void markDirty(Node node, DirtyBits dirtyBit) { 82 getHelper(node).markDirtyImpl(node, dirtyBit); 83 } 84 85 public static void updatePeer(Node node) { 86 getHelper(node).updatePeerImpl(node); 87 } 88 89 public static Bounds computeLayoutBounds(Node node) { 90 return getHelper(node).computeLayoutBoundsImpl(node); 91 } 92 93 /* 94 * Computes the geometric bounds for this Node. This method is abstract 95 * and must be implemented by each Node subclass. 96 */ 97 public static BaseBounds computeGeomBounds(Node node, 98 BaseBounds bounds, BaseTransform tx) { 99 return getHelper(node).computeGeomBoundsImpl(node, bounds, tx); 100 } 101 102 public static void transformsChanged(Node node) { 103 getHelper(node).transformsChangedImpl(node); 104 } 105 106 public static boolean computeContains(Node node, double localX, double localY) { 107 return getHelper(node).computeContainsImpl(node, localX, localY); 108 } 109 110 public static void pickNodeLocal(Node node, PickRay localPickRay, 111 PickResultChooser result) { 112 getHelper(node).pickNodeLocalImpl(node, localPickRay, result); 113 } 114 115 public static boolean computeIntersects(Node node, PickRay pickRay, 116 PickResultChooser pickResult) { 117 return getHelper(node).computeIntersectsImpl(node, pickRay, pickResult); 118 } 119 120 public static void geomChanged(Node node) { 121 getHelper(node).geomChangedImpl(node); 122 } 123 124 public static void notifyLayoutBoundsChanged(Node node) { 125 getHelper(node).notifyLayoutBoundsChangedImpl(node); 126 } 127 128 public static void processCSS(Node node) { 129 getHelper(node).processCSSImpl(node); 130 } 131 132 /* 133 * This method is used by Scene-graph JMX bean to obtain the Scene-graph structure. 134 * 135 * @param alg current algorithm to process this node 136 * @param ctx current context 137 * @return the algorithm specific result for this node 138 */ 139 public static Object processMXNode(Node node, MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) { 140 return getHelper(node).processMXNodeImpl(node, alg, ctx); 141 } 142 143 /* 144 * Methods that will be overridden by subclasses 145 */ 146 147 protected abstract NGNode createPeerImpl(Node node); 148 protected abstract boolean computeContainsImpl(Node node, double localX, double localY); 149 protected abstract BaseBounds computeGeomBoundsImpl(Node node, 150 BaseBounds bounds, BaseTransform tx); 151 protected abstract Object processMXNodeImpl(Node node, MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx); 152 153 protected void markDirtyImpl(Node node, DirtyBits dirtyBit) { 154 nodeAccessor.doMarkDirty(node, dirtyBit); 155 } 156 157 protected void updatePeerImpl(Node node) { 158 nodeAccessor.doUpdatePeer(node); 159 } 160 161 protected Bounds computeLayoutBoundsImpl(Node node) { 162 return nodeAccessor.doComputeLayoutBounds(node); 163 } 164 165 protected void transformsChangedImpl(Node node) { 166 nodeAccessor.doTransformsChanged(node); 167 } 168 169 protected void pickNodeLocalImpl(Node node, PickRay localPickRay, 170 PickResultChooser result) { 171 nodeAccessor.doPickNodeLocal(node, localPickRay, result); 172 } 173 174 protected boolean computeIntersectsImpl(Node node, PickRay pickRay, 175 PickResultChooser pickResult) { 176 return nodeAccessor.doComputeIntersects(node, pickRay, pickResult); 177 } 178 179 protected void geomChangedImpl(Node node) { 180 nodeAccessor.doGeomChanged(node); 181 } 182 183 protected void notifyLayoutBoundsChangedImpl(Node node) { 184 nodeAccessor.doNotifyLayoutBoundsChanged(node); 185 } 186 187 protected void processCSSImpl(Node node) { 188 nodeAccessor.doProcessCSS(node); 189 } 190 191 /* 192 * Methods used by Node (base) class only 193 */ 194 195 public static boolean isDirty(Node node, DirtyBits dirtyBit) { 196 return nodeAccessor.isDirty(node, dirtyBit); 197 } 198 199 public static boolean isDirtyEmpty(Node node) { 200 return nodeAccessor.isDirtyEmpty(node); 201 } 202 203 public static void syncPeer(Node node) { 204 nodeAccessor.syncPeer(node); 205 } 206 207 public static <P extends NGNode> P getPeer(Node node) { 208 return nodeAccessor.getPeer(node); 209 } 210 211 public static BaseTransform getLeafTransform(Node node) { 212 return nodeAccessor.getLeafTransform(node); 213 } 214 215 public static void layoutBoundsChanged(Node node) { 216 nodeAccessor.layoutBoundsChanged(node); 217 } 218 219 public static void setShowMnemonics(Node node, boolean value) { 220 nodeAccessor.setShowMnemonics(node, value); 221 } 222 223 public static boolean isShowMnemonics(Node node) { 224 return nodeAccessor.isShowMnemonics(node); 225 } 226 227 public static BooleanProperty showMnemonicsProperty(Node node) { 228 return nodeAccessor.showMnemonicsProperty(node); 229 } 230 231 public static boolean traverse(Node node, Direction direction) { 232 return nodeAccessor.traverse(node, direction); 233 } 234 235 public static double getPivotX(Node node) { 236 return nodeAccessor.getPivotX(node); 237 } 238 239 public static double getPivotY(Node node) { 240 return nodeAccessor.getPivotY(node); 241 } 242 243 public static double getPivotZ(Node node) { 244 return nodeAccessor.getPivotZ(node); 245 } 246 247 public static void pickNode(Node node, PickRay pickRay, 248 PickResultChooser result) { 249 nodeAccessor.pickNode(node, pickRay, result); 250 } 251 252 public static boolean intersects(Node node, PickRay pickRay, 253 PickResultChooser pickResult) { 254 return nodeAccessor.intersects(node, pickRay, pickResult); 255 } 256 257 public static double intersectsBounds(Node node, PickRay pickRay) { 258 return nodeAccessor.intersectsBounds(node, pickRay); 259 } 260 261 public static void layoutNodeForPrinting(Node node) { 262 nodeAccessor.layoutNodeForPrinting(node); 263 } 264 265 public static boolean isDerivedDepthTest(Node node) { 266 return nodeAccessor.isDerivedDepthTest(node); 267 } 268 269 public static SubScene getSubScene(Node node) { 270 return nodeAccessor.getSubScene(node); 271 } 272 273 public static Accessible getAccessible(Node node) { 274 return nodeAccessor.getAccessible(node); 275 } 276 277 public static void reapplyCSS(Node node) { 278 nodeAccessor.reapplyCSS(node); 279 } 280 281 public static boolean isTreeVisible(Node node) { 282 return nodeAccessor.isTreeVisible(node); 283 } 284 285 public static BooleanExpression treeVisibleProperty(Node node) { 286 return nodeAccessor.treeVisibleProperty(node); 287 } 288 289 public static List<Style> getMatchingStyles(CssMetaData cssMetaData, Styleable styleable) { 290 return getMatchingStyles(cssMetaData, styleable); 291 } 292 293 public static Map<StyleableProperty<?>,List<Style>> findStyles(Node node, Map<StyleableProperty<?>,List<Style>> styleMap) { 294 return nodeAccessor.findStyles(node, styleMap); 295 } 296 297 public static void setNodeAccessor(final NodeAccessor newAccessor) { 298 if (nodeAccessor != null) { 299 throw new IllegalStateException(); 300 } 301 302 nodeAccessor = newAccessor; 303 } 304 305 public static NodeAccessor getNodeAccessor() { 306 if (nodeAccessor == null) { 307 throw new IllegalStateException(); 308 } 309 310 return nodeAccessor; 311 } 312 313 public interface NodeAccessor { 314 NodeHelper getHelper(Node node); 315 void setHelper(Node node, NodeHelper nodeHelper); 316 void doMarkDirty(Node node, DirtyBits dirtyBit); 317 void doUpdatePeer(Node node); 318 BaseTransform getLeafTransform(Node node); 319 Bounds doComputeLayoutBounds(Node node); 320 void doTransformsChanged(Node node); 321 void doPickNodeLocal(Node node, PickRay localPickRay, 322 PickResultChooser result); 323 boolean doComputeIntersects(Node node, PickRay pickRay, 324 PickResultChooser pickResult); 325 void doGeomChanged(Node node); 326 void doNotifyLayoutBoundsChanged(Node node); 327 void doProcessCSS(Node node); 328 boolean isDirty(Node node, DirtyBits dirtyBit); 329 boolean isDirtyEmpty(Node node); 330 void syncPeer(Node node); 331 <P extends NGNode> P getPeer(Node node); 332 void layoutBoundsChanged(Node node); 333 void setShowMnemonics(Node node, boolean value); 334 boolean isShowMnemonics(Node node); 335 BooleanProperty showMnemonicsProperty(Node node); 336 boolean traverse(Node node, Direction direction); 337 double getPivotX(Node node); 338 double getPivotY(Node node); 339 double getPivotZ(Node node); 340 void pickNode(Node node, PickRay pickRay, PickResultChooser result); 341 boolean intersects(Node node, PickRay pickRay, PickResultChooser pickResult); 342 double intersectsBounds(Node node, PickRay pickRay); 343 void layoutNodeForPrinting(Node node); 344 boolean isDerivedDepthTest(Node node); 345 SubScene getSubScene(Node node); 346 void setLabeledBy(Node node, Node labeledBy); 347 Accessible getAccessible(Node node); 348 void reapplyCSS(Node node); 349 boolean isTreeVisible(Node node); 350 BooleanExpression treeVisibleProperty(Node node); 351 List<Style> getMatchingStyles(CssMetaData cssMetaData, Styleable styleable); 352 Map<StyleableProperty<?>,List<Style>> findStyles(Node node, 353 Map<StyleableProperty<?>,List<Style>> styleMap); 354 } 355 356 }