54225119b3050855067decc6ea81ef247152c2f8
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / internal / ui / preferences / JavaEditorHoverConfigurationBlock.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.internal.ui.preferences;
13
14 import java.util.HashMap;
15 import java.util.StringTokenizer;
16
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;
24
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 //incastrix
30 //import org.eclipse.jface.text.Assert;
31 import org.eclipse.core.runtime.Assert;
32 import org.eclipse.swt.SWT;
33 import org.eclipse.swt.events.KeyEvent;
34 import org.eclipse.swt.events.KeyListener;
35 import org.eclipse.swt.events.ModifyEvent;
36 import org.eclipse.swt.events.ModifyListener;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.SelectionListener;
39 import org.eclipse.swt.graphics.Point;
40 import org.eclipse.swt.layout.GridData;
41 import org.eclipse.swt.layout.GridLayout;
42 import org.eclipse.swt.widgets.Button;
43 import org.eclipse.swt.widgets.Composite;
44 import org.eclipse.swt.widgets.Control;
45 import org.eclipse.swt.widgets.Label;
46 import org.eclipse.swt.widgets.List;
47 import org.eclipse.swt.widgets.Text;
48
49 /**
50  * Configures Java Editor hover preferences.
51  * 
52  * @since 2.1
53  */
54 class JavaEditorHoverConfigurationBlock {
55
56         private static final String DELIMITER = PreferencesMessages
57                         .getString("JavaEditorHoverConfigurationBlock.delimiter"); //$NON-NLS-1$
58
59         // Data structure to hold the values which are edited by the user
60         private static class HoverConfig {
61
62                 private String fModifierString;
63
64                 private boolean fIsEnabled;
65
66                 private int fStateMask;
67
68                 private HoverConfig(String modifier, int stateMask, boolean enabled) {
69                         fModifierString = modifier;
70                         fIsEnabled = enabled;
71                         fStateMask = stateMask;
72                 }
73         }
74
75         private IPreferenceStore fStore;
76
77         private HoverConfig[] fHoverConfigs;
78
79         private Text fModifierEditor;
80
81         private Button fEnableField;
82
83         private List fHoverList;
84
85         private Text fDescription;
86
87         private Button fShowHoverAffordanceCheckbox;
88
89         private JavaEditorPreferencePage fMainPreferencePage;
90
91         private StatusInfo fStatus;
92
93         public JavaEditorHoverConfigurationBlock(
94                         JavaEditorPreferencePage mainPreferencePage, IPreferenceStore store) {
95                 Assert.isNotNull(mainPreferencePage);
96                 Assert.isNotNull(store);
97                 fMainPreferencePage = mainPreferencePage;
98                 fStore = store;
99         }
100
101         /**
102          * Creates page for hover preferences.
103          */
104         public Control createControl(Composite parent) {
105
106                 PixelConverter pixelConverter = new PixelConverter(parent);
107
108                 Composite hoverComposite = new Composite(parent, SWT.NULL);
109                 GridLayout layout = new GridLayout();
110                 layout.numColumns = 2;
111                 hoverComposite.setLayout(layout);
112                 GridData gd = new GridData(GridData.GRAB_HORIZONTAL
113                                 | GridData.VERTICAL_ALIGN_FILL);
114                 hoverComposite.setLayoutData(gd);
115
116                 Label label = new Label(hoverComposite, SWT.NONE);
117                 label
118                                 .setText(PreferencesMessages
119                                                 .getString("JavaEditorHoverConfigurationBlock.hoverPreferences")); //$NON-NLS-1$
120                 gd = new GridData(GridData.FILL_HORIZONTAL);
121                 gd.horizontalAlignment = GridData.BEGINNING;
122                 gd.horizontalSpan = 2;
123                 label.setLayoutData(gd);
124                 gd = new GridData(GridData.GRAB_HORIZONTAL
125                                 | GridData.VERTICAL_ALIGN_FILL);
126
127                 // Hover list
128                 fHoverList = new List(hoverComposite, SWT.SINGLE | SWT.V_SCROLL
129                                 | SWT.BORDER);
130                 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
131                                 | GridData.FILL_HORIZONTAL);
132                 int listHeight = 10 * fHoverList.getItemHeight();
133                 gd.heightHint = listHeight;
134                 fHoverList.setLayoutData(gd);
135                 fHoverList.addSelectionListener(new SelectionListener() {
136                         public void widgetSelected(SelectionEvent e) {
137                                 handleHoverListSelection();
138                         }
139
140                         public void widgetDefaultSelected(SelectionEvent e) {
141                         }
142                 });
143
144                 Composite stylesComposite = new Composite(hoverComposite, SWT.NONE);
145                 layout = new GridLayout();
146                 layout.marginHeight = 0;
147                 layout.marginWidth = 0;
148                 layout.numColumns = 2;
149                 stylesComposite.setLayout(layout);
150                 gd = new GridData(GridData.FILL_HORIZONTAL);
151                 gd.heightHint = listHeight + (2 * fHoverList.getBorderWidth());
152                 stylesComposite.setLayoutData(gd);
153
154                 // Enabled checkbox
155                 fEnableField = new Button(stylesComposite, SWT.CHECK);
156                 fEnableField.setText(PreferencesMessages
157                                 .getString("JavaEditorHoverConfigurationBlock.enabled")); //$NON-NLS-1$
158                 gd = new GridData(GridData.FILL_HORIZONTAL);
159                 gd.horizontalAlignment = GridData.BEGINNING;
160                 gd.horizontalSpan = 2;
161                 fEnableField.setLayoutData(gd);
162                 fEnableField.addSelectionListener(new SelectionListener() {
163                         public void widgetSelected(SelectionEvent e) {
164                                 int i = fHoverList.getSelectionIndex();
165                                 boolean state = fEnableField.getSelection();
166                                 fModifierEditor.setEnabled(state);
167                                 fHoverConfigs[i].fIsEnabled = state;
168                                 handleModifierModified();
169                         }
170
171                         public void widgetDefaultSelected(SelectionEvent e) {
172                         }
173                 });
174
175                 // Text field for modifier string
176                 label = new Label(stylesComposite, SWT.LEFT);
177                 label.setText(PreferencesMessages
178                                 .getString("JavaEditorHoverConfigurationBlock.keyModifier")); //$NON-NLS-1$
179                 fModifierEditor = new Text(stylesComposite, SWT.BORDER);
180                 gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
181                 fModifierEditor.setLayoutData(gd);
182
183                 fModifierEditor.addKeyListener(new KeyListener() {
184                         private boolean isModifierCandidate;
185
186                         public void keyPressed(KeyEvent e) {
187                                 isModifierCandidate = e.keyCode > 0 && e.character == 0
188                                                 && e.stateMask == 0;
189                         }
190
191                         public void keyReleased(KeyEvent e) {
192                                 if (isModifierCandidate && e.stateMask > 0
193                                                 && e.stateMask == e.stateMask && e.character == 0) {// &&
194                                                                                                                                                         // e.time
195                                                                                                                                                         // -time
196                                                                                                                                                         // <
197                                                                                                                                                         // 1000)
198                                                                                                                                                         // {
199                                         String text = fModifierEditor.getText();
200                                         Point selection = fModifierEditor.getSelection();
201                                         int i = selection.x - 1;
202                                         while (i > -1 && Character.isWhitespace(text.charAt(i))) {
203                                                 i--;
204                                         }
205                                         boolean needsPrefixDelimiter = i > -1
206                                                         && !String.valueOf(text.charAt(i))
207                                                                         .equals(DELIMITER);
208
209                                         i = selection.y;
210                                         while (i < text.length()
211                                                         && Character.isWhitespace(text.charAt(i))) {
212                                                 i++;
213                                         }
214                                         boolean needsPostfixDelimiter = i < text.length()
215                                                         && !String.valueOf(text.charAt(i))
216                                                                         .equals(DELIMITER);
217
218                                         String insertString;
219
220                                         if (needsPrefixDelimiter && needsPostfixDelimiter)
221                                                 insertString = PreferencesMessages
222                                                                 .getFormattedString(
223                                                                                 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
224                                         else if (needsPrefixDelimiter)
225                                                 insertString = PreferencesMessages
226                                                                 .getFormattedString(
227                                                                                 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifier", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
228                                         else if (needsPostfixDelimiter)
229                                                 insertString = PreferencesMessages
230                                                                 .getFormattedString(
231                                                                                 "JavaEditorHoverConfigurationBlock.insertModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
232                                         else
233                                                 insertString = Action.findModifierString(e.stateMask);
234
235                                         if (insertString != null)
236                                                 fModifierEditor.insert(insertString);
237                                 }
238                         }
239                 });
240
241                 fModifierEditor.addModifyListener(new ModifyListener() {
242                         public void modifyText(ModifyEvent e) {
243                                 handleModifierModified();
244                         }
245                 });
246
247                 // Description
248                 Label descriptionLabel = new Label(stylesComposite, SWT.LEFT);
249                 descriptionLabel.setText(PreferencesMessages
250                                 .getString("JavaEditorHoverConfigurationBlock.description")); //$NON-NLS-1$
251                 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
252                 gd.horizontalSpan = 2;
253                 descriptionLabel.setLayoutData(gd);
254                 fDescription = new Text(stylesComposite, SWT.LEFT | SWT.WRAP
255                                 | SWT.MULTI | SWT.READ_ONLY | SWT.BORDER);
256                 gd = new GridData(GridData.FILL_BOTH);
257                 gd.horizontalSpan = 2;
258                 fDescription.setLayoutData(gd);
259
260                 // Vertical filler
261                 Label filler = new Label(hoverComposite, SWT.LEFT);
262                 gd = new GridData(GridData.BEGINNING | GridData.VERTICAL_ALIGN_FILL);
263                 gd.heightHint = pixelConverter.convertHeightInCharsToPixels(1) / 3;
264                 filler.setLayoutData(gd);
265
266                 // Affordance checkbox
267                 fShowHoverAffordanceCheckbox = new Button(hoverComposite, SWT.CHECK);
268                 fShowHoverAffordanceCheckbox.setText(PreferencesMessages
269                                 .getString("JavaEditorHoverConfigurationBlock.showAffordance")); //$NON-NLS-1$
270                 gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
271                 gd.horizontalIndent = 0;
272                 gd.horizontalSpan = 2;
273                 fShowHoverAffordanceCheckbox.setLayoutData(gd);
274
275                 initialize();
276
277                 Dialog.applyDialogFont(hoverComposite);
278                 return hoverComposite;
279         }
280
281         private JavaEditorTextHoverDescriptor[] getContributedHovers() {
282                 return WebUI.getDefault()
283                                 .getJavaEditorTextHoverDescriptors();
284         }
285
286         void initialize() {
287                 JavaEditorTextHoverDescriptor[] hoverDescs = getContributedHovers();
288                 fHoverConfigs = new HoverConfig[hoverDescs.length];
289                 for (int i = 0; i < hoverDescs.length; i++) {
290                         fHoverConfigs[i] = new HoverConfig(hoverDescs[i]
291                                         .getModifierString(), hoverDescs[i].getStateMask(),
292                                         hoverDescs[i].isEnabled());
293                         fHoverList.add(hoverDescs[i].getLabel());
294                 }
295                 initializeFields();
296         }
297
298         void initializeFields() {
299                 fHoverList.getDisplay().asyncExec(new Runnable() {
300                         public void run() {
301                                 if (fHoverList != null && !fHoverList.isDisposed()) {
302                                         fHoverList.select(0);
303                                         handleHoverListSelection();
304                                 }
305                         }
306                 });
307                 fShowHoverAffordanceCheckbox
308                                 .setSelection(fStore
309                                                 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
310         }
311
312         void performOk() {
313                 StringBuffer buf = new StringBuffer();
314                 StringBuffer maskBuf = new StringBuffer();
315                 for (int i = 0; i < fHoverConfigs.length; i++) {
316                         buf.append(getContributedHovers()[i].getId());
317                         buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
318                         if (!fHoverConfigs[i].fIsEnabled)
319                                 buf.append(JavaEditorTextHoverDescriptor.DISABLED_TAG);
320                         String modifier = fHoverConfigs[i].fModifierString;
321                         if (modifier == null || modifier.length() == 0)
322                                 modifier = JavaEditorTextHoverDescriptor.NO_MODIFIER;
323                         buf.append(modifier);
324                         buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
325
326                         maskBuf.append(getContributedHovers()[i].getId());
327                         maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
328                         maskBuf.append(fHoverConfigs[i].fStateMask);
329                         maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
330                 }
331                 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS, buf
332                                 .toString());
333                 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS,
334                                 maskBuf.toString());
335
336                 fStore.setValue(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE,
337                                 fShowHoverAffordanceCheckbox.getSelection());
338
339                 WebUI.getDefault().resetJavaEditorTextHoverDescriptors();
340         }
341
342         void performDefaults() {
343                 restoreFromPreferences();
344                 initializeFields();
345         }
346
347         private void restoreFromPreferences() {
348
349                 fShowHoverAffordanceCheckbox
350                                 .setSelection(fStore
351                                                 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
352
353                 String compiledTextHoverModifiers = fStore
354                                 .getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
355
356                 StringTokenizer tokenizer = new StringTokenizer(
357                                 compiledTextHoverModifiers,
358                                 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
359                 HashMap idToModifier = new HashMap(tokenizer.countTokens() / 2);
360
361                 while (tokenizer.hasMoreTokens()) {
362                         String id = tokenizer.nextToken();
363                         if (tokenizer.hasMoreTokens())
364                                 idToModifier.put(id, tokenizer.nextToken());
365                 }
366
367                 String compiledTextHoverModifierMasks = WebUI.getDefault()
368                                 .getPreferenceStore().getString(
369                                                 PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
370
371                 tokenizer = new StringTokenizer(compiledTextHoverModifierMasks,
372                                 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
373                 HashMap idToModifierMask = new HashMap(tokenizer.countTokens() / 2);
374
375                 while (tokenizer.hasMoreTokens()) {
376                         String id = tokenizer.nextToken();
377                         if (tokenizer.hasMoreTokens())
378                                 idToModifierMask.put(id, tokenizer.nextToken());
379                 }
380
381                 for (int i = 0; i < fHoverConfigs.length; i++) {
382                         String modifierString = (String) idToModifier
383                                         .get(getContributedHovers()[i].getId());
384                         boolean enabled = true;
385                         if (modifierString == null)
386                                 modifierString = JavaEditorTextHoverDescriptor.DISABLED_TAG;
387
388                         if (modifierString
389                                         .startsWith(JavaEditorTextHoverDescriptor.DISABLED_TAG)) {
390                                 enabled = false;
391                                 modifierString = modifierString.substring(1);
392                         }
393
394                         if (modifierString
395                                         .equals(JavaEditorTextHoverDescriptor.NO_MODIFIER))
396                                 modifierString = ""; //$NON-NLS-1$
397
398                         fHoverConfigs[i].fModifierString = modifierString;
399                         fHoverConfigs[i].fIsEnabled = enabled;
400                         fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
401                                         .computeStateMask(modifierString);
402
403                         if (fHoverConfigs[i].fStateMask == -1) {
404                                 try {
405                                         fHoverConfigs[i].fStateMask = Integer
406                                                         .parseInt((String) idToModifierMask
407                                                                         .get(getContributedHovers()[i].getId()));
408                                 } catch (NumberFormatException ex) {
409                                         fHoverConfigs[i].fStateMask = -1;
410                                 }
411                         }
412                 }
413         }
414
415         private void handleModifierModified() {
416                 int i = fHoverList.getSelectionIndex();
417                 String modifiers = fModifierEditor.getText();
418                 fHoverConfigs[i].fModifierString = modifiers;
419                 fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
420                                 .computeStateMask(modifiers);
421                 if (fHoverConfigs[i].fIsEnabled && fHoverConfigs[i].fStateMask == -1)
422                         fStatus = new StatusInfo(
423                                         IStatus.ERROR,
424                                         PreferencesMessages
425                                                         .getFormattedString(
426                                                                         "JavaEditorHoverConfigurationBlock.modifierIsNotValid", fHoverConfigs[i].fModifierString)); //$NON-NLS-1$
427                 else
428                         fStatus = new StatusInfo();
429                 updateStatus();
430         }
431
432         private void handleHoverListSelection() {
433                 int i = fHoverList.getSelectionIndex();
434                 boolean enabled = fHoverConfigs[i].fIsEnabled;
435                 fEnableField.setSelection(enabled);
436                 fModifierEditor.setEnabled(enabled);
437                 fModifierEditor.setText(fHoverConfigs[i].fModifierString);
438                 String description = getContributedHovers()[i].getDescription();
439                 if (description == null)
440                         description = ""; //$NON-NLS-1$
441                 fDescription.setText(description);
442         }
443
444         IStatus getStatus() {
445                 if (fStatus == null)
446                         fStatus = new StatusInfo();
447                 return fStatus;
448         }
449
450         private void updateStatus() {
451                 int i = 0;
452                 HashMap stateMasks = new HashMap(fHoverConfigs.length);
453                 while (fStatus.isOK() && i < fHoverConfigs.length) {
454                         if (fHoverConfigs[i].fIsEnabled) {
455                                 String label = getContributedHovers()[i].getLabel();
456                                 Integer stateMask = new Integer(fHoverConfigs[i].fStateMask);
457                                 if (fHoverConfigs[i].fStateMask == -1)
458                                         fStatus = new StatusInfo(
459                                                         IStatus.ERROR,
460                                                         PreferencesMessages
461                                                                         .getFormattedString(
462                                                                                         "JavaEditorHoverConfigurationBlock.modifierIsNotValidForHover", new String[] { fHoverConfigs[i].fModifierString, label })); //$NON-NLS-1$
463                                 else if (stateMasks.containsKey(stateMask))
464                                         fStatus = new StatusInfo(
465                                                         IStatus.ERROR,
466                                                         PreferencesMessages
467                                                                         .getFormattedString(
468                                                                                         "JavaEditorHoverConfigurationBlock.duplicateModifier", new String[] { label, (String) stateMasks.get(stateMask) })); //$NON-NLS-1$
469                                 else
470                                         stateMasks.put(stateMask, label);
471                         }
472                         i++;
473                 }
474
475                 if (fStatus.isOK())
476                         fMainPreferencePage.updateStatus(fStatus);
477                 else {
478                         fMainPreferencePage.setValid(false);
479                         StatusUtil.applyToStatusLine(fMainPreferencePage, fStatus);
480                 }
481         }
482 }