de.innot.avreclipse.ui.preferences.AVRPathsFieldEditor.java Source code

Java tutorial

Introduction

Here is the source code for de.innot.avreclipse.ui.preferences.AVRPathsFieldEditor.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2011 Thomas Holland (thomas@innot.de) 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:
 *     Thomas Holland - initial API and implementation
 *******************************************************************************/

package de.innot.avreclipse.ui.preferences;

import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
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.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;

import de.innot.avreclipse.core.paths.AVRPath;
import de.innot.avreclipse.core.paths.AVRPathManager;

/**
 * A custom field editor to edit all plugin paths.
 * 
 * This can be used on a FieldEditorPreferencePage to manage the the current path settings.
 * 
 * @author Thomas Holland
 * 
 */
public class AVRPathsFieldEditor extends FieldEditor {

    // GUI Widgets
    private Table fTable;
    private Composite fButtons;
    private Button fEditButton;
    private Button fRescanButton;

    private boolean fValid = true;

    // The three columns
    private static final int COLUMN_NAME = 0;
    private static final int COLUMN_TYPE = 1;
    private static final int COLUMN_PATH = 2;

    // fonts and colors used
    final Font fBoldFont = JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT);
    final Font fDialogFont = JFaceResources.getFontRegistry().get(JFaceResources.DIALOG_FONT);

    /**
     * Handle selection events from the edit button.
     * 
     * It will open a PathSettingDialog, where the currently selected path can be modified.
     */
    private class ButtonSelectionListener implements SelectionListener {

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

        public void widgetSelected(SelectionEvent e) {
            // Get the selected item and get the associated path.
            // open a PathSettingDialog to modify the path.
            TableItem selected = fTable.getSelection()[0];
            AVRPathManager path = (AVRPathManager) selected.getData();

            if (e.getSource() == fEditButton) {
                PathSettingDialog dialog = new PathSettingDialog(fTable.getShell(), path);
                if (dialog.open() == Window.OK) {
                    // OK Button selected:
                    // get the modified Path, keep it and update this Editor
                    path = dialog.getResult();
                }
            } else if (e.getSource() == fRescanButton) {
                // force a search for the current system path.
                // This may take a while so we display a Wait cursor
                final AVRPathManager finalpath = path;
                BusyIndicator.showWhile(fTable.getDisplay(), new Runnable() {
                    public void run() {
                        finalpath.getSystemPath(true);
                    }
                });
            }
            selected.setData(path);
            updateTableItem(selected);
            refreshValidState();
        }
    }

    /**
     * Handle selection events from the table.
     * 
     * Once a TableItem has been selected, the Edit button is enabled
     * 
     */
    private class TableSelectionListener implements SelectionListener {

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

        public void widgetSelected(SelectionEvent e) {
            // Enable the Edit button
            fEditButton.setEnabled(true);

            // Enable the rescan button of a system path item has been selected
            TableItem selected = fTable.getSelection()[0];
            AVRPathManager path = (AVRPathManager) selected.getData();
            switch (path.getSourceType()) {
            case System:
                fRescanButton.setEnabled(true);
                break;
            default:
                fRescanButton.setEnabled(false);
            }

        }

    }

    /**
     * Constructor for the AVRPathsFieldEditor.
     * 
     * Sets the preference name (unused) and the labeltext (also unused) to fixed values.
     */
    public AVRPathsFieldEditor(Composite parent) {
        super("avrpaths", "AVR Paths:", parent);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int)
     */
    @Override
    protected void adjustForNumColumns(int numColumns) {
        // Adjust the Layout for the given number of columns.
        // The button will get one column, the table all other columns

        GridData buttonsData = (GridData) fButtons.getLayoutData();
        buttonsData.horizontalSpan = 1;

        GridData tableData = (GridData) fTable.getLayoutData();
        tableData.horizontalSpan = numColumns - 1;

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doFillIntoGrid(org.eclipse.swt.widgets.Composite,
     *      int)
     */
    @Override
    protected void doFillIntoGrid(Composite parent, int numColumns) {

        // Create the Table for all paths

        fTable = new Table(parent, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
        GridData tableData = new GridData(GridData.FILL_BOTH);
        tableData.horizontalSpan = numColumns - 1;
        fTable.setLayoutData(tableData);
        fTable.addSelectionListener(new TableSelectionListener());

        TableColumn nameColumn = new TableColumn(fTable, SWT.LEFT, COLUMN_NAME);
        TableColumn typeColumn = new TableColumn(fTable, SWT.LEFT, COLUMN_TYPE);
        TableColumn pathColumn = new TableColumn(fTable, SWT.LEFT, COLUMN_PATH);

        nameColumn.setText("Path to");
        typeColumn.setText("Source");
        pathColumn.setText("Current value");
        fTable.setHeaderVisible(true);

        // Creates the composite containing the button(s)

        fButtons = new Composite(parent, SWT.NO_FOCUS);

        GridData buttonsData = new GridData(GridData.END);
        buttonsData.horizontalSpan = 1;
        buttonsData.horizontalAlignment = SWT.FILL;
        fButtons.setLayoutData(buttonsData);

        FillLayout buttonsLayout = new FillLayout(SWT.VERTICAL);
        buttonsLayout.spacing = 5;
        fButtons.setLayout(buttonsLayout);

        // Create the edit Button

        fEditButton = new Button(fButtons, SWT.PUSH);

        fEditButton.setText("Edit...");
        fEditButton.addSelectionListener(new ButtonSelectionListener());
        fEditButton.setEnabled(false);

        // Create the rescan Button

        fRescanButton = new Button(fButtons, SWT.PUSH);

        fRescanButton.setText("Rescan");
        fRescanButton.addSelectionListener(new ButtonSelectionListener());
        fRescanButton.setEnabled(false);

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doLoad()
     */
    @Override
    protected void doLoad() {

        // Get the list of all supported paths
        AVRPath[] allpaths = AVRPath.values();

        for (AVRPath current : allpaths) {
            // Create a IPathManager for each path and store it
            // within a new TableItem
            AVRPathManager item = new AVRPathManager(current);

            TableItem ti = new TableItem(fTable, 0);
            ti.setData(item);
            updateTableItem(ti);

        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doLoadDefault()
     */
    @Override
    protected void doLoadDefault() {

        // Get all TableItems
        TableItem[] allitems = fTable.getItems();

        for (TableItem tableitem : allitems) {
            // get the IPathManager for the item and set it to the default value
            AVRPathManager path = (AVRPathManager) tableitem.getData();
            path.setToDefault();
            updateTableItem(tableitem);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doStore()
     */
    @Override
    protected void doStore() {

        // Get all TableItems
        TableItem[] allitems = fTable.getItems();

        for (TableItem tableitem : allitems) {
            // Get the IPathManager of the item and store its value to the
            // persistent storage
            AVRPathManager path = (AVRPathManager) tableitem.getData();
            path.store();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#store()
     */
    @Override
    public void store() {
        // We need to override this method, because we don't access the
        // PreferenceStore directly, but rather indirectly via the IPathManager
        // interface. super.store() tried to use setToDefault on the
        // PreferenceStore, which does not work here.
        if (getPreferenceStore() == null) {
            return;
        }
        doStore();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls()
     */
    @Override
    public int getNumberOfControls() {
        // Table and Buttons
        return 2;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#isValid()
     */
    @Override
    public boolean isValid() {
        return fValid;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#refreshValidState()
     */
    @Override
    protected void refreshValidState() {
        super.refreshValidState();

        // Get all TableItems, extract their IPathManager and check
        // if it is valid and not optional.
        // If any one IPathManager is invalid, the
        // valid boolean is set to false and an error message indicating
        // the culprit is shown.

        TableItem[] allitems = fTable.getItems();
        boolean oldValid = fValid;
        boolean newValid = true;
        String invalidPath = null;

        for (TableItem ti : allitems) {
            AVRPathManager pathitem = (AVRPathManager) ti.getData();
            if (!pathitem.isValid() && !pathitem.isOptional()) {
                newValid = false;
                invalidPath = pathitem.getName();
            }
        }

        // Updates validity and error message.
        fValid = newValid;
        if (fValid == false) {
            showErrorMessage("Path for '" + invalidPath + "' is not valid");
        } else {
            clearErrorMessage();
        }

        // Send some notifications.
        if (newValid != oldValid) {
            fireStateChanged(IS_VALID, oldValid, newValid);
        }

    }

    /**
     * Updates the visual of the given TableItem according to its IPathManager.
     * 
     * @param item
     *            TableItem whose visual needs to be updated
     */
    private void updateTableItem(TableItem item) {

        AVRPathManager path = (AVRPathManager) item.getData();

        // add warn / error icons if path is empty / invalid
        boolean valid = path.isValid();
        boolean optional = path.isOptional();
        boolean empty = (path.getPath().isEmpty());

        if (valid && !empty) {
            // valid path
            item.setImage((Image) null);
        } else if ((valid && empty) || (!valid && optional)) {
            // valid but empty path or invalid and optional path (use for optional paths)
            item.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK));
        } else {
            // Path is invalid
            item.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK));
        }

        item.setText(COLUMN_NAME, path.getName());
        item.setText(COLUMN_TYPE, path.getSourceType().toString());
        item.setText(COLUMN_PATH, path.getPath().toOSString());

        // Adjust color/font according to source type
        switch (path.getSourceType()) {
        case System:
            item.setFont(COLUMN_TYPE, fDialogFont);
            item.setFont(COLUMN_PATH, fDialogFont);
            item.setForeground(COLUMN_PATH, fTable.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
            break;
        case Bundled:
            item.setFont(COLUMN_TYPE, fDialogFont);
            item.setFont(COLUMN_PATH, fDialogFont);
            item.setForeground(COLUMN_PATH, fTable.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
            break;
        case Custom:
            item.setFont(COLUMN_TYPE, fBoldFont);
            item.setFont(COLUMN_PATH, fBoldFont);
            item.setForeground(COLUMN_PATH, fTable.getDisplay().getSystemColor(SWT.COLOR_BLACK));
        }

        // Updates the table layout.
        fTable.getColumn(COLUMN_NAME).pack();
        fTable.getColumn(COLUMN_TYPE).pack();
        fTable.getColumn(COLUMN_PATH).pack();
        fTable.layout();

    }
}