Bug 474962 - it should be possible to support Radio Group for data
collection or enumeration, like ComboViewer
diff --git a/org.eclipse.xwt/src/org/eclipse/xwt/jface/JFacesHelper.java b/org.eclipse.xwt/src/org/eclipse/xwt/jface/JFacesHelper.java
index be7031f..ae2ddc1 100644
--- a/org.eclipse.xwt/src/org/eclipse/xwt/jface/JFacesHelper.java
+++ b/org.eclipse.xwt/src/org/eclipse/xwt/jface/JFacesHelper.java
@@ -66,6 +66,7 @@
JFACES_VIEWER = Class.forName("org.eclipse.jface.viewers.Viewer");
String[] jfaceClasses = new String[] {
+ "org.eclipse.xwt.jface.RadioGroupViewer",
"org.eclipse.jface.viewers.ComboViewer",
"org.eclipse.jface.viewers.ListViewer",
"org.eclipse.jface.viewers.TreeViewer",
diff --git a/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioGroup.java b/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioGroup.java
new file mode 100644
index 0000000..1686451
--- /dev/null
+++ b/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioGroup.java
@@ -0,0 +1,291 @@
+package org.eclipse.xwt.jface;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+
+public class RadioGroup extends Composite {
+ private final int cardinality;
+ private final int buttonStyle;
+
+ private RadioItem[] items = {};
+
+ private RadioItem selection = null;
+
+ public RadioGroup(Composite parent, int style) {
+ super(parent, checkCompositeStyle(style));
+ this.cardinality = checkCardinality(style);
+ this.buttonStyle = checkButtonStyle(style);
+
+ super.setLayout(new RowLayout(cardinality));
+
+ setBackgroundMode(SWT.INHERIT_DEFAULT);
+
+ addListener(SWT.Dispose, new Listener() {
+ public void handleEvent(Event event) {
+ handleDispose(event);
+ }
+ });
+ }
+
+ private static int checkCompositeStyle(int style) {
+ int result = style & SWT.BORDER;
+ if ((style & SWT.LEFT_TO_RIGHT) != 0)
+ result |= SWT.LEFT_TO_RIGHT;
+ else if ((style & SWT.RIGHT_TO_LEFT) != 0)
+ result |= SWT.RIGHT_TO_LEFT;
+ return result;
+ }
+
+ private int checkCardinality(int style) {
+ if ((style & SWT.VERTICAL) != 0)
+ return SWT.VERTICAL;
+ return SWT.HORIZONTAL;
+ }
+
+ private static int checkButtonStyle(int style) {
+ int result = 0;
+ if ((style & SWT.FLAT) != 0)
+ result |= SWT.FLAT;
+ if ((style & SWT.LEFT) != 0)
+ result |= SWT.LEFT;
+ else if ((style & SWT.CENTER) != 0)
+ result |= SWT.CENTER;
+ else if ((style & SWT.RIGHT) != 0)
+ result |= SWT.RIGHT;
+ else
+ result |= SWT.LEFT;
+ return result;
+ }
+
+ private void handleDispose(Event event) {
+ RadioItem[] items = getItems();
+ for (int i = 0; i < items.length; i++)
+ items[i].dispose();
+ }
+
+ public int getStyle() {
+ return super.getStyle() | buttonStyle | cardinality;
+ }
+
+ public void setLayout(Layout layout) {
+ checkWidget();
+ return;
+ }
+
+ public void clear(int position) {
+ checkWidget();
+ checkExistingPosition(position);
+ items[position].clear();
+ }
+
+ private void checkExistingPosition(int position) {
+ if (position < 0 || position >= getItemCount())
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ public void remove(RadioItem item) {
+ checkWidget();
+ if (item.isDisposed() || item.getParent() != this)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ item.dispose();
+ }
+
+ public void remove(int position) {
+ checkWidget();
+ checkExistingPosition(position);
+ items[position].dispose();
+ }
+
+ public void remove(int start, int end) {
+ checkWidget();
+ if (start > end)
+ return;
+ if (start < 0 || end >= items.length)
+ SWT.error(SWT.ERROR_INVALID_RANGE);
+
+ setLayoutDeferred(true);
+ try {
+ Item[] items = (Item[]) this.items.clone();
+ for (int i = start; i <= end; i++) {
+ items[i].dispose();
+ }
+ } finally {
+ setLayoutDeferred(false);
+ }
+ }
+
+ public void removeAll() {
+ checkWidget();
+ remove(0, items.length - 1);
+ }
+ public int getItemCount() {
+ checkWidget();
+ if (items == null)
+ return 0;
+ return items.length;
+ }
+
+ public void addSelectionListener(SelectionListener listener) {
+ checkWidget();
+ if (listener == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ TypedListener typedListener = new TypedListener(listener);
+ addListener(SWT.Selection, typedListener);
+ addListener(SWT.DefaultSelection, typedListener);
+ }
+
+ public void removeSelectionListener(SelectionListener listener) {
+ checkWidget();
+ removeListener(SWT.Selection, listener);
+ removeListener(SWT.DefaultSelection, listener);
+ }
+
+ public RadioItem[] getItems() {
+ checkWidget();
+ if (items == null)
+ return new RadioItem[0];
+ RadioItem[] result = new RadioItem[items.length];
+ System.arraycopy(items, 0, result, 0, items.length);
+ return result;
+ }
+
+ public int indexOf(RadioItem item) {
+ checkWidget();
+ if (items == null)
+ return -1;
+ if (item == null)
+ return -1;
+ for (int i = 0; i < items.length; i++) {
+ if (items[i] == item)
+ return i;
+ }
+ return -1;
+ }
+
+ public RadioItem getSelection() {
+ checkWidget();
+ return selection;
+ }
+
+ public int getSelectionIndex() {
+ checkWidget();
+ return indexOf(selection);
+ }
+
+ public void setSelection(RadioItem item) {
+ checkWidget();
+ if (selection == item)
+ return;
+ if (selection != null)
+ selection.deselect();
+ if (item != null) {
+ if (item.getParent() != this)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ item.select();
+ }
+ }
+
+ public void select(int index) {
+ checkWidget();
+ checkExistingPosition(index);
+ setSelection(items[index]);
+ }
+
+ public void deselectAll() {
+ checkWidget();
+ setSelection(null);
+ }
+
+ Button createButton(int itemStyle, int position) {
+ // Check add position (which may throw exception) before creating button
+ position = checkAddPosition(position);
+
+ Button button = new Button(this, computeButtonStyle(itemStyle));
+
+ if (position < items.length)
+ button.moveAbove(items[position].getButton());
+
+ layout(new Control[] { button });
+
+ return button;
+ }
+
+ private int computeButtonStyle(int itemStyle) {
+ int buttonStyle = SWT.RADIO | this.buttonStyle;
+
+ int itemStyleMask = SWT.LEFT | SWT.CENTER | SWT.RIGHT;
+ if ((itemStyle & itemStyleMask) != 0) {
+ buttonStyle &= ~itemStyleMask;
+ buttonStyle |= itemStyle;
+ }
+
+ return buttonStyle;
+ }
+
+ void addItem(RadioItem item, int position) {
+ position = checkAddPosition(position);
+ RadioItem[] newItems = new RadioItem[items == null ? 1
+ : items.length + 1];
+
+ if (items == null) {
+ items = new RadioItem[] { item };
+ } else {
+ System.arraycopy(items, 0, newItems, 0, position);
+ newItems[position] = item;
+ System.arraycopy(items, position, newItems, position + 1,
+ items.length - position);
+ items = newItems;
+ }
+ }
+
+ private int checkAddPosition(int position) {
+ if (position == -1)
+ position = getItemCount();
+ else if (position < 0 || position > getItemCount())
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ return position;
+ }
+
+ void removeItem(RadioItem item) {
+ checkWidget();
+
+ int position = indexOf(item);
+ if (position != -1) {
+ RadioItem[] newItems = new RadioItem[items.length - 1];
+ System.arraycopy(items, 0, newItems, 0, position);
+ System.arraycopy(items, position + 1, newItems, position,
+ newItems.length - position);
+ items = newItems;
+ }
+
+ if (selection == item) {
+ selection = null;
+ notifyListeners(SWT.Selection, null);
+ }
+ }
+
+ void itemSelected(RadioItem item) {
+ RadioItem oldSelection = selection;
+ RadioItem newSelection = item.isSelected() ? item : null;
+ if (oldSelection == newSelection)
+ return;
+
+ selection = newSelection;
+
+ Event event = new Event();
+ event.item = selection;
+ event.index = indexOf(selection);
+
+ notifyListeners(SWT.Selection, event);
+ }
+}
diff --git a/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioGroupViewer.java b/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioGroupViewer.java
new file mode 100644
index 0000000..a2fdddd
--- /dev/null
+++ b/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioGroupViewer.java
@@ -0,0 +1,118 @@
+package org.eclipse.xwt.jface;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.viewers.AbstractListViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+public class RadioGroupViewer extends AbstractListViewer {
+ private RadioGroup radioGroup;
+
+ public RadioGroupViewer(Composite parent) {
+ this(parent, SWT.NONE);
+ }
+
+ public RadioGroupViewer(Composite parent, int style) {
+ this(new RadioGroup(parent, style));
+ }
+
+ public RadioGroupViewer(RadioGroup group) {
+ Assert.isNotNull(group);
+ this.radioGroup = group;
+ hookControl(group);
+ }
+
+ public Control getControl() {
+ return radioGroup;
+ }
+
+ public RadioGroup getRadioGroup() {
+ return radioGroup;
+ }
+
+ public void reveal(Object element) {
+ }
+
+ protected void listShowSelection() {
+ }
+
+ protected void listSetSelection(int[] ixs) {
+ for (int idx = 0; idx < ixs.length; idx++) {
+ radioGroup.select(ixs[idx]);
+ }
+ }
+
+ protected int[] listGetSelectionIndices() {
+ return new int[] { radioGroup.getSelectionIndex() };
+ }
+
+ protected void listAdd(String string, int index) {
+ radioGroup.setLayoutDeferred(true);
+ try {
+ RadioItem item = new RadioItem(radioGroup, SWT.NONE, index);
+ item.setText(string);
+ } finally {
+ radioGroup.setLayoutDeferred(false);
+ }
+ }
+ protected void listDeselectAll() {
+ radioGroup.deselectAll();
+ }
+
+ protected int listGetItemCount() {
+ return radioGroup.getItemCount();
+ }
+ protected void listRemove(int index) {
+ radioGroup.remove(index);
+ }
+
+ protected void listRemoveAll() {
+ radioGroup.removeAll();
+ }
+ protected void listSetItem(int index, String string) {
+ RadioItem item = radioGroup.getItems()[index];
+ item.setText(string);
+ }
+ protected void listSetItems(String[] labels) {
+ radioGroup.removeAll();
+
+ for (int i = 0; i < labels.length; i++) {
+ RadioItem item = new RadioItem(radioGroup, SWT.NONE);
+ item.setText(labels[i]);
+ }
+ }
+
+ public void add(Object element) {
+ super.add(element);
+ }
+
+ public void add(Object[] elements) {
+ super.add(elements);
+ }
+ public void insert(Object element, int position) {
+ super.insert(element, position);
+ }
+ public Object getElementAt(int index) {
+ return super.getElementAt(index);
+ }
+ protected int indexForElement(Object element) {
+ return super.indexForElement(element);
+ }
+
+ protected int listGetTopIndex() {
+ return super.listGetTopIndex();
+ }
+
+ protected void listSetTopIndex(int index) {
+ super.listSetTopIndex(index);
+ }
+
+ public void remove(Object element) {
+ super.remove(element);
+ }
+
+ public void remove(Object[] elements) {
+ super.remove(elements);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioItem.java b/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioItem.java
new file mode 100644
index 0000000..4ca28f2
--- /dev/null
+++ b/org.eclipse.xwt/src/org/eclipse/xwt/jface/RadioItem.java
@@ -0,0 +1,163 @@
+package org.eclipse.xwt.jface;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Listener;
+
+public class RadioItem extends Item {
+ private RadioGroup parent;
+ private Button button;
+
+ public RadioItem(RadioGroup parent, int style) {
+ this(parent, style, -1);
+ }
+
+ public RadioItem(final RadioGroup parent, int style, int index) {
+ super(parent, checkStyle(style), checkIndex(parent, index));
+ this.parent = parent;
+ this.button = parent.createButton(getStyle(), index);
+
+ Listener listener = new Listener() {
+ public void handleEvent(Event event) {
+ if (event.type == SWT.Selection)
+ handleSelection(event);
+ else if (event.type == SWT.Dispose)
+ handleDispose(event);
+ }
+ };
+ button.addListener(SWT.Selection, listener);
+ addListener(SWT.Dispose, listener);
+
+ parent.addItem(this, index);
+ }
+
+ private static int checkStyle(int style) {
+ int result = 0;
+ if ((style & SWT.LEFT) != 0)
+ result |= SWT.LEFT;
+ else if ((style & SWT.CENTER) != 0)
+ result |= SWT.CENTER;
+ else if ((style & SWT.RIGHT) != 0)
+ result |= SWT.RIGHT;
+ return result;
+ }
+
+ private static int checkIndex(RadioGroup parent, int position) {
+ if (position == -1)
+ return parent.getItemCount();
+ if (position < 0 || position > parent.getItemCount())
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ return position;
+ }
+
+ private void handleSelection(Event event) {
+ parent.itemSelected(this);
+ }
+
+ private void handleDispose(Event event) {
+ if (parent != null) {
+ parent.removeItem(RadioItem.this);
+ }
+ if (button != null) {
+ button.dispose();
+ if (parent != null && !parent.isDisposed())
+ parent.layout(false);
+ }
+ RadioItem.this.parent = null;
+ button = null;
+ }
+
+ public RadioGroup getParent() {
+ return parent;
+ }
+
+ public String getText() {
+ checkWidget();
+ return button.getText();
+ }
+
+ public void setText(String string) {
+ checkWidget();
+ button.setText(string);
+ parent.layout(new Control[] { button });
+ }
+
+ public Image getImage() {
+ checkWidget();
+ return button.getImage();
+ }
+
+ public void setImage(Image image) {
+ checkWidget();
+ button.setImage(image);
+ parent.layout(new Control[] { button });
+ }
+
+ public Color getForeground() {
+ checkWidget();
+ return button.getForeground();
+ }
+
+ public void setForeground(Color foreground) {
+ checkWidget();
+ if (foreground == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ button.setForeground(foreground);
+ }
+
+ public Color getBackground() {
+ checkWidget();
+ return button.getBackground();
+ }
+
+ public void setBackground(Color background) {
+ checkWidget();
+ if (background == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ button.setBackground(background);
+ }
+
+ public Font getFont() {
+ checkWidget();
+ return button.getFont();
+ }
+
+ public void setFont(Font font) {
+ checkWidget();
+ if (font == null)
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ button.setFont(font);
+ }
+
+ public Button getButton() {
+ return button;
+ }
+
+ public boolean isSelected() {
+ return button.getSelection();
+ }
+
+ void select() {
+ button.setSelection(true);
+ parent.itemSelected(this);
+ }
+
+ void deselect() {
+ button.setSelection(false);
+ parent.itemSelected(this);
+ }
+
+ void clear() {
+ setText("");
+ setImage(null);
+ setFont(parent.getFont());
+ setForeground(parent.getForeground());
+ setBackground(parent.getBackground());
+ }
+}
\ No newline at end of file