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;
 
  14 import java.util.HashMap;
 
  15 import java.util.StringTokenizer;
 
  17 import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
 
  18 import net.sourceforge.phpdt.internal.ui.dialogs.StatusUtil;
 
  19 import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaEditorTextHoverDescriptor;
 
  20 import net.sourceforge.phpdt.internal.ui.util.PixelConverter;
 
  21 import net.sourceforge.phpdt.ui.PreferenceConstants;
 
  22 import net.sourceforge.phpeclipse.ui.WebUI;
 
  23 //import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
  25 import org.eclipse.core.runtime.IStatus;
 
  26 import org.eclipse.jface.action.Action;
 
  27 import org.eclipse.jface.dialogs.Dialog;
 
  28 import org.eclipse.jface.preference.IPreferenceStore;
 
  29 import org.eclipse.jface.text.Assert;
 
  30 import org.eclipse.swt.SWT;
 
  31 import org.eclipse.swt.events.KeyEvent;
 
  32 import org.eclipse.swt.events.KeyListener;
 
  33 import org.eclipse.swt.events.ModifyEvent;
 
  34 import org.eclipse.swt.events.ModifyListener;
 
  35 import org.eclipse.swt.events.SelectionEvent;
 
  36 import org.eclipse.swt.events.SelectionListener;
 
  37 import org.eclipse.swt.graphics.Point;
 
  38 import org.eclipse.swt.layout.GridData;
 
  39 import org.eclipse.swt.layout.GridLayout;
 
  40 import org.eclipse.swt.widgets.Button;
 
  41 import org.eclipse.swt.widgets.Composite;
 
  42 import org.eclipse.swt.widgets.Control;
 
  43 import org.eclipse.swt.widgets.Label;
 
  44 import org.eclipse.swt.widgets.List;
 
  45 import org.eclipse.swt.widgets.Text;
 
  48  * Configures Java Editor hover preferences.
 
  52 class JavaEditorHoverConfigurationBlock {
 
  54         private static final String DELIMITER = PreferencesMessages
 
  55                         .getString("JavaEditorHoverConfigurationBlock.delimiter"); //$NON-NLS-1$
 
  57         // Data structure to hold the values which are edited by the user
 
  58         private static class HoverConfig {
 
  60                 private String fModifierString;
 
  62                 private boolean fIsEnabled;
 
  64                 private int fStateMask;
 
  66                 private HoverConfig(String modifier, int stateMask, boolean enabled) {
 
  67                         fModifierString = modifier;
 
  69                         fStateMask = stateMask;
 
  73         private IPreferenceStore fStore;
 
  75         private HoverConfig[] fHoverConfigs;
 
  77         private Text fModifierEditor;
 
  79         private Button fEnableField;
 
  81         private List fHoverList;
 
  83         private Text fDescription;
 
  85         private Button fShowHoverAffordanceCheckbox;
 
  87         private JavaEditorPreferencePage fMainPreferencePage;
 
  89         private StatusInfo fStatus;
 
  91         public JavaEditorHoverConfigurationBlock(
 
  92                         JavaEditorPreferencePage mainPreferencePage, IPreferenceStore store) {
 
  93                 Assert.isNotNull(mainPreferencePage);
 
  94                 Assert.isNotNull(store);
 
  95                 fMainPreferencePage = mainPreferencePage;
 
 100          * Creates page for hover preferences.
 
 102         public Control createControl(Composite parent) {
 
 104                 PixelConverter pixelConverter = new PixelConverter(parent);
 
 106                 Composite hoverComposite = new Composite(parent, SWT.NULL);
 
 107                 GridLayout layout = new GridLayout();
 
 108                 layout.numColumns = 2;
 
 109                 hoverComposite.setLayout(layout);
 
 110                 GridData gd = new GridData(GridData.GRAB_HORIZONTAL
 
 111                                 | GridData.VERTICAL_ALIGN_FILL);
 
 112                 hoverComposite.setLayoutData(gd);
 
 114                 Label label = new Label(hoverComposite, SWT.NONE);
 
 116                                 .setText(PreferencesMessages
 
 117                                                 .getString("JavaEditorHoverConfigurationBlock.hoverPreferences")); //$NON-NLS-1$
 
 118                 gd = new GridData(GridData.FILL_HORIZONTAL);
 
 119                 gd.horizontalAlignment = GridData.BEGINNING;
 
 120                 gd.horizontalSpan = 2;
 
 121                 label.setLayoutData(gd);
 
 122                 gd = new GridData(GridData.GRAB_HORIZONTAL
 
 123                                 | GridData.VERTICAL_ALIGN_FILL);
 
 126                 fHoverList = new List(hoverComposite, SWT.SINGLE | SWT.V_SCROLL
 
 128                 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
 
 129                                 | GridData.FILL_HORIZONTAL);
 
 130                 int listHeight = 10 * fHoverList.getItemHeight();
 
 131                 gd.heightHint = listHeight;
 
 132                 fHoverList.setLayoutData(gd);
 
 133                 fHoverList.addSelectionListener(new SelectionListener() {
 
 134                         public void widgetSelected(SelectionEvent e) {
 
 135                                 handleHoverListSelection();
 
 138                         public void widgetDefaultSelected(SelectionEvent e) {
 
 142                 Composite stylesComposite = new Composite(hoverComposite, SWT.NONE);
 
 143                 layout = new GridLayout();
 
 144                 layout.marginHeight = 0;
 
 145                 layout.marginWidth = 0;
 
 146                 layout.numColumns = 2;
 
 147                 stylesComposite.setLayout(layout);
 
 148                 gd = new GridData(GridData.FILL_HORIZONTAL);
 
 149                 gd.heightHint = listHeight + (2 * fHoverList.getBorderWidth());
 
 150                 stylesComposite.setLayoutData(gd);
 
 153                 fEnableField = new Button(stylesComposite, SWT.CHECK);
 
 154                 fEnableField.setText(PreferencesMessages
 
 155                                 .getString("JavaEditorHoverConfigurationBlock.enabled")); //$NON-NLS-1$
 
 156                 gd = new GridData(GridData.FILL_HORIZONTAL);
 
 157                 gd.horizontalAlignment = GridData.BEGINNING;
 
 158                 gd.horizontalSpan = 2;
 
 159                 fEnableField.setLayoutData(gd);
 
 160                 fEnableField.addSelectionListener(new SelectionListener() {
 
 161                         public void widgetSelected(SelectionEvent e) {
 
 162                                 int i = fHoverList.getSelectionIndex();
 
 163                                 boolean state = fEnableField.getSelection();
 
 164                                 fModifierEditor.setEnabled(state);
 
 165                                 fHoverConfigs[i].fIsEnabled = state;
 
 166                                 handleModifierModified();
 
 169                         public void widgetDefaultSelected(SelectionEvent e) {
 
 173                 // Text field for modifier string
 
 174                 label = new Label(stylesComposite, SWT.LEFT);
 
 175                 label.setText(PreferencesMessages
 
 176                                 .getString("JavaEditorHoverConfigurationBlock.keyModifier")); //$NON-NLS-1$
 
 177                 fModifierEditor = new Text(stylesComposite, SWT.BORDER);
 
 178                 gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
 
 179                 fModifierEditor.setLayoutData(gd);
 
 181                 fModifierEditor.addKeyListener(new KeyListener() {
 
 182                         private boolean isModifierCandidate;
 
 184                         public void keyPressed(KeyEvent e) {
 
 185                                 isModifierCandidate = e.keyCode > 0 && e.character == 0
 
 189                         public void keyReleased(KeyEvent e) {
 
 190                                 if (isModifierCandidate && e.stateMask > 0
 
 191                                                 && e.stateMask == e.stateMask && e.character == 0) {// &&
 
 197                                         String text = fModifierEditor.getText();
 
 198                                         Point selection = fModifierEditor.getSelection();
 
 199                                         int i = selection.x - 1;
 
 200                                         while (i > -1 && Character.isWhitespace(text.charAt(i))) {
 
 203                                         boolean needsPrefixDelimiter = i > -1
 
 204                                                         && !String.valueOf(text.charAt(i))
 
 208                                         while (i < text.length()
 
 209                                                         && Character.isWhitespace(text.charAt(i))) {
 
 212                                         boolean needsPostfixDelimiter = i < text.length()
 
 213                                                         && !String.valueOf(text.charAt(i))
 
 218                                         if (needsPrefixDelimiter && needsPostfixDelimiter)
 
 219                                                 insertString = PreferencesMessages
 
 221                                                                                 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
 
 222                                         else if (needsPrefixDelimiter)
 
 223                                                 insertString = PreferencesMessages
 
 225                                                                                 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifier", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
 
 226                                         else if (needsPostfixDelimiter)
 
 227                                                 insertString = PreferencesMessages
 
 229                                                                                 "JavaEditorHoverConfigurationBlock.insertModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
 
 231                                                 insertString = Action.findModifierString(e.stateMask);
 
 233                                         if (insertString != null)
 
 234                                                 fModifierEditor.insert(insertString);
 
 239                 fModifierEditor.addModifyListener(new ModifyListener() {
 
 240                         public void modifyText(ModifyEvent e) {
 
 241                                 handleModifierModified();
 
 246                 Label descriptionLabel = new Label(stylesComposite, SWT.LEFT);
 
 247                 descriptionLabel.setText(PreferencesMessages
 
 248                                 .getString("JavaEditorHoverConfigurationBlock.description")); //$NON-NLS-1$
 
 249                 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
 
 250                 gd.horizontalSpan = 2;
 
 251                 descriptionLabel.setLayoutData(gd);
 
 252                 fDescription = new Text(stylesComposite, SWT.LEFT | SWT.WRAP
 
 253                                 | SWT.MULTI | SWT.READ_ONLY | SWT.BORDER);
 
 254                 gd = new GridData(GridData.FILL_BOTH);
 
 255                 gd.horizontalSpan = 2;
 
 256                 fDescription.setLayoutData(gd);
 
 259                 Label filler = new Label(hoverComposite, SWT.LEFT);
 
 260                 gd = new GridData(GridData.BEGINNING | GridData.VERTICAL_ALIGN_FILL);
 
 261                 gd.heightHint = pixelConverter.convertHeightInCharsToPixels(1) / 3;
 
 262                 filler.setLayoutData(gd);
 
 264                 // Affordance checkbox
 
 265                 fShowHoverAffordanceCheckbox = new Button(hoverComposite, SWT.CHECK);
 
 266                 fShowHoverAffordanceCheckbox.setText(PreferencesMessages
 
 267                                 .getString("JavaEditorHoverConfigurationBlock.showAffordance")); //$NON-NLS-1$
 
 268                 gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
 
 269                 gd.horizontalIndent = 0;
 
 270                 gd.horizontalSpan = 2;
 
 271                 fShowHoverAffordanceCheckbox.setLayoutData(gd);
 
 275                 Dialog.applyDialogFont(hoverComposite);
 
 276                 return hoverComposite;
 
 279         private JavaEditorTextHoverDescriptor[] getContributedHovers() {
 
 280                 return WebUI.getDefault()
 
 281                                 .getJavaEditorTextHoverDescriptors();
 
 285                 JavaEditorTextHoverDescriptor[] hoverDescs = getContributedHovers();
 
 286                 fHoverConfigs = new HoverConfig[hoverDescs.length];
 
 287                 for (int i = 0; i < hoverDescs.length; i++) {
 
 288                         fHoverConfigs[i] = new HoverConfig(hoverDescs[i]
 
 289                                         .getModifierString(), hoverDescs[i].getStateMask(),
 
 290                                         hoverDescs[i].isEnabled());
 
 291                         fHoverList.add(hoverDescs[i].getLabel());
 
 296         void initializeFields() {
 
 297                 fHoverList.getDisplay().asyncExec(new Runnable() {
 
 299                                 if (fHoverList != null && !fHoverList.isDisposed()) {
 
 300                                         fHoverList.select(0);
 
 301                                         handleHoverListSelection();
 
 305                 fShowHoverAffordanceCheckbox
 
 307                                                 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
 
 311                 StringBuffer buf = new StringBuffer();
 
 312                 StringBuffer maskBuf = new StringBuffer();
 
 313                 for (int i = 0; i < fHoverConfigs.length; i++) {
 
 314                         buf.append(getContributedHovers()[i].getId());
 
 315                         buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
 
 316                         if (!fHoverConfigs[i].fIsEnabled)
 
 317                                 buf.append(JavaEditorTextHoverDescriptor.DISABLED_TAG);
 
 318                         String modifier = fHoverConfigs[i].fModifierString;
 
 319                         if (modifier == null || modifier.length() == 0)
 
 320                                 modifier = JavaEditorTextHoverDescriptor.NO_MODIFIER;
 
 321                         buf.append(modifier);
 
 322                         buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
 
 324                         maskBuf.append(getContributedHovers()[i].getId());
 
 325                         maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
 
 326                         maskBuf.append(fHoverConfigs[i].fStateMask);
 
 327                         maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
 
 329                 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS, buf
 
 331                 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS,
 
 334                 fStore.setValue(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE,
 
 335                                 fShowHoverAffordanceCheckbox.getSelection());
 
 337                 WebUI.getDefault().resetJavaEditorTextHoverDescriptors();
 
 340         void performDefaults() {
 
 341                 restoreFromPreferences();
 
 345         private void restoreFromPreferences() {
 
 347                 fShowHoverAffordanceCheckbox
 
 349                                                 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
 
 351                 String compiledTextHoverModifiers = fStore
 
 352                                 .getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
 
 354                 StringTokenizer tokenizer = new StringTokenizer(
 
 355                                 compiledTextHoverModifiers,
 
 356                                 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
 
 357                 HashMap idToModifier = new HashMap(tokenizer.countTokens() / 2);
 
 359                 while (tokenizer.hasMoreTokens()) {
 
 360                         String id = tokenizer.nextToken();
 
 361                         if (tokenizer.hasMoreTokens())
 
 362                                 idToModifier.put(id, tokenizer.nextToken());
 
 365                 String compiledTextHoverModifierMasks = WebUI.getDefault()
 
 366                                 .getPreferenceStore().getString(
 
 367                                                 PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
 
 369                 tokenizer = new StringTokenizer(compiledTextHoverModifierMasks,
 
 370                                 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
 
 371                 HashMap idToModifierMask = new HashMap(tokenizer.countTokens() / 2);
 
 373                 while (tokenizer.hasMoreTokens()) {
 
 374                         String id = tokenizer.nextToken();
 
 375                         if (tokenizer.hasMoreTokens())
 
 376                                 idToModifierMask.put(id, tokenizer.nextToken());
 
 379                 for (int i = 0; i < fHoverConfigs.length; i++) {
 
 380                         String modifierString = (String) idToModifier
 
 381                                         .get(getContributedHovers()[i].getId());
 
 382                         boolean enabled = true;
 
 383                         if (modifierString == null)
 
 384                                 modifierString = JavaEditorTextHoverDescriptor.DISABLED_TAG;
 
 387                                         .startsWith(JavaEditorTextHoverDescriptor.DISABLED_TAG)) {
 
 389                                 modifierString = modifierString.substring(1);
 
 393                                         .equals(JavaEditorTextHoverDescriptor.NO_MODIFIER))
 
 394                                 modifierString = ""; //$NON-NLS-1$
 
 396                         fHoverConfigs[i].fModifierString = modifierString;
 
 397                         fHoverConfigs[i].fIsEnabled = enabled;
 
 398                         fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
 
 399                                         .computeStateMask(modifierString);
 
 401                         if (fHoverConfigs[i].fStateMask == -1) {
 
 403                                         fHoverConfigs[i].fStateMask = Integer
 
 404                                                         .parseInt((String) idToModifierMask
 
 405                                                                         .get(getContributedHovers()[i].getId()));
 
 406                                 } catch (NumberFormatException ex) {
 
 407                                         fHoverConfigs[i].fStateMask = -1;
 
 413         private void handleModifierModified() {
 
 414                 int i = fHoverList.getSelectionIndex();
 
 415                 String modifiers = fModifierEditor.getText();
 
 416                 fHoverConfigs[i].fModifierString = modifiers;
 
 417                 fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
 
 418                                 .computeStateMask(modifiers);
 
 419                 if (fHoverConfigs[i].fIsEnabled && fHoverConfigs[i].fStateMask == -1)
 
 420                         fStatus = new StatusInfo(
 
 424                                                                         "JavaEditorHoverConfigurationBlock.modifierIsNotValid", fHoverConfigs[i].fModifierString)); //$NON-NLS-1$
 
 426                         fStatus = new StatusInfo();
 
 430         private void handleHoverListSelection() {
 
 431                 int i = fHoverList.getSelectionIndex();
 
 432                 boolean enabled = fHoverConfigs[i].fIsEnabled;
 
 433                 fEnableField.setSelection(enabled);
 
 434                 fModifierEditor.setEnabled(enabled);
 
 435                 fModifierEditor.setText(fHoverConfigs[i].fModifierString);
 
 436                 String description = getContributedHovers()[i].getDescription();
 
 437                 if (description == null)
 
 438                         description = ""; //$NON-NLS-1$
 
 439                 fDescription.setText(description);
 
 442         IStatus getStatus() {
 
 444                         fStatus = new StatusInfo();
 
 448         private void updateStatus() {
 
 450                 HashMap stateMasks = new HashMap(fHoverConfigs.length);
 
 451                 while (fStatus.isOK() && i < fHoverConfigs.length) {
 
 452                         if (fHoverConfigs[i].fIsEnabled) {
 
 453                                 String label = getContributedHovers()[i].getLabel();
 
 454                                 Integer stateMask = new Integer(fHoverConfigs[i].fStateMask);
 
 455                                 if (fHoverConfigs[i].fStateMask == -1)
 
 456                                         fStatus = new StatusInfo(
 
 460                                                                                         "JavaEditorHoverConfigurationBlock.modifierIsNotValidForHover", new String[] { fHoverConfigs[i].fModifierString, label })); //$NON-NLS-1$
 
 461                                 else if (stateMasks.containsKey(stateMask))
 
 462                                         fStatus = new StatusInfo(
 
 466                                                                                         "JavaEditorHoverConfigurationBlock.duplicateModifier", new String[] { label, (String) stateMasks.get(stateMask) })); //$NON-NLS-1$
 
 468                                         stateMasks.put(stateMask, label);
 
 474                         fMainPreferencePage.updateStatus(fStatus);
 
 476                         fMainPreferencePage.setValid(false);
 
 477                         StatusUtil.applyToStatusLine(fMainPreferencePage, fStatus);