1 11 package org.eclipse.jdt.internal.ui.wizards.dialogfields; 12 13 import java.util.ArrayList ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 17 import org.eclipse.core.runtime.Assert; 18 19 import org.eclipse.swt.SWT; 20 import org.eclipse.swt.events.KeyAdapter; 21 import org.eclipse.swt.events.KeyEvent; 22 import org.eclipse.swt.events.SelectionEvent; 23 import org.eclipse.swt.events.SelectionListener; 24 import org.eclipse.swt.layout.GridData; 25 import org.eclipse.swt.layout.GridLayout; 26 import org.eclipse.swt.widgets.Button; 27 import org.eclipse.swt.widgets.Composite; 28 import org.eclipse.swt.widgets.Control; 29 import org.eclipse.swt.widgets.Display; 30 import org.eclipse.swt.widgets.Label; 31 import org.eclipse.swt.widgets.Tree; 32 33 import org.eclipse.jface.viewers.DoubleClickEvent; 34 import org.eclipse.jface.viewers.IDoubleClickListener; 35 import org.eclipse.jface.viewers.ILabelProvider; 36 import org.eclipse.jface.viewers.ISelection; 37 import org.eclipse.jface.viewers.ISelectionChangedListener; 38 import org.eclipse.jface.viewers.IStructuredSelection; 39 import org.eclipse.jface.viewers.ITreeContentProvider; 40 import org.eclipse.jface.viewers.SelectionChangedEvent; 41 import org.eclipse.jface.viewers.StructuredSelection; 42 import org.eclipse.jface.viewers.TreeViewer; 43 import org.eclipse.jface.viewers.Viewer; 44 import org.eclipse.jface.viewers.ViewerComparator; 45 46 import org.eclipse.jdt.internal.ui.util.PixelConverter; 47 import org.eclipse.jdt.internal.ui.util.SWTUtil; 48 49 55 public class TreeListDialogField extends DialogField { 56 57 protected TreeViewer fTree; 58 protected ILabelProvider fLabelProvider; 59 protected TreeViewerAdapter fTreeViewerAdapter; 60 protected List fElements; 61 protected ViewerComparator fViewerComparator; 62 63 protected String [] fButtonLabels; 64 private Button[] fButtonControls; 65 66 private boolean[] fButtonsEnabled; 67 68 private int fRemoveButtonIndex; 69 private int fUpButtonIndex; 70 private int fDownButtonIndex; 71 72 private Label fLastSeparator; 73 74 private Tree fTreeControl; 75 private Composite fButtonsControl; 76 private ISelection fSelectionWhenEnabled; 77 78 private ITreeListAdapter fTreeAdapter; 79 80 private Object fParentElement; 81 private int fTreeExpandLevel; 82 83 86 public TreeListDialogField(ITreeListAdapter adapter, String [] buttonLabels, ILabelProvider lprovider) { 87 super(); 88 fTreeAdapter= adapter; 89 90 fLabelProvider= lprovider; 91 fTreeViewerAdapter= new TreeViewerAdapter(); 92 fParentElement= this; 93 94 fElements= new ArrayList (10); 95 96 fButtonLabels= buttonLabels; 97 if (fButtonLabels != null) { 98 int nButtons= fButtonLabels.length; 99 fButtonsEnabled= new boolean[nButtons]; 100 for (int i= 0; i < nButtons; i++) { 101 fButtonsEnabled[i]= true; 102 } 103 } 104 105 fTree= null; 106 fTreeControl= null; 107 fButtonsControl= null; 108 109 fRemoveButtonIndex= -1; 110 fUpButtonIndex= -1; 111 fDownButtonIndex= -1; 112 113 fTreeExpandLevel= 0; 114 } 115 116 122 public void setRemoveButtonIndex(int removeButtonIndex) { 123 Assert.isTrue(removeButtonIndex < fButtonLabels.length); 124 fRemoveButtonIndex= removeButtonIndex; 125 } 126 127 133 public void setUpButtonIndex(int upButtonIndex) { 134 Assert.isTrue(upButtonIndex < fButtonLabels.length); 135 fUpButtonIndex= upButtonIndex; 136 } 137 138 144 public void setDownButtonIndex(int downButtonIndex) { 145 Assert.isTrue(downButtonIndex < fButtonLabels.length); 146 fDownButtonIndex= downButtonIndex; 147 } 148 149 153 public void setViewerComparator(ViewerComparator viewerComparator) { 154 fViewerComparator= viewerComparator; 155 } 156 157 public void setTreeExpansionLevel(int level) { 158 fTreeExpandLevel= level; 159 if (isOkToUse(fTreeControl) && fTreeExpandLevel > 0) { 160 fTree.expandToLevel(level); 161 } 162 } 163 164 166 private void buttonPressed(int index) { 167 if (!managedButtonPressed(index) && fTreeAdapter != null) { 168 fTreeAdapter.customButtonPressed(this, index); 169 } 170 } 171 172 176 protected boolean managedButtonPressed(int index) { 177 if (index == fRemoveButtonIndex) { 178 remove(); 179 } else if (index == fUpButtonIndex) { 180 up(); 181 } else if (index == fDownButtonIndex) { 182 down(); 183 } else { 184 return false; 185 } 186 return true; 187 } 188 189 191 194 public Control[] doFillIntoGrid(Composite parent, int nColumns) { 195 PixelConverter converter= new PixelConverter(parent); 196 197 assertEnoughColumns(nColumns); 198 199 Label label= getLabelControl(parent); 200 GridData gd= gridDataForLabel(1); 201 gd.verticalAlignment= GridData.BEGINNING; 202 label.setLayoutData(gd); 203 204 Control list= getTreeControl(parent); 205 gd= new GridData(); 206 gd.horizontalAlignment= GridData.FILL; 207 gd.grabExcessHorizontalSpace= false; 208 gd.verticalAlignment= GridData.FILL; 209 gd.grabExcessVerticalSpace= true; 210 gd.horizontalSpan= nColumns - 2; 211 gd.widthHint= converter.convertWidthInCharsToPixels(50); 212 gd.heightHint= converter.convertHeightInCharsToPixels(6); 213 214 list.setLayoutData(gd); 215 216 Composite buttons= getButtonBox(parent); 217 gd= new GridData(); 218 gd.horizontalAlignment= GridData.FILL; 219 gd.grabExcessHorizontalSpace= false; 220 gd.verticalAlignment= GridData.FILL; 221 gd.grabExcessVerticalSpace= true; 222 gd.horizontalSpan= 1; 223 buttons.setLayoutData(gd); 224 225 return new Control[] { label, list, buttons }; 226 } 227 228 231 public int getNumberOfControls() { 232 return 3; 233 } 234 235 238 public void setButtonsMinWidth(int minWidth) { 239 if (fLastSeparator != null) { 240 ((GridData) fLastSeparator.getLayoutData()).widthHint= minWidth; 241 } 242 } 243 244 246 252 public Control getTreeControl(Composite parent) { 253 if (fTreeControl == null) { 254 assertCompositeNotNull(parent); 255 256 fTree= createTreeViewer(parent); 257 258 fTreeControl= (Tree) fTree.getControl(); 259 fTreeControl.addKeyListener(new KeyAdapter() { 260 public void keyPressed(KeyEvent e) { 261 handleKeyPressed(e); 262 } 263 }); 264 fTree.setContentProvider(fTreeViewerAdapter); 265 fTree.setLabelProvider(fLabelProvider); 266 fTree.addSelectionChangedListener(fTreeViewerAdapter); 267 fTree.addDoubleClickListener(fTreeViewerAdapter); 268 269 fTree.setInput(fParentElement); 270 fTree.expandToLevel(fTreeExpandLevel); 271 272 if (fViewerComparator != null) { 273 fTree.setComparator(fViewerComparator); 274 } 275 276 fTreeControl.setEnabled(isEnabled()); 277 if (fSelectionWhenEnabled != null) { 278 postSetSelection(fSelectionWhenEnabled); 279 } 280 } 281 return fTreeControl; 282 } 283 284 287 public TreeViewer getTreeViewer() { 288 return fTree; 289 } 290 291 294 protected int getTreeStyle() { 295 int style= SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL; 296 return style; 297 } 298 299 protected TreeViewer createTreeViewer(Composite parent) { 300 Tree tree= new Tree(parent, getTreeStyle()); 301 tree.setFont(parent.getFont()); 302 return new TreeViewer(tree); 303 } 304 305 protected Button createButton(Composite parent, String label, SelectionListener listener) { 306 Button button= new Button(parent, SWT.PUSH); 307 button.setFont(parent.getFont()); 308 button.setText(label); 309 button.addSelectionListener(listener); 310 GridData gd= new GridData(); 311 gd.horizontalAlignment= GridData.FILL; 312 gd.grabExcessHorizontalSpace= true; 313 gd.verticalAlignment= GridData.BEGINNING; 314 gd.widthHint= SWTUtil.getButtonWidthHint(button); 315 316 button.setLayoutData(gd); 317 return button; 318 } 319 320 private Label createSeparator(Composite parent) { 321 Label separator= new Label(parent, SWT.NONE); 322 separator.setFont(parent.getFont()); 323 separator.setVisible(false); 324 GridData gd= new GridData(); 325 gd.horizontalAlignment= GridData.FILL; 326 gd.verticalAlignment= GridData.BEGINNING; 327 gd.heightHint= 4; 328 separator.setLayoutData(gd); 329 return separator; 330 } 331 332 338 public Composite getButtonBox(Composite parent) { 339 if (fButtonsControl == null) { 340 assertCompositeNotNull(parent); 341 342 SelectionListener listener= new SelectionListener() { 343 public void widgetDefaultSelected(SelectionEvent e) { 344 doButtonSelected(e); 345 } 346 public void widgetSelected(SelectionEvent e) { 347 doButtonSelected(e); 348 } 349 }; 350 351 Composite contents= new Composite(parent, SWT.NONE); 352 contents.setFont(parent.getFont()); 353 354 GridLayout layout= new GridLayout(); 355 layout.marginWidth= 0; 356 layout.marginHeight= 0; 357 contents.setLayout(layout); 358 359 if (fButtonLabels != null) { 360 fButtonControls= new Button[fButtonLabels.length]; 361 for (int i= 0; i < fButtonLabels.length; i++) { 362 String currLabel= fButtonLabels[i]; 363 if (currLabel != null) { 364 fButtonControls[i]= createButton(contents, currLabel, listener); 365 fButtonControls[i].setEnabled(isEnabled() && fButtonsEnabled[i]); 366 } else { 367 fButtonControls[i]= null; 368 createSeparator(contents); 369 } 370 } 371 } 372 373 fLastSeparator= createSeparator(contents); 374 375 updateButtonState(); 376 fButtonsControl= contents; 377 } 378 379 return fButtonsControl; 380 } 381 382 private void doButtonSelected(SelectionEvent e) { 383 if (fButtonControls != null) { 384 for (int i= 0; i < fButtonControls.length; i++) { 385 if (e.widget == fButtonControls[i]) { 386 buttonPressed(i); 387 return; 388 } 389 } 390 } 391 } 392 393 397 protected void handleKeyPressed(KeyEvent event) { 398 if (event.character == SWT.DEL && event.stateMask == 0) { 399 if (fRemoveButtonIndex != -1 && isButtonEnabled(fTree.getSelection(), fRemoveButtonIndex)) { 400 managedButtonPressed(fRemoveButtonIndex); 401 return; 402 } 403 } 404 fTreeAdapter.keyPressed(this, event); 405 } 406 407 409 412 public void dialogFieldChanged() { 413 super.dialogFieldChanged(); 414 updateButtonState(); 415 } 416 417 420 protected void updateButtonState() { 421 if (fButtonControls != null && isOkToUse(fTreeControl) && fTreeControl.isEnabled()) { 422 ISelection sel= fTree.getSelection(); 423 for (int i= 0; i < fButtonControls.length; i++) { 424 Button button= fButtonControls[i]; 425 if (isOkToUse(button)) { 426 button.setEnabled(isButtonEnabled(sel, i)); 427 } 428 } 429 } 430 } 431 432 433 protected boolean containsAttributes(List selected) { 434 for (int i= 0; i < selected.size(); i++) { 435 if (!fElements.contains(selected.get(i))) { 436 return true; 437 } 438 } 439 return false; 440 } 441 442 443 protected boolean getManagedButtonState(ISelection sel, int index) { 444 List selected= getSelectedElements(); 445 boolean hasAttributes= containsAttributes(selected); 446 if (index == fRemoveButtonIndex) { 447 return !selected.isEmpty() && !hasAttributes; 448 } else if (index == fUpButtonIndex) { 449 return !sel.isEmpty() && !hasAttributes && canMoveUp(selected); 450 } else if (index == fDownButtonIndex) { 451 return !sel.isEmpty() && !hasAttributes && canMoveDown(selected); 452 } 453 return true; 454 } 455 456 459 protected void updateEnableState() { 460 super.updateEnableState(); 461 462 boolean enabled= isEnabled(); 463 if (isOkToUse(fTreeControl)) { 464 if (!enabled) { 465 if (fSelectionWhenEnabled == null) { 466 fSelectionWhenEnabled= fTree.getSelection(); 467 selectElements(null); 468 } 469 } else if (fSelectionWhenEnabled != null) { 470 selectElements(fSelectionWhenEnabled); 471 } 472 fTreeControl.setEnabled(enabled); 473 } 474 updateButtonState(); 475 } 476 477 480 public void enableButton(int index, boolean enable) { 481 if (fButtonsEnabled != null && index < fButtonsEnabled.length) { 482 fButtonsEnabled[index]= enable; 483 updateButtonState(); 484 } 485 } 486 487 private boolean isButtonEnabled(ISelection sel, int index) { 488 boolean extraState= getManagedButtonState(sel, index); 489 return isEnabled() && extraState && fButtonsEnabled[index]; 490 } 491 492 494 497 public void setElements(List elements) { 498 fElements= new ArrayList (elements); 499 refresh(); 500 if (isOkToUse(fTreeControl)) { 501 fTree.expandToLevel(fTreeExpandLevel); 502 } 503 dialogFieldChanged(); 504 } 505 506 510 public List getElements() { 511 return new ArrayList (fElements); 512 } 513 514 517 public Object getElement(int index) { 518 return fElements.get(index); 519 } 520 521 524 public int getIndexOfElement(Object elem) { 525 return fElements.indexOf(elem); 526 } 527 528 531 public void replaceElement(Object oldElement, Object newElement) throws IllegalArgumentException { 532 int idx= fElements.indexOf(oldElement); 533 if (idx != -1) { 534 fElements.set(idx, newElement); 535 if (isOkToUse(fTreeControl)) { 536 List selected= getSelectedElements(); 537 if (selected.remove(oldElement)) { 538 selected.add(newElement); 539 } 540 boolean isExpanded= fTree.getExpandedState(oldElement); 541 fTree.remove(oldElement); 542 fTree.add(fParentElement, newElement); 543 if (isExpanded) { 544 fTree.expandToLevel(newElement, fTreeExpandLevel); 545 } 546 selectElements(new StructuredSelection(selected)); 547 } 548 dialogFieldChanged(); 549 } else { 550 throw new IllegalArgumentException (); 551 } 552 } 553 554 557 public boolean addElement(Object element) { 558 if (fElements.contains(element)) { 559 return false; 560 } 561 fElements.add(element); 562 if (isOkToUse(fTreeControl)) { 563 fTree.add(fParentElement, element); 564 fTree.expandToLevel(element, fTreeExpandLevel); 565 } 566 dialogFieldChanged(); 567 return true; 568 } 569 570 573 public boolean addElements(List elements) { 574 int nElements= elements.size(); 575 576 if (nElements > 0) { 577 ArrayList elementsToAdd= new ArrayList (nElements); 579 580 for (int i= 0; i < nElements; i++) { 581 Object elem= elements.get(i); 582 if (!fElements.contains(elem)) { 583 elementsToAdd.add(elem); 584 } 585 } 586 if (!elementsToAdd.isEmpty()) { 587 fElements.addAll(elementsToAdd); 588 if (isOkToUse(fTreeControl)) { 589 fTree.add(fParentElement, elementsToAdd.toArray()); 590 for (int i= 0; i < elementsToAdd.size(); i++) { 591 fTree.expandToLevel(elementsToAdd.get(i), fTreeExpandLevel); 592 } 593 } 594 dialogFieldChanged(); 595 return true; 596 } 597 } 598 return false; 599 } 600 601 604 public void insertElementAt(Object element, int index) { 605 if (fElements.contains(element)) { 606 return; 607 } 608 fElements.add(index, element); 609 if (isOkToUse(fTreeControl)) { 610 fTree.add(fParentElement, element); 611 if (fTreeExpandLevel != -1) { 612 fTree.expandToLevel(element, fTreeExpandLevel); 613 } 614 } 615 616 dialogFieldChanged(); 617 } 618 619 622 public void removeAllElements() { 623 if (fElements.size() > 0) { 624 fElements.clear(); 625 refresh(); 626 dialogFieldChanged(); 627 } 628 } 629 630 633 public void removeElement(Object element) throws IllegalArgumentException { 634 if (fElements.remove(element)) { 635 if (isOkToUse(fTreeControl)) { 636 fTree.remove(element); 637 } 638 dialogFieldChanged(); 639 } else { 640 throw new IllegalArgumentException (); 641 } 642 } 643 644 647 public void removeElements(List elements) { 648 if (elements.size() > 0) { 649 fElements.removeAll(elements); 650 if (isOkToUse(fTreeControl)) { 651 fTree.remove(elements.toArray()); 652 } 653 dialogFieldChanged(); 654 } 655 } 656 657 660 public int getSize() { 661 return fElements.size(); 662 } 663 664 public void selectElements(ISelection selection) { 665 fSelectionWhenEnabled= selection; 666 if (isOkToUse(fTreeControl)) { 667 fTree.setSelection(selection, true); 668 } 669 } 670 671 public void selectFirstElement() { 672 Object element= null; 673 if (fViewerComparator != null) { 674 Object [] arr= fElements.toArray(); 675 fViewerComparator.sort(fTree, arr); 676 if (arr.length > 0) { 677 element= arr[0]; 678 } 679 } else { 680 if (fElements.size() > 0) { 681 element= fElements.get(0); 682 } 683 } 684 if (element != null) { 685 selectElements(new StructuredSelection(element)); 686 } 687 } 688 689 public void postSetSelection(final ISelection selection) { 690 if (isOkToUse(fTreeControl)) { 691 Display d= fTreeControl.getDisplay(); 692 d.asyncExec(new Runnable () { 693 public void run() { 694 if (isOkToUse(fTreeControl)) { 695 selectElements(selection); 696 } 697 } 698 }); 699 } 700 } 701 702 705 public void refresh() { 706 super.refresh(); 707 if (isOkToUse(fTreeControl)) { 708 fTree.refresh(); 709 } 710 } 711 712 715 public void refresh(Object element) { 716 if (isOkToUse(fTreeControl)) { 717 fTree.refresh(element); 718 } 719 } 720 721 724 public void update(Object element) { 725 if (isOkToUse(fTreeControl)) { 726 fTree.update(element, null); 727 } 728 } 729 730 732 private List moveUp(List elements, List move) { 733 int nElements= elements.size(); 734 List res= new ArrayList (nElements); 735 Object floating= null; 736 for (int i= 0; i < nElements; i++) { 737 Object curr= elements.get(i); 738 if (move.contains(curr)) { 739 res.add(curr); 740 } else { 741 if (floating != null) { 742 res.add(floating); 743 } 744 floating= curr; 745 } 746 } 747 if (floating != null) { 748 res.add(floating); 749 } 750 return res; 751 } 752 753 private void moveUp(List toMoveUp) { 754 if (toMoveUp.size() > 0) { 755 setElements(moveUp(fElements, toMoveUp)); 756 fTree.reveal(toMoveUp.get(0)); 757 } 758 } 759 760 private void moveDown(List toMoveDown) { 761 if (toMoveDown.size() > 0) { 762 setElements(reverse(moveUp(reverse(fElements), toMoveDown))); 763 fTree.reveal(toMoveDown.get(toMoveDown.size() - 1)); 764 } 765 } 766 767 private List reverse(List p) { 768 List reverse= new ArrayList (p.size()); 769 for (int i= p.size() - 1; i >= 0; i--) { 770 reverse.add(p.get(i)); 771 } 772 return reverse; 773 } 774 775 private void remove() { 776 removeElements(getSelectedElements()); 777 } 778 779 private void up() { 780 moveUp(getSelectedElements()); 781 } 782 783 private void down() { 784 moveDown(getSelectedElements()); 785 } 786 787 private boolean canMoveUp(List selectedElements) { 788 if (isOkToUse(fTreeControl)) { 789 int nSelected= selectedElements.size(); 790 int nElements= fElements.size(); 791 for (int i= 0; i < nElements && nSelected > 0; i++) { 792 if (!selectedElements.contains(fElements.get(i))) { 793 return true; 794 } 795 nSelected--; 796 } 797 } 798 return false; 799 } 800 801 private boolean canMoveDown(List selectedElements) { 802 if (isOkToUse(fTreeControl)) { 803 int nSelected= selectedElements.size(); 804 for (int i= fElements.size() - 1; i >= 0 && nSelected > 0; i--) { 805 if (!selectedElements.contains(fElements.get(i))) { 806 return true; 807 } 808 nSelected--; 809 } 810 } 811 return false; 812 } 813 814 817 public List getSelectedElements() { 818 ArrayList result= new ArrayList (); 819 if (isOkToUse(fTreeControl)) { 820 ISelection selection= fTree.getSelection(); 821 if (selection instanceof IStructuredSelection) { 822 Iterator iter= ((IStructuredSelection)selection).iterator(); 823 while (iter.hasNext()) { 824 result.add(iter.next()); 825 } 826 } 827 } 828 return result; 829 } 830 831 public void expandElement(Object element, int level) { 832 if (isOkToUse(fTreeControl)) { 833 fTree.expandToLevel(element, level); 834 } 835 } 836 837 838 840 private class TreeViewerAdapter implements ITreeContentProvider, ISelectionChangedListener, IDoubleClickListener { 841 842 private final Object [] NO_ELEMENTS= new Object [0]; 843 844 846 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 847 } 849 850 public boolean isDeleted(Object element) { 851 return false; 852 } 853 854 public void dispose() { 855 } 856 857 public Object [] getElements(Object obj) { 858 return fElements.toArray(); 859 } 860 861 public Object [] getChildren(Object element) { 862 if (fTreeAdapter != null) { 863 return fTreeAdapter.getChildren(TreeListDialogField.this, element); 864 } 865 return NO_ELEMENTS; 866 } 867 868 public Object getParent(Object element) { 869 if (!fElements.contains(element) && fTreeAdapter != null) { 870 return fTreeAdapter.getParent(TreeListDialogField.this, element); 871 } 872 return fParentElement; 873 } 874 875 public boolean hasChildren(Object element) { 876 if (fTreeAdapter != null) { 877 return fTreeAdapter.hasChildren(TreeListDialogField.this, element); 878 } 879 return false; 880 } 881 882 884 public void selectionChanged(SelectionChangedEvent event) { 885 doListSelected(event); 886 } 887 888 891 public void doubleClick(DoubleClickEvent event) { 892 doDoubleClick(event); 893 } 894 895 } 896 897 protected void doListSelected(SelectionChangedEvent event) { 898 updateButtonState(); 899 if (fTreeAdapter != null) { 900 fTreeAdapter.selectionChanged(this); 901 } 902 } 903 904 protected void doDoubleClick(DoubleClickEvent event) { 905 if (fTreeAdapter != null) { 906 fTreeAdapter.doubleClicked(this); 907 } 908 } 909 910 911 912 } 913 | Popular Tags |