diff options
author | Jerome Gaillard <jgaillard@google.com> | 2015-04-24 18:07:11 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-04-24 18:07:11 +0000 |
commit | 744fa997da07350c3b55330b34b6a975f72609b7 (patch) | |
tree | d737e45ae47af20df73e119dadde0cd1736dc58d | |
parent | f4c6c6950ea258e4c6b3285468e19a3fb8c7b5f6 (diff) | |
parent | 8e0d340026c100cc7c1c766be4c5f65aafa3fd8c (diff) | |
download | idea-744fa997da07350c3b55330b34b6a975f72609b7.tar.gz |
am 8e0d3400: Merge "Adds renaming in the theme selector of the Theme Editor" into studio-1.3-dev automerge: df6dd83 automerge: fa79622
* commit '8e0d340026c100cc7c1c766be4c5f65aafa3fd8c':
Adds renaming in the theme selector of the Theme Editor
6 files changed, 92 insertions, 219 deletions
diff --git a/android/src/com/android/tools/idea/editors/theme/AttributesPanel.java b/android/src/com/android/tools/idea/editors/theme/AttributesPanel.java index 51bf9969127..124522cccd8 100644 --- a/android/src/com/android/tools/idea/editors/theme/AttributesPanel.java +++ b/android/src/com/android/tools/idea/editors/theme/AttributesPanel.java @@ -79,6 +79,16 @@ public class AttributesPanel { return ThemesListModel.SHOW_ALL_THEMES.equals(myThemeCombo.getSelectedItem()); } + public boolean isRenameSelected() { + Object selectedItem = myThemeCombo.getSelectedItem(); + if (!(selectedItem instanceof String)) { + // Selected themes are instances of EditedStyleItem + // So this method will return false on selecting a theme + return false; + } + return ((String)selectedItem).startsWith(ThemesListModel.RENAME); + } + public ThemeEditorStyle getSelectedTheme() { Object item = myThemeCombo.getSelectedItem(); if (item != null && !(item instanceof ThemeEditorStyle)) { diff --git a/android/src/com/android/tools/idea/editors/theme/ThemeEditorComponent.java b/android/src/com/android/tools/idea/editors/theme/ThemeEditorComponent.java index c1ac2d963d2..9fb59bbaa54 100644 --- a/android/src/com/android/tools/idea/editors/theme/ThemeEditorComponent.java +++ b/android/src/com/android/tools/idea/editors/theme/ThemeEditorComponent.java @@ -45,6 +45,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Splitter; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.rename.RenameDialog; import com.intellij.util.Processor; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; @@ -262,6 +264,12 @@ public class ThemeEditorComponent extends Splitter { } return; } + if (myPanel.isRenameSelected()) { + if (!renameTheme()) { + myPanel.getThemeCombo().getModel().setSelectedItem(mySelectedTheme); + } + return; + } mySelectedTheme = myPanel.getSelectedTheme(); saveCurrentSelectedTheme(); myCurrentSubStyle = null; @@ -343,6 +351,27 @@ public class ThemeEditorComponent extends Splitter { return false; } + /** + * Uses Android Studio refactoring to rename the current theme + * @return Whether the renaming is successful + */ + private boolean renameTheme() { + assert mySelectedTheme.isProjectStyle(); + PsiElement namePsiElement = mySelectedTheme.getNamePsiElement(); + if (namePsiElement == null) { + return false; + } + RenameDialog renameDialog = new RenameDialog(myModule.getProject(), namePsiElement, null, null); + renameDialog.show(); + if (renameDialog.isOK()) { + String newName = renameDialog.getNewName(); + String newQualifiedName = mySelectedTheme.getName().replace(mySelectedTheme.getSimpleName(), newName); + reload(newQualifiedName); + return true; + } + return false; + } + public void goToParent() { ThemeEditorStyle selectedStyle = getSelectedStyle(); if (selectedStyle == null) { @@ -605,11 +634,7 @@ public class ThemeEditorComponent extends Splitter { @Override public void tableChanged(TableModelEvent e) { if (e.getType() == TableModelEvent.UPDATE) { - - if (e.getLastRow() == 0) { // Indicates a change in the theme name - reload(model.getThemeNameInXml()); - } - else if (e.getLastRow() == TableModelEvent.HEADER_ROW) { // Indicates a change of the model + if (e.getLastRow() == TableModelEvent.HEADER_ROW) { // Indicates a change of the model myAttributesTable.updateRowHeights(); } } @@ -715,7 +740,7 @@ public class ThemeEditorComponent extends Splitter { return true; } int row = entry.getIdentifier().intValue(); - if (entry.getModel().isSpecialRow(row)) { + if (entry.getModel().isThemeParentRow(row)) { return true; } diff --git a/android/src/com/android/tools/idea/editors/theme/ThemesListModel.java b/android/src/com/android/tools/idea/editors/theme/ThemesListModel.java index 6ad86ff1c8c..1364a3bee7d 100644 --- a/android/src/com/android/tools/idea/editors/theme/ThemesListModel.java +++ b/android/src/com/android/tools/idea/editors/theme/ThemesListModel.java @@ -53,12 +53,14 @@ public class ThemesListModel extends AbstractListModel implements ComboBoxModel }; public static final String CREATE_NEW_THEME = "Create New Theme"; public static final String SHOW_ALL_THEMES = "Show all themes"; + public static final String RENAME = "Rename "; private static final Object[] EXTRA_OPTIONS = {SHOW_ALL_THEMES, SEPARATOR, CREATE_NEW_THEME}; private ImmutableList<ThemeEditorStyle> myThemeList; private Object mySelectedObject; private int myNumberProjectThemes; private int mySizeBeforeExtraOptions; + private boolean isRenameAllowed; public ThemesListModel(@NotNull ThemeResolver themeResolver) { this(themeResolver, null); @@ -134,12 +136,15 @@ public class ThemesListModel extends AbstractListModel implements ComboBoxModel @Override public int getSize() { - return mySizeBeforeExtraOptions + EXTRA_OPTIONS.length; + return mySizeBeforeExtraOptions + EXTRA_OPTIONS.length + (isRenameAllowed ? 1 : 0); } @NotNull @Override public Object getElementAt(int index) { + if (isRenameAllowed && index == getSize() - 1) { + return renameOption(); + } if (index >= mySizeBeforeExtraOptions) { return EXTRA_OPTIONS[index - mySizeBeforeExtraOptions]; } @@ -161,6 +166,12 @@ public class ThemesListModel extends AbstractListModel implements ComboBoxModel } if (!Objects.equal(mySelectedObject, anItem)) { mySelectedObject = anItem; + if (mySelectedObject instanceof ThemeEditorStyle) { + isRenameAllowed = ((ThemeEditorStyle)mySelectedObject).isProjectStyle(); + } + else { + isRenameAllowed = false; + } fireContentsChanged(this, -1, -1); } } @@ -170,4 +181,12 @@ public class ThemesListModel extends AbstractListModel implements ComboBoxModel public Object getSelectedItem() { return mySelectedObject; } + + @NotNull + private String renameOption() { + assert mySelectedObject instanceof ThemeEditorStyle; + ThemeEditorStyle theme = (ThemeEditorStyle)mySelectedObject; + assert theme.isProjectStyle(); + return RENAME + theme.getSimpleName(); + } } diff --git a/android/src/com/android/tools/idea/editors/theme/attributes/AttributesTableModel.java b/android/src/com/android/tools/idea/editors/theme/attributes/AttributesTableModel.java index 93257cc42e1..0a92723bc75 100644 --- a/android/src/com/android/tools/idea/editors/theme/attributes/AttributesTableModel.java +++ b/android/src/com/android/tools/idea/editors/theme/attributes/AttributesTableModel.java @@ -15,7 +15,6 @@ */ package com.android.tools.idea.editors.theme.attributes; -import com.android.SdkConstants; import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.resources.ResourceResolver; import com.android.resources.ResourceType; @@ -26,7 +25,6 @@ import com.android.tools.idea.editors.theme.datamodels.ThemeEditorStyle; import com.android.tools.idea.editors.theme.ThemeEditorUtils; import com.android.tools.idea.editors.theme.attributes.editors.AttributeReferenceRendererEditor; import com.android.tools.idea.editors.theme.attributes.editors.ColorEditor.ColorInfo; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.FileEditorManager; @@ -42,7 +40,6 @@ import org.jetbrains.annotations.NotNull; import spantable.CellSpanModel; import com.intellij.openapi.diagnostic.Logger; -import javax.swing.event.TableModelEvent; import javax.swing.table.AbstractTableModel; import java.awt.*; import java.awt.event.ActionEvent; @@ -65,11 +62,6 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan private final Configuration myConfiguration; private List<TableLabel> myLabels; /** - * Used to store the name of the theme as it is in the styles.xml file - * May be different from the name of mySelectedStyle as a reloading of the theme may be necessary - */ - private String myThemeNameInXml; - /** * Used to store the name of the theme parent as it is in the styles.xml file * May be different from the name of mySelectedStyle.getParent() as a reloading of the theme may be necessary */ @@ -83,10 +75,6 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan private final List<ThemePropertyChangedListener> myThemePropertyChangedListeners = new ArrayList<ThemePropertyChangedListener>(); public final ParentAttribute parentAttribute = new ParentAttribute(); - private final List<RowContents> mySpecialRows = ImmutableList.of( - new ThemeNameAttribute(), - parentAttribute - ); private AttributeReferenceRendererEditor.ClickListener myGoToDefinitionListener; @@ -143,10 +131,6 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan myThemePropertyChangedListeners.add(listener); } - public String getThemeNameInXml() { - return myThemeNameInXml; - } - public AttributesTableModel(@NotNull ThemeEditorStyle selectedStyle, @NotNull AttributesGrouper.GroupBy groupBy, @NotNull Configuration configuration, @@ -156,7 +140,6 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan myLabels = new ArrayList<TableLabel>(); mySelectedStyle = selectedStyle; myGroupBy = groupBy; - myThemeNameInXml = mySelectedStyle.getName(); myResourceResolver = configuration.getResourceResolver(); myConfiguration = configuration; @@ -173,11 +156,11 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan } public RowContents getRowContents(final int rowIndex) { - if (rowIndex < mySpecialRows.size()) { - return mySpecialRows.get(rowIndex); + if (rowIndex == 0) { + return parentAttribute; } - int offset = mySpecialRows.size(); + int offset = 1; for (final TableLabel label : myLabels) { final int labelRowIndex = label.getRowPosition() + offset; @@ -196,15 +179,15 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan } /** - * returns true if this row is not a attribute or a label and is the Theme name or Theme parent. + * returns true if this row is not a attribute or a label and is the Theme parent. */ - public boolean isSpecialRow(int row) { - return row < mySpecialRows.size(); + public boolean isThemeParentRow(int row) { + return row == 0; } @Override public int getRowCount() { - return myAttributes.size() + myLabels.size() + mySpecialRows.size(); + return myAttributes.size() + myLabels.size() + 1; } @Override @@ -252,7 +235,7 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan } /** - * Basically a union type, RowContents = LabelContents | AttributeContents | ParentAttribute | ThemeNameAttribute + * Basically a union type, RowContents = LabelContents | AttributeContents | ParentAttribute */ public interface RowContents { int getColumnSpan(int column); @@ -279,60 +262,6 @@ public class AttributesTableModel extends AbstractTableModel implements CellSpan ActionListener getResetCallback(); } - /** - * Deals with setting up the theme name as an attribute that can be changed - */ - private class ThemeNameAttribute implements RowContents { - @Override - public int getColumnSpan(int column) { - return 1; - } - - @Override - public Object getValueAt(int column) { - if (column == 0) { - return "Theme Name"; - } - else { - return mySelectedStyle.getSimpleName(); - } - } - - @Override - public void setValueAt(int column, Object value) { - if (column == 0) { - throw new RuntimeException("Tried to setValue at parent attribute label"); - } - else { - String newName = (String) value; - mySelectedStyle.setName(newName); - myThemeNameInXml = SdkConstants.STYLE_RESOURCE_PREFIX + newName; - - fireTableChanged(new TableModelEvent(AttributesTableModel.this, 0)); - } - } - - @Override - public Class<?> getCellClass(int column) { - return String.class; - } - - @Override - public boolean isCellEditable(int column) { - return (column == 1 && !mySelectedStyle.isReadOnly()); - } - - @Override - public ActionListener getGoToDefinitionCallback() { - return null; - } - - @Override - public ActionListener getResetCallback() { - return null; - } - } - public class ParentAttribute implements RowContents { private ActionListener myGotoDefinitionCallback; diff --git a/android/src/com/android/tools/idea/editors/theme/datamodels/ThemeEditorStyle.java b/android/src/com/android/tools/idea/editors/theme/datamodels/ThemeEditorStyle.java index dca2c3ad668..147ba4ac6b5 100644 --- a/android/src/com/android/tools/idea/editors/theme/datamodels/ThemeEditorStyle.java +++ b/android/src/com/android/tools/idea/editors/theme/datamodels/ThemeEditorStyle.java @@ -35,7 +35,6 @@ import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlTag; -import com.intellij.refactoring.rename.RenameProcessor; import org.jetbrains.android.dom.wrappers.ValueResourceElementWrapper; import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.annotations.NotNull; @@ -258,36 +257,6 @@ public class ThemeEditorStyle { } } - /** - * Uses refactor to change the name of the themes in all the xml files - * The theme needs to be reloaded in ThemeEditorComponent for the change to be complete - * THIS METHOD DOES NOT DIRECTLY MODIFY THE VALUE ONE GETS WHEN EVALUATING getName() - */ - public void setName(@NotNull final String newName) { - if (!isProjectStyle()) { - throw new UnsupportedOperationException("Non project styles can not be modified"); - } - - if (newName.equals(getSimpleName())) { - return; - } - - for (XmlTag sourceXml : getSourceXmls()) { - final XmlAttribute nameAttribute = sourceXml.getAttribute("name"); - if (nameAttribute == null) { - return; - } - - final XmlAttributeValue attributeValue = nameAttribute.getValueElement(); - if (attributeValue == null) { - return; - } - - RenameProcessor processor = new RenameProcessor(myProject, new ValueResourceElementWrapper(attributeValue), newName, false, false); - processor.run(); - } - } - @NotNull public StyleResolver getResolver() { return myThemeResolver; @@ -342,4 +311,27 @@ public class ThemeEditorStyle { } } + /** + * Returns a PsiElement of the name attribute for this theme + * made from a RANDOM sourceXml + */ + @Nullable + public PsiElement getNamePsiElement() { + List<XmlTag> sourceXmls = getSourceXmls(); + if (sourceXmls.isEmpty()){ + return null; + } + // Any sourceXml will do to get the name attribute from + final XmlAttribute nameAttribute = sourceXmls.get(0).getAttribute("name"); + if (nameAttribute == null) { + return null; + } + + XmlAttributeValue attributeValue = nameAttribute.getValueElement(); + if (attributeValue == null) { + return null; + } + + return new ValueResourceElementWrapper(attributeValue); + } } diff --git a/android/testSrc/com/android/tools/idea/editors/theme/ThemeNameChangeTest.java b/android/testSrc/com/android/tools/idea/editors/theme/ThemeNameChangeTest.java deleted file mode 100644 index 90d51bd183d..00000000000 --- a/android/testSrc/com/android/tools/idea/editors/theme/ThemeNameChangeTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.tools.idea.editors.theme; - - -import com.android.tools.idea.configurations.Configuration; -import com.android.tools.idea.configurations.ConfigurationManager; -import com.android.tools.idea.editors.theme.datamodels.ThemeEditorStyle; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.android.AndroidTestCase; - -import java.util.Collection; - -/** - * Tests the theme name changing feature in the Theme Editor - */ -public class ThemeNameChangeTest extends AndroidTestCase { - - /** - * Tests that changing the name of a theme propagates to that theme's children - */ - public void testThemeNameChange() { - VirtualFile myLayout = myFixture.copyFileToProject("themeEditor/layout.xml", "res/layout/layout.xml"); - myFixture.copyFileToProject("themeEditor/themeNameChangeStyles.xml", "res/values/styles.xml"); - - ConfigurationManager configurationManager = myFacet.getConfigurationManager(); - Configuration configuration = configurationManager.getConfiguration(myLayout); - ThemeResolver themeResolver = new ThemeResolver(configuration); - ThemeEditorStyle theme = themeResolver.getTheme("@style/TestTheme"); - - assertNotNull(theme); - theme.setName("NewName"); - - configuration.setTheme(null); - themeResolver = new ThemeResolver(configuration); - - // Checks the theme with the old name does not exist anymore - theme = themeResolver.getTheme("@style/TestTheme"); - assertNull(theme); - - // Checks the theme with the new name exists - theme = themeResolver.getTheme("@style/NewName"); - assertNotNull(theme); - assertTrue(themeResolver.isTheme(theme)); - - // Checks the children of the theme have been updated - ThemeEditorStyle childTheme = themeResolver.getTheme("@style/NewChildTheme"); - assertNotNull(childTheme); - assertTrue(theme.equals(childTheme.getParent())); - - // Checks that the renaming correctly handles the Parent.Child naming convention - childTheme = themeResolver.getTheme("@style/TestTheme.Child"); - assertNull(childTheme); - childTheme = themeResolver.getTheme("@style/NewName.Child"); - assertNotNull(childTheme); - - childTheme = themeResolver.getTheme("@style/TestTheme.OtherChild"); - // The name of this child theme is not modified - // Because it explicitly specifies its parent in the xml file - // So the Parent.Child convention is ignored in that case - assertNotNull(childTheme); - assertTrue(theme.equals(childTheme.getParent())); - } - - /** - * Tests that nothing happens when changing a theme's name to its current name - */ - public void testNoChange() { - VirtualFile myLayout = myFixture.copyFileToProject("themeEditor/layout.xml", "res/layout/layout.xml"); - myFixture.copyFileToProject("themeEditor/themeNameChangeStyles.xml", "res/values/styles.xml"); - - ConfigurationManager configurationManager = myFacet.getConfigurationManager(); - Configuration configuration = configurationManager.getConfiguration(myLayout); - ThemeResolver themeResolver = new ThemeResolver(configuration); - ThemeEditorStyle theme = themeResolver.getTheme("@style/TestTheme"); - - assertNotNull(theme); - theme.setName("TestTheme"); - - configuration.setTheme(null); - ThemeResolver newThemeResolver = new ThemeResolver(configuration); - Collection<ThemeEditorStyle> oldThemes = themeResolver.getThemes(); - Collection<ThemeEditorStyle> newThemes = newThemeResolver.getThemes(); - assertTrue(oldThemes.size() == newThemes.size()); - for (ThemeEditorStyle oldTheme : oldThemes) { - assertTrue(newThemes.contains(oldTheme)); - } - } -} |