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.PHPeclipsePlugin;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.jface.action.Action;
26 import org.eclipse.jface.dialogs.Dialog;
27 import org.eclipse.jface.preference.IPreferenceStore;
28 import org.eclipse.jface.text.Assert;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.KeyEvent;
31 import org.eclipse.swt.events.KeyListener;
32 import org.eclipse.swt.events.ModifyEvent;
33 import org.eclipse.swt.events.ModifyListener;
34 import org.eclipse.swt.events.SelectionEvent;
35 import org.eclipse.swt.events.SelectionListener;
36 import org.eclipse.swt.graphics.Point;
37 import org.eclipse.swt.layout.GridData;
38 import org.eclipse.swt.layout.GridLayout;
39 import org.eclipse.swt.widgets.Button;
40 import org.eclipse.swt.widgets.Composite;
41 import org.eclipse.swt.widgets.Control;
42 import org.eclipse.swt.widgets.Label;
43 import org.eclipse.swt.widgets.List;
44 import org.eclipse.swt.widgets.Text;
47 * Configures Java Editor hover preferences.
51 class JavaEditorHoverConfigurationBlock {
53 private static final String DELIMITER = PreferencesMessages
54 .getString("JavaEditorHoverConfigurationBlock.delimiter"); //$NON-NLS-1$
56 // Data structure to hold the values which are edited by the user
57 private static class HoverConfig {
59 private String fModifierString;
61 private boolean fIsEnabled;
63 private int fStateMask;
65 private HoverConfig(String modifier, int stateMask, boolean enabled) {
66 fModifierString = modifier;
68 fStateMask = stateMask;
72 private IPreferenceStore fStore;
74 private HoverConfig[] fHoverConfigs;
76 private Text fModifierEditor;
78 private Button fEnableField;
80 private List fHoverList;
82 private Text fDescription;
84 private Button fShowHoverAffordanceCheckbox;
86 private JavaEditorPreferencePage fMainPreferencePage;
88 private StatusInfo fStatus;
90 public JavaEditorHoverConfigurationBlock(
91 JavaEditorPreferencePage mainPreferencePage, IPreferenceStore store) {
92 Assert.isNotNull(mainPreferencePage);
93 Assert.isNotNull(store);
94 fMainPreferencePage = mainPreferencePage;
99 * Creates page for hover preferences.
101 public Control createControl(Composite parent) {
103 PixelConverter pixelConverter = new PixelConverter(parent);
105 Composite hoverComposite = new Composite(parent, SWT.NULL);
106 GridLayout layout = new GridLayout();
107 layout.numColumns = 2;
108 hoverComposite.setLayout(layout);
109 GridData gd = new GridData(GridData.GRAB_HORIZONTAL
110 | GridData.VERTICAL_ALIGN_FILL);
111 hoverComposite.setLayoutData(gd);
113 Label label = new Label(hoverComposite, SWT.NONE);
115 .setText(PreferencesMessages
116 .getString("JavaEditorHoverConfigurationBlock.hoverPreferences")); //$NON-NLS-1$
117 gd = new GridData(GridData.FILL_HORIZONTAL);
118 gd.horizontalAlignment = GridData.BEGINNING;
119 gd.horizontalSpan = 2;
120 label.setLayoutData(gd);
121 gd = new GridData(GridData.GRAB_HORIZONTAL
122 | GridData.VERTICAL_ALIGN_FILL);
125 fHoverList = new List(hoverComposite, SWT.SINGLE | SWT.V_SCROLL
127 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
128 | GridData.FILL_HORIZONTAL);
129 int listHeight = 10 * fHoverList.getItemHeight();
130 gd.heightHint = listHeight;
131 fHoverList.setLayoutData(gd);
132 fHoverList.addSelectionListener(new SelectionListener() {
133 public void widgetSelected(SelectionEvent e) {
134 handleHoverListSelection();
137 public void widgetDefaultSelected(SelectionEvent e) {
141 Composite stylesComposite = new Composite(hoverComposite, SWT.NONE);
142 layout = new GridLayout();
143 layout.marginHeight = 0;
144 layout.marginWidth = 0;
145 layout.numColumns = 2;
146 stylesComposite.setLayout(layout);
147 gd = new GridData(GridData.FILL_HORIZONTAL);
148 gd.heightHint = listHeight + (2 * fHoverList.getBorderWidth());
149 stylesComposite.setLayoutData(gd);
152 fEnableField = new Button(stylesComposite, SWT.CHECK);
153 fEnableField.setText(PreferencesMessages
154 .getString("JavaEditorHoverConfigurationBlock.enabled")); //$NON-NLS-1$
155 gd = new GridData(GridData.FILL_HORIZONTAL);
156 gd.horizontalAlignment = GridData.BEGINNING;
157 gd.horizontalSpan = 2;
158 fEnableField.setLayoutData(gd);
159 fEnableField.addSelectionListener(new SelectionListener() {
160 public void widgetSelected(SelectionEvent e) {
161 int i = fHoverList.getSelectionIndex();
162 boolean state = fEnableField.getSelection();
163 fModifierEditor.setEnabled(state);
164 fHoverConfigs[i].fIsEnabled = state;
165 handleModifierModified();
168 public void widgetDefaultSelected(SelectionEvent e) {
172 // Text field for modifier string
173 label = new Label(stylesComposite, SWT.LEFT);
174 label.setText(PreferencesMessages
175 .getString("JavaEditorHoverConfigurationBlock.keyModifier")); //$NON-NLS-1$
176 fModifierEditor = new Text(stylesComposite, SWT.BORDER);
177 gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
178 fModifierEditor.setLayoutData(gd);
180 fModifierEditor.addKeyListener(new KeyListener() {
181 private boolean isModifierCandidate;
183 public void keyPressed(KeyEvent e) {
184 isModifierCandidate = e.keyCode > 0 && e.character == 0
188 public void keyReleased(KeyEvent e) {
189 if (isModifierCandidate && e.stateMask > 0
190 && e.stateMask == e.stateMask && e.character == 0) {// &&
196 String text = fModifierEditor.getText();
197 Point selection = fModifierEditor.getSelection();
198 int i = selection.x - 1;
199 while (i > -1 && Character.isWhitespace(text.charAt(i))) {
202 boolean needsPrefixDelimiter = i > -1
203 && !String.valueOf(text.charAt(i))
207 while (i < text.length()
208 && Character.isWhitespace(text.charAt(i))) {
211 boolean needsPostfixDelimiter = i < text.length()
212 && !String.valueOf(text.charAt(i))
217 if (needsPrefixDelimiter && needsPostfixDelimiter)
218 insertString = PreferencesMessages
220 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
221 else if (needsPrefixDelimiter)
222 insertString = PreferencesMessages
224 "JavaEditorHoverConfigurationBlock.insertDelimiterAndModifier", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
225 else if (needsPostfixDelimiter)
226 insertString = PreferencesMessages
228 "JavaEditorHoverConfigurationBlock.insertModifierAndDelimiter", new String[] { Action.findModifierString(e.stateMask) }); //$NON-NLS-1$
230 insertString = Action.findModifierString(e.stateMask);
232 if (insertString != null)
233 fModifierEditor.insert(insertString);
238 fModifierEditor.addModifyListener(new ModifyListener() {
239 public void modifyText(ModifyEvent e) {
240 handleModifierModified();
245 Label descriptionLabel = new Label(stylesComposite, SWT.LEFT);
246 descriptionLabel.setText(PreferencesMessages
247 .getString("JavaEditorHoverConfigurationBlock.description")); //$NON-NLS-1$
248 gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
249 gd.horizontalSpan = 2;
250 descriptionLabel.setLayoutData(gd);
251 fDescription = new Text(stylesComposite, SWT.LEFT | SWT.WRAP
252 | SWT.MULTI | SWT.READ_ONLY | SWT.BORDER);
253 gd = new GridData(GridData.FILL_BOTH);
254 gd.horizontalSpan = 2;
255 fDescription.setLayoutData(gd);
258 Label filler = new Label(hoverComposite, SWT.LEFT);
259 gd = new GridData(GridData.BEGINNING | GridData.VERTICAL_ALIGN_FILL);
260 gd.heightHint = pixelConverter.convertHeightInCharsToPixels(1) / 3;
261 filler.setLayoutData(gd);
263 // Affordance checkbox
264 fShowHoverAffordanceCheckbox = new Button(hoverComposite, SWT.CHECK);
265 fShowHoverAffordanceCheckbox.setText(PreferencesMessages
266 .getString("JavaEditorHoverConfigurationBlock.showAffordance")); //$NON-NLS-1$
267 gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
268 gd.horizontalIndent = 0;
269 gd.horizontalSpan = 2;
270 fShowHoverAffordanceCheckbox.setLayoutData(gd);
274 Dialog.applyDialogFont(hoverComposite);
275 return hoverComposite;
278 private JavaEditorTextHoverDescriptor[] getContributedHovers() {
279 return PHPeclipsePlugin.getDefault()
280 .getJavaEditorTextHoverDescriptors();
284 JavaEditorTextHoverDescriptor[] hoverDescs = getContributedHovers();
285 fHoverConfigs = new HoverConfig[hoverDescs.length];
286 for (int i = 0; i < hoverDescs.length; i++) {
287 fHoverConfigs[i] = new HoverConfig(hoverDescs[i]
288 .getModifierString(), hoverDescs[i].getStateMask(),
289 hoverDescs[i].isEnabled());
290 fHoverList.add(hoverDescs[i].getLabel());
295 void initializeFields() {
296 fHoverList.getDisplay().asyncExec(new Runnable() {
298 if (fHoverList != null && !fHoverList.isDisposed()) {
299 fHoverList.select(0);
300 handleHoverListSelection();
304 fShowHoverAffordanceCheckbox
306 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
310 StringBuffer buf = new StringBuffer();
311 StringBuffer maskBuf = new StringBuffer();
312 for (int i = 0; i < fHoverConfigs.length; i++) {
313 buf.append(getContributedHovers()[i].getId());
314 buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
315 if (!fHoverConfigs[i].fIsEnabled)
316 buf.append(JavaEditorTextHoverDescriptor.DISABLED_TAG);
317 String modifier = fHoverConfigs[i].fModifierString;
318 if (modifier == null || modifier.length() == 0)
319 modifier = JavaEditorTextHoverDescriptor.NO_MODIFIER;
320 buf.append(modifier);
321 buf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
323 maskBuf.append(getContributedHovers()[i].getId());
324 maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
325 maskBuf.append(fHoverConfigs[i].fStateMask);
326 maskBuf.append(JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
328 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS, buf
330 fStore.setValue(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS,
333 fStore.setValue(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE,
334 fShowHoverAffordanceCheckbox.getSelection());
336 PHPeclipsePlugin.getDefault().resetJavaEditorTextHoverDescriptors();
339 void performDefaults() {
340 restoreFromPreferences();
344 private void restoreFromPreferences() {
346 fShowHoverAffordanceCheckbox
348 .getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE));
350 String compiledTextHoverModifiers = fStore
351 .getString(PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS);
353 StringTokenizer tokenizer = new StringTokenizer(
354 compiledTextHoverModifiers,
355 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
356 HashMap idToModifier = new HashMap(tokenizer.countTokens() / 2);
358 while (tokenizer.hasMoreTokens()) {
359 String id = tokenizer.nextToken();
360 if (tokenizer.hasMoreTokens())
361 idToModifier.put(id, tokenizer.nextToken());
364 String compiledTextHoverModifierMasks = PHPeclipsePlugin.getDefault()
365 .getPreferenceStore().getString(
366 PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS);
368 tokenizer = new StringTokenizer(compiledTextHoverModifierMasks,
369 JavaEditorTextHoverDescriptor.VALUE_SEPARATOR);
370 HashMap idToModifierMask = new HashMap(tokenizer.countTokens() / 2);
372 while (tokenizer.hasMoreTokens()) {
373 String id = tokenizer.nextToken();
374 if (tokenizer.hasMoreTokens())
375 idToModifierMask.put(id, tokenizer.nextToken());
378 for (int i = 0; i < fHoverConfigs.length; i++) {
379 String modifierString = (String) idToModifier
380 .get(getContributedHovers()[i].getId());
381 boolean enabled = true;
382 if (modifierString == null)
383 modifierString = JavaEditorTextHoverDescriptor.DISABLED_TAG;
386 .startsWith(JavaEditorTextHoverDescriptor.DISABLED_TAG)) {
388 modifierString = modifierString.substring(1);
392 .equals(JavaEditorTextHoverDescriptor.NO_MODIFIER))
393 modifierString = ""; //$NON-NLS-1$
395 fHoverConfigs[i].fModifierString = modifierString;
396 fHoverConfigs[i].fIsEnabled = enabled;
397 fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
398 .computeStateMask(modifierString);
400 if (fHoverConfigs[i].fStateMask == -1) {
402 fHoverConfigs[i].fStateMask = Integer
403 .parseInt((String) idToModifierMask
404 .get(getContributedHovers()[i].getId()));
405 } catch (NumberFormatException ex) {
406 fHoverConfigs[i].fStateMask = -1;
412 private void handleModifierModified() {
413 int i = fHoverList.getSelectionIndex();
414 String modifiers = fModifierEditor.getText();
415 fHoverConfigs[i].fModifierString = modifiers;
416 fHoverConfigs[i].fStateMask = JavaEditorTextHoverDescriptor
417 .computeStateMask(modifiers);
418 if (fHoverConfigs[i].fIsEnabled && fHoverConfigs[i].fStateMask == -1)
419 fStatus = new StatusInfo(
423 "JavaEditorHoverConfigurationBlock.modifierIsNotValid", fHoverConfigs[i].fModifierString)); //$NON-NLS-1$
425 fStatus = new StatusInfo();
429 private void handleHoverListSelection() {
430 int i = fHoverList.getSelectionIndex();
431 boolean enabled = fHoverConfigs[i].fIsEnabled;
432 fEnableField.setSelection(enabled);
433 fModifierEditor.setEnabled(enabled);
434 fModifierEditor.setText(fHoverConfigs[i].fModifierString);
435 String description = getContributedHovers()[i].getDescription();
436 if (description == null)
437 description = ""; //$NON-NLS-1$
438 fDescription.setText(description);
441 IStatus getStatus() {
443 fStatus = new StatusInfo();
447 private void updateStatus() {
449 HashMap stateMasks = new HashMap(fHoverConfigs.length);
450 while (fStatus.isOK() && i < fHoverConfigs.length) {
451 if (fHoverConfigs[i].fIsEnabled) {
452 String label = getContributedHovers()[i].getLabel();
453 Integer stateMask = new Integer(fHoverConfigs[i].fStateMask);
454 if (fHoverConfigs[i].fStateMask == -1)
455 fStatus = new StatusInfo(
459 "JavaEditorHoverConfigurationBlock.modifierIsNotValidForHover", new String[] { fHoverConfigs[i].fModifierString, label })); //$NON-NLS-1$
460 else if (stateMasks.containsKey(stateMask))
461 fStatus = new StatusInfo(
465 "JavaEditorHoverConfigurationBlock.duplicateModifier", new String[] { label, (String) stateMasks.get(stateMask) })); //$NON-NLS-1$
467 stateMasks.put(stateMask, label);
473 fMainPreferencePage.updateStatus(fStatus);
475 fMainPreferencePage.setValid(false);
476 StatusUtil.applyToStatusLine(fMainPreferencePage, fStatus);