core/com.nokia.cpp.utils.ui/src/com/nokia/cpp/internal/api/utils/ui/RadioButtonTableViewer.java
Add S60 5.2 support.
/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.cpp.internal.api.utils.ui;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.*;
import com.nokia.cpp.internal.api.utils.core.ListenerList;
import java.util.*;
import java.util.Map.Entry;
/**
* A TableViewer supporting embedded radio button controls.
* The content provider should implement the IRadioButtonContentProvider
* interface in order to tell the viewer which items have radio buttons
* and which is the initially selected item.
*/
public class RadioButtonTableViewer extends TableViewer {
class RadioItem {
TableEditor editor;
Button button;
}
/**
* Callback to notify clients when the currently
* selected item has changed.
*/
public interface IRadioStateListener {
/** Called when current radio button changes.
* @param prevSelected previous selected item, or null
* @param newSelected new selected item, or null
*/
void radioStateChanged(Object prevSelected, Object newSelected);
}
public interface IRadioButtonContentProvider {
/**
* Return the element whose radio button should be selected
*/
Object getSelectedElement();
/**
* Return true if the element should have a radio button
*/
boolean hasRadioButton(Object element);
}
private int radioColumn = 0;
private boolean forceSelectedItem = true;
private Map<Object, RadioItem> itemMap = new HashMap<Object, RadioItem>();
private ListenerList<IRadioStateListener> listeners = new ListenerList<IRadioStateListener>();
private int style = 0;
public RadioButtonTableViewer(Table table) {
super(table);
}
public void addRadioStateListener(IRadioStateListener listener) {
listeners.add(listener);
}
public void removeRadioStateListener(IRadioStateListener listener) {
listeners.remove(listener);
}
/**
* Set the column to hold radio buttons. Must be set
* before the viewer is initially populated.
* @param column the column index
*/
public void setRadioColumn(int column) {
this.radioColumn = column;
}
/**
* When true, the viewer attempts to make
* @param force
*/
public void setForceSelectedIem(boolean force) {
this.forceSelectedItem = force;
}
@Override
protected void inputChanged(Object input, Object oldInput) {
super.inputChanged(input, oldInput);
IContentProvider cp = getContentProvider();
if (cp instanceof IRadioButtonContentProvider) {
IRadioButtonContentProvider rbcp = (IRadioButtonContentProvider) cp;
Object selectedElement = rbcp.getSelectedElement();
if (selectedElement != null) {
setSelectedItem(selectedElement);
}
else if (forceSelectedItem) {
forceSelectedItem();
}
}
}
private void fireRadioStateChanged(Object oldSelected, Object newSelected) {
for (IRadioStateListener l : listeners) {
l.radioStateChanged(oldSelected, newSelected);
}
}
public void setSelectedItem(Object item) {
RadioItem ri = itemMap.get(item);
if (ri != null) {
for (RadioItem currRI : itemMap.values()) {
currRI.button.setSelection(currRI == ri);
}
}
}
public Object getSelectedItem() {
Object result = null;
for (Iterator<Entry<Object, RadioItem>> iter = itemMap.entrySet().iterator(); iter.hasNext();) {
Entry<Object, RadioItem> entry = iter.next();
if (entry.getValue().button.getSelection()) {
result = entry.getKey();
break;
}
}
return result;
}
private void updateSelectedRadio(Button changedButton, boolean isSelected) {
Object oldSelected = null;
Object newSelected = null;
// ensure single item only is selected
if (isSelected) {
for (Iterator<Entry<Object, RadioItem>> iter = itemMap.entrySet().iterator(); iter.hasNext();) {
Entry<Object, RadioItem> entry = iter.next();
Button currBtn = entry.getValue().button;
if (currBtn.getSelection()) {
if (currBtn == changedButton) {
newSelected = entry.getKey();
} else {
oldSelected = entry.getKey();
currBtn.setSelection(false);
}
}
}
fireRadioStateChanged(oldSelected, newSelected);
}
// ensure some item is selected, if possible
else if (forceSelectedItem) {
forceSelectedItem();
}
}
public void forceSelectedItem() {
if (getSelectedItem() == null) {
Object newSelected = null;
// selected first eligible item, from top down
for (int i = 0; i < getTable().getItemCount(); i++) {
Object curr = getElementAt(i);
RadioItem ri = itemMap.get(curr);
if (ri != null) {
ri.button.setSelection(true);
newSelected = curr;
break;
}
}
if (newSelected != null) {
fireRadioStateChanged(null, newSelected);
}
}
}
/**
* Set additional style bits for radio button appearance.
* Most likely style added may be FLAT when in a non-3D view.
* @param style int
* @see SWT#FLAT
*/
public void setStyle(int style) {
this.style = style;
}
/**
* We override associate to maintain each items optional
* radio button information.
*/
@Override
protected void associate(Object element, Item item) {
super.associate(element, item);
IContentProvider contentProvider = getContentProvider();
if (contentProvider instanceof IRadioButtonContentProvider) {
Table table = getTable();
IRadioButtonContentProvider rbcp = (IRadioButtonContentProvider) contentProvider;
RadioItem ri = itemMap.get(element);
if (rbcp.hasRadioButton(element)) {
if (ri == null) {
ri = new RadioItem();
itemMap.put(element, ri);
ri.editor = new TableEditor(table);
ri.button = new Button(table, SWT.RADIO | style);
ri.button.pack();
ri.button.setBackground(table.getBackground());
ri.editor.grabHorizontal = true;
ri.editor.setEditor(ri.button, (TableItem)item, radioColumn);
ri.editor.minimumWidth = ri.button.getSize().x;
ri.editor.horizontalAlignment = SWT.LEFT;
ri.button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Button btn = (Button) e.getSource();
updateSelectedRadio(btn, btn.getSelection());
}
});
}
}
else if (ri != null) {
ri.editor.dispose();
ri.button.dispose();
itemMap.remove(element);
}
}
}
/**
* We override disassociate to clean up any
* allocated radio button information and to
* help implement force selection.
*/
@Override
protected void disassociate(Item item) {
boolean wasSelected = false;
Object element = item.getData();
RadioItem ri = itemMap.get(element);
if (ri != null) {
wasSelected = ri.button.getSelection();
ri.editor.dispose();
ri.button.dispose();
itemMap.remove(element);
}
super.disassociate(item);
if (wasSelected && forceSelectedItem) {
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
forceSelectedItem();
}
});
}
}
}