| /* |
| * Copyright (C) 2013 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; |
| |
| import com.intellij.application.options.editor.WebEditorOptions; |
| import com.intellij.codeInsight.CodeInsightSettings; |
| import com.intellij.ide.ui.UISettings; |
| import com.intellij.ide.util.PropertiesComponent; |
| import com.intellij.openapi.actionSystem.KeyboardShortcut; |
| import com.intellij.openapi.actionSystem.Shortcut; |
| import com.intellij.openapi.application.ApplicationInfo; |
| import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; |
| import com.intellij.openapi.extensions.ExtensionPointName; |
| import com.intellij.openapi.fileTypes.FileTypeManager; |
| import com.intellij.openapi.keymap.Keymap; |
| import com.intellij.openapi.keymap.KeymapManager; |
| import com.intellij.openapi.keymap.ex.KeymapManagerEx; |
| import com.intellij.openapi.keymap.impl.KeymapManagerImpl; |
| import com.intellij.openapi.util.SystemInfo; |
| import com.intellij.util.messages.MessageBus; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.Nullable; |
| |
| /** Customize Android IDE specific experience. */ |
| public class AndroidInitialConfigurator { |
| @NonNls |
| private static final ExtensionPointName<Runnable> EP_NAME = |
| ExtensionPointName.create("com.intellij.androidStudioInitializer"); |
| |
| @NonNls private static final String CONFIG_V1 = "AndroidInitConfigurator.V1"; |
| @NonNls private static final String CONFIG_V2 = "AndroidInitConfigurator.V2"; |
| @NonNls private static final String CONFIG_V3 = "AndroidInitConfigurator.V3"; |
| @NonNls private static final String CONFIG_V4 = "AndroidInitConfigurator.V4"; |
| |
| @SuppressWarnings("SpellCheckingInspection") |
| @NonNls private static final String TODO_TOOLWINDOW_ACTION_ID = "ActivateTODOToolWindow"; |
| @SuppressWarnings("SpellCheckingInspection") |
| @NonNls private static final String ANDROID_TOOLWINDOW_ACTION_ID = "ActivateAndroidToolWindow"; |
| |
| @SuppressWarnings("UnusedParameters") |
| public AndroidInitialConfigurator(MessageBus bus, |
| final PropertiesComponent propertiesComponent, |
| final FileTypeManager fileTypeManager) { |
| validateConfiguration(); |
| setupSystemProperties(); |
| customizeSettings(propertiesComponent); |
| |
| // change default key maps to add a activate Android ToolWindow shortcut |
| setActivateAndroidToolWindowShortcut(); |
| |
| activateAndroidStudioInitializerExtensions(); |
| } |
| |
| /** |
| * Validates that the IDE configuration follows Android Studio requirements. |
| */ |
| private static void validateConfiguration() { |
| String[] versions = { |
| ApplicationInfo.getInstance().getMajorVersion(), |
| ApplicationInfo.getInstance().getMinorVersion(), |
| ApplicationInfo.getInstance().getMicroVersion(), |
| ApplicationInfo.getInstance().getPatchVersion(), |
| }; |
| for (String version : versions) { |
| if (version == null || !version.matches("0|([1-9]+[0-9]*)")) { |
| throw new AssertionError("Invalid version component found: " + version); |
| } |
| } |
| } |
| |
| /** |
| * Setup some Java system properties based on environment variables. |
| * This makes it easier to do local testing. |
| */ |
| private static void setupSystemProperties() { |
| // If defined, AS_UPDATE_URL should point to the *root* of the updates.xml file to use |
| // and patches are expected to be in the same folder. |
| String updateUrl = System.getenv("AS_UPDATE_URL"); |
| if (updateUrl != null) { |
| if (!updateUrl.endsWith("/")) { |
| updateUrl += "/"; |
| } |
| // Set the Java system properties expected by UpdateChecker. |
| System.setProperty("idea.updates.url", updateUrl + "updates.xml"); |
| System.setProperty("idea.patches.url", updateUrl); |
| } |
| } |
| |
| private static void customizeSettings(PropertiesComponent propertiesComponent) { |
| if (!propertiesComponent.getBoolean(CONFIG_V4, false)) { |
| propertiesComponent.setValue(CONFIG_V4, "true"); |
| UISettings.getInstance().HIDE_TOOL_STRIPES = false; |
| |
| if (!propertiesComponent.getBoolean(CONFIG_V3, false)) { |
| propertiesComponent.setValue(CONFIG_V3, "true"); |
| // See https://youtrack.jetbrains.com/issue/IDEA-113332 |
| // It's not really fixed but worked around by turning off the =-quoting |
| WebEditorOptions.getInstance().setInsertQuotesForAttributeValue(false); |
| } |
| |
| if (!propertiesComponent.getBoolean(CONFIG_V1, false)) { |
| propertiesComponent.setValue(CONFIG_V1, "true"); |
| CodeInsightSettings.getInstance().AUTO_POPUP_JAVADOC_INFO = true; |
| UISettings.getInstance().SCROLL_TAB_LAYOUT_IN_EDITOR = true; |
| EditorSettingsExternalizable.getInstance().setVirtualSpace(false); |
| |
| // For Macs, use 10.5+ keymap as the default |
| if (SystemInfo.isMac) { |
| setDefaultMacKeymap(); |
| } |
| } |
| |
| if (!propertiesComponent.getBoolean(CONFIG_V2, false)) { |
| propertiesComponent.setValue(CONFIG_V2, "true"); |
| UISettings.getInstance().SHOW_MAIN_TOOLBAR = true; |
| } |
| } |
| } |
| |
| private static void setDefaultMacKeymap() { |
| KeymapManagerImpl instance = (KeymapManagerImpl)KeymapManager.getInstance(); |
| Keymap mac105Keymap = getMac105Keymap(); |
| if (mac105Keymap != null) { |
| instance.setActiveKeymap(mac105Keymap); |
| } |
| } |
| |
| @Nullable |
| private static Keymap getMac105Keymap() { |
| for (Keymap keymap: KeymapManagerEx.getInstanceEx().getAllKeymaps()) { |
| if (keymap.getName().contains("10.5")) { |
| return keymap; |
| } |
| } |
| |
| return null; |
| } |
| |
| private static void setActivateAndroidToolWindowShortcut() { |
| // The IntelliJ keymap implementation behaves as follows: |
| // - getting a shortcut from a keymap gets the shortcut only from that keymap, and not from its parent, unless no shortcuts |
| // are defined in the keymap itself |
| // - however, adding a shortcut to a keymap explicitly copies all the shortcuts for that action from the parent keymap to this keymap |
| // The upshot of all this is that to add a shortcut, we should do so in all the child keymaps first, then the parent keymap. |
| // The following code does a simplified implementation of this behavior by changing the default keymap last after all the other |
| // keymaps have been changed. |
| Keymap defaultKeymap = null; |
| for (Keymap keymap: KeymapManagerEx.getInstanceEx().getAllKeymaps()) { |
| if (KeymapManager.DEFAULT_IDEA_KEYMAP.equals(keymap.getName())) { |
| defaultKeymap = keymap; |
| continue; |
| } |
| setActivateAndroidToolWindowShortcut(keymap); |
| } |
| |
| if (defaultKeymap != null) { |
| setActivateAndroidToolWindowShortcut(defaultKeymap); |
| } |
| } |
| |
| private static void setActivateAndroidToolWindowShortcut(Keymap keymap) { |
| KeyboardShortcut shortcut = removeFirstKeyboardShortcut(keymap, TODO_TOOLWINDOW_ACTION_ID); |
| if (shortcut != null) { |
| keymap.addShortcut(ANDROID_TOOLWINDOW_ACTION_ID, shortcut); |
| } |
| } |
| |
| @Nullable |
| private static KeyboardShortcut removeFirstKeyboardShortcut(Keymap keymap, String actionId) { |
| Shortcut[] shortcuts = keymap.getShortcuts(actionId); |
| for (Shortcut each : shortcuts) { |
| if (each instanceof KeyboardShortcut) { |
| keymap.removeShortcut(actionId, each); |
| return (KeyboardShortcut)each; |
| } |
| } |
| |
| return null; |
| } |
| |
| private static void activateAndroidStudioInitializerExtensions() { |
| Runnable[] extensions = EP_NAME.getExtensions(); |
| for (Runnable r : extensions) { |
| r.run(); |
| } |
| } |
| } |