1 11 package org.eclipse.ui.internal.layout; 12 13 import java.util.ArrayList ; 14 import java.util.Collections ; 15 import java.util.HashMap ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Map ; 19 20 import org.eclipse.jface.preference.IPreferenceStore; 21 import org.eclipse.jface.util.Geometry; 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.custom.CBanner; 24 import org.eclipse.swt.events.DisposeEvent; 25 import org.eclipse.swt.events.DisposeListener; 26 import org.eclipse.swt.graphics.Point; 27 import org.eclipse.swt.graphics.Rectangle; 28 import org.eclipse.swt.widgets.Composite; 29 import org.eclipse.swt.widgets.Control; 30 import org.eclipse.swt.widgets.Layout; 31 import org.eclipse.ui.IWorkbenchPreferenceConstants; 32 import org.eclipse.ui.PlatformUI; 33 import org.eclipse.ui.internal.TrimDragPreferences; 34 35 64 public class TrimLayout extends Layout implements ICachingLayout, ITrimManager { 65 66 69 public static final Integer TOP_ID = new Integer (TOP); 70 71 74 public static final Integer BOTTOM_ID = new Integer (BOTTOM); 75 76 79 public static final Integer LEFT_ID = new Integer (LEFT); 80 81 84 public static final Integer RIGHT_ID = new Integer (RIGHT); 85 86 89 public static final Integer NONTRIM_ID = new Integer (NONTRIM); 90 91 94 private static final int[] TRIM_ID_INFO = { LEFT, RIGHT, TOP, BOTTOM }; 95 96 private SizeCache centerArea = new SizeCache(); 97 98 101 private Map fTrimArea = new HashMap (); 102 103 106 private Map fTrimDescriptors = new HashMap (); 107 108 private int marginWidth; 109 110 private int marginHeight; 111 112 private int topSpacing; 113 114 private int bottomSpacing; 115 116 private int leftSpacing; 117 118 private int rightSpacing; 119 120 private int spacing = 3; 121 122 private boolean trimLocked; 123 124 private HashMap preferredLocationMap = new HashMap (); 125 126 129 public TrimLayout() { 130 final IPreferenceStore store = PlatformUI.getPreferenceStore(); 132 trimLocked = store.getBoolean(IWorkbenchPreferenceConstants.LOCK_TRIM); 133 134 createTrimArea(TOP_ID, TOP_ID.toString(), SWT.DEFAULT, SWT.TOP); 135 createTrimArea(BOTTOM_ID, BOTTOM_ID.toString(), SWT.DEFAULT, SWT.BOTTOM); 136 createTrimArea(LEFT_ID, LEFT_ID.toString(), SWT.DEFAULT, SWT.LEFT); 137 createTrimArea(RIGHT_ID, RIGHT_ID.toString(), SWT.DEFAULT, SWT.RIGHT); 138 } 139 140 private void createTrimArea(Integer id, String displayName, int trimSize, 141 int trimMods) { 142 TrimArea top = new TrimArea(id.intValue(), displayName); 143 top.setTrimSize(trimSize); 144 top.setControlModifiers(trimMods); 145 fTrimArea.put(id, top); 146 } 147 148 161 public void setSpacing(int left, int right, int top, int bottom) { 162 leftSpacing = left; 163 rightSpacing = right; 164 topSpacing = top; 165 bottomSpacing = bottom; 166 } 167 168 175 public void setMargins(int marginWidth, int marginHeight) { 176 this.marginWidth = marginWidth; 177 this.marginHeight = marginHeight; 178 } 179 180 190 public void setTrimSize(int areaId, int size) { 191 TrimArea area = (TrimArea) fTrimArea.get(new Integer (areaId)); 192 if (area != null) { 193 area.setTrimSize(size); 194 } 195 } 196 197 209 public int getTrimAreaId(Control trimControl) { 210 TrimDescriptor desc = findTrimDescription(trimControl); 211 if (desc != null) { 212 return desc.getAreaId(); 213 } 214 return SWT.DEFAULT; 215 } 216 217 225 public void addTrim(IWindowTrim control, int areaId) { 226 addTrim(areaId, control, null); 227 } 228 229 242 public void addTrim(IWindowTrim trim, int areaId, IWindowTrim beforeMe) { 243 addTrim(areaId, trim, beforeMe); 244 } 245 246 252 public void addTrim(int areaId, IWindowTrim trim) { 253 IWindowTrim insertBefore = null; 256 List trimDescs = getAreaTrim(areaId); 257 for (Iterator trimIter = trimDescs.iterator(); trimIter.hasNext();) { 258 IWindowTrim curTrim = (IWindowTrim) trimIter.next(); 259 if (curTrim.getId().equals(trim.getId())) { 260 if (trimIter.hasNext()) { 261 insertBefore = (IWindowTrim) trimIter.next(); 262 } 263 } 264 } 265 266 addTrim(areaId, trim, insertBefore); 267 } 268 269 276 public void addTrim(int areaId, IWindowTrim trim, IWindowTrim beforeMe) { 277 TrimArea area = (TrimArea) fTrimArea.get(new Integer (areaId)); 278 if (area == null) { 279 return; 280 } 281 282 removeTrim(trim); 284 285 TrimDescriptor desc = new TrimDescriptor(trim, areaId); 287 288 boolean isAlreadyAHandle = trim instanceof TrimToolBarBase; 290 if (!trimLocked && trim.getValidSides() != SWT.NONE && !isAlreadyAHandle) { 291 Composite dockingHandle = new TrimCommonUIHandle(this, trim, areaId); 293 desc.setDockingCache(new SizeCache(dockingHandle)); 294 } 295 296 SizeCache cache = new SizeCache(trim.getControl()); 298 trim.getControl().setLayoutData(trim); 299 desc.setCache(cache); 300 301 trim.getControl().addDisposeListener(new DisposeListener() { 303 public void widgetDisposed(DisposeEvent e) { 304 Control control = (Control) e.widget; 305 if (control.getLayoutData() instanceof IWindowTrim) { 306 IWindowTrim trim = (IWindowTrim) control.getLayoutData(); 307 removeTrim(trim); 308 } 310 } 311 }); 312 313 fTrimDescriptors.put(desc.getId(), desc); 315 316 if (beforeMe != null) { 318 TrimDescriptor beforeDesc = (TrimDescriptor) fTrimDescriptors 319 .get(beforeMe.getId()); 320 if (beforeDesc != null && beforeDesc.getAreaId() == areaId) { 321 area.addTrim(desc, beforeDesc); 322 } else { 323 area.addTrim(desc); 324 } 325 } else { 326 area.addTrim(desc); 327 } 328 } 329 330 333 public void forceLayout() { 334 removeDisposed(); 335 336 Iterator d = fTrimDescriptors.values().iterator(); 339 while (d.hasNext()) { 340 TrimDescriptor desc = (TrimDescriptor) d.next(); 341 if (desc.getTrim().getControl() != null) { 342 LayoutUtil.resize(desc.getTrim().getControl()); 343 return; 344 } 345 } 346 } 347 348 353 public void removeTrim(IWindowTrim toRemove) { 354 TrimDescriptor desc = (TrimDescriptor) fTrimDescriptors.remove(toRemove 355 .getId()); 356 if (desc == null) { 357 return; 358 } 359 360 TrimArea area = (TrimArea) fTrimArea.get(new Integer (desc.getAreaId())); 361 if (area != null) { 362 area.removeTrim(desc); 363 desc.getCache().getControl().setLayoutData(null); 364 } 365 366 if (desc.getDockingCache() != null) { 368 Control ctrl = desc.getDockingCache().getControl(); 369 370 ctrl.setVisible(false); 373 desc.setDockingCache(null); 375 } 376 } 377 378 383 public IWindowTrim getTrim(String id) { 384 TrimDescriptor desc = (TrimDescriptor) fTrimDescriptors.get(id); 385 if (desc != null) { 386 return desc.getTrim(); 387 } 388 return null; 389 } 390 391 395 private void removeDisposed() { 396 Iterator a = fTrimArea.values().iterator(); 397 while (a.hasNext()) { 398 TrimArea area = (TrimArea) a.next(); 399 Iterator d = area.getDescriptors().iterator(); 400 while (d.hasNext()) { 401 TrimDescriptor desc = (TrimDescriptor) d.next(); 402 Control nextControl = desc.getTrim().getControl(); 403 if (nextControl == null || nextControl.isDisposed()) { 404 area.removeTrim(desc); 406 407 fTrimDescriptors.remove(desc.getId()); 409 } 410 } 411 } 412 } 413 414 420 protected Point computeSize(Composite composite, int wHint, int hHint, 421 boolean flushCache) { 422 Point result = new Point(wHint, hHint); 423 424 TrimArea top = (TrimArea) fTrimArea.get(TOP_ID); 425 TrimArea bottom = (TrimArea) fTrimArea.get(BOTTOM_ID); 426 TrimArea left = (TrimArea) fTrimArea.get(LEFT_ID); 427 TrimArea right = (TrimArea) fTrimArea.get(RIGHT_ID); 428 429 int horizontalTrim = left.calculateTrimSize(wHint, hHint) 430 + right.calculateTrimSize(wHint, hHint) + (2 * marginWidth) 431 + leftSpacing + rightSpacing; 432 int verticalTrim = top.calculateTrimSize(wHint, hHint) 433 + bottom.calculateTrimSize(wHint, hHint) + (2 * marginHeight) 434 + topSpacing + bottomSpacing; 435 436 Point innerSize = centerArea.computeSize(wHint == SWT.DEFAULT ? wHint 437 : wHint - horizontalTrim, hHint == SWT.DEFAULT ? hHint : hHint 438 - verticalTrim); 439 440 if (wHint == SWT.DEFAULT) { 441 result.x = innerSize.x + horizontalTrim; 442 } else if (hHint == SWT.DEFAULT) { 443 result.y = innerSize.y + verticalTrim; 444 } 445 446 455 return new Point(0, 0); 456 } 457 458 464 protected void layout(Composite composite, boolean flushCache) { 465 removeDisposed(); 466 467 TrimArea top = (TrimArea) fTrimArea.get(TOP_ID); 468 TrimArea bottom = (TrimArea) fTrimArea.get(BOTTOM_ID); 469 TrimArea left = (TrimArea) fTrimArea.get(LEFT_ID); 470 TrimArea right = (TrimArea) fTrimArea.get(RIGHT_ID); 471 472 Rectangle clientArea = composite.getClientArea(); 473 474 clientArea.x += marginWidth; 475 clientArea.width -= 2 * marginWidth; 476 clientArea.y += marginHeight; 477 clientArea.height -= 2 * marginHeight; 478 479 int trim_top = top.calculateTrimSize(clientArea.width, 481 clientArea.height); 482 int trim_bottom = bottom.calculateTrimSize(clientArea.width, 483 clientArea.height); 484 int trim_left = left.calculateTrimSize(clientArea.width, 485 clientArea.height); 486 int trim_right = right.calculateTrimSize(clientArea.width, 487 clientArea.height); 488 489 int leftOfLayout = clientArea.x; 491 int leftOfCenterPane = leftOfLayout + trim_left + leftSpacing; 492 int widthOfCenterPane = clientArea.width - trim_left - trim_right 493 - leftSpacing - rightSpacing; 494 int rightOfCenterPane = clientArea.x + clientArea.width - trim_right; 495 496 503 int topOfLayout = clientArea.y; 506 trim_top = arrange(new Rectangle(leftOfLayout, topOfLayout, clientArea.width, 507 trim_top), top.getCaches(), !top.isVertical(), spacing); 508 509 int topOfCenterPane = topOfLayout + trim_top + topSpacing; 512 int heightOfCenterPane = clientArea.height - trim_top - trim_bottom 513 - topSpacing - bottomSpacing; 514 int bottomOfCenterPane = clientArea.y + clientArea.height - trim_bottom; 515 516 arrange(new Rectangle(leftOfCenterPane, bottomOfCenterPane, 517 widthOfCenterPane, trim_bottom), bottom.getCaches(), !bottom 518 .isVertical(), spacing); 519 arrange(new Rectangle(leftOfLayout, topOfCenterPane, trim_left, 520 clientArea.height - trim_top), left.getCaches(), !left 521 .isVertical(), spacing); 522 arrange(new Rectangle(rightOfCenterPane, topOfCenterPane, trim_right, 523 clientArea.height - trim_top), right.getCaches(), !right 524 .isVertical(), spacing); 525 526 if (centerArea.getControl() != null) { 527 centerArea.getControl().setBounds(leftOfCenterPane, 528 topOfCenterPane, widthOfCenterPane, heightOfCenterPane); 529 } 530 } 531 532 545 private static int arrange(Rectangle area, List caches, 546 boolean horizontally, int spacing) { 547 Point currentPosition = new Point(area.x, area.y); 548 549 List resizable = new ArrayList (caches.size()); 550 List nonResizable = new ArrayList (caches.size()); 551 552 TrimArea.filterResizable(caches, resizable, nonResizable, horizontally); 553 554 int[] sizes = new int[nonResizable.size()]; 555 556 int idx = 0; 557 int used = 0; 558 int hint = Geometry.getDimension(area, !horizontally); 559 560 Iterator iter = nonResizable.iterator(); 562 563 while (iter.hasNext()) { 564 SizeCache next = (SizeCache) iter.next(); 565 566 sizes[idx] = TrimArea.getSize(next, hint, horizontally); 567 used += sizes[idx]; 568 idx++; 569 } 570 571 int available = Geometry.getDimension(area, horizontally) - used 572 - spacing * (caches.size() - 1); 573 idx = 0; 574 int remainingResizable = resizable.size(); 575 576 iter = caches.iterator(); 577 578 while (iter.hasNext()) { 579 SizeCache next = (SizeCache) iter.next(); 580 if (next.getControl().isVisible()) { 581 582 int thisSize; 583 if (TrimArea.isResizable(next.getControl(), horizontally)) { 584 thisSize = available / remainingResizable; 585 available -= thisSize; 586 remainingResizable--; 587 } else { 588 thisSize = sizes[idx]; 589 idx++; 590 } 591 592 if (TrimDragPreferences.showRaggedTrim()) { 593 Point prefSize = next.computeSize(SWT.DEFAULT, SWT.DEFAULT); 594 if (horizontally) { 595 if (next.getControl() instanceof CBanner) { 602 prefSize = next.getControl().computeSize(thisSize, SWT.DEFAULT); 603 if (prefSize.y > hint) 604 hint = prefSize.y; 605 } 606 607 next.getControl().setBounds(currentPosition.x, 608 currentPosition.y, thisSize, prefSize.y); 609 currentPosition.x += thisSize + spacing; 610 } else { 611 next.getControl().setBounds(currentPosition.x, 612 currentPosition.y, prefSize.x, thisSize); 613 currentPosition.y += thisSize + spacing; 614 } 615 } 616 else { 617 if (horizontally) { 618 next.getControl().setBounds(currentPosition.x, 619 currentPosition.y, thisSize, hint); 620 currentPosition.x += thisSize + spacing; 621 } else { 622 next.getControl().setBounds(currentPosition.x, 623 currentPosition.y, hint, thisSize); 624 currentPosition.y += thisSize + spacing; 625 } 626 } 627 } 628 } 629 630 return hint; 631 } 632 633 642 public void setCenterControl(Control center) { 643 centerArea.setControl(center); 644 } 645 646 651 public Control getCenterControl() { 652 return centerArea.getControl(); 653 } 654 655 660 public void flush(Control dirtyControl) { 661 if (dirtyControl == centerArea.getControl()) { 662 centerArea.flush(); 663 } else { 664 TrimDescriptor desc = findTrimDescription(dirtyControl); 665 if (desc != null) { 666 desc.flush(); 667 } 668 } 669 } 670 671 676 public int[] getAreaIds() { 677 return (int[]) TRIM_ID_INFO.clone(); 678 } 679 680 685 public List getAreaTrim(int areaId) { 686 TrimArea area = (TrimArea) fTrimArea.get(new Integer (areaId)); 687 if (area == null) { 688 return Collections.EMPTY_LIST; 689 } 690 return area.getTrims(); 691 } 692 693 699 public void updateAreaTrim(int id, List trim, boolean removeExtra) { 700 TrimArea area = (TrimArea) fTrimArea.get(new Integer (id)); 701 if (area == null) { 702 return; 703 } 704 List current = area.getTrims(); 705 706 Iterator i = trim.iterator(); 709 while (i.hasNext()) { 710 IWindowTrim t = (IWindowTrim) i.next(); 711 t.dock(id); addTrim(id, t, null); 713 current.remove(t); 714 } 715 716 if (removeExtra) { 717 i = current.iterator(); 720 while (i.hasNext()) { 721 IWindowTrim t = (IWindowTrim) i.next(); 722 removeTrim(t); 723 } 724 } 725 } 726 727 738 public Rectangle getTrimRect(Composite window, int areaId) { 739 Rectangle bb = window.getBounds(); 740 741 Rectangle cr = window.getClientArea(); 742 Rectangle tr = window.computeTrim(cr.x, cr.y, cr.width, cr.height); 743 744 Geometry.moveRectangle(cr, new Point(bb.x - tr.x, bb.y - tr.y)); 746 747 TrimArea top = (TrimArea) fTrimArea.get(TOP_ID); 748 TrimArea bottom = (TrimArea) fTrimArea.get(BOTTOM_ID); 749 TrimArea left = (TrimArea) fTrimArea.get(LEFT_ID); 750 TrimArea right = (TrimArea) fTrimArea.get(RIGHT_ID); 751 752 int trim_top = top.calculateTrimSize(cr.width, cr.height); 753 int trim_bottom = bottom.calculateTrimSize(cr.width, cr.height); 754 int trim_left = left.calculateTrimSize(cr.width, cr.height); 755 int trim_right = right.calculateTrimSize(cr.width, cr.height); 756 757 if (trim_top == 0) { 760 trim_top = marginHeight; 761 } 762 if (trim_bottom == 0) { 763 trim_bottom = marginHeight; 764 } 765 if (trim_left == 0) { 766 trim_left = marginWidth; 767 } 768 if (trim_right == 0) { 769 trim_right = marginWidth; 770 } 771 772 Rectangle trimRect = new Rectangle(0, 0, 0, 0); 773 switch (areaId) { 774 case TOP: 775 trimRect.x = cr.x; 776 trimRect.width = cr.width; 777 trimRect.y = cr.y; 778 trimRect.height = trim_top; 779 break; 780 case BOTTOM: 781 trimRect.x = cr.x; 782 trimRect.width = cr.width; 783 trimRect.y = (cr.y + cr.height) - trim_bottom; 784 trimRect.height = trim_bottom; 785 break; 786 case LEFT: 787 trimRect.x = cr.x; 788 trimRect.width = trim_left; 789 trimRect.y = cr.y + trim_top; 790 trimRect.height = cr.height - (trim_top + trim_bottom); 791 break; 792 case RIGHT: 793 trimRect.x = (cr.x + cr.width) - trim_right; 794 trimRect.width = trim_right; 795 trimRect.y = cr.y + trim_top; 796 trimRect.height = cr.height - (trim_top + trim_bottom); 797 break; 798 } 799 800 return trimRect; 801 } 802 803 808 public List getAllTrim() { 809 List trimList = new ArrayList (fTrimDescriptors.size()); 810 811 Iterator d = fTrimDescriptors.values().iterator(); 812 while (d.hasNext()) { 813 TrimDescriptor desc = (TrimDescriptor) d.next(); 814 trimList.add(desc.getTrim()); 815 } 816 817 return trimList; 818 } 819 820 826 public void setTrimVisible(IWindowTrim trim, boolean visible) { 827 TrimDescriptor desc = findTrimDescription(trim.getControl()); 828 829 if (desc != null) { 830 desc.setVisible(visible); 831 } 832 } 833 834 842 private TrimDescriptor findTrimDescription(Control trim) { 843 Iterator d = fTrimDescriptors.values().iterator(); 844 while (d.hasNext()) { 845 TrimDescriptor desc = (TrimDescriptor) d.next(); 846 if (desc.getTrim().getControl() == trim) { 847 return desc; 848 } 849 if (desc.getDockingCache() != null 850 && desc.getDockingCache().getControl() == trim) { 851 return desc; 852 } 853 } 854 return null; 855 } 856 857 864 public TrimArea getTrimArea(int areaId) { 865 return (TrimArea) fTrimArea.get(new Integer (areaId)); 866 } 867 868 875 public void setPreferredLocations(int areaId, List preferredLocations) { 876 preferredLocationMap.put(new Integer (areaId), preferredLocations); 877 } 878 879 885 public int getPreferredArea(String trimId) { 886 Iterator keyIter = preferredLocationMap.keySet().iterator(); 887 while (keyIter.hasNext()) { 888 Integer key = (Integer ) keyIter.next(); 889 List areaList = (List ) preferredLocationMap.get(key); 890 if (areaList.contains(trimId)) 891 return key.intValue(); 892 } 893 894 return -1; 895 } 896 897 905 public IWindowTrim getPreferredLocation(String trimId) { 906 Iterator keyIter = preferredLocationMap.keySet().iterator(); 907 while (keyIter.hasNext()) { 908 Integer key = (Integer ) keyIter.next(); 909 List areaList = (List ) preferredLocationMap.get(key); 910 int index = areaList.indexOf(trimId); 911 if (index != -1) { 912 for (int i = index+1; i < areaList.size(); i++) { 916 String id = (String ) areaList.get(i); 917 IWindowTrim trim = getTrim(id); 918 if (trim != null) 919 return trim; 920 } 921 } 922 } 923 924 return null; 925 } 926 927 942 public List disableTrim(IWindowTrim ignoreMe) { 943 List disabledControls = new ArrayList (); 944 945 List allTrim = getAllTrim(); 947 for (Iterator trimIter = allTrim.iterator(); trimIter.hasNext();) { 948 IWindowTrim trim = (IWindowTrim) trimIter.next(); 949 if (ignoreMe == trim) 950 continue; 951 952 Control ctrl = trim.getControl(); 953 if (ctrl == null || ctrl.isDisposed() || !ctrl.isVisible() || !ctrl.isEnabled()) 954 continue; 955 956 ctrl.setEnabled(false); 957 disabledControls.add(ctrl); 958 } 959 960 return disabledControls; 961 } 962 963 968 public void enableTrim(List disabledControls) { 969 for (Iterator dcIter = disabledControls.iterator(); dcIter.hasNext();) { 971 Control ctrl = (Control) dcIter.next(); 972 973 if (!ctrl.isDisposed() && !ctrl.isEnabled()) 974 ctrl.setEnabled(true); 975 } 976 } 977 } 978 | Popular Tags |