diff --git a/plugins/android-designer/src/com/intellij/android/designer/actions/ProfileAction.java b/plugins/android-designer/src/com/intellij/android/designer/actions/ProfileAction.java index 5aa97f7d971e..3994478d9d5a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/actions/ProfileAction.java +++ b/plugins/android-designer/src/com/intellij/android/designer/actions/ProfileAction.java @@ -132,10 +132,12 @@ public class ProfileAction { dialog.show(); if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { - // TODO: send event to manager's - myProfileList.setProfiles(dialog.getResult()); updateActions(); } } + + public void externalUpdate() { + // TODO + } } \ No newline at end of file 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 72e28104e612..f61cd8d0fab4 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 @@ -54,6 +54,7 @@ import com.intellij.util.ThrowableRunnable; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.uipreview.*; +import org.jetbrains.android.util.AndroidSdkNotConfiguredException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -247,8 +248,6 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { private void createRenderer(final String layoutXmlText, final ThrowableRunnable runnable) throws Exception { - // TODO: (profile|device|target|...|theme) panel - if (mySession == null) { ApplicationManager.getApplication().invokeLater( new Runnable() { @@ -273,29 +272,33 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { @Override public void run() { - AndroidPlatform platform = AndroidPlatform.getInstance(myModule); - IAndroidTarget target = platform.getTarget(); - AndroidFacet facet = AndroidFacet.getInstance(myModule); - - LayoutDeviceManager layoutDeviceManager = new LayoutDeviceManager(); - layoutDeviceManager.loadDevices(platform.getSdkData()); - LayoutDevice layoutDevice = layoutDeviceManager.getCombinedList().get(0); - - LayoutDeviceConfiguration deviceConfiguration = layoutDevice.getConfigurations().get(0); - - FolderConfiguration config = new FolderConfiguration(); - config.set(deviceConfiguration.getConfiguration()); - config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL)); - config.setNightModeQualifier(new NightModeQualifier(NightMode.NIGHT)); - config.setLanguageQualifier(new LanguageQualifier()); - config.setRegionQualifier(new RegionQualifier()); - - float xdpi = deviceConfiguration.getDevice().getXDpi(); - float ydpi = deviceConfiguration.getDevice().getYDpi(); - - ThemeData theme = new ThemeData("Theme", false); - try { + AndroidPlatform platform = AndroidPlatform.getInstance(myModule); + if (platform == null) { + throw new AndroidSdkNotConfiguredException(); + } + + IAndroidTarget target = platform.getTarget(); + AndroidFacet facet = AndroidFacet.getInstance(myModule); + + LayoutDeviceManager layoutDeviceManager = new LayoutDeviceManager(); + layoutDeviceManager.loadDevices(platform.getSdkData()); + LayoutDevice layoutDevice = layoutDeviceManager.getCombinedList().get(0); + + LayoutDeviceConfiguration deviceConfiguration = layoutDevice.getConfigurations().get(0); + + FolderConfiguration config = new FolderConfiguration(); + config.set(deviceConfiguration.getConfiguration()); + config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL)); + config.setNightModeQualifier(new NightModeQualifier(NightMode.NIGHT)); + config.setLanguageQualifier(new LanguageQualifier()); + config.setRegionQualifier(new RegionQualifier()); + + float xdpi = deviceConfiguration.getDevice().getXDpi(); + float ydpi = deviceConfiguration.getDevice().getYDpi(); + + ThemeData theme = new ThemeData("Theme", false); + mySession = RenderUtil.createRenderSession(getProject(), layoutXmlText, myFile, target, facet, config, xdpi, ydpi, theme); ApplicationManager.getApplication().invokeLater(new Runnable() { @@ -336,6 +339,15 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { super.showError(message, e); } + public ProfileAction getProfileAction() { + return myProfileAction; + } + + @Override + public void activate() { + myProfileAction.externalUpdate(); + } + @Override public void dispose() { myPSIChangeListener.stop(); diff --git a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileDialog.java b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileDialog.java index 57884729769e..d6da61b2d94a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileDialog.java +++ b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileDialog.java @@ -75,6 +75,7 @@ public class ProfileDialog extends DialogWrapper { myProfileModel.add(new ProfileWrapper(profile)); } + // TODO: DND reorder elements myProfileList = new JBList(); myProfileList.setModel(myProfileModel); myProfileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); diff --git a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java index e2505ea6f9df..89f7832ba95c 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java +++ b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileList.java @@ -15,85 +15,163 @@ */ package com.intellij.android.designer.profile; +import com.intellij.ProjectTopics; +import com.intellij.android.designer.designSurface.AndroidDesignerEditorPanel; +import com.intellij.designer.DesignerToolWindowManager; +import com.intellij.designer.designSurface.DesignerEditorPanel; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; -import com.intellij.util.xmlb.XmlSerializerUtil; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ModuleRootEvent; +import com.intellij.openapi.roots.ModuleRootListener; +import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Tag; -import com.intellij.util.xmlb.annotations.Transient; +import org.jetbrains.android.sdk.AndroidPlatform; +import org.jetbrains.android.sdk.AndroidSdkAdditionalData; +import org.jetbrains.android.sdk.AndroidSdkType; import org.jetbrains.android.uipreview.LayoutDeviceManager; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @author Alexander Lobas + * @author Eugene.Kudelevsky */ @State(name = "AndroidDesignerProfile", storages = {@Storage(file = "$WORKSPACE_FILE$")}) -public class ProfileList implements PersistentStateComponent { - private List myProfiles = new ArrayList(); - private Profile myFullProfile = new Profile(); - private String mySelection = ""; - @Transient +public class ProfileList implements PersistentStateComponent { private final LayoutDeviceManager myLayoutDeviceManager = new LayoutDeviceManager(); + private final Map myModule2Sdk = new HashMap(); + private ProfileState myState = new ProfileState(); + private final Project myProject; + + public ProfileList(Project project) { + myProject = project; + updateModules(); + project.getMessageBus().connect(project).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() { + @Override + public void beforeRootsChange(ModuleRootEvent event) { + } + + @Override + public void rootsChanged(ModuleRootEvent event) { + updatePlatform(); + } + }); + } public static ProfileList getInstance(Project project) { return ServiceManager.getService(project, ProfileList.class); } - @Tag("profiles") - @AbstractCollection(surroundWithTag = false) + public Sdk getModuleSdk(Module module) { + return myModule2Sdk.get(module); + } + + private void updateModules() { + myModule2Sdk.clear(); + for (Module module : ModuleManager.getInstance(myProject).getModules()) { + myModule2Sdk.put(module, ModuleRootManager.getInstance(module).getSdk()); + } + } + + private void updatePlatform() { + DesignerEditorPanel designer = DesignerToolWindowManager.getInstance(myProject).getActiveDesigner(); + if (designer instanceof AndroidDesignerEditorPanel) { + Module module = designer.getModule(); + Sdk prevSdk = myModule2Sdk.get(module); + Sdk newSdk = ModuleRootManager.getInstance(module).getSdk(); + if (newSdk != null + && (newSdk.getSdkType() instanceof AndroidSdkType || + (prevSdk != null && prevSdk.getSdkType() instanceof AndroidSdkType)) + && !newSdk.equals(prevSdk)) { + + AndroidSdkAdditionalData additionalData = (AndroidSdkAdditionalData)newSdk.getSdkAdditionalData(); + AndroidPlatform newPlatform = additionalData != null ? additionalData.getAndroidPlatform() : null; + ((AndroidDesignerEditorPanel)designer).getProfileAction().getProfileManager().update(newPlatform); + } + } + + updateModules(); + } + public List getProfiles() { - return myProfiles; + return myState.getProfiles(); } public void setProfiles(List profiles) { - myProfiles = profiles; - } - - public String getSelection() { - return mySelection; + myState.setProfiles(profiles); } public void setSelection(String selection) { - mySelection = selection; + myState.setSelection(selection); } public Profile getFullProfile() { - return myFullProfile; + return myState.getFullProfile(); } - public void setFullProfile(Profile fullProfile) { - myFullProfile = fullProfile; - } - - @Transient public LayoutDeviceManager getLayoutDeviceManager() { return myLayoutDeviceManager; } - @Nullable - @Transient public Profile getProfile() { - for (Profile profile : myProfiles) { - if (mySelection.equals(profile.getName())) { + String selection = myState.getSelection(); + for (Profile profile : getProfiles()) { + if (selection.equals(profile.getName())) { return profile; } } - return myFullProfile; + return getFullProfile(); } @Override - public ProfileList getState() { - return this; + public ProfileState getState() { + return myState; } @Override - public void loadState(ProfileList state) { - XmlSerializerUtil.copyBean(state, this); + public void loadState(ProfileState state) { + myState = state; + } + + public static class ProfileState { + private List myProfiles = new ArrayList(); + private Profile myFullProfile = new Profile(); + private String mySelection = ""; + + @Tag("profiles") + @AbstractCollection(surroundWithTag = false) + public List getProfiles() { + return myProfiles; + } + + public void setProfiles(List profiles) { + myProfiles = profiles; + } + + public String getSelection() { + return mySelection; + } + + public void setSelection(String selection) { + mySelection = selection; + } + + public Profile getFullProfile() { + return myFullProfile; + } + + public void setFullProfile(Profile fullProfile) { + myFullProfile = fullProfile; + } } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileManager.java b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileManager.java index 2e0e7838b0cc..4e60a17c400a 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileManager.java +++ b/plugins/android-designer/src/com/intellij/android/designer/profile/ProfileManager.java @@ -22,8 +22,6 @@ import com.android.resources.NightMode; import com.android.resources.UiMode; import com.android.sdklib.IAndroidTarget; import com.intellij.designer.actions.AbstractComboBoxAction; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.module.Module; @@ -176,32 +174,20 @@ public class ProfileManager { }; myThemeAction = new AbstractComboBoxAction() { - @Override - protected boolean addSeparator(DefaultActionGroup actionGroup, ThemeData item) { - if (item == ThemeManager.FRAMEWORK || item == ThemeManager.PROJECT) { - // TODO: ??????? - actionGroup.add(new AnAction("") { - @Override - public void actionPerformed(AnActionEvent e) { - } - }); - actionGroup.addSeparator(item.getName()); - return true; - } - return false; - } - @Override protected void update(ThemeData theme, Presentation presentation, boolean popup) { - presentation.setEnabled(theme != null); + presentation.setEnabled(theme != null && theme != ThemeManager.FRAMEWORK && theme != ThemeManager.PROJECT); if (theme != null) { - if (!theme.isProjectTheme() && myThemeManager.getAddedThemes().contains(new ThemeData(theme.getName(), true))) { + if (!popup && !theme.isProjectTheme() && myThemeManager.getAddedThemes().contains(new ThemeData(theme.getName(), true))) { presentation.setText(theme.getName() + " (framework)"); } - else { + else if (!popup || theme == ThemeManager.FRAMEWORK || theme == ThemeManager.PROJECT) { presentation.setText(theme.getName()); } + else { + presentation.setText(" " + theme.getName()); + } } else { presentation.setText("[None]"); @@ -220,6 +206,7 @@ public class ProfileManager { return 20; // TODO: not worked } }; + myThemeAction.showDisabledActions(true); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -242,8 +229,6 @@ public class ProfileManager { } else { update(getPlatform()); - myDockModeAction.setItems(Arrays.asList(UiMode.values()), UiMode.getEnum(myProfile.getDockMode())); - myNightModeAction.setItems(Arrays.asList(NightMode.values()), NightMode.getEnum(myProfile.getNightMode())); } } @@ -262,6 +247,8 @@ public class ProfileManager { updateLocales(); updatePlatform(platform); updateThemes(); + myDockModeAction.setItems(Arrays.asList(UiMode.values()), UiMode.getEnum(myProfile.getDockMode())); + myNightModeAction.setItems(Arrays.asList(NightMode.values()), NightMode.getEnum(myProfile.getNightMode())); } } @@ -559,9 +546,6 @@ public class ProfileManager { break; } } - if (newTheme == null) { - System.out.println("Theme: " + themeName + " not found"); - } } if (newTheme == null && !themes.isEmpty()) { for (ThemeData theme : themes) { @@ -573,6 +557,7 @@ public class ProfileManager { } myThemeAction.setItems(themes, newTheme); + myThemeAction.update(); updateTheme(newTheme); myRefreshAction.run(); } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java index dd773cf78b10..ef8e0773719f 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java @@ -15,11 +15,11 @@ */ package com.intellij.designer.actions; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.DefaultActionGroup; -import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopup; +import com.intellij.openapi.util.IconLoader; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,9 +32,12 @@ import java.util.List; * @author Alexander Lobas */ public abstract class AbstractComboBoxAction extends ComboBoxAction { + private static final Icon CHECKED = IconLoader.getIcon("/actions/check.png"); + private List myItems = Collections.emptyList(); private T mySelection; private Presentation myPresentation; + private boolean myShowDisabledActions; public void setItems(List items, @Nullable T selection) { myItems = items; @@ -57,6 +60,10 @@ public abstract class AbstractComboBoxAction extends ComboBoxAction { update(); } + public void showDisabledActions(boolean value) { + myShowDisabledActions = value; + } + @Override public JComponent createCustomComponent(Presentation presentation) { myPresentation = presentation; @@ -69,6 +76,23 @@ public abstract class AbstractComboBoxAction extends ComboBoxAction { return panel; } + @Override + protected ComboBoxButton createComboBoxButton(Presentation presentation) { + if (myShowDisabledActions) { + return new ComboBoxButton(presentation) { + @Override + protected ListPopup createPopup(Runnable onDispose) { + ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup( + null, createPopupActionGroup(this), getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true, onDispose, + getMaxRows()); + popup.setMinimumSize(new Dimension(getMinWidth(), getMinHeight())); + return popup; + } + }; + } + return super.createComboBoxButton(presentation); + } + public void update() { update(mySelection, myPresentation, false); } @@ -92,8 +116,11 @@ public abstract class AbstractComboBoxAction extends ComboBoxAction { } } }; - update(item, action.getTemplatePresentation(), true); actionGroup.add(action); + + Presentation presentation = action.getTemplatePresentation(); + presentation.setIcon(mySelection == item ? CHECKED : null); + update(item, presentation, true); } return actionGroup; diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/DesignerActionPanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/DesignerActionPanel.java index edf8d92a9c72..fa6bc87f4d46 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/DesignerActionPanel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/DesignerActionPanel.java @@ -26,10 +26,6 @@ import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.NonNls; import javax.swing.*; -import java.awt.*; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; import java.util.List; import java.util.Set; @@ -89,11 +85,34 @@ public class DesignerActionPanel implements DataProvider { } public void update() { - myToolbar.setVisible(myActionGroup.getChildrenCount() > 0); + boolean oldVisible = myToolbar.isVisible(); + boolean newVisible = isVisible(myActionGroup); + myToolbar.setVisible(newVisible); + if (oldVisible && newVisible) { + ((JComponent)myToolbar.getParent()).revalidate(); + } + } + + private static boolean isVisible(DefaultActionGroup group) { + if (group.getChildrenCount() == 0) { + return false; + } + + for (AnAction action : group.getChildren(null)) { + if (action instanceof DefaultActionGroup) { + if (isVisible((DefaultActionGroup)action)) { + return true; + } + } + else { + return true; + } + } + return false; } private void updateSelectionActions(List selection) { - boolean update = myDynamicGroup.getChildrenCount() > 0; + boolean update = isVisible(myDynamicGroup); for (AnAction action : myDynamicGroup.getChildActionsOrStubs()) { action.unregisterCustomShortcutSet(myShortcuts); @@ -114,7 +133,7 @@ public class DesignerActionPanel implements DataProvider { for (RadComponent component : selection) { component.addSelectionActions(myDynamicGroup, myShortcuts, selection); } - update |= myDynamicGroup.getChildrenCount() > 0; + update |= isVisible(myDynamicGroup); if (update) { update();