1 12 13 package org.eclipse.jface.text; 14 15 16 import org.eclipse.swt.SWT; 17 import org.eclipse.swt.events.DisposeEvent; 18 import org.eclipse.swt.events.DisposeListener; 19 import org.eclipse.swt.graphics.GC; 20 import org.eclipse.swt.graphics.Point; 21 import org.eclipse.swt.graphics.Rectangle; 22 import org.eclipse.swt.widgets.Control; 23 import org.eclipse.swt.widgets.Display; 24 import org.eclipse.swt.widgets.Monitor; 25 26 import org.eclipse.core.runtime.Assert; 27 28 import org.eclipse.jface.dialogs.IDialogSettings; 29 import org.eclipse.jface.util.Geometry; 30 31 32 48 abstract public class AbstractInformationControlManager { 49 50 58 public interface IInformationControlCloser { 59 60 69 public void setSubjectControl(Control subject); 70 71 78 public void setInformationControl(IInformationControl control); 79 80 87 public void start(Rectangle subjectArea); 88 89 92 public void stop(); 93 } 94 95 96 97 100 public static final class Anchor { 101 private final int fFlag; 102 private Anchor(int flag) { 103 fFlag= flag; 104 } 105 112 int getSWTFlag() { 113 return fFlag; 114 } 115 } 116 117 118 private final static Anchor[] ANCHORS= { new Anchor(SWT.TOP), new Anchor(SWT.BOTTOM), new Anchor(SWT.LEFT), new Anchor(SWT.RIGHT) }; 119 120 121 public final static Anchor ANCHOR_TOP= ANCHORS[0]; 122 123 public final static Anchor ANCHOR_BOTTOM= ANCHORS[1]; 124 125 public final static Anchor ANCHOR_LEFT= ANCHORS[2]; 126 127 public final static Anchor ANCHOR_RIGHT= ANCHORS[3]; 128 132 public final static Anchor ANCHOR_GLOBAL= new Anchor(SWT.CENTER); 133 134 138 public static final String STORE_LOCATION_X= "location.x"; 143 public static final String STORE_LOCATION_Y= "location.y"; 148 public static final String STORE_SIZE_WIDTH= "size.width"; 153 public static final String STORE_SIZE_HEIGHT= "size.height"; 155 156 157 private Control fSubjectControl; 158 159 160 private Rectangle fSubjectArea; 161 162 163 private Object fInformation; 164 165 166 private boolean fTakesFocusWhenVisible= false; 167 168 169 protected IInformationControl fInformationControl; 170 171 172 protected IInformationControlCreator fInformationControlCreator; 173 174 175 protected IInformationControlCloser fInformationControlCloser; 176 177 178 protected boolean fDisposed= false; 179 180 181 private boolean fEnabled= false; 182 183 184 private Point fSizeConstraints; 185 186 187 private int fMarginY= 5; 188 189 190 private int fMarginX= 5; 191 192 193 private int fWidthConstraint= 60; 194 195 196 private int fHeightConstraint= 6; 197 198 199 private boolean fEnforceAsMinimalSize= false; 200 201 202 private boolean fEnforceAsMaximalSize= false; 203 204 205 private Anchor fAnchor= ANCHOR_BOTTOM; 206 207 220 private Anchor[] fFallbackAnchors= ANCHORS; 221 222 226 private volatile IInformationControlCreator fCustomInformationControlCreator; 227 228 232 private boolean fIsCustomInformationControl= false; 233 234 238 private IDialogSettings fDialogSettings; 239 240 247 private boolean fIsRestoringLocation; 248 249 256 private boolean fIsRestoringSize; 257 258 263 private DisposeListener fSubjectControlDisposeListener; 264 265 266 284 protected AbstractInformationControlManager(IInformationControlCreator creator) { 285 Assert.isNotNull(creator); 286 fInformationControlCreator= creator; 287 } 288 289 294 abstract protected void computeInformation(); 295 296 305 protected final void setInformation(String information, Rectangle subjectArea) { 306 fInformation= information; 307 fSubjectArea= subjectArea; 308 presentInformation(); 309 } 310 311 321 protected final void setInformation(Object information, Rectangle subjectArea) { 322 fInformation= information; 323 fSubjectArea= subjectArea; 324 presentInformation(); 325 } 326 327 332 protected void setCloser(IInformationControlCloser closer) { 333 fInformationControlCloser= closer; 334 } 335 336 343 public void setMargins(int xMargin, int yMargin) { 344 fMarginX= xMargin; 345 fMarginY= yMargin; 346 } 347 348 356 public void setSizeConstraints(int widthInChar, int heightInChar, boolean enforceAsMinimalSize, boolean enforceAsMaximalSize) { 357 fSizeConstraints= null; 358 fWidthConstraint= widthInChar; 359 fHeightConstraint= heightInChar; 360 fEnforceAsMinimalSize= enforceAsMinimalSize; 361 fEnforceAsMaximalSize= enforceAsMaximalSize; 362 363 } 364 365 390 public void setRestoreInformationControlBounds(IDialogSettings dialogSettings, boolean restoreLocation, boolean restoreSize) { 391 Assert.isTrue(dialogSettings != null && (restoreLocation || restoreSize)); 392 fDialogSettings= dialogSettings; 393 fIsRestoringLocation= restoreLocation; 394 fIsRestoringSize= restoreSize; 395 } 396 397 405 public void setAnchor(Anchor anchor) { 406 fAnchor= anchor; 407 } 408 409 424 public void setFallbackAnchors(Anchor[] fallbackAnchors) { 425 if (fallbackAnchors != null) { 426 fFallbackAnchors= new Anchor[fallbackAnchors.length]; 427 System.arraycopy(fallbackAnchors, 0, fFallbackAnchors, 0, fallbackAnchors.length); 428 } else 429 fFallbackAnchors= null; 430 } 431 432 438 protected void setCustomInformationControlCreator(IInformationControlCreator informationControlCreator) { 439 if (informationControlCreator != null && fCustomInformationControlCreator instanceof IInformationControlCreatorExtension) { 440 IInformationControlCreatorExtension extension= (IInformationControlCreatorExtension) fCustomInformationControlCreator; 441 if (extension.canReplace(informationControlCreator)) 442 return; 443 } 444 fCustomInformationControlCreator= informationControlCreator; 445 } 446 447 452 public void takesFocusWhenVisible(boolean takesFocus) { 453 fTakesFocusWhenVisible= takesFocus; 454 } 455 456 461 protected void handleSubjectControlDisposed() { 462 disposeInformationControl(); 463 } 464 465 472 public void install(Control subjectControl) { 473 if (fSubjectControl != null && !fSubjectControl.isDisposed() && fSubjectControlDisposeListener != null) 474 fSubjectControl.removeDisposeListener(fSubjectControlDisposeListener); 475 476 fSubjectControl= subjectControl; 477 478 if (fSubjectControl != null) 479 fSubjectControl.addDisposeListener(getSubjectControlDisposeListener()); 480 481 if (fInformationControlCloser != null) 482 fInformationControlCloser.setSubjectControl(subjectControl); 483 484 setEnabled(true); 485 fDisposed= false; 486 } 487 488 495 private DisposeListener getSubjectControlDisposeListener() { 496 if (fSubjectControlDisposeListener == null) { 497 fSubjectControlDisposeListener= new DisposeListener() { 498 public void widgetDisposed(DisposeEvent e) { 499 handleSubjectControlDisposed(); 500 } 501 }; 502 } 503 return fSubjectControlDisposeListener; 504 } 505 506 511 protected Control getSubjectControl() { 512 return fSubjectControl; 513 } 514 515 520 protected Rectangle getSubjectArea() { 521 return fSubjectArea; 522 } 523 524 530 public void setEnabled(boolean enabled) { 531 fEnabled= enabled; 532 } 533 534 539 protected boolean isEnabled() { 540 return fEnabled; 541 } 542 543 552 protected Point computeSizeConstraints(Control subjectControl, IInformationControl informationControl) { 553 554 if (fSizeConstraints == null) { 555 556 if (subjectControl == null) 557 return null; 558 559 GC gc= new GC(subjectControl); 560 gc.setFont(subjectControl.getFont()); 561 int width= gc.getFontMetrics().getAverageCharWidth(); 562 int height = gc.getFontMetrics().getHeight(); 563 gc.dispose(); 564 565 fSizeConstraints= new Point (fWidthConstraint * width, fHeightConstraint * height); 566 } 567 568 return new Point(fSizeConstraints.x, fSizeConstraints.y); 569 } 570 571 580 protected Point computeSizeConstraints(Control subjectControl, Rectangle subjectArea, IInformationControl informationControl) { 581 return computeSizeConstraints(subjectControl, informationControl); 582 } 583 584 588 protected void handleInformationControlDisposed() { 589 590 storeInformationControlBounds(); 591 592 fInformationControl= null; 593 if (fInformationControlCloser != null) { 594 fInformationControlCloser.setInformationControl(null); 595 fInformationControlCloser.stop(); 596 } 597 } 598 599 605 protected IInformationControl getInformationControl() { 606 607 if (fDisposed) 608 return fInformationControl; 609 610 IInformationControlCreator creator= null; 611 612 if (fCustomInformationControlCreator == null) { 613 creator= fInformationControlCreator; 614 if (fIsCustomInformationControl && fInformationControl != null) { 615 fInformationControl.dispose(); 616 fInformationControl= null; 617 } 618 fIsCustomInformationControl= false; 619 620 } else { 621 622 creator= fCustomInformationControlCreator; 623 if (creator instanceof IInformationControlCreatorExtension) { 624 IInformationControlCreatorExtension extension= (IInformationControlCreatorExtension) creator; 625 if (fInformationControl != null && extension.canReuse(fInformationControl)) 626 return fInformationControl; 627 } 628 if (fInformationControl != null) { 629 fInformationControl.dispose(); 630 fInformationControl= null; 631 } 632 fIsCustomInformationControl= true; 633 } 634 635 if (fInformationControl == null) { 636 fInformationControl= creator.createInformationControl(fSubjectControl.getShell()); 637 fInformationControl.addDisposeListener(new DisposeListener() { 638 public void widgetDisposed(DisposeEvent e) { 639 handleInformationControlDisposed(); 640 } 641 }); 642 643 if (fInformationControlCloser != null) 644 fInformationControlCloser.setInformationControl(fInformationControl); 645 } 646 647 return fInformationControl; 648 } 649 650 661 protected Point computeLocation(Rectangle subjectArea, Point controlSize, Anchor anchor) { 662 int xShift= 0; 663 int yShift= 0; 664 665 switch (anchor.getSWTFlag()) { 666 case SWT.CENTER: 667 Point subjectControlSize= fSubjectControl.getSize(); 668 Point location= new Point(subjectControlSize.x / 2, subjectControlSize.y / 2); 669 location.x -= (controlSize.x / 2); 670 location.y -= (controlSize.y / 2); 671 return fSubjectControl.toDisplay(location); 672 case SWT.BOTTOM: 673 yShift= subjectArea.height + fMarginY; 674 break; 675 case SWT.RIGHT: 676 xShift= fMarginX + subjectArea.width; 677 break; 678 case SWT.TOP: 679 yShift= -controlSize.y - fMarginY; 680 break; 681 case SWT.LEFT: 682 xShift= -controlSize.x - fMarginX; 683 break; 684 } 685 686 boolean isRTL= fSubjectControl != null && (fSubjectControl.getStyle() & SWT.RIGHT_TO_LEFT) != 0; 687 if (isRTL) 688 xShift += controlSize.x; 689 690 return fSubjectControl.toDisplay(new Point(subjectArea.x + xShift, subjectArea.y + yShift)); 691 } 692 693 704 protected Rectangle computeAvailableArea(Rectangle subjectArea, Rectangle bounds, Anchor anchor) { 705 Rectangle area; 706 switch (anchor.getSWTFlag()) { 707 case SWT.CENTER: 708 area= bounds; 709 break; 710 case SWT.BOTTOM: 711 int y= subjectArea.y + subjectArea.height + fMarginY; 712 area= new Rectangle(bounds.x, y, bounds.width, bounds.y + bounds.height - y); 713 break; 714 case SWT.RIGHT: 715 int x= subjectArea.x + subjectArea.width + fMarginX; 716 area= new Rectangle(x, bounds.y, bounds.x + bounds.width - x, bounds.height); 717 break; 718 case SWT.TOP: 719 area= new Rectangle(bounds.x, bounds.y, bounds.width, subjectArea.y - bounds.y - fMarginY); 720 break; 721 case SWT.LEFT: 722 area= new Rectangle(bounds.x, bounds.y, subjectArea.x - bounds.x - fMarginX, bounds.height); 723 break; 724 default: 725 Assert.isLegal(false); 726 return null; 727 } 728 729 area.intersect(bounds); 731 return area; 732 } 733 734 749 protected boolean updateLocation(Point location, Point size, Rectangle displayArea, Anchor anchor) { 750 751 int displayLowerRightX= displayArea.x + displayArea.width; 752 int displayLowerRightY= displayArea.y + displayArea.height; 753 int lowerRightX= location.x + size.x; 754 int lowerRightY= location.y + size.y; 755 756 if (ANCHOR_BOTTOM == anchor || ANCHOR_TOP == anchor) { 757 758 if (ANCHOR_BOTTOM == anchor) { 759 if (lowerRightY > displayLowerRightY) 760 return false; 761 } else { 762 if (location.y < displayArea.y) 763 return false; 764 } 765 766 if (lowerRightX > displayLowerRightX) 767 location.x= location.x - (lowerRightX - displayLowerRightX); 768 769 return (location.x >= displayArea.x && location.y >= displayArea.y); 770 771 } else if (ANCHOR_RIGHT == anchor || ANCHOR_LEFT == anchor) { 772 773 if (ANCHOR_RIGHT == anchor) { 774 if (lowerRightX > displayLowerRightX) 775 return false; 776 } else { 777 if (location.x < displayArea.x) 778 return false; 779 } 780 781 if (lowerRightY > displayLowerRightY) 782 location.y= location.y - (lowerRightY - displayLowerRightY); 783 784 return (location.x >= displayArea.x && location.y >= displayArea.y); 785 786 } else if (ANCHOR_GLOBAL == anchor) { 787 788 if (lowerRightX > displayLowerRightX) 789 location.x= location.x - (lowerRightX - displayLowerRightX); 790 791 if (lowerRightY > displayLowerRightY) 792 location.y= location.y - (lowerRightY - displayLowerRightY); 793 794 return (location.x >= displayArea.x && location.y >= displayArea.y); 795 } 796 797 return false; 798 } 799 800 817 protected Anchor getNextFallbackAnchor(Anchor anchor) { 818 819 if (anchor == null || fFallbackAnchors == null) 820 return null; 821 822 for (int i= 0; i < fFallbackAnchors.length; i++) { 823 if (fFallbackAnchors[i] == anchor) 824 return fFallbackAnchors[i + 1 == fFallbackAnchors.length ? 0 : i + 1]; 825 } 826 827 return null; 828 } 829 830 841 protected Point computeInformationControlLocation(Rectangle subjectArea, Point controlSize) { 842 Rectangle subjectAreaDisplayRelative= Geometry.toDisplay(fSubjectControl, subjectArea); 843 844 Point upperLeft; 845 Anchor testAnchor= fAnchor; 846 Rectangle bestBounds= null; 847 int bestArea= Integer.MIN_VALUE; 848 Anchor bestAnchor= null; 849 do { 850 851 upperLeft= computeLocation(subjectArea, controlSize, testAnchor); 852 Monitor monitor= getClosestMonitor(subjectAreaDisplayRelative, testAnchor); 853 if (updateLocation(upperLeft, controlSize, monitor.getClientArea(), testAnchor)) 854 return upperLeft; 855 856 Rectangle available= computeAvailableArea(subjectAreaDisplayRelative, monitor.getClientArea(), testAnchor); 858 Rectangle proposed= new Rectangle(upperLeft.x, upperLeft.y, controlSize.x, controlSize.y); 859 available.intersect(proposed); 860 int area= available.width * available.height; 861 if (area > bestArea) { 862 bestArea= area; 863 bestBounds= available; 864 bestAnchor= testAnchor; 865 } 866 867 testAnchor= getNextFallbackAnchor(testAnchor); 868 869 } while (testAnchor != fAnchor && testAnchor != null); 870 871 if (bestAnchor != ANCHOR_GLOBAL) 873 Geometry.set(controlSize, Geometry.getSize(bestBounds)); 874 return Geometry.getLocation(bestBounds); 875 } 876 877 886 private Monitor getClosestMonitor(Rectangle area, Anchor anchor) { 887 Point center; 888 if (ANCHOR_GLOBAL == anchor) 889 center= Geometry.centerPoint(area); 890 else 891 center= Geometry.centerPoint(Geometry.getExtrudedEdge(area, 0, anchor.getSWTFlag())); 892 return getClosestMonitor(fSubjectControl.getDisplay(), Geometry.createRectangle(center, new Point(0, 0))); 893 } 894 895 905 private Monitor getClosestMonitor(Display display, Rectangle rectangle) { 906 int closest = Integer.MAX_VALUE; 907 908 Point toFind= Geometry.centerPoint(rectangle); 909 Monitor[] monitors = display.getMonitors(); 910 Monitor result = monitors[0]; 911 912 for (int idx = 0; idx < monitors.length; idx++) { 913 Monitor current = monitors[idx]; 914 915 Rectangle clientArea = current.getClientArea(); 916 917 if (clientArea.contains(toFind)) { 918 return current; 919 } 920 921 int distance = Geometry.distanceSquared(Geometry.centerPoint(clientArea), toFind); 922 if (distance < closest) { 923 closest = distance; 924 result = current; 925 } 926 } 927 928 return result; 929 } 930 931 936 public void showInformation() { 937 if (fEnabled) 938 doShowInformation(); 939 } 940 941 945 protected void doShowInformation() { 946 fSubjectArea= null; 947 fInformation= null; 948 computeInformation(); 949 } 950 951 956 protected void presentInformation() { 957 boolean hasContents= false; 958 if (fInformation instanceof String ) 959 hasContents= ((String )fInformation).trim().length() > 0; 960 else 961 hasContents= (fInformation != null); 962 963 if (fSubjectArea != null && hasContents) 964 internalShowInformationControl(fSubjectArea, fInformation); 965 else 966 hideInformationControl(); 967 } 968 969 976 private void internalShowInformationControl(Rectangle subjectArea, Object information) { 977 978 IInformationControl informationControl= getInformationControl(); 979 if (informationControl != null) { 980 981 Point sizeConstraints= computeSizeConstraints(fSubjectControl, fSubjectArea, informationControl); 982 informationControl.setSizeConstraints(sizeConstraints.x, sizeConstraints.y); 983 984 if (informationControl instanceof IInformationControlExtension2) 985 ((IInformationControlExtension2)informationControl).setInput(information); 986 else 987 informationControl.setInformation(information.toString()); 988 989 if (informationControl instanceof IInformationControlExtension) { 990 IInformationControlExtension extension= (IInformationControlExtension)informationControl; 991 if (!extension.hasContents()) 992 return; 993 } 994 995 Point size= null; 996 Point location= null; 997 Rectangle bounds= restoreInformationControlBounds(); 998 999 if (bounds != null) { 1000 if (bounds.x > -1 && bounds.y > -1) 1001 location= Geometry.getLocation(bounds); 1002 1003 if (bounds.width > -1 && bounds.height > -1) 1004 size= Geometry.getSize(bounds); 1005 } 1006 1007 if (size == null) 1008 size= informationControl.computeSizeHint(); 1009 1010 if (fEnforceAsMinimalSize) 1011 size= Geometry.max(size, sizeConstraints); 1012 if (fEnforceAsMaximalSize) 1013 size= Geometry.min(size, sizeConstraints); 1014 1015 if (location == null) 1016 location= computeInformationControlLocation(subjectArea, size); 1017 1018 Rectangle controlBounds= Geometry.createRectangle(location, size); 1020 Rectangle monitorBounds= getClosestMonitor(fSubjectControl.getDisplay(), controlBounds).getClientArea(); 1021 controlBounds.intersect(monitorBounds); 1022 1023 informationControl.setLocation(location); 1024 informationControl.setSize(size.x, size.y); 1025 1026 showInformationControl(subjectArea); 1027 } 1028 } 1029 1030 1033 protected void hideInformationControl() { 1034 if (fInformationControl != null) { 1035 storeInformationControlBounds(); 1036 fInformationControl.setVisible(false); 1037 if (fInformationControlCloser != null) 1038 fInformationControlCloser.stop(); 1039 } 1040 } 1041 1042 1048 protected void showInformationControl(Rectangle subjectArea) { 1049 fInformationControl.setVisible(true); 1050 1051 if (fTakesFocusWhenVisible) 1052 fInformationControl.setFocus(); 1053 1054 if (fInformationControlCloser != null) 1055 fInformationControlCloser.start(subjectArea); 1056 } 1057 1058 1061 public void disposeInformationControl() { 1062 if (fInformationControl != null) { 1063 fInformationControl.dispose(); 1064 handleInformationControlDisposed(); 1065 } 1066 } 1067 1068 1072 public void dispose() { 1073 if (!fDisposed) { 1074 1075 fDisposed= true; 1076 1077 setEnabled(false); 1078 disposeInformationControl(); 1079 1080 if (fSubjectControl != null && !fSubjectControl.isDisposed() && fSubjectControlDisposeListener != null) 1081 fSubjectControl.removeDisposeListener(fSubjectControlDisposeListener); 1082 fSubjectControl= null; 1083 fSubjectControlDisposeListener= null; 1084 1085 fIsCustomInformationControl= false; 1086 fCustomInformationControlCreator= null; 1087 fInformationControlCreator= null; 1088 fInformationControlCloser= null; 1089 } 1090 } 1091 1092 1094 1099 protected void storeInformationControlBounds() { 1100 if (fDialogSettings == null || fInformationControl == null || !(fIsRestoringLocation || fIsRestoringSize)) 1101 return; 1102 1103 if (!(fInformationControl instanceof IInformationControlExtension3)) 1104 throw new UnsupportedOperationException (); 1105 1106 boolean controlRestoresSize= ((IInformationControlExtension3)fInformationControl).restoresSize(); 1107 boolean controlRestoresLocation= ((IInformationControlExtension3)fInformationControl).restoresLocation(); 1108 1109 Rectangle bounds= ((IInformationControlExtension3)fInformationControl).getBounds(); 1110 if (bounds == null) 1111 return; 1112 1113 if (fIsRestoringSize && controlRestoresSize) { 1114 fDialogSettings.put(STORE_SIZE_WIDTH, bounds.width); 1115 fDialogSettings.put(STORE_SIZE_HEIGHT, bounds.height); 1116 } 1117 if (fIsRestoringLocation && controlRestoresLocation) { 1118 fDialogSettings.put(STORE_LOCATION_X, bounds.x); 1119 fDialogSettings.put(STORE_LOCATION_Y, bounds.y); 1120 } 1121 } 1122 1128 protected Rectangle restoreInformationControlBounds() { 1129 if (fDialogSettings == null || !(fIsRestoringLocation || fIsRestoringSize)) 1130 return null; 1131 1132 if (!(fInformationControl instanceof IInformationControlExtension3)) 1133 throw new UnsupportedOperationException (); 1134 1135 boolean controlRestoresSize= ((IInformationControlExtension3)fInformationControl).restoresSize(); 1136 boolean controlRestoresLocation= ((IInformationControlExtension3)fInformationControl).restoresLocation(); 1137 1138 Rectangle bounds= new Rectangle(-1, -1, -1, -1); 1139 1140 if (fIsRestoringSize && controlRestoresSize) { 1141 try { 1142 bounds.width= fDialogSettings.getInt(STORE_SIZE_WIDTH); 1143 bounds.height= fDialogSettings.getInt(STORE_SIZE_HEIGHT); 1144 } catch (NumberFormatException ex) { 1145 bounds.width= -1; 1146 bounds.height= -1; 1147 } 1148 } 1149 1150 if (fIsRestoringLocation && controlRestoresLocation) { 1151 try { 1152 bounds.x= fDialogSettings.getInt(STORE_LOCATION_X); 1153 bounds.y= fDialogSettings.getInt(STORE_LOCATION_Y); 1154 } catch (NumberFormatException ex) { 1155 bounds.x= -1; 1156 bounds.y= -1; 1157 } 1158 } 1159 1160 if (bounds.x == -1 && bounds.y == -1 && bounds.width == -1 && bounds.height == -1) 1162 return null; 1163 1164 Rectangle maxBounds= null; 1165 if (fSubjectControl != null && !fSubjectControl.isDisposed()) 1166 maxBounds= fSubjectControl.getDisplay().getBounds(); 1167 else { 1168 Display display= Display.getCurrent(); 1170 if (display == null) 1171 display= Display.getDefault(); 1172 if (display != null && !display.isDisposed()) 1173 maxBounds= display.getBounds(); 1174 } 1175 1176 1177 if (bounds.width > -1 && bounds.height > -1) { 1178 if (maxBounds != null) { 1179 bounds.width= Math.min(bounds.width, maxBounds.width); 1180 bounds.height= Math.min(bounds.height, maxBounds.height); 1181 } 1182 1183 bounds.width= Math.max(bounds.width, 30); 1185 bounds.height= Math.max(bounds.height, 30); 1186 } 1187 1188 if (bounds.x > -1 && bounds.y > -1 && maxBounds != null) { 1189 bounds.x= Math.max(bounds.x, maxBounds.x); 1190 bounds.y= Math.max(bounds.y, maxBounds.y); 1191 1192 if (bounds .width > -1 && bounds.height > -1) { 1193 bounds.x= Math.min(bounds.x, maxBounds.width - bounds.width); 1194 bounds.y= Math.min(bounds.y, maxBounds.height - bounds.height); 1195 } 1196 } 1197 1198 return bounds; 1199 } 1200} 1201 | Popular Tags |