1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 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 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.preferences;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
19 import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds;
20 import net.sourceforge.phpdt.internal.ui.dialogs.StatusDialog;
21 import net.sourceforge.phpdt.internal.ui.dialogs.StatusInfo;
22 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
23 import net.sourceforge.phpdt.internal.ui.text.template.preferences.TemplateVariableProcessor;
24 import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
25 import net.sourceforge.phpdt.ui.IContextMenuConstants;
26 import net.sourceforge.phpdt.ui.PreferenceConstants;
27 import net.sourceforge.phpdt.ui.text.JavaTextTools;
28 //import net.sourceforge.phpeclipse.PHPeclipsePlugin;
29 import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
30 import net.sourceforge.phpeclipse.ui.WebUI;
32 import org.eclipse.jface.action.Action;
33 import org.eclipse.jface.action.GroupMarker;
34 import org.eclipse.jface.action.IAction;
35 import org.eclipse.jface.action.IMenuListener;
36 import org.eclipse.jface.action.IMenuManager;
37 import org.eclipse.jface.action.MenuManager;
38 import org.eclipse.jface.action.Separator;
39 import org.eclipse.jface.preference.IPreferenceStore;
40 import org.eclipse.jface.resource.JFaceResources;
41 import org.eclipse.jface.text.Document;
42 import org.eclipse.jface.text.IDocument;
43 import org.eclipse.jface.text.ITextListener;
44 import org.eclipse.jface.text.ITextOperationTarget;
45 import org.eclipse.jface.text.ITextViewer;
46 import org.eclipse.jface.text.TextEvent;
47 import org.eclipse.jface.text.source.ISourceViewer;
48 import org.eclipse.jface.text.source.SourceViewer;
49 import org.eclipse.jface.text.templates.ContextTypeRegistry;
50 import org.eclipse.jface.text.templates.Template;
51 import org.eclipse.jface.text.templates.TemplateContextType;
52 import org.eclipse.jface.text.templates.TemplateException;
53 import org.eclipse.jface.viewers.ISelectionChangedListener;
54 import org.eclipse.jface.viewers.SelectionChangedEvent;
55 import org.eclipse.swt.SWT;
56 import org.eclipse.swt.custom.StyledText;
57 import org.eclipse.swt.custom.VerifyKeyListener;
58 import org.eclipse.swt.events.FocusEvent;
59 import org.eclipse.swt.events.FocusListener;
60 import org.eclipse.swt.events.ModifyEvent;
61 import org.eclipse.swt.events.ModifyListener;
62 import org.eclipse.swt.events.SelectionEvent;
63 import org.eclipse.swt.events.SelectionListener;
64 import org.eclipse.swt.events.VerifyEvent;
65 import org.eclipse.swt.graphics.Font;
66 import org.eclipse.swt.layout.GridData;
67 import org.eclipse.swt.layout.GridLayout;
68 import org.eclipse.swt.widgets.Button;
69 import org.eclipse.swt.widgets.Combo;
70 import org.eclipse.swt.widgets.Composite;
71 import org.eclipse.swt.widgets.Control;
72 import org.eclipse.swt.widgets.Label;
73 import org.eclipse.swt.widgets.Menu;
74 import org.eclipse.swt.widgets.Shell;
75 import org.eclipse.swt.widgets.Text;
76 import org.eclipse.swt.widgets.Widget;
77 import org.eclipse.ui.PlatformUI;
78 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
79 import org.eclipse.ui.texteditor.IUpdate;
82 * Dialog to edit a template.
84 public class EditTemplateDialog extends StatusDialog {
86 private static class TextViewerAction extends Action implements IUpdate {
88 private int fOperationCode = -1;
90 private ITextOperationTarget fOperationTarget;
93 * Creates a new action.
97 * @param operationCode
100 public TextViewerAction(ITextViewer viewer, int operationCode) {
101 fOperationCode = operationCode;
102 fOperationTarget = viewer.getTextOperationTarget();
107 * Updates the enabled state of the action. Fires a property change if
108 * the enabled state changes.
110 * @see Action#firePropertyChange(String, Object, Object)
112 public void update() {
114 boolean wasEnabled = isEnabled();
115 boolean isEnabled = (fOperationTarget != null && fOperationTarget
116 .canDoOperation(fOperationCode));
117 setEnabled(isEnabled);
119 if (wasEnabled != isEnabled) {
120 firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE
121 : Boolean.FALSE, isEnabled ? Boolean.TRUE
130 if (fOperationCode != -1 && fOperationTarget != null) {
131 fOperationTarget.doOperation(fOperationCode);
136 private final Template fTemplate;
138 private Text fNameText;
140 private Text fDescriptionText;
142 private Combo fContextCombo;
144 private SourceViewer fPatternEditor;
146 private Button fInsertVariableButton;
148 private boolean fIsNameModifiable;
150 private StatusInfo fValidationStatus;
152 private boolean fSuppressError = true; // #4354
154 private Map fGlobalActions = new HashMap(10);
156 private List fSelectionActions = new ArrayList(3);
158 private String[][] fContextTypes;
160 private ContextTypeRegistry fContextTypeRegistry;
162 private final TemplateVariableProcessor fTemplateProcessor = new TemplateVariableProcessor();
165 * Creates a new dialog.
168 * the shell parent of the dialog
170 * the template to edit
172 * whether this is a new template or an existing being edited
173 * @param isNameModifiable
174 * whether the name of the template may be modified
176 * the context type registry to use
178 public EditTemplateDialog(Shell parent, Template template, boolean edit,
179 boolean isNameModifiable, ContextTypeRegistry registry) {
182 setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE);
184 String title = edit ? PreferencesMessages
185 .getString("EditTemplateDialog.title.edit") //$NON-NLS-1$
186 : PreferencesMessages.getString("EditTemplateDialog.title.new"); //$NON-NLS-1$
189 fTemplate = template;
190 fIsNameModifiable = isNameModifiable;
192 // XXX workaround for bug 63313 - disabling prefix until fixed.
193 // String delim= new Document().getLegalLineDelimiters()[0];
195 List contexts = new ArrayList();
196 for (Iterator it = registry.contextTypes(); it.hasNext();) {
197 TemplateContextType type = (TemplateContextType) it.next();
198 // if (type.getId().equals("javadoc")) //$NON-NLS-1$
199 // contexts.add(new String[] { type.getId(), type.getName(), "/**" +
200 // delim }); //$NON-NLS-1$
202 contexts.add(new String[] { type.getId(), type.getName(), "" }); //$NON-NLS-1$
204 fContextTypes = (String[][]) contexts.toArray(new String[contexts
207 fValidationStatus = new StatusInfo();
209 fContextTypeRegistry = registry;
211 TemplateContextType type = fContextTypeRegistry.getContextType(template
212 .getContextTypeId());
213 fTemplateProcessor.setContextType(type);
217 * @see net.sourceforge.phpdt.internal.ui.dialogs.StatusDialog#create()
219 public void create() {
221 // update initial ok button to be disabled for new templates
222 boolean valid = fNameText == null
223 || fNameText.getText().trim().length() != 0;
225 StatusInfo status = new StatusInfo();
226 status.setError(PreferencesMessages
227 .getString("EditTemplateDialog.error.noname")); //$NON-NLS-1$
228 updateButtonsEnableState(status);
233 * @see Dialog#createDialogArea(Composite)
235 protected Control createDialogArea(Composite ancestor) {
236 Composite parent = new Composite(ancestor, SWT.NONE);
237 GridLayout layout = new GridLayout();
238 layout.numColumns = 2;
239 parent.setLayout(layout);
240 parent.setLayoutData(new GridData(GridData.FILL_BOTH));
242 ModifyListener listener = new ModifyListener() {
243 public void modifyText(ModifyEvent e) {
244 doTextWidgetChanged(e.widget);
248 if (fIsNameModifiable) {
249 createLabel(parent, PreferencesMessages
250 .getString("EditTemplateDialog.name")); //$NON-NLS-1$
252 Composite composite = new Composite(parent, SWT.NONE);
253 composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
254 layout = new GridLayout();
255 layout.numColumns = 3;
256 layout.marginWidth = 0;
257 layout.marginHeight = 0;
258 composite.setLayout(layout);
260 fNameText = createText(composite);
261 fNameText.addFocusListener(new FocusListener() {
263 public void focusGained(FocusEvent e) {
266 public void focusLost(FocusEvent e) {
267 if (fSuppressError) {
268 fSuppressError = false;
274 createLabel(composite, PreferencesMessages
275 .getString("EditTemplateDialog.context")); //$NON-NLS-1$
276 fContextCombo = new Combo(composite, SWT.READ_ONLY);
278 for (int i = 0; i < fContextTypes.length; i++) {
279 fContextCombo.add(fContextTypes[i][1]);
282 fContextCombo.addModifyListener(listener);
285 createLabel(parent, PreferencesMessages
286 .getString("EditTemplateDialog.description")); //$NON-NLS-1$
288 int descFlags = fIsNameModifiable ? SWT.BORDER : SWT.BORDER
290 fDescriptionText = new Text(parent, descFlags);
291 fDescriptionText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
293 fDescriptionText.addModifyListener(listener);
295 Label patternLabel = createLabel(parent, PreferencesMessages
296 .getString("EditTemplateDialog.pattern")); //$NON-NLS-1$
297 patternLabel.setLayoutData(new GridData(
298 GridData.VERTICAL_ALIGN_BEGINNING));
299 fPatternEditor = createEditor(parent);
301 Label filler = new Label(parent, SWT.NONE);
302 filler.setLayoutData(new GridData());
304 Composite composite = new Composite(parent, SWT.NONE);
305 layout = new GridLayout();
306 layout.marginWidth = 0;
307 layout.marginHeight = 0;
308 composite.setLayout(layout);
309 composite.setLayoutData(new GridData());
311 fInsertVariableButton = new Button(composite, SWT.NONE);
312 fInsertVariableButton
313 .setLayoutData(getButtonGridData(fInsertVariableButton));
314 fInsertVariableButton.setText(PreferencesMessages
315 .getString("EditTemplateDialog.insert.variable")); //$NON-NLS-1$
316 fInsertVariableButton.addSelectionListener(new SelectionListener() {
317 public void widgetSelected(SelectionEvent e) {
318 fPatternEditor.getTextWidget().setFocus();
320 .doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
323 public void widgetDefaultSelected(SelectionEvent e) {
327 fDescriptionText.setText(fTemplate.getDescription());
328 if (fIsNameModifiable) {
329 fNameText.setText(fTemplate.getName());
330 fNameText.addModifyListener(listener);
331 fContextCombo.select(getIndex(fTemplate.getContextTypeId()));
333 fPatternEditor.getControl().setFocus();
337 applyDialogFont(parent);
341 protected void doTextWidgetChanged(Widget w) {
342 if (w == fNameText) {
343 fSuppressError = false;
344 String name = fNameText.getText();
345 fTemplate.setName(name);
347 } else if (w == fContextCombo) {
348 String name = fContextCombo.getText();
349 String contextId = getContextId(name);
350 fTemplate.setContextTypeId(contextId);
351 fTemplateProcessor.setContextType(fContextTypeRegistry
352 .getContextType(contextId));
353 } else if (w == fDescriptionText) {
354 String desc = fDescriptionText.getText();
355 fTemplate.setDescription(desc);
359 private String getContextId(String name) {
363 for (int i = 0; i < fContextTypes.length; i++) {
364 if (name.equals(fContextTypes[i][1])) {
365 return fContextTypes[i][0];
371 protected void doSourceChanged(IDocument document) {
372 String text = document.get();
373 String prefix = getPrefix();
374 fTemplate.setPattern(text.substring(prefix.length(), text.length()));
375 fValidationStatus.setOK();
376 TemplateContextType contextType = fContextTypeRegistry
377 .getContextType(fTemplate.getContextTypeId());
378 if (contextType != null) {
380 contextType.validate(text);
381 } catch (TemplateException e) {
382 fValidationStatus.setError(e.getLocalizedMessage());
390 private static GridData getButtonGridData(Button button) {
391 GridData data = new GridData(GridData.FILL_HORIZONTAL);
392 data.heightHint = SWTUtil.getButtonHeightHint(button);
397 private static Label createLabel(Composite parent, String name) {
398 Label label = new Label(parent, SWT.NULL);
400 label.setLayoutData(new GridData());
405 private static Text createText(Composite parent) {
406 Text text = new Text(parent, SWT.BORDER);
407 text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
412 private SourceViewer createEditor(Composite parent) {
413 String prefix = getPrefix();
414 IDocument document = new Document(prefix + fTemplate.getPattern());
415 JavaTextTools tools = WebUI.getDefault().getJavaTextTools();
416 tools.setupJavaDocumentPartitioner(document,
417 IPHPPartitions.PHP_PARTITIONING);
418 IPreferenceStore store = WebUI.getDefault()
419 .getCombinedPreferenceStore();
420 SourceViewer viewer = new JavaSourceViewer(parent, null, null, false,
421 SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store);
422 TemplateEditorSourceViewerConfiguration configuration = new TemplateEditorSourceViewerConfiguration(
423 tools.getColorManager(), store, null, fTemplateProcessor);
424 viewer.configure(configuration);
425 viewer.setEditable(true);
426 // XXX workaround for bug 63313 - disabling prefix until fixed.
427 // viewer.setDocument(document, prefix.length(), document.getLength() -
429 viewer.setDocument(document);
431 Font font = JFaceResources
432 .getFont(PreferenceConstants.EDITOR_TEXT_FONT);
433 viewer.getTextWidget().setFont(font);
434 new JavaSourcePreviewerUpdater(viewer, configuration, store);
436 int nLines = document.getNumberOfLines();
439 } else if (nLines > 12) {
443 Control control = viewer.getControl();
444 GridData data = new GridData(GridData.FILL_BOTH);
445 data.widthHint = convertWidthInCharsToPixels(80);
446 data.heightHint = convertHeightInCharsToPixels(nLines);
447 control.setLayoutData(data);
449 viewer.addTextListener(new ITextListener() {
450 public void textChanged(TextEvent event) {
451 if (event.getDocumentEvent() != null)
452 doSourceChanged(event.getDocumentEvent().getDocument());
456 viewer.addSelectionChangedListener(new ISelectionChangedListener() {
457 public void selectionChanged(SelectionChangedEvent event) {
458 updateSelectionDependentActions();
462 viewer.prependVerifyKeyListener(new VerifyKeyListener() {
463 public void verifyKey(VerifyEvent event) {
464 handleVerifyKeyPressed(event);
471 private String getPrefix() {
473 int idx = getIndex(fTemplate.getContextTypeId());
475 prefix = fContextTypes[idx][2];
477 prefix = ""; //$NON-NLS-1$
482 private void handleVerifyKeyPressed(VerifyEvent event) {
486 if (event.stateMask != SWT.MOD1)
489 switch (event.character) {
491 fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
497 fPatternEditor.doOperation(ITextOperationTarget.UNDO);
503 private void initializeActions() {
504 TextViewerAction action = new TextViewerAction(fPatternEditor,
507 .setText(PreferencesMessages
508 .getString("EditTemplateDialog.undo")); //$NON-NLS-1$
509 fGlobalActions.put(ITextEditorActionConstants.UNDO, action);
511 action = new TextViewerAction(fPatternEditor, SourceViewer.CUT);
512 action.setText(PreferencesMessages.getString("EditTemplateDialog.cut")); //$NON-NLS-1$
513 fGlobalActions.put(ITextEditorActionConstants.CUT, action);
515 action = new TextViewerAction(fPatternEditor, SourceViewer.COPY);
517 .setText(PreferencesMessages
518 .getString("EditTemplateDialog.copy")); //$NON-NLS-1$
519 fGlobalActions.put(ITextEditorActionConstants.COPY, action);
521 action = new TextViewerAction(fPatternEditor, SourceViewer.PASTE);
522 action.setText(PreferencesMessages
523 .getString("EditTemplateDialog.paste")); //$NON-NLS-1$
524 fGlobalActions.put(ITextEditorActionConstants.PASTE, action);
526 action = new TextViewerAction(fPatternEditor, SourceViewer.SELECT_ALL);
527 action.setText(PreferencesMessages
528 .getString("EditTemplateDialog.select.all")); //$NON-NLS-1$
529 fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action);
531 action = new TextViewerAction(fPatternEditor,
532 SourceViewer.CONTENTASSIST_PROPOSALS);
533 action.setText(PreferencesMessages
534 .getString("EditTemplateDialog.content.assist")); //$NON-NLS-1$
535 fGlobalActions.put("ContentAssistProposal", action); //$NON-NLS-1$
537 fSelectionActions.add(ITextEditorActionConstants.CUT);
538 fSelectionActions.add(ITextEditorActionConstants.COPY);
539 fSelectionActions.add(ITextEditorActionConstants.PASTE);
541 // create context menu
542 MenuManager manager = new MenuManager(null, null);
543 manager.setRemoveAllWhenShown(true);
544 manager.addMenuListener(new IMenuListener() {
545 public void menuAboutToShow(IMenuManager mgr) {
546 fillContextMenu(mgr);
550 StyledText text = fPatternEditor.getTextWidget();
551 Menu menu = manager.createContextMenu(text);
555 private void fillContextMenu(IMenuManager menu) {
556 menu.add(new GroupMarker(ITextEditorActionConstants.GROUP_UNDO));
557 menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO,
558 (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO));
560 menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
561 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT,
562 (IAction) fGlobalActions.get(ITextEditorActionConstants.CUT));
563 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT,
564 (IAction) fGlobalActions.get(ITextEditorActionConstants.COPY));
565 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT,
566 (IAction) fGlobalActions.get(ITextEditorActionConstants.PASTE));
567 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT,
568 (IAction) fGlobalActions
569 .get(ITextEditorActionConstants.SELECT_ALL));
571 menu.add(new Separator(IContextMenuConstants.GROUP_GENERATE));
572 menu.appendToGroup(IContextMenuConstants.GROUP_GENERATE,
573 (IAction) fGlobalActions.get("ContentAssistProposal")); //$NON-NLS-1$
576 protected void updateSelectionDependentActions() {
577 Iterator iterator = fSelectionActions.iterator();
578 while (iterator.hasNext())
579 updateAction((String) iterator.next());
582 protected void updateUndoAction() {
583 IAction action = (IAction) fGlobalActions
584 .get(ITextEditorActionConstants.UNDO);
585 if (action instanceof IUpdate)
586 ((IUpdate) action).update();
589 protected void updateAction(String actionId) {
590 IAction action = (IAction) fGlobalActions.get(actionId);
591 if (action instanceof IUpdate)
592 ((IUpdate) action).update();
595 private int getIndex(String contextid) {
597 if (contextid == null)
600 for (int i = 0; i < fContextTypes.length; i++) {
601 if (contextid.equals(fContextTypes[i][0])) {
608 protected void okPressed() {
612 private void updateButtons() {
615 boolean valid = fNameText == null
616 || fNameText.getText().trim().length() != 0;
618 status = new StatusInfo();
619 if (!fSuppressError) {
620 status.setError(PreferencesMessages
621 .getString("EditTemplateDialog.error.noname")); //$NON-NLS-1$
624 status = fValidationStatus;
626 updateStatus(status);
630 * @see org.eclipse.jface.window.Window#configureShell(Shell)
632 protected void configureShell(Shell newShell) {
633 super.configureShell(newShell);
634 PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
635 IJavaHelpContextIds.EDIT_TEMPLATE_DIALOG);