/* * 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.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtUtils; import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; 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.IEditorSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.part.FileEditorInput; abstract class VisualRefactoringAction implements IWorkbenchWindowActionDelegate { protected IWorkbenchWindow mWindow; protected ITextSelection mTextSelection; protected ITreeSelection mTreeSelection; protected LayoutEditorDelegate mDelegate; protected IFile mFile; /** * Keep track of the current workbench window. */ @Override public void init(IWorkbenchWindow window) { mWindow = window; } @Override 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 */ @Override 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; editor = AdtUtils.getActiveEditor(); mFile = getSelectedFile(editor); } else if (selection instanceof ITreeSelection) { Object firstElement = ((ITreeSelection)selection).getFirstElement(); if (firstElement instanceof CanvasViewInfo) { mTreeSelection = (ITreeSelection) selection; editor = AdtUtils.getActiveEditor(); mFile = getSelectedFile(editor); } } mDelegate = LayoutEditorDelegate.fromEditor(editor); action.setEnabled((mTextSelection != null || mTreeSelection != null) && mFile != null && mDelegate != null); } /** * Create a new instance of our refactoring and a wizard to configure it. */ @Override public abstract void run(IAction action); /** * 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(AdtConstants.NATURE_DEFAULT)) { return file; } } catch (CoreException e) { // ignore } } } } return null; } public static IAction create(String title, LayoutEditorDelegate editorDelegate, Class<? extends VisualRefactoringAction> clz) { return new ActionWrapper(title, editorDelegate, clz); } private static class ActionWrapper extends Action { private Class<? extends VisualRefactoringAction> mClass; private LayoutEditorDelegate mEditorDelegate; ActionWrapper(String title, LayoutEditorDelegate editorDelegate, Class<? extends VisualRefactoringAction> clz) { super(title); mEditorDelegate = editorDelegate; mClass = clz; } @Override public void run() { VisualRefactoringAction action; try { action = mClass.newInstance(); } catch (Exception e) { AdtPlugin.log(e, null); return; } IEditorSite site = mEditorDelegate.getEditor().getEditorSite(); action.init(site.getWorkbenchWindow()); ISelection selection = site.getSelectionProvider().getSelection(); action.selectionChanged(ActionWrapper.this, selection); if (isEnabled()) { action.run(ActionWrapper.this); } } } }