1 11 package org.eclipse.jdt.internal.ui.preferences; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 19 import org.eclipse.swt.SWT; 20 import org.eclipse.swt.custom.StyledText; 21 import org.eclipse.swt.custom.VerifyKeyListener; 22 import org.eclipse.swt.events.FocusEvent; 23 import org.eclipse.swt.events.FocusListener; 24 import org.eclipse.swt.events.ModifyEvent; 25 import org.eclipse.swt.events.ModifyListener; 26 import org.eclipse.swt.events.SelectionEvent; 27 import org.eclipse.swt.events.SelectionListener; 28 import org.eclipse.swt.events.VerifyEvent; 29 import org.eclipse.swt.graphics.Font; 30 import org.eclipse.swt.layout.GridData; 31 import org.eclipse.swt.layout.GridLayout; 32 import org.eclipse.swt.widgets.Button; 33 import org.eclipse.swt.widgets.Combo; 34 import org.eclipse.swt.widgets.Composite; 35 import org.eclipse.swt.widgets.Control; 36 import org.eclipse.swt.widgets.Label; 37 import org.eclipse.swt.widgets.Menu; 38 import org.eclipse.swt.widgets.Shell; 39 import org.eclipse.swt.widgets.Text; 40 import org.eclipse.swt.widgets.Widget; 41 42 import org.eclipse.jface.action.Action; 43 import org.eclipse.jface.action.GroupMarker; 44 import org.eclipse.jface.action.IAction; 45 import org.eclipse.jface.action.IMenuListener; 46 import org.eclipse.jface.action.IMenuManager; 47 import org.eclipse.jface.action.MenuManager; 48 import org.eclipse.jface.action.Separator; 49 import org.eclipse.jface.dialogs.IDialogConstants; 50 import org.eclipse.jface.dialogs.IDialogSettings; 51 import org.eclipse.jface.dialogs.StatusDialog; 52 import org.eclipse.jface.preference.IPreferenceStore; 53 import org.eclipse.jface.resource.JFaceResources; 54 import org.eclipse.jface.viewers.ISelectionChangedListener; 55 import org.eclipse.jface.viewers.SelectionChangedEvent; 56 57 import org.eclipse.jface.text.BadLocationException; 58 import org.eclipse.jface.text.Document; 59 import org.eclipse.jface.text.IDocument; 60 import org.eclipse.jface.text.IRegion; 61 import org.eclipse.jface.text.ITextListener; 62 import org.eclipse.jface.text.ITextOperationTarget; 63 import org.eclipse.jface.text.ITextViewer; 64 import org.eclipse.jface.text.TextEvent; 65 import org.eclipse.jface.text.source.ISourceViewer; 66 import org.eclipse.jface.text.source.SourceViewer; 67 import org.eclipse.jface.text.templates.ContextTypeRegistry; 68 import org.eclipse.jface.text.templates.Template; 69 import org.eclipse.jface.text.templates.TemplateContextType; 70 import org.eclipse.jface.text.templates.TemplateException; 71 72 import org.eclipse.ui.PlatformUI; 73 import org.eclipse.ui.texteditor.ITextEditorActionConstants; 74 import org.eclipse.ui.texteditor.IUpdate; 75 76 import org.eclipse.jdt.internal.corext.template.java.JavaDocContextType; 77 78 import org.eclipse.jdt.ui.IContextMenuConstants; 79 import org.eclipse.jdt.ui.PreferenceConstants; 80 import org.eclipse.jdt.ui.text.IJavaPartitions; 81 import org.eclipse.jdt.ui.text.JavaTextTools; 82 83 import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; 84 import org.eclipse.jdt.internal.ui.JavaPlugin; 85 import org.eclipse.jdt.internal.ui.dialogs.StatusInfo; 86 import org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer; 87 import org.eclipse.jdt.internal.ui.text.template.preferences.TemplateVariableProcessor; 88 89 92 class EditTemplateDialog extends StatusDialog { 93 94 private static class TextViewerAction extends Action implements IUpdate { 95 96 private int fOperationCode= -1; 97 private ITextOperationTarget fOperationTarget; 98 99 105 public TextViewerAction(ITextViewer viewer, int operationCode) { 106 fOperationCode= operationCode; 107 fOperationTarget= viewer.getTextOperationTarget(); 108 update(); 109 } 110 111 117 public void update() { 118 119 boolean wasEnabled= isEnabled(); 120 boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode)); 121 setEnabled(isEnabled); 122 123 if (wasEnabled != isEnabled) { 124 firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE); 125 } 126 } 127 128 131 public void run() { 132 if (fOperationCode != -1 && fOperationTarget != null) { 133 fOperationTarget.doOperation(fOperationCode); 134 } 135 } 136 } 137 138 private Template fTemplate; 139 140 private Text fNameText; 141 private Text fDescriptionText; 142 private Combo fContextCombo; 143 private SourceViewer fPatternEditor; 144 private Button fInsertVariableButton; 145 private Button fAutoInsertCheckbox; 146 private boolean fIsNameModifiable; 147 148 private StatusInfo fValidationStatus; 149 private boolean fSuppressError= true; private Map fGlobalActions= new HashMap (10); 151 private List fSelectionActions = new ArrayList (3); 152 private String [][] fContextTypes; 153 154 private ContextTypeRegistry fContextTypeRegistry; 155 156 private final TemplateVariableProcessor fTemplateProcessor= new TemplateVariableProcessor(); 157 158 167 public EditTemplateDialog(Shell parent, Template template, boolean edit, boolean isNameModifiable, ContextTypeRegistry registry) { 168 super(parent); 169 170 setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE); 171 172 String title= edit 173 ? PreferencesMessages.EditTemplateDialog_title_edit 174 : PreferencesMessages.EditTemplateDialog_title_new; 175 setTitle(title); 176 177 fTemplate= template; 178 fIsNameModifiable= isNameModifiable; 179 180 String delim= new Document().getLegalLineDelimiters()[0]; 181 182 List contexts= new ArrayList (); 183 for (Iterator it= registry.contextTypes(); it.hasNext();) { 184 TemplateContextType type= (TemplateContextType) it.next(); 185 if (type.getId().equals("javadoc")) contexts.add(new String [] { type.getId(), type.getName(), "/**" + delim }); else 188 contexts.add(0, new String [] { type.getId(), type.getName(), "" }); } 190 fContextTypes= (String [][]) contexts.toArray(new String [contexts.size()][]); 191 192 fValidationStatus= new StatusInfo(); 193 194 fContextTypeRegistry= registry; 195 196 TemplateContextType type= fContextTypeRegistry.getContextType(template.getContextTypeId()); 197 fTemplateProcessor.setContextType(type); 198 } 199 200 203 public void create() { 204 super.create(); 205 updateStatusAndButtons(); 206 getButton(IDialogConstants.OK_ID).setEnabled(getStatus().isOK()); 207 } 208 209 212 protected Control createDialogArea(Composite ancestor) { 213 Composite parent= new Composite(ancestor, SWT.NONE); 214 GridLayout layout= new GridLayout(); 215 layout.numColumns= 2; 216 parent.setLayout(layout); 217 parent.setLayoutData(new GridData(GridData.FILL_BOTH)); 218 219 ModifyListener listener= new ModifyListener() { 220 public void modifyText(ModifyEvent e) { 221 doTextWidgetChanged(e.widget); 222 } 223 }; 224 225 if (fIsNameModifiable) { 226 createLabel(parent, PreferencesMessages.EditTemplateDialog_name); 227 228 Composite composite= new Composite(parent, SWT.NONE); 229 composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 230 layout= new GridLayout(); 231 layout.numColumns= 4; 232 layout.marginWidth= 0; 233 layout.marginHeight= 0; 234 composite.setLayout(layout); 235 236 fNameText= createText(composite); 237 fNameText.addFocusListener(new FocusListener() { 238 239 public void focusGained(FocusEvent e) { 240 } 241 242 public void focusLost(FocusEvent e) { 243 if (fSuppressError) { 244 fSuppressError= false; 245 updateStatusAndButtons(); 246 } 247 } 248 }); 249 250 createLabel(composite, PreferencesMessages.EditTemplateDialog_context); 251 fContextCombo= new Combo(composite, SWT.READ_ONLY); 252 253 for (int i= 0; i < fContextTypes.length; i++) { 254 fContextCombo.add(fContextTypes[i][1]); 255 } 256 257 fContextCombo.addModifyListener(listener); 258 259 fAutoInsertCheckbox= createCheckbox(composite, PreferencesMessages.EditTemplateDialog_autoinsert); 260 fAutoInsertCheckbox.setSelection(fTemplate.isAutoInsertable()); 261 } 262 263 createLabel(parent, PreferencesMessages.EditTemplateDialog_description); 264 265 int descFlags= fIsNameModifiable ? SWT.BORDER : SWT.BORDER | SWT.READ_ONLY; 266 fDescriptionText= new Text(parent, descFlags ); 267 fDescriptionText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 268 269 fDescriptionText.addModifyListener(listener); 270 271 Label patternLabel= createLabel(parent, PreferencesMessages.EditTemplateDialog_pattern); 272 patternLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); 273 fPatternEditor= createEditor(parent); 274 275 Label filler= new Label(parent, SWT.NONE); 276 filler.setLayoutData(new GridData()); 277 278 Composite composite= new Composite(parent, SWT.NONE); 279 layout= new GridLayout(); 280 layout.marginWidth= 0; 281 layout.marginHeight= 0; 282 composite.setLayout(layout); 283 composite.setLayoutData(new GridData()); 284 285 fInsertVariableButton= new Button(composite, SWT.NONE); 286 fInsertVariableButton.setLayoutData(getButtonGridData(fInsertVariableButton)); 287 fInsertVariableButton.setText(PreferencesMessages.EditTemplateDialog_insert_variable); 288 fInsertVariableButton.addSelectionListener(new SelectionListener() { 289 public void widgetSelected(SelectionEvent e) { 290 fPatternEditor.getTextWidget().setFocus(); 291 fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); 292 } 293 294 public void widgetDefaultSelected(SelectionEvent e) {} 295 }); 296 297 fDescriptionText.setText(fTemplate.getDescription()); 298 if (fIsNameModifiable) { 299 fNameText.setText(fTemplate.getName()); 300 fNameText.addModifyListener(listener); 301 fContextCombo.select(getIndex(fTemplate.getContextTypeId())); 302 } else { 303 fPatternEditor.getControl().setFocus(); 304 } 305 initializeActions(); 306 307 applyDialogFont(parent); 308 return composite; 309 } 310 311 protected void doTextWidgetChanged(Widget w) { 312 if (w == fNameText) { 313 fSuppressError= false; 314 updateStatusAndButtons(); 315 } else if (w == fContextCombo) { 316 String contextId= getContextId(); 317 fTemplateProcessor.setContextType(fContextTypeRegistry.getContextType(contextId)); 318 IDocument document= fPatternEditor.getDocument(); 319 String prefix= getPrefix(); 320 document.set(prefix + getPattern()); 321 fPatternEditor.setVisibleRegion(prefix.length(), document.getLength() - prefix.length()); 322 updateStatusAndButtons(); 323 } else if (w == fDescriptionText) { 324 } 326 } 327 328 private String getContextId() { 329 if (fContextCombo != null && !fContextCombo.isDisposed()) { 330 String name= fContextCombo.getText(); 331 for (int i= 0; i < fContextTypes.length; i++) { 332 if (name.equals(fContextTypes[i][1])) { 333 return fContextTypes[i][0]; 334 } 335 } 336 } 337 338 return fTemplate.getContextTypeId(); 339 } 340 341 protected void doSourceChanged(IDocument document) { 342 String text= document.get(); 343 fValidationStatus.setOK(); 344 TemplateContextType contextType= fContextTypeRegistry.getContextType(getContextId()); 345 if (contextType != null) { 346 try { 347 contextType.validate(text); 348 } catch (TemplateException e) { 349 fValidationStatus.setError(e.getLocalizedMessage()); 350 } 351 } 352 353 updateUndoAction(); 354 updateStatusAndButtons(); 355 } 356 357 private static GridData getButtonGridData(Button button) { 358 GridData data= new GridData(GridData.FILL_HORIZONTAL); 359 return data; 360 } 361 362 private static Label createLabel(Composite parent, String name) { 363 Label label= new Label(parent, SWT.NULL); 364 label.setText(name); 365 label.setLayoutData(new GridData()); 366 367 return label; 368 } 369 370 private static Button createCheckbox(Composite parent, String name) { 371 Button button= new Button(parent, SWT.CHECK); 372 button.setText(name); 373 button.setLayoutData(new GridData()); 374 375 return button; 376 } 377 378 private static Text createText(Composite parent) { 379 Text text= new Text(parent, SWT.BORDER); 380 text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 381 382 return text; 383 } 384 385 private SourceViewer createEditor(Composite parent) { 386 String prefix= getPrefix(); 387 IDocument document= new Document(prefix + fTemplate.getPattern()); 388 JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools(); 389 tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING); 390 IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore(); 391 SourceViewer viewer= new JavaSourceViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, store); 392 CodeTemplateSourceViewerConfiguration configuration= new CodeTemplateSourceViewerConfiguration(tools.getColorManager(), store, null, fTemplateProcessor); 393 viewer.configure(configuration); 394 viewer.setEditable(true); 395 viewer.setDocument(document, prefix.length(), document.getLength() - prefix.length()); 396 397 Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT); 398 viewer.getTextWidget().setFont(font); 399 new JavaSourcePreviewerUpdater(viewer, configuration, store); 400 401 int nLines= document.getNumberOfLines(); 402 if (nLines < 5) { 403 nLines= 5; 404 } else if (nLines > 12) { 405 nLines= 12; 406 } 407 408 Control control= viewer.getControl(); 409 GridData data= new GridData(GridData.FILL_BOTH); 410 data.widthHint= convertWidthInCharsToPixels(80); 411 data.heightHint= convertHeightInCharsToPixels(nLines); 412 control.setLayoutData(data); 413 414 viewer.addTextListener(new ITextListener() { 415 public void textChanged(TextEvent event) { 416 if (event .getDocumentEvent() != null) 417 doSourceChanged(event.getDocumentEvent().getDocument()); 418 } 419 }); 420 421 viewer.addSelectionChangedListener(new ISelectionChangedListener() { 422 public void selectionChanged(SelectionChangedEvent event) { 423 updateSelectionDependentActions(); 424 } 425 }); 426 427 viewer.prependVerifyKeyListener(new VerifyKeyListener() { 428 public void verifyKey(VerifyEvent event) { 429 handleVerifyKeyPressed(event); 430 } 431 }); 432 433 return viewer; 434 } 435 436 private String getPrefix() { 437 String id= getContextId(); 438 int idx= getIndex(id); 439 if (idx != -1) 440 return fContextTypes[idx][2]; 441 else 442 return ""; } 444 445 private void handleVerifyKeyPressed(VerifyEvent event) { 446 if (!event.doit) 447 return; 448 449 if (event.stateMask != SWT.MOD1) 450 return; 451 452 switch (event.character) { 453 case ' ': 454 fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); 455 event.doit= false; 456 break; 457 458 case 'z' - 'a' + 1: 460 fPatternEditor.doOperation(ITextOperationTarget.UNDO); 461 event.doit= false; 462 break; 463 } 464 } 465 466 private void initializeActions() { 467 TextViewerAction action= new TextViewerAction(fPatternEditor, ITextOperationTarget.UNDO); 468 action.setText(PreferencesMessages.EditTemplateDialog_undo); 469 fGlobalActions.put(ITextEditorActionConstants.UNDO, action); 470 471 action= new TextViewerAction(fPatternEditor, ITextOperationTarget.CUT); 472 action.setText(PreferencesMessages.EditTemplateDialog_cut); 473 fGlobalActions.put(ITextEditorActionConstants.CUT, action); 474 475 action= new TextViewerAction(fPatternEditor, ITextOperationTarget.COPY); 476 action.setText(PreferencesMessages.EditTemplateDialog_copy); 477 fGlobalActions.put(ITextEditorActionConstants.COPY, action); 478 479 action= new TextViewerAction(fPatternEditor, ITextOperationTarget.PASTE); 480 action.setText(PreferencesMessages.EditTemplateDialog_paste); 481 fGlobalActions.put(ITextEditorActionConstants.PASTE, action); 482 483 action= new TextViewerAction(fPatternEditor, ITextOperationTarget.SELECT_ALL); 484 action.setText(PreferencesMessages.EditTemplateDialog_select_all); 485 fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action); 486 487 action= new TextViewerAction(fPatternEditor, ISourceViewer.CONTENTASSIST_PROPOSALS); 488 action.setText(PreferencesMessages.EditTemplateDialog_content_assist); 489 fGlobalActions.put("ContentAssistProposal", action); 491 fSelectionActions.add(ITextEditorActionConstants.CUT); 492 fSelectionActions.add(ITextEditorActionConstants.COPY); 493 fSelectionActions.add(ITextEditorActionConstants.PASTE); 494 495 MenuManager manager= new MenuManager(null, null); 497 manager.setRemoveAllWhenShown(true); 498 manager.addMenuListener(new IMenuListener() { 499 public void menuAboutToShow(IMenuManager mgr) { 500 fillContextMenu(mgr); 501 } 502 }); 503 504 StyledText text= fPatternEditor.getTextWidget(); 505 Menu menu= manager.createContextMenu(text); 506 text.setMenu(menu); 507 } 508 509 private void fillContextMenu(IMenuManager menu) { 510 menu.add(new GroupMarker(ITextEditorActionConstants.GROUP_UNDO)); 511 menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO)); 512 513 menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT)); 514 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.CUT)); 515 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.COPY)); 516 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.PASTE)); 517 menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.SELECT_ALL)); 518 519 menu.add(new Separator(IContextMenuConstants.GROUP_GENERATE)); 520 menu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, (IAction) fGlobalActions.get("ContentAssistProposal")); } 522 523 protected void updateSelectionDependentActions() { 524 Iterator iterator= fSelectionActions.iterator(); 525 while (iterator.hasNext()) 526 updateAction((String )iterator.next()); 527 } 528 529 protected void updateUndoAction() { 530 IAction action= (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO); 531 if (action instanceof IUpdate) 532 ((IUpdate) action).update(); 533 } 534 535 protected void updateAction(String actionId) { 536 IAction action= (IAction) fGlobalActions.get(actionId); 537 if (action instanceof IUpdate) 538 ((IUpdate) action).update(); 539 } 540 541 private int getIndex(String contextid) { 542 543 if (contextid == null) 544 return -1; 545 546 for (int i= 0; i < fContextTypes.length; i++) { 547 if (contextid.equals(fContextTypes[i][0])) { 548 return i; 549 } 550 } 551 return -1; 552 } 553 554 protected void okPressed() { 555 String name= fNameText == null ? fTemplate.getName() : fNameText.getText(); 556 boolean isAutoInsertable= fAutoInsertCheckbox != null && fAutoInsertCheckbox.getSelection(); 557 fTemplate= new Template(name, fDescriptionText.getText(), getContextId(), getPattern(), isAutoInsertable); 558 super.okPressed(); 559 } 560 561 private void updateStatusAndButtons() { 562 StatusInfo status= fValidationStatus; 563 boolean isEmpty= fNameText != null && fNameText.getText().length() == 0; 564 if (!fSuppressError && isEmpty) { 565 status= new StatusInfo(); 566 status.setError(PreferencesMessages.EditTemplateDialog_error_noname); 567 } else if (fNameText != null && !isValidTemplateName(fNameText.getText())) { 568 status= new StatusInfo(); 569 status.setError(PreferencesMessages.EditTemplateDialog_error_spaces); 570 } 571 updateStatus(status); 572 } 573 574 582 private boolean isValidTemplateName(String name) { 583 int nameLength= name.length(); 584 if (nameLength == 0) 585 return true; 586 587 char firstChar= name.charAt(0); 588 boolean isJavadocTemplate= JavaDocContextType.NAME.equals(getContextId()); 589 if (!Character.isUnicodeIdentifierStart(firstChar) && !(isJavadocTemplate && (firstChar == '<' || firstChar == '@'))) 590 return false; 591 592 if (nameLength == 1) 593 return true; 594 595 for (int i= 1; i < nameLength - 1; i++) { 596 if (!Character.isUnicodeIdentifierPart(name.charAt(i))) 597 return false; 598 } 599 600 char lastChar= name.charAt(nameLength - 1); 601 return Character.isUnicodeIdentifierPart(lastChar) || isJavadocTemplate && lastChar == '>'; 602 } 603 604 607 protected void configureShell(Shell newShell) { 608 super.configureShell(newShell); 609 PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IJavaHelpContextIds.EDIT_TEMPLATE_DIALOG); 610 } 611 612 618 public Template getTemplate() { 619 return fTemplate; 620 } 621 622 private String getPattern() { 623 IDocument doc= fPatternEditor.getDocument(); 624 IRegion visible= fPatternEditor.getVisibleRegion(); 625 try { 626 return doc.get(visible.getOffset(), doc.getLength() - visible.getOffset()); 627 } catch (BadLocationException e) { 628 return ""; } 630 } 631 632 636 protected IDialogSettings getDialogBoundsSettings() { 637 String sectionName= getClass().getName() + "_dialogBounds"; IDialogSettings settings= JavaPlugin.getDefault().getDialogSettings(); 639 IDialogSettings section= settings.getSection(sectionName); 640 if (section == null) 641 section= settings.addNewSection(sectionName); 642 return section; 643 } 644 645 } 646 | Popular Tags |