Java tutorial
/* * 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(); } }); } } }