io.usethesource.impulse.preferences.TabbedPreferencesPage.java Source code

Java tutorial

Introduction

Here is the source code for io.usethesource.impulse.preferences.TabbedPreferencesPage.java

Source

/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* 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:
*    Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation
    
*******************************************************************************/

package io.usethesource.impulse.preferences;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

/**
 * A multi-tab preferences page for IMP-supported languages.
 * The various tabs nominally represent the same sets of preferences
 * as set on different levels (default, workspace configuration,
 * workspace instance, and project).
 * 
 * @author suttons@us.ibm.com
 */
public abstract class TabbedPreferencesPage extends PreferencePage implements IWorkbenchPreferencePage {

    // To hold tabs created by specializations of this class;
    // used below in methods that respond to buttons
    PreferencesTab[] tabs = new PreferencesTab[4];

    // To be provided by a language-specific preferences page
    // that is specialized from this one
    protected IPreferencesService prefService = null;

    public TabbedPreferencesPage() {
        this.noDefaultAndApplyButton();
    }

    protected Control createContents(Composite parent) {

        // Create a tab folder to put onto the page
        final TabFolder tabFolder = new TabFolder(parent, SWT.NONE);
        final GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
        gd.widthHint = 0;
        gd.heightHint = SWT.DEFAULT;
        gd.horizontalSpan = 1;
        tabFolder.setLayoutData(gd);

        // Create the tabs that go into the tab folder   
        tabs = createTabs(prefService, this, tabFolder);
        setInitialStateForTabs();

        // The validity of the page depends on the validity of its tabs,
        // so refresh the valid state of the page now that all of the
        // tabs have been created
        notifyState(true);

        // Set the font on the page
        Dialog.applyDialogFont(parent);

        // If there's more than 1 tab, start out by selecting the 2nd tab
        // (usually the "Workspace" tab), rather than the "Project" tab,
        // which doesn't even show values until the user selects a project.
        if (tabs.length > 1) {
            int idx = -1;
            for (int i = 0; i < tabs.length; i++) {
                if (tabs[i].getLevel().equals(IPreferencesService.INSTANCE_LEVEL)) {
                    idx = i;
                }
            }
            if (idx > 0) {
                tabFolder.setSelection(idx);
            }
        }
        return tabFolder;
    }

    /**
     * Assure that the enabled state of conditionally enabled
     * tabs is set appropriately.
     * 
     * When a tab is newly created with some fields that are supposed to
     * be enabled depending on the value of other (boolean) fields, it
     * seems that the enabled state of the conditional fields does not
     * get set properly.  This happens despite explicit attempts to set
     * the appropriate enabled state (perhaps due to race conditions?).
     * Toggling of the condition fields once the tab has been created
     * does cause the enabled state of conditional fields to be set
     * correctly.  This method automates that activity, which can be
     * emulated on the default tab by restoring and applying the default
     * field values.  However, changes on the default tab can affect
     * lower levels in the preferences hierarchy--values inherited from
     * the default level do not change, but the fact that the default
     * values have been restored causes inherited values to be marked as
     * modified.  To clear the modified marks from lower levels of the
     * preferences hierarchy, the tabs for those levels are also applied,
     * in a top-down order.  On the project level default values are
     * restored before being applied; this assures that the fields are
     * empty, as they should be, because there should be no project
     * selected at this point.
     *
     */
    protected void setInitialStateForTabs() {
        // Assure that all tabs are initialized properly
        // and reflect an unmodified state
        for (int i = 0; i < tabs.length; i++) {
            if (tabs[i] instanceof DefaultPreferencesTab) {
                tabs[i].performDefaults();
                tabs[i].performApply();
                break;
            }
        }
        for (int i = 0; i < tabs.length; i++) {
            if (tabs[i] instanceof ConfigurationPreferencesTab) {
                tabs[i].performApply();
                break;
            }
        }
        for (int i = 0; i < tabs.length; i++) {
            if (tabs[i] instanceof InstancePreferencesTab) {
                tabs[i].performApply();
                break;
            }
        }
        for (int i = 0; i < tabs.length; i++) {
            if (tabs[i] instanceof ProjectPreferencesTab) {
                tabs[i].performDefaults();
                tabs[i].performApply();
                break;
            }
        }
    }

    /**
     * Create the tabs that represent the different levels of preferences
     * shown on this page.  Nominally these are the default, workspace configuraiton,
     * workspace instance, and project levels.
     * 
     * @param prefService   The service that manages the preferences by level
     * @param page         The page on which the tabs are to be created (that is, this page)
     * @param tabFolder      The tab folder, on this page, that will contain the created tabs
     * @return            An array containing the created tabs
     */
    protected abstract PreferencesTab[] createTabs(IPreferencesService prefService, TabbedPreferencesPage page,
            TabFolder tabFolder);

    /**
     * 
     */
    public boolean notifyState(boolean state) {
        boolean allValid = true;
        for (int i = 0; i < tabs.length && allValid; i++) {
            allValid = allValid && tabs[i] != null && tabs[i].isValid();
        }
        setValid(allValid);
        return allValid;
    }

    /*
     * The following four operations provide a page-level response to the pressing of
     * buttons on the page.  Note, though, that a preference page may not have all of
     * these buttons--buttons not present on the page may instead be present on individual
     * tabs on the page.
     */

    /**
     * Respond to pressing of the Apply button by saving the prevailing preferences.
     * 
     * Note:  In a system of multiple preference levels with preference-value
     * inheritance, this may only save values on the levels on which they
     * are stored, i.e., not on levels where they apply through inheritance only.
     * 
     * @see org.eclipse.jface.preference.PreferencePage#performApply()
     */
    public void performApply() {
        for (int i = 0; i < tabs.length; i++) {
            tabs[i].performApply();
        }
    }

    /**
     * Respond to pressing of Cancel button by cancelling in-progress
     * preference updates on each level.
     * 
     * @see org.eclipse.jface.preference.IPreferencePage#performCancel()
     */
    public boolean performCancel() {
        // SMS 4 Dec 2006
        // Previously just used to return true; now trying to
        // allow for a negative return
        boolean result = true;
        for (int i = 0; i < tabs.length; i++) {
            // If there was a problem initializing the tabs, one or more might be null now.
            if (tabs[i] != null) {
                result = result && tabs[i].performCancel();
            }
        }

        return result;
    }

    /**
     * Respond to pressing of Restore Defaults button by restoring default
     * values on each level.
     * 
     * Note:  In a system of multiple preference levels with preference-value
     * inheritance, the default value on levels other than the default level
     * may be considered to be the level inherited from the next higher level,
     * so this may entail removing the preferences stored on each level other
     * than the default level.  On the default level, the programmed default
     * values should be restored.
     * 
     * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
     */
    public void performDefaults() {
        // SMS 4 Dec 2006
        // Need to check visibility of a composite that contains the tab;
        // be sure that the right one is checked here ...
        for (int i = 0; i < tabs.length; i++) {
            if (tabs[i].getTabItem().getControl().isVisible())
                tabs[i].performDefaults();
        }

    }

    /**
     * Respond to pressing of the Save button by saving the prevailing preferences.
     * 
     * Note:  In a system of multiple preference levels with preference-value
     * inheritance, this may only save values on the levels on which they
     * are stored, i.e., not on levels where they apply through inheritance only.
     * 
     * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
     */
    public boolean performOk() {
        // SMS 4 Dec 2006
        // Not sure of the effect of returning false, but
        // should probably allow for that   
        boolean result = true;
        for (int i = tabs.length - 1; i >= 0; i--) {
            result = result && tabs[i].performOk();
        }

        return result;
    }

    /**
     * For IWorkbenchPreferencePage
     * 
     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
     */
    public void init(IWorkbench workbench) {
    }

    /**
     * Get the tabs used on this preference page
     * 
     * @return   The tabs used on this preference page
     */
    protected PreferencesTab[] getTabs() {
        return tabs;
    }

    /**
     * Should be overridden in language-specific tabbed preferences page
     * to make use of language-specific preference initializer.
     * 
     * @return    The preference initializer to be used to initialize
     *          preferences in this tab
     */
    // TODO:  Probably should make this an abstract method
    public PreferencesInitializer getPreferenceInitializer() {
        // TODO:  Override in subclass where the language-specific
        // initializer should be known
        System.out.println(
                "TabbedPreferencesPage.getPreferenceInitializar():  unimplemented; should be overridden with language-specific implementation");
        return null;
    }

}