Java tutorial
/******************************************************************************* * Copyright (c) 2003, 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 * Les Jones <lesojones@gmail.com> - Bug 214511 *******************************************************************************/ package com.siteview.mde.internal.ui.editor; import com.siteview.mde.core.IBaseModel; import com.siteview.mde.internal.core.text.*; import com.siteview.mde.internal.ui.*; import com.siteview.mde.internal.ui.editor.actions.*; import com.siteview.mde.internal.ui.editor.context.InputContext; import com.siteview.mde.internal.ui.editor.monitor.ExtensionHyperLink; import com.siteview.mde.internal.ui.editor.outline.IOutlineContentCreator; import com.siteview.mde.internal.ui.editor.outline.IOutlineSelectionHandler; import com.siteview.mde.internal.ui.editor.text.PDESelectAnnotationRulerAction; import java.util.ResourceBundle; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.viewers.*; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.*; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextEditor; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.editor.FormEditor; import org.eclipse.ui.forms.editor.IFormPage; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.ide.IGotoMarker; import org.eclipse.ui.part.IShowInTargetList; import org.eclipse.ui.texteditor.*; public abstract class MDESourcePage extends TextEditor implements IFormPage, IGotoMarker, ISelectionChangedListener, IOutlineContentCreator, IOutlineSelectionHandler { private static String RES_BUNDLE_LOCATION = "com.siteview.mde.internal.ui.editor.text.ConstructedPDEEditorMessages"; //$NON-NLS-1$ private static ResourceBundle fgBundleForConstructedKeys = ResourceBundle.getBundle(RES_BUNDLE_LOCATION); public static ResourceBundle getBundleForConstructedKeys() { return fgBundleForConstructedKeys; } /* (non-Javadoc) * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes() */ protected void initializeKeyBindingScopes() { setKeyBindingScopes(new String[] { "com.siteview.mde.ui.pdeEditorContext" }); //$NON-NLS-1$ } /** * Updates the OutlinePage selection and this editor's range indicator. * * @since 3.0 */ private class MDESourcePageChangedListener implements ISelectionChangedListener { /** * Installs this selection changed listener with the given selection * provider. If the selection provider is a post selection provider, * post selection changed events are the preferred choice, otherwise * normal selection changed events are requested. * * @param selectionProvider */ public void install(ISelectionProvider selectionProvider) { if (selectionProvider != null) { if (selectionProvider instanceof IPostSelectionProvider) { IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider; provider.addPostSelectionChangedListener(this); } else { selectionProvider.addSelectionChangedListener(this); } } } /* * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ public void selectionChanged(SelectionChangedEvent event) { handleSelectionChangedSourcePage(event); } /** * Removes this selection changed listener from the given selection * provider. * * @param selectionProviderstyle */ public void uninstall(ISelectionProvider selectionProvider) { if (selectionProvider != null) { if (selectionProvider instanceof IPostSelectionProvider) { IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider; provider.removePostSelectionChangedListener(this); } else { selectionProvider.removeSelectionChangedListener(this); } } } } /** * The editor selection changed listener. * * @since 3.0 */ private MDESourcePageChangedListener fEditorSelectionChangedListener; private MDEFormEditor fEditor; private Control fControl; private int fIndex; private String fId; private InputContext fInputContext; private ISortableContentOutlinePage fOutlinePage; private ISelectionChangedListener fOutlineSelectionChangedListener; private Object fSelection; public MDESourcePage(MDEFormEditor editor, String id, String title) { fId = id; initialize(editor); IPreferenceStore[] stores = new IPreferenceStore[2]; stores[0] = MDEPlugin.getDefault().getPreferenceStore(); stores[1] = EditorsUI.getPreferenceStore(); setPreferenceStore(new ChainedPreferenceStore(stores)); setRangeIndicator(new DefaultRangeIndicator()); if (isSelectionListener()) getEditor().getSite().getSelectionProvider().addSelectionChangedListener(this); } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#initialize(org.eclipse.ui.forms.editor.FormEditor) */ public void initialize(FormEditor editor) { fEditor = (MDEFormEditor) editor; } public void dispose() { if (fEditorSelectionChangedListener != null) { fEditorSelectionChangedListener.uninstall(getSelectionProvider()); fEditorSelectionChangedListener = null; } if (fOutlinePage != null) { fOutlinePage.dispose(); fOutlinePage = null; } if (isSelectionListener()) getEditor().getSite().getSelectionProvider().removeSelectionChangedListener(this); super.dispose(); } /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineContentCreator#createOutlineLabelProvider() */ public abstract ILabelProvider createOutlineLabelProvider(); /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineContentCreator#createOutlineContentProvider() */ public abstract ITreeContentProvider createOutlineContentProvider(); /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineContentCreator#createOutlineComparator() */ public abstract ViewerComparator createOutlineComparator(); /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineSelectionHandler#updateSelection(org.eclipse.jface.viewers.SelectionChangedEvent) */ public void updateSelection(SelectionChangedEvent event) { ISelection sel = event.getSelection(); if (sel instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) sel; updateSelection(structuredSelection.getFirstElement()); } } /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineSelectionHandler#updateSelection(java.lang.Object) */ public abstract void updateSelection(Object object); /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineContentCreator#createDefaultOutlineComparator() */ public ViewerComparator createDefaultOutlineComparator() { return null; } protected ISortableContentOutlinePage createOutlinePage() { SourceOutlinePage sourceOutlinePage = new SourceOutlinePage(fEditor, (IEditingModel) getInputContext().getModel(), createOutlineLabelProvider(), createOutlineContentProvider(), createDefaultOutlineComparator(), createOutlineComparator()); fOutlinePage = sourceOutlinePage; fOutlineSelectionChangedListener = new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { updateSelection(event); } }; fOutlinePage.addSelectionChangedListener(fOutlineSelectionChangedListener); getSelectionProvider().addSelectionChangedListener(sourceOutlinePage); fEditorSelectionChangedListener = new MDESourcePageChangedListener(); fEditorSelectionChangedListener.install(getSelectionProvider()); return fOutlinePage; } /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineSelectionHandler#getContentOutline() */ public ISortableContentOutlinePage getContentOutline() { if (fOutlinePage == null) fOutlinePage = createOutlinePage(); return fOutlinePage; } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#getEditor() */ public FormEditor getEditor() { return fEditor; } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#getManagedForm() */ public IManagedForm getManagedForm() { // not a form page return null; } protected void firePropertyChange(int type) { if (type == PROP_DIRTY) { fEditor.fireSaveNeeded(getEditorInput(), true); } super.firePropertyChange(type); } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#setActive(boolean) */ public void setActive(boolean active) { fInputContext.setSourceEditingMode(active); // Update the text selection if this page is being activated if (active) { updateTextSelection(); } } public boolean canLeaveThePage() { return true; } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#isActive() */ public boolean isActive() { return this.equals(fEditor.getActivePageInstance()); } public void createPartControl(Composite parent) { super.createPartControl(parent); Control[] children = parent.getChildren(); fControl = children[children.length - 1]; PlatformUI.getWorkbench().getHelpSystem().setHelp(fControl, IHelpContextIds.MANIFEST_SOURCE_PAGE); } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#getPartControl() */ public Control getPartControl() { return fControl; } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#getId() */ public String getId() { return fId; } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#getIndex() */ public int getIndex() { return fIndex; } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#setIndex(int) */ public void setIndex(int index) { fIndex = index; } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#isSource() */ public boolean isEditor() { return true; } /** * @return Returns the inputContext. */ public InputContext getInputContext() { return fInputContext; } /** * @param inputContext The inputContext to set. */ public void setInputContext(InputContext inputContext) { fInputContext = inputContext; setDocumentProvider(inputContext.getDocumentProvider()); } /* (non-Javadoc) * @see org.eclipse.ui.forms.editor.IFormPage#focusOn(java.lang.Object) */ public boolean selectReveal(Object object) { if (object instanceof IMarker) { IDE.gotoMarker(this, (IMarker) object); return true; } return false; } public IDocumentRange getRangeElement(int offset, boolean searchChildren) { return null; } public void setHighlightRange(IDocumentRange range, boolean moveCursor) { int offset = range.getOffset(); if (offset == -1) { resetHighlightRange(); return; } ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer == null) return; IDocument document = sourceViewer.getDocument(); if (document == null) return; int length = range.getLength(); setHighlightRange(offset, length == -1 ? 1 : length, moveCursor); } public void setSelectedRange(IDocumentRange range, boolean fullNodeSelection) { ISourceViewer sourceViewer = getSourceViewer(); if (sourceViewer == null) return; IDocument document = sourceViewer.getDocument(); if (document == null) return; int offset; int length; if (range instanceof IDocumentElementNode && !fullNodeSelection) { length = ((IDocumentElementNode) range).getXMLTagName().length(); offset = range.getOffset() + 1; } else { length = range.getLength(); offset = range.getOffset(); } sourceViewer.setSelectedRange(offset, length); } public int getOrientation() { return SWT.LEFT_TO_RIGHT; } protected void createActions() { super.createActions(); PDESelectAnnotationRulerAction action = new PDESelectAnnotationRulerAction(getBundleForConstructedKeys(), "PDESelectAnnotationRulerAction.", this, getVerticalRuler()); //$NON-NLS-1$ setAction(ITextEditorActionConstants.RULER_CLICK, action); MDEFormEditorContributor contributor = fEditor == null ? null : fEditor.getContributor(); if (contributor instanceof MDEFormTextEditorContributor) { MDEFormTextEditorContributor textContributor = (MDEFormTextEditorContributor) contributor; setAction(MDEActionConstants.OPEN, textContributor.getHyperlinkAction()); setAction(MDEActionConstants.FORMAT, textContributor.getFormatAction()); } // Create the quick outline action createQuickOutlineAction(); } /** * */ private void createQuickOutlineAction() { // Quick Outline Action ResourceAction action = new TextOperationAction(getBundleForConstructedKeys(), "QuickOutline.", this, //$NON-NLS-1$ MDEProjectionViewer.QUICK_OUTLINE, true); action.setActionDefinitionId(MDEActionConstants.COMMAND_ID_QUICK_OUTLINE); action.setText(MDEUIMessages.PDESourcePage_actionTextQuickOutline); action.setId(MDEActionConstants.COMMAND_ID_QUICK_OUTLINE); action.setImageDescriptor(MDEPluginImages.DESC_OVERVIEW_OBJ); setAction(MDEActionConstants.COMMAND_ID_QUICK_OUTLINE, action); } public final void selectionChanged(SelectionChangedEvent event) { if (event.getSource() == getSelectionProvider()) return; ISelection sel = event.getSelection(); if (sel instanceof IStructuredSelection) { IStructuredSelection structuredSel = (IStructuredSelection) sel; // Store the selected object to save us having to do this again. setSelectedObject(structuredSel.getFirstElement()); } else if (sel instanceof ITextSelection) { ITextSelection textSel = (ITextSelection) sel; setSelectedObject(getRangeElement(textSel.getOffset(), false)); } else fSelection = null; } /* * Locate an IDocumentRange, subclasses that want to * highlight text components based on site selection * should override this method. */ protected IDocumentRange findRange() { return null; } public void updateTextSelection() { IDocumentRange range = findRange(); if (range == null) return; IBaseModel model = getInputContext().getModel(); if (!(model instanceof AbstractEditingModel)) return; if (range.getOffset() == -1 || isDirty()) { try { ((AbstractEditingModel) model).adjustOffsets(((AbstractEditingModel) model).getDocument()); } catch (CoreException e) { } range = findRange(); } setHighlightRange(range, true); setSelectedRange(range, false); } /* * Subclasses that wish to provide PDEFormPage -> PDESourcePage * selection persistence should override this and return true. */ protected boolean isSelectionListener() { return false; } public ISourceViewer getViewer() { return getSourceViewer(); } protected void editorContextMenuAboutToShow(IMenuManager menu) { MDEFormEditorContributor contributor = fEditor == null ? null : fEditor.getContributor(); if (contributor instanceof MDEFormTextEditorContributor) { MDEFormTextEditorContributor textContributor = (MDEFormTextEditorContributor) contributor; HyperlinkAction action = textContributor.getHyperlinkAction(); if ((action != null) && action.isEnabled() && ((action.getHyperLink() instanceof ExtensionHyperLink) == false)) { // Another detector handles this the extension hyperlink case // org.eclipse.pde.internal.ui.editor.plugin.ExtensionAttributePointDectector.java // Implemented at a higher level. As a result, need to disable // the action here to prevent duplicate entries in the context menu menu.add(action); } FormatAction formatManifestAction = textContributor.getFormatAction(); if (isEditable() && formatManifestAction != null && formatManifestAction.isEnabled()) menu.add(formatManifestAction); } super.editorContextMenuAboutToShow(menu); } public Object getSelection() { return fSelection; } /** * Allow for programmatic selection of the currently selected object by * subclasses */ protected void setSelectedObject(Object selectedObject) { fSelection = selectedObject; } /* (non-Javadoc) * @see org.eclipse.pde.internal.ui.editor.outline.IOutlineContentCreator#getOutlineInput() */ public Object getOutlineInput() { return getInputContext().getModel(); } /** * @param rangeElement */ protected void updateOutlinePageSelection(Object rangeElement) { // Set selection in source outline page if the 'Link with Editor' // feature is on if (MDEPlugin.getDefault().getPreferenceStore().getBoolean("ToggleLinkWithEditorAction.isChecked")) { //$NON-NLS-1$ // Ensure we have a source outline page if ((fOutlinePage instanceof SourceOutlinePage) == false) { return; } SourceOutlinePage outlinePage = (SourceOutlinePage) fOutlinePage; // Temporarily remove the listener to prevent a selection event being fired // back at this page outlinePage.removeAllSelectionChangedListeners(); if (rangeElement != null) { outlinePage.setSelection(new StructuredSelection(rangeElement)); } else { outlinePage.setSelection(StructuredSelection.EMPTY); } outlinePage.addAllSelectionChangedListeners(); } } /** * Handles selection events generated from the source page * @param event The selection changed event */ protected void handleSelectionChangedSourcePage(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (!selection.isEmpty() && selection instanceof ITextSelection) { ITextSelection textSel = (ITextSelection) selection; // Get the current element from the offset int offset = textSel.getOffset(); IDocumentRange rangeElement; rangeElement = this.getRangeElement(offset, false); // store this as the current selection setSelectedObject(rangeElement); // Synchronize the outline page synchronizeOutlinePage(rangeElement); } } /** * @param rangeElement */ protected void updateHighlightRange(IDocumentRange rangeElement) { if (rangeElement != null) { setHighlightRange(rangeElement, false); } else { resetHighlightRange(); } } /** * Synchronize the outline page to show a relevant element given the * current offset. * * @param offset The current offset within the source page */ protected void synchronizeOutlinePage(int offset) { IDocumentRange rangeElement = getRangeElement(offset, false); synchronizeOutlinePage(rangeElement); } /** * Synchronize the outline page to show the specified element * @param rangeElement The element to show in the outline page */ private void synchronizeOutlinePage(IDocumentRange rangeElement) { updateHighlightRange(rangeElement); updateOutlinePageSelection(rangeElement); } /** * Triggered by toggling the 'Link with Editor' button in the outline * view * @param offset */ public void synchronizeOutlinePage() { // Get the current position of the cursor in this page int current_offset = getSourceViewer().getSelectedRange().x; synchronizeOutlinePage(current_offset); } /** * Utility method for getRangeElement(int, boolean) * @param node * @param offset * @param searchChildren * @see org.eclipse.pde.internal.MDESourcePage.editor.PDESourcePage#findNode(Object[], int, boolean) */ protected IDocumentRange findNode(IDocumentElementNode node, int offset, boolean searchChildren) { return findNode(new Object[] { node }, offset, searchChildren); } /** * Utility method for getRangeElement(int, boolean) * @param nodes All entries should be instances of IDocumentElementNode * @param offset The offset the cursor is currently on in the document * @param searchChildren <code>true</code> to search child nodes; <code>false</code> otherwise. * @return Node the offset is in */ protected IDocumentRange findNode(Object[] nodes, int offset, boolean searchChildren) { for (int i = 0; i < nodes.length; i++) { IDocumentElementNode node = (IDocumentElementNode) nodes[i]; if (node.getOffset() <= offset && offset < node.getOffset() + node.getLength()) { if (!searchChildren) return node; if (node.getOffset() < offset && offset <= node.getOffset() + node.getXMLTagName().length() + 1) return node; IDocumentAttributeNode[] attrs = node.getNodeAttributes(); if (attrs != null) for (int a = 0; a < attrs.length; a++) if (attrs[a].getNameOffset() <= offset && offset <= attrs[a].getValueOffset() + attrs[a].getValueLength()) return attrs[a]; IDocumentTextNode textNode = node.getTextNode(); if (textNode != null && textNode.getOffset() <= offset && offset < textNode.getOffset() + textNode.getLength()) return textNode; IDocumentElementNode[] children = node.getChildNodes(); if (children != null) for (int c = 0; c < children.length; c++) if (children[c].getOffset() <= offset && offset < children[c].getOffset() + children[c].getLength()) return findNode(children[c], offset, searchChildren); // not contained inside any sub elements, must be inside node return node; } } return null; } /** * Override the getAdapter function to return a list of targets * for the "Show In >" action in the context menu. * * @param adapter * @return A list of targets (IShowInTargetList) for the "Show In >" * submenu if the appropriate adapter is passed in and the editor * is not read-only. Returns <code>super.getAdapter(adapter)</code> * otherwise. */ public Object getAdapter(Class adapter) { if ((adapter == IShowInTargetList.class) && (fEditor != null) && (fEditor.getEditorInput() instanceof IFileEditorInput)) { return getShowInTargetList(); } return super.getAdapter(adapter); } /** * Returns the <code>IShowInTargetList</code> for this view. * @return the <code>IShowInTargetList</code> */ protected IShowInTargetList getShowInTargetList() { return new IShowInTargetList() { public String[] getShowInTargetIds() { return new String[] { JavaUI.ID_PACKAGES, IPageLayout.ID_RES_NAV }; } }; } /** * @param range */ public IDocumentRange adaptRange(IDocumentRange range) { // Subclasses to override return range; } }