| /******************************************************************************* |
| * Copyright (c) 2005, 2008 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 |
| * QNX Software System |
| * Anton Leherbauer (Wind River Systems) |
| * Markus Schorn (Wind River Systems) |
| * Sergey Prigogin (Google) |
| *******************************************************************************/ |
| package org.eclipse.photran.internal.cdtinterface.ui.editor; |
| |
| import java.util.ResourceBundle; |
| |
| import org.eclipse.cdt.core.model.CModelException; |
| import org.eclipse.cdt.core.model.CoreModel; |
| import org.eclipse.cdt.core.model.ICElement; |
| import org.eclipse.cdt.core.model.ISourceRange; |
| import org.eclipse.cdt.core.model.ISourceReference; |
| import org.eclipse.cdt.core.model.IWorkingCopy; |
| import org.eclipse.cdt.internal.ui.actions.SelectionConverter; |
| import org.eclipse.cdt.internal.ui.editor.CContentOutlinePage; |
| import org.eclipse.cdt.internal.ui.editor.CEditor; |
| import org.eclipse.cdt.internal.ui.editor.ConstructedCEditorMessages; |
| import org.eclipse.cdt.ui.CUIPlugin; |
| import org.eclipse.cdt.ui.IWorkingCopyManager; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.search.ui.actions.TextSearchGroup; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IPageLayout; |
| import org.eclipse.ui.IPartService; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.editors.text.TextEditor; |
| import org.eclipse.ui.part.IShowInSource; |
| import org.eclipse.ui.part.IShowInTargetList; |
| import org.eclipse.ui.part.ShowInContext; |
| import org.eclipse.ui.texteditor.ContentAssistAction; |
| import org.eclipse.ui.texteditor.ITextEditorActionConstants; |
| import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; |
| import org.eclipse.ui.texteditor.TextOperationAction; |
| import org.eclipse.ui.views.contentoutline.IContentOutlinePage; |
| |
| /** |
| * A {@link TextEditor} that reuses the Outline view from CDT, as well as its document provider |
| * and possibly its ruler context menu. Also uses CDT's resource bundle to support content |
| * assist actions. |
| * |
| * @author Jeff Overbey, mostly copied from {@link CEditor} |
| */ |
| /* |
| * The parts of this code that don't follow Photran's source formatting conventions were copied |
| * from CDT. |
| */ |
| @SuppressWarnings("restriction") |
| public abstract class CDTBasedTextEditor extends TextEditor implements ISelectionChangedListener |
| { |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| // Utility Methods to Be Called in Subclass Constructors |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| private TextSearchGroup textSearchGroup; |
| |
| protected void useCDTDocumentProvider() |
| { |
| // We must use the CUIPlugin's document provider in order for the |
| // working copy manager in setOutlinePageInput (below) to function correctly. |
| setDocumentProvider(CUIPlugin.getDefault().getDocumentProvider()); |
| } |
| |
| protected void useCDTRulerContextMenuID() |
| { |
| // JO: This gives you a "Toggle Breakpoint" action (and others) |
| // when you right-click the Fortran editor's ruler |
| setRulerContextMenuId("#CEditorRulerContext"); //$NON-NLS-1$ |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| // Actions (use CDT resource bundle) |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| @Override |
| protected void createActions() |
| { |
| super.createActions(); |
| |
| // See CEditor#createActions |
| |
| final ResourceBundle bundle = ConstructedCEditorMessages.getResourceBundle(); |
| |
| // Add content assist actions |
| |
| IAction action = new ContentAssistAction(bundle, "ContentAssistProposal.", this); //$NON-NLS-1$ |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); |
| setAction("ContentAssistProposal", action); //$NON-NLS-1$ |
| markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$ |
| |
| action= new TextOperationAction(bundle, "ContentAssistContextInformation.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$ |
| action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION); |
| setAction("ContentAssistContextInformation", action); //$NON-NLS-1$ |
| markAsStateDependentAction("ContentAssistContextInformation", true); //$NON-NLS-1$ |
| |
| // Add Search > Text actions to the menu bar (added to context menu in #editorContextMenuAboutToShow(IMenuManager) below) |
| |
| textSearchGroup = new TextSearchGroup(this); |
| } |
| |
| /** |
| * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager) |
| */ |
| @Override |
| public void editorContextMenuAboutToShow(IMenuManager menu) |
| { |
| super.editorContextMenuAboutToShow(menu); |
| |
| if (textSearchGroup != null) { |
| textSearchGroup.fillContextMenu(menu); |
| } |
| } |
| |
| @Override |
| public void dispose() |
| { |
| if (textSearchGroup != null) { |
| textSearchGroup.dispose(); |
| } |
| super.dispose(); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| // Outline View Support |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| private CContentOutlinePage fOutlinePage; |
| |
| /** |
| * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) |
| */ |
| @Override |
| public Object getAdapter(Class required) { |
| if (IContentOutlinePage.class.equals(required)) { |
| return getOutlinePage(); |
| } |
| if (required == IShowInTargetList.class) { |
| return new IShowInTargetList() { |
| @SuppressWarnings("deprecation") |
| public String[] getShowInTargetIds() { |
| return new String[] { CUIPlugin.CVIEW_ID, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV }; |
| } |
| |
| }; |
| } |
| if (required == IShowInSource.class) { |
| ICElement ce= null; |
| try { |
| ce= SelectionConverter.getElementAtOffset(this); |
| } catch (CModelException ex) { |
| ce= null; |
| } |
| if (ce != null) { |
| final ISelection selection= new StructuredSelection(ce); |
| return new IShowInSource() { |
| public ShowInContext getShowInContext() { |
| return new ShowInContext(getEditorInput(), selection); |
| } |
| }; |
| } |
| } |
| return super.getAdapter(required); |
| } |
| |
| /** |
| * Gets the outline page of the c-editor. |
| * @return Outline page. |
| */ |
| public CContentOutlinePage getOutlinePage() { |
| if (fOutlinePage == null) { |
| fOutlinePage = new CContentOutlinePage(new CEditor()); |
| fOutlinePage.addSelectionChangedListener(this); |
| } |
| setOutlinePageInput(fOutlinePage, getEditorInput()); |
| return fOutlinePage; |
| } |
| |
| /** |
| * Sets an input for the outline page. |
| * @param page Page to set the input. |
| * @param input Input to set. |
| */ |
| public static void setOutlinePageInput(CContentOutlinePage page, IEditorInput input) { |
| if (page != null) { |
| IWorkingCopyManager manager = CUIPlugin.getDefault().getWorkingCopyManager(); |
| IWorkingCopy workingCopy = manager.getWorkingCopy(input); |
| if (workingCopy != null) |
| page.setInput(workingCopy); |
| } |
| } |
| |
| // ISelectionChangedListener Implementation /////////////////////////////////////////////////// |
| // (for updating editor when Outline clicked) |
| |
| /** |
| * React to changed selection in the outline view. |
| * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) |
| */ |
| public void selectionChanged(SelectionChangedEvent event) { |
| ISelection sel = event.getSelection(); |
| if (sel instanceof IStructuredSelection) { |
| IStructuredSelection selection = (IStructuredSelection) sel; |
| Object obj = selection.getFirstElement(); |
| if (obj instanceof ISourceReference) { |
| try { |
| ISourceRange range = ((ISourceReference) obj).getSourceRange(); |
| if (range != null) { |
| setSelection(range, !isActivePart()); |
| } |
| } catch (CModelException e) { |
| // Selection change not applied. |
| } |
| } |
| } |
| } |
| |
| /** |
| * Sets the current editor selection to the source range. Optionally |
| * sets the current editor position. |
| * |
| * @param element the source range to be shown in the editor, can be null. |
| * @param moveCursor if true the editor is scrolled to show the range. |
| */ |
| public void setSelection(ISourceRange element, boolean moveCursor) { |
| |
| if (element == null) { |
| return; |
| } |
| |
| try { |
| IRegion alternateRegion = null; |
| int start = element.getStartPos(); |
| int length = element.getLength(); |
| |
| // Sanity check sometimes the parser may throw wrong numbers. |
| if (start < 0 || length < 0) { |
| start = 0; |
| length = 0; |
| } |
| |
| // 0 length and start and non-zero start line says we know |
| // the line for some reason, but not the offset. |
| if (length == 0 && start == 0 && element.getStartLine() > 0) { |
| // We have the information in term of lines, we can work it out. |
| // Binary elements return the first executable statement so we have to substract -1 |
| start = getDocumentProvider().getDocument(getEditorInput()).getLineOffset(element.getStartLine() - 1); |
| if (element.getEndLine() > 0) { |
| length = getDocumentProvider().getDocument(getEditorInput()).getLineOffset(element.getEndLine()) - start; |
| } else { |
| length = start; |
| } |
| // create an alternate region for the keyword highlight. |
| alternateRegion = getDocumentProvider().getDocument(getEditorInput()).getLineInformation(element.getStartLine() - 1); |
| if (start == length || length < 0) { |
| if (alternateRegion != null) { |
| start = alternateRegion.getOffset(); |
| length = alternateRegion.getLength(); |
| } |
| } |
| } |
| setHighlightRange(start, length, moveCursor); |
| |
| if (moveCursor) { |
| start = element.getIdStartPos(); |
| length = element.getIdLength(); |
| if (start == 0 && length == 0 && alternateRegion != null) { |
| start = alternateRegion.getOffset(); |
| length = alternateRegion.getLength(); |
| } |
| if (start > -1 && getSourceViewer() != null) { |
| getSourceViewer().revealRange(start, length); |
| getSourceViewer().setSelectedRange(start, length); |
| } |
| updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_POSITION); |
| } |
| return; |
| } catch (IllegalArgumentException x) { |
| // No information to the user |
| } catch (BadLocationException e) { |
| // No information to the user |
| } |
| |
| if (moveCursor) |
| resetHighlightRange(); |
| } |
| |
| /** |
| * Checks is the editor active part. |
| * @return <code>true</code> if editor is the active part of the workbench. |
| */ |
| private boolean isActivePart() { |
| IWorkbenchWindow window = getSite().getWorkbenchWindow(); |
| IPartService service = window.getPartService(); |
| return (this == service.getActivePart()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| // Utility Methods for Subclasses |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| public void forceOutlineViewUpdate() |
| { |
| try |
| { |
| CoreModel.getDefault().getCModel().makeConsistent(new NullProgressMonitor()); |
| } |
| catch (CModelException e) |
| { |
| // Ignore |
| } |
| } |
| } |