--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.preferences;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
+import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
+import net.sourceforge.phpdt.internal.ui.text.spelling.SpellCheckEngine;
+import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
+import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
+import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+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.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.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Options configuration block for spell-check related settings.
+ *
+ * @since 3.0
+ */
+public class SpellingConfigurationBlock extends OptionsConfigurationBlock {
+
+ /** Preference keys for the preferences in this block */
+ private static final String PREF_SPELLING_CHECK_SPELLING = PreferenceConstants.SPELLING_CHECK_SPELLING;
+
+ private static final String PREF_SPELLING_IGNORE_DIGITS = PreferenceConstants.SPELLING_IGNORE_DIGITS;
+
+ private static final String PREF_SPELLING_IGNORE_MIXED = PreferenceConstants.SPELLING_IGNORE_MIXED;
+
+ private static final String PREF_SPELLING_IGNORE_SENTENCE = PreferenceConstants.SPELLING_IGNORE_SENTENCE;
+
+ private static final String PREF_SPELLING_IGNORE_UPPER = PreferenceConstants.SPELLING_IGNORE_UPPER;
+
+ private static final String PREF_SPELLING_IGNORE_URLS = PreferenceConstants.SPELLING_IGNORE_URLS;
+
+ private static final String PREF_SPELLING_LOCALE = PreferenceConstants.SPELLING_LOCALE;
+
+ private static final String PREF_SPELLING_PROPOSAL_THRESHOLD = PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD;
+
+ private static final String PREF_SPELLING_USER_DICTIONARY = PreferenceConstants.SPELLING_USER_DICTIONARY;
+
+ private static final String PREF_SPELLING_ENABLE_CONTENTASSIST = PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST;
+
+ /**
+ * Creates a selection dependency between a master and a slave control.
+ *
+ * @param master
+ * The master button that controls the state of the slave
+ * @param slave
+ * The slave control that is enabled only if the master is
+ * selected
+ */
+ protected static void createSelectionDependency(final Button master,
+ final Control slave) {
+
+ master.addSelectionListener(new SelectionListener() {
+
+ public void widgetDefaultSelected(SelectionEvent event) {
+ // Do nothing
+ }
+
+ public void widgetSelected(SelectionEvent event) {
+ slave.setEnabled(master.getSelection());
+ }
+ });
+ slave.setEnabled(master.getSelection());
+ }
+
+ /**
+ * Returns the locale codes for the locale list.
+ *
+ * @param locales
+ * The list of locales
+ * @return Array of locale codes for the list
+ */
+ protected static String[] getDictionaryCodes(final Set locales) {
+
+ int index = 0;
+ Locale locale = null;
+
+ final String[] codes = new String[locales.size()];
+ for (final Iterator iterator = locales.iterator(); iterator.hasNext();) {
+
+ locale = (Locale) iterator.next();
+ codes[index++] = locale.toString();
+ }
+ return codes;
+ }
+
+ /**
+ * Returns the display labels for the locale list.
+ *
+ * @param locales
+ * The list of locales
+ * @return Array of display labels for the list
+ */
+ protected static String[] getDictionaryLabels(final Set locales) {
+
+ int index = 0;
+ Locale locale = null;
+
+ final String[] labels = new String[locales.size()];
+ for (final Iterator iterator = locales.iterator(); iterator.hasNext();) {
+
+ locale = (Locale) iterator.next();
+ labels[index++] = locale.getDisplayName(SpellCheckEngine
+ .getDefaultLocale());
+ }
+ return labels;
+ }
+
+ /**
+ * Validates that the file with the specified absolute path exists and can
+ * be opened.
+ *
+ * @param path
+ * The path of the file to validate
+ * @return <code>true</code> iff the file exists and can be opened,
+ * <code>false</code> otherwise
+ */
+ protected static IStatus validateAbsoluteFilePath(final String path) {
+
+ final StatusInfo status = new StatusInfo();
+ if (path.length() > 0) {
+
+ final File file = new File(path);
+ if (!file.isFile() || !file.isAbsolute() || !file.exists()
+ || !file.canRead() || !file.canWrite())
+ status.setError(PreferencesMessages
+ .getString("SpellingPreferencePage.dictionary.error")); //$NON-NLS-1$
+
+ }
+ return status;
+ }
+
+ /**
+ * Validates that the specified locale is available.
+ *
+ * @param locale
+ * The locale to validate
+ * @return The status of the validation
+ */
+ protected static IStatus validateLocale(final String locale) {
+
+ final StatusInfo status = new StatusInfo(IStatus.ERROR,
+ PreferencesMessages
+ .getString("SpellingPreferencePage.locale.error")); //$NON-NLS-1$
+ final Set locales = SpellCheckEngine.getAvailableLocales();
+
+ Locale current = null;
+ for (final Iterator iterator = locales.iterator(); iterator.hasNext();) {
+
+ current = (Locale) iterator.next();
+ if (current.toString().equals(locale))
+ return new StatusInfo();
+ }
+ return status;
+ }
+
+ /**
+ * Validates that the specified number is positive.
+ *
+ * @param number
+ * The number to validate
+ * @return The status of the validation
+ */
+ protected static IStatus validatePositiveNumber(final String number) {
+
+ final StatusInfo status = new StatusInfo();
+ if (number.length() == 0) {
+ status.setError(PreferencesMessages
+ .getString("SpellingPreferencePage.empty_threshold")); //$NON-NLS-1$
+ } else {
+ try {
+ final int value = Integer.parseInt(number);
+ if (value < 0) {
+ status
+ .setError(PreferencesMessages
+ .getFormattedString(
+ "SpellingPreferencePage.invalid_threshold", number)); //$NON-NLS-1$
+ }
+ } catch (NumberFormatException exception) {
+ status.setError(PreferencesMessages.getFormattedString(
+ "SpellingPreferencePage.invalid_threshold", number)); //$NON-NLS-1$
+ }
+ }
+ return status;
+ }
+
+ /** The dictionary path field */
+ private Text fDictionaryPath = null;
+
+ /** The status for the workspace dictionary file */
+ private IStatus fFileStatus = new StatusInfo();
+
+ /** The status for the platform locale */
+ private IStatus fLocaleStatus = new StatusInfo();
+
+ /** The status for the proposal threshold */
+ private IStatus fThresholdStatus = new StatusInfo();
+
+ /**
+ * Creates a new spelling configuration block.
+ *
+ * @param context
+ * The status change listener
+ * @param project
+ * The Java project
+ */
+ public SpellingConfigurationBlock(final IStatusChangeListener context,
+ final IJavaProject project) {
+ super(context, project, getAllKeys());
+
+ IStatus status = validateAbsoluteFilePath((String) fWorkingValues
+ .get(PREF_SPELLING_USER_DICTIONARY));
+ if (status.getSeverity() != IStatus.OK)
+ fWorkingValues.put(PREF_SPELLING_USER_DICTIONARY, ""); //$NON-NLS-1$
+
+ status = validateLocale((String) fWorkingValues
+ .get(PREF_SPELLING_LOCALE));
+ if (status.getSeverity() != IStatus.OK)
+ fWorkingValues.put(PREF_SPELLING_LOCALE, SpellCheckEngine
+ .getDefaultLocale().toString());
+ }
+
+ protected Combo addComboBox(Composite parent, String label, String key,
+ String[] values, String[] valueLabels, int indent) {
+ ControlData data = new ControlData(key, values);
+
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indent;
+
+ Label labelControl = new Label(parent, SWT.LEFT | SWT.WRAP);
+ labelControl.setText(label);
+ labelControl.setLayoutData(gd);
+
+ Combo comboBox = new Combo(parent, SWT.READ_ONLY);
+ comboBox.setItems(valueLabels);
+ comboBox.setData(data);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gd.horizontalSpan = 2;
+ comboBox.setLayoutData(gd);
+ comboBox.addSelectionListener(getSelectionListener());
+
+ fLabels.put(comboBox, labelControl);
+
+ String currValue = (String) fWorkingValues.get(key);
+ comboBox.select(data.getSelection(currValue));
+
+ fComboBoxes.add(comboBox);
+ return comboBox;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(final Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+
+ final PixelConverter converter = new PixelConverter(parent);
+
+ layout = new GridLayout();
+ layout.numColumns = 3;
+
+ final String[] trueFalse = new String[] { IPreferenceStore.TRUE,
+ IPreferenceStore.FALSE };
+
+ Group user = new Group(composite, SWT.NONE);
+ user.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.preferences.user")); //$NON-NLS-1$
+ user.setLayout(new GridLayout());
+ user.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ String label = PreferencesMessages
+ .getString("SpellingPreferencePage.enable.label"); //$NON-NLS-1$
+ final Button master = addCheckBox(user, label,
+ PREF_SPELLING_CHECK_SPELLING, trueFalse, 0);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.digits.label"); //$NON-NLS-1$
+ Control slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_DIGITS,
+ trueFalse, 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.mixed.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_MIXED, trueFalse,
+ 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.sentence.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_SENTENCE,
+ trueFalse, 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.upper.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_UPPER, trueFalse,
+ 20);
+ createSelectionDependency(master, slave);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.ignore.url.label"); //$NON-NLS-1$
+ slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_URLS, trueFalse,
+ 20);
+ createSelectionDependency(master, slave);
+
+ final Group engine = new Group(composite, SWT.NONE);
+ engine.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.preferences.engine")); //$NON-NLS-1$
+ layout = new GridLayout();
+ layout.numColumns = 4;
+ engine.setLayout(layout);
+ engine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.dictionary.label"); //$NON-NLS-1$
+ final Set locales = SpellCheckEngine.getAvailableLocales();
+
+ Combo combo = addComboBox(engine, label, PREF_SPELLING_LOCALE,
+ getDictionaryCodes(locales), getDictionaryLabels(locales), 0);
+ combo.setEnabled(locales.size() > 1);
+
+ new Label(engine, SWT.NONE); // placeholder
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.workspace.dictionary.label"); //$NON-NLS-1$
+ fDictionaryPath = addTextField(engine, label,
+ PREF_SPELLING_USER_DICTIONARY, 0, 0);
+
+ Button button = new Button(engine, SWT.PUSH);
+ button.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.browse.label")); //$NON-NLS-1$
+ button.addSelectionListener(new SelectionAdapter() {
+
+ public void widgetSelected(final SelectionEvent event) {
+ handleBrowseButtonSelected();
+ }
+ });
+ button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
+ SWTUtil.setButtonDimensionHint(button);
+
+ layout = new GridLayout();
+ layout.numColumns = 3;
+
+ Group advanced = new Group(composite, SWT.NONE);
+ advanced.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.preferences.advanced")); //$NON-NLS-1$
+ layout = new GridLayout();
+ layout.numColumns = 3;
+ advanced.setLayout(layout);
+ advanced.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.proposals.threshold"); //$NON-NLS-1$
+ Text text = addTextField(advanced, label,
+ PREF_SPELLING_PROPOSAL_THRESHOLD, 0, 0);
+ text.setTextLimit(3);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ data.widthHint = converter.convertWidthInCharsToPixels(4);
+ text.setLayoutData(data);
+
+ label = PreferencesMessages
+ .getString("SpellingPreferencePage.enable.contentassist.label"); //$NON-NLS-1$
+ addCheckBox(advanced, label, PREF_SPELLING_ENABLE_CONTENTASSIST,
+ trueFalse, 0);
+
+ return composite;
+ }
+
+ private static String[] getAllKeys() {
+ return new String[] { PREF_SPELLING_USER_DICTIONARY,
+ PREF_SPELLING_CHECK_SPELLING, PREF_SPELLING_IGNORE_DIGITS,
+ PREF_SPELLING_IGNORE_MIXED, PREF_SPELLING_IGNORE_SENTENCE,
+ PREF_SPELLING_IGNORE_UPPER, PREF_SPELLING_IGNORE_URLS,
+ PREF_SPELLING_LOCALE, PREF_SPELLING_PROPOSAL_THRESHOLD,
+ PREF_SPELLING_ENABLE_CONTENTASSIST };
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getDefaultOptions()
+ */
+ protected Map getDefaultOptions() {
+
+ final String[] keys = fAllKeys;
+ final Map options = new HashMap();
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ options.put(keys[index], store.getDefaultString(keys[index]));
+
+ return options;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
+ */
+ protected final String[] getFullBuildDialogStrings(final boolean workspace) {
+ return null;
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getOptions(boolean)
+ */
+ protected Map getOptions(final boolean inherit) {
+
+ final String[] keys = fAllKeys;
+ final Map options = new HashMap();
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ options.put(keys[index], store.getString(keys[index]));
+
+ return options;
+ }
+
+ /**
+ * Handles selections of the browse button.
+ */
+ protected void handleBrowseButtonSelected() {
+
+ final FileDialog dialog = new FileDialog(fDictionaryPath.getShell(),
+ SWT.OPEN);
+ dialog.setText(PreferencesMessages
+ .getString("SpellingPreferencePage.filedialog.title")); //$NON-NLS-1$
+ dialog
+ .setFilterExtensions(new String[] {
+ PreferencesMessages
+ .getString("SpellingPreferencePage.filter.dictionary.extension"), PreferencesMessages.getString("SpellingPreferencePage.filter.all.extension") }); //$NON-NLS-1$ //$NON-NLS-2$
+ dialog
+ .setFilterNames(new String[] {
+ PreferencesMessages
+ .getString("SpellingPreferencePage.filter.dictionary.label"), PreferencesMessages.getString("SpellingPreferencePage.filter.all.label") }); //$NON-NLS-1$ //$NON-NLS-2$
+
+ final String path = dialog.open();
+ if (path != null)
+ fDictionaryPath.setText(path);
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#setOptions(java.util.Map)
+ */
+ protected void setOptions(final Map options) {
+
+ final String[] keys = fAllKeys;
+ final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
+
+ for (int index = 0; index < keys.length; index++)
+ store.setValue(keys[index], (String) fWorkingValues
+ .get(keys[index]));
+ }
+
+ /*
+ * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(java.lang.String,java.lang.String)
+ */
+ protected void validateSettings(final String key, final String value) {
+
+ if (key == null || PREF_SPELLING_PROPOSAL_THRESHOLD.equals(key))
+ fThresholdStatus = validatePositiveNumber((String) fWorkingValues
+ .get(PREF_SPELLING_PROPOSAL_THRESHOLD));
+
+ if (key == null || PREF_SPELLING_USER_DICTIONARY.equals(key))
+ fFileStatus = validateAbsoluteFilePath((String) fWorkingValues
+ .get(PREF_SPELLING_USER_DICTIONARY));
+
+ if (key == null || PREF_SPELLING_LOCALE.equals(key))
+ fLocaleStatus = validateLocale((String) fWorkingValues
+ .get(PREF_SPELLING_LOCALE));
+
+ fContext.statusChanged(StatusUtil.getMostSevere(new IStatus[] {
+ fThresholdStatus, fFileStatus, fLocaleStatus }));
+ }
+}