diff --git a/plugins/android-designer/src/META-INF/plugin.xml b/plugins/android-designer/src/META-INF/plugin.xml index 26fb86c102b5..36fb46e22dca 100644 --- a/plugins/android-designer/src/META-INF/plugin.xml +++ b/plugins/android-designer/src/META-INF/plugin.xml @@ -20,4 +20,8 @@ serviceImplementation="com.intellij.android.designer.model.ViewsMetaManager"/> + + + + diff --git a/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerRefactoringContextProvider.java b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerRefactoringContextProvider.java new file mode 100644 index 000000000000..13854f92f2d4 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerRefactoringContextProvider.java @@ -0,0 +1,38 @@ +package com.intellij.android.designer; + +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.designSurface.EditableArea; +import com.intellij.designer.model.EmptyXmlTag; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.android.refactoring.AndroidRefactoringContextProvider; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author Eugene.Kudelevsky + */ +public class AndroidDesignerRefactoringContextProvider implements AndroidRefactoringContextProvider { + @Override + public XmlTag getComponentTag(@NotNull DataContext dataContext) { + final EditableArea area = EditableArea.DATA_KEY.getData(dataContext); + + if (area == null) { + return null; + } + final List selection = area.getSelection(); + + if (selection.size() != 1) { + return null; + } + final RadComponent component = selection.get(0); + + if (!(component instanceof RadViewComponent)) { + return null; + } + final XmlTag tag = ((RadViewComponent)component).getTag(); + return tag != null && !tag.equals(EmptyXmlTag.INSTANCE) ? tag : null; + } +} diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java index 4df167a3cd20..ca1275b3c02b 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java @@ -38,9 +38,7 @@ import com.intellij.designer.palette.DefaultPaletteItem; import com.intellij.designer.palette.PaletteGroup; import com.intellij.designer.palette.PaletteItem; import com.intellij.designer.palette.PaletteToolWindowManager; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.module.Module; @@ -62,6 +60,7 @@ import com.intellij.util.ThrowableConsumer; import com.intellij.util.ThrowableRunnable; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.maven.AndroidMavenUtil; +import org.jetbrains.android.refactoring.AndroidExtractStyleAction; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.sdk.AndroidSdkUtils; import org.jetbrains.android.uipreview.*; @@ -137,6 +136,8 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { }); myActionPanel.getPopupGroup().addSeparator(); + myActionPanel.getPopupGroup().add(buildRefactorActionGroup()); + AnAction gotoDeclaration = new AnAction("Go To Declaration") { @Override public void update(AnActionEvent e) { @@ -155,6 +156,15 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { myActionPanel.getPopupGroup().add(gotoDeclaration); } + @NotNull + private static ActionGroup buildRefactorActionGroup() { + final DefaultActionGroup group = new DefaultActionGroup("_Refactor", true); + final ActionManager manager = ActionManager.getInstance(); + final AnAction action = manager.getAction(AndroidExtractStyleAction.ACTION_ID); + group.add(new AndroidRefactoringActionWrapper("_Extract style", action)); + return group; + } + private void reparseFile() { try { storeState(); diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidRefactoringActionWrapper.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidRefactoringActionWrapper.java new file mode 100644 index 000000000000..5000c9cd7057 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidRefactoringActionWrapper.java @@ -0,0 +1,34 @@ +package com.intellij.android.designer.designSurface; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.Presentation; +import org.jetbrains.annotations.NotNull; + +/** + * @author Eugene.Kudelevsky + */ +class AndroidRefactoringActionWrapper extends AnAction { + private final AnAction myWrappee; + + public AndroidRefactoringActionWrapper(@NotNull String text, @NotNull AnAction wrappee) { + super(text, null, null); + myWrappee = wrappee; + getTemplatePresentation().setDescription(wrappee.getTemplatePresentation().getDescription()); + } + + @Override + public void actionPerformed(AnActionEvent e) { + myWrappee.actionPerformed(e); + } + + @Override + public void update(AnActionEvent e) { + myWrappee.update(e); + final Presentation p = e.getPresentation(); + if (!p.isVisible()) { + p.setEnabled(false); + p.setVisible(true); + } + } +} diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml index 287282e4fda2..385a4a5d4128 100644 --- a/plugins/android/src/META-INF/plugin.xml +++ b/plugins/android/src/META-INF/plugin.xml @@ -241,5 +241,6 @@ + diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidExtractStyleAction.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidExtractStyleAction.java index 5449ea7d1c30..c2077f28ae85 100644 --- a/plugins/android/src/org/jetbrains/android/refactoring/AndroidExtractStyleAction.java +++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidExtractStyleAction.java @@ -5,7 +5,9 @@ import com.android.resources.ResourceType; import com.android.sdklib.SdkConstants; import com.intellij.lang.Language; import com.intellij.lang.xml.XMLLanguage; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.UndoConfirmationPolicy; @@ -39,6 +41,7 @@ import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -52,6 +55,8 @@ import java.util.Set; * @author Eugene.Kudelevsky */ public class AndroidExtractStyleAction extends BaseRefactoringAction { + @NonNls public static final String ACTION_ID = "AndroidExtractStyleAction"; + private static String[] NON_EXTRACTABLE_ATTRIBUTES = new String[]{AndroidDomUtil.ATTR_ID, AndroidDomUtil.ATTR_TEXT, AndroidDomUtil.ATTR_HINT, AndroidDomUtil.ATTR_SRC, AndroidDomUtil.ATTR_ON_CLICK}; @@ -109,7 +114,45 @@ public class AndroidExtractStyleAction extends BaseRefactoringAction { @Override protected RefactoringActionHandler getHandler(DataContext dataContext) { - return new MyHandler(myTestConfig); + final XmlTag componentTag = getComponentTag(dataContext); + return new MyHandler(myTestConfig, componentTag); + } + + @Override + public void update(AnActionEvent e) { + final DataContext context = e.getDataContext(); + + final DataContext patchedContext = new DataContext() { + @Override + public Object getData(@NonNls String dataId) { + final Object data = context.getData(dataId); + if (data != null) { + return data; + } + if (LangDataKeys.PSI_ELEMENT.is(dataId)) { + return getComponentTag(context); + } + return null; + } + }; + super.update(new AnActionEvent(e.getInputEvent(), patchedContext, e.getPlace(), e.getPresentation(), + e.getActionManager(), e.getModifiers())); + } + + @Nullable + private static XmlTag getComponentTag(DataContext dataContext) { + if (dataContext == null) { + return null; + } + + for (AndroidRefactoringContextProvider provider : AndroidRefactoringContextProvider.EP_NAME.getExtensions()) { + final XmlTag componentTag = provider.getComponentTag(dataContext); + + if (componentTag != null) { + return componentTag; + } + } + return null; } @Override @@ -293,13 +336,19 @@ public class AndroidExtractStyleAction extends BaseRefactoringAction { private static class MyHandler implements RefactoringActionHandler { private final MyTestConfig myTestConfig; + private final XmlTag myTag; - private MyHandler(@Nullable MyTestConfig testConfig) { + private MyHandler(@Nullable MyTestConfig testConfig, @Nullable XmlTag tag) { myTestConfig = testConfig; + myTag = tag; } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { + if (myTag != null) { + doExtractStyle(myTag, myTestConfig); + return; + } final PsiElement element = getElementAtCaret(editor, file); if (element == null) { return; @@ -313,6 +362,10 @@ public class AndroidExtractStyleAction extends BaseRefactoringAction { @Override public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { + if (myTag != null) { + doExtractStyle(myTag, myTestConfig); + return; + } if (elements.length != 1) { return; } diff --git a/plugins/android/src/org/jetbrains/android/refactoring/AndroidRefactoringContextProvider.java b/plugins/android/src/org/jetbrains/android/refactoring/AndroidRefactoringContextProvider.java new file mode 100644 index 000000000000..e3a625139e53 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/refactoring/AndroidRefactoringContextProvider.java @@ -0,0 +1,18 @@ +package org.jetbrains.android.refactoring; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +public interface AndroidRefactoringContextProvider { + ExtensionPointName EP_NAME = + ExtensionPointName.create("org.jetbrains.android.refactoringContextProvider"); + + @Nullable + XmlTag getComponentTag(@NotNull DataContext dataContext); +}