1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  12 package net.sourceforge.phpdt.internal.ui.preferences;
 
  15 import java.util.HashMap;
 
  16 import java.util.Iterator;
 
  17 import java.util.Locale;
 
  21 import net.sourceforge.phpdt.core.IJavaProject;
 
  22 import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
 
  23 import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
 
  24 import net.sourceforge.phpdt.internal.ui.text.spelling.SpellCheckEngine;
 
  25 import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
 
  26 import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
 
  27 import net.sourceforge.phpdt.internal.ui.wizards.IStatusChangeListener;
 
  28 import net.sourceforge.phpdt.ui.PreferenceConstants;
 
  30 import org.eclipse.core.runtime.IStatus;
 
  31 import org.eclipse.jface.preference.IPreferenceStore;
 
  32 import org.eclipse.swt.SWT;
 
  33 import org.eclipse.swt.events.SelectionAdapter;
 
  34 import org.eclipse.swt.events.SelectionEvent;
 
  35 import org.eclipse.swt.events.SelectionListener;
 
  36 import org.eclipse.swt.layout.GridData;
 
  37 import org.eclipse.swt.layout.GridLayout;
 
  38 import org.eclipse.swt.widgets.Button;
 
  39 import org.eclipse.swt.widgets.Combo;
 
  40 import org.eclipse.swt.widgets.Composite;
 
  41 import org.eclipse.swt.widgets.Control;
 
  42 import org.eclipse.swt.widgets.FileDialog;
 
  43 import org.eclipse.swt.widgets.Group;
 
  44 import org.eclipse.swt.widgets.Label;
 
  45 import org.eclipse.swt.widgets.Text;
 
  48  * Options configuration block for spell-check related settings.
 
  52 public class SpellingConfigurationBlock extends OptionsConfigurationBlock {
 
  54         /** Preference keys for the preferences in this block */
 
  55         private static final String PREF_SPELLING_CHECK_SPELLING = PreferenceConstants.SPELLING_CHECK_SPELLING;
 
  57         private static final String PREF_SPELLING_IGNORE_DIGITS = PreferenceConstants.SPELLING_IGNORE_DIGITS;
 
  59         private static final String PREF_SPELLING_IGNORE_MIXED = PreferenceConstants.SPELLING_IGNORE_MIXED;
 
  61         private static final String PREF_SPELLING_IGNORE_SENTENCE = PreferenceConstants.SPELLING_IGNORE_SENTENCE;
 
  63         private static final String PREF_SPELLING_IGNORE_UPPER = PreferenceConstants.SPELLING_IGNORE_UPPER;
 
  65         private static final String PREF_SPELLING_IGNORE_URLS = PreferenceConstants.SPELLING_IGNORE_URLS;
 
  67         private static final String PREF_SPELLING_LOCALE = PreferenceConstants.SPELLING_LOCALE;
 
  69         private static final String PREF_SPELLING_PROPOSAL_THRESHOLD = PreferenceConstants.SPELLING_PROPOSAL_THRESHOLD;
 
  71         private static final String PREF_SPELLING_USER_DICTIONARY = PreferenceConstants.SPELLING_USER_DICTIONARY;
 
  73         private static final String PREF_SPELLING_ENABLE_CONTENTASSIST = PreferenceConstants.SPELLING_ENABLE_CONTENTASSIST;
 
  76          * Creates a selection dependency between a master and a slave control.
 
  79          *            The master button that controls the state of the slave
 
  81          *            The slave control that is enabled only if the master is
 
  84         protected static void createSelectionDependency(final Button master,
 
  85                         final Control slave) {
 
  87                 master.addSelectionListener(new SelectionListener() {
 
  89                         public void widgetDefaultSelected(SelectionEvent event) {
 
  93                         public void widgetSelected(SelectionEvent event) {
 
  94                                 slave.setEnabled(master.getSelection());
 
  97                 slave.setEnabled(master.getSelection());
 
 101          * Returns the locale codes for the locale list.
 
 104          *            The list of locales
 
 105          * @return Array of locale codes for the list
 
 107         protected static String[] getDictionaryCodes(final Set locales) {
 
 110                 Locale locale = null;
 
 112                 final String[] codes = new String[locales.size()];
 
 113                 for (final Iterator iterator = locales.iterator(); iterator.hasNext();) {
 
 115                         locale = (Locale) iterator.next();
 
 116                         codes[index++] = locale.toString();
 
 122          * Returns the display labels for the locale list.
 
 125          *            The list of locales
 
 126          * @return Array of display labels for the list
 
 128         protected static String[] getDictionaryLabels(final Set locales) {
 
 131                 Locale locale = null;
 
 133                 final String[] labels = new String[locales.size()];
 
 134                 for (final Iterator iterator = locales.iterator(); iterator.hasNext();) {
 
 136                         locale = (Locale) iterator.next();
 
 137                         labels[index++] = locale.getDisplayName(SpellCheckEngine
 
 138                                         .getDefaultLocale());
 
 144          * Validates that the file with the specified absolute path exists and can
 
 148          *            The path of the file to validate
 
 149          * @return <code>true</code> iff the file exists and can be opened,
 
 150          *         <code>false</code> otherwise
 
 152         protected static IStatus validateAbsoluteFilePath(final String path) {
 
 154                 final StatusInfo status = new StatusInfo();
 
 155                 if (path.length() > 0) {
 
 157                         final File file = new File(path);
 
 158                         if (!file.isFile() || !file.isAbsolute() || !file.exists()
 
 159                                         || !file.canRead() || !file.canWrite())
 
 160                                 status.setError(PreferencesMessages
 
 161                                                 .getString("SpellingPreferencePage.dictionary.error")); //$NON-NLS-1$
 
 168          * Validates that the specified locale is available.
 
 171          *            The locale to validate
 
 172          * @return The status of the validation
 
 174         protected static IStatus validateLocale(final String locale) {
 
 176                 final StatusInfo status = new StatusInfo(IStatus.ERROR,
 
 178                                                 .getString("SpellingPreferencePage.locale.error")); //$NON-NLS-1$
 
 179                 final Set locales = SpellCheckEngine.getAvailableLocales();
 
 181                 Locale current = null;
 
 182                 for (final Iterator iterator = locales.iterator(); iterator.hasNext();) {
 
 184                         current = (Locale) iterator.next();
 
 185                         if (current.toString().equals(locale))
 
 186                                 return new StatusInfo();
 
 192          * Validates that the specified number is positive.
 
 195          *            The number to validate
 
 196          * @return The status of the validation
 
 198         protected static IStatus validatePositiveNumber(final String number) {
 
 200                 final StatusInfo status = new StatusInfo();
 
 201                 if (number.length() == 0) {
 
 202                         status.setError(PreferencesMessages
 
 203                                         .getString("SpellingPreferencePage.empty_threshold")); //$NON-NLS-1$
 
 206                                 final int value = Integer.parseInt(number);
 
 209                                                         .setError(PreferencesMessages
 
 211                                                                                         "SpellingPreferencePage.invalid_threshold", number)); //$NON-NLS-1$
 
 213                         } catch (NumberFormatException exception) {
 
 214                                 status.setError(PreferencesMessages.getFormattedString(
 
 215                                                 "SpellingPreferencePage.invalid_threshold", number)); //$NON-NLS-1$
 
 221         /** The dictionary path field */
 
 222         private Text fDictionaryPath = null;
 
 224         /** The status for the workspace dictionary file */
 
 225         private IStatus fFileStatus = new StatusInfo();
 
 227         /** The status for the platform locale */
 
 228         private IStatus fLocaleStatus = new StatusInfo();
 
 230         /** The status for the proposal threshold */
 
 231         private IStatus fThresholdStatus = new StatusInfo();
 
 234          * Creates a new spelling configuration block.
 
 237          *            The status change listener
 
 241         public SpellingConfigurationBlock(final IStatusChangeListener context,
 
 242                         final IJavaProject project) {
 
 243                 super(context, project, getAllKeys());
 
 245                 IStatus status = validateAbsoluteFilePath((String) fWorkingValues
 
 246                                 .get(PREF_SPELLING_USER_DICTIONARY));
 
 247                 if (status.getSeverity() != IStatus.OK)
 
 248                         fWorkingValues.put(PREF_SPELLING_USER_DICTIONARY, ""); //$NON-NLS-1$
 
 250                 status = validateLocale((String) fWorkingValues
 
 251                                 .get(PREF_SPELLING_LOCALE));
 
 252                 if (status.getSeverity() != IStatus.OK)
 
 253                         fWorkingValues.put(PREF_SPELLING_LOCALE, SpellCheckEngine
 
 254                                         .getDefaultLocale().toString());
 
 257         protected Combo addComboBox(Composite parent, String label, String key,
 
 258                         String[] values, String[] valueLabels, int indent) {
 
 259                 ControlData data = new ControlData(key, values);
 
 261                 GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
 
 262                 gd.horizontalIndent = indent;
 
 264                 Label labelControl = new Label(parent, SWT.LEFT | SWT.WRAP);
 
 265                 labelControl.setText(label);
 
 266                 labelControl.setLayoutData(gd);
 
 268                 Combo comboBox = new Combo(parent, SWT.READ_ONLY);
 
 269                 comboBox.setItems(valueLabels);
 
 270                 comboBox.setData(data);
 
 271                 gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
 
 272                 gd.horizontalSpan = 2;
 
 273                 comboBox.setLayoutData(gd);
 
 274                 comboBox.addSelectionListener(getSelectionListener());
 
 276                 fLabels.put(comboBox, labelControl);
 
 278                 String currValue = (String) fWorkingValues.get(key);
 
 279                 comboBox.select(data.getSelection(currValue));
 
 281                 fComboBoxes.add(comboBox);
 
 286          * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
 
 288         protected Control createContents(final Composite parent) {
 
 290                 Composite composite = new Composite(parent, SWT.NONE);
 
 291                 GridLayout layout = new GridLayout();
 
 292                 layout.numColumns = 1;
 
 293                 composite.setLayout(layout);
 
 295                 final PixelConverter converter = new PixelConverter(parent);
 
 297                 layout = new GridLayout();
 
 298                 layout.numColumns = 3;
 
 300                 final String[] trueFalse = new String[] { IPreferenceStore.TRUE,
 
 301                                 IPreferenceStore.FALSE };
 
 303                 Group user = new Group(composite, SWT.NONE);
 
 304                 user.setText(PreferencesMessages
 
 305                                 .getString("SpellingPreferencePage.preferences.user")); //$NON-NLS-1$
 
 306                 user.setLayout(new GridLayout());
 
 307                 user.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
 309                 String label = PreferencesMessages
 
 310                                 .getString("SpellingPreferencePage.enable.label"); //$NON-NLS-1$
 
 311                 final Button master = addCheckBox(user, label,
 
 312                                 PREF_SPELLING_CHECK_SPELLING, trueFalse, 0);
 
 314                 label = PreferencesMessages
 
 315                                 .getString("SpellingPreferencePage.ignore.digits.label"); //$NON-NLS-1$
 
 316                 Control slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_DIGITS,
 
 318                 createSelectionDependency(master, slave);
 
 320                 label = PreferencesMessages
 
 321                                 .getString("SpellingPreferencePage.ignore.mixed.label"); //$NON-NLS-1$
 
 322                 slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_MIXED, trueFalse,
 
 324                 createSelectionDependency(master, slave);
 
 326                 label = PreferencesMessages
 
 327                                 .getString("SpellingPreferencePage.ignore.sentence.label"); //$NON-NLS-1$
 
 328                 slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_SENTENCE,
 
 330                 createSelectionDependency(master, slave);
 
 332                 label = PreferencesMessages
 
 333                                 .getString("SpellingPreferencePage.ignore.upper.label"); //$NON-NLS-1$
 
 334                 slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_UPPER, trueFalse,
 
 336                 createSelectionDependency(master, slave);
 
 338                 label = PreferencesMessages
 
 339                                 .getString("SpellingPreferencePage.ignore.url.label"); //$NON-NLS-1$
 
 340                 slave = addCheckBox(user, label, PREF_SPELLING_IGNORE_URLS, trueFalse,
 
 342                 createSelectionDependency(master, slave);
 
 344                 final Group engine = new Group(composite, SWT.NONE);
 
 345                 engine.setText(PreferencesMessages
 
 346                                 .getString("SpellingPreferencePage.preferences.engine")); //$NON-NLS-1$
 
 347                 layout = new GridLayout();
 
 348                 layout.numColumns = 4;
 
 349                 engine.setLayout(layout);
 
 350                 engine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
 352                 label = PreferencesMessages
 
 353                                 .getString("SpellingPreferencePage.dictionary.label"); //$NON-NLS-1$
 
 354                 final Set locales = SpellCheckEngine.getAvailableLocales();
 
 356                 Combo combo = addComboBox(engine, label, PREF_SPELLING_LOCALE,
 
 357                                 getDictionaryCodes(locales), getDictionaryLabels(locales), 0);
 
 358                 combo.setEnabled(locales.size() > 1);
 
 360                 new Label(engine, SWT.NONE); // placeholder
 
 362                 label = PreferencesMessages
 
 363                                 .getString("SpellingPreferencePage.workspace.dictionary.label"); //$NON-NLS-1$
 
 364                 fDictionaryPath = addTextField(engine, label,
 
 365                                 PREF_SPELLING_USER_DICTIONARY, 0, 0);
 
 367                 Button button = new Button(engine, SWT.PUSH);
 
 368                 button.setText(PreferencesMessages
 
 369                                 .getString("SpellingPreferencePage.browse.label")); //$NON-NLS-1$
 
 370                 button.addSelectionListener(new SelectionAdapter() {
 
 372                         public void widgetSelected(final SelectionEvent event) {
 
 373                                 handleBrowseButtonSelected();
 
 376                 button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
 
 377                 SWTUtil.setButtonDimensionHint(button);
 
 379                 layout = new GridLayout();
 
 380                 layout.numColumns = 3;
 
 382                 Group advanced = new Group(composite, SWT.NONE);
 
 383                 advanced.setText(PreferencesMessages
 
 384                                 .getString("SpellingPreferencePage.preferences.advanced")); //$NON-NLS-1$
 
 385                 layout = new GridLayout();
 
 386                 layout.numColumns = 3;
 
 387                 advanced.setLayout(layout);
 
 388                 advanced.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
 390                 label = PreferencesMessages
 
 391                                 .getString("SpellingPreferencePage.proposals.threshold"); //$NON-NLS-1$
 
 392                 Text text = addTextField(advanced, label,
 
 393                                 PREF_SPELLING_PROPOSAL_THRESHOLD, 0, 0);
 
 394                 text.setTextLimit(3);
 
 395                 GridData data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
 
 396                 data.widthHint = converter.convertWidthInCharsToPixels(4);
 
 397                 text.setLayoutData(data);
 
 399                 label = PreferencesMessages
 
 400                                 .getString("SpellingPreferencePage.enable.contentassist.label"); //$NON-NLS-1$
 
 401                 addCheckBox(advanced, label, PREF_SPELLING_ENABLE_CONTENTASSIST,
 
 407         private static String[] getAllKeys() {
 
 408                 return new String[] { PREF_SPELLING_USER_DICTIONARY,
 
 409                                 PREF_SPELLING_CHECK_SPELLING, PREF_SPELLING_IGNORE_DIGITS,
 
 410                                 PREF_SPELLING_IGNORE_MIXED, PREF_SPELLING_IGNORE_SENTENCE,
 
 411                                 PREF_SPELLING_IGNORE_UPPER, PREF_SPELLING_IGNORE_URLS,
 
 412                                 PREF_SPELLING_LOCALE, PREF_SPELLING_PROPOSAL_THRESHOLD,
 
 413                                 PREF_SPELLING_ENABLE_CONTENTASSIST };
 
 417          * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getDefaultOptions()
 
 419         protected Map getDefaultOptions() {
 
 421                 final String[] keys = fAllKeys;
 
 422                 final Map options = new HashMap();
 
 423                 final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
 
 425                 for (int index = 0; index < keys.length; index++)
 
 426                         options.put(keys[index], store.getDefaultString(keys[index]));
 
 432          * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
 
 434         protected final String[] getFullBuildDialogStrings(final boolean workspace) {
 
 439          * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#getOptions(boolean)
 
 441         protected Map getOptions(final boolean inherit) {
 
 443                 final String[] keys = fAllKeys;
 
 444                 final Map options = new HashMap();
 
 445                 final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
 
 447                 for (int index = 0; index < keys.length; index++)
 
 448                         options.put(keys[index], store.getString(keys[index]));
 
 454          * Handles selections of the browse button.
 
 456         protected void handleBrowseButtonSelected() {
 
 458                 final FileDialog dialog = new FileDialog(fDictionaryPath.getShell(),
 
 460                 dialog.setText(PreferencesMessages
 
 461                                 .getString("SpellingPreferencePage.filedialog.title")); //$NON-NLS-1$
 
 463                                 .setFilterExtensions(new String[] {
 
 465                                                                 .getString("SpellingPreferencePage.filter.dictionary.extension"), PreferencesMessages.getString("SpellingPreferencePage.filter.all.extension") }); //$NON-NLS-1$ //$NON-NLS-2$
 
 467                                 .setFilterNames(new String[] {
 
 469                                                                 .getString("SpellingPreferencePage.filter.dictionary.label"), PreferencesMessages.getString("SpellingPreferencePage.filter.all.label") }); //$NON-NLS-1$ //$NON-NLS-2$
 
 471                 final String path = dialog.open();
 
 473                         fDictionaryPath.setText(path);
 
 477          * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#setOptions(java.util.Map)
 
 479         protected void setOptions(final Map options) {
 
 481                 final String[] keys = fAllKeys;
 
 482                 final IPreferenceStore store = PreferenceConstants.getPreferenceStore();
 
 484                 for (int index = 0; index < keys.length; index++)
 
 485                         store.setValue(keys[index], (String) fWorkingValues
 
 490          * @see net.sourceforge.phpdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(java.lang.String,java.lang.String)
 
 492         protected void validateSettings(final String key, final String value) {
 
 494                 if (key == null || PREF_SPELLING_PROPOSAL_THRESHOLD.equals(key))
 
 495                         fThresholdStatus = validatePositiveNumber((String) fWorkingValues
 
 496                                         .get(PREF_SPELLING_PROPOSAL_THRESHOLD));
 
 498                 if (key == null || PREF_SPELLING_USER_DICTIONARY.equals(key))
 
 499                         fFileStatus = validateAbsoluteFilePath((String) fWorkingValues
 
 500                                         .get(PREF_SPELLING_USER_DICTIONARY));
 
 502                 if (key == null || PREF_SPELLING_LOCALE.equals(key))
 
 503                         fLocaleStatus = validateLocale((String) fWorkingValues
 
 504                                         .get(PREF_SPELLING_LOCALE));
 
 506                 fContext.statusChanged(StatusUtil.getMostSevere(new IStatus[] {
 
 507                                 fThresholdStatus, fFileStatus, fLocaleStatus }));