I adapted the CCombo. Was fairly easy, mostly index->Indices. I've marked the more complex things with //mifritscher.
As the original is over 2000 lines, here is just the diff against the original CCombo:
--- CCombo.java Sat Feb 25 21:05:43 2023
+++ MultipleSelectionCombo.java Sat Feb 25 21:00:51 2023
@@ -12,13 +12,15 @@
* IBM Corporation - initial API and implementation
* Paul Pazderski - Bug 349112: allow setting alignment on the text field
*******************************************************************************/
-package org.eclipse.swt.custom;
+package com.vogella.tycho.plugin2.utils.rcp;
+import java.util.Arrays;
import java.util.function.*;
import org.eclipse.swt.*;
import org.eclipse.swt.accessibility.*;
+import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
@@ -51,7 +53,7 @@
* @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: CustomControlExample</a>
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
*/
-public class CCombo extends Composite {
+public class MultipleSelectionCombo extends Composite {
Text text;
List list;
@@ -99,7 +101,7 @@
* @see SWT#TRAIL
* @see Widget#getStyle()
*/
-public CCombo (Composite parent, int style) {
+public MultipleSelectionCombo (Composite parent, int style) {
super (parent, style = checkStyle (style));
_shell = super.getShell ();
@@ -121,7 +123,7 @@
arrowEvent (event);
return;
}
- if (CCombo.this == event.widget) {
+ if (MultipleSelectionCombo.this == event.widget) {
comboEvent (event);
return;
}
@@ -148,7 +150,7 @@
}
if (event.widget instanceof Control) {
Shell shell = ((Control)event.widget).getShell ();
- if (shell == CCombo.this.getShell ()) {
+ if (shell == MultipleSelectionCombo.this.getShell ()) {
handleFocus (SWT.FocusOut);
}
}
@@ -163,7 +165,7 @@
for (int arrowEvent : arrowEvents)
arrow.addListener (arrowEvent, listener);
- createPopup(null, -1);
+ createPopup(null, null);
if ((style & SWT.SIMPLE) == 0) {
int itemHeight = list.getItemHeight ();
if (itemHeight != 0) {
@@ -383,6 +385,7 @@
event.type = SWT.None;
break;
}
+ /*- mifritscher: unneeded...
case SWT.MouseWheel: {
Point pt = getDisplay ().map (arrow, this, event.x, event.y);
event.x = pt.x; event.y = pt.y;
@@ -392,13 +395,13 @@
if (!event.doit) break;
if (event.count != 0) {
event.doit = false;
- int oldIndex = getSelectionIndex ();
+ int oldIndex = getSelectionIndices ();
if (event.count > 0) {
select (Math.max (oldIndex - 1, 0));
} else {
select (Math.min (oldIndex + 1, getItemCount () - 1));
}
- if (oldIndex != getSelectionIndex ()) {
+ if (oldIndex != getSelectionIndices ()) {
Event e = new Event();
e.time = event.time;
e.stateMask = event.stateMask;
@@ -408,6 +411,7 @@
}
break;
}
+ */
case SWT.Selection: {
text.setFocus();
dropDown (!isDropped ());
@@ -420,7 +424,9 @@
String name = getClass ().getName ();
int index = name.lastIndexOf ('.');
if (!name.substring (0, index + 1).equals (PACKAGE_PREFIX)) {
+ /*- mifritscher: hmmhmm^^
SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+ */
}
}
/**
@@ -526,11 +532,12 @@
checkWidget ();
text.copy ();
}
-void createPopup(String[] items, int selectionIndex) {
+void createPopup(String[] items, int[] selectionIndices) {
// create shell and list
popup = new Shell (getShell (), SWT.NO_TRIM | SWT.ON_TOP);
int style = getStyle ();
- int listStyle = SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL;
+ // mifritscher
+ int listStyle = SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI;
if ((style & SWT.FLAT) != 0) listStyle |= SWT.FLAT;
if ((style & SWT.RIGHT_TO_LEFT) != 0) listStyle |= SWT.RIGHT_TO_LEFT;
if ((style & SWT.LEFT_TO_RIGHT) != 0) listStyle |= SWT.LEFT_TO_RIGHT;
@@ -547,7 +554,7 @@
list.addListener (listEvent, listener);
if (items != null) list.setItems (items);
- if (selectionIndex != -1) list.setSelection (selectionIndex);
+ if (selectionIndices != null) list.setSelection (selectionIndices);
}
/**
* Cuts the selected text.
@@ -621,12 +628,12 @@
if (!isVisible()) return;
if (getShell() != popup.getParent ()) {
String[] items = list.getItems ();
- int selectionIndex = list.getSelectionIndex ();
+ int[] selectionIndices = list.getSelectionIndices ();
list.removeListener (SWT.Dispose, listener);
popup.dispose();
popup = null;
list = null;
- createPopup (items, selectionIndex);
+ createPopup (items, selectionIndices);
}
Point comboSize = getSize ();
@@ -869,9 +876,9 @@
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*/
-public int getSelectionIndex () {
+public int[] getSelectionIndices () {
checkWidget ();
- return list.getSelectionIndex ();
+ return list.getSelectionIndices ();
}
@Override
public Shell getShell () {
@@ -1192,10 +1199,10 @@
case SWT.Dispose:
if (getShell () != popup.getParent ()) {
String[] items = list.getItems ();
- int selectionIndex = list.getSelectionIndex ();
+ int[] selectionIndices = list.getSelectionIndices ();
popup = null;
list = null;
- createPopup (items, selectionIndex);
+ createPopup (items, selectionIndices);
}
break;
case SWT.FocusIn: {
@@ -1226,15 +1233,26 @@
}
case SWT.MouseUp: {
if (event.button != 1) return;
- dropDown (false);
+ // mifritscher: Allow multi editing
+ if ((event.stateMask & SWT.CTRL) == 0 && (event.stateMask & SWT.SHIFT) == 0) {
+ dropDown (false);
+ }
break;
}
case SWT.Selection: {
- int index = list.getSelectionIndex ();
- if (index == -1) return;
- text.setText (list.getItem (index));
+ // mifritscher
+ int[] indices = list.getSelectionIndices ();
+ if (indices == null) return;
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0 ; i < indices.length;i++) {
+ sb.append(list.getItem (indices[i]));
+ if (i < indices.length -1) {
+ sb.append(',');
+ }
+ }
+ text.setText (sb.toString());
if (text.getEditable() && text.isFocusControl()) text.selectAll ();
- list.setSelection (index);
+ list.setSelection (indices);
Event e = new Event ();
e.time = event.time;
e.stateMask = event.stateMask;
@@ -1505,27 +1523,34 @@
* list. If the item at the index was already selected, it remains
* selected. Indices that are out of range are ignored.
*
- * @param index the index of the item to select
+ * @param indices the index of the item to select
*
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*/
-public void select (int index) {
+public void select (int[] indices) {
checkWidget();
- if (index == -1) {
+ //mifritscher: more or less unneeded...
+ if (indices == null) {
list.deselectAll ();
text.setText (""); //$NON-NLS-1$
return;
}
- if (0 <= index && index < list.getItemCount()) {
- if (index != getSelectionIndex()) {
- text.setText (list.getItem (index));
- if (text.getEditable() && text.isFocusControl()) text.selectAll ();
- list.select (index);
- list.showSelection ();
+ if (!Arrays.equals(indices, getSelectionIndices())) {
+ // mifritscher
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0 ; i < indices.length;i++) {
+ sb.append(list.getItem (indices[i]));
+ if (i < indices.length -1) {
+ sb.append(',');
+ }
}
+ text.setText (sb.toString());
+ if (text.getEditable() && text.isFocusControl()) text.selectAll ();
+ list.select (indices);
+ list.showSelection ();
}
}
@@ -1855,6 +1880,7 @@
if (isDisposed ()) break;
event.doit = keyEvent.doit;
if (!event.doit) break;
+ /*- mifritscher: not needed
if (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN) {
event.doit = false;
if ((event.stateMask & SWT.ALT) != 0) {
@@ -1865,13 +1891,13 @@
break;
}
- int oldIndex = getSelectionIndex ();
+ int oldIndex = getSelectionIndices ();
if (event.keyCode == SWT.ARROW_UP) {
select (Math.max (oldIndex - 1, 0));
} else {
select (Math.min (oldIndex + 1, getItemCount () - 1));
}
- if (oldIndex != getSelectionIndex ()) {
+ if (oldIndex != getSelectionIndices ()) {
Event e = new Event();
e.time = event.time;
e.stateMask = event.stateMask;
@@ -1879,6 +1905,7 @@
}
if (isDisposed ()) break;
}
+ */
// Further work : Need to add support for incremental search in
// pop up list as characters typed in text widget
@@ -1956,6 +1983,7 @@
if (text.getEditable() && text.isFocusControl()) text.selectAll ();
break;
}
+ /*- mifritscher: not needed
case SWT.MouseWheel: {
notifyListeners (SWT.MouseWheel, event);
event.type = SWT.None;
@@ -1963,13 +1991,13 @@
if (!event.doit) break;
if (event.count != 0) {
event.doit = false;
- int oldIndex = getSelectionIndex ();
+ int oldIndex = getSelectionIndices ();
if (event.count > 0) {
select (Math.max (oldIndex - 1, 0));
} else {
select (Math.min (oldIndex + 1, getItemCount () - 1));
}
- if (oldIndex != getSelectionIndex ()) {
+ if (oldIndex != getSelectionIndices ()) {
Event e = new Event();
e.time = event.time;
e.stateMask = event.stateMask;
@@ -1979,6 +2007,7 @@
}
break;
}
+ */
case SWT.Traverse: {
switch (event.detail) {
case SWT.TRAVERSE_ARROW_PREVIOUS:
The big advantage: it can be used e.g. in a CellEditor quite easiely (Copy ComboBoxCellEditor
to MultipleComboBoxCellEditor
, stuff the AbstractComboBoxCellEditor
in it, change the CCombo Widget and do some trivial int->int[] and Index->Indices exchanges). Or also other SWT/Jface stuff like in a Tree Viewer.
Btw, this patch is public domain, so of somebody would like to get it upstreamed: Go for it :-)