/*******************************************************************************
* 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 true
iff the file exists and can be opened,
* false
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 }));
}
}