diff dwtx/jface/viewers/TableViewer.d @ 10:b6c35faf97c8

Viewers
author Frank Benoit <benoit@tionex.de>
date Mon, 31 Mar 2008 00:47:19 +0200
parents
children cf7413989c65
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TableViewer.d	Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ *     Tom Schindl <tom.schindl@bestsolution.at> - concept of ViewerRow,
+ *                                                 fix for 159597, refactoring (bug 153993),
+ *                                                 widget-independency (bug 154329), fix for 187826, 191468
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+
+module dwtx.jface.viewers.TableViewer;
+
+import dwtx.jface.viewers.AbstractTableViewer;
+import dwtx.jface.viewers.TableViewerRow;
+import dwtx.jface.viewers.ColumnViewerEditor;
+import dwtx.jface.viewers.ISelection;
+import dwtx.jface.viewers.ViewerRow;
+import dwtx.jface.viewers.TableViewerEditor;
+import dwtx.jface.viewers.ColumnViewerEditorActivationStrategy;
+
+import dwt.DWT;
+import dwt.graphics.Point;
+import dwt.widgets.Composite;
+import dwt.widgets.Control;
+import dwt.widgets.Item;
+import dwt.widgets.Table;
+import dwt.widgets.TableItem;
+import dwt.widgets.Widget;
+import dwtx.core.runtime.Assert;
+
+import dwt.dwthelper.utils;
+import dwt.dwthelper.Runnable;
+
+/**
+ * A concrete viewer based on a DWT <code>Table</code> control.
+ * <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, table label provider,
+ * element filter (optional), and element sorter (optional).
+ * </p>
+ * <p>
+ * Label providers for table viewers must implement either the
+ * <code>ITableLabelProvider</code> or the <code>ILabelProvider</code>
+ * interface (see <code>TableViewer.setLabelProvider</code> for more details).
+ * </p>
+ * <p>
+ * As of 3.1 the TableViewer now supports the DWT.VIRTUAL flag. If the
+ * underlying table is DWT.VIRTUAL, the content provider may implement
+ * {@link ILazyContentProvider} instead of {@link IStructuredContentProvider}.
+ * Note that in this case, the viewer does not support sorting or filtering.
+ * Also note that in this case, the Widget based APIs may return null if the
+ * element is not specified or not created yet.
+ * </p>
+ * <p>
+ * Users of DWT.VIRTUAL should also avoid using getItems() from the Table within
+ * the TreeViewer as this does not necessarily generate a callback for the
+ * TreeViewer to populate the items. It also has the side effect of creating all
+ * of the items thereby eliminating the performance improvements of DWT.VIRTUAL.
+ * </p>
+ *
+ * @see DWT#VIRTUAL
+ * @see #doFindItem(Object)
+ * @see #internalRefresh(Object, bool)
+ */
+public class TableViewer : AbstractTableViewer {
+
+    public alias AbstractTableViewer.preservingSelection preservingSelection;
+
+    /**
+     * This viewer's table control.
+     */
+    private Table table;
+
+    /**
+     * The cached row which is reused all over
+     */
+    private TableViewerRow cachedRow;
+
+    /**
+     * 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>MULTI, H_SCROLL, V_SCROLL,</code> and <code>BORDER</code>. The
+     * viewer has no input, no content provider, a default label provider, no
+     * sorter, and no filters. The table has no columns.
+     *
+     * @param parent
+     *            the parent control
+     */
+    public this(Composite parent) {
+        this(parent, DWT.MULTI | DWT.H_SCROLL | DWT.V_SCROLL | DWT.BORDER);
+    }
+
+    /**
+     * Creates a table viewer on a newly-created table control under the given
+     * parent. The table control is created using the given style bits. The
+     * viewer has no input, no content provider, a default label provider, no
+     * sorter, and no filters. The table has no columns.
+     *
+     * @param parent
+     *            the parent control
+     * @param style
+     *            DWT style bits
+     */
+    public this(Composite parent, int style) {
+        this(new Table(parent, style));
+    }
+
+    /**
+     * Creates a table viewer 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) {
+        this.table = table;
+        hookControl(table);
+    }
+
+    public Control getControl() {
+        return table;
+    }
+
+    /**
+     * Returns this table viewer's table control.
+     *
+     * @return the table control
+     */
+    public Table getTable() {
+        return table;
+    }
+
+    protected ColumnViewerEditor createViewerEditor() {
+        return new TableViewerEditor(this,null,new ColumnViewerEditorActivationStrategy(this),ColumnViewerEditor.DEFAULT);
+    }
+
+    /**
+     * <p>
+     * Sets a new selection for this viewer and optionally makes it visible. The
+     * TableViewer implementation of this method is inefficient for the
+     * ILazyContentProvider as lookup is done by indices rather than elements
+     * and may require population of the entire table in worse case.
+     * </p>
+     * <p>
+     * Use Table#setSelection(int[] indices) and Table#showSelection() if you
+     * wish to set selection more efficiently when using a ILazyContentProvider.
+     * </p>
+     *
+     * @param selection
+     *            the new selection
+     * @param reveal
+     *            <code>true</code> if the selection is to be made visible,
+     *            and <code>false</code> otherwise
+     * @see Table#setSelection(int[])
+     * @see Table#showSelection()
+     */
+    public void setSelection(ISelection selection, bool reveal) {
+        super.setSelection(selection, reveal);
+    }
+
+    protected ViewerRow getViewerRowFromItem(Widget item) {
+        if( cachedRow is null ) {
+            cachedRow = new TableViewerRow(cast(TableItem) item);
+        } else {
+            cachedRow.setItem(cast(TableItem) item);
+        }
+
+        return cachedRow;
+    }
+
+    /**
+     * Create a new row with style at index
+     *
+     * @param style
+     * @param rowIndex
+     * @return ViewerRow
+     * @since 3.3
+     */
+    protected ViewerRow internalCreateNewRowPart(int style, int rowIndex) {
+        TableItem item;
+
+        if (rowIndex >= 0) {
+            item = new TableItem(table, style, rowIndex);
+        } else {
+            item = new TableItem(table, style);
+        }
+
+        return getViewerRowFromItem(item);
+    }
+
+    protected Item getItemAt(Point p) {
+        TableItem[] selection = table.getSelection();
+
+        if( selection.length is 1 ) {
+            int columnCount = table.getColumnCount();
+
+            for( int i = 0; i < columnCount; i++ ) {
+                if( selection[0].getBounds(i).contains(p) ) {
+                    return selection[0];
+                }
+            }
+        }
+
+        return table.getItem(p);
+    }
+
+    // Methods to provide widget independency
+
+    protected int doGetItemCount() {
+        return table.getItemCount();
+    }
+
+    protected int doIndexOf(Item item) {
+        return table.indexOf(cast(TableItem)item);
+    }
+
+    protected void doSetItemCount(int count) {
+        table.setItemCount(count);
+    }
+
+    protected Item[] doGetItems() {
+        return table.getItems();
+    }
+
+    protected int doGetColumnCount() {
+        return table.getColumnCount();
+    }
+
+    protected Widget doGetColumn(int index) {
+        return table.getColumn(index);
+    }
+
+    protected Item doGetItem(int index) {
+        return table.getItem(index);
+    }
+
+    protected Item[] doGetSelection() {
+        return table.getSelection();
+    }
+
+    protected int[] doGetSelectionIndices() {
+        return table.getSelectionIndices();
+    }
+
+    protected void doClearAll() {
+        table.clearAll();
+    }
+
+    protected void doResetItem(Item item) {
+        TableItem tableItem = cast(TableItem) item;
+        int columnCount = Math.max(1, table.getColumnCount());
+        for (int i = 0; i < columnCount; i++) {
+            tableItem.setText(i, ""); //$NON-NLS-1$
+            if (tableItem.getImage(i) !is null) {
+                tableItem.setImage(i, null);
+            }
+        }
+    }
+
+    protected void doRemove(int start, int end) {
+        table.remove(start, end);
+    }
+
+    protected void doRemoveAll() {
+        table.removeAll();
+    }
+
+    protected void doRemove(int[] indices) {
+        table.remove(indices);
+    }
+
+    protected void doShowItem(Item item) {
+        table.showItem(cast(TableItem)item);
+    }
+
+    protected void doDeselectAll() {
+        table.deselectAll();
+    }
+
+    protected void doSetSelection(Item[] items) {
+//         Assert.isNotNull(items, "Items-Array can not be null"); //$NON-NLS-1$
+
+        TableItem[] t = new TableItem[items.length];
+        System.arraycopy(items, 0, t, 0, t.length);
+
+        table.setSelection(t);
+    }
+
+    protected void doShowSelection() {
+        table.showSelection();
+    }
+
+    protected void doSetSelection(int[] indices) {
+        table.setSelection(indices);
+    }
+
+    protected void doClear(int index) {
+        table.clear(index);
+    }
+
+    protected void doSelect(int[] indices) {
+        table.select(indices);
+    }
+
+    /**
+     * Refreshes this viewer starting with the given element. Labels are updated
+     * as described in <code>refresh(bool updateLabels)</code>. The
+     * methods attempts to preserve the selection.
+     * <p>
+     * Unlike the <code>update</code> methods, this handles structural changes
+     * to the given element (e.g. addition or removal of children). If only the
+     * given element needs updating, it is more efficient to use the
+     * <code>update</code> methods.
+     * </p>
+     *
+     * <p>
+     * Subclasses who can provide this feature can open this method for the
+     * public
+     * </p>
+     *
+     * @param element
+     *            the element
+     * @param updateLabels
+     *            <code>true</code> to update labels for existing elements,
+     *            <code>false</code> to only update labels as needed, assuming
+     *            that labels for existing elements are unchanged.
+     * @param reveal
+     *            <code>true</code> to make the preserved selection visible
+     *            afterwards
+     *
+     * @since 3.3
+     */
+    public void refresh(Object element, bool updateLabels,
+            bool reveal) {
+        if (isBusy())
+            return;
+
+        if( isCellEditorActive() ) {
+            cancelEditing();
+        }
+
+        preservingSelection(new class Runnable {
+            Object element_;
+            bool updateLabels_;
+            this(){
+                element_ = element;
+                updateLabels_ = updateLabels;
+            }
+            public void run() {
+                internalRefresh(element_, updateLabels_);
+            }
+        }, reveal);
+    }
+
+    /**
+     * Refreshes this viewer with information freshly obtained from this
+     * viewer's model. If <code>updateLabels</code> is <code>true</code>
+     * then labels for otherwise unaffected elements are updated as well.
+     * Otherwise, it assumes labels for existing elements are unchanged, and
+     * labels are only obtained as needed (for example, for new elements).
+     * <p>
+     * Calling <code>refresh(true)</code> has the same effect as
+     * <code>refresh()</code>.
+     * <p>
+     * Note that the implementation may still obtain labels for existing
+     * elements even if <code>updateLabels</code> is false. The intent is
+     * simply to allow optimization where possible.
+     *
+     * @param updateLabels
+     *            <code>true</code> to update labels for existing elements,
+     *            <code>false</code> to only update labels as needed, assuming
+     *            that labels for existing elements are unchanged.
+     * @param reveal
+     *            <code>true</code> to make the preserved selection visible
+     *            afterwards
+     *
+     * @since 3.3
+     */
+    public void refresh(bool updateLabels, bool reveal) {
+        refresh(getRoot(), updateLabels, reveal);
+    }
+}