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