comparison dwtx/jface/viewers/StructuredViewer.d @ 104:04b47443bb01

Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections. These new wrappers now use the tango.util.containers instead of the tango.util.collections.
author Frank Benoit <benoit@tionex.de>
date Thu, 07 Aug 2008 15:01:33 +0200
parents 7ffeace6c47f
children
comparison
equal deleted inserted replaced
103:2d6540440fe6 104:04b47443bb01
39 import dwtx.jface.viewers.ILabelProvider; 39 import dwtx.jface.viewers.ILabelProvider;
40 import dwtx.jface.viewers.IStructuredContentProvider; 40 import dwtx.jface.viewers.IStructuredContentProvider;
41 import dwtx.jface.viewers.StructuredSelection; 41 import dwtx.jface.viewers.StructuredSelection;
42 import dwtx.jface.viewers.IStructuredSelection; 42 import dwtx.jface.viewers.IStructuredSelection;
43 43
44 import tango.util.collection.ArraySeq;
45 import tango.util.collection.model.Seq;
46 import tango.util.collection.model.SeqView;
47 44
48 import dwt.custom.TableTreeItem; 45 import dwt.custom.TableTreeItem;
49 import dwt.dnd.DragSource; 46 import dwt.dnd.DragSource;
50 import dwt.dnd.DragSourceListener; 47 import dwt.dnd.DragSourceListener;
51 import dwt.dnd.DropTarget; 48 import dwt.dnd.DropTarget;
67 import dwtx.jface.util.IOpenEventListener; 64 import dwtx.jface.util.IOpenEventListener;
68 import dwtx.jface.util.OpenStrategy; 65 import dwtx.jface.util.OpenStrategy;
69 import dwtx.jface.util.SafeRunnable; 66 import dwtx.jface.util.SafeRunnable;
70 67
71 import dwt.dwthelper.utils; 68 import dwt.dwthelper.utils;
69 import dwtx.dwtxhelper.Collection;
72 import dwt.dwthelper.Runnable; 70 import dwt.dwthelper.Runnable;
73 71
74 /** 72 /**
75 * Abstract base implementation for structure-oriented viewers (trees, lists, 73 * Abstract base implementation for structure-oriented viewers (trees, lists,
76 * tables). Supports custom sorting, filtering, and rendering. 74 * tables). Supports custom sorting, filtering, and rendering.
107 105
108 /** 106 /**
109 * This viewer's filters (element type: <code>ViewerFilter</code>). 107 * This viewer's filters (element type: <code>ViewerFilter</code>).
110 * <code>null</code> means there are no filters. 108 * <code>null</code> means there are no filters.
111 */ 109 */
112 private Seq!(ViewerFilter) filters; 110 private List filters;
113 111
114 /** 112 /**
115 * Indicates whether a selection change is in progress on this viewer. 113 * Indicates whether a selection change is in progress on this viewer.
116 * 114 *
117 * @see #setSelection(ISelection, bool) 115 * @see #setSelection(ISelection, bool)
595 * a viewer filter 593 * a viewer filter
596 * @see StructuredViewer#setFilters(ViewerFilter[]) 594 * @see StructuredViewer#setFilters(ViewerFilter[])
597 */ 595 */
598 public void addFilter(ViewerFilter filter) { 596 public void addFilter(ViewerFilter filter) {
599 if (filters is null) { 597 if (filters is null) {
600 filters = new ArraySeq!(ViewerFilter); 598 filters = new ArrayList();
601 } 599 }
602 filters.append(filter); 600 filters.add(filter);
603 refresh(); 601 refresh();
604 } 602 }
605 603
606 /** 604 /**
607 * Asserts that the given array of elements is itself non- <code>null</code> 605 * Asserts that the given array of elements is itself non- <code>null</code>
730 * the elements to filter 728 * the elements to filter
731 * @return only the elements which all filters accept 729 * @return only the elements which all filters accept
732 */ 730 */
733 protected Object[] filter(Object[] elements) { 731 protected Object[] filter(Object[] elements) {
734 if (filters !is null) { 732 if (filters !is null) {
735 ArraySeq!(Object) filtered = new ArraySeq!(Object); 733 ArrayList filtered = new ArrayList(elements.length);
736 filtered.capacity(elements.length);
737 Object root = getRoot(); 734 Object root = getRoot();
738 for (int i = 0; i < elements.length; i++) { 735 for (int i = 0; i < elements.length; i++) {
739 bool add = true; 736 bool add = true;
740 for (int j = 0; j < filters.size(); j++) { 737 for (int j = 0; j < filters.size(); j++) {
741 add = (cast(ViewerFilter) filters.get(j)).select(this, root, elements[i]); 738 add = (cast(ViewerFilter) filters.get(j)).select(this, root, elements[i]);
742 if (!add) { 739 if (!add) {
743 break; 740 break;
744 } 741 }
745 } 742 }
746 if (add) { 743 if (add) {
747 filtered.append(elements[i]); 744 filtered.add(elements[i]);
748 } 745 }
749 } 746 }
750 return filtered.toArray(); 747 return filtered.toArray();
751 } 748 }
752 return elements; 749 return elements;
828 * @see IDoubleClickListener#doubleClick 825 * @see IDoubleClickListener#doubleClick
829 */ 826 */
830 protected void fireDoubleClick(DoubleClickEvent event) { 827 protected void fireDoubleClick(DoubleClickEvent event) {
831 Object[] listeners = doubleClickListeners.getListeners(); 828 Object[] listeners = doubleClickListeners.getListeners();
832 for (int i = 0; i < listeners.length; ++i) { 829 for (int i = 0; i < listeners.length; ++i) {
833 SafeRunnable.run(new class(cast(IDoubleClickListener) listeners[i], event) SafeRunnable { 830 SafeRunnable.run( dgSafeRunnable( (IDoubleClickListener l, DoubleClickEvent event_){
834 IDoubleClickListener l; 831 l.doubleClick(event_);
835 DoubleClickEvent event_; 832 }, cast(IDoubleClickListener) listeners[i], event));
836 this(IDoubleClickListener a,DoubleClickEvent b){
837 l = a;
838 event_=b;
839 }
840 public void run() {
841 l.doubleClick(event_);
842 }
843 });
844 } 833 }
845 } 834 }
846 package void fireDoubleClick_package(DoubleClickEvent event) { 835 package void fireDoubleClick_package(DoubleClickEvent event) {
847 fireDoubleClick(event); 836 fireDoubleClick(event);
848 } 837 }
857 * @see IOpenListener#open(OpenEvent) 846 * @see IOpenListener#open(OpenEvent)
858 */ 847 */
859 protected void fireOpen(OpenEvent event) { 848 protected void fireOpen(OpenEvent event) {
860 Object[] listeners = openListeners.getListeners(); 849 Object[] listeners = openListeners.getListeners();
861 for (int i = 0; i < listeners.length; ++i) { 850 for (int i = 0; i < listeners.length; ++i) {
862 SafeRunnable.run(new class(cast(IOpenListener) listeners[i],event) SafeRunnable { 851 SafeRunnable.run( dgSafeRunnable( (IOpenListener l,OpenEvent event_){
863 IOpenListener l; 852 l.open(event_);
864 OpenEvent event_; 853 }, cast(IOpenListener) listeners[i],event));
865 this(IOpenListener a, OpenEvent b){
866 l = a;
867 event_=b;
868 }
869 public void run() {
870 l.open(event_);
871 }
872 });
873 } 854 }
874 } 855 }
875 package void fireOpen_package(OpenEvent event) { 856 package void fireOpen_package(OpenEvent event) {
876 fireOpen(event); 857 fireOpen(event);
877 } 858 }
887 * @see #addPostSelectionChangedListener(ISelectionChangedListener) 868 * @see #addPostSelectionChangedListener(ISelectionChangedListener)
888 */ 869 */
889 protected void firePostSelectionChanged(SelectionChangedEvent event) { 870 protected void firePostSelectionChanged(SelectionChangedEvent event) {
890 Object[] listeners = postSelectionChangedListeners.getListeners(); 871 Object[] listeners = postSelectionChangedListeners.getListeners();
891 for (int i = 0; i < listeners.length; ++i) { 872 for (int i = 0; i < listeners.length; ++i) {
892 SafeRunnable.run(new class(cast(ISelectionChangedListener) listeners[i],event) SafeRunnable { 873 SafeRunnable.run( dgSafeRunnable( (ISelectionChangedListener l, SelectionChangedEvent event_){
893 ISelectionChangedListener l; 874 l.selectionChanged(event_);
894 SelectionChangedEvent event_; 875 },cast(ISelectionChangedListener) listeners[i],event));
895 this(ISelectionChangedListener a,SelectionChangedEvent b){
896 l = a;
897 event_=b;
898 }
899 public void run() {
900 l.selectionChanged(event_);
901 }
902 });
903 } 876 }
904 } 877 }
905 878
906 /** 879 /**
907 * Returns the comparer to use for comparing elements, or 880 * Returns the comparer to use for comparing elements, or
926 * @return a filtered array of child elements 899 * @return a filtered array of child elements
927 */ 900 */
928 protected Object[] getFilteredChildren(Object parent) { 901 protected Object[] getFilteredChildren(Object parent) {
929 Object[] result = getRawChildren(parent); 902 Object[] result = getRawChildren(parent);
930 if (filters !is null) { 903 if (filters !is null) {
931 foreach (f;filters) { 904 for (Iterator iter = filters.iterator(); iter.hasNext();) {
905 ViewerFilter f = cast(ViewerFilter) iter.next();
932 result = f.filter(this, parent, result); 906 result = f.filter(this, parent, result);
933 } 907 }
934 } 908 }
935 return result; 909 return result;
936 } 910 }
943 */ 917 */
944 public ViewerFilter[] getFilters() { 918 public ViewerFilter[] getFilters() {
945 if (filters is null) { 919 if (filters is null) {
946 return new ViewerFilter[0]; 920 return new ViewerFilter[0];
947 } 921 }
948 return filters.toArray(); 922 return arraycast!(ViewerFilter)(filters.toArray());
949 } 923 }
950 924
951 /** 925 /**
952 * Returns the item at the given display-relative coordinates, or 926 * Returns the item at the given display-relative coordinates, or
953 * <code>null</code> if there is no item at that location or 927 * <code>null</code> if there is no item at that location or
1022 public override ISelection getSelection() { 996 public override ISelection getSelection() {
1023 Control control = getControl(); 997 Control control = getControl();
1024 if (control is null || control.isDisposed()) { 998 if (control is null || control.isDisposed()) {
1025 return StructuredSelection.EMPTY; 999 return StructuredSelection.EMPTY;
1026 } 1000 }
1027 auto list = getSelectionFromWidget(); 1001 List list = getSelectionFromWidget();
1028 return new StructuredSelection(list, comparer); 1002 return new StructuredSelection(list, comparer);
1029 } 1003 }
1030 1004
1031 /** 1005 /**
1032 * Retrieves the selection, as a <code>List</code>, from the underlying 1006 * Retrieves the selection, as a <code>List</code>, from the underlying
1033 * widget. 1007 * widget.
1034 * 1008 *
1035 * @return the list of selected elements 1009 * @return the list of selected elements
1036 */ 1010 */
1037 protected abstract SeqView!(Object) getSelectionFromWidget(); 1011 protected abstract List getSelectionFromWidget();
1038 package SeqView!(Object) getSelectionFromWidget_package(){ 1012 package List getSelectionFromWidget_package(){
1039 return getSelectionFromWidget(); 1013 return getSelectionFromWidget();
1040 } 1014 }
1041 1015
1042 /** 1016 /**
1043 * Returns the sorted and filtered set of children of the given element. The 1017 * Returns the sorted and filtered set of children of the given element. The
1308 if (widgetOrWidgets !is item) { 1282 if (widgetOrWidgets !is item) {
1309 elementMap.put(element, new ArrayWrapperT!(Widget)( [ w, item ] )); 1283 elementMap.put(element, new ArrayWrapperT!(Widget)( [ w, item ] ));
1310 } 1284 }
1311 } else { 1285 } else {
1312 Widget[] widgets = (cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array; 1286 Widget[] widgets = (cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array;
1313 int indexOfItem = -1; 1287 int indexOfItem = Arrays.asList(widgets).indexOf(item);
1314 foreach( idx, w; widgets ){
1315 if( w == item ){
1316 indexOfItem = idx;
1317 break;
1318 }
1319 }
1320 if (indexOfItem is -1) { 1288 if (indexOfItem is -1) {
1321 int length_ = widgets.length; 1289 int length_ = widgets.length;
1322 System.arraycopy(widgets, 0, 1290 System.arraycopy(widgets, 0,
1323 widgets = new Widget[length_ + 1], 0, length_); 1291 widgets = new Widget[length_ + 1], 0, length_);
1324 widgets[length_] = item; 1292 widgets[length_] = item;
1325 elementMap.put(element, new ArrayWrapperT!(Widget)(widgets)); 1293 elementMap.put(element, new ArrayWrapperObject(widgets));
1326 } 1294 }
1327 } 1295 }
1328 } 1296 }
1329 } 1297 }
1330 1298
1347 if (sorter !is null && sorter.isSorterProperty(element, property)) { 1315 if (sorter !is null && sorter.isSorterProperty(element, property)) {
1348 return true; 1316 return true;
1349 } 1317 }
1350 1318
1351 if (filters !is null) { 1319 if (filters !is null) {
1352 foreach( filter; filters ){ 1320 for (int i = 0, n = filters.size(); i < n; ++i) {
1321 ViewerFilter filter = cast(ViewerFilter) filters.get(i);
1353 if (filter.isFilterProperty(element, property)) { 1322 if (filter.isFilterProperty(element, property)) {
1354 return true; 1323 return true;
1355 } 1324 }
1356 } 1325 }
1357 } 1326 }
1488 * 1457 *
1489 * @param element 1458 * @param element
1490 * the element 1459 * the element
1491 */ 1460 */
1492 public void refresh(Object element) { 1461 public void refresh(Object element) {
1493 preservingSelection(new class(element) Runnable { 1462 preservingSelection( dgRunnable( (Object element_){
1494 Object element_; 1463 internalRefresh(element_);
1495 this(Object a){ 1464 }, element ));
1496 element_ = a;
1497 }
1498 public void run() {
1499 internalRefresh(element_);
1500 }
1501 });
1502 } 1465 }
1503 1466
1504 /** 1467 /**
1505 * Refreshes this viewer starting with the given element. Labels are updated 1468 * Refreshes this viewer starting with the given element. Labels are updated
1506 * as described in <code>refresh(bool updateLabels)</code>. 1469 * as described in <code>refresh(bool updateLabels)</code>.
1519 * that labels for existing elements are unchanged. 1482 * that labels for existing elements are unchanged.
1520 * 1483 *
1521 * @since 2.0 1484 * @since 2.0
1522 */ 1485 */
1523 public void refresh(Object element, bool updateLabels) { 1486 public void refresh(Object element, bool updateLabels) {
1524 preservingSelection(new class(element, updateLabels) Runnable { 1487 preservingSelection( dgRunnable( (Object element_, bool updateLabels_){
1525 Object element_; 1488 internalRefresh(element_, updateLabels_);
1526 bool updateLabels_; 1489 },element, updateLabels));
1527 this(Object a, bool b){
1528 element_ = a;
1529 updateLabels_ = b;
1530 }
1531 public void run() {
1532 internalRefresh(element_, updateLabels_);
1533 }
1534 });
1535 } 1490 }
1536 1491
1537 /** 1492 /**
1538 * 1493 *
1539 * Refreshes the given item with the given element. Calls 1494 * Refreshes the given item with the given element. Calls
1593 public void removeFilter(ViewerFilter filter) { 1548 public void removeFilter(ViewerFilter filter) {
1594 Assert.isNotNull(filter); 1549 Assert.isNotNull(filter);
1595 if (filters !is null) { 1550 if (filters !is null) {
1596 // Note: can't use List.remove(Object). Use identity comparison 1551 // Note: can't use List.remove(Object). Use identity comparison
1597 // instead. 1552 // instead.
1598 int delIdx = 0; 1553 for (Iterator i = filters.iterator(); i.hasNext();) {
1599 foreach( o; filters ){ 1554 Object o = i.next();
1600 if (o is filter) { 1555 if (o is filter) {
1601 filters.removeAt(delIdx); 1556 i.remove();
1602 refresh(); 1557 refresh();
1603 if (filters.size() is 0) { 1558 if (filters.size() is 0) {
1604 filters = null; 1559 filters = null;
1605 } 1560 }
1606 return; 1561 return;
1607 } 1562 }
1608 delIdx++;
1609 } 1563 }
1610 } 1564 }
1611 } 1565 }
1612 1566
1613 /** 1567 /**
1620 */ 1574 */
1621 public void setFilters(ViewerFilter[] filters) { 1575 public void setFilters(ViewerFilter[] filters) {
1622 if (filters.length is 0) { 1576 if (filters.length is 0) {
1623 resetFilters(); 1577 resetFilters();
1624 } else { 1578 } else {
1625 auto tmp = new ArraySeq!(ViewerFilter); 1579 this.filters = new ArrayList(Arrays.asList(filters));
1626 foreach( f; filters ){
1627 tmp.append(f);
1628 }
1629 this.filters = tmp;
1630 refresh(); 1580 refresh();
1631 } 1581 }
1632 } 1582 }
1633 1583
1634 /** 1584 /**
1736 * or <code>null</code> if the selection is to be cleared 1686 * or <code>null</code> if the selection is to be cleared
1737 * @param reveal 1687 * @param reveal
1738 * <code>true</code> if the selection is to be made visible, 1688 * <code>true</code> if the selection is to be made visible,
1739 * and <code>false</code> otherwise 1689 * and <code>false</code> otherwise
1740 */ 1690 */
1741 protected abstract void setSelectionToWidget(SeqView!(Object) l, bool reveal); 1691 protected abstract void setSelectionToWidget(List l, bool reveal);
1742 1692
1743 /** 1693 /**
1744 * Converts the selection to a <code>List</code> and calls 1694 * Converts the selection to a <code>List</code> and calls
1745 * <code>setSelectionToWidget(List, bool)</code>. The selection is 1695 * <code>setSelectionToWidget(List, bool)</code>. The selection is
1746 * expected to be an <code>IStructuredSelection</code> of elements. If 1696 * expected to be an <code>IStructuredSelection</code> of elements. If
1757 */ 1707 */
1758 protected void setSelectionToWidget(ISelection selection, bool reveal) { 1708 protected void setSelectionToWidget(ISelection selection, bool reveal) {
1759 if ( auto ss = cast(IStructuredSelection) selection ) { 1709 if ( auto ss = cast(IStructuredSelection) selection ) {
1760 setSelectionToWidget(ss.toList(), reveal); 1710 setSelectionToWidget(ss.toList(), reveal);
1761 } else { 1711 } else {
1762 setSelectionToWidget(cast(SeqView!(Object)) null, reveal); 1712 setSelectionToWidget(cast(List) null, reveal);
1763 } 1713 }
1764 } 1714 }
1765 1715
1766 /** 1716 /**
1767 * Sets this viewer's sorter and triggers refiltering and resorting of this 1717 * Sets this viewer's sorter and triggers refiltering and resorting of this
1913 if (item is widgetOrWidgets) { 1863 if (item is widgetOrWidgets) {
1914 elementMap.remove(element); 1864 elementMap.remove(element);
1915 } 1865 }
1916 } else { 1866 } else {
1917 Widget[] widgets = ( cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array; 1867 Widget[] widgets = ( cast(ArrayWrapperT!(Widget)) widgetOrWidgets).array;
1918 int indexOfItem = -1; 1868 int indexOfItem = Arrays.asList(widgets).indexOf(item);
1919 foreach( idx, w; widgets ){
1920 if( w == item ){
1921 indexOfItem = idx;
1922 break;
1923 }
1924 }
1925 if (indexOfItem is -1) { 1869 if (indexOfItem is -1) {
1926 return; 1870 return;
1927 } 1871 }
1928 int length = widgets.length; 1872 int length = widgets.length;
1929 if (indexOfItem is 0) { 1873 if (indexOfItem is 0) {
1930 if(length is 1) { 1874 if(length is 1) {
1931 elementMap.remove(element); 1875 elementMap.remove(element);
1932 } else { 1876 } else {
1933 Widget[] updatedWidgets = new Widget[length - 1]; 1877 Widget[] updatedWidgets = new Widget[length - 1];
1934 System.arraycopy(widgets, 1, updatedWidgets, 0, length -1 ); 1878 System.arraycopy(widgets, 1, updatedWidgets, 0, length -1 );
1935 elementMap.put(element, new ArrayWrapperT!(Widget)( updatedWidgets)); 1879 elementMap.put(element, new ArrayWrapperObject( updatedWidgets));
1936 } 1880 }
1937 } else { 1881 } else {
1938 Widget[] updatedWidgets = new Widget[length - 1]; 1882 Widget[] updatedWidgets = new Widget[length - 1];
1939 System.arraycopy(widgets, 0, updatedWidgets, 0, indexOfItem); 1883 System.arraycopy(widgets, 0, updatedWidgets, 0, indexOfItem);
1940 System.arraycopy(widgets, indexOfItem + 1, updatedWidgets, indexOfItem, length - indexOfItem - 1); 1884 System.arraycopy(widgets, indexOfItem + 1, updatedWidgets, indexOfItem, length - indexOfItem - 1);
1941 elementMap.put(element, new ArrayWrapperT!(Widget)(updatedWidgets)); 1885 elementMap.put(element, new ArrayWrapperObject(updatedWidgets));
1942 } 1886 }
1943 } 1887 }
1944 } 1888 }
1945 } 1889 }
1946 1890
1947 // flag to indicate that a full refresh took place. See bug 102440. 1891 // flag to indicate that a full refresh took place. See bug 102440.
1948 private bool refreshOccurred; 1892 private bool refreshOccurred;
1949 1893
1950 /** 1894 /**
1951 * Updates the given elements' presentation when one or more of their 1895 * Updates the given elements' presentation when one or more of their
1952 * properties change. Only the given elements are updated. 1896 * properties change. Only the given elements are updated.
1953 * <p> 1897 * <p>
1954 * This does not handle structural changes (e.g. addition or removal of 1898 * This does not handle structural changes (e.g. addition or removal of
2046 1990
2047 bool mayExitEarly = !refreshOccurred; 1991 bool mayExitEarly = !refreshOccurred;
2048 for (int i = 0; i < items.length; i++) { 1992 for (int i = 0; i < items.length; i++) {
2049 internalUpdate(items[i], element, properties); 1993 internalUpdate(items[i], element, properties);
2050 if (mayExitEarly && refreshOccurred) { 1994 if (mayExitEarly && refreshOccurred) {
2051 // detected a change from refreshOccurred is false to refreshOccurred is true 1995 // detected a change from refreshOccurred is false to refreshOccurred is true
2052 return; 1996 return;
2053 } 1997 }
2054 } 1998 }
2055 } 1999 }
2056 2000
2082 break; 2026 break;
2083 } 2027 }
2084 } 2028 }
2085 } 2029 }
2086 if (needsRefilter_) { 2030 if (needsRefilter_) {
2087 preservingSelection(new class Runnable { 2031 preservingSelection(dgRunnable( {
2088 public void run() { 2032 internalRefresh(getRoot());
2089 internalRefresh(getRoot()); 2033 refreshOccurred = true;
2090 refreshOccurred = true; 2034 }));
2091 }
2092 });
2093 return; 2035 return;
2094 } 2036 }
2095 2037
2096 bool needsUpdate; 2038 bool needsUpdate;
2097 if (properties is null) { 2039 if (properties is null) {