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