Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.image; 027 028import java.util.ArrayList; 029import java.util.Collections; 030import java.util.List; 031 032import javafx.beans.Observable; 033import javafx.geometry.Rectangle2D; 034import javafx.scene.Node; 035 036import com.sun.javafx.beans.event.AbstractNotifyListener; 037import com.sun.javafx.css.StyleManager; 038import javafx.css.CssMetaData; 039import javafx.css.StyleableStringProperty; 040import com.sun.javafx.css.converters.StringConverter; 041import com.sun.javafx.css.converters.URLConverter; 042import com.sun.javafx.geom.BaseBounds; 043import com.sun.javafx.geom.transform.BaseTransform; 044import com.sun.javafx.jmx.MXNodeAlgorithm; 045import com.sun.javafx.jmx.MXNodeAlgorithmContext; 046import com.sun.javafx.scene.DirtyBits; 047import com.sun.javafx.sg.PGImageView; 048import com.sun.javafx.sg.PGNode; 049import com.sun.javafx.tk.Toolkit; 050import java.net.MalformedURLException; 051import java.net.URL; 052import javafx.beans.DefaultProperty; 053import javafx.beans.property.*; 054import javafx.css.Styleable; 055import javafx.css.StyleableProperty; 056import javafx.geometry.NodeOrientation; 057 058/** 059 * The {@code ImageView} is a {@code Node} used for painting images loaded with 060 * {@link Image} class. 061 * 062 * <p> 063 * This class allows resizing the displayed image (with or without preserving 064 * the original aspect ratio) and specifying a viewport into the source image 065 * for restricting the pixels displayed by this {@code ImageView}. 066 * </p> 067 * 068 * 069 * <p> 070 * Example code for displaying images 071 * </p> 072 * 073 * <pre> 074 * <code> 075 * import javafx.application.Application; 076 * import javafx.geometry.Rectangle2D; 077 * import javafx.scene.Group; 078 * import javafx.scene.Scene; 079 * import javafx.scene.image.Image; 080 * import javafx.scene.image.ImageView; 081 * import javafx.scene.layout.HBox; 082 * import javafx.scene.paint.Color; 083 * import javafx.stage.Stage; 084 * 085 * public class HelloMenu extends Application { 086 * 087 * @Override public void start(Stage stage) { 088 * // load the image 089 * Image image = new Image("flower.png"); 090 * 091 * // simple displays ImageView the image as is 092 * ImageView iv1 = new ImageView(); 093 * iv1.setImage(image); 094 * 095 * // resizes the image to have width of 100 while preserving the ratio and using 096 * // higher quality filtering method; this ImageView is also cached to 097 * // improve performance 098 * ImageView iv2 = new ImageView(); 099 * iv2.setImage(image); 100 * iv2.setFitWidth(100); 101 * iv2.setPreserveRatio(true); 102 * iv2.setSmooth(true); 103 * iv2.setCache(true); 104 * 105 * // defines a viewport into the source image (achieving a "zoom" effect) and 106 * // displays it rotated 107 * ImageView iv3 = new ImageView(); 108 * iv3.setImage(image); 109 * Rectangle2D viewportRect = new Rectangle2D(40, 35, 110, 110); 110 * iv3.setViewport(viewportRect); 111 * iv3.setRotate(90); 112 * 113 * Group root = new Group(); 114 * Scene scene = new Scene(root); 115 * scene.setFill(Color.BLACK); 116 * HBox box = new HBox(); 117 * box.getChildren().add(iv1); 118 * box.getChildren().add(iv2); 119 * box.getChildren().add(iv3); 120 * root.getChildren().add(box); 121 * 122 * stage.setTitle("ImageView"); 123 * stage.setWidth(415); 124 * stage.setHeight(200); 125 * stage.setScene(scene); 126 * stage.sizeToScene(); 127 * stage.show(); 128 * } 129 * 130 * public static void main(String[] args) { 131 * Application.launch(args); 132 * } 133 * } 134 * </code> 135 * </pre> 136 * <p> 137 * The code above produces the following: 138 * </p> 139 * <p> 140 * <img src="doc-files/imageview.png"/> 141 * </p> 142 */ 143@DefaultProperty("image") 144public class ImageView extends Node { 145 146 /** 147 * Allocates a new ImageView object. 148 */ 149 public ImageView() { 150 setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT); 151 } 152 153 /** 154 * Allocates a new ImageView object with image loaded from the specified 155 * URL. 156 * <p> 157 * The {@code new ImageView(url)} has the same effect as 158 * {@code new ImageView(new Image(url))}. 159 * </p> 160 * 161 * @param url the string representing the URL from which to load the image 162 * @throws NullPointerException if URL is null 163 * @throws IllegalArgumentException if URL is invalid or unsupported 164 * @since JavaFX 2.1 165 */ 166 public ImageView(String url) { 167 this(new Image(url)); 168 } 169 170 /** 171 * Allocates a new ImageView object using the given image. 172 * 173 * @param image Image that this ImageView uses 174 */ 175 public ImageView(Image image) { 176 setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT); 177 setImage(image); 178 } 179 180 /** 181 * The {@link Image} to be painted by this {@code ImageView}. 182 * 183 * @defaultValue null 184 */ 185 private ObjectProperty<Image> image; 186 187 public final void setImage(Image value) { 188 imageProperty().set(value); 189 } 190 public final Image getImage() { 191 return image == null ? null : image.get(); 192 } 193 194 private Image oldImage; 195 public final ObjectProperty<Image> imageProperty() { 196 if (image == null) { 197 image = new ObjectPropertyBase<Image>() { 198 199 private boolean needsListeners = false; 200 201 @Override 202 public void invalidated() { 203 Image _image = get(); 204 boolean dimensionChanged = _image == null || oldImage == null || 205 (oldImage.getWidth() != _image.getWidth() || 206 oldImage.getHeight() != _image.getHeight()); 207 208 if (needsListeners) { 209 Toolkit.getImageAccessor().getImageProperty(oldImage). 210 removeListener(platformImageChangeListener.getWeakListener()); 211 } 212 213 needsListeners = _image != null && (_image.isAnimation() || _image.getProgress() < 1); 214 oldImage = _image; 215 216 if (needsListeners) { 217 Toolkit.getImageAccessor().getImageProperty(_image). 218 addListener(platformImageChangeListener.getWeakListener()); 219 } 220 if (dimensionChanged) { 221 impl_geomChanged(); 222 invalidateWidthHeight(); 223 } 224 impl_markDirty(DirtyBits.NODE_CONTENTS); 225 } 226 227 @Override 228 public Object getBean() { 229 return ImageView.this; 230 } 231 232 @Override 233 public String getName() { 234 return "image"; 235 } 236 }; 237 } 238 return image; 239 } 240 241 private StringProperty imageUrl = null; 242 /** 243 * The imageUrl property is set from CSS and then the image property is 244 * set from the invalidated method. This ensures that the same image isn't 245 * reloaded. 246 */ 247 private StringProperty imageUrlProperty() { 248 if (imageUrl == null) { 249 imageUrl = new StyleableStringProperty() { 250 251 @Override 252 protected void invalidated() { 253 254 final String imageUrl = get(); 255 if (imageUrl != null) { 256 setImage(StyleManager.getInstance().getCachedImage(imageUrl)); 257 } else { 258 setImage(null); 259 } 260 } 261 262 @Override 263 public Object getBean() { 264 return ImageView.this; 265 } 266 267 @Override 268 public String getName() { 269 return "imageUrl"; 270 } 271 272 @Override 273 public CssMetaData<ImageView,String> getCssMetaData() { 274 return StyleableProperties.IMAGE; 275 } 276 277 }; 278 } 279 return imageUrl; 280 } 281 282 private final AbstractNotifyListener platformImageChangeListener = 283 new AbstractNotifyListener() { 284 @Override 285 public void invalidated(Observable valueModel) { 286 impl_markDirty(DirtyBits.NODE_CONTENTS); 287 impl_geomChanged(); 288 invalidateWidthHeight(); 289 } 290 }; 291 /** 292 * The current x coordinate of the {@code ImageView} origin. 293 * 294 * @defaultValue 0 295 */ 296 private DoubleProperty x; 297 298 299 public final void setX(double value) { 300 xProperty().set(value); 301 } 302 303 public final double getX() { 304 return x == null ? 0.0 : x.get(); 305 } 306 307 public final DoubleProperty xProperty() { 308 if (x == null) { 309 x = new DoublePropertyBase() { 310 311 @Override 312 protected void invalidated() { 313 impl_markDirty(DirtyBits.NODE_GEOMETRY); 314 impl_geomChanged(); 315 } 316 317 @Override 318 public Object getBean() { 319 return ImageView.this; 320 } 321 322 @Override 323 public String getName() { 324 return "x"; 325 } 326 }; 327 } 328 return x; 329 } 330 331 /** 332 * The current y coordinate of the {@code ImageView} origin. 333 * 334 * @defaultValue 0 335 */ 336 private DoubleProperty y; 337 338 339 public final void setY(double value) { 340 yProperty().set(value); 341 } 342 343 public final double getY() { 344 return y == null ? 0.0 : y.get(); 345 } 346 347 public final DoubleProperty yProperty() { 348 if (y == null) { 349 y = new DoublePropertyBase() { 350 351 @Override 352 protected void invalidated() { 353 impl_markDirty(DirtyBits.NODE_GEOMETRY); 354 impl_geomChanged(); 355 } 356 357 @Override 358 public Object getBean() { 359 return ImageView.this; 360 } 361 362 @Override 363 public String getName() { 364 return "y"; 365 } 366 }; 367 } 368 return y; 369 } 370 371 /** 372 * The width of the bounding box within which the source image is resized as 373 * necessary to fit. If set to a value <= 0, then the intrinsic width of the 374 * image will be used as the {@code fitWidth}. 375 * <p/> 376 * See {@link #preserveRatio} for information on interaction between image 377 * view's {@code fitWidth}, {@code fitHeight} and {@code preserveRatio} 378 * attributes. 379 * 380 * @defaultValue 0 381 */ 382 private DoubleProperty fitWidth; 383 384 385 public final void setFitWidth(double value) { 386 fitWidthProperty().set(value); 387 } 388 389 public final double getFitWidth() { 390 return fitWidth == null ? 0.0 : fitWidth.get(); 391 } 392 393 public final DoubleProperty fitWidthProperty() { 394 if (fitWidth == null) { 395 fitWidth = new DoublePropertyBase() { 396 397 @Override 398 protected void invalidated() { 399 impl_markDirty(DirtyBits.NODE_VIEWPORT); 400 impl_geomChanged(); 401 invalidateWidthHeight(); 402 } 403 404 @Override 405 public Object getBean() { 406 return ImageView.this; 407 } 408 409 @Override 410 public String getName() { 411 return "fitWidth"; 412 } 413 }; 414 } 415 return fitWidth; 416 } 417 418 /** 419 * The height of the bounding box within which the source image is resized 420 * as necessary to fit. If set to a value <= 0, then the intrinsic height of 421 * the image will be used as the {@code fitHeight}. 422 * <p> 423 * See {@link #preserveRatio} for information on interaction between image 424 * view's {@code fitWidth}, {@code fitHeight} and {@code preserveRatio} 425 * attributes. 426 * </p> 427 * 428 * @defaultValue 0 429 */ 430 private DoubleProperty fitHeight; 431 432 433 public final void setFitHeight(double value) { 434 fitHeightProperty().set(value); 435 } 436 437 public final double getFitHeight() { 438 return fitHeight == null ? 0.0 : fitHeight.get(); 439 } 440 441 public final DoubleProperty fitHeightProperty() { 442 if (fitHeight == null) { 443 fitHeight = new DoublePropertyBase() { 444 445 @Override 446 protected void invalidated() { 447 impl_markDirty(DirtyBits.NODE_VIEWPORT); 448 impl_geomChanged(); 449 invalidateWidthHeight(); 450 } 451 452 @Override 453 public Object getBean() { 454 return ImageView.this; 455 } 456 457 @Override 458 public String getName() { 459 return "fitHeight"; 460 } 461 }; 462 } 463 return fitHeight; 464 } 465 466 /** 467 * Indicates whether to preserve the aspect ratio of the source image when 468 * scaling to fit the image within the fitting bounding box. 469 * <p/> 470 * If set to {@code true}, it affects the dimensions of this 471 * {@code ImageView} in the following way * 472 * <ul> 473 * <li>If only {@code fitWidth} is set, height is scaled to preserve ratio 474 * <li>If only {@code fitHeight} is set, width is scaled to preserve ratio 475 * <li>If both are set, they both may be scaled to get the best fit in a 476 * width by height rectangle while preserving the original aspect ratio 477 * </ul> 478 * 479 * If unset or set to {@code false}, it affects the dimensions of this 480 * {@code ImageView} in the following way * 481 * <ul> 482 * <li>If only {@code fitWidth} is set, image's view width is scaled to 483 * match and height is unchanged; 484 * <li>If only {@code fitHeight} is set, image's view height is scaled to 485 * match and height is unchanged; 486 * <li>If both are set, the image view is scaled to match both. 487 * </ul> 488 * </p> 489 * Note that the dimensions of this node as reported by the node's bounds 490 * will be equal to the size of the scaled image and is guaranteed to be 491 * contained within {@code fitWidth x fitHeight} bonding box. 492 * 493 * @defaultValue false 494 */ 495 private BooleanProperty preserveRatio; 496 497 498 public final void setPreserveRatio(boolean value) { 499 preserveRatioProperty().set(value); 500 } 501 502 public final boolean isPreserveRatio() { 503 return preserveRatio == null ? false : preserveRatio.get(); 504 } 505 506 public final BooleanProperty preserveRatioProperty() { 507 if (preserveRatio == null) { 508 preserveRatio = new BooleanPropertyBase() { 509 510 @Override 511 protected void invalidated() { 512 impl_markDirty(DirtyBits.NODE_VIEWPORT); 513 impl_geomChanged(); 514 invalidateWidthHeight(); 515 } 516 517 @Override 518 public Object getBean() { 519 return ImageView.this; 520 } 521 522 @Override 523 public String getName() { 524 return "preserveRatio"; 525 } 526 }; 527 } 528 return preserveRatio; 529 } 530 531 /** 532 * Indicates whether to use a better quality filtering algorithm or a faster 533 * one when transforming or scaling the source image to fit within the 534 * bounding box provided by {@code fitWidth} and {@code fitHeight}. 535 * 536 * <p> 537 * If set to {@code true} a better quality filtering will be used, if set to 538 * {@code false} a faster but lesser quality filtering will be used. 539 * </p> 540 * 541 * <p> 542 * The default value depends on platform configuration. 543 * </p> 544 * 545 * @defaultValue platform-dependent 546 */ 547 private BooleanProperty smooth; 548 549 550 public final void setSmooth(boolean value) { 551 smoothProperty().set(value); 552 } 553 554 public final boolean isSmooth() { 555 return smooth == null ? SMOOTH_DEFAULT : smooth.get(); 556 } 557 558 public final BooleanProperty smoothProperty() { 559 if (smooth == null) { 560 smooth = new BooleanPropertyBase(SMOOTH_DEFAULT) { 561 562 @Override 563 protected void invalidated() { 564 impl_markDirty(DirtyBits.NODE_SMOOTH); 565 } 566 567 @Override 568 public Object getBean() { 569 return ImageView.this; 570 } 571 572 @Override 573 public String getName() { 574 return "smooth"; 575 } 576 }; 577 } 578 return smooth; 579 } 580 581 /** 582 * Platform-dependent default value of the {@link #smoothProperty smooth} property. 583 */ 584 public static final boolean SMOOTH_DEFAULT = Toolkit.getToolkit() 585 .getDefaultImageSmooth(); 586 /** 587 * The rectangular viewport into the image. The viewport is specified in the 588 * coordinates of the image, prior to scaling or any other transformations. 589 * 590 * <p> 591 * If {@code viewport} is {@code null}, the entire image is displayed. If 592 * {@code viewport} is non-{@code null}, only the portion of the image which 593 * falls within the viewport will be displayed. If the image does not fully 594 * cover the viewport then any remaining area of the viewport will be empty. 595 * </p> 596 * 597 * @defaultValue null 598 */ 599 private ObjectProperty<Rectangle2D> viewport; 600 601 602 public final void setViewport(Rectangle2D value) { 603 viewportProperty().set(value); 604 } 605 606 public final Rectangle2D getViewport() { 607 return viewport == null ? null : viewport.get(); 608 } 609 610 public final ObjectProperty<Rectangle2D> viewportProperty() { 611 if (viewport == null) { 612 viewport = new ObjectPropertyBase<Rectangle2D>() { 613 614 @Override 615 protected void invalidated() { 616 impl_markDirty(DirtyBits.NODE_VIEWPORT); 617 impl_geomChanged(); 618 invalidateWidthHeight(); 619 } 620 621 @Override 622 public Object getBean() { 623 return ImageView.this; 624 } 625 626 @Override 627 public String getName() { 628 return "viewport"; 629 } 630 }; 631 } 632 return viewport; 633 } 634 635 // Need to track changes to image width and image height and recompute 636 // bounds when changed. 637 // imageWidth = bind image.width on replace { 638 // impl_geomChanged(); 639 // } 640 // 641 // imageHeight = bind image.height on replace { 642 // impl_geomChanged(); 643 // } 644 645 private double destWidth, destHeight; 646 647 /** 648 * @treatAsPrivate implementation detail 649 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 650 */ 651 @Deprecated 652 @Override protected PGNode impl_createPGNode() { 653 return Toolkit.getToolkit().createPGImageView(); 654 } 655 656 private PGImageView getPGImageView() { 657 return (PGImageView) impl_getPGNode(); 658 } 659 660 /** 661 * @treatAsPrivate implementation detail 662 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 663 */ 664 @Deprecated 665 @Override public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) { 666 recomputeWidthHeight(); 667 668 bounds = bounds.deriveWithNewBounds((float)getX(), (float)getY(), 0.0f, 669 (float)(getX() + destWidth), (float)(getY() + destHeight), 0.0f); 670 bounds = tx.transform(bounds, bounds); 671 return bounds; 672 } 673 674 private boolean validWH; 675 676 private void invalidateWidthHeight() { 677 validWH = false; 678 } 679 680 private void recomputeWidthHeight() { 681 if (validWH) { 682 return; 683 } 684 Image localImage = getImage(); 685 Rectangle2D localViewport = getViewport(); 686 687 double w = 0; 688 double h = 0; 689 if (localViewport != null && localViewport.getWidth() > 0 && localViewport.getHeight() > 0) { 690 w = localViewport.getWidth(); 691 h = localViewport.getHeight(); 692 } else if (localImage != null) { 693 w = localImage.getWidth(); 694 h = localImage.getHeight(); 695 } 696 697 double localFitWidth = getFitWidth(); 698 double localFitHeight = getFitHeight(); 699 700 if (isPreserveRatio() && w > 0 && h > 0 && (localFitWidth > 0 || localFitHeight > 0)) { 701 if (localFitWidth <= 0 || (localFitHeight > 0 && localFitWidth * h > localFitHeight * w)) { 702 w = w * localFitHeight / h; 703 h = localFitHeight; 704 } else { 705 h = h * localFitWidth / w; 706 w = localFitWidth; 707 } 708 } else { 709 if (localFitWidth > 0f) { 710 w = localFitWidth; 711 } 712 if (localFitHeight > 0f) { 713 h = localFitHeight; 714 } 715 } 716 717 // Store these values for use later in impl_computeContains() to support 718 // Node.contains(). 719 destWidth = w; 720 destHeight = h; 721 722 validWH = true; 723 } 724 725 /** 726 * @treatAsPrivate implementation detail 727 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 728 */ 729 @Deprecated 730 @Override protected boolean impl_computeContains(double localX, double localY) { 731 if (getImage() == null) { 732 return false; 733 } 734 735 recomputeWidthHeight(); 736 // Local Note bounds contain test is already done by the caller. 737 // (Node.contains()). 738 739 double dx = localX - getX(); 740 double dy = localY - getY(); 741 742 Image localImage = getImage(); 743 double srcWidth = localImage.getWidth(); 744 double srcHeight = localImage.getHeight(); 745 double viewWidth = srcWidth; 746 double viewHeight = srcHeight; 747 double vw = 0; 748 double vh = 0; 749 double vminx = 0; 750 double vminy = 0; 751 Rectangle2D localViewport = getViewport(); 752 if (localViewport != null) { 753 vw = localViewport.getWidth(); 754 vh = localViewport.getHeight(); 755 vminx = localViewport.getMinX(); 756 vminy = localViewport.getMinY(); 757 } 758 759 if (vw > 0 && vh > 0) { 760 viewWidth = vw; 761 viewHeight = vh; 762 } 763 764 // desWidth Note and destHeight are computed by impl_computeGeomBounds() 765 // via a call from Node.contains() before calling 766 // impl_computeContains(). 767 // Transform into image's coordinate system. 768 dx = vminx + dx * viewWidth / destWidth; 769 dy = vminy + dy * viewHeight / destHeight; 770 // test whether it's inside the original image AND inside of viewport 771 // (viewport may stick out from the image bounds) 772 if (dx < 0.0 || dy < 0.0 || dx >= srcWidth || dy >= srcHeight || 773 dx < vminx || dy < vminy || 774 dx >= vminx + viewWidth || dy >= vminy + viewHeight) { 775 return false; 776 } 777 // Do alpha test on the picked pixel. 778 return Toolkit.getToolkit().imageContains(localImage.impl_getPlatformImage(), (float)dx, (float)dy); 779 } 780 781 /*************************************************************************** 782 * * Stylesheet Handling * * 783 **************************************************************************/ 784 785 /** 786 * Super-lazy instantiation pattern from Bill Pugh. 787 * @treatAsPrivate implementation detail 788 */ 789 private static class StyleableProperties { 790 // TODO 791 // "preserve-ratio","smooth","viewport","fit-width","fit-height" 792 private static final CssMetaData<ImageView, String> IMAGE = 793 new CssMetaData<ImageView,String>("-fx-image", 794 URLConverter.getInstance()) { 795 796 @Override 797 public boolean isSettable(ImageView n) { 798 // Note that we care about the image, not imageUrl 799 return n.image == null || !n.image.isBound(); 800 } 801 802 @Override 803 public StyleableProperty<String> getStyleableProperty(ImageView n) { 804 return (StyleableProperty<String>)n.imageUrlProperty(); 805 } 806 }; 807 808 private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; 809 static { 810 final List<CssMetaData<? extends Styleable, ?>> styleables = 811 new ArrayList<CssMetaData<? extends Styleable, ?>>(Node.getClassCssMetaData()); 812 styleables.add(IMAGE); 813 STYLEABLES = Collections.unmodifiableList(styleables); 814 } 815 } 816 817 /** 818 * @return The CssMetaData associated with this class, which may include the 819 * CssMetaData of its super classes. 820 */ 821 public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { 822 return StyleableProperties.STYLEABLES; 823 } 824 825 /** 826 * {@inheritDoc} 827 * 828 */ 829 830 831 @Override 832 public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() { 833 return getClassCssMetaData(); 834 } 835 836 void updateViewport() { 837 recomputeWidthHeight(); 838 if (getImage() == null || getImage().impl_getPlatformImage() == null) { 839 return; 840 } 841 842 Rectangle2D localViewport = getViewport(); 843 if (localViewport != null) { 844 getPGImageView().setViewport((float)localViewport.getMinX(), (float)localViewport.getMinY(), 845 (float)localViewport.getWidth(), (float)localViewport.getHeight(), 846 (float)destWidth, (float)destHeight); 847 } else { 848 getPGImageView().setViewport(0, 0, 0, 0, (float)destWidth, (float)destHeight); 849 } 850 } 851 852 /** 853 * @treatAsPrivate implementation detail 854 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 855 */ 856 @Deprecated 857 @Override public void impl_updatePG() { 858 super.impl_updatePG(); 859 860 if (impl_isDirty(DirtyBits.NODE_GEOMETRY)) { 861 PGImageView peer = getPGImageView(); 862 peer.setX((float)getX()); 863 peer.setY((float)getY()); 864 } 865 if (impl_isDirty(DirtyBits.NODE_SMOOTH)) { 866 getPGImageView().setSmooth(isSmooth()); 867 } 868 if (impl_isDirty(DirtyBits.NODE_CONTENTS)) { 869 getPGImageView().setImage(getImage()!= null? getImage().impl_getPlatformImage():null); 870 } 871 // The NG part expects this to be called when image changes 872 if (impl_isDirty(DirtyBits.NODE_VIEWPORT) || impl_isDirty(DirtyBits.NODE_CONTENTS)) { 873 updateViewport(); 874 } 875 } 876 877 /** 878 * @treatAsPrivate implementation detail 879 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 880 */ 881 @Deprecated 882 @Override public Object impl_processMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) { 883 return alg.processLeafNode(this, ctx); 884 } 885}