com.xse.eclipseui.table.AbstractTable.java Source code

Java tutorial

Introduction

Here is the source code for com.xse.eclipseui.table.AbstractTable.java

Source

/*******************************************************************************
 * Eclipse UI
 *
 * Copyright (c) 2015 Mentor Graphics 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:
 *      Mentor Graphics - initial API and implementation
 ******************************************************************************/
package com.xse.eclipseui.table;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
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;

/**
 * Base implementation of a generic table viewer.
 *
 * @author pberg
 *
 */
public abstract class AbstractTable {

    private final class DisposeListenerImplementation implements DisposeListener {

        private final Table listenerTable;

        private DisposeListenerImplementation(final Table table) {
            this.listenerTable = table;
        }

        @Override
        public void widgetDisposed(final DisposeEvent e) {
            this.listenerTable.removeDisposeListener(this);
            AbstractTable.this.dispose();
        }
    }

    public enum CheckedState {
        CHECKED, UNCHECKED, INDETERMINATE;
    }

    private final Table table;
    private final TableViewer viewer;

    private final Map<Integer, TableViewerColumn> tableViewerColumnMap = new HashMap<>();

    private final List<SelectionAdapter> selectionAdapterList = new ArrayList<>();

    private ISortingHandler sortingHandler;
    private CellLabelProvider cellLabelProvider;

    protected final Set<Object> checkedItems = new HashSet<>();
    protected final Set<Object> grayedItems = new HashSet<>();

    private IExtendedLazyTableContentProvider extendedContentProvider;

    private final List<IInputChangedListener> inputChangedListeners = new ArrayList<>();

    public AbstractTable(final Composite parent, final int style) {
        this(null, parent, style);
    }

    public AbstractTable(final Table table) {
        this(table, null, SWT.NONE);
    }

    private AbstractTable(final Table table, final Composite parent, final int style) {
        if (null == table) {
            this.table = this.createTable(parent, style);
        } else {
            this.table = table;
        }

        if ((style & SWT.CHECK) != 0) {
            this.viewer = new CheckboxTableViewer(this.table);
            ((CheckboxTableViewer) this.viewer).setCheckStateProvider(new ICheckStateProvider() {
                @Override
                public boolean isGrayed(final Object element) {
                    return AbstractTable.this.grayedItems.contains(element);
                }

                @Override
                public boolean isChecked(final Object element) {
                    return AbstractTable.this.checkedItems.contains(element);
                }
            });
        } else {
            this.viewer = new TableViewer(this.table);
        }

        this.table.setHeaderVisible(true);
        this.table.setLinesVisible(true);

        if (this.hasToolTipColumns()) {
            ColumnViewerToolTipSupport.enableFor(this.viewer, ToolTip.NO_RECREATE);
        }

        this.refreshColumns();

        if (this.table.getHorizontalBar() != null) {
            this.table.getHorizontalBar().setVisible(false);
            this.table.pack();
            this.table.getParent().layout();
        }

        this.table.addDisposeListener(new DisposeListenerImplementation(this.table));
    }

    public void refreshColumns() {
        this.getTable().setRedraw(false);
        this.removeAllColumns();
        int cell = 0;
        for (final com.xse.eclipseui.table.TableColumn column : this.getColumns()) {
            final TableColumn nameColumn = new TableColumn(this.table, column.getStyle());

            if (column.isProvideTooltip() || column.hasEditingSupport()) {
                final TableViewerColumn tableViewerColumn = new TableViewerColumn(this.viewer, nameColumn);
                this.tableViewerColumnMap.put(Integer.valueOf(cell), tableViewerColumn);

                if (column.hasEditingSupport()) {
                    tableViewerColumn.setEditingSupport(column.getEditingSupport());
                }

            }
            nameColumn.setText(column.getTitle());
            nameColumn.setWidth(column.getWidth());
            nameColumn.setMoveable(column.isMoveable());
            if (column.getHeaderTooltip() != null) {
                nameColumn.setToolTipText(column.getHeaderTooltip());
            }

            cell++;
        }

        this.getTable().setRedraw(true);
        this.addSelectionAdapter();
    }

    private void removeAllColumns() {
        this.resetSelectionAdapter();
        this.tableViewerColumnMap.clear();
        final int columnCount = this.getTable().getColumnCount();
        for (int i = 0; i < columnCount; ++i) {
            final TableColumn column = this.getTable().getColumn(0);
            if (column != null) {
                this.getTable().setRedraw(false);
                column.dispose();
                this.getTable().setRedraw(true);
            }
        }
    }

    protected Table createTable(final Composite parent, final int style) {
        return new Table(parent, style);
    }

    public Map<Integer, TableViewerColumn> getColumnMap() {
        return this.tableViewerColumnMap;
    }

    private void addSelectionAdapter() {
        int i = 0;
        for (final TableColumn column1 : this.getViewer().getTable().getColumns()) {
            this.selectionAdapterList.add(this.getSelectionAdapter(i));
            int n = 0;
            for (final SelectionAdapter sa : this.selectionAdapterList) {
                if (i == n) {
                    column1.addSelectionListener(sa);
                }
                n++;
            }
            i++;
        }
    }

    private void resetSelectionAdapter() {
        int i = 0;
        for (final TableColumn column1 : this.getViewer().getTable().getColumns()) {
            int n = 0;
            for (final SelectionAdapter sa : this.selectionAdapterList) {
                if (i == n) {
                    column1.removeSelectionListener(sa);
                    break;
                }
                n++;
            }
            i++;
        }
        this.selectionAdapterList.clear();
    }

    private SelectionAdapter getSelectionAdapter(final int ptColumn) {
        final SelectionAdapter selectionAdapter = new SelectionAdapter() {
            private int direction = SWT.UP;

            @Override
            public void widgetSelected(final SelectionEvent e) {
                if (AbstractTable.this.table.getSortDirection() == SWT.NONE) {
                    this.direction = SWT.DOWN;
                } else {
                    if (this.direction == SWT.UP) {
                        this.direction = SWT.DOWN;
                    } else {
                        this.direction = SWT.UP;
                    }
                }

                if (AbstractTable.this.sortingHandler != null) {
                    AbstractTable.this.sortingHandler.setSortDirection(this.direction);
                    AbstractTable.this.sortingHandler.sort(ptColumn, true);
                }
            }
        };
        return selectionAdapter;
    }

    // will automatically be called on disposal of the underlying SWT table
    protected void dispose() {
        // do nothing - needs to be overriden if needed
    }

    public TableItem[] getTableSelection() {
        return this.table.getSelection();
    }

    public ISelection getViewerSelection() {
        return this.viewer.getSelection();
    }

    public void setSelection(final ISelection selection) {
        this.viewer.setSelection(selection);
    }

    public void setInput(final Object input) {
        this.firePreInputChanged(input);
        this.viewer.setInput(input);
        this.fireAfterInputChanged(input);
    }

    public void setContentProvider(final IContentProvider provider) {
        this.viewer.setContentProvider(provider);
    }

    public void setContentProvider(final IExtendedLazyTableContentProvider provider) {
        this.extendedContentProvider = provider;
        this.viewer.setContentProvider(provider);
    }

    public void setSortingHandler(final ISortingHandler handler) {
        this.sortingHandler = handler;
    }

    public ISortingHandler getSortingHandler() {
        return this.sortingHandler;
    }

    /**
     * Set label contentProvider for the table viewer of the table.
     * Use this to set one label contentProvider for every column!
     *
     * @param labelProvider
     *            The label contentProvider to set for the table viewer.
     */
    public void setLabelProvider(final ITableLabelProvider labelProvider) {
        assert this.cellLabelProvider == null : "TableLableProvider overwrites already set CellLabelProvider!";
        this.viewer.setLabelProvider(labelProvider);
    }

    /**
     * Set cell label contentProvider for the table viewer of the table.
     * Use this to set the same cell label contentProvider for every column.
     *
     * @param labelProvider
     */
    public void setLabelProvider(final CellLabelProvider labelProvider) {
        this.cellLabelProvider = labelProvider;
        for (final TableViewerColumn c : this.tableViewerColumnMap.values()) {
            c.setLabelProvider(labelProvider);
        }
    }

    /**
     * Set label contentProvider for a single column(cell) of the table.
     * Use this to set one label contentProvider per column when tooltips are activated!
     *
     * @param cell
     *            The column/cell to provide a label contentProvider
     *
     * @param labelProvider
     *            A CellLabelProvider for a single column/cell.
     */
    protected void setCellLabelProvider(final int cell, final CellLabelProvider labelProvider) {
        assert !(this.viewer.getLabelProvider() instanceof ITableLabelProvider) : "CellLabelProvider doesn't "
                + "work because TableLabelProvider is already set!";
        if (this.tableViewerColumnMap.get(Integer.valueOf(cell)) != null) {
            this.tableViewerColumnMap.get(Integer.valueOf(cell)).setLabelProvider(labelProvider);
        }
    }

    public TableViewer getViewer() {
        return this.viewer;
    }

    public CheckboxTableViewer getCheckBoxViewer() {
        if (this.viewer instanceof CheckboxTableViewer) {
            return (CheckboxTableViewer) this.viewer;
        }
        return null;
    }

    public void setAllUnchecked() {
        this.getCheckBoxViewer().setAllChecked(false);
        this.getCheckBoxViewer().setAllGrayed(false);

        this.checkedItems.clear();
        this.grayedItems.clear();

        this.getCheckBoxViewer().refresh();

        this.fireCheckedStateChanged();
    }

    public void setAllChecked() {
        this.setCollectionChecked(this.getAllActiveElements());
    }

    public void setCollectionChecked(final Collection<Object> elements) {
        this.getTable().setRedraw(false);

        this.getCheckBoxViewer().setCheckedElements(elements.toArray());
        this.getCheckBoxViewer().setGrayedElements(new ArrayList<>(0).toArray());

        this.checkedItems.addAll(elements);
        this.grayedItems.removeAll(elements);

        this.getCheckBoxViewer().refresh();

        this.getTable().setRedraw(true);
        this.fireCheckedStateChanged();
    }

    public void setCheckedElements(final Collection<Object> elements) {
        this.checkedItems.clear();
        this.grayedItems.clear();

        this.setCollectionChecked(elements);
    }

    protected void fireCheckedStateChanged() {
        // do nothing - to be overwritten
    }

    /**
     * This method is considered to be overwritten by subclasses.
     *
     * @return
     */
    public List<Object> getAllActiveElements() {
        return this.getAllElements();
    }

    public List<Object> getAllElements() {
        if (this.extendedContentProvider != null) {
            return new ArrayList<>(this.extendedContentProvider.getRootItems());
        } else {
            if (this.getViewer().getContentProvider() instanceof IStructuredContentProvider) {
                return Arrays.asList(((IStructuredContentProvider) this.getViewer().getContentProvider())
                        .getElements(this.viewer.getInput()));
            } else {
                // Invalid usage of AbstractTable
                return null;
            }
        }
    }

    public Table getTable() {
        return this.table;
    }

    public Set<Object> getCheckedItems() {
        return Collections.unmodifiableSet(this.checkedItems);
    }

    public Set<Object> getGrayedItems() {
        return Collections.unmodifiableSet(this.grayedItems);
    }

    protected void setCheckedState(final Object element, final CheckedState state) {
        switch (state) {
        case CHECKED:
            this.getCheckBoxViewer().setChecked(element, true);
            this.getCheckBoxViewer().setGrayed(element, false);
            this.checkedItems.add(element);
            this.grayedItems.remove(element);
            break;
        case UNCHECKED:
            this.getCheckBoxViewer().setChecked(element, false);
            this.getCheckBoxViewer().setGrayed(element, false);
            this.checkedItems.remove(element);
            this.grayedItems.remove(element);
            break;
        case INDETERMINATE:
            this.getCheckBoxViewer().setChecked(element, true);
            this.getCheckBoxViewer().setGrayed(element, true);
            this.checkedItems.add(element);
            this.grayedItems.add(element);
            break;
        default:
            // do nothing
        }
    }

    public void setSelectionByIndex(final int index) {
        this.table.setSelection(index);
    }

    protected abstract com.xse.eclipseui.table.TableColumn[] getColumns();

    private boolean hasToolTipColumns() {
        for (final com.xse.eclipseui.table.TableColumn column : this.getColumns()) {
            if (column.isProvideTooltip()) {
                return true;
            }
        }

        return false;
    }

    public CellLabelProvider getCellLabelProvider() {
        return this.cellLabelProvider;
    }

    public IContentProvider getContentProvider() {
        return this.viewer.getContentProvider();
    }

    public IExtendedLazyTableContentProvider getExtendedContentProvider() {
        return this.extendedContentProvider;
    }

    protected void firePreInputChanged(final Object newInput) {
        this.inputChangedListeners.forEach(l -> l.preInputChanged(newInput));
    }

    protected void fireAfterInputChanged(final Object newInput) {
        this.inputChangedListeners.forEach(l -> l.afterInputChanged(newInput));
    }

    public void addInputChangedListener(final IInputChangedListener listener) {
        this.inputChangedListeners.add(listener);
    }

    public void removeInputChangedListener(final IInputChangedListener listener) {
        this.inputChangedListeners.remove(listener);
    }

}