diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java | 591 |
1 files changed, 0 insertions, 591 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java deleted file mode 100644 index 2e60df5bf..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidTextEditor.java +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.editors; - -import com.android.ide.eclipse.adt.AdtPlugin; - -import org.eclipse.core.internal.filebuffers.SynchronizableDocument; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.QualifiedName; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.DocumentRewriteSession; -import org.eclipse.jface.text.DocumentRewriteSessionType; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IDocumentExtension4; -import org.eclipse.jface.text.IDocumentListener; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IEditorSite; -import org.eclipse.ui.IFileEditorInput; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.browser.IWorkbenchBrowserSupport; -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.forms.events.HyperlinkAdapter; -import org.eclipse.ui.forms.events.HyperlinkEvent; -import org.eclipse.ui.forms.events.IHyperlinkListener; -import org.eclipse.ui.forms.widgets.FormText; -import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport; -import org.eclipse.ui.part.FileEditorInput; -import org.eclipse.ui.part.MultiPageEditorPart; -import org.eclipse.ui.part.WorkbenchPart; -import org.eclipse.ui.texteditor.IDocumentProvider; -import org.eclipse.wst.sse.ui.StructuredTextEditor; - -import java.net.MalformedURLException; -import java.net.URL; - -/** - * Multi-page form editor for Android text files. - * <p/> - * It is designed to work with a {@link TextEditor} that will display a text file. - * <br/> - * Derived classes must implement createFormPages to create the forms before the - * source editor. This can be a no-op if desired. - */ -@SuppressWarnings("restriction") -public abstract class AndroidTextEditor extends FormEditor implements IResourceChangeListener { - - /** Preference name for the current page of this file */ - private static final String PREF_CURRENT_PAGE = "_current_page"; - - /** Id string used to create the Android SDK browser */ - private static String BROWSER_ID = "android"; //$NON-NLS-1$ - - /** Page id of the XML source editor, used for switching tabs programmatically */ - public final static String TEXT_EDITOR_ID = "editor_part"; //$NON-NLS-1$ - - /** Width hint for text fields. Helps the grid layout resize properly on smaller screens */ - public static final int TEXT_WIDTH_HINT = 50; - - /** Page index of the text editor (always the last page) */ - private int mTextPageIndex; - - /** The text editor */ - private TextEditor mTextEditor; - - /** flag set during page creation */ - private boolean mIsCreatingPage = false; - - private IDocument mDocument; - - /** - * Creates a form editor. - */ - public AndroidTextEditor() { - super(); - } - - // ---- Abstract Methods ---- - - /** - * Creates the various form pages. - * <p/> - * Derived classes must implement this to add their own specific tabs. - */ - abstract protected void createFormPages(); - - /** - * Called by the base class {@link AndroidTextEditor} once all pages (custom form pages - * as well as text editor page) have been created. This give a chance to deriving - * classes to adjust behavior once the text page has been created. - */ - protected void postCreatePages() { - // Nothing in the base class. - } - - /** - * Subclasses should override this method to process the new text model. - * This is called after the document has been edited. - * - * The base implementation is empty. - * - * @param event Specification of changes applied to document. - */ - protected void onDocumentChanged(DocumentEvent event) { - // pass - } - - // ---- Base Class Overrides, Interfaces Implemented ---- - - /** - * Creates the pages of the multi-page editor. - */ - @Override - protected void addPages() { - createAndroidPages(); - selectDefaultPage(null /* defaultPageId */); - } - - /** - * Creates the page for the Android Editors - */ - protected void createAndroidPages() { - mIsCreatingPage = true; - createFormPages(); - createTextEditor(); - createUndoRedoActions(); - postCreatePages(); - mIsCreatingPage = false; - } - - /** - * Returns whether the editor is currently creating its pages. - */ - public boolean isCreatingPages() { - return mIsCreatingPage; - } - - /** - * Creates undo redo actions for the editor site (so that it works for any page of this - * multi-page editor) by re-using the actions defined by the {@link TextEditor} - * (aka the XML text editor.) - */ - private void createUndoRedoActions() { - IActionBars bars = getEditorSite().getActionBars(); - if (bars != null) { - IAction action = mTextEditor.getAction(ActionFactory.UNDO.getId()); - bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), action); - - action = mTextEditor.getAction(ActionFactory.REDO.getId()); - bars.setGlobalActionHandler(ActionFactory.REDO.getId(), action); - - bars.updateActionBars(); - } - } - - /** - * Selects the default active page. - * @param defaultPageId the id of the page to show. If <code>null</code> the editor attempts to - * find the default page in the properties of the {@link IResource} object being edited. - */ - protected void selectDefaultPage(String defaultPageId) { - if (defaultPageId == null) { - if (getEditorInput() instanceof IFileEditorInput) { - IFile file = ((IFileEditorInput) getEditorInput()).getFile(); - - QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID, - getClass().getSimpleName() + PREF_CURRENT_PAGE); - String pageId; - try { - pageId = file.getPersistentProperty(qname); - if (pageId != null) { - defaultPageId = pageId; - } - } catch (CoreException e) { - // ignored - } - } - } - - if (defaultPageId != null) { - try { - setActivePage(Integer.parseInt(defaultPageId)); - } catch (Exception e) { - // We can get NumberFormatException from parseInt but also - // AssertionError from setActivePage when the index is out of bounds. - // Generally speaking we just want to ignore any exception and fall back on the - // first page rather than crash the editor load. Logging the error is enough. - AdtPlugin.log(e, "Selecting page '%s' in AndroidXmlEditor failed", defaultPageId); - } - } - } - - /** - * Removes all the pages from the editor. - */ - protected void removePages() { - int count = getPageCount(); - for (int i = count - 1 ; i >= 0 ; i--) { - removePage(i); - } - } - - /** - * Overrides the parent's setActivePage to be able to switch to the xml editor. - * - * If the special pageId TEXT_EDITOR_ID is given, switches to the mTextPageIndex page. - * This is needed because the editor doesn't actually derive from IFormPage and thus - * doesn't have the get-by-page-id method. In this case, the method returns null since - * IEditorPart does not implement IFormPage. - */ - @Override - public IFormPage setActivePage(String pageId) { - if (pageId.equals(TEXT_EDITOR_ID)) { - super.setActivePage(mTextPageIndex); - return null; - } else { - return super.setActivePage(pageId); - } - } - - - /** - * Notifies this multi-page editor that the page with the given id has been - * activated. This method is called when the user selects a different tab. - * - * @see MultiPageEditorPart#pageChange(int) - */ - @Override - protected void pageChange(int newPageIndex) { - super.pageChange(newPageIndex); - - // Do not record page changes during creation of pages - if (mIsCreatingPage) { - return; - } - - if (getEditorInput() instanceof IFileEditorInput) { - IFile file = ((IFileEditorInput) getEditorInput()).getFile(); - - QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID, - getClass().getSimpleName() + PREF_CURRENT_PAGE); - try { - file.setPersistentProperty(qname, Integer.toString(newPageIndex)); - } catch (CoreException e) { - // ignore - } - } - } - - /** - * Notifies this listener that some resource changes - * are happening, or have already happened. - * - * Closes all project files on project close. - * @see IResourceChangeListener - */ - @Override - public void resourceChanged(final IResourceChangeEvent event) { - if (event.getType() == IResourceChangeEvent.PRE_CLOSE) { - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - @SuppressWarnings("hiding") - IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages(); - for (int i = 0; i < pages.length; i++) { - if (((FileEditorInput)mTextEditor.getEditorInput()) - .getFile().getProject().equals( - event.getResource())) { - IEditorPart editorPart = pages[i].findEditor(mTextEditor - .getEditorInput()); - pages[i].closeEditor(editorPart, true); - } - } - } - }); - } - } - - /** - * Initializes the editor part with a site and input. - * <p/> - * Checks that the input is an instance of {@link IFileEditorInput}. - * - * @see FormEditor - */ - @Override - public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException { - if (!(editorInput instanceof IFileEditorInput)) - throw new PartInitException("Invalid Input: Must be IFileEditorInput"); - super.init(site, editorInput); - } - - /** - * Returns the {@link IFile} matching the editor's input or null. - * <p/> - * By construction, the editor input has to be an {@link IFileEditorInput} so it must - * have an associated {@link IFile}. Null can only be returned if this editor has no - * input somehow. - */ - public IFile getFile() { - if (getEditorInput() instanceof IFileEditorInput) { - return ((IFileEditorInput) getEditorInput()).getFile(); - } - return null; - } - - /** - * Removes attached listeners. - * - * @see WorkbenchPart - */ - @Override - public void dispose() { - ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); - - super.dispose(); - } - - /** - * Commit all dirty pages then saves the contents of the text editor. - * <p/> - * This works by committing all data to the XML model and then - * asking the Structured XML Editor to save the XML. - * - * @see IEditorPart - */ - @Override - public void doSave(IProgressMonitor monitor) { - commitPages(true /* onSave */); - - // The actual "save" operation is done by the Structured XML Editor - getEditor(mTextPageIndex).doSave(monitor); - } - - /* (non-Javadoc) - * Saves the contents of this editor to another object. - * <p> - * Subclasses must override this method to implement the open-save-close lifecycle - * for an editor. For greater details, see <code>IEditorPart</code> - * </p> - * - * @see IEditorPart - */ - @Override - public void doSaveAs() { - commitPages(true /* onSave */); - - IEditorPart editor = getEditor(mTextPageIndex); - editor.doSaveAs(); - setPageText(mTextPageIndex, editor.getTitle()); - setInput(editor.getEditorInput()); - } - - /** - * Commits all dirty pages in the editor. This method should - * be called as a first step of a 'save' operation. - * <p/> - * This is the same implementation as in {@link FormEditor} - * except it fixes two bugs: a cast to IFormPage is done - * from page.get(i) <em>before</em> being tested with instanceof. - * Another bug is that the last page might be a null pointer. - * <p/> - * The incorrect casting makes the original implementation crash due - * to our {@link StructuredTextEditor} not being an {@link IFormPage} - * so we have to override and duplicate to fix it. - * - * @param onSave <code>true</code> if commit is performed as part - * of the 'save' operation, <code>false</code> otherwise. - * @since 3.3 - */ - @Override - public void commitPages(boolean onSave) { - if (pages != null) { - for (int i = 0; i < pages.size(); i++) { - Object page = pages.get(i); - if (page != null && page instanceof IFormPage) { - IFormPage form_page = (IFormPage) page; - IManagedForm managed_form = form_page.getManagedForm(); - if (managed_form != null && managed_form.isDirty()) { - managed_form.commit(onSave); - } - } - } - } - } - - /* (non-Javadoc) - * Returns whether the "save as" operation is supported by this editor. - * <p> - * Subclasses must override this method to implement the open-save-close lifecycle - * for an editor. For greater details, see <code>IEditorPart</code> - * </p> - * - * @see IEditorPart - */ - @Override - public boolean isSaveAsAllowed() { - return false; - } - - // ---- Local methods ---- - - - /** - * Helper method that creates a new hyper-link Listener. - * Used by derived classes which need active links in {@link FormText}. - * <p/> - * This link listener handles two kinds of URLs: - * <ul> - * <li> Links starting with "http" are simply sent to a local browser. - * <li> Links starting with "file:/" are simply sent to a local browser. - * <li> Links starting with "page:" are expected to be an editor page id to switch to. - * <li> Other links are ignored. - * </ul> - * - * @return A new hyper-link listener for FormText to use. - */ - public final IHyperlinkListener createHyperlinkListener() { - return new HyperlinkAdapter() { - /** - * Switch to the page corresponding to the link that has just been clicked. - * For this purpose, the HREF of the <a> tags above is the page ID to switch to. - */ - @Override - public void linkActivated(HyperlinkEvent e) { - super.linkActivated(e); - String link = e.data.toString(); - if (link.startsWith("http") || //$NON-NLS-1$ - link.startsWith("file:/")) { //$NON-NLS-1$ - openLinkInBrowser(link); - } else if (link.startsWith("page:")) { //$NON-NLS-1$ - // Switch to an internal page - setActivePage(link.substring(5 /* strlen("page:") */)); - } - } - }; - } - - /** - * Open the http link into a browser - * - * @param link The URL to open in a browser - */ - private void openLinkInBrowser(String link) { - try { - IWorkbenchBrowserSupport wbs = WorkbenchBrowserSupport.getInstance(); - wbs.createBrowser(BROWSER_ID).openURL(new URL(link)); - } catch (PartInitException e1) { - // pass - } catch (MalformedURLException e1) { - // pass - } - } - - /** - * Creates the XML source editor. - * <p/> - * Memorizes the index page of the source editor (it's always the last page, but the number - * of pages before can change.) - * <br/> - * Retrieves the underlying XML model from the StructuredEditor and attaches a listener to it. - * Finally triggers modelChanged() on the model listener -- derived classes can use this - * to initialize the model the first time. - * <p/> - * Called only once <em>after</em> createFormPages. - */ - private void createTextEditor() { - try { - mTextEditor = new TextEditor(); - int index = addPage(mTextEditor, getEditorInput()); - mTextPageIndex = index; - setPageText(index, mTextEditor.getTitle()); - - IDocumentProvider provider = mTextEditor.getDocumentProvider(); - mDocument = provider.getDocument(getEditorInput()); - - mDocument.addDocumentListener(new IDocumentListener() { - @Override - public void documentChanged(DocumentEvent event) { - onDocumentChanged(event); - } - - @Override - public void documentAboutToBeChanged(DocumentEvent event) { - // ignore - } - }); - - - } catch (PartInitException e) { - ErrorDialog.openError(getSite().getShell(), - "Android Text Editor Error", null, e.getStatus()); - } - } - - /** - * Gives access to the {@link IDocument} from the {@link TextEditor}, corresponding to - * the current file input. - * <p/> - * All edits should be wrapped in a {@link #wrapRewriteSession(Runnable)}. - * The actual document instance is a {@link SynchronizableDocument}, which creates a lock - * around read/set operations. The base API provided by {@link IDocument} provides ways to - * manipulate the document line per line or as a bulk. - */ - public IDocument getDocument() { - return mDocument; - } - - /** - * Returns the {@link IProject} for the edited file. - */ - public IProject getProject() { - if (mTextEditor != null) { - IEditorInput input = mTextEditor.getEditorInput(); - if (input instanceof FileEditorInput) { - FileEditorInput fileInput = (FileEditorInput)input; - IFile inputFile = fileInput.getFile(); - - if (inputFile != null) { - return inputFile.getProject(); - } - } - } - - return null; - } - - /** - * Runs the given operation in the context of a document RewriteSession. - * Takes care of properly starting and stopping the operation. - * <p/> - * The operation itself should just access {@link #getDocument()} and use the - * normal document's API to manipulate it. - * - * @see #getDocument() - */ - public void wrapRewriteSession(Runnable operation) { - if (mDocument instanceof IDocumentExtension4) { - IDocumentExtension4 doc4 = (IDocumentExtension4) mDocument; - - DocumentRewriteSession session = null; - try { - session = doc4.startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED_SMALL); - - operation.run(); - } catch(IllegalStateException e) { - AdtPlugin.log(e, "wrapRewriteSession failed"); - e.printStackTrace(); - } finally { - if (session != null) { - doc4.stopRewriteSession(session); - } - } - - } else { - // Not an IDocumentExtension4? Unlikely. Try the operation anyway. - operation.run(); - } - } - -} |