/* * Copyright (C) 2011 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.layout.refactoring; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AndroidConstants; import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor; import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ITreeSelection; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.FileEditorInput; abstract class VisualRefactoringAction implements IWorkbenchWindowActionDelegate { protected IWorkbenchWindow mWindow; protected ITextSelection mTextSelection; protected ITreeSelection mTreeSelection; protected LayoutEditor mEditor; protected IFile mFile; /** * Keep track of the current workbench window. */ public void init(IWorkbenchWindow window) { mWindow = window; } public void dispose() { } /** * Examine the selection to determine if the action should be enabled or not. * <p/> * Keep a link to the relevant selection structure (i.e. a part of the Java AST). */ public void selectionChanged(IAction action, ISelection selection) { // Look for selections in XML and in the layout UI editor // Note, two kinds of selections are returned here: // ITextSelection on a Java source window // IStructuredSelection in the outline or navigator // This simply deals with the refactoring based on a non-empty selection. // At that point, just enable the action and later decide if it's valid when it actually // runs since we don't have access to the AST yet. mTextSelection = null; mTreeSelection = null; mFile = null; IEditorPart editor = null; if (selection instanceof ITextSelection) { mTextSelection = (ITextSelection) selection; if (mTextSelection.getLength() > 0) { editor = getActiveEditor(); mFile = getSelectedFile(editor); } } else if (selection instanceof ITreeSelection) { Object firstElement = ((ITreeSelection)selection).getFirstElement(); if (firstElement instanceof CanvasViewInfo) { mTreeSelection = (ITreeSelection) selection; editor = getActiveEditor(); mFile = getSelectedFile(editor); } } if (editor instanceof LayoutEditor) { mEditor = (LayoutEditor) editor; } action.setEnabled((mTextSelection != null || mTreeSelection != null) && mFile != null && mEditor != null); } /** * Create a new instance of our refactoring and a wizard to configure it. */ public abstract void run(IAction action); /** * Returns the active editor (hopefully matching our selection) or null. */ private IEditorPart getActiveEditor() { IWorkbenchWindow wwin = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (wwin != null) { IWorkbenchPage page = wwin.getActivePage(); if (page != null) { return page.getActiveEditor(); } } return null; } /** * Returns the active {@link IFile} (hopefully matching our selection) or null. * The file is only returned if it's a file from a project with an Android nature. * <p/> * At that point we do not try to analyze if the selection nor the file is suitable * for the refactoring. This check is performed when the refactoring is invoked since * it can then produce meaningful error messages as needed. */ private IFile getSelectedFile(IEditorPart editor) { if (editor != null) { IEditorInput input = editor.getEditorInput(); if (input instanceof FileEditorInput) { FileEditorInput fi = (FileEditorInput) input; IFile file = fi.getFile(); if (file.exists()) { IProject proj = file.getProject(); try { if (proj != null && proj.hasNature(AndroidConstants.NATURE_DEFAULT)) { return file; } } catch (CoreException e) { // ignore } } } } return null; } public static IAction create(String title, LayoutEditor editor, Class<? extends VisualRefactoringAction> clz) { return new ActionWrapper(title, editor, clz); } private static class ActionWrapper extends Action { private Class<? extends VisualRefactoringAction> mClass; private LayoutEditor mEditor; ActionWrapper(String title, LayoutEditor editor, Class<? extends VisualRefactoringAction> clz) { super(title); mEditor = editor; mClass = clz; } @Override public void run() { VisualRefactoringAction action; try { action = mClass.newInstance(); } catch (Exception e) { AdtPlugin.log(e, null); return; } action.init(mEditor.getEditorSite().getWorkbenchWindow()); ISelection selection = mEditor.getEditorSite().getSelectionProvider().getSelection(); action.selectionChanged(ActionWrapper.this, selection); if (isEnabled()) { action.run(ActionWrapper.this); } } } }