Mercurial > projects > dwt-addons
view dwtx/jface/viewers/CheckboxTableViewer.d @ 90:7ffeace6c47f
Update 3.4M7 to 3.4
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 06 Jul 2008 23:30:07 +0200 |
parents | ea8ff534f622 |
children | 04b47443bb01 |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Port to the D programming language: * Frank Benoit <benoit@tionex.de> *******************************************************************************/ module dwtx.jface.viewers.CheckboxTableViewer; import dwtx.jface.viewers.ICheckable; import dwtx.jface.viewers.TableViewer; import dwtx.jface.viewers.ICheckStateListener; import dwtx.jface.viewers.CheckStateChangedEvent; import dwtx.jface.viewers.TableLayout; import dwtx.jface.viewers.ColumnWeightData; import dwtx.jface.viewers.CustomHashtable; import tango.util.collection.ArraySeq; import tango.util.collection.model.Seq; import dwt.DWT; import dwt.events.SelectionEvent; import dwt.widgets.Composite; import dwt.widgets.Table; import dwt.widgets.TableColumn; import dwt.widgets.TableItem; import dwt.widgets.Widget; import dwtx.core.runtime.Assert; import dwtx.core.runtime.ListenerList; import dwtx.jface.util.SafeRunnable; import dwt.dwthelper.utils; import dwt.dwthelper.Runnable; /** * A concrete viewer based on an DWT <code>Table</code> * control with checkboxes on each node. * <p> * This class is not intended to be subclassed outside the viewer framework. * It is designed to be instantiated with a pre-existing DWT table control and configured * with a domain-specific content provider, label provider, element filter (optional), * and element sorter (optional). * </p> * @noextend This class is not intended to be subclassed by clients. */ public class CheckboxTableViewer : TableViewer, ICheckable { alias TableViewer.preservingSelection preservingSelection; /** * List of check state listeners (element type: <code>ICheckStateListener</code>). */ private ListenerList checkStateListeners; /** * Creates a table viewer on a newly-created table control under the given parent. * The table control is created using the DWT style bits: * <code>DWT.CHECK</code> and <code>DWT.BORDER</code>. * The table has one column. * The viewer has no input, no content provider, a default label provider, * no sorter, and no filters. * <p> * This is equivalent to calling <code>new CheckboxTableViewer(parent, DWT.BORDER)</code>. * See that constructor for more details. * </p> * * @param parent the parent control * * @deprecated use newCheckList(Composite, int) or new CheckboxTableViewer(Table) * instead (see below for details) */ public this(Composite parent) { this(parent, DWT.BORDER); } /** * Creates a table viewer on a newly-created table control under the given parent. * The table control is created using the given DWT style bits, plus the * <code>DWT.CHECK</code> style bit. * The table has one column. * The viewer has no input, no content provider, a default label provider, * no sorter, and no filters. * <p> * This also adds a <code>TableColumn</code> for the single column, * and sets a <code>TableLayout</code> on the table which sizes the column to fill * the table for its initial sizing, but does nothing on subsequent resizes. * </p> * <p> * If the caller just needs to show a single column with no header, * it is preferable to use the <code>newCheckList</code> factory method instead, * since DWT properly handles the initial sizing and subsequent resizes in this case. * </p> * <p> * If the caller adds its own columns, uses <code>Table.setHeadersVisible(true)</code>, * or needs to handle dynamic resizing of the table, it is recommended to * create the <code>Table</code> itself, specifying the <code>DWT.CHECK</code> style bit * (along with any other style bits needed), and use <code>new CheckboxTableViewer(Table)</code> * rather than this constructor. * </p> * * @param parent the parent control * @param style DWT style bits * * @deprecated use newCheckList(Composite, int) or new CheckboxTableViewer(Table) * instead (see above for details) */ public this(Composite parent, int style) { this(createTable(parent, style)); } /** * Creates a table viewer on a newly-created table control under the given parent. * The table control is created using the given DWT style bits, plus the * <code>DWT.CHECK</code> style bit. * The table shows its contents in a single column, with no header. * The viewer has no input, no content provider, a default label provider, * no sorter, and no filters. * <p> * No <code>TableColumn</code> is added. DWT does not require a * <code>TableColumn</code> if showing only a single column with no header. * DWT correctly handles the initial sizing and subsequent resizes in this case. * * @param parent the parent control * @param style DWT style bits * * @since 2.0 * @return CheckboxTableViewer */ public static CheckboxTableViewer newCheckList(Composite parent, int style) { Table table = new Table(parent, DWT.CHECK | style); return new CheckboxTableViewer(table); } /** * Creates a table viewer on the given table control. * The <code>DWT.CHECK</code> style bit must be set on the given table control. * The viewer has no input, no content provider, a default label provider, * no sorter, and no filters. * * @param table the table control */ public this(Table table) { super(table); checkStateListeners = new ListenerList(); } /* (non-Javadoc) * Method declared on ICheckable. */ public void addCheckStateListener(ICheckStateListener listener) { checkStateListeners.add(cast(Object)listener); } /** * Creates a new table control with one column. * * @param parent the parent control * @param style style bits * @return a new table control */ protected static Table createTable(Composite parent, int style) { Table table = new Table(parent, DWT.CHECK | style); // Although this table column is not needed, and can cause resize problems, // it can't be removed since this would be a breaking change against R1.0. // See bug 6643 for more details. new TableColumn(table, DWT.NONE); TableLayout layout = new TableLayout(); layout.addColumnData(new ColumnWeightData(100)); table.setLayout(layout); return table; } /** * Notifies any check state listeners that a check state changed has been received. * Only listeners registered at the time this method is called are notified. * * @param event a check state changed event * * @see ICheckStateListener#checkStateChanged */ private void fireCheckStateChanged(CheckStateChangedEvent event) { Object[] array = checkStateListeners.getListeners(); for (int i = 0; i < array.length; i++) { SafeRunnable.run(new class(cast(ICheckStateListener) array[i], event) SafeRunnable { ICheckStateListener l; CheckStateChangedEvent event_; this(ICheckStateListener a,CheckStateChangedEvent b){ event_=b; l = a; } public void run() { l.checkStateChanged(event_); } }); } } /* (non-Javadoc) * Method declared on ICheckable. */ public bool getChecked(Object element) { Widget widget = findItem(element); if ( auto ti = cast(TableItem) widget ) { return ti.getChecked(); } return false; } /** * Returns a list of elements corresponding to checked table items in this * viewer. * <p> * This method is typically used when preserving the interesting * state of a viewer; <code>setCheckedElements</code> is used during the restore. * </p> * * @return the array of checked elements * @see #setCheckedElements */ public Object[] getCheckedElements() { TableItem[] children = getTable().getItems(); auto v = new ArraySeq!(Object); v.capacity(children.length); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; if (item.getChecked()) { v.append(item.getData()); } } return v.toArray(); } /** * Returns the grayed state of the given element. * * @param element the element * @return <code>true</code> if the element is grayed, * and <code>false</code> if not grayed */ public bool getGrayed(Object element) { Widget widget = findItem(element); if ( auto ti = cast(TableItem) widget ) { return ti.getGrayed(); } return false; } /** * Returns a list of elements corresponding to grayed nodes in this * viewer. * <p> * This method is typically used when preserving the interesting * state of a viewer; <code>setGrayedElements</code> is used during the restore. * </p> * * @return the array of grayed elements * @see #setGrayedElements */ public Object[] getGrayedElements() { TableItem[] children = getTable().getItems(); auto v = new ArraySeq!(Object); v.capacity(children.length); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; if (item.getGrayed()) { v.append(item.getData()); } } return v.toArray(); } /* (non-Javadoc) * Method declared on StructuredViewer. */ public override void handleSelect(SelectionEvent event) { if (event.detail is DWT.CHECK) { super.handleSelect(event); // this will change the current selection TableItem item = cast(TableItem) event.item; Object data = item.getData(); if (data !is null) { fireCheckStateChanged(new CheckStateChangedEvent(this, data, item.getChecked())); } } else { super.handleSelect(event); } } /* (non-Javadoc) * Method declared on Viewer. */ protected override void preservingSelection(Runnable updateCode) { TableItem[] children = getTable().getItems(); CustomHashtable checked = newHashtable(children.length * 2 + 1); CustomHashtable grayed = newHashtable(children.length * 2 + 1); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; Object data = item.getData(); if (data !is null) { if (item.getChecked()) { checked.put(data, data); } if (item.getGrayed()) { grayed.put(data, data); } } } super.preservingSelection(updateCode); children = getTable().getItems(); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; Object data = item.getData(); if (data !is null) { item.setChecked(checked.containsKey(data)); item.setGrayed(grayed.containsKey(data)); } } } /* (non-Javadoc) * Method declared on ICheckable. */ public void removeCheckStateListener(ICheckStateListener listener) { checkStateListeners.remove(cast(Object)listener); } /** * Sets to the given value the checked state for all elements in this viewer. * Does not fire events to check state listeners. * * @param state <code>true</code> if the element should be checked, * and <code>false</code> if it should be unchecked */ public void setAllChecked(bool state) { TableItem[] children = getTable().getItems(); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; item.setChecked(state); } } /** * Sets to the given value the grayed state for all elements in this viewer. * * @param state <code>true</code> if the element should be grayed, * and <code>false</code> if it should be ungrayed */ public void setAllGrayed(bool state) { TableItem[] children = getTable().getItems(); for (int i = 0; i < children.length; i++) { TableItem item = children[i]; item.setGrayed(state); } } /* (non-Javadoc) * Method declared on ICheckable. */ public bool setChecked(Object element, bool state) { Assert.isNotNull(element); Widget widget = findItem(element); if ( auto ti = cast(TableItem) widget ) { ti.setChecked(state); return true; } return false; } /** * Sets which nodes are checked in this viewer. * The given list contains the elements that are to be checked; * all other nodes are to be unchecked. * Does not fire events to check state listeners. * <p> * This method is typically used when restoring the interesting * state of a viewer captured by an earlier call to <code>getCheckedElements</code>. * </p> * * @param elements the list of checked elements (element type: <code>Object</code>) * @see #getCheckedElements */ public void setCheckedElements(Object[] elements) { assertElementsNotNull(elements); CustomHashtable set = newHashtable(elements.length * 2 + 1); for (int i = 0; i < elements.length; ++i) { set.put(elements[i], elements[i]); } TableItem[] items = getTable().getItems(); for (int i = 0; i < items.length; ++i) { TableItem item = items[i]; Object element = item.getData(); if (element !is null) { bool check = set.containsKey(element); // only set if different, to avoid flicker if (item.getChecked() !is check) { item.setChecked(check); } } } } /** * Sets the grayed state for the given element in this viewer. * * @param element the element * @param state <code>true</code> if the item should be grayed, * and <code>false</code> if it should be ungrayed * @return <code>true</code> if the element is visible and the gray * state could be set, and <code>false</code> otherwise */ public bool setGrayed(Object element, bool state) { Assert.isNotNull(element); Widget widget = findItem(element); if ( auto ti = cast(TableItem) widget ) { ti.setGrayed(state); return true; } return false; } /** * Sets which nodes are grayed in this viewer. * The given list contains the elements that are to be grayed; * all other nodes are to be ungrayed. * <p> * This method is typically used when restoring the interesting * state of a viewer captured by an earlier call to <code>getGrayedElements</code>. * </p> * * @param elements the array of grayed elements * * @see #getGrayedElements */ public void setGrayedElements(Object[] elements) { assertElementsNotNull(elements); CustomHashtable set = newHashtable(elements.length * 2 + 1); for (int i = 0; i < elements.length; ++i) { set.put(elements[i], elements[i]); } TableItem[] items = getTable().getItems(); for (int i = 0; i < items.length; ++i) { TableItem item = items[i]; Object element = item.getData(); if (element !is null) { bool gray = set.containsKey(element); // only set if different, to avoid flicker if (item.getGrayed() !is gray) { item.setGrayed(gray); } } } } }