org.eclipse.ui.ide.dialogs.AbstractEncodingFieldEditor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ui.ide.dialogs.AbstractEncodingFieldEditor.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2009 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
 *     Daniel Megert daniel_megert@ch.ibm.com Bug 169696
 *******************************************************************************/
package org.eclipse.ui.ide.dialogs;

import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.util.List;

import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.osgi.util.NLS;

import org.eclipse.swt.SWT;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.ui.WorkbenchEncoding;
import org.eclipse.ui.ide.IDEEncoding;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;

/**
 * The abstract superclass of field editors used to set an encoding. Any user
 * entered encodings will be added to the list of encodings available via
 * {@link org.eclipse.ui.ide.IDEEncoding}.
 * <p>
 * Subclasses may extend, but must call <code>createEncodingGroup</code>
 * during <code>doFillIntoGrid</code>.
 * </p>
 * 
 * @see org.eclipse.ui.ide.IDEEncoding
 * @since 3.1
 */
public abstract class AbstractEncodingFieldEditor extends FieldEditor {

    private Composite container;

    private Button defaultEncodingButton;

    private String defaultEnc;

    private Button otherEncodingButton;

    private Combo encodingCombo;

    private boolean isValid = true;

    private String oldSelectedEncoding;

    private String groupTitle = IDEWorkbenchMessages.WorkbenchPreference_encoding;

    /**
     * Creates a new encoding field editor with no settings set.
     */
    protected AbstractEncodingFieldEditor() {
        super();
    }

    /**
     * Creates a new encoding field editor with the given preference name, label
     * and parent.
     * 
     * @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
     */
    protected AbstractEncodingFieldEditor(String name, String labelText, Composite parent) {
        super(name, labelText, parent);
    }

    /**
     * Creates a new encoding field editor with the given preference name, label
     * and parent.
     * 
     * @param name
     *            the name of the preference this field editor works on
     * @param labelText
     *            the label text of the field editor
     * @param groupTitle
     *            the title for the field editor's control. If groupTitle is
     *            <code>null</code> the control will be unlabelled
     *            (by default a {@link Composite} instead of a {@link Group}.
     * @param parent
     *            the parent of the field editor's control
     * @see AbstractEncodingFieldEditor#setGroupTitle(String)
     * @since 3.3
     */
    protected AbstractEncodingFieldEditor(String name, String labelText, String groupTitle, Composite parent) {
        init(name, labelText);
        this.groupTitle = groupTitle;
        createControl(parent);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int)
     */
    protected void adjustForNumColumns(int numColumns) {
        ((GridData) getContainer().getLayoutData()).horizontalSpan = numColumns;
    }

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

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#doLoad()
     */
    protected void doLoad() {
        if (encodingCombo != null) {
            List encodings = IDEEncoding.getIDEEncodings();
            String resourcePreference = getStoredValue();
            populateEncodingsCombo(encodings, resourcePreference);
            updateEncodingState(resourcePreference == null);
        }
    }

    /**
     * Returns the value that is currently stored for the encoding.
     * 
     * @return the currently stored encoding
     */
    protected abstract String getStoredValue();

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

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls()
     */
    public int getNumberOfControls() {
        return 1;
    }

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

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

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore)
     */
    public void setPreferenceStore(IPreferenceStore store) {
        super.setPreferenceStore(store);
        defaultEnc = store.getDefaultString(getPreferenceName());
        updateDefaultEncoding();
    }

    private void updateDefaultEncoding() {
        defaultEncodingButton.setText(defaultButtonText());
    }

    private Composite getContainer() {
        return container;
    }

    /**
     * Creates a composite with all the encoding controls.
     * <p>
     * Subclasses may extend.
     * </p>
     * 
     * @param parent
     *            the parent widget
     * @param numColumns
     *            the number of columns in the parent
     * @return the group control
     */
    protected Composite createEncodingGroup(Composite parent, int numColumns) {

        Composite topControl;
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;

        if (groupTitle == null) {
            topControl = new Composite(parent, SWT.NONE);
            layout.marginWidth = 0;
            layout.marginHeight = 0;
        } else {
            Group top = new Group(parent, SWT.NONE);
            top.setText(groupTitle);
            topControl = top;
        }

        GridData data = new GridData(GridData.FILL_HORIZONTAL);
        topControl.setLayoutData(data);
        topControl.setLayout(layout);

        SelectionAdapter buttonListener = new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                updateEncodingState(defaultEncodingButton.getSelection());
                updateValidState();
            }
        };

        defaultEncodingButton = new Button(topControl, SWT.RADIO);
        defaultEnc = findDefaultEncoding();
        defaultEncodingButton.setText(defaultButtonText());
        data = new GridData();
        data.horizontalSpan = 2;
        defaultEncodingButton.setLayoutData(data);
        defaultEncodingButton.addSelectionListener(buttonListener);

        otherEncodingButton = new Button(topControl, SWT.RADIO);
        otherEncodingButton.setText(IDEWorkbenchMessages.WorkbenchPreference_otherEncoding);
        otherEncodingButton.addSelectionListener(buttonListener);

        encodingCombo = new Combo(topControl, SWT.NONE);
        data = new GridData();
        encodingCombo.setLayoutData(data);
        encodingCombo.addSelectionListener(new SelectionAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
             */
            public void widgetSelected(SelectionEvent e) {
                updateValidState();
            }
        });
        encodingCombo.addKeyListener(new KeyAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
             */
            public void keyReleased(KeyEvent e) {
                updateValidState();
            }
        });

        return topControl;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.preference.FieldEditor#setEnabled(boolean,
     *      org.eclipse.swt.widgets.Composite)
     * @since 3.3
     */
    public void setEnabled(boolean enabled, Composite parent) {
        if (container != null)
            container.setEnabled(enabled);
        if (defaultEncodingButton != null)
            defaultEncodingButton.setEnabled(enabled);
        if (otherEncodingButton != null)
            otherEncodingButton.setEnabled(enabled);
        if (encodingCombo != null)
            encodingCombo.setEnabled(enabled && otherEncodingButton.getSelection());

    }

    /**
     * Returns the default encoding for the object being shown.
     * 
     * @return the default encoding for the object being shown
     */
    protected String findDefaultEncoding() {
        return WorkbenchEncoding.getWorkbenchDefaultEncoding();
    }

    /**
     * Returns the text for the default encoding button.
     * 
     * @return the text for the default encoding button
     */
    protected String defaultButtonText() {
        return NLS.bind(IDEWorkbenchMessages.WorkbenchPreference_defaultEncoding, defaultEnc);
    }

    /**
     * Populates the encodings combo. Sets the text based on the selected
     * encoding. If there is no selected encoding, the text is set to the
     * default encoding.
     * 
     * @param encodings
     *            the list of encodings (list of String)
     * @param selectedEncoding
     *            the selected encoding, or <code>null</code>
     */
    private void populateEncodingsCombo(List encodings, String selectedEncoding) {
        String[] encodingStrings = new String[encodings.size()];
        encodings.toArray(encodingStrings);
        encodingCombo.setItems(encodingStrings);

        if (selectedEncoding == null) {
            encodingCombo.setText(getDefaultEnc());
        } else {
            encodingCombo.setText(selectedEncoding);
        }
    }

    private void updateEncodingState(boolean useDefault) {
        defaultEncodingButton.setSelection(useDefault);
        otherEncodingButton.setSelection(!useDefault);
        if (useDefault) {
            encodingCombo.setText(getDefaultEnc());
        }
        encodingCombo.setEnabled(!useDefault);
        setPresentsDefaultValue(useDefault);
        updateValidState();
    }

    private void updateValidState() {
        boolean isValidNow = isEncodingValid();
        if (isValidNow != isValid) {
            isValid = isValidNow;
            if (isValid) {
                clearErrorMessage();
            } else {
                showErrorMessage(IDEWorkbenchMessages.WorkbenchPreference_unsupportedEncoding);
            }
            fireStateChanged(IS_VALID, !isValid, isValid);
        }
        String newValue = getSelectedEncoding();
        if (isValid && !newValue.equals(oldSelectedEncoding)) {
            fireValueChanged(VALUE, oldSelectedEncoding, newValue);
            oldSelectedEncoding = newValue;
        }
    }

    /**
     * Returns the currently selected encoding.
     * 
     * @return the currently selected encoding
     */
    protected String getSelectedEncoding() {
        if (defaultEncodingButton.getSelection()) {
            return defaultEnc;
        }
        return encodingCombo.getText();
    }

    private boolean isEncodingValid() {
        return defaultEncodingButton.getSelection() || isValidEncoding(encodingCombo.getText());
    }

    /**
     * Returns whether or not the given encoding is valid.
     * 
     * @param enc
     *            the encoding to validate
     * @return <code>true</code> if the encoding is valid, <code>false</code>
     *         otherwise
     */
    private boolean isValidEncoding(String enc) {
        try {
            return Charset.isSupported(enc);
        } catch (IllegalCharsetNameException e) {
            // This is a valid exception
            return false;
        }

    }

    /**
     * Returns the default encoding.
     * 
     * @return the default encoding
     */
    protected String getDefaultEnc() {
        return defaultEnc;
    }

    /**
     * Returns whether or not the encoding setting changed.
     * 
     * @param encodingSetting
     *            the setting from the page.
     * @return boolean <code>true</code> if the resource encoding is the same
     *         as before.
     */
    protected boolean hasSameEncoding(String encodingSetting) {

        String current = getStoredValue();

        if (encodingSetting == null) {
            // Changed if default is selected and there is no setting
            return current == null || current.length() == 0;
        }
        return encodingSetting.equals(current);
    }

    /**
     * Return whether or not the default has been selected.
     * 
     * @return <code>true</code> if the default button has been selected.
     */
    boolean isDefaultSelected() {
        return defaultEncodingButton.getSelection();
    }

    /**
     * Set the title of the group to groupTitle. If this is not called a default
     * title is used. If groupTitle is <code>null</code> the control will be
     * unlabelled (by default a {@link Composite} instead of a {@link Group}.
     * 
     * <strong>NOTE</strong> this value must be set before
     * {@link #createControl(Composite)} is called or it will be ignored.
     * 
     * @param groupTitle
     *            The groupTitle to set.
      * @since 3.3
     */
    public void setGroupTitle(String groupTitle) {
        this.groupTitle = groupTitle;
    }

}