32f3e6f3eb565a3cebb3e9701ac6f27af0291fe6
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / wizards / dialogfields / ListDialogField.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.wizards.dialogfields;
12
13
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
17
18 import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
19 import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
20 import net.sourceforge.phpdt.internal.ui.util.TableLayoutComposite;
21
22 import org.eclipse.jface.util.Assert;
23 import org.eclipse.jface.viewers.ColumnLayoutData;
24 import org.eclipse.jface.viewers.ColumnWeightData;
25 import org.eclipse.jface.viewers.DoubleClickEvent;
26 import org.eclipse.jface.viewers.IDoubleClickListener;
27 import org.eclipse.jface.viewers.ILabelProvider;
28 import org.eclipse.jface.viewers.ISelection;
29 import org.eclipse.jface.viewers.ISelectionChangedListener;
30 import org.eclipse.jface.viewers.IStructuredContentProvider;
31 import org.eclipse.jface.viewers.IStructuredSelection;
32 import org.eclipse.jface.viewers.SelectionChangedEvent;
33 import org.eclipse.jface.viewers.StructuredSelection;
34 import org.eclipse.jface.viewers.TableLayout;
35 import org.eclipse.jface.viewers.TableViewer;
36 import org.eclipse.jface.viewers.Viewer;
37 import org.eclipse.jface.viewers.ViewerSorter;
38 import org.eclipse.swt.SWT;
39 import org.eclipse.swt.events.KeyAdapter;
40 import org.eclipse.swt.events.KeyEvent;
41 import org.eclipse.swt.events.SelectionEvent;
42 import org.eclipse.swt.events.SelectionListener;
43 import org.eclipse.swt.layout.GridData;
44 import org.eclipse.swt.layout.GridLayout;
45 import org.eclipse.swt.widgets.Button;
46 import org.eclipse.swt.widgets.Composite;
47 import org.eclipse.swt.widgets.Control;
48 import org.eclipse.swt.widgets.Display;
49 import org.eclipse.swt.widgets.Label;
50 import org.eclipse.swt.widgets.Table;
51 import org.eclipse.swt.widgets.TableColumn;
52
53 /**
54  * A list with a button bar.
55  * Typical buttons are 'Add', 'Remove', 'Up' and 'Down'.
56  * List model is independend of widget creation.
57  * DialogFields controls are: Label, List and Composite containing buttons.
58  */
59 public class ListDialogField extends DialogField {
60         
61         public static class ColumnsDescription {
62                 private ColumnLayoutData[] columns;
63                 private String[] headers;
64                 private boolean drawLines;
65                 
66                 public ColumnsDescription(ColumnLayoutData[] columns, String[] headers, boolean drawLines) {
67                         this.columns= columns;
68                         this.headers= headers;
69                         this.drawLines= drawLines;
70                 }
71                 
72                 public ColumnsDescription(String[] headers, boolean drawLines) {
73                         this(createColumnWeightData(headers.length), headers, drawLines);
74                 }
75                 
76                 public ColumnsDescription(int nColumns, boolean drawLines) {
77                         this(createColumnWeightData(nColumns), null, drawLines);
78                 }
79                 
80                 private static ColumnLayoutData[] createColumnWeightData(int nColumns) {
81                         ColumnLayoutData[] data= new ColumnLayoutData[nColumns];
82                         for (int i= 0; i < nColumns; i++) {
83                                 data[i]= new ColumnWeightData(1);
84                         }                       
85                         return data;
86                 }
87         }
88         
89         protected TableViewer fTable;
90         protected ILabelProvider fLabelProvider;
91         protected ListViewerAdapter fListViewerAdapter;
92         protected List fElements;
93         protected ViewerSorter fViewerSorter;
94
95         protected String[] fButtonLabels;
96         private Button[] fButtonControls;
97         
98         private boolean[] fButtonsEnabled;
99         
100         private int fRemoveButtonIndex;
101         private int fUpButtonIndex;
102         private int fDownButtonIndex;
103         
104         private Label fLastSeparator;
105         
106         private Control fTableControl;
107         private Composite fButtonsControl;
108         private ISelection fSelectionWhenEnabled;
109         
110         private IListAdapter fListAdapter;
111         
112         private Object fParentElement;
113         
114         private ColumnsDescription fTableColumns;
115         
116
117         /**
118          * Creates the <code>ListDialogField</code>.
119          * @param adapter A listener for button invocation, selection changes. Can
120          * be <code>null</code>.
121          * @param buttonLabels The labels of all buttons: <code>null</code> is a valid array entry and
122          * marks a separator.
123          * @param lprovider The label provider to render the table entries
124          */     
125         public ListDialogField(IListAdapter adapter, String[] buttonLabels, ILabelProvider lprovider) {
126                 super();
127                 fListAdapter= adapter;
128
129                 fLabelProvider= lprovider;
130                 fListViewerAdapter= new ListViewerAdapter();
131                 fParentElement= this;
132
133                 fElements= new ArrayList(10);
134                                         
135                 fButtonLabels= buttonLabels;
136                 if (fButtonLabels != null) {
137                         int nButtons= fButtonLabels.length;
138                         fButtonsEnabled= new boolean[nButtons];
139                         for (int i= 0; i < nButtons; i++) {
140                                 fButtonsEnabled[i]= true;
141                         }
142                 }       
143                                 
144                 fTable= null;
145                 fTableControl= null;
146                 fButtonsControl= null;
147                 fTableColumns= null;
148                 
149                 fRemoveButtonIndex= -1;
150                 fUpButtonIndex= -1;
151                 fDownButtonIndex= -1;
152         }
153                 
154         /**
155          * Sets the index of the 'remove' button in the button label array passed in the constructor.
156          * The behaviour of the button marked as the 'remove' button will then be handled internally.
157          * (enable state, button invocation behaviour)
158          */     
159         public void setRemoveButtonIndex(int removeButtonIndex) {
160                 Assert.isTrue(removeButtonIndex < fButtonLabels.length);
161                 fRemoveButtonIndex= removeButtonIndex;
162         }
163
164         /**
165          * Sets the index of the 'up' button in the button label array passed in the constructor.
166          * The behaviour of the button marked as the 'up' button will then be handled internally.
167          * (enable state, button invocation behaviour)
168          */     
169         public void setUpButtonIndex(int upButtonIndex) {
170                 Assert.isTrue(upButtonIndex < fButtonLabels.length);
171                 fUpButtonIndex= upButtonIndex;
172         }
173
174         /**
175          * Sets the index of the 'down' button in the button label array passed in the constructor.
176          * The behaviour of the button marked as the 'down' button will then be handled internally.
177          * (enable state, button invocation behaviour)
178          */     
179         public void setDownButtonIndex(int downButtonIndex) {
180                 Assert.isTrue(downButtonIndex < fButtonLabels.length);
181                 fDownButtonIndex= downButtonIndex;
182         }
183         
184         /**
185          * Sets the viewerSorter.
186          * @param viewerSorter The viewerSorter to set
187          */
188         public void setViewerSorter(ViewerSorter viewerSorter) {
189                 fViewerSorter= viewerSorter;
190         }
191         
192         public void setTableColumns(ColumnsDescription column) {
193                 fTableColumns= column;
194         }
195         
196         
197         
198         // ------ adapter communication
199         
200         private void buttonPressed(int index) {
201                 if (!managedButtonPressed(index) && fListAdapter != null) {
202                         fListAdapter.customButtonPressed(this, index);
203                 }
204         }
205         
206         /**
207          * Checks if the button pressed is handled internally
208          * @return Returns true if button has been handled.
209          */
210         protected boolean managedButtonPressed(int index) {
211                 if (index == fRemoveButtonIndex) {
212                         remove();
213                 } else if (index == fUpButtonIndex) {
214                         up();
215                 } else if (index == fDownButtonIndex) {
216                         down();
217                 } else {
218                         return false;
219                 }
220                 return true;
221         }
222         
223
224         // ------ layout helpers
225         
226         /*
227          * @see DialogField#doFillIntoGrid
228          */
229         public Control[] doFillIntoGrid(Composite parent, int nColumns) {
230                 PixelConverter converter= new PixelConverter(parent);
231                 
232                 assertEnoughColumns(nColumns);
233                 
234                 Label label= getLabelControl(parent);
235                 GridData gd= gridDataForLabel(1);
236                 gd.verticalAlignment= GridData.BEGINNING;
237                 label.setLayoutData(gd);
238                 
239                 Control list= getListControl(parent);
240                 gd= new GridData();
241                 gd.horizontalAlignment= GridData.FILL;
242                 gd.grabExcessHorizontalSpace= false;
243                 gd.verticalAlignment= GridData.FILL;
244                 gd.grabExcessVerticalSpace= true;
245                 gd.horizontalSpan= nColumns - 2;
246                 gd.widthHint= converter.convertWidthInCharsToPixels(50);
247                 gd.heightHint= converter.convertHeightInCharsToPixels(6);
248
249                 list.setLayoutData(gd);
250                 
251                 Composite buttons= getButtonBox(parent);
252                 gd= new GridData();
253                 gd.horizontalAlignment= GridData.FILL;
254                 gd.grabExcessHorizontalSpace= false;
255                 gd.verticalAlignment= GridData.FILL;
256                 gd.grabExcessVerticalSpace= true;
257                 gd.horizontalSpan= 1;
258                 buttons.setLayoutData(gd);
259                 
260                 return new Control[] { label, list, buttons };
261         }
262
263         /*
264          * @see DialogField#getNumberOfControls
265          */     
266         public int getNumberOfControls() {
267                 return 3;       
268         }
269
270         /**
271          * Sets the minimal width of the buttons. Must be called after widget creation.
272          */             
273         public void setButtonsMinWidth(int minWidth) {
274                 if (fLastSeparator != null) {
275                         ((GridData)fLastSeparator.getLayoutData()).widthHint= minWidth;
276                 }
277         }
278         
279         
280         // ------ ui creation
281         
282         /**
283          * Returns the list control. When called the first time, the control will be created.
284          * @param The parent composite when called the first time, or <code>null</code>
285          * after.
286          */
287         public Control getListControl(Composite parent) {
288                 if (fTableControl == null) {
289                         assertCompositeNotNull(parent);
290                         
291                         if (fTableColumns == null) {
292                                 fTable= createTableViewer(parent);
293                                 Table tableControl= fTable.getTable();
294                                 
295                                 fTableControl= tableControl;
296                                 tableControl.setLayout(new TableLayout());
297                         } else {
298                                 TableLayoutComposite composite= new TableLayoutComposite(parent, SWT.NONE);
299                                 fTableControl= composite;
300                                 
301                                 fTable= createTableViewer(composite);
302                                 Table tableControl= fTable.getTable();
303                                                                 
304                                 tableControl.setHeaderVisible(fTableColumns.headers != null);
305                                 tableControl.setLinesVisible(fTableColumns.drawLines);
306                                 ColumnLayoutData[] columns= fTableColumns.columns;
307                                 for (int i= 0; i < columns.length; i++) {
308                                         composite.addColumnData(columns[i]);
309                                         TableColumn column= new TableColumn(tableControl, SWT.NONE);
310                                         //tableLayout.addColumnData(columns[i]);
311                                         if (fTableColumns.headers != null) {
312                                                 column.setText(fTableColumns.headers[i]);
313                                         }
314                                 }
315                         }
316
317                         fTable.getTable().addKeyListener(new KeyAdapter() {
318                                 public void keyPressed(KeyEvent e) {
319                                         handleKeyPressed(e);
320                                 }
321                         });
322                         
323                         //fTableControl.setLayout(tableLayout);                                         
324                         
325                         fTable.setContentProvider(fListViewerAdapter);
326                         fTable.setLabelProvider(fLabelProvider);
327                         fTable.addSelectionChangedListener(fListViewerAdapter);
328                         fTable.addDoubleClickListener(fListViewerAdapter);
329                         
330                         fTable.setInput(fParentElement);
331                         
332                         if (fViewerSorter != null) {
333                                 fTable.setSorter(fViewerSorter);
334                         }
335                         
336                         fTableControl.setEnabled(isEnabled());
337                         if (fSelectionWhenEnabled != null) {
338                                 postSetSelection(fSelectionWhenEnabled);
339                         }
340                 }
341                 return fTableControl;
342         }
343
344         /**
345          * Returns the internally used table viewer.
346          */             
347         public TableViewer getTableViewer() {
348                 return fTable;
349         }
350         
351         /* 
352          * Subclasses may override to specify a different style.
353          */
354         protected int getListStyle(){
355                 int style=  SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL ;
356                 if (fTableColumns != null) {
357                         style |= SWT.FULL_SELECTION;
358                 }
359                 return style;           
360         }
361         
362         protected TableViewer createTableViewer(Composite parent) {
363                 Table table= new Table(parent, getListStyle());
364                 return new TableViewer(table);
365         }       
366         
367         protected Button createButton(Composite parent, String label, SelectionListener listener) {
368                 Button button= new Button(parent, SWT.PUSH);
369                 button.setText(label);
370                 button.addSelectionListener(listener);
371                 GridData gd= new GridData();
372                 gd.horizontalAlignment= GridData.FILL;
373                 gd.grabExcessHorizontalSpace= true;
374                 gd.verticalAlignment= GridData.BEGINNING;
375                 gd.heightHint = SWTUtil.getButtonHeigthHint(button);
376                 gd.widthHint = SWTUtil.getButtonWidthHint(button);
377         
378                 button.setLayoutData(gd);
379                 return button;
380         }
381         
382         private Label createSeparator(Composite parent) {
383                 Label separator= new Label(parent, SWT.NONE);
384                 separator.setVisible(false);
385                 GridData gd= new GridData();
386                 gd.horizontalAlignment= GridData.FILL;
387                 gd.verticalAlignment= GridData.BEGINNING;
388                 gd.heightHint= 4;
389                 separator.setLayoutData(gd);
390                 return separator;
391         }                       
392
393         /**
394          * Returns the composite containing the buttons. When called the first time, the control
395          * will be created.
396          * @param The parent composite when called the first time, or <code>null</code>
397          * after.
398          */     
399         public Composite getButtonBox(Composite parent) {
400                 if (fButtonsControl == null) {
401                         assertCompositeNotNull(parent);
402                         
403                         SelectionListener listener= new SelectionListener() {
404                                 public void widgetDefaultSelected(SelectionEvent e) {
405                                         doButtonSelected(e);
406                                 }
407                                 public void widgetSelected(SelectionEvent e) {
408                                         doButtonSelected(e);
409                                 }
410                         };
411                         
412                         Composite contents= new Composite(parent, SWT.NULL);
413                         GridLayout layout= new GridLayout();
414                         layout.marginWidth= 0;
415                         layout.marginHeight= 0;
416                         contents.setLayout(layout);
417                         
418                         if (fButtonLabels != null) {
419                                 fButtonControls= new Button[fButtonLabels.length];
420                                 for (int i= 0; i < fButtonLabels.length; i++) {
421                                         String currLabel= fButtonLabels[i];
422                                         if (currLabel != null) {
423                                                 fButtonControls[i]= createButton(contents, currLabel, listener);
424                                                 fButtonControls[i].setEnabled(isEnabled() && fButtonsEnabled[i]);
425                                         } else {
426                                                 fButtonControls[i]= null;
427                                                 createSeparator(contents);
428                                         }
429                                 }
430                         }
431                                                 
432                         fLastSeparator= createSeparator(contents);      
433         
434                         updateButtonState();
435                         fButtonsControl= contents;
436                 }
437                 
438                 return fButtonsControl;
439         }
440         
441         private void doButtonSelected(SelectionEvent e) {
442                 if (fButtonControls != null) {
443                         for (int i= 0; i < fButtonControls.length; i++) {
444                                 if (e.widget == fButtonControls[i]) {
445                                         buttonPressed(i);
446                                         return;
447                                 }
448                         }
449                 }
450         }
451         
452         /**
453          * Handles key events in the table viewer. Specifically
454          * when the delete key is pressed.
455          */
456         protected void handleKeyPressed(KeyEvent event) {
457                 if (event.character == SWT.DEL && event.stateMask == 0) {
458                         if (fRemoveButtonIndex != -1 && isButtonEnabled(fTable.getSelection(), fRemoveButtonIndex)) {
459                                 managedButtonPressed(fRemoveButtonIndex);
460                         }
461                 } 
462         }       
463         
464         // ------ enable / disable management
465
466         /*
467          * @see DialogField#dialogFieldChanged
468          */     
469         public void dialogFieldChanged() {
470                 super.dialogFieldChanged();
471                 updateButtonState();
472         }
473         
474         /*
475          * Updates the enable state of the all buttons
476          */ 
477         protected void updateButtonState() {
478                 if (fButtonControls != null) {
479                         ISelection sel= fTable.getSelection();
480                         for (int i= 0; i < fButtonControls.length; i++) {
481                                 Button button= fButtonControls[i];
482                                 if (isOkToUse(button)) {
483                                         button.setEnabled(isButtonEnabled(sel, i));
484                                 }                               
485                         }
486                 }
487         }
488         
489         protected boolean getManagedButtonState(ISelection sel, int index) {
490                 if (index == fRemoveButtonIndex) {
491                         return !sel.isEmpty();
492                 } else if (index == fUpButtonIndex) {
493                         return !sel.isEmpty() && canMoveUp();
494                 } else if (index == fDownButtonIndex) {
495                         return !sel.isEmpty() && canMoveDown();
496                 }
497                 return true;
498         }               
499
500         /*
501          * @see DialogField#updateEnableState
502          */     
503         protected void updateEnableState() {
504                 super.updateEnableState();
505                 
506                 boolean enabled= isEnabled();
507                 if (isOkToUse(fTableControl)) {
508                         if (!enabled) {
509                                 fSelectionWhenEnabled= fTable.getSelection();
510                                 selectElements(null);
511                         } else {
512                                 selectElements(fSelectionWhenEnabled);
513                                 fSelectionWhenEnabled= null;
514                         }
515                         fTableControl.setEnabled(enabled);
516                 }
517                 updateButtonState();
518         }
519
520         /**
521          * Sets a button enabled or disabled.
522          */     
523         public void enableButton(int index, boolean enable) {
524                 if (fButtonsEnabled != null && index < fButtonsEnabled.length) {
525                         fButtonsEnabled[index]= enable;
526                         updateButtonState();
527                 }
528         }
529         
530         private boolean isButtonEnabled(ISelection sel, int index) {
531                 boolean extraState= getManagedButtonState(sel, index);
532                 return isEnabled() && extraState && fButtonsEnabled[index];
533         }               
534         
535
536         // ------ model access
537         
538         /**
539          * Sets the elements shown in the list.
540          */
541         public void setElements(List elements) {
542                 fElements= new ArrayList(elements);
543                 if (fTable != null) {
544                         fTable.refresh();
545                 }
546                 dialogFieldChanged();
547         }
548
549         /**
550          * Gets the elements shown in the list.
551          * The list returned is a copy, so it can be modified by the user.
552          */     
553         public List getElements() {
554                 return new ArrayList(fElements);
555         }
556
557         /**
558          * Gets the elements shown at the given index.
559          */             
560         public Object getElement(int index) {
561                 return fElements.get(index);
562         }
563         
564         /**
565         * Gets the index of an element in the list or -1 if element is not in list.
566         */
567         public int getIndexOfElement(Object elem) {
568                 return fElements.indexOf(elem);
569         }       
570
571         /**
572          * Replace an element.
573          */             
574         public void replaceElement(Object oldElement, Object newElement) throws IllegalArgumentException { 
575                 int idx= fElements.indexOf(oldElement);
576                 if (idx != -1) {
577                         fElements.set(idx, newElement);
578                         if (fTable != null) {
579                                 List selected= getSelectedElements();
580                                 if (selected.remove(oldElement)) {
581                                         selected.add(newElement);
582                                 }
583                                 fTable.refresh();
584                                 selectElements(new StructuredSelection(selected));
585                         }
586                         dialogFieldChanged();
587                 } else {
588                         throw new IllegalArgumentException();
589                 }
590         }       
591
592         /**
593          * Adds an element at the end of the list.
594          */             
595         public void addElement(Object element) {                
596                 if (fElements.contains(element)) {
597                         return;
598                 }
599                 fElements.add(element);
600                 if (fTable != null) {
601                         fTable.add(element);
602                 }
603                 dialogFieldChanged();
604         }
605
606         /**
607          * Adds elements at the end of the list.
608          */     
609         public void addElements(List elements) {
610                 int nElements= elements.size();
611                 
612                 if (nElements > 0) {
613                         // filter duplicated
614                         ArrayList elementsToAdd= new ArrayList(nElements);
615                         
616                         for (int i= 0; i < nElements; i++) {
617                                 Object elem= elements.get(i);
618                                 if (!fElements.contains(elem)) {
619                                         elementsToAdd.add(elem);
620                                 }       
621                         }
622                         fElements.addAll(elementsToAdd);
623                         if (fTable != null) {
624                                 fTable.add(elementsToAdd.toArray());
625                         }
626                         dialogFieldChanged();
627                 }
628         }       
629
630         /**
631          * Adds an element at a position.
632          */             
633         public void insertElementAt(Object element, int index) {
634                 if (fElements.contains(element)) {
635                         return;
636                 }
637                 fElements.add(index, element);
638                 if (fTable != null) {
639                         fTable.add(element);
640                 }
641                 
642                 dialogFieldChanged();
643         }       
644
645
646         /**
647          * Adds an element at a position.
648          */     
649         public void removeAllElements() {
650                 if (fElements.size() > 0) {
651                         fElements.clear();
652                         if (fTable != null) {
653                                 fTable.refresh();
654                         }
655                         dialogFieldChanged();
656                 }
657         }
658                 
659         /**
660          * Removes an element from the list.
661          */             
662         public void removeElement(Object element) throws IllegalArgumentException {
663                 if (fElements.remove(element)) {
664                         if (fTable != null) {
665                                 fTable.remove(element);
666                         }
667                         dialogFieldChanged();
668                 } else {
669                         throw new IllegalArgumentException();
670                 }
671         }
672
673         /**
674          * Removes elements from the list.
675          */             
676         public void removeElements(List elements) {
677                 if (elements.size() > 0) {
678                         fElements.removeAll(elements);
679                         if (fTable != null) {
680                                 fTable.remove(elements.toArray());
681                         }
682                         dialogFieldChanged();
683                 }
684         }
685
686         /**
687          * Gets the number of elements
688          */             
689         public int getSize() {
690                 return fElements.size();
691         }
692         
693
694         public void selectElements(ISelection selection) {
695                 fSelectionWhenEnabled= selection;
696                 if (fTable != null) {
697                         fTable.setSelection(selection, true);
698                 }
699         }
700         
701         public void selectFirstElement() {
702                 Object element= null;
703                 if (fViewerSorter != null) {
704                         Object[] arr= fElements.toArray(); 
705                         fViewerSorter.sort(fTable, arr);
706                         if (arr.length > 0) {
707                                 element= arr[0];
708                         }
709                 } else {
710                         if (fElements.size() > 0) {
711                                 element= fElements.get(0);
712                         }
713                 }
714                 if (element != null) {
715                         selectElements(new StructuredSelection(element));
716                 }
717         }
718         
719                 
720         public void postSetSelection(final ISelection selection) {
721                 if (isOkToUse(fTableControl)) {
722                         Display d= fTableControl.getDisplay();
723                         d.asyncExec(new Runnable() {
724                                 public void run() {
725                                         if (isOkToUse(fTableControl)) {
726                                                 selectElements(selection);
727                                         }
728                                 }
729                         });
730                 }
731         }
732         
733         /**
734          * Refreshes the table.
735          */
736         public void refresh() {
737                 if (fTable != null) {
738                         fTable.refresh();
739                 }
740         }
741         
742         // ------- list maintenance
743         
744         private List moveUp(List elements, List move) {
745                 int nElements= elements.size();
746                 List res= new ArrayList(nElements);
747                 Object floating= null;
748                 for (int i= 0; i < nElements; i++) {
749                         Object curr= elements.get(i);
750                         if (move.contains(curr)) {
751                                 res.add(curr);
752                         } else {
753                                 if (floating != null) {
754                                         res.add(floating);
755                                 }
756                                 floating= curr;
757                         }
758                 }
759                 if (floating != null) {
760                         res.add(floating);
761                 }
762                 return res;
763         }       
764         
765         private void moveUp(List toMoveUp) {
766                 if (toMoveUp.size() > 0) {
767                         setElements(moveUp(fElements, toMoveUp));
768                         fTable.reveal(toMoveUp.get(0));
769                 }
770         }
771         
772         private void moveDown(List toMoveDown) {
773                 if (toMoveDown.size() > 0) {
774                         setElements(reverse(moveUp(reverse(fElements), toMoveDown)));
775                         fTable.reveal(toMoveDown.get(toMoveDown.size() - 1));
776                 }
777         }
778         
779         private List reverse(List p) {
780                 List reverse= new ArrayList(p.size());
781                 for (int i= p.size()-1; i >= 0; i--) {
782                         reverse.add(p.get(i));
783                 }
784                 return reverse;
785         }
786         
787         
788         private void remove() {
789                 removeElements(getSelectedElements());
790         }
791         
792         private void up() {
793                 moveUp(getSelectedElements());
794         }
795         
796         private void down() {
797                 moveDown(getSelectedElements());
798         }
799         
800         private boolean canMoveUp() {
801                 if (isOkToUse(fTableControl)) {
802                         int[] indc= fTable.getTable().getSelectionIndices();
803                         for (int i= 0; i < indc.length; i++) {
804                                 if (indc[i] != i) {
805                                         return true;
806                                 }
807                         }
808                 }
809                 return false;
810         }
811         
812         private boolean canMoveDown() {
813                 if (isOkToUse(fTableControl)) {
814                         int[] indc= fTable.getTable().getSelectionIndices();
815                         int k= fElements.size() - 1;
816                         for (int i= indc.length - 1; i >= 0 ; i--, k--) {
817                                 if (indc[i] != k) {
818                                         return true;
819                                 }
820                         }
821                 }
822                 return false;
823         }       
824
825         /**
826          * Returns the selected elements.
827          */
828         public List getSelectedElements() {
829                 List result= new ArrayList();
830                 if (fTable != null) {
831                         ISelection selection= fTable.getSelection();
832                         if (selection instanceof IStructuredSelection) {
833                                 Iterator iter= ((IStructuredSelection)selection).iterator();
834                                 while (iter.hasNext()) {
835                                         result.add(iter.next());
836                                 }
837                         }
838                 }
839                 return result;
840         }
841         
842         // ------- ListViewerAdapter
843         
844         private class ListViewerAdapter implements IStructuredContentProvider, ISelectionChangedListener, IDoubleClickListener {
845
846                 // ------- ITableContentProvider Interface ------------
847         
848                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
849                         // will never happen
850                 }
851                 
852                 public boolean isDeleted(Object element) {
853                         return false;
854                 }
855         
856                 public void dispose() {
857                 }
858                 
859                 public Object[] getElements(Object obj) {
860                         return fElements.toArray();
861                 }
862         
863                 // ------- ISelectionChangedListener Interface ------------
864                 
865                 public void selectionChanged(SelectionChangedEvent event) {
866                         doListSelected(event);
867                 }
868                 
869                 /* (non-Javadoc)
870                  * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent)
871                  */
872                 public void doubleClick(DoubleClickEvent event) {
873                         doDoubleClick(event);
874                 }
875
876         }
877         
878         
879         protected void doListSelected(SelectionChangedEvent event) {
880                 updateButtonState();
881                 if (fListAdapter != null) {
882                         fListAdapter.selectionChanged(this);
883                 }
884         }
885         
886         protected void doDoubleClick(DoubleClickEvent event) {
887                 if (fListAdapter != null) {
888                         fListAdapter.doubleClicked(this);
889                 }
890         }       
891
892
893
894 }