aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ThemeMenuAction.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ThemeMenuAction.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ThemeMenuAction.java318
1 files changed, 318 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ThemeMenuAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ThemeMenuAction.java
new file mode 100644
index 000000000..b1ce21d36
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ThemeMenuAction.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2012 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.configuration;
+
+import static com.android.SdkConstants.ANDROID_STYLE_RESOURCE_PREFIX;
+
+import com.android.ide.eclipse.adt.internal.editors.Hyperlinks;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SubmenuAction;
+import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
+import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo.ActivityAttributes;
+import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.text.hyperlink.IHyperlink;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ToolItem;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Action which creates a submenu displaying available themes
+ */
+class ThemeMenuAction extends SubmenuAction {
+ private static final String DEVICE_LIGHT_PREFIX =
+ ANDROID_STYLE_RESOURCE_PREFIX + "Theme.DeviceDefault.Light"; //$NON-NLS-1$
+ private static final String HOLO_LIGHT_PREFIX =
+ ANDROID_STYLE_RESOURCE_PREFIX + "Theme.Holo.Light"; //$NON-NLS-1$
+ private static final String DEVICE_PREFIX =
+ ANDROID_STYLE_RESOURCE_PREFIX + "Theme.DeviceDefault"; //$NON-NLS-1$
+ private static final String HOLO_PREFIX =
+ ANDROID_STYLE_RESOURCE_PREFIX + "Theme.Holo"; //$NON-NLS-1$
+ private static final String LIGHT_PREFIX =
+ ANDROID_STYLE_RESOURCE_PREFIX +"Theme.Light"; //$NON-NLS-1$
+ private static final String THEME_PREFIX =
+ ANDROID_STYLE_RESOURCE_PREFIX +"Theme"; //$NON-NLS-1$
+
+ // Constants used to indicate what type of menu is being shown, such that
+ // the submenus can lazily construct their contents
+ private static final int MENU_MANIFEST = 1;
+ private static final int MENU_PROJECT = 2;
+ private static final int MENU_THEME = 3;
+ private static final int MENU_THEME_LIGHT = 4;
+ private static final int MENU_HOLO = 5;
+ private static final int MENU_HOLO_LIGHT = 6;
+ private static final int MENU_DEVICE = 7;
+ private static final int MENU_DEVICE_LIGHT = 8;
+ private static final int MENU_ALL = 9;
+
+ private final ConfigurationChooser mConfigChooser;
+ private final List<String> mThemeList;
+ /** Type of menu; one of the constants {@link #MENU_ALL} etc */
+ private final int mType;
+
+ ThemeMenuAction(int type, String title, ConfigurationChooser configuration,
+ List<String> themeList) {
+ super(title);
+ mType = type;
+ mConfigChooser = configuration;
+ mThemeList = themeList;
+ }
+
+ static void showThemeMenu(ConfigurationChooser configChooser, ToolItem combo,
+ List<String> themeList) {
+ MenuManager manager = new MenuManager();
+
+ // First show the currently selected theme (grayed out since you can't
+ // reselect it)
+ Configuration configuration = configChooser.getConfiguration();
+ String currentTheme = configuration.getTheme();
+ String currentName = null;
+ if (currentTheme != null) {
+ currentName = ResourceHelper.styleToTheme(currentTheme);
+ SelectThemeAction action = new SelectThemeAction(configChooser,
+ currentName,
+ currentTheme,
+ true /* selected */);
+ action.setEnabled(false);
+ manager.add(action);
+ manager.add(new Separator());
+ }
+
+ String preferred = configuration.computePreferredTheme();
+ if (preferred != null && !preferred.equals(currentTheme)) {
+ manager.add(new SelectThemeAction(configChooser,
+ ResourceHelper.styleToTheme(preferred),
+ preferred, false /* selected */));
+ manager.add(new Separator());
+ }
+
+ IAndroidTarget target = configuration.getTarget();
+ int apiLevel = target != null ? target.getVersion().getApiLevel() : 1;
+ boolean hasHolo = apiLevel >= 11; // Honeycomb
+ boolean hasDeviceDefault = apiLevel >= 14; // ICS
+
+ // TODO: Add variations of the current theme here, e.g.
+ // if you're using Theme.Holo, add Theme.Holo.Dialog, Theme.Holo.Panel,
+ // Theme.Holo.Wallpaper etc
+
+ manager.add(new ThemeMenuAction(MENU_PROJECT, "Project Themes",
+ configChooser, themeList));
+ manager.add(new ThemeMenuAction(MENU_MANIFEST, "Manifest Themes",
+ configChooser, themeList));
+
+ manager.add(new Separator());
+
+ if (hasHolo) {
+ manager.add(new ThemeMenuAction(MENU_HOLO, "Holo",
+ configChooser, themeList));
+ manager.add(new ThemeMenuAction(MENU_HOLO_LIGHT, "Holo.Light",
+ configChooser, themeList));
+ }
+ if (hasDeviceDefault) {
+ manager.add(new ThemeMenuAction(MENU_DEVICE, "DeviceDefault",
+ configChooser, themeList));
+ manager.add(new ThemeMenuAction(MENU_DEVICE_LIGHT, "DeviceDefault.Light",
+ configChooser, themeList));
+ }
+ manager.add(new ThemeMenuAction(MENU_THEME, "Theme",
+ configChooser, themeList));
+ manager.add(new ThemeMenuAction(MENU_THEME_LIGHT, "Theme.Light",
+ configChooser, themeList));
+
+ // TODO: Add generic types like Wallpaper, Dialog, Alert, etc here, with
+ // submenus for picking it within each theme category?
+
+ manager.add(new Separator());
+ manager.add(new ThemeMenuAction(MENU_ALL, "All",
+ configChooser, themeList));
+
+ if (currentTheme != null) {
+ assert currentName != null;
+ manager.add(new Separator());
+ String title = String.format("Open %1$s Declaration...", currentName);
+ manager.add(new OpenThemeAction(title, configChooser.getEditedFile(), currentTheme));
+ }
+
+ Menu menu = manager.createContextMenu(configChooser.getShell());
+
+ Rectangle bounds = combo.getBounds();
+ Point location = new Point(bounds.x, bounds.y + bounds.height);
+ location = combo.getParent().toDisplay(location);
+ menu.setLocation(location.x, location.y);
+ menu.setVisible(true);
+ }
+
+ @Override
+ protected void addMenuItems(Menu menu) {
+ switch (mType) {
+ case MENU_ALL:
+ addMenuItems(menu, mThemeList);
+ break;
+
+ case MENU_MANIFEST: {
+ IProject project = mConfigChooser.getEditedFile().getProject();
+ ManifestInfo manifest = ManifestInfo.get(project);
+ Configuration configuration = mConfigChooser.getConfiguration();
+ String activity = configuration.getActivity();
+ if (activity != null) {
+ ActivityAttributes attributes = manifest.getActivityAttributes(activity);
+ if (attributes != null) {
+ String theme = attributes.getTheme();
+ if (theme != null) {
+ addMenuItem(menu, theme, isSelectedTheme(theme));
+ }
+ }
+ }
+
+ String manifestTheme = manifest.getManifestTheme();
+ boolean found = false;
+ Set<String> allThemes = new HashSet<String>();
+ if (manifestTheme != null) {
+ found = true;
+ allThemes.add(manifestTheme);
+ }
+ for (ActivityAttributes info : manifest.getActivityAttributesMap().values()) {
+ if (info.getTheme() != null) {
+ found = true;
+ allThemes.add(info.getTheme());
+ }
+ }
+ List<String> sorted = new ArrayList<String>(allThemes);
+ Collections.sort(sorted);
+ String current = configuration.getTheme();
+ for (String theme : sorted) {
+ boolean selected = theme.equals(current);
+ addMenuItem(menu, theme, selected);
+ }
+ if (!found) {
+ addDisabledMessageItem("No themes are registered in the manifest");
+ }
+ break;
+ }
+ case MENU_PROJECT: {
+ int size = mThemeList.size();
+ List<String> themes = new ArrayList<String>(size);
+ for (int i = 0; i < size; i++) {
+ String theme = mThemeList.get(i);
+ if (ResourceHelper.isProjectStyle(theme)) {
+ themes.add(theme);
+ }
+ }
+ if (themes.isEmpty()) {
+ addDisabledMessageItem("There are no local theme styles in the project");
+ } else {
+ addMenuItems(menu, themes);
+ }
+ break;
+ }
+ case MENU_THEME: {
+ // Can't just use the usual filterThemes() call here because we need
+ // to exclude on multiple prefixes: Holo, DeviceDefault, Light, ...
+ List<String> themes = new ArrayList<String>(mThemeList.size());
+ for (String theme : mThemeList) {
+ if (theme.startsWith(THEME_PREFIX)
+ && !theme.startsWith(LIGHT_PREFIX)
+ && !theme.startsWith(HOLO_PREFIX)
+ && !theme.startsWith(DEVICE_PREFIX)) {
+ themes.add(theme);
+ }
+ }
+
+ addMenuItems(menu, themes);
+ break;
+ }
+ case MENU_THEME_LIGHT:
+ addMenuItems(menu, filterThemes(LIGHT_PREFIX, null));
+ break;
+ case MENU_HOLO:
+ addMenuItems(menu, filterThemes(HOLO_PREFIX, HOLO_LIGHT_PREFIX));
+ break;
+ case MENU_HOLO_LIGHT:
+ addMenuItems(menu, filterThemes(HOLO_LIGHT_PREFIX, null));
+ break;
+ case MENU_DEVICE:
+ addMenuItems(menu, filterThemes(DEVICE_PREFIX, DEVICE_LIGHT_PREFIX));
+ break;
+ case MENU_DEVICE_LIGHT:
+ addMenuItems(menu, filterThemes(DEVICE_LIGHT_PREFIX, null));
+ break;
+ }
+ }
+
+ private List<String> filterThemes(String include, String exclude) {
+ List<String> themes = new ArrayList<String>(mThemeList.size());
+ for (String theme : mThemeList) {
+ if (theme.startsWith(include) && (exclude == null || !theme.startsWith(exclude))) {
+ themes.add(theme);
+ }
+ }
+
+ return themes;
+ }
+
+ private void addMenuItems(Menu menu, List<String> themes) {
+ String current = mConfigChooser.getConfiguration().getTheme();
+ for (String theme : themes) {
+ addMenuItem(menu, theme, theme.equals(current));
+ }
+ }
+
+ private boolean isSelectedTheme(String theme) {
+ return theme.equals(mConfigChooser.getConfiguration().getTheme());
+ }
+
+ private void addMenuItem(Menu menu, String theme, boolean selected) {
+ String title = ResourceHelper.styleToTheme(theme);
+ SelectThemeAction action = new SelectThemeAction(mConfigChooser, title, theme, selected);
+ new ActionContributionItem(action).fill(menu, -1);
+ }
+
+ private static class OpenThemeAction extends Action {
+ private final String mTheme;
+ private final IFile mFile;
+
+ private OpenThemeAction(String title, IFile file, String theme) {
+ super(title, IAction.AS_PUSH_BUTTON);
+ mFile = file;
+ mTheme = theme;
+ }
+
+ @Override
+ public void run() {
+ IProject project = mFile.getProject();
+ IHyperlink[] links = Hyperlinks.getResourceLinks(null, mTheme, project, null);
+ if (links != null && links.length > 0) {
+ IHyperlink link = links[0];
+ link.open();
+ }
+ }
+ }
+}