/******************************************************************************* * Copyright (c) 2000, 2015 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.display; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.ResourceBundle; 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.commands.operations.IUndoContext; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants; import org.eclipse.jdt.internal.debug.ui.EvaluationContextManager; import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds; import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; import org.eclipse.jdt.internal.debug.ui.JDISourceViewer; import org.eclipse.jdt.ui.text.IJavaPartitions; import org.eclipse.jdt.ui.text.JavaTextTools; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.text.BadLocationException; 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.IFindReplaceTarget; import org.eclipse.jface.text.ITextInputListener; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.IUndoManager; import org.eclipse.jface.text.IUndoManagerExtension; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DragSourceAdapter; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IPerspectiveListener2; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.XMLMemento; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.console.actions.ClearOutputAction; import org.eclipse.ui.handlers.IHandlerActivation; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.operations.OperationHistoryActionHandler; import org.eclipse.ui.operations.RedoActionHandler; import org.eclipse.ui.operations.UndoActionHandler; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.texteditor.FindReplaceAction; import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.ui.texteditor.IUpdate; public class DisplayView extends ViewPart implements ITextInputListener, IPerspectiveListener2 { class DataDisplay implements IDataDisplay { /** * @see IDataDisplay#clear() */ @Override public void clear() { IDocument document= fSourceViewer.getDocument(); if (document != null) { document.set(""); //$NON-NLS-1$ } } /** * @see IDataDisplay#displayExpression(String) */ @Override public void displayExpression(String expression) { IDocument document= fSourceViewer.getDocument(); int offset= document.getLength(); try { // add a cariage return if needed. if (offset != document.getLineInformationOfOffset(offset).getOffset()) { expression= System.getProperty("line.separator") + expression.trim(); //$NON-NLS-1$ } fSourceViewer.getDocument().replace(offset, 0, expression); fSourceViewer.setSelectedRange(offset + expression.length(), 0); fSourceViewer.revealRange(offset, expression.length()); } catch (BadLocationException ble) { JDIDebugUIPlugin.log(ble); } } /** * @see IDataDisplay#displayExpressionValue(String) */ @Override public void displayExpressionValue(String value) { value= System.getProperty("line.separator") + '\t' + value; //$NON-NLS-1$ ITextSelection selection= (ITextSelection)fSourceViewer.getSelection(); int offset= selection.getOffset() + selection.getLength(); int length= value.length(); try { fSourceViewer.getDocument().replace(offset, 0, value); } catch (BadLocationException ble) { JDIDebugUIPlugin.log(ble); } fSourceViewer.setSelectedRange(offset + length, 0); fSourceViewer.revealRange(offset, length); } } protected IDataDisplay fDataDisplay= new DataDisplay(); protected IDocumentListener fDocumentListener= null; protected JDISourceViewer fSourceViewer; protected IAction fClearDisplayAction; protected DisplayViewAction fContentAssistAction; protected Map<String, IAction> fGlobalActions= new HashMap<>(4); protected List<String> fSelectionActions= new ArrayList<>(3); protected String fRestoredContents= null; /** * This memento allows the Display view to save and restore state * when it is closed and opened within a session. A different * memento is supplied by the platform for persistance at * workbench shutdown. */ private static IMemento fgMemento; private IHandlerActivation fHandlerActivation; /** * @see ViewPart#createChild(IWorkbenchPartContainer) */ @Override public void createPartControl(Composite parent) { fSourceViewer= new JDISourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION | SWT.LEFT_TO_RIGHT); fSourceViewer.configure(new DisplayViewerConfiguration()); fSourceViewer.getSelectionProvider().addSelectionChangedListener(getSelectionChangedListener()); IDocument doc= getRestoredDocument(); fSourceViewer.setDocument(doc); fSourceViewer.addTextInputListener(this); fRestoredContents= null; createActions(); createUndoRedoActions(); initializeToolBar(); // create context menu MenuManager menuMgr = new MenuManager("#PopUp"); //$NON-NLS-1$ menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager mgr) { fillContextMenu(mgr); } }); Menu menu = menuMgr.createContextMenu(fSourceViewer.getTextWidget()); fSourceViewer.getTextWidget().setMenu(menu); getSite().registerContextMenu(menuMgr, fSourceViewer.getSelectionProvider()); getSite().setSelectionProvider(fSourceViewer.getSelectionProvider()); PlatformUI.getWorkbench().getHelpSystem().setHelp(fSourceViewer.getTextWidget(), IJavaDebugHelpContextIds.DISPLAY_VIEW); getSite().getWorkbenchWindow().addPerspectiveListener(this); initDragAndDrop(); } protected IDocument getRestoredDocument() { IDocument doc= null; if (fRestoredContents != null) { doc= new Document(fRestoredContents); } else { doc= new Document(); } JavaTextTools tools= JDIDebugUIPlugin.getDefault().getJavaTextTools(); tools.setupJavaDocumentPartitioner(doc, IJavaPartitions.JAVA_PARTITIONING); fDocumentListener= new IDocumentListener() { /** * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent) */ @Override public void documentAboutToBeChanged(DocumentEvent event) { } /** * @see IDocumentListener#documentChanged(DocumentEvent) */ @Override public void documentChanged(DocumentEvent event) { updateAction(ActionFactory.FIND.getId()); } }; doc.addDocumentListener(fDocumentListener); return doc; } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPart#setFocus() */ @Override public void setFocus() { if (fSourceViewer != null) { fSourceViewer.getControl().setFocus(); } } /** * Initialize the actions of this view */ protected void createActions() { fClearDisplayAction= new ClearOutputAction(fSourceViewer); IAction action= new DisplayViewAction(this, ITextOperationTarget.CUT); action.setText(DisplayMessages.DisplayView_Cut_label); action.setToolTipText(DisplayMessages.DisplayView_Cut_tooltip); action.setDescription(DisplayMessages.DisplayView_Cut_description); setGlobalAction(ActionFactory.CUT.getId(), action); action= new DisplayViewAction(this, ITextOperationTarget.COPY); action.setText(DisplayMessages.DisplayView_Copy_label); action.setToolTipText(DisplayMessages.DisplayView_Copy_tooltip); action.setDescription(DisplayMessages.DisplayView_Copy_description); setGlobalAction(ActionFactory.COPY.getId(), action); action= new DisplayViewAction(this, ITextOperationTarget.PASTE); action.setText(DisplayMessages.DisplayView_Paste_label); action.setToolTipText(DisplayMessages.DisplayView_Paste_tooltip); action.setDescription(DisplayMessages.DisplayView_Paste_Description); setGlobalAction(ActionFactory.PASTE.getId(), action); action= new DisplayViewAction(this, ITextOperationTarget.SELECT_ALL); action.setText(DisplayMessages.DisplayView_SelectAll_label); action.setToolTipText(DisplayMessages.DisplayView_SelectAll_tooltip); action.setDescription(DisplayMessages.DisplayView_SelectAll_description); setGlobalAction(ActionFactory.SELECT_ALL.getId(), action); //TODO: Still using "old" resource access ResourceBundle bundle= ResourceBundle.getBundle("org.eclipse.jdt.internal.debug.ui.display.DisplayResourceBundleMessages"); //$NON-NLS-1$ FindReplaceAction findReplaceAction = new FindReplaceAction(bundle, "find_replace_action_", this); //$NON-NLS-1$ findReplaceAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE); setGlobalAction(ActionFactory.FIND.getId(), findReplaceAction); fSelectionActions.add(ActionFactory.CUT.getId()); fSelectionActions.add(ActionFactory.COPY.getId()); fSelectionActions.add(ActionFactory.PASTE.getId()); fContentAssistAction= new DisplayViewAction(this, ISourceViewer.CONTENTASSIST_PROPOSALS); fContentAssistAction.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); fContentAssistAction.setText(DisplayMessages.DisplayView_Co_ntent_Assist_Ctrl_Space_1); fContentAssistAction.setDescription(DisplayMessages.DisplayView_Content_Assist_2); fContentAssistAction.setToolTipText(DisplayMessages.DisplayView_Content_Assist_2); fContentAssistAction.setImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_ELCL_CONTENT_ASSIST)); fContentAssistAction.setHoverImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_LCL_CONTENT_ASSIST)); fContentAssistAction.setDisabledImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_DLCL_CONTENT_ASSIST)); getViewSite().getActionBars().updateActionBars(); IHandler handler = new AbstractHandler() { @Override public Object execute(ExecutionEvent event) throws ExecutionException { fContentAssistAction.run(); return null; } }; IHandlerService handlerService = getSite().getService(IHandlerService.class); fHandlerActivation = handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, handler); } /** * Creates this editor's undo/redo actions. * <p> * Subclasses may override or extend.</p> * * @since 3.2 */ protected void createUndoRedoActions() { IUndoContext undoContext= getUndoContext(); if (undoContext != null) { // Use actions provided by global undo/redo // Create the undo action OperationHistoryActionHandler undoAction= new UndoActionHandler(getSite(), undoContext); PlatformUI.getWorkbench().getHelpSystem().setHelp(undoAction, IAbstractTextEditorHelpContextIds.UNDO_ACTION); undoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_UNDO); setGlobalAction(ITextEditorActionConstants.UNDO, undoAction); // Create the redo action. OperationHistoryActionHandler redoAction= new RedoActionHandler(getSite(), undoContext); PlatformUI.getWorkbench().getHelpSystem().setHelp(redoAction, IAbstractTextEditorHelpContextIds.REDO_ACTION); redoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_REDO); setGlobalAction(ITextEditorActionConstants.REDO, redoAction); } } /** * Returns this editor's viewer's undo manager undo context. * * @return the undo context or <code>null</code> if not available * @since 3.2 */ private IUndoContext getUndoContext() { IUndoManager undoManager= fSourceViewer.getUndoManager(); if (undoManager instanceof IUndoManagerExtension) { return ((IUndoManagerExtension)undoManager).getUndoContext(); } return null; } protected void setGlobalAction(String actionID, IAction action) { IActionBars actionBars = getViewSite().getActionBars(); fGlobalActions.put(actionID, action); actionBars.setGlobalActionHandler(actionID, action); } /** * Configures the toolBar. */ private void initializeToolBar() { IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager(); tbm.add(new Separator(IJavaDebugUIConstants.EVALUATION_GROUP)); tbm.add(fClearDisplayAction); getViewSite().getActionBars().updateActionBars(); } /** * Adds the context menu actions for the display view. */ protected void fillContextMenu(IMenuManager menu) { if (fSourceViewer.getDocument() == null) { return; } menu.add(new Separator(IJavaDebugUIConstants.EVALUATION_GROUP)); if (EvaluationContextManager.getEvaluationContext(this) != null) { menu.add(fContentAssistAction); } menu.add(new Separator()); menu.add(fGlobalActions.get(ActionFactory.CUT.getId())); menu.add(fGlobalActions.get(ActionFactory.COPY.getId())); menu.add(fGlobalActions.get(ActionFactory.PASTE.getId())); menu.add(fGlobalActions.get(ActionFactory.SELECT_ALL.getId())); menu.add(new Separator()); menu.add(fGlobalActions.get(ActionFactory.FIND.getId())); menu.add(fClearDisplayAction); menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#getAdapter(Class) */ @SuppressWarnings("unchecked") @Override public <T> T getAdapter(Class<T> required) { if (ITextOperationTarget.class.equals(required)) { return (T) fSourceViewer.getTextOperationTarget(); } if (IFindReplaceTarget.class.equals(required)) { return (T) fSourceViewer.getFindReplaceTarget(); } if (IDataDisplay.class.equals(required)) { return (T) fDataDisplay; } if (ITextViewer.class.equals(required)) { return (T) fSourceViewer; } return super.getAdapter(required); } protected void updateActions() { Iterator<String> iterator = fSelectionActions.iterator(); while (iterator.hasNext()) { IAction action = fGlobalActions.get(iterator.next()); if (action instanceof IUpdate) { ((IUpdate) action).update(); } } } /** * Saves the contents of the display view and the formatting. * * @see org.eclipse.ui.IViewPart#saveState(IMemento) */ @Override public void saveState(IMemento memento) { if (fSourceViewer != null) { String contents= getContents(); if (contents != null) { memento.putTextData(contents); } } else if (fRestoredContents != null) { memento.putTextData(fRestoredContents); } } /** * Restores the contents of the display view and the formatting. * * @see org.eclipse.ui.IViewPart#init(IViewSite, IMemento) */ @Override public void init(IViewSite site, IMemento memento) throws PartInitException { init(site); if (fgMemento != null) { memento= fgMemento; } if (memento != null) { fRestoredContents= memento.getTextData(); } } /** * Initializes the drag and/or drop adapters for this view. * * @since 3.4 */ protected void initDragAndDrop() { // Drag only DragSource ds = new DragSource(fSourceViewer.getTextWidget(), DND.DROP_COPY | DND.DROP_MOVE); ds.setTransfer(new Transfer[] {TextTransfer.getInstance()}); ds.addDragListener(new DragSourceAdapter() { @Override public void dragSetData(org.eclipse.swt.dnd.DragSourceEvent event) { event.data = fSourceViewer.getTextWidget().getSelectionText(); } }); } /** * Returns the entire trimmed contents of the current document. * If the contents are "empty" <code>null</code> is returned. */ private String getContents() { if (fSourceViewer != null) { IDocument doc= fSourceViewer.getDocument(); if (doc != null) { String contents= doc.get().trim(); if (contents.length() > 0) { return contents; } } } return null; } protected final ISelectionChangedListener getSelectionChangedListener() { return new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { updateSelectionDependentActions(); } }; } protected void updateSelectionDependentActions() { Iterator<String> iterator= fSelectionActions.iterator(); while (iterator.hasNext()) { updateAction(iterator.next()); } } protected void updateAction(String actionId) { IAction action= fGlobalActions.get(actionId); if (action instanceof IUpdate) { ((IUpdate) action).update(); } } /** * @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument, IDocument) */ @Override public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { } /** * @see ITextInputListener#inputDocumentChanged(IDocument, IDocument) */ @Override public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { oldInput.removeDocumentListener(fDocumentListener); } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPart#dispose() */ @Override public void dispose() { getSite().getWorkbenchWindow().removePerspectiveListener(this); if (fSourceViewer != null) { fSourceViewer.dispose(); fSourceViewer = null; } IHandlerService handlerService = getSite().getService(IHandlerService.class); handlerService.deactivateHandler(fHandlerActivation); super.dispose(); } /* (non-Javadoc) * @see org.eclipse.ui.IPerspectiveListener2#perspectiveChanged(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor, org.eclipse.ui.IWorkbenchPartReference, java.lang.String) */ @Override public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, IWorkbenchPartReference partRef, String changeId) { if (partRef instanceof IViewReference && changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE)) { String id = ((IViewReference) partRef).getId(); if (id.equals(getViewSite().getId())) { // Display view closed. Persist contents. String contents= getContents(); if (contents != null) { fgMemento= XMLMemento.createWriteRoot("DisplayViewMemento"); //$NON-NLS-1$ fgMemento.putTextData(contents); } } } } /* (non-Javadoc) * @see org.eclipse.ui.IPerspectiveListener#perspectiveActivated(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor) */ @Override public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) { } /* (non-Javadoc) * @see org.eclipse.ui.IPerspectiveListener#perspectiveChanged(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor, java.lang.String) */ @Override public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) { } }