new version 1.0.4
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / preferences / EditTemplateDialog.java
1 /*
2  * (c) Copyright IBM Corp. 2000, 2001.
3  * All Rights Reserved.
4  */
5 package net.sourceforge.phpdt.internal.ui.preferences;
6
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Vector;
13
14 import net.sourceforge.phpdt.internal.corext.template.ContextTypeRegistry;
15 import net.sourceforge.phpdt.internal.corext.template.Template;
16 import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
17 import net.sourceforge.phpdt.internal.corext.template.TemplateTranslator;
18 import net.sourceforge.phpdt.internal.ui.dialog.StatusDialog;
19 import net.sourceforge.phpdt.internal.ui.dialog.StatusInfo;
20 import net.sourceforge.phpdt.internal.ui.text.template.TemplateVariableProcessor;
21 import net.sourceforge.phpdt.internal.ui.util.SWTUtil;
22 import net.sourceforge.phpeclipse.IPreferenceConstants;
23 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
24 import net.sourceforge.phpeclipse.phpeditor.PHPSourceViewerConfiguration;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.jface.action.Action;
27 import org.eclipse.jface.action.GroupMarker;
28 import org.eclipse.jface.action.IAction;
29 import org.eclipse.jface.action.IMenuListener;
30 import org.eclipse.jface.action.IMenuManager;
31 import org.eclipse.jface.action.MenuManager;
32 import org.eclipse.jface.action.Separator;
33 import org.eclipse.jface.preference.IPreferenceStore;
34 import org.eclipse.jface.preference.PreferenceConverter;
35 import org.eclipse.jface.resource.JFaceResources;
36 import org.eclipse.jface.text.Document;
37 import org.eclipse.jface.text.IDocument;
38 import org.eclipse.jface.text.ITextListener;
39 import org.eclipse.jface.text.ITextOperationTarget;
40 import org.eclipse.jface.text.ITextViewer;
41 import org.eclipse.jface.text.ITextViewerExtension;
42 import org.eclipse.jface.text.TextEvent;
43 import org.eclipse.jface.text.contentassist.ContentAssistant;
44 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
45 import org.eclipse.jface.text.contentassist.IContentAssistant;
46 import org.eclipse.jface.text.source.ISourceViewer;
47 import org.eclipse.jface.text.source.SourceViewer;
48 import org.eclipse.jface.viewers.ISelectionChangedListener;
49 import org.eclipse.jface.viewers.SelectionChangedEvent;
50 import org.eclipse.swt.SWT;
51 import org.eclipse.swt.custom.StyledText;
52 import org.eclipse.swt.custom.VerifyKeyListener;
53 import org.eclipse.swt.events.KeyEvent;
54 import org.eclipse.swt.events.KeyListener;
55 import org.eclipse.swt.events.ModifyEvent;
56 import org.eclipse.swt.events.ModifyListener;
57 import org.eclipse.swt.events.SelectionEvent;
58 import org.eclipse.swt.events.SelectionListener;
59 import org.eclipse.swt.events.VerifyEvent;
60 import org.eclipse.swt.graphics.Color;
61 import org.eclipse.swt.graphics.Font;
62 import org.eclipse.swt.graphics.RGB;
63 import org.eclipse.swt.layout.GridData;
64 import org.eclipse.swt.layout.GridLayout;
65 import org.eclipse.swt.widgets.Button;
66 import org.eclipse.swt.widgets.Combo;
67 import org.eclipse.swt.widgets.Composite;
68 import org.eclipse.swt.widgets.Control;
69 import org.eclipse.swt.widgets.Display;
70 import org.eclipse.swt.widgets.Label;
71 import org.eclipse.swt.widgets.Menu;
72 import org.eclipse.swt.widgets.Shell;
73 import org.eclipse.swt.widgets.Text;
74 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
75 import org.eclipse.ui.texteditor.IUpdate;
76
77 /**
78  * Dialog to edit a template.
79  */
80 public class EditTemplateDialog extends StatusDialog {
81
82         private static class SimpleJavaSourceViewerConfiguration extends PHPSourceViewerConfiguration {
83
84                 private final IContentAssistProcessor fProcessor;
85
86         //      SimpleJavaSourceViewerConfiguration(JavaTextTools tools, ITextEditor editor, IContentAssistProcessor processor) {
87                 SimpleJavaSourceViewerConfiguration(IContentAssistProcessor processor) {        
88       super();
89                         fProcessor= processor;
90                 }
91                 
92                 /*
93                  * @see SourceViewerConfiguration#getContentAssistant(ISourceViewer)
94                  */
95                 public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
96
97                         IPreferenceStore store= PHPeclipsePlugin.getDefault().getPreferenceStore();
98
99                         ContentAssistant assistant= new ContentAssistant();
100                         assistant.setContentAssistProcessor(fProcessor, IDocument.DEFAULT_CONTENT_TYPE);
101                                 // Register the same processor for strings and single line comments to get code completion at the start of those partitions.
102 //                      assistant.setContentAssistProcessor(fProcessor, JavaPartitionScanner.JAVA_STRING);
103 //                      assistant.setContentAssistProcessor(fProcessor, JavaPartitionScanner.JAVA_SINGLE_LINE_COMMENT);
104 //                      
105 //                      assistant.setContentAssistProcessor(fProcessor, JavaPartitionScanner.JAVA_DOC);
106
107 //                      assistant.enableAutoInsert(store.getBoolean(ContentAssistPreference.AUTOINSERT));
108 //                      assistant.enableAutoActivation(store.getBoolean(ContentAssistPreference.AUTOACTIVATION));
109 //                      assistant.setAutoActivationDelay(store.getInt(ContentAssistPreference.AUTOACTIVATION_DELAY));
110                         assistant.setProposalPopupOrientation(assistant.PROPOSAL_OVERLAY);
111                         assistant.setContextInformationPopupOrientation(assistant.CONTEXT_INFO_ABOVE);
112 //                      assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
113
114                         Display display= sourceViewer.getTextWidget().getDisplay();
115                         
116                         Color background= createColor(store, IPreferenceConstants.PROPOSALS_BACKGROUND, display);                       
117                         assistant.setContextInformationPopupBackground(background);
118                         assistant.setContextSelectorBackground(background);
119                         assistant.setProposalSelectorBackground(background);
120
121                         Color foreground= createColor(store, IPreferenceConstants.PROPOSALS_FOREGROUND, display);
122                         assistant.setContextInformationPopupForeground(foreground);
123                         assistant.setContextSelectorForeground(foreground);
124                         assistant.setProposalSelectorForeground(foreground);
125                         
126                         return assistant;
127                 }       
128
129                 /**
130                  * Creates a color from the information stored in the given preference store.
131                  * Returns <code>null</code> if there is no such information available.
132                  */
133                 private Color createColor(IPreferenceStore store, String key, Display display) {
134                 
135                         RGB rgb= null;          
136                         
137                         if (store.contains(key)) {
138                                 
139                                 if (store.isDefault(key))
140                                         rgb= PreferenceConverter.getDefaultColor(store, key);
141                                 else
142                                         rgb= PreferenceConverter.getColor(store, key);
143                         
144                                 if (rgb != null)
145                                         return new Color(display, rgb);
146                         }
147                         
148                         return null;
149                 }       
150         }
151
152         private static class TextViewerAction extends Action implements IUpdate {
153         
154                 private int fOperationCode= -1;
155                 private ITextOperationTarget fOperationTarget;
156         
157                 public TextViewerAction(ITextViewer viewer, int operationCode) {
158                         fOperationCode= operationCode;
159                         fOperationTarget= viewer.getTextOperationTarget();
160                         update();
161                 }
162         
163                 /**
164                  * Updates the enabled state of the action.
165                  * Fires a property change if the enabled state changes.
166                  * 
167                  * @see Action#firePropertyChange(String, Object, Object)
168                  */
169                 public void update() {
170         
171                         boolean wasEnabled= isEnabled();
172                         boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode));
173                         setEnabled(isEnabled);
174         
175                         if (wasEnabled != isEnabled) {
176                                 firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE);
177                         }
178                 }
179                 
180                 /**
181                  * @see Action#run()
182                  */
183                 public void run() {
184                         if (fOperationCode != -1 && fOperationTarget != null) {
185                                 fOperationTarget.doOperation(fOperationCode);
186                         }
187                 }
188         }       
189
190         private final Template fTemplate;
191         
192         private Text fNameText;
193         private Text fDescriptionText;
194         private Combo fContextCombo;
195         private SourceViewer fPatternEditor;    
196         private Button fInsertVariableButton;
197
198         private TemplateTranslator fTranslator= new TemplateTranslator();       
199         private boolean fSuppressError= true; // #4354  
200         private Map fGlobalActions= new HashMap(10);
201         private List fSelectionActions = new ArrayList(3);      
202         private Vector fContextTypes= new Vector();
203         
204         private final TemplateVariableProcessor fProcessor= new TemplateVariableProcessor();
205                 
206         public EditTemplateDialog(Shell parent, Template template, boolean edit) {
207                 super(parent);
208                 
209                 setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE);
210                 
211                 String title= edit
212                         ? TemplateMessages.getString("EditTemplateDialog.title.edit") //$NON-NLS-1$
213                         : TemplateMessages.getString("EditTemplateDialog.title.new"); //$NON-NLS-1$
214                 setTitle(title);
215
216                 fTemplate= template;
217                 
218                 ContextTypeRegistry registry= ContextTypeRegistry.getInstance();
219                 for (Iterator iterator= registry.iterator(); iterator.hasNext(); )
220                         fContextTypes.add(iterator.next());
221
222                 if (fContextTypes.size() > 0)
223                         fProcessor.setContextType(ContextTypeRegistry.getInstance().getContextType((String) fContextTypes.get(0)));
224         }
225         
226         /*
227          * @see Dialog#createDialogArea(Composite)
228          */
229         protected Control createDialogArea(Composite ancestor) {
230                 Composite parent= new Composite(ancestor, SWT.NONE);
231                 GridLayout layout= new GridLayout();
232                 layout.numColumns= 2;
233                 parent.setLayout(layout);
234                 parent.setLayoutData(new GridData(GridData.FILL_BOTH));
235                 
236                 createLabel(parent, TemplateMessages.getString("EditTemplateDialog.name")); //$NON-NLS-1$       
237                 
238                 Composite composite= new Composite(parent, SWT.NONE);
239                 composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
240                 layout= new GridLayout();               
241                 layout.numColumns= 3;
242                 layout.marginWidth= 0;
243                 layout.marginHeight= 0;
244                 composite.setLayout(layout);
245
246                 fNameText= createText(composite);
247                 fNameText.addModifyListener(new ModifyListener() {
248                         public void modifyText(ModifyEvent e) {
249                                 if (fSuppressError && (fNameText.getText().trim().length() != 0))
250                                         fSuppressError= false;
251
252                                 updateButtons();
253                         }
254                 });
255
256                 createLabel(composite, TemplateMessages.getString("EditTemplateDialog.context")); //$NON-NLS-1$         
257                 fContextCombo= new Combo(composite, SWT.READ_ONLY);
258
259                 for (Iterator iterator= fContextTypes.iterator(); iterator.hasNext(); )
260                         fContextCombo.add((String) iterator.next());
261
262                 fContextCombo.addModifyListener(new ModifyListener() {
263                         public void modifyText(ModifyEvent e) {
264                                 String name= fContextCombo.getText();
265                                 fProcessor.setContextType(ContextTypeRegistry.getInstance().getContextType(name));                              
266                         }
267                 });
268                 
269                 createLabel(parent, TemplateMessages.getString("EditTemplateDialog.description")); //$NON-NLS-1$                
270                 fDescriptionText= createText(parent);
271
272                 Label patternLabel= createLabel(parent, TemplateMessages.getString("EditTemplateDialog.pattern")); //$NON-NLS-1$
273                 patternLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
274                 fPatternEditor= createEditor(parent);
275                 
276                 Label filler= new Label(parent, SWT.NONE);              
277                 filler.setLayoutData(new GridData());
278                 
279                 composite= new Composite(parent, SWT.NONE);
280                 layout= new GridLayout();               
281                 layout.marginWidth= 0;
282                 layout.marginHeight= 0;
283                 composite.setLayout(layout);            
284                 composite.setLayoutData(new GridData());
285                 
286                 fInsertVariableButton= new Button(composite, SWT.NONE);
287                 fInsertVariableButton.setLayoutData(getButtonGridData(fInsertVariableButton));
288                 fInsertVariableButton.setText(TemplateMessages.getString("EditTemplateDialog.insert.variable")); //$NON-NLS-1$
289                 fInsertVariableButton.addSelectionListener(new SelectionListener() {
290                         public void widgetSelected(SelectionEvent e) {
291                                 fPatternEditor.getTextWidget().setFocus();
292                                 fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);                      
293                         }
294
295                         public void widgetDefaultSelected(SelectionEvent e) {}
296                 });
297
298                 fNameText.setText(fTemplate.getName());
299                 fDescriptionText.setText(fTemplate.getDescription());
300                 fContextCombo.select(getIndex(fTemplate.getContextTypeName()));
301
302                 initializeActions();
303
304                 return composite;
305         }
306
307         private static GridData getButtonGridData(Button button) {
308                 GridData data= new GridData(GridData.FILL_HORIZONTAL);
309                 data.heightHint= SWTUtil.getButtonHeigthHint(button);
310         
311                 return data;
312         }
313
314         private static Label createLabel(Composite parent, String name) {
315                 Label label= new Label(parent, SWT.NULL);
316                 label.setText(name);
317                 label.setLayoutData(new GridData());
318
319                 return label;
320         }
321
322         private static Text createText(Composite parent) {
323                 Text text= new Text(parent, SWT.BORDER);
324                 text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));             
325                 
326                 return text;
327         }
328
329         private SourceViewer createEditor(Composite parent) {
330                 SourceViewer viewer= new SourceViewer(parent, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
331         //      JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools();
332                 IDocument document= new Document(fTemplate.getPattern());
333         //      IDocumentPartitioner partitioner= tools.createDocumentPartitioner();
334         //      document.setDocumentPartitioner(partitioner);
335         //      partitioner.connect(document);          
336         //      viewer.configure(new SimpleJavaSourceViewerConfiguration(tools, null, fProcessor));
337                 viewer.configure(new SimpleJavaSourceViewerConfiguration(fProcessor));
338     viewer.setEditable(true);
339                 viewer.setDocument(document);
340                 
341                 Font font= JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT);
342                 viewer.getTextWidget().setFont(font);
343                 
344                 Control control= viewer.getControl();
345                 GridData data= new GridData(GridData.FILL_BOTH);
346                 data.widthHint= convertWidthInCharsToPixels(60);
347                 data.heightHint= convertHeightInCharsToPixels(5);
348                 control.setLayoutData(data);
349                 
350                 viewer.addTextListener(new ITextListener() {
351                         public void textChanged(TextEvent event) {
352                             try {
353                                         fTranslator.translate(event.getDocumentEvent().getDocument().get());
354                             } catch (CoreException e) {
355                                 PHPeclipsePlugin.log(e);
356                             }
357                                 
358                                 updateUndoAction();
359                                 updateButtons();
360                         }
361                 });
362
363                 viewer.addSelectionChangedListener(new ISelectionChangedListener() {                    
364                         public void selectionChanged(SelectionChangedEvent event) {
365                                 updateSelectionDependentActions();
366                         }
367                 });
368
369                 if (viewer instanceof ITextViewerExtension) {
370                          ((ITextViewerExtension) viewer).prependVerifyKeyListener(new VerifyKeyListener() {
371                                 public void verifyKey(VerifyEvent event) {
372                                         handleVerifyKeyPressed(event);
373                                 }
374                         });
375                 } else {                        
376                         viewer.getTextWidget().addKeyListener(new KeyListener() {
377                                 public void keyPressed(KeyEvent e) {
378                                         handleKeyPressed(e);
379                                 }
380         
381                                 public void keyReleased(KeyEvent e) {}
382                         });
383                 }
384                 
385                 return viewer;
386         }
387
388         private void handleKeyPressed(KeyEvent event) {
389                 if (event.stateMask != SWT.CTRL)
390                         return;
391                         
392                 switch (event.character) {
393                         case ' ':
394                                 fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
395                                 break;
396
397                         // CTRL-Z
398                         case (int) 'z' - (int) 'a' + 1:
399                                 fPatternEditor.doOperation(ITextOperationTarget.UNDO);
400                                 break;                          
401                 }
402         }
403
404         private void handleVerifyKeyPressed(VerifyEvent event) {
405                 if (!event.doit)
406                         return;
407
408                 if (event.stateMask != SWT.CTRL)
409                         return;
410                         
411                 switch (event.character) {
412                         case ' ':
413                                 fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
414                                 event.doit= false;
415                                 break;
416
417                         // CTRL-Z
418                         case (int) 'z' - (int) 'a' + 1:
419                                 fPatternEditor.doOperation(ITextOperationTarget.UNDO);
420                                 event.doit= false;
421                                 break;                          
422                 }
423         }
424
425         private void initializeActions() {
426                 TextViewerAction action= new TextViewerAction(fPatternEditor, fPatternEditor.UNDO);
427                 action.setText(TemplateMessages.getString("EditTemplateDialog.undo")); //$NON-NLS-1$
428                 fGlobalActions.put(ITextEditorActionConstants.UNDO, action);
429
430                 action= new TextViewerAction(fPatternEditor, fPatternEditor.CUT);
431                 action.setText(TemplateMessages.getString("EditTemplateDialog.cut")); //$NON-NLS-1$
432                 fGlobalActions.put(ITextEditorActionConstants.CUT, action);
433
434                 action= new TextViewerAction(fPatternEditor, fPatternEditor.COPY);
435                 action.setText(TemplateMessages.getString("EditTemplateDialog.copy")); //$NON-NLS-1$
436                 fGlobalActions.put(ITextEditorActionConstants.COPY, action);
437
438                 action= new TextViewerAction(fPatternEditor, fPatternEditor.PASTE);
439                 action.setText(TemplateMessages.getString("EditTemplateDialog.paste")); //$NON-NLS-1$
440                 fGlobalActions.put(ITextEditorActionConstants.PASTE, action);
441
442                 action= new TextViewerAction(fPatternEditor, fPatternEditor.SELECT_ALL);
443                 action.setText(TemplateMessages.getString("EditTemplateDialog.select.all")); //$NON-NLS-1$
444                 fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action);
445
446                 action= new TextViewerAction(fPatternEditor, fPatternEditor.CONTENTASSIST_PROPOSALS);
447                 action.setText(TemplateMessages.getString("EditTemplateDialog.content.assist")); //$NON-NLS-1$
448                 fGlobalActions.put("ContentAssistProposal", action); //$NON-NLS-1$
449
450                 fSelectionActions.add(ITextEditorActionConstants.CUT);
451                 fSelectionActions.add(ITextEditorActionConstants.COPY);
452                 fSelectionActions.add(ITextEditorActionConstants.PASTE);
453                 
454                 // create context menu
455                 MenuManager manager= new MenuManager(null, null);
456                 manager.setRemoveAllWhenShown(true);
457                 manager.addMenuListener(new IMenuListener() {
458                         public void menuAboutToShow(IMenuManager mgr) {
459                                 fillContextMenu(mgr);
460                         }
461                 });
462
463                 StyledText text= fPatternEditor.getTextWidget();                
464                 Menu menu= manager.createContextMenu(text);
465                 text.setMenu(menu);
466         }
467
468         private void fillContextMenu(IMenuManager menu) {
469                 menu.add(new GroupMarker(ITextEditorActionConstants.GROUP_UNDO));
470                 menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO));
471                 
472                 menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));         
473                 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.CUT));
474                 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.COPY));
475                 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.PASTE));
476                 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.SELECT_ALL));
477
478         //      menu.add(new Separator(IContextMenuConstants.GROUP_GENERATE));
479         //      menu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, (IAction) fGlobalActions.get("ContentAssistProposal")); //$NON-NLS-1$
480         }
481
482         protected void updateSelectionDependentActions() {
483                 Iterator iterator= fSelectionActions.iterator();
484                 while (iterator.hasNext())
485                         updateAction((String)iterator.next());          
486         }
487
488         protected void updateUndoAction() {
489                 IAction action= (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO);
490                 if (action instanceof IUpdate)
491                         ((IUpdate) action).update();
492         }
493
494         protected void updateAction(String actionId) {
495                 IAction action= (IAction) fGlobalActions.get(actionId);
496                 if (action instanceof IUpdate)
497                         ((IUpdate) action).update();
498         }
499
500         private int getIndex(String context) {
501                 ContextTypeRegistry registry= ContextTypeRegistry.getInstance();
502                 registry.getContextType(context);
503                 
504                 if (context == null)
505                         return -1;
506                         
507                 return fContextTypes.indexOf(context);
508         }
509         
510         protected void okPressed() {
511                 fTemplate.setName(fNameText.getText());
512                 fTemplate.setDescription(fDescriptionText.getText());
513                 fTemplate.setContext(fContextCombo.getText());
514                 fTemplate.setPattern(fPatternEditor.getTextWidget().getText());
515                 
516                 super.okPressed();
517         }
518         
519         private void updateButtons() {          
520                 boolean valid= fNameText.getText().trim().length() != 0;
521
522                 StatusInfo status= new StatusInfo();
523                 
524                 if (!valid) {
525                         if (fSuppressError)
526                                 status.setError(""); //$NON-NLS-1$                                                      
527                         else
528                                 status.setError(TemplateMessages.getString("EditTemplateDialog.error.noname")); //$NON-NLS-1$
529                 } else if (fTranslator.getErrorMessage() != null) {
530                         status.setError(fTranslator.getErrorMessage()); 
531                 }
532
533                 updateStatus(status);
534         }
535
536         /*
537          * @see org.eclipse.jface.window.Window#configureShell(Shell)
538          */
539         protected void configureShell(Shell newShell) {
540                 super.configureShell(newShell);
541 //              WorkbenchHelp.setHelp(newShell, IJavaHelpContextIds.EDIT_TEMPLATE_DIALOG);
542         }
543
544
545 }