| /******************************************************************************* |
| * Copyright (c) 2000, 2009 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.debug.ui; |
| |
| |
| import java.util.List; |
| |
| import com.ibm.icu.text.MessageFormat; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| |
| import org.eclipse.core.commands.AbstractHandler; |
| import org.eclipse.core.commands.ExecutionEvent; |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.commands.IHandler; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.StatusDialog; |
| |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.DocumentEvent; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IDocumentListener; |
| import org.eclipse.jface.text.contentassist.IContentAssistProcessor; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.SelectionDialog; |
| import org.eclipse.ui.handlers.IHandlerActivation; |
| import org.eclipse.ui.handlers.IHandlerService; |
| import org.eclipse.ui.keys.IBindingService; |
| |
| import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; |
| |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.search.IJavaSearchConstants; |
| import org.eclipse.jdt.core.search.IJavaSearchScope; |
| import org.eclipse.jdt.core.search.SearchEngine; |
| import org.eclipse.jdt.core.search.SearchMatch; |
| import org.eclipse.jdt.core.search.SearchParticipant; |
| import org.eclipse.jdt.core.search.SearchPattern; |
| import org.eclipse.jdt.core.search.SearchRequestor; |
| |
| import org.eclipse.jdt.internal.debug.ui.contentassist.DynamicTypeContext; |
| import org.eclipse.jdt.internal.debug.ui.contentassist.JavaDebugContentAssistProcessor; |
| import org.eclipse.jdt.internal.debug.ui.contentassist.DynamicTypeContext.ITypeProvider; |
| import org.eclipse.jdt.internal.debug.ui.display.DisplayViewerConfiguration; |
| |
| import org.eclipse.jdt.ui.IJavaElementSearchConstants; |
| import org.eclipse.jdt.ui.JavaUI; |
| import org.eclipse.jdt.ui.text.IJavaPartitions; |
| import org.eclipse.jdt.ui.text.JavaTextTools; |
| |
| /** |
| * Dialog for edit detail formatter. |
| */ |
| public class DetailFormatterDialog extends StatusDialog implements ITypeProvider { |
| |
| /** |
| * The detail formatter to edit. |
| */ |
| private DetailFormatter fDetailFormatter; |
| |
| // widgets |
| private Text fTypeNameText; |
| private JDISourceViewer fSnippetViewer; |
| private Button fCheckBox; |
| |
| /** |
| * Indicate if a search for a type with the given name |
| * have been already performed. |
| */ |
| private boolean fTypeSearched; |
| |
| /** |
| * Indicate if the type can be modified. |
| */ |
| private boolean fEditTypeName; |
| |
| /** |
| * The type object which corresponds to the given name. |
| * If this field is <code>null</code> and <code>fTypeSearched</code> is |
| * <code>true</code>, that means there is no type with the given name in |
| * the workspace. |
| */ |
| private IType fType; |
| |
| /** |
| * List of types that have detail formatters already defined. |
| */ |
| private List fDefinedTypes; |
| |
| /** |
| * Activation handler for content assist, must be deactivated on disposal. |
| */ |
| private IHandlerActivation fHandlerActivation; |
| |
| /** |
| * DetailFormatterDialog constructor. Creates a new dialog to create/edit a detail formatter. |
| * |
| * @param parent parent shell |
| * @param detailFormatter detail formatter to edit, not <code>null</code> |
| * @param definedTypes list of types with detail formatters already defined, or <code>null</code> |
| * @param editDialog whether the dialog is being used to edit a detail formatter |
| */ |
| public DetailFormatterDialog(Shell parent, DetailFormatter detailFormatter, List definedTypes, boolean editDialog) { |
| this(parent, detailFormatter, definedTypes, true, editDialog); |
| } |
| |
| /** |
| * DetailFormatterDialog constructor. Creates a new dialog to create/edit a detail formatter. |
| * |
| * @param parent parent shell |
| * @param detailFormatter detail formatter to edit, not <code>null</code> |
| * @param definedTypes list of types with detail formatters already defined, or <code>null</code> |
| * @param editTypeName whether the user should be able to modify the type |
| * @param editDialog whether the dialog is being used to edit a detail formatter |
| */ |
| public DetailFormatterDialog(Shell parent, DetailFormatter detailFormatter, List definedTypes, boolean editTypeName, boolean editDialog) { |
| super(parent); |
| fDetailFormatter= detailFormatter; |
| fTypeSearched= false; |
| setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE); |
| if (editDialog) { |
| setTitle(DebugUIMessages.DetailFormatterDialog_Edit_Detail_Formatter_1); |
| } else { |
| setTitle(DebugUIMessages.DetailFormatterDialog_Add_Detail_Formatter_2); |
| } |
| fEditTypeName= editTypeName; |
| fDefinedTypes= definedTypes; |
| } |
| |
| /** |
| * Create the dialog area. |
| * |
| * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite) |
| */ |
| protected Control createDialogArea(Composite parent) { |
| IWorkbench workbench = PlatformUI.getWorkbench(); |
| |
| workbench.getHelpSystem().setHelp( |
| parent, |
| IJavaDebugHelpContextIds.EDIT_DETAIL_FORMATTER_DIALOG); |
| |
| Font font = parent.getFont(); |
| Composite container = (Composite)super.createDialogArea(parent); |
| |
| SWTFactory.createLabel(container, DebugUIMessages.DetailFormatterDialog_Qualified_type__name__2, 1); |
| |
| Composite innerContainer = SWTFactory.createComposite(container, font, 2, 1, GridData.FILL_HORIZONTAL); |
| |
| fTypeNameText = SWTFactory.createSingleText(innerContainer, 1); |
| fTypeNameText.setEditable(fEditTypeName); |
| fTypeNameText.setText(fDetailFormatter.getTypeName()); |
| fTypeNameText.addModifyListener(new ModifyListener() { |
| public void modifyText(ModifyEvent e) { |
| fTypeSearched= false; |
| checkValues(); |
| } |
| }); |
| |
| Button typeSearchButton = SWTFactory.createPushButton(innerContainer, DebugUIMessages.DetailFormatterDialog_Select__type_4, null); |
| typeSearchButton.setEnabled(fEditTypeName); |
| typeSearchButton.addListener(SWT.Selection, new Listener() { |
| public void handleEvent(Event e) { |
| selectType(); |
| } |
| }); |
| |
| String labelText = null; |
| IBindingService bindingService = (IBindingService) workbench.getAdapter(IBindingService.class); |
| String binding = bindingService.getBestActiveBindingFormattedFor(IWorkbenchCommandConstants.EDIT_CONTENT_ASSIST); |
| if (binding != null) { |
| labelText = MessageFormat.format(DebugUIMessages.DetailFormatterDialog_17, new String[] { binding }); |
| } |
| if (labelText == null) { |
| labelText = DebugUIMessages.DetailFormatterDialog_Detail_formatter__code_snippet__1; |
| } |
| |
| SWTFactory.createLabel(container, labelText, 1); |
| |
| createSnippetViewer(container); |
| |
| fCheckBox = SWTFactory.createCheckButton(container, DebugUIMessages.DetailFormatterDialog__Enable_1, null, fDetailFormatter.isEnabled(), 1); |
| |
| // Set up content assist in the viewer |
| IHandler handler = new AbstractHandler() { |
| public Object execute(ExecutionEvent event) throws ExecutionException { |
| if (fSnippetViewer.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS) && fSnippetViewer.getControl().isFocusControl()){ |
| findCorrespondingType(); |
| fSnippetViewer.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); |
| } |
| return null; |
| } |
| }; |
| IHandlerService handlerService = (IHandlerService) workbench.getAdapter(IHandlerService.class); |
| fHandlerActivation = handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, handler); |
| |
| checkValues(); |
| return container; |
| } |
| |
| /** |
| * Creates the JDISourceViewer that displays the code snippet to the user. |
| * |
| * @param parent parent composite |
| */ |
| private void createSnippetViewer(Composite parent) { |
| fSnippetViewer= new JDISourceViewer(parent, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.LEFT_TO_RIGHT); |
| fSnippetViewer.setInput(this); |
| |
| JavaTextTools tools= JDIDebugUIPlugin.getDefault().getJavaTextTools(); |
| IDocument document= new Document(); |
| tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING); |
| fSnippetViewer.configure(new DisplayViewerConfiguration() { |
| public IContentAssistProcessor getContentAssistantProcessor() { |
| return new JavaDebugContentAssistProcessor(new DynamicTypeContext(DetailFormatterDialog.this)); |
| } |
| }); |
| fSnippetViewer.setEditable(true); |
| fSnippetViewer.setDocument(document); |
| |
| Control control= fSnippetViewer.getControl(); |
| GridData gd= new GridData(GridData.FILL_BOTH); |
| gd.heightHint= convertHeightInCharsToPixels(10); |
| gd.widthHint= convertWidthInCharsToPixels(80); |
| control.setLayoutData(gd); |
| document.set(fDetailFormatter.getSnippet()); |
| |
| fSnippetViewer.getDocument().addDocumentListener(new IDocumentListener() { |
| public void documentAboutToBeChanged(DocumentEvent event) { |
| } |
| public void documentChanged(DocumentEvent event) { |
| checkValues(); |
| } |
| }); |
| |
| if (fDetailFormatter.getTypeName().length() > 0) { |
| fSnippetViewer.getControl().setFocus(); |
| } |
| } |
| |
| /** |
| * Check the field values and display a message in the status if needed. |
| */ |
| private void checkValues() { |
| StatusInfo status= new StatusInfo(); |
| String typeName= fTypeNameText.getText().trim(); |
| if (typeName.length() == 0) { |
| status.setError(DebugUIMessages.DetailFormatterDialog_Qualified_type_name_must_not_be_empty__3); |
| } else if (fDefinedTypes != null && fDefinedTypes.contains(typeName)) { |
| status.setError(DebugUIMessages.DetailFormatterDialog_A_detail_formatter_is_already_defined_for_this_type_2); |
| } else if (fSnippetViewer.getDocument().get().trim().length() == 0) { |
| status.setError(DebugUIMessages.DetailFormatterDialog_Associated_code_must_not_be_empty_3); |
| } else if (fType == null && fTypeSearched) { |
| status.setWarning(DebugUIMessages.No_type_with_the_given_name_found_in_the_workspace__1); |
| } |
| updateStatus(status); |
| } |
| |
| /** |
| * @see org.eclipse.jface.dialogs.Dialog#okPressed() |
| */ |
| protected void okPressed() { |
| fDetailFormatter.setEnabled(fCheckBox.getSelection()); |
| fDetailFormatter.setTypeName(fTypeNameText.getText().trim()); |
| fDetailFormatter.setSnippet(fSnippetViewer.getDocument().get()); |
| |
| super.okPressed(); |
| } |
| |
| /** |
| * Open the 'select type' dialog, and set the user choice into the formatter. |
| */ |
| private void selectType() { |
| Shell shell= getShell(); |
| SelectionDialog dialog= null; |
| try { |
| dialog= JavaUI.createTypeDialog(shell, PlatformUI.getWorkbench().getProgressService(), |
| SearchEngine.createWorkspaceScope(), IJavaElementSearchConstants.CONSIDER_ALL_TYPES, false, fTypeNameText.getText()); |
| } catch (JavaModelException jme) { |
| String title= DebugUIMessages.DetailFormatterDialog_Select_type_6; |
| String message= DebugUIMessages.DetailFormatterDialog_Could_not_open_type_selection_dialog_for_detail_formatters_7; |
| ExceptionHandler.handle(jme, title, message); |
| return; |
| } |
| |
| dialog.setTitle(DebugUIMessages.DetailFormatterDialog_Select_type_8); |
| dialog.setMessage(DebugUIMessages.DetailFormatterDialog_Select_a_type_to_format_when_displaying_its_detail_9); |
| if (dialog.open() == IDialogConstants.CANCEL_ID) { |
| return; |
| } |
| |
| Object[] types= dialog.getResult(); |
| if (types != null && types.length > 0) { |
| fType = (IType)types[0]; |
| fTypeNameText.setText(fType.getFullyQualifiedName()); |
| fTypeSearched = true; |
| } |
| } |
| |
| /** |
| * Use the Java search engine to find the type which corresponds |
| * to the given name. |
| */ |
| private void findCorrespondingType() { |
| if (fTypeSearched) { |
| return; |
| } |
| fType= null; |
| fTypeSearched= true; |
| final String pattern= fTypeNameText.getText().trim().replace('$', '.'); |
| if (pattern == null || "".equals(pattern)) { //$NON-NLS-1$ |
| return; |
| } |
| final IProgressMonitor monitor = new NullProgressMonitor(); |
| final SearchRequestor collector = new SearchRequestor() { |
| private boolean fFirst= true; |
| |
| public void endReporting() { |
| checkValues(); |
| } |
| |
| public void acceptSearchMatch(SearchMatch match) throws CoreException { |
| Object enclosingElement = match.getElement(); |
| if (!fFirst) { |
| return; |
| } |
| fFirst= false; |
| if (enclosingElement instanceof IType) { |
| fType= (IType) enclosingElement; |
| } |
| // cancel once we have one match |
| monitor.setCanceled(true); |
| } |
| }; |
| |
| SearchEngine engine= new SearchEngine(JavaCore.getWorkingCopies(null)); |
| SearchPattern searchPattern = SearchPattern.createPattern(pattern, IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE); |
| IJavaSearchScope scope= SearchEngine.createWorkspaceScope(); |
| SearchParticipant[] participants = new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}; |
| try { |
| engine.search(searchPattern, participants, scope, collector, monitor); |
| } catch (CoreException e) { |
| JDIDebugUIPlugin.log(e); |
| } catch (OperationCanceledException e) { |
| } |
| } |
| |
| /** |
| * Return the type object which corresponds to the given name. |
| */ |
| public IType getType() { |
| if (!fTypeSearched) { |
| findCorrespondingType(); |
| } |
| return fType; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.window.Window#close() |
| */ |
| public boolean close() { |
| IWorkbench workbench = PlatformUI.getWorkbench(); |
| IHandlerService handlerService = (IHandlerService) workbench.getAdapter(IHandlerService.class); |
| handlerService.deactivateHandler(fHandlerActivation); |
| fSnippetViewer.dispose(); |
| return super.close(); |
| } |
| |
| } |