001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.preferences;
011:
012: import java.util.Arrays;
013: import java.util.List;
014:
015: import org.eclipse.core.runtime.Assert;
016: import org.eclipse.core.runtime.IStatus;
017:
018: import org.eclipse.swt.SWT;
019: import org.eclipse.swt.graphics.Image;
020: import org.eclipse.swt.graphics.Point;
021: import org.eclipse.swt.layout.GridData;
022: import org.eclipse.swt.layout.GridLayout;
023: import org.eclipse.swt.widgets.Composite;
024: import org.eclipse.swt.widgets.Control;
025: import org.eclipse.swt.widgets.Label;
026: import org.eclipse.swt.widgets.Shell;
027: import org.eclipse.swt.widgets.Text;
028:
029: import org.eclipse.jface.dialogs.Dialog;
030: import org.eclipse.jface.dialogs.StatusDialog;
031: import org.eclipse.jface.operation.IRunnableContext;
032: import org.eclipse.jface.viewers.LabelProvider;
033: import org.eclipse.jface.viewers.ViewerComparator;
034: import org.eclipse.jface.window.Window;
035:
036: import org.eclipse.ui.PlatformUI;
037: import org.eclipse.ui.dialogs.SelectionDialog;
038: import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
039:
040: import org.eclipse.jdt.core.IType;
041: import org.eclipse.jdt.core.JavaConventions;
042: import org.eclipse.jdt.core.JavaCore;
043: import org.eclipse.jdt.core.JavaModelException;
044: import org.eclipse.jdt.core.search.IJavaSearchScope;
045: import org.eclipse.jdt.core.search.SearchEngine;
046:
047: import org.eclipse.jdt.ui.IJavaElementSearchConstants;
048: import org.eclipse.jdt.ui.JavaUI;
049: import org.eclipse.jdt.ui.PreferenceConstants;
050:
051: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
052: import org.eclipse.jdt.internal.ui.JavaPluginImages;
053: import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
054: import org.eclipse.jdt.internal.ui.dialogs.TextFieldNavigationHandler;
055: import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
056: import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
057: import org.eclipse.jdt.internal.ui.util.PixelConverter;
058: import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
059: import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
060: import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
061: import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
062: import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
063: import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
064: import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
065: import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
066: import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
067:
068: /**
069: * Configures the Content Assist > Static Members preference page.
070: *
071: * @since 3.3
072: */
073: class CodeAssistFavoritesConfigurationBlock extends
074: OptionsConfigurationBlock {
075:
076: private static class FavoriteStaticMemberInputDialog extends
077: StatusDialog {
078:
079: private class StringButtonAdapter implements
080: IDialogFieldListener, IStringButtonAdapter {
081: /*
082: * @see IDialogFieldListener#dialogFieldChanged(DialogField)
083: */
084: public void dialogFieldChanged(DialogField field) {
085: doDialogFieldChanged(field);
086: }
087:
088: /*
089: * @see IStringButtonAdapter#changeControlPressed(DialogField)
090: */
091: public void changeControlPressed(DialogField field) {
092: doBrowseTypes();
093: }
094: }
095:
096: private StringButtonDialogField fNameDialogField;
097: private List fExistingEntries;
098: private final boolean fIsEditingMember;
099:
100: public FavoriteStaticMemberInputDialog(Shell parent,
101: List existingEntries, boolean isEditingMember) {
102: super (parent);
103: fIsEditingMember = isEditingMember;
104: setShellStyle(getShellStyle() | SWT.RESIZE);
105:
106: fExistingEntries = existingEntries;
107:
108: String label, title;
109: if (isEditingMember) {
110: title = PreferencesMessages.FavoriteStaticMemberInputDialog_member_title;
111: label = PreferencesMessages.FavoriteStaticMemberInputDialog_member_labelText;
112: } else {
113: title = PreferencesMessages.FavoriteStaticMemberInputDialog_type_title;
114: label = PreferencesMessages.FavoriteStaticMemberInputDialog_type_labelText;
115: }
116: setTitle(title);
117:
118: StringButtonAdapter adapter = new StringButtonAdapter();
119:
120: fNameDialogField = new StringButtonDialogField(adapter);
121: fNameDialogField.setLabelText(label);
122: fNameDialogField
123: .setButtonLabel(PreferencesMessages.FavoriteStaticMemberInputDialog_browse_button);
124: fNameDialogField.setDialogFieldListener(adapter);
125: fNameDialogField.setText(""); //$NON-NLS-1$
126: }
127:
128: public void setInitialSelection(String editedEntry) {
129: Assert.isNotNull(editedEntry);
130: if (editedEntry.length() == 0)
131: fNameDialogField.setText(""); //$NON-NLS-1$
132: else
133: fNameDialogField.setText(editedEntry);
134: }
135:
136: public String getResult() {
137: String val = fNameDialogField.getText();
138: if (!fIsEditingMember)
139: val = val + WILDCARD;
140: return val;
141: }
142:
143: protected Control createDialogArea(Composite parent) {
144: Composite composite = (Composite) super
145: .createDialogArea(parent);
146: initializeDialogUnits(parent);
147:
148: GridLayout layout = (GridLayout) composite.getLayout();
149: layout.numColumns = 2;
150:
151: fNameDialogField.doFillIntoGrid(composite, 3);
152:
153: fNameDialogField.getChangeControl(null).setVisible(
154: !fIsEditingMember);
155:
156: LayoutUtil.setHorizontalSpan(fNameDialogField
157: .getLabelControl(null), 2);
158:
159: int fieldWidthHint = convertWidthInCharsToPixels(60);
160: Text text = fNameDialogField.getTextControl(null);
161: LayoutUtil.setWidthHint(text, fieldWidthHint);
162: LayoutUtil.setHorizontalGrabbing(text);
163: LayoutUtil
164: .setHorizontalSpan(text, fIsEditingMember ? 2 : 1);
165: TextFieldNavigationHandler.install(text);
166:
167: DialogField.createEmptySpace(composite, 1);
168:
169: fNameDialogField.postSetFocusOnDialogField(parent
170: .getDisplay());
171:
172: applyDialogFont(composite);
173: return composite;
174: }
175:
176: private void doBrowseTypes() {
177: IRunnableContext context = new BusyIndicatorRunnableContext();
178: IJavaSearchScope scope = SearchEngine
179: .createWorkspaceScope();
180: int style = IJavaElementSearchConstants.CONSIDER_ALL_TYPES;
181: try {
182: SelectionDialog dialog = JavaUI.createTypeDialog(
183: getShell(), context, scope, style, false,
184: fNameDialogField.getText());
185: dialog
186: .setTitle(PreferencesMessages.FavoriteStaticMemberInputDialog_ChooseTypeDialog_title);
187: dialog
188: .setMessage(PreferencesMessages.FavoriteStaticMemberInputDialog_ChooseTypeDialog_description);
189: if (dialog.open() == Window.OK) {
190: IType res = (IType) dialog.getResult()[0];
191: fNameDialogField.setText(res
192: .getFullyQualifiedName('.'));
193: }
194: } catch (JavaModelException e) {
195: ExceptionHandler
196: .handle(
197: e,
198: getShell(),
199: PreferencesMessages.FavoriteStaticMemberInputDialog_ChooseTypeDialog_title,
200: PreferencesMessages.FavoriteStaticMemberInputDialog_ChooseTypeDialog_error_message);
201: }
202: }
203:
204: void doDialogFieldChanged(DialogField field) {
205: doValidation();
206: }
207:
208: private void doValidation() {
209: StatusInfo status = new StatusInfo();
210: String newText = fNameDialogField.getText();
211: if (newText.length() == 0) {
212: status.setError(""); //$NON-NLS-1$
213: } else {
214: IStatus val = JavaConventions.validateJavaTypeName(
215: newText, JavaCore.VERSION_1_3,
216: JavaCore.VERSION_1_3);
217: if (val.matches(IStatus.ERROR)) {
218: if (fIsEditingMember)
219: status
220: .setError(PreferencesMessages.FavoriteStaticMemberInputDialog_error_invalidMemberName);
221: else
222: status
223: .setError(PreferencesMessages.FavoriteStaticMemberInputDialog_error_invalidTypeName);
224: } else {
225: if (doesExist(newText, fIsEditingMember)) {
226: status
227: .setError(PreferencesMessages.FavoriteStaticMemberInputDialog_error_entryExists);
228: }
229: }
230: }
231: updateStatus(status);
232: }
233:
234: private boolean doesExist(String name, boolean isStatic) {
235: for (int i = 0; i < fExistingEntries.size(); i++) {
236: String entry = (String) fExistingEntries.get(i);
237: if (name.equals(entry)) {
238: return true;
239: }
240: }
241: return false;
242: }
243:
244: /*
245: * @see org.eclipse.jface.window.Window#configureShell(Shell)
246: */
247: protected void configureShell(Shell newShell) {
248: super .configureShell(newShell);
249: PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
250: IJavaHelpContextIds.JAVA_EDITOR_PREFERENCE_PAGE);
251: }
252:
253: }
254:
255: private static class ListLabelProvider extends LabelProvider {
256:
257: public final Image MEMBER_ICON;
258: private final Image CLASS_ICON;
259:
260: public ListLabelProvider() {
261: MEMBER_ICON = JavaElementImageProvider.getDecoratedImage(
262: JavaPluginImages.DESC_MISC_PUBLIC, 0,
263: JavaElementImageProvider.SMALL_SIZE);
264: CLASS_ICON = JavaElementImageProvider.getDecoratedImage(
265: JavaPluginImages.DESC_OBJS_CLASS, 0,
266: JavaElementImageProvider.SMALL_SIZE);
267: }
268:
269: public Image getImage(Object element) {
270: return ((String) element).endsWith(WILDCARD) ? CLASS_ICON
271: : MEMBER_ICON;
272: }
273:
274: public String getText(Object element) {
275: return (String) element;
276: }
277: }
278:
279: private class ListAdapter implements IListAdapter,
280: IDialogFieldListener {
281:
282: private boolean canEdit(ListDialogField field) {
283: List selected = field.getSelectedElements();
284: return selected.size() == 1;
285: }
286:
287: public void customButtonPressed(ListDialogField field, int index) {
288: doButtonPressed(index);
289: }
290:
291: public void selectionChanged(ListDialogField field) {
292: fList.enableButton(IDX_EDIT, canEdit(field));
293: }
294:
295: public void dialogFieldChanged(DialogField field) {
296: doDialogFieldChanged(field);
297: }
298:
299: public void doubleClicked(ListDialogField field) {
300: if (canEdit(field)) {
301: doButtonPressed(IDX_EDIT);
302: }
303: }
304: }
305:
306: private static final Key PREF_CODEASSIST_FAVORITE_STATIC_MEMBERS = getJDTUIKey(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS);
307:
308: private static final String WILDCARD = ".*"; //$NON-NLS-1$
309:
310: private static final int IDX_NEW_TYPE = 0;
311: private static final int IDX_NEW_MEMBER = 1;
312: private static final int IDX_EDIT = 2;
313: private static final int IDX_REMOVE = 3;
314:
315: private ListDialogField fList;
316:
317: private static Key[] getAllKeys() {
318: return new Key[] { PREF_CODEASSIST_FAVORITE_STATIC_MEMBERS };
319: }
320:
321: public CodeAssistFavoritesConfigurationBlock(
322: IStatusChangeListener statusListener,
323: IWorkbenchPreferenceContainer workbenchcontainer) {
324: super (statusListener, null, getAllKeys(), workbenchcontainer);
325: }
326:
327: protected Control createContents(Composite parent) {
328: ScrolledPageContent scrolled = new ScrolledPageContent(parent,
329: SWT.H_SCROLL | SWT.V_SCROLL);
330: scrolled.setExpandHorizontal(true);
331: scrolled.setExpandVertical(true);
332:
333: Composite control = new Composite(scrolled, SWT.NONE);
334: GridLayout layout = new GridLayout();
335: layout.numColumns = 2;
336: layout.marginWidth = 0;
337: layout.marginHeight = 0;
338: control.setLayout(layout);
339:
340: createFavoriteList(control);
341:
342: initialize();
343:
344: scrolled.setContent(control);
345: final Point size = control
346: .computeSize(SWT.DEFAULT, SWT.DEFAULT);
347: scrolled.setMinSize(size.x, size.y);
348:
349: Dialog.applyDialogFont(scrolled);
350:
351: return scrolled;
352: }
353:
354: private void createFavoriteList(Composite parent) {
355: String[] buttonLabels = new String[] {
356: PreferencesMessages.CodeAssistStaticMembersConfigurationBlock_newType_button,
357: PreferencesMessages.CodeAssistStaticMembersConfigurationBlock_newMember_button,
358: PreferencesMessages.CodeAssistStaticMembersConfigurationBlock_edit_button,
359: PreferencesMessages.CodeAssistStaticMembersConfigurationBlock_remove_button };
360:
361: ListAdapter adapter = new ListAdapter();
362:
363: fList = new ListDialogField(adapter, buttonLabels,
364: new ListLabelProvider());
365: fList.setDialogFieldListener(adapter);
366: fList
367: .setLabelText(PreferencesMessages.CodeAssistStaticMembersConfigurationBlock_description);
368: fList.setRemoveButtonIndex(IDX_REMOVE);
369: fList.enableButton(IDX_EDIT, false);
370: fList.setViewerComparator(new ViewerComparator());
371:
372: PixelConverter pixelConverter = new PixelConverter(parent);
373:
374: fList.doFillIntoGrid(parent, 3);
375: LayoutUtil.setHorizontalSpan(fList.getLabelControl(null), 2);
376: LayoutUtil.setWidthHint(fList.getLabelControl(null),
377: pixelConverter.convertWidthInCharsToPixels(60));
378: LayoutUtil.setHorizontalGrabbing(fList.getListControl(null));
379:
380: Control listControl = fList.getListControl(null);
381: GridData gd = (GridData) listControl.getLayoutData();
382: gd.verticalAlignment = GridData.BEGINNING;
383: gd.heightHint = pixelConverter.convertHeightInCharsToPixels(7);
384: }
385:
386: public void initialize() {
387: initializeFields();
388: }
389:
390: private void initializeFields() {
391: fList.setElements(Arrays
392: .asList(getFavoriteStaticMembersPreference()));
393: }
394:
395: public void performDefaults() {
396: super .performDefaults();
397: initializeFields();
398: }
399:
400: protected String[] getFullBuildDialogStrings(
401: boolean workspaceSettings) {
402: return null;
403: }
404:
405: protected void validateSettings(Key key, String oldValue,
406: String newValue) {
407: // no validation
408: }
409:
410: protected void setControlEnabled(Key key, boolean enabled) {
411: Control control = getControl(key);
412: control.setEnabled(enabled);
413: Label label = (Label) fLabels.get(control);
414: if (label != null)
415: label.setEnabled(enabled);
416: }
417:
418: private Control getControl(Key key) {
419: for (int i = fComboBoxes.size() - 1; i >= 0; i--) {
420: Control curr = (Control) fComboBoxes.get(i);
421: ControlData data = (ControlData) curr.getData();
422: if (key.equals(data.getKey())) {
423: return curr;
424: }
425: }
426: for (int i = fCheckBoxes.size() - 1; i >= 0; i--) {
427: Control curr = (Control) fCheckBoxes.get(i);
428: ControlData data = (ControlData) curr.getData();
429: if (key.equals(data.getKey())) {
430: return curr;
431: }
432: }
433: for (int i = fTextBoxes.size() - 1; i >= 0; i--) {
434: Control curr = (Control) fTextBoxes.get(i);
435: Key currKey = (Key) curr.getData();
436: if (key.equals(currKey)) {
437: return curr;
438: }
439: }
440: return null;
441: }
442:
443: private void doButtonPressed(int index) {
444: if (index == IDX_NEW_TYPE || index == IDX_NEW_MEMBER) { // add new
445: List existing = fList.getElements();
446: FavoriteStaticMemberInputDialog dialog = new FavoriteStaticMemberInputDialog(
447: getShell(), existing, index == IDX_NEW_MEMBER);
448: if (dialog.open() == Window.OK) {
449: fList.addElement(dialog.getResult());
450: }
451: } else if (index == IDX_EDIT) { // edit
452: List selected = fList.getSelectedElements();
453: if (selected.isEmpty())
454: return;
455:
456: String editedEntry = (String) selected.get(0);
457:
458: List existing = fList.getElements();
459: existing.remove(editedEntry);
460: boolean isType = editedEntry.endsWith(WILDCARD);
461: FavoriteStaticMemberInputDialog dialog = new FavoriteStaticMemberInputDialog(
462: getShell(), existing, !isType);
463: if (isType)
464: dialog.setInitialSelection(editedEntry.substring(0,
465: editedEntry.length() - 2));
466: else
467: dialog.setInitialSelection(editedEntry);
468:
469: if (dialog.open() == Window.OK) {
470: fList.replaceElement(editedEntry, dialog.getResult());
471: }
472: }
473: }
474:
475: protected final void doDialogFieldChanged(DialogField field) {
476: // set values in working copy
477: if (field == fList)
478: setValue(PREF_CODEASSIST_FAVORITE_STATIC_MEMBERS,
479: serializeFavorites(fList.getElements()));
480: }
481:
482: private String[] getFavoriteStaticMembersPreference() {
483: String str = getValue(PREF_CODEASSIST_FAVORITE_STATIC_MEMBERS);
484: if (str != null && str.length() > 0)
485: return deserializeFavorites(str);
486: return new String[0];
487: }
488:
489: private static String[] deserializeFavorites(String str) {
490: return str.split(";"); //$NON-NLS-1$
491: }
492:
493: private static String serializeFavorites(List favorites) {
494: int size = favorites.size();
495: StringBuffer buf = new StringBuffer();
496: for (int i = 0; i < size; i++) {
497: buf.append((String) favorites.get(i));
498: if (i < size - 1)
499: buf.append(';');
500: }
501: return buf.toString();
502: }
503:
504: }
|