All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.viewers.CheckboxTableViewer Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Alexander Fedorov  - Bug 548314
 *******************************************************************************/
package org.eclipse.jface.viewers;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.pde.api.tools.annotations.NoExtend;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;

/**
 * A concrete viewer based on an SWT Table
 * control with checkboxes on each node.
 * 

This class supports setting an {@link ICheckStateProvider} to * set the checkbox states. To see standard SWT behavior, view * SWT Snippet274.

*

* This class is not intended to be subclassed outside the viewer framework. * It is designed to be instantiated with a pre-existing SWT table control and configured * with a domain-specific content provider, label provider, element filter (optional), * and element sorter (optional). *

*/ @NoExtend public class CheckboxTableViewer extends TableViewer implements ICheckable { /** * List of check state listeners (element type: ICheckStateListener). */ private ListenerList checkStateListeners = new ListenerList<>(); /** * Provides the desired state of the check boxes. */ private ICheckStateProvider checkStateProvider; /** * Creates a table viewer on a newly-created table control under the given parent. * The table control is created using the SWT style bits: * SWT.CHECK and SWT.BORDER. * The table has one column. * The viewer has no input, no content provider, a default label provider, * no sorter, and no filters. *

* This is equivalent to calling new CheckboxTableViewer(parent, SWT.BORDER). * See that constructor for more details. *

* * @param parent the parent control * * @deprecated use newCheckList(Composite, int) or new CheckboxTableViewer(Table) * instead (see below for details) */ @Deprecated public CheckboxTableViewer(Composite parent) { this(parent, SWT.BORDER); } /** * Creates a table viewer on a newly-created table control under the given parent. * The table control is created using the given SWT style bits, plus the * SWT.CHECK style bit. * The table has one column. * The viewer has no input, no content provider, a default label provider, * no sorter, and no filters. *

* This also adds a TableColumn for the single column, * and sets a TableLayout on the table which sizes the column to fill * the table for its initial sizing, but does nothing on subsequent resizes. *

*

* If the caller just needs to show a single column with no header, * it is preferable to use the newCheckList factory method instead, * since SWT properly handles the initial sizing and subsequent resizes in this case. *

*

* If the caller adds its own columns, uses Table.setHeadersVisible(true), * or needs to handle dynamic resizing of the table, it is recommended to * create the Table itself, specifying the SWT.CHECK style bit * (along with any other style bits needed), and use new CheckboxTableViewer(Table) * rather than this constructor. *

* * @param parent the parent control * @param style SWT style bits * * @deprecated use newCheckList(Composite, int) or new CheckboxTableViewer(Table) * instead (see above for details) */ @Deprecated public CheckboxTableViewer(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 SWT style bits, plus the * SWT.CHECK 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. *

* No TableColumn is added. SWT does not require a * TableColumn if showing only a single column with no header. * SWT correctly handles the initial sizing and subsequent resizes in this case. * * @param parent the parent control * @param style SWT style bits * * @since 2.0 * @return CheckboxTableViewer */ public static CheckboxTableViewer newCheckList(Composite parent, int style) { Table table = new Table(parent, SWT.CHECK | style); return new CheckboxTableViewer(table); } /** * Creates a table viewer on the given table control. * The SWT.CHECK 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 CheckboxTableViewer(Table table) { super(table); } @Override public void addCheckStateListener(ICheckStateListener listener) { checkStateListeners.add(listener); } /** * Sets the {@link ICheckStateProvider} for this {@link CheckboxTreeViewer}. * The check state provider will supply the logic for deciding whether the * check box associated with each item should be checked, grayed or * unchecked. * @param checkStateProvider The provider. * @since 3.5 */ public void setCheckStateProvider(ICheckStateProvider checkStateProvider) { this.checkStateProvider = checkStateProvider; refresh(); } /* * Extends this method to update check box states. */ @Override protected void doUpdateItem(Widget widget, Object element, boolean fullMap) { super.doUpdateItem(widget, element, fullMap); if(!widget.isDisposed()) { if(checkStateProvider != null) { setChecked(element, checkStateProvider.isChecked(element)); setGrayed(element, checkStateProvider.isGrayed(element)); } } } /** * 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, SWT.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, SWT.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(final CheckStateChangedEvent event) { for (ICheckStateListener l : checkStateListeners) { SafeRunnable.run(new SafeRunnable() { @Override public void run() { l.checkStateChanged(event); } }); } } @Override public boolean getChecked(Object element) { Widget widget = findItem(element); if (widget instanceof TableItem) { return ((TableItem) widget).getChecked(); } return false; } /** * Returns a list of elements corresponding to checked table items in this * viewer. *

* This method is typically used when preserving the interesting * state of a viewer; setCheckedElements is used during the restore. *

* * @return the array of checked elements * @see #setCheckedElements */ public Object[] getCheckedElements() { TableItem[] children = getTable().getItems(); List v = new ArrayList<>(children.length); for (TableItem item : children) { Object data = item.getData(); if (data != null) { if (item.getChecked()) { v.add(data); } } } return v.toArray(); } /** * Returns the grayed state of the given element. * * @param element the element * @return true if the element is grayed, * and false if not grayed */ public boolean getGrayed(Object element) { Widget widget = findItem(element); if (widget instanceof TableItem) { return ((TableItem) widget).getGrayed(); } return false; } /** * Returns a list of elements corresponding to grayed nodes in this * viewer. *

* This method is typically used when preserving the interesting * state of a viewer; setGrayedElements is used during the restore. *

* * @return the array of grayed elements * @see #setGrayedElements */ public Object[] getGrayedElements() { TableItem[] children = getTable().getItems(); List v = new ArrayList<>(children.length); for (TableItem item : children) { Object data = item.getData(); if (data != null) { if (item.getGrayed()) { v.add(data); } } } return v.toArray(); } @Override public void handleSelect(SelectionEvent event) { if (event.detail == SWT.CHECK) { super.handleSelect(event); // this will change the current selection TableItem item = (TableItem) event.item; Object data = item.getData(); if (data != null) { fireCheckStateChanged(new CheckStateChangedEvent(this, data, item.getChecked())); } } else { super.handleSelect(event); } } @Override protected void preservingSelection(Runnable updateCode) { if (!getPreserveSelection()) { return; } //If a check provider is present, it determines the state across input //changes. if(checkStateProvider != null) { //Try to preserve the selection, let the ICheckProvider manage //the check states super.preservingSelection(updateCode); return; } //Preserve checked items TableItem[] children = getTable().getItems(); CustomHashtable checked = newHashtable(children.length * 2 + 1); CustomHashtable grayed = newHashtable(children.length * 2 + 1); for (TableItem item : children) { Object data = item.getData(); if (data != null) { if (item.getChecked()) { checked.put(data, data); } if (item.getGrayed()) { grayed.put(data, data); } } } super.preservingSelection(updateCode); children = getTable().getItems(); for (TableItem item : children) { Object data = item.getData(); if (data != null) { item.setChecked(checked.containsKey(data)); item.setGrayed(grayed.containsKey(data)); } } } @Override public void removeCheckStateListener(ICheckStateListener listener) { checkStateListeners.remove(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 true if the element should be checked, * and false if it should be unchecked */ public void setAllChecked(boolean state) { TableItem[] children = getTable().getItems(); for (TableItem item : children) { if (item.getData() != null) { if (item.getChecked() != state) item.setChecked(state); } } } /** * Sets to the given value the grayed state for all elements in this viewer. * * @param state true if the element should be grayed, * and false if it should be ungrayed */ public void setAllGrayed(boolean state) { TableItem[] children = getTable().getItems(); for (TableItem item : children) { if (item.getData() != null) { if (item.getGrayed() != state) item.setGrayed(state); } } } @Override public boolean setChecked(Object element, boolean state) { Assert.isNotNull(element); Widget widget = findItem(element); if (widget instanceof TableItem) { TableItem item = (TableItem) widget; if (item.getChecked() != state) item.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. *

* This method is typically used when restoring the interesting * state of a viewer captured by an earlier call to getCheckedElements. *

* * @param elements the list of checked elements (element type: Object) * @see #getCheckedElements */ public void setCheckedElements(Object[] elements) { assertElementsNotNull(elements); CustomHashtable set = newHashtable(elements.length * 2 + 1); for (Object element : elements) { set.put(element, element); } TableItem[] items = getTable().getItems(); for (TableItem item : items) { Object element = item.getData(); if (element != null) { boolean check = set.containsKey(element); // only set if different, to avoid flicker if (item.getChecked() != check) { item.setChecked(check); } } } } /** * Sets the grayed state for the given element in this viewer. * * @param element the element * @param state true if the item should be grayed, * and false if it should be ungrayed * @return true if the element is visible and the gray * state could be set, and false otherwise */ public boolean setGrayed(Object element, boolean state) { Assert.isNotNull(element); Widget widget = findItem(element); if (widget instanceof TableItem) { TableItem item = (TableItem) widget; if (item.getGrayed() != state) item.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. *

* This method is typically used when restoring the interesting * state of a viewer captured by an earlier call to getGrayedElements. *

* * @param elements the array of grayed elements * * @see #getGrayedElements */ public void setGrayedElements(Object... elements) { assertElementsNotNull(elements); CustomHashtable set = newHashtable(elements.length * 2 + 1); for (Object element : elements) { set.put(element, element); } TableItem[] items = getTable().getItems(); for (TableItem item : items) { Object element = item.getData(); if (element != null) { boolean gray = set.containsKey(element); // only set if different, to avoid flicker if (item.getGrayed() != gray) { item.setGrayed(gray); } } } } }