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);