codeshine.utils.TableFieldEditor.java Source code

Java tutorial

Introduction

Here is the source code for codeshine.utils.TableFieldEditor.java

Source

/*******************************************************************************
 * Copyright notice                                                            *
 *                                                                             *
 * Copyright (c) 2005-2006 Feed'n Read Development Team                             *
 * http://sourceforge.net/fnr                                                  *
 *                                                                             *
 * All rights reserved.                                                        *
 *                                                                             *
 * This program and the accompanying materials are made available under the    *
 * terms of the Common Public License v1.0 which accompanies this distribution,*
 * and is available at                                                         *
 * http://www.eclipse.org/legal/cpl-v10.html                                   *
 *                                                                             *
 * A copy is found in the file cpl-v10.html and important notices to the       *
 * license from the team is found in the textfile LICENSE.txt distributed      *
 * in this package.                                                            *
 *                                                                             *
 * This copyright notice MUST APPEAR in all copies of the file.                *
 *                                                                             *
 * Contributors:                                                               *
 *    Feed'n Read - initial API and implementation                             *
 *                  (smachhau@users.sourceforge.net)                           *
 *******************************************************************************/
package codeshine.utils;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;

import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ControlEditor;
import org.eclipse.swt.custom.TableCursor;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
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.Text;

//import org.eclipse.ui.internal.presentations.UpdatingActionContributionItem;
import codeshine.preferences.IPreferenceConstants;

/**
 * <p>
 * A <code>FieldEditor</code> implementation that supports the selection of
 * tabular data.
 * </p>
 *
 * @author <a href="mailto:Sebastian.Machhausen@gmail.com">Sebastian Machhausen</a>
 */
public class TableFieldEditor extends FieldEditor implements Accessible {

    /**
    * <p>
    * The <code>Table</code> used to present the selectable tabular data
    * </p>
    */
    private Table table;

    /** <p> The <code>TableViewer</code> used as controller </p> */
    private TableViewer viewer;

    /** <p> The content provider used to query the table data </p> */
    private IStructuredContentProvider contentProvider;

    /** <p>
     * The label provider used to convert domain objects to ui specific
     * textual representations.
     * </p>
     */
    private ITableLabelProvider labelProvider;

    /**
    * <p>
    * The input or model object that holds the data of the
    * <code>TableViewer</code>
    * </p>
    */
    private Object input;

    /** <p> The column headers to display in the <code>Table</code> </p> */
    private String[] columnHeaders;

    /** <o> The <code>Table</code> sorter </p> */
    private TableViewerSorter sorter;

    /**
    * <p>
    * The handler used to sort the underlying
    * <code>IStructuredContentProvider</code>
    * </p>
    */
    private TableViewerSorterHandler sorterHandler;

    /**
    * <p>
    * The index of the column to store/retrieve the value for. If set to -1 the
    * complete row represented as domain object is stored/retrieved. This is
    * done by calling toString() on the respective domain object.
    * </p>
    */
    private int selectionColumn;

    /** <p> The last selected value of the <code>Table</code> </p> */
    private Object oldValue;

    /**
     * <p>
     * Creates a new <code>TableFieldEditor</code> instance.
     * </p>
     * 
     * @param name the name of the preference this field editor works on
     * @param labelText the label text of the field editor
     * @param parent the parent of the field editor's control
     * @param contentProvider the <code>IStructuredContentProvider</code> used
     * to query the table data
     * @param labelProvider the <code>ITableLabelProvider</code> used to
     * convert domain objects to ui specific textual representations
     * @param columnHeaders an array of <code>String</code> objects representing
     * the column headers
     * @param input the input or model object which holds the data for
     * this <code>TableFieldEditor</code>
     */
    public TableFieldEditor(String name, String labelText, Composite parent,
            IStructuredContentProvider contentProvider, ITableLabelProvider labelProvider, String[] columnHeaders,
            Object input) {
        this.contentProvider = contentProvider;
        this.labelProvider = labelProvider;
        this.columnHeaders = columnHeaders;
        this.input = input;
        this.init(name, labelText);
        this.createControl(parent);
    }

    /**
     * </p>
     * Returns the number of controls in this 
     * <code>TableFieldEditor</code>. Returns <code>1</code> as the
     * <code>Table</code> is the only control.
     * </p>
     * 
     * @return <code>1</code>
     * @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls()
     */
    public int getNumberOfControls() {
        return (1);
    }

    /**
     * <p>
     * Sets the selection column to the specified <code>columnIndex</code>.
     * The index represents the column whose value is stored/retrieved in this
     * <code>TableFieldEditor</code>. If set to -1 the complete row
     * represented as domain object is stored/retrieved. This is done by calling
     * {@link #toString()} on the respective domain object.
     * </p>
     * 
     * @param columnIndex the column whose value is stored/retrieved in this
     * <code>TableFieldEditor</code>
     * 
     * @see #getSelectionColumn()
     */
    public void setSelectionColumn(int columnIndex) {
        this.selectionColumn = columnIndex;
    }

    /**
     * <p>
     * Gets the selection column which represents the index of the column whose
     * value is stored/retrieved in this <code>TableFieldEditor</code>. A
     * value of <code>-1</code> means that the complete row represented as
     * domain object is stored/retrieved. This is done by calling
     * {@link #toString()} on the respective domain object.
     * </p>
     * 
     * @return the column whose value is stored/retrieved in this
     * <code>TableFieldEditor</code>
     * 
     * @see #setSelectionColumn(int)
     */
    public int getSelectionColumn() {
        return this.selectionColumn;
    }

    /**
     * <p>
     * Gets the currently selected value of this <code>TableFieldEditor</code>.
     * The value returned by this method depends on the selection column 
     * set up as returned by {@link #getSelectionColumn()}. If the selection
     * column is set to <code>-1</code> the complete row represented as
     * domain object is returned by calling {@link #toString()} on it. 
     * Otherwise the respective column value is queried and returned using
     * the <code>ITableLabelProvider</code> bound to this
     * <code>TableFieldEditor</code>.
     * </p>
     * 
     * @return the currently selected value or an empty <code>String</code> 
     * if no selection 
     * 
     * @see #setSelectionColumn(int)
     * @see #getSelectionColumn()
     */
    public String getSelection() {
        IStructuredSelection selection = (IStructuredSelection) this.viewer.getSelection();
        if (selection.isEmpty()) {
            /* Empty selection */
            return (StringUtils.EMPTY_STRING);
        } else if (this.selectionColumn == -1) {
            /* Row selection */
            return (selection.getFirstElement().toString());
        } else {
            /* Column selection */
            return (this.labelProvider.getColumnText(selection.getFirstElement(), this.selectionColumn));
        }
    }

    /**
    * <p>
    * Enables or disables the sorting of the <code>Table</code> depending on
    * the specified <code>enabled</code> status.</br> The
    * <code>IStructuredContentProvider</code> used in this
    * <code>TableFieldEditor</code> has to implement the
    * {@link net.sourceforge.java.util.gui.jface.viewers.ITableContentProvider}
    * interface to enable sorting.
    * </p>
    * 
    * @param enabled <code>true</code> to enable sorting; <code>false</code>
    * to disable
    * 
    * @see #isSortingEnabled()
    */
    public void setSortingEnabled(boolean enabled) {
        if (this.contentProvider instanceof ITableContentProvider) {
            if (enabled) {
                this.sorter = new TableViewerSorter(this.viewer, (ITableContentProvider) this.contentProvider);
                this.sorterHandler = new TableViewerSorterHandler(this.table, this.sorter);
                this.viewer.setSorter(sorter);
            } else {
                this.sorter = null;
                this.sorterHandler = null;
                this.viewer.setSorter(null);
            }
        }
    }

    /**
     * <p>
     * Returns true if <code>Table</code> sorting is enabled;
     * <code>false</code> otherwise.
     * </p>
     * 
     * @return <code>true</code> if sorting is enabled; <code>false</code>
     * otherwise
     * 
     * @see #setSortingEnabled(boolean)
     */
    public boolean isSortingEnabled() {
        return this.sorterHandler != null;
    }

    /**
    * <p>
    * Sorts the <code>Table</code> by the specified <code>columnIndex</code>
    * in the specified sort order. If sorting is disabled this method does
    * nothing.
    * </p>
    * 
    * @param columnIndex the index of the column to sort by
    * @param ascending <code>true</code> to sort in ascending,
    * <code>false</code> to sort in descending order
    * 
    * @see #setSortingEnabled(boolean)
    * @see #isSortingEnabled()
    * @see #getSortingColumn()
    * @see #isSortAscending()
    */
    public void sort(int columnIndex, boolean ascending) {
        if (this.isSortingEnabled()) {
            this.sorterHandler.sort(columnIndex, ascending);
        }
    }

    /**
    * <p>
    * Gets the index of the column by which sorting is done. If sorting is
    * disabled <i>-1</i> is returned.
    * </p>
    * 
    * @return the index of the column upon which sorting is done; <i>-1</i> if
    * sorting is disabled
    * 
    * @see #isSortAscending()
    * @see #sort(int, boolean)
    */
    public int getSortingColumn() {
        if (this.isSortingEnabled()) {
            return this.sorter.getSortingColumn();
        } else {
            return -1;
        }
    }

    /**
    * <p>
    * Returns <code>true</code> if sorting is done in ascending order;
    * <code>false</code> if done in descending order or sorting is disabled;
    * </p>
    * 
    * @return <code>true</code> if sorting is done in ascending order;
    * <code>false</code> if done in descending order or sorting is disabled;
    * 
    * @see #getSortingColumn()
    * @see #sort(int, boolean)
    */
    public boolean isSortAscending() {
        if (this.isSortingEnabled()) {
            return this.sorter.isAscending();
        } else {
            return false;
        }
    }

    /**
    * <p>
    * Sets the width of the column at the specified <code>columnIndex</code>
    * to the given <code>width</code>. If no <code>TableColumn</code>
    * exists at the specified <code>columnIndex</code> the method does
    * nothing.
    * </p>
    * 
    * @param columnIndex the index of the column to set the width for
    * @param width the width of the column in pixel
    * 
    * @see #getColumnWidth(int)
    */
    public void setColumnWidth(int columnIndex, int width) {
        if (columnIndex >= 0 && columnIndex < this.columnHeaders.length) {
            TableColumn column = this.table.getColumn(columnIndex);
            column.setWidth(width);
        }
    }

    /**
    * <p>
    * Gets the width in pixel of the column at the specified
    * <code>columnIndex</code>. If no <code>TableColumn</code> exists at
    * the specified <code>columnIndex</code> the method returns <i>0</i>.
    * </p>
    * 
    * @param columnIndex the index of the column to get the width for
    * 
    * @return the column width
    * 
    * @see #setColumnWidth(int, int)
    */
    public int getColumnWidth(int columnIndex) {
        if (columnIndex >= 0 && columnIndex < this.columnHeaders.length) {
            TableColumn column = this.table.getColumn(columnIndex);
            return column.getWidth();
        } else {
            return 0;
        }
    }

    /**
     * <p>
     * Adjusts the horizontal span of this <code>TableFieldEditor</code>'s basic
     * controls. The number of columnHeaders will always be equal to or greater than
     * the value returned by this editor's <code>getNumberOfControls</code>
     * method.
     * </p>
     * 
     * @param numColumns the number of columnHeaders
     * 
     * @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int)
     */
    protected void adjustForNumColumns(int numColumns) {
        GridData gd = (GridData) this.table.getLayoutData();
        gd.horizontalSpan = numColumns - 1;
        gd.grabExcessHorizontalSpace = gd.horizontalSpan <= 1;
    } // end method adjustForNumColumns(int)

    /**
     * <p>
     * Fills this <code>TableFieldEditor</code>'s basic controls into the
     * given parent.
     * </p>
     * 
     * @param parent the composite used as a parent for the basic controls; the
     * parent's layout must be a <code>GridLayout</code>
     * @param numColumns the number of columnHeaders
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doFillIntoGrid(org.eclipse.swt.widgets.Composite,
     * int)
     */
    protected void doFillIntoGrid(Composite parent, int numColumns) {
        this.getLabelControl(parent);

        this.table = new Table(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
        this.table.setHeaderVisible(true);
        this.table.setLinesVisible(false);
        this.table.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
                valueChanged();
            }

            public void widgetSelected(SelectionEvent e) {
                valueChanged();
            }
        });

        this.initializeColumns();
        this.initializeViewer();

        final GridData gd = new GridData();
        gd.horizontalSpan = numColumns - 1;
        gd.horizontalAlignment = GridData.FILL;
        gd.verticalAlignment = GridData.FILL;
        gd.grabExcessHorizontalSpace = true;
        gd.grabExcessVerticalSpace = true;
        this.table.setLayoutData(gd);
        this.table.setLinesVisible(true);
        final TableCursor cursor = new TableCursor(table, SWT.NONE);
        final ControlEditor editor = new ControlEditor(cursor);
        editor.grabHorizontal = true;
        editor.grabVertical = true;

        cursor.addSelectionListener(new SelectionAdapter() {
            // when the TableEditor is over a cell, select the corresponding row in
            // the table
            public void widgetSelected(SelectionEvent e) {
                table.setSelection(new TableItem[] { cursor.getRow() });
                selectionColumn = cursor.getColumn();
            }

            // when the user hits "ENTER" in the TableCursor, pop up a text editor so
            // that
            // they can change the text of the cell
            public void widgetDefaultSelected(SelectionEvent e) {
                final Text text = new Text(cursor, SWT.NONE);
                TableItem row = cursor.getRow();
                int column = cursor.getColumn();
                selectionColumn = column;
                if (row.getText(column).equals(IPreferenceConstants.SPECIAL))
                    text.setText("");
                else
                    text.setText(row.getText(column));
                text.addKeyListener(new KeyAdapter() {
                    public void keyPressed(KeyEvent e) {
                        // close the text editor and copy the data over
                        // when the user hits "ENTER"
                        if (e.character == SWT.CR) {
                            TableItem row = cursor.getRow();
                            int column = cursor.getColumn();
                            String oldText = row.getText(column);
                            row.setText(column, text.getText());
                            updateInput(column, row, oldText);
                            text.dispose();
                            selectionColumn = cursor.getColumn();
                            cursor.setFocus();
                        }
                    }

                    //              Chap para actualizar el objeto input.
                    public void updateInput(int column, TableItem row, String old) {
                        TokenList tl = (TokenList) input;
                        if ((old.equals(IPreferenceConstants.SPECIAL)) && (row.getText(0).equals(""))) {
                            Token t = new Token(IPreferenceConstants.SPECIAL, row.getText(1), row.getText(2));
                            tl.addToken(t);
                        } else {
                            if (tl.getCollection().containsKey(old)) {
                                System.out.println("TFE: removed " + old);
                                tl.removeToken(old);
                            }
                            if (!row.getText(0).equals("")) {
                                Token t = new Token(row.getText(0), row.getText(1), row.getText(2));
                                tl.addToken(t);
                            }
                        }
                        System.out.println("TableFieldEditor: " + tl.toString());
                        viewer.setInput(tl);
                    }
                });
                // close the text editor when the user tabs away
                text.addFocusListener(new FocusAdapter() {
                    public void focusLost(FocusEvent e) {
                        text.dispose();
                        selectionColumn = cursor.getColumn();
                    }
                });
                editor.setEditor(text);
                text.setFocus();

            }
        });
        // Hide the TableCursor when the user hits the "CTRL" or "SHIFT" key.
        // This alows the user to select multiple items in the table.
        cursor.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == SWT.CTRL || e.keyCode == SWT.SHIFT || (e.stateMask & SWT.CONTROL) != 0
                        || (e.stateMask & SWT.SHIFT) != 0) {
                    cursor.setVisible(false);
                }
            }
        });

        // Show the TableCursor when the user releases the "SHIFT" or "CTRL" key.
        // This signals the end of the multiple selection task.
        table.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent e) {
                if (e.keyCode == SWT.CONTROL && (e.stateMask & SWT.SHIFT) != 0)
                    return;
                if (e.keyCode == SWT.SHIFT && (e.stateMask & SWT.CONTROL) != 0)
                    return;
                if (e.keyCode != SWT.CONTROL && (e.stateMask & SWT.CONTROL) != 0)
                    return;
                if (e.keyCode != SWT.SHIFT && (e.stateMask & SWT.SHIFT) != 0)
                    return;

                TableItem[] selection = table.getSelection();
                TableItem row = (selection.length == 0) ? table.getItem(table.getTopIndex()) : selection[0];
                table.showItem(row);
                cursor.setSelection(row, 0);
                cursor.setVisible(true);
                cursor.setFocus();
                selectionColumn = cursor.getColumn();
            }
        });

    } // end method doFillIntoGrid()

    /**
     * <p>
     * Initializes this <code>TableFieldEditor</code> with the
     * preference value from the preference store. 
     * </p>
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doLoad()
     */
    protected void doLoad() {
        String value = this.getPreferenceStore().getString(this.getPreferenceName());
        this.setSelection(value);
        this.oldValue = value;
    } // end method doLoad()

    /**
     * <p>
     * Initializes this <code>TableFieldEditor</code> with the
     * default preference value from the preference store.
     * </p>
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doLoadDefault()
     */
    protected void doLoadDefault() {
        String defaultValue = this.getPreferenceStore().getDefaultString(this.getPreferenceName());
        this.setSelection(defaultValue);
        this.valueChanged();
    } // end method doLoadDefault()

    /**
     * <p>
     * Stores the preference value from this
     * <code>TableFieldEditor</code> into the preference store.
     * </p>
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doStore()
     */
    protected void doStore() {
        this.valueChanged();
        this.getPreferenceStore().setValue(this.getPreferenceName(), this.getSelection());
    } // end method doStore()

    /**
     * <p>
     * Informs this field editor's listener, if it has one, about a change to
     * the value (<code>VALUE</code> property) provided that the old and new
     * values are different. This hook is <em>not</em> called when the value is
     * initialized (or reset to the default value) from the preference store.
     * </p>
     */
    protected void valueChanged() {

        System.out.println("Invocado ValueChanged");
        this.setPresentsDefaultValue(false);

        final IStructuredSelection selection = (IStructuredSelection) this.viewer.getSelection();

        String newValue;
        //        System.out.println("NewVAlue: " + newValue);
        if (selection.isEmpty()) {
            newValue = StringUtils.EMPTY_STRING;
        } else if (this.selectionColumn == -1) {
            newValue = selection.getFirstElement().toString();
        } else {
            newValue = this.labelProvider.getColumnText(selection.getFirstElement(), this.selectionColumn);
        }

        if (newValue.equals(oldValue)) {
            this.fireValueChanged(VALUE, oldValue, newValue);
            oldValue = newValue;
        }
    } // end method valueChanged()

    /**
     * <p>
     * Initializes this <code>TableFieldEditor</code>'s
     * <code>TableViewer</code>.
     * </p>
     */
    private void initializeViewer() {
        this.viewer = new TableViewer(this.table);
        this.viewer.setContentProvider(this.contentProvider);
        this.viewer.setLabelProvider(this.labelProvider);

        this.viewer.setColumnProperties(this.columnHeaders);

        this.viewer.setInput(this.input);

        /* Pack all columnHeaders */
        TableColumn column;
        for (int i = 0; i < this.columnHeaders.length; i++) {
            column = this.table.getColumn(i);
            column.pack();
        }
    } // end method initializeViewer()

    //    New method added by tivi

    public void setInput(Object newInput) {
        this.input = newInput;
        this.initializeViewer();
    }

    public Object getInput() {
        return this.input;
    }

    /**
     * <p>
     * Initializes the table columnHeaders by setting their widths and adjusting their
     * settings.
     * </p>
     */
    private void initializeColumns() {
        TableColumn column;
        for (int i = 0; i < this.columnHeaders.length; i++) {
            column = new TableColumn(this.table, SWT.LEFT);
            column.setText(this.columnHeaders[i]);
            column.setToolTipText(this.columnHeaders[i]);
        }
    } // end method initializeColumns()

    /**
     * </p>
     * Sets the selection of this <code>TableFieldEditor</code> to
     * the row or element matching the specified <code>selectionStr</code>.
     * </p>
     * 
     * @param selectionStr the <code>String</code> that identifies the
     * row or element to select
     */
    private void setSelection(String selectionStr) {
        if (this.viewer != null) {
            Object[] items = this.contentProvider.getElements(this.viewer.getInput());
            boolean selected = false;
            if (this.selectionColumn == -1) {
                for (int i = 0; i < items.length && !selected; i++) {
                    if (selectionStr.equals(items[i].toString())) {
                        StructuredSelection selection = new StructuredSelection(items[i]);
                        this.viewer.setSelection(selection);
                        selected = true;
                    }
                }
            } else {
                for (int i = 0; i < items.length && !selected; i++) {
                    if (selectionStr.equals(this.labelProvider.getColumnText(items[i], this.selectionColumn))) {
                        StructuredSelection selection = new StructuredSelection(items[i]);
                        this.viewer.setSelection(selection);
                        selected = true;
                    }
                }
            }
        }
    } // end method setSelection(String)

    public AccessibleContext getAccessibleContext() {
        return null;
    }

}