refactory: added UI removed from core plugin.
[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 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;
46
47 /**
48  * Configures Java Editor hover preferences.
49  * 
50  * @since 2.1
51  */
52 class JavaEditorHoverConfigurationBlock {
53
54         private static final String DELIMITER = PreferencesMessages
55                         .getString("JavaEditorHoverConfigurationBlock.delimiter"); //$NON-NLS-1$
56
57         // Data structure to hold the values which are edited by the user
58         private static class HoverConfig {
59
60                 private String fModifierString;
61
62                 private boolean fIsEnabled;
63
64                 private int fStateMask;
65
66                 private HoverConfig(String modifier, int stateMask, boolean enabled) {
67                         fModifierString = modifier;
68                         fIsEnabled = enabled;
69                         fStateMask = stateMask;
70                 }
71         }
72
73         private IPreferenceStore fStore;
74
75         private HoverConfig[] fHoverConfigs;
76
77         private Text fModifierEditor;
78
79         private Button fEnableField;
80
81         private List fHoverList;
82
83         private Text fDescription;
84
85         private Button fShowHoverAffordanceCheckbox;
86
87         private JavaEditorPreferencePage fMainPreferencePage;
88
89         private StatusInfo fStatus;
90
91         public JavaEditorHoverConfigurationBlock(
92                         JavaEditorPreferencePage mainPreferencePage, IPreferenceStore store) {
93                 Assert.isNotNull(mainPreferencePage);
94                 Assert.isNotNull(store);
95                 fMainPreferencePage = mainPreferencePage;
96                 fStore = store;
97         }
98
99         /**
100          * Creates page for hover preferences.
101          */
102         public Control createControl(Composite parent) {
103
104                 PixelConverter pixelConverter = new PixelConverter(parent);
105
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);
113
114                 Label label = new Label(hoverComposite, SWT.NONE);
115                 label
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);
124
125                 // Hover list
126                 fHoverList = new List(hoverComposite, SWT.SINGLE | SWT.V_SCROLL
127                                 | SWT.BORDER);
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();
136                         }
137
138                         public void widgetDefaultSelected(SelectionEvent e) {
139                         }
140                 });
141
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);
151
152                 // Enabled checkbox
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();
167                         }
168
169                         public void widgetDefaultSelected(SelectionEvent e) {
170                         }
171                 });
172
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);
180
181                 fModifierEditor.addKeyListener(new KeyListener() {
182                         private boolean isModifierCandidate;
183
184                         public void keyPressed(KeyEvent e) {
185                                 isModifierCandidate = e.keyCode > 0 && e.character == 0
186                                                 && e.stateMask == 0;
187                         }
188
189                         public void keyReleased(KeyEvent e) {
190                                 if (isModifierCandidate && e.stateMask > 0
191                                                 && e.stateMask == e.stateMask && e.character == 0) {// &&
192                                                                                                                                                         // e.time
193                                                                                                                                                         // -time
194                                                                                                                                                         // <
195                                                                                                                                                         // 1000)
196                                                                                                                                                         // {
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))) {
201                                                 i--;
202                                         }
203                                         boolean needsPrefixDelimiter = i > -1
204                                                         && !String.valueOf(text.charAt(i))
205                                                                         .equals(DELIMITER);
206
207                                         i = selection.y;
208                                         while (i < text.length()
209                                                         && Character.isWhitespace(text.charAt(i))) {
210                                                 i++;
211                                         }
212                                         boolean needsPostfixDelimiter = i < text.length()
213                                                         && !String.valueOf(text.charAt(i))
214                                                                         .equals(DELIMITER);
215
216                                         String insertString;
217
218                                         if (needsPrefixDelimiter && needsPostfixDelimiter)
219                                                 insertString = PreferencesMessages
220                                                                 .getFormattedString(
221                                                                                 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
222                                         else if (needsPrefixDelimiter)
223                                                 insertString = PreferencesMessages
224                                                                 .getFormattedString(
225                                                                                 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifier", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
226                                         else if (needsPostfixDelimiter)
227                                                 insertString = PreferencesMessages
228                                                                 .getFormattedString(
229                                                                                 "JavaEditorHoverConfigurationBlock.insertModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
230                                         else
231                                                 insertString = Action.findModifierString(e.stateMask);
232
233                                         if (insertString != null)
234                                                 fModifierEditor.insert(insertString);
235                                 }
236                         }
237                 });
238
239                 fModifierEditor.addModifyListener(new ModifyListener() {
240                         public void modifyText(ModifyEvent e) {
241                                 handleModifierModified();
242                         }
243                 });
244
245                 // Description
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);
257
258                 // Vertical filler
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);
263
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);
272
273                 initialize();
274
275                 Dialog.applyDialogFont(hoverComposite);
276                 return hoverComposite;
277         }
278
279         private JavaEditorTextHoverDescriptor[] getContributedHovers() {
280                 return WebUI.getDefault()
281                                 .getJavaEditorTextHoverDescriptors();
282         }
283
284         void initialize() {
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());
292                 }
293                 initializeFields();
294         }
295
296         void initializeFields() {
297                 fHoverList.getDisplay().asyncExec(new Runnable() {
298                         public void run() {
299                                 if (fHoverList != null && !fHoverList.isDisposed()) {
300                                         fHoverList.select(0);
301                                         handleHoverListSelection();
302                                 }
303                         }
304                 });
305                 fShowHoverAffordanceCheckbox
306                                 .setSelection(fStore
307                                                 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
308         }
309
310         void performOk() {
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);
323
324                         maskBuf.append(getContributedHovers()[i].getId());
325                         maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
326                         maskBuf.append(fHoverConfigs[i].fStateMask);
327                         maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
328                 }
329                 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS, buf
330                                 .toString());
331                 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS,
332                                 maskBuf.toString());
333
334                 fStore.setValue(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE,
335                                 fShowHoverAffordanceCheckbox.getSelection());
336
337                 WebUI.getDefault().resetJavaEditorTextHoverDescriptors();
338         }
339
340         void performDefaults() {
341                 restoreFromPreferences();
342                 initializeFields();
343         }
344
345         private void restoreFromPreferences() {
346
347                 fShowHoverAffordanceCheckbox
348                                 .setSelection(fStore
349                                                 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
350
351                 String compiledTextHoverModifiers = fStore
352                                 .getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
353
354                 StringTokenizer tokenizer = new StringTokenizer(
355                                 compiledTextHoverModifiers,
356                                 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
357                 HashMap idToModifier = new HashMap(tokenizer.countTokens() / 2);
358
359                 while (tokenizer.hasMoreTokens()) {
360                         String id = tokenizer.nextToken();
361                         if (tokenizer.hasMoreTokens())
362                                 idToModifier.put(id, tokenizer.nextToken());
363                 }
364
365                 String compiledTextHoverModifierMasks = WebUI.getDefault()
366                                 .getPreferenceStore().getString(
367                                                 PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
368
369                 tokenizer = new StringTokenizer(compiledTextHoverModifierMasks,
370                                 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
371                 HashMap idToModifierMask = new HashMap(tokenizer.countTokens() / 2);
372
373                 while (tokenizer.hasMoreTokens()) {
374                         String id = tokenizer.nextToken();
375                         if (tokenizer.hasMoreTokens())
376                                 idToModifierMask.put(id, tokenizer.nextToken());
377                 }
378
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;
385
386                         if (modifierString
387                                         .startsWith(JavaEditorTextHoverDescriptor.DISABLED_TAG)) {
388                                 enabled = false;
389                                 modifierString = modifierString.substring(1);
390                         }
391
392                         if (modifierString
393                                         .equals(JavaEditorTextHoverDescriptor.NO_MODIFIER))
394                                 modifierString = ""; //$NON-NLS-1$
395
396                         fHoverConfigs[i].fModifierString = modifierString;
397                         fHoverConfigs[i].fIsEnabled = enabled;
398                         fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
399                                         .computeStateMask(modifierString);
400
401                         if (fHoverConfigs[i].fStateMask == -1) {
402                                 try {
403                                         fHoverConfigs[i].fStateMask = Integer
404                                                         .parseInt((String) idToModifierMask
405                                                                         .get(getContributedHovers()[i].getId()));
406                                 } catch (NumberFormatException ex) {
407                                         fHoverConfigs[i].fStateMask = -1;
408                                 }
409                         }
410                 }
411         }
412
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(
421                                         IStatus.ERROR,
422                                         PreferencesMessages
423                                                         .getFormattedString(
424                                                                         "JavaEditorHoverConfigurationBlock.modifierIsNotValid", fHoverConfigs[i].fModifierString)); //$NON-NLS-1$
425                 else
426                         fStatus = new StatusInfo();
427                 updateStatus();
428         }
429
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);
440         }
441
442         IStatus getStatus() {
443                 if (fStatus == null)
444                         fStatus = new StatusInfo();
445                 return fStatus;
446         }
447
448         private void updateStatus() {
449                 int i = 0;
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(
457                                                         IStatus.ERROR,
458                                                         PreferencesMessages
459                                                                         .getFormattedString(
460                                                                                         "JavaEditorHoverConfigurationBlock.modifierIsNotValidForHover", new String[] { fHoverConfigs[i].fModifierString, label })); //$NON-NLS-1$
461                                 else if (stateMasks.containsKey(stateMask))
462                                         fStatus = new StatusInfo(
463                                                         IStatus.ERROR,
464                                                         PreferencesMessages
465                                                                         .getFormattedString(
466                                                                                         "JavaEditorHoverConfigurationBlock.duplicateModifier", new String[] { label, (String) stateMasks.get(stateMask) })); //$NON-NLS-1$
467                                 else
468                                         stateMasks.put(stateMask, label);
469                         }
470                         i++;
471                 }
472
473                 if (fStatus.isOK())
474                         fMainPreferencePage.updateStatus(fStatus);
475                 else {
476                         fMainPreferencePage.setValid(false);
477                         StatusUtil.applyToStatusLine(fMainPreferencePage, fStatus);
478                 }
479         }
480 }