diff options
Diffstat (limited to 'platform/platform-impl/src/com/intellij')
86 files changed, 2245 insertions, 647 deletions
diff --git a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java index 142b3924f96a..ec112437520b 100644 --- a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java +++ b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java @@ -181,8 +181,6 @@ public class ITNProxy { private static HttpURLConnection post(URL url, byte[] bytes) throws IOException { HttpURLConnection connection = (HttpURLConnection)HttpConfigurable.getInstance().openConnection(url.toString()); - connection.setReadTimeout(10 * 1000); - connection.setConnectTimeout(10 * 1000); connection.setRequestMethod(HTTP_POST); connection.setDoInput(true); connection.setDoOutput(true); diff --git a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java index ac197b192284..340fbb9ae186 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,18 +49,17 @@ public class HelpManagerImpl extends HelpManager { private Object myFXHelpBrowser = null; public void invokeHelp(@Nullable String id) { - if (myHelpSet == null) { myHelpSet = createHelpSet(); } - if (SystemInfo.isJavaVersionAtLeast("1.7.0.40") && Registry.is("ide.help.fxbrowser")) { - showHelpInFXBrowser(id); + if (MacHelpUtil.isApplicable() && MacHelpUtil.invokeHelp(id)) { return; } - if (MacHelpUtil.isApplicable()) { - if (MacHelpUtil.invokeHelp(id)) return; + if (SystemInfo.isJavaVersionAtLeast("1.7.0.40") && Registry.is("ide.help.fxbrowser")) { + showHelpInFXBrowser(id); + return; } if (myHelpSet == null) { diff --git a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java index a73295c90f74..27fd6f52e4a6 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java +++ b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java @@ -28,20 +28,20 @@ import org.jetbrains.annotations.Nullable; */ public class MacHelpUtil { static boolean invokeHelp(@NonNls @Nullable String id) { - id = id == null || "top".equals(id) ? "startpage" : id; + if (id == null || "top".equals(id)) id = "startpage"; - final ID mainBundle = Foundation.invoke("NSBundle", "mainBundle"); - final ID helpBundle = Foundation.invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleHelpBookName")); + ID mainBundle = Foundation.invoke("NSBundle", "mainBundle"); + ID helpBundle = Foundation.invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleHelpBookName")); if (helpBundle.equals(ID.NIL)) { return false; } - final ID helpManager = Foundation.invoke("NSHelpManager", "sharedHelpManager"); + + ID helpManager = Foundation.invoke("NSHelpManager", "sharedHelpManager"); Foundation.invoke(helpManager, "openHelpAnchor:inBook:", Foundation.nsString(id), helpBundle); return true; } static boolean isApplicable() { - return SystemInfo.isMac && Registry.is("ide.mac.show.native.help") && !PlatformUtils.isCidr() && !PlatformUtils - .isIdeaCommunity(); + return SystemInfo.isMac && Registry.is("ide.mac.show.native.help") && !PlatformUtils.isCidr() && !PlatformUtils.isIdeaCommunity(); } } diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index c8699c083ef4..a7d07c9fa1e8 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -590,7 +590,6 @@ public class IdeEventQueue extends EventQueue { final Method setActive = ReflectionUtil.findMethod(ReflectionUtil.getClassDeclaredMethods(KeyboardFocusManager.class, false), resetMethod, Window.class); if (setActive != null) { try { - setActive.setAccessible(true); setActive.invoke(mgr, (Window)showingWindow); } catch (Exception exc) { @@ -630,7 +629,6 @@ public class IdeEventQueue extends EventQueue { if (showingWindow == null) { Method getNativeFocusOwner = ReflectionUtil.getDeclaredMethod(KeyboardFocusManager.class, "getNativeFocusOwner"); if (getNativeFocusOwner != null) { - getNativeFocusOwner.setAccessible(true); try { Object owner = getNativeFocusOwner.invoke(mgr); if (owner instanceof Component) { @@ -744,10 +742,7 @@ public class IdeEventQueue extends EventQueue { && !(e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT)) { try { if (stickyAltField == null) { - stickyAltField = Class - .forName("com.sun.java.swing.plaf.windows.WindowsRootPaneUI$AltProcessor") - .getDeclaredField("menuCanceledOnPress"); - stickyAltField.setAccessible(true); + stickyAltField = ReflectionUtil.getDeclaredField(Class.forName("com.sun.java.swing.plaf.windows.WindowsRootPaneUI$AltProcessor"), "menuCanceledOnPress"); } stickyAltField.set(null, true); } diff --git a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java index dd969f32ac04..baefe3db672d 100644 --- a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java +++ b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java @@ -139,8 +139,7 @@ public final class SwingCleanuper implements ApplicationComponent{ focusManager.setGlobalCurrentFocusCycleRoot(null); //Remove focus leaks try { - final Method m = KeyboardFocusManager.class.getDeclaredMethod("setGlobalFocusOwner", Component.class); - m.setAccessible(true); + final Method m = ReflectionUtil.getDeclaredMethod(KeyboardFocusManager.class,"setGlobalFocusOwner", Component.class); m.invoke(focusManager, new Object[]{null}); } catch (Exception e) { @@ -169,7 +168,6 @@ public final class SwingCleanuper implements ApplicationComponent{ if (SystemInfo.isMac) { try { field = ReflectionUtil.findField(AccessibleContext.class, Object.class, "nativeAXResource"); - field.setAccessible(true); } catch (NoSuchFieldException ignored) { } @@ -228,7 +226,6 @@ public final class SwingCleanuper implements ApplicationComponent{ Object resource = myNativeAXResourceField.get(ac); if (resource != null && resource.getClass().getName().equals("apple.awt.CAccessible")) { Field accessible = ReflectionUtil.findField(resource.getClass(), Accessible.class, "accessible"); - accessible.setAccessible(true); accessible.set(resource, null); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java index b76839fbffe4..411f2d9d93bb 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java @@ -45,6 +45,7 @@ import static java.util.Arrays.asList; */ public class CreateLauncherScriptAction extends DumbAwareAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateLauncherScriptAction"); + private static final String CONTENTS = "/Contents"; public static boolean isAvailable() { return SystemInfo.isUnix; @@ -137,6 +138,8 @@ public class CreateLauncherScriptAction extends DumbAwareAction { // for Macs just use "*.app" final String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase(); runPath += "/bin/" + productName + ".sh"; + } else if (runPath.endsWith(CONTENTS)) { + runPath = runPath.substring(0, runPath.length() - CONTENTS.length()); } String launcherContents = ExecUtil.loadTemplate(CreateLauncherScriptAction.class.getClassLoader(), "launcher.py", newHashMap(asList("$CONFIG_PATH$", "$RUN_PATH$"), diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java index c7c729c89424..786a5825e783 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java @@ -50,7 +50,7 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt public final AtomicBoolean myCanceled = new AtomicBoolean(false); - public CustomizeFeaturedPluginsStepPanel() throws OfflineException { + public CustomizeFeaturedPluginsStepPanel(PluginGroups pluginGroups) throws OfflineException { setLayout(new GridLayout(1, 1)); JPanel gridPanel = new JPanel(new GridLayout(0, 3)); JBScrollPane scrollPane = @@ -58,9 +58,9 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt scrollPane.getVerticalScrollBar().setUnitIncrement(10); scrollPane.setBorder(null); - Map<String, String> config = PluginGroups.getInstance().getFeaturedPlugins(); + Map<String, String> config = pluginGroups.getFeaturedPlugins(); boolean isEmptyOrOffline = true; - List<IdeaPluginDescriptor> pluginsFromRepository = PluginGroups.getInstance().getPluginsFromRepository(); + List<IdeaPluginDescriptor> pluginsFromRepository = pluginGroups.getPluginsFromRepository(); for (Map.Entry<String, String> entry : config.entrySet()) { JPanel groupPanel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); @@ -263,5 +263,5 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt return "New plugins can also be downloaded in " + CommonBundle.settingsTitle() + " | Plugins"; } - static class OfflineException extends Exception {}; + public static class OfflineException extends Exception {}; } diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java index 1b0644a3a20f..be37f9d9d7f6 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java @@ -16,6 +16,7 @@ package com.intellij.ide.customize; import com.intellij.ide.startup.StartupActionScriptManager; +import com.intellij.idea.Main; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.SystemInfo; @@ -62,6 +63,26 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis System.setProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE, "true"); } + public static void showCustomSteps(String stepsProviderName) { + final CustomizeIDEWizardStepsProvider provider; + + try { + Class<CustomizeIDEWizardStepsProvider> providerClass = (Class<CustomizeIDEWizardStepsProvider>)Class.forName(stepsProviderName); + provider = providerClass.newInstance(); + } + catch (Throwable e) { + Main.showMessage("Start Failed", e); + return; + } + + new CustomizeIDEWizardDialog() { + @Override + protected void initSteps() { + provider.initSteps(this, mySteps); + } + }.show(); + } + @Override protected void dispose() { System.clearProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE); @@ -73,9 +94,11 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis if (SystemInfo.isMac) { mySteps.add(new CustomizeKeyboardSchemeStepPanel()); } - mySteps.add(new CustomizePluginsStepPanel()); + + PluginGroups pluginGroups = new PluginGroups(); + mySteps.add(new CustomizePluginsStepPanel(pluginGroups)); try { - mySteps.add(new CustomizeFeaturedPluginsStepPanel()); + mySteps.add(new CustomizeFeaturedPluginsStepPanel(pluginGroups)); } catch (CustomizeFeaturedPluginsStepPanel.OfflineException e) { //skip featured step if we're offline diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardStepsProvider.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardStepsProvider.java new file mode 100644 index 000000000000..ceea34db05fd --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardStepsProvider.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * 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.intellij.ide.customize; + +import java.util.List; + +/** + * @author Alexander Lobas + */ +public interface CustomizeIDEWizardStepsProvider { + void initSteps(CustomizeIDEWizardDialog wizardDialog, List<AbstractCustomizeWizardStep> steps); +}
\ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java index 2b35ebe7a6fc..53b215516c09 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java @@ -94,6 +94,6 @@ public class CustomizeKeyboardSchemeStepPanel extends AbstractCustomizeWizardSte @Override public String getHTMLFooter() { - return "Keymap scheme can be later changed in " + CommonBundle.settingsTitle() + " | Keymap"; + return "Keymap scheme can be changed later in " + CommonBundle.settingsTitle() + " | Keymap"; } } diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java index 9bd14b69cb47..8924c09780dd 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java @@ -19,7 +19,6 @@ import com.intellij.ide.plugins.PluginManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.VerticalFlowLayout; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; import com.intellij.ui.ColorUtil; import com.intellij.ui.JBCardLayout; @@ -52,9 +51,11 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple private static final String CUSTOMIZE_COMMAND = "Customize"; private final JBCardLayout myCardLayout; private final IdSetPanel myCustomizePanel; + private final PluginGroups myPluginGroups; - public CustomizePluginsStepPanel() { + public CustomizePluginsStepPanel(PluginGroups pluginGroups) { + myPluginGroups = pluginGroups; myCardLayout = new JBCardLayout(); setLayout(myCardLayout); JPanel gridPanel = new JPanel(new GridLayout(0, COLS)); @@ -66,8 +67,8 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple add(scrollPane, MAIN); add(myCustomizePanel, CUSTOMIZE); - Map<String, Pair<String, List<String>>> groups = PluginGroups.getInstance().getTree(); - for (final Map.Entry<String, Pair<String, List<String>>> entry : groups.entrySet()) { + Map<String, Pair<Icon, List<String>>> groups = pluginGroups.getTree(); + for (final Map.Entry<String, Pair<Icon, List<String>>> entry : groups.entrySet()) { final String group = entry.getKey(); if (PluginGroups.CORE.equals(group)) continue; @@ -89,10 +90,10 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple return isGroupEnabled(group); } }; - groupPanel.add(new JLabel(IconLoader.getIcon(entry.getValue().getFirst())), gbc); + groupPanel.add(new JLabel(entry.getValue().getFirst()), gbc); //gbc.insets.bottom = 5; groupPanel.add(titleLabel, gbc); - JLabel descriptionLabel = new JLabel(PluginGroups.getInstance().getDescription(group), SwingConstants.CENTER) { + JLabel descriptionLabel = new JLabel(pluginGroups.getDescription(group), SwingConstants.CENTER) { @Override public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); @@ -116,7 +117,7 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple gbc.weighty = 0; JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5)); buttonsPanel.setOpaque(false); - if (PluginGroups.getInstance().getSets(group).size() == 1) { + if (pluginGroups.getSets(group).size() == 1) { buttonsPanel.add(createLink(SWITCH_COMMAND + ":" + group, getGroupSwitchTextProvider(group))); } else { @@ -152,11 +153,11 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple if (SWITCH_COMMAND.equals(command)) { boolean enabled = isGroupEnabled(group); - List<IdSet> sets = PluginGroups.getInstance().getSets(group); + List<IdSet> sets = myPluginGroups.getSets(group); for (IdSet idSet : sets) { String[] ids = idSet.getIds(); for (String id : ids) { - PluginGroups.getInstance().setPluginEnabledWithDependencies(id, !enabled); + myPluginGroups.setPluginEnabledWithDependencies(id, !enabled); } } repaint(); @@ -190,17 +191,17 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple @Override public String getText() { return (isGroupEnabled(group) ? "Disable" : "Enable") + - (PluginGroups.getInstance().getSets(group).size() > 1 ? " All" : ""); + (myPluginGroups.getSets(group).size() > 1 ? " All" : ""); } }; } private boolean isGroupEnabled(String group) { - List<IdSet> sets = PluginGroups.getInstance().getSets(group); + List<IdSet> sets = myPluginGroups.getSets(group); for (IdSet idSet : sets) { String[] ids = idSet.getIds(); for (String id : ids) { - if (PluginGroups.getInstance().isPluginEnabled(id)) return true; + if (myPluginGroups.isPluginEnabled(id)) return true; } } return false; @@ -229,7 +230,7 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple @Override public boolean beforeOkAction() { try { - PluginManager.saveDisabledPlugins(PluginGroups.getInstance().getDisabledPluginIds(), false); + PluginManager.saveDisabledPlugins(myPluginGroups.getDisabledPluginIds(), false); } catch (IOException ignored) { } @@ -269,9 +270,9 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple public void linkSelected(LinkLabel aSource, String command) { if (myGroup == null) return; boolean enable = "enable".equals(command); - List<IdSet> idSets = PluginGroups.getInstance().getSets(myGroup); + List<IdSet> idSets = myPluginGroups.getSets(myGroup); for (IdSet set : idSets) { - PluginGroups.getInstance().setIdSetEnabled(set, enable); + myPluginGroups.setIdSetEnabled(set, enable); } CustomizePluginsStepPanel.this.repaint(); } @@ -280,19 +281,19 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple myGroup = group; myTitleLabel.setText("<html><body><h2 style=\"text-align:left;\">" + group + "</h2></body></html>"); myContentPanel.removeAll(); - List<IdSet> idSets = PluginGroups.getInstance().getSets(group); + List<IdSet> idSets = myPluginGroups.getSets(group); for (final IdSet set : idSets) { - final JCheckBox checkBox = new JCheckBox(set.getTitle(), PluginGroups.getInstance().isIdSetAllEnabled(set)); + final JCheckBox checkBox = new JCheckBox(set.getTitle(), myPluginGroups.isIdSetAllEnabled(set)); checkBox.setModel(new JToggleButton.ToggleButtonModel() { @Override public boolean isSelected() { - return PluginGroups.getInstance().isIdSetAllEnabled(set); + return myPluginGroups.isIdSetAllEnabled(set); } }); checkBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - PluginGroups.getInstance().setIdSetEnabled(set, !checkBox.isSelected()); + myPluginGroups.setIdSetEnabled(set, !checkBox.isSelected()); CustomizePluginsStepPanel.this.repaint(); } }); diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java index 1af2fb883efb..b369e49f8bca 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java @@ -34,12 +34,12 @@ import java.util.LinkedHashMap; import java.util.Map; public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep { + protected static final String DEFAULT = "Default"; + protected static final String DARCULA = "Darcula"; + protected static final String INTELLIJ = "IntelliJ"; + protected static final String ALLOY = "Alloy. IDEA Theme"; + protected static final String GTK = "GTK+"; - private static final String DEFAULT = "Default"; - private static final String DARCULA = "Darcula"; - private static final String INTELLIJ = "IntelliJ"; - private static final String ALLOY = "Alloy. IDEA Theme"; - private static final String GTK = "GTK+"; private boolean myInitial = true; private boolean myColumnMode; private JLabel myPreviewLabel; @@ -49,24 +49,8 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep { setLayout(new BorderLayout(10, 10)); IconLoader.activate(); - if (SystemInfo.isMac) { - myLafNames.put(DEFAULT, IconLoader.getIcon("/lafs/OSXAqua.png")); - myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/OSXDarcula.png")); - } - else if (SystemInfo.isWindows) { - //if (PlatformUtils.isIdeaCommunity()) { - myLafNames.put(INTELLIJ, IconLoader.getIcon("/lafs/WindowsIntelliJ.png")); - //} - //else { - // myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png")); - //} - myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/WindowsDarcula.png")); - } - else { - myLafNames.put(INTELLIJ, IconLoader.getIcon("/lafs/LinuxIntelliJ.png")); - myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/LinuxDarcula.png")); - myLafNames.put(GTK, IconLoader.getIcon("/lafs/LinuxGTK.png")); - } + initLafs(); + myColumnMode = myLafNames.size() > 2; JPanel buttonsPanel = new JPanel(new GridLayout(myColumnMode ? myLafNames.size() : 1, myColumnMode ? 1 : myLafNames.size(), 5, 5)); ButtonGroup group = new ButtonGroup(); @@ -111,6 +95,31 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep { myInitial = false; } + protected void initLafs() { + if (SystemInfo.isMac) { + addLaf(DEFAULT, "/lafs/OSXAqua.png"); + addLaf(DARCULA, "/lafs/OSXDarcula.png"); + } + else if (SystemInfo.isWindows) { + //if (PlatformUtils.isIdeaCommunity()) { + addLaf(INTELLIJ,"/lafs/WindowsIntelliJ.png"); + //} + //else { + // addLaf(ALLOY, "/lafs/WindowsAlloy.png"); + //} + addLaf(DARCULA, "/lafs/WindowsDarcula.png"); + } + else { + addLaf(INTELLIJ, "/lafs/LinuxIntelliJ.png"); + addLaf(DARCULA, "/lafs/LinuxDarcula.png"); + addLaf(GTK, "/lafs/LinuxGTK.png"); + } + } + + protected final void addLaf(String name, String icon) { + myLafNames.put(name, IconLoader.getIcon(icon)); + } + @Override public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); @@ -118,7 +127,6 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep { return size; } - @Override public String getTitle() { return "UI Themes"; diff --git a/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java b/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java index 47f8863b9ceb..fb406d21359a 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java @@ -28,7 +28,7 @@ class IdSet { String myTitle; String[] myIds; - IdSet(String description) { + IdSet(final PluginGroups pluginGroups, String description) { int i = description.indexOf(":"); if (i > 0) { myTitle = description.substring(0, i); @@ -38,7 +38,7 @@ class IdSet { myIds = ContainerUtil.filter(myIds, new Condition<String>() { @Override public boolean value(String id) { - return PluginGroups.getInstance().findPlugin(id) != null; + return pluginGroups.findPlugin(id) != null; } }).toArray(new String[]{}); @@ -47,7 +47,7 @@ class IdSet { } if (myTitle == null && myIds.length>0) { //noinspection ConstantConditions - myTitle = PluginGroups.getInstance().findPlugin(myIds[0]).getName(); + myTitle = pluginGroups.findPlugin(myIds[0]).getName(); } if (myTitle != null) { for (String skipWord : BLACK_LIST) { diff --git a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java index 930901d55105..b17805579869 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java @@ -16,7 +16,6 @@ package com.intellij.ide.customize; import com.intellij.ide.plugins.IdeaPluginDescriptor; -import com.intellij.ide.plugins.PluginManager; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.ide.plugins.RepositoryHelper; import com.intellij.idea.StartupUtil; @@ -27,19 +26,18 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; +import icons.PlatformImplIcons; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.io.File; import java.util.*; -class PluginGroups { +public class PluginGroups { static final String CORE = "Core"; private static final int MAX_DESCR_LENGTH = 55; - - private static PluginGroups instance = null; - - final Map<String, Pair<String, List<String>>> myTree = new LinkedHashMap<String, Pair<String, List<String>>>(); + final Map<String, Pair<Icon, List<String>>> myTree = new LinkedHashMap<String, Pair<Icon, List<String>>>(); final Map<String, String> myFeaturedPlugins = new LinkedHashMap<String, String>(); private final Map<String, List<IdSet>> myGroups = new LinkedHashMap<String, List<IdSet>>(); @@ -50,15 +48,7 @@ class PluginGroups { private boolean myInitialized = false; private Set<String> myFeaturedIds = new HashSet<String>(); - - static synchronized PluginGroups getInstance() { - if (instance == null) { - instance = new PluginGroups(); - } - return instance; - } - - private PluginGroups() { + public PluginGroups() { myAllPlugins = PluginManagerCore.loadDescriptors(null); try { myPluginsFromRepository.addAll(RepositoryHelper.loadPluginsFromRepository(null)); @@ -68,8 +58,12 @@ class PluginGroups { } PluginManagerCore.loadDisabledPlugins(new File(PathManager.getConfigPath()).getPath(), myDisabledPluginIds); + initGroups(myTree, myFeaturedPlugins); + } - myTree.put(CORE, Pair.create((String)null, Arrays.asList( + protected void + initGroups(Map<String, Pair<Icon, List<String>>> tree, Map<String, String> featuredPlugins) { + tree.put(CORE, Pair.create((Icon)null, Arrays.asList( "com.intellij.copyright", "com.intellij.java-i18n", "org.intellij.intelliLang", @@ -78,7 +72,7 @@ class PluginGroups { "Type Migration", "ZKM" ))); - myTree.put("Java Frameworks", Pair.create("/plugins/JavaFrameworks.png", Arrays.asList( + tree.put("Java Frameworks", Pair.create(PlatformImplIcons.JavaFrameworks, Arrays.asList( "com.intellij.appengine", "org.intellij.grails", "com.intellij.gwt", @@ -113,12 +107,12 @@ class PluginGroups { "com.intellij.aspectj", "Osmorc" ))); - myTree.put("Build Tools", Pair.create("/plugins/BuildTools.png", Arrays.asList( + tree.put("Build Tools", Pair.create(PlatformImplIcons.BuildTools, Arrays.asList( "AntSupport", "Maven:org.jetbrains.idea.maven,org.jetbrains.idea.maven.ext", "org.jetbrains.plugins.gradle" ))); - myTree.put("Web Development", Pair.create("/plugins/WebDevelopment.png", Arrays.asList( + tree.put("Web Development", Pair.create(PlatformImplIcons.WebDevelopment, Arrays.asList( "HTML:HtmlTools,QuirksMode,W3Validators", "org.jetbrains.plugins.haml", "com.jetbrains.plugins.jade", @@ -132,24 +126,17 @@ class PluginGroups { "com.intellij.plugins.html.instantEditing", "com.jetbrains.restClient" ))); - myTree.put("Version Controls", Pair.create("/plugins/VersionControls.png", Arrays.asList( - "ClearcasePlugin", - "CVS", - "Git4Idea", - "org.jetbrains.plugins.github", - "hg4idea", - "PerforceDirectPlugin", - "Subversion", - "TFS" - ))); - myTree.put("Test Tools", Pair.create("/plugins/TestTools.png", Arrays.asList( + + addVcsGroup(tree); + + tree.put("Test Tools", Pair.create(PlatformImplIcons.TestTools, Arrays.asList( "JUnit", "TestNG-J", "cucumber-java", "cucumber", "Coverage:Coverage,Emma" ))); - myTree.put("Application Servers", Pair.create("/plugins/ApplicationServers.png", Arrays.asList( + tree.put("Application Servers", Pair.create(PlatformImplIcons.ApplicationServers, Arrays.asList( "com.intellij.javaee.view", "Geronimo", "GlassFish", @@ -162,7 +149,7 @@ class PluginGroups { "com.intellij.dmserver", "JSR45Plugin" ))); - myTree.put("Clouds", Pair.create("/plugins/Clouds.png", Arrays.asList( + tree.put("Clouds", Pair.create(PlatformImplIcons.Clouds, Arrays.asList( "CloudFoundry", "CloudBees", "Heroku", @@ -170,16 +157,16 @@ class PluginGroups { ))); //myTree.put("Groovy", Arrays.asList("org.intellij.grails")); //TODO Scala -> Play 2.x (Play 2.0 Support) - myTree.put("Swing", Pair.create("/plugins/Swing.png", Arrays.asList( + tree.put("Swing", Pair.create(PlatformImplIcons.Swing, Arrays.asList( "com.intellij.uiDesigner"//TODO JavaFX? ))); - myTree.put("Android", Pair.create("/plugins/Android.png", Arrays.asList( + tree.put("Android", Pair.create(PlatformImplIcons.Android, Arrays.asList( "org.jetbrains.android", "com.intellij.android-designer"))); - myTree.put("Database Tools", Pair.create("/plugins/DatabaseTools.png", Arrays.asList( + tree.put("Database Tools", Pair.create(PlatformImplIcons.DatabaseTools, Arrays.asList( "com.intellij.database" ))); - myTree.put("Other Tools", Pair.create("/plugins/OtherTools.png", Arrays.asList( + tree.put("Other Tools", Pair.create(PlatformImplIcons.OtherTools, Arrays.asList( "ByteCodeViewer", "com.intellij.dsm", "org.jetbrains.idea.eclipse", @@ -190,27 +177,63 @@ class PluginGroups { "org.jetbrains.plugins.yaml", "XSLT and XPath:XPathView,XSLT-Debugger" ))); - myTree.put("Plugin Development", Pair.create("/plugins/PluginDevelopment.png", Arrays.asList("DevKit"))); + tree.put("Plugin Development", Pair.create(PlatformImplIcons.PluginDevelopment, Arrays.asList("DevKit"))); + + featuredPlugins.put("Scala", "Custom Languages:Plugin for Scala language support:org.intellij.scala"); + featuredPlugins.put("Live Edit Tool", + "Web Development:Provides live edit HTML/CSS/JavaScript:com.intellij.plugins.html.instantEditing"); + addVimPlugin(featuredPlugins); + featuredPlugins.put("NodeJS", "JavaScript:Node.js integration:NodeJS"); + featuredPlugins.put("Atlassian Connector", + "Tools Integration:Integration for Atlassian JIRA, Bamboo, Cricible, FishEye:atlassian-idea-plugin"); + } - myFeaturedPlugins.put("Scala", "Custom Languages:Plugin for Scala language support:org.intellij.scala"); - myFeaturedPlugins.put("Live Edit Tool", "Web Development:Provides live edit HTML/CSS/JavaScript:com.intellij.plugins.html.instantEditing"); - myFeaturedPlugins.put("IdeaVIM", "Editor:Vim emulation plug-in for IDEs based on the IntelliJ platform:IdeaVIM"); - myFeaturedPlugins.put("NodeJS", "JavaScript:Node.js integration:NodeJS"); - myFeaturedPlugins.put("Atlassian Connector", "Tools Integration:Integration for Atlassian JIRA, Bamboo, Cricible, FishEye:atlassian-idea-plugin"); + protected static void addVcsGroup(Map<String, Pair<Icon, List<String>>> tree) { + tree.put("Version Controls", Pair.create(PlatformImplIcons.VersionControls, Arrays.asList( + "ClearcasePlugin", + "CVS", + "Git4Idea", + "org.jetbrains.plugins.github", + "hg4idea", + "PerforceDirectPlugin", + "Subversion", + "TFS" + ))); + } + protected static void addVimPlugin(Map<String, String> featuredPlugins) { + featuredPlugins.put("IdeaVIM", "Editor:Vim emulation plug-in for IDEs based on the IntelliJ platform:IdeaVIM"); + } + + protected static void addLuaPlugin(Map<String, String> featuredPlugins) { + featuredPlugins.put("Lua", "Custom Languages:Lua language integration:Lua"); + } + + protected static void addMarkdownPlugin(Map<String, String> featuredPlugins) { + featuredPlugins.put("Markdown", "Custom Languages:Markdown language integration:net.nicoulaj.idea.markdown"); + } + + protected static void addConfigurationServerPlugin(Map<String, String> featuredPlugins) { + featuredPlugins.put("Configuration Server", + "Team Work:Supports sharing settings between installations of IntelliJ Platform based products used by the same developer on different computers:IdeaServerPlugin"); + } + + protected static void addTeamCityPlugin(Map<String, String> featuredPlugins) { + featuredPlugins.put("TeamCity Integration", + "Tools Integration:Integration with JetBrains TeamCity - innovative solution for continuous integration and build management:Jetbrains TeamCity Plugin"); } private void initIfNeed() { if (myInitialized) return; myInitialized = true; - for (Map.Entry<String, Pair<String, List<String>>> entry : myTree.entrySet()) { + for (Map.Entry<String, Pair<Icon, List<String>>> entry : myTree.entrySet()) { final String group = entry.getKey(); if (CORE.equals(group)) continue; List<IdSet> idSets = new ArrayList<IdSet>(); StringBuilder description = new StringBuilder(); for (String idDescription : entry.getValue().getSecond()) { - IdSet idSet = new IdSet(idDescription); + IdSet idSet = new IdSet(this, idDescription); String idSetTitle = idSet.getTitle(); if (idSetTitle == null) continue; idSets.add(idSet); @@ -230,7 +253,7 @@ class PluginGroups { } } - Map<String, Pair<String, List<String>>> getTree() { + Map<String, Pair<Icon, List<String>>> getTree() { initIfNeed(); return myTree; } @@ -302,7 +325,8 @@ class PluginGroups { void setFeaturedPluginEnabled(String pluginId, boolean enabled) { if (enabled) { myFeaturedIds.add(pluginId); - } else { + } + else { myFeaturedIds.remove(pluginId); } StartupUtil.setFeaturedPluginsToInstall(myFeaturedIds); diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java index 00b529933f68..20d7d5188efb 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java @@ -19,22 +19,29 @@ package com.intellij.ide.passwordSafe; * The exception that is thrown when password safe is not available (unable to ask for master password) */ public class PasswordSafeException extends Exception { - /** - * The constructor - * - * @param message the message - * @param cause the cause - */ + + private static final long MIN_INTERVAL = 1000L; + + private long myTimeMillis = System.currentTimeMillis(); + public PasswordSafeException(String message, Throwable cause) { super(message, cause); } - /** - * The constructor - * - * @param message the message - */ public PasswordSafeException(String message) { super(message); } + + public long getTimeMillis() { + return myTimeMillis; + } + + public boolean justHappened() { + long timeMillis = System.currentTimeMillis(); + if (timeMillis - myTimeMillis < MIN_INTERVAL) { + myTimeMillis = timeMillis; + return true; + } + return false; + } } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java index a0b001824d90..8bfa859d5ceb 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java @@ -43,6 +43,7 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider { * @throws PasswordSafeException in case of problems with access to the password database. * @throws IllegalStateException if the method is called from the read action. */ + @NotNull protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor) throws PasswordSafeException; @Nullable diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java index 01fef01cecb1..7bbb8bc80789 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java @@ -15,6 +15,8 @@ */ package com.intellij.ide.passwordSafe.impl.providers; +import org.jetbrains.annotations.NotNull; + import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; @@ -115,7 +117,7 @@ public class EncryptionUtil { * @param rawKey the raw key to encrypt * @return the encrypted key */ - public static byte[] encryptKey(byte[] password, byte[] rawKey) { + public static byte[] encryptKey(@NotNull byte[] password, byte[] rawKey) { try { Cipher c = Cipher.getInstance(ENCRYPT_KEY_ALGORITHM); c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(password, SECRET_KEY_ALGORITHM), CBC_SALT_KEY); @@ -130,12 +132,12 @@ public class EncryptionUtil { * Create encrypted db key * * @param password the password to protect the key - * @param requester the requester for the key - * @param key the key within requester + * @param requestor the requestor for the key + * @param key the key within requestor * @return the key to use in the database */ - public static byte[] dbKey(byte[] password, Class requester, String key) { - return encryptKey(password, rawKey(requester, key)); + public static byte[] dbKey(@NotNull byte[] password, Class requestor, String key) { + return encryptKey(password, rawKey(requestor, key)); } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java index 840159270a8d..6b0b9814698b 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java @@ -22,12 +22,14 @@ import com.intellij.ide.passwordSafe.impl.providers.BasePasswordSafeProvider; import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper; import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil; import com.intellij.ide.passwordSafe.impl.providers.masterKey.windows.WindowsCryptUtils; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; @@ -36,7 +38,6 @@ import org.jetbrains.annotations.Nullable; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; /** * The password safe that stores information in configuration file encrypted by master password @@ -44,13 +45,11 @@ import java.util.concurrent.atomic.AtomicReference; public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { private static final String TEST_PASSWORD_KEY = "TEST_PASSWORD:"; private static final String TEST_PASSWORD_VALUE = "test password"; - final PasswordDatabase database; - /** - * The key to use to encrypt data - */ - private transient final PasswordSafeTimed<AtomicReference<byte[]>> key = new PasswordSafeTimed<AtomicReference<byte[]>>() { - protected AtomicReference<byte[]> compute() { - return new AtomicReference<byte[]>(); + + private final PasswordDatabase myDatabase; + private transient final PasswordSafeTimed<Ref<Object>> myKey = new PasswordSafeTimed<Ref<Object>>() { + protected Ref<Object> compute() { + return Ref.create(); } @Override @@ -60,11 +59,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { }; public MasterKeyPasswordSafe(PasswordDatabase database) { - this.database = database; - } - - protected boolean isTestMode() { - return false; + this.myDatabase = database; } /** @@ -74,15 +69,15 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { * @param encrypt if the password should be encrypted an stored is master database */ void resetMasterPassword(String password, boolean encrypt) { - key.get().set(EncryptionUtil.genPasswordKey(password)); - database.clear(); + myKey.get().set(EncryptionUtil.genPasswordKey(password)); + myDatabase.clear(); try { storePassword(null, MasterKeyPasswordSafe.class, testKey(password), TEST_PASSWORD_VALUE); if (encrypt) { - database.setPasswordInfo(encryptPassword(password)); + myDatabase.setPasswordInfo(encryptPassword(password)); } else { - database.setPasswordInfo(ArrayUtil.EMPTY_BYTE_ARRAY); + myDatabase.setPasswordInfo(ArrayUtil.EMPTY_BYTE_ARRAY); } } catch (PasswordSafeException e) { @@ -97,8 +92,8 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { * @return true, if password is a correct one */ boolean setMasterPassword(String password) { - byte[] savedKey = key.get().get(); - key.get().set(EncryptionUtil.genPasswordKey(password)); + Object savedKey = myKey.get().get(); + myKey.get().set(EncryptionUtil.genPasswordKey(password)); String rc; try { rc = getPassword(null, MasterKeyPasswordSafe.class, testKey(password)); @@ -107,7 +102,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { throw new IllegalStateException("There should be no problem with password at this point", e); } if (!TEST_PASSWORD_VALUE.equals(rc)) { - key.get().set(savedKey); + myKey.get().set(savedKey); return false; } else { @@ -127,11 +122,11 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { if (!setMasterPassword(oldPassword)) { return false; } - byte[] oldKey = key.get().get(); // set right in the previous call + byte[] oldKey = (byte[])myKey.get().get(); // set right in the previous call byte[] newKey = EncryptionUtil.genPasswordKey(newPassword); ByteArrayWrapper testKey = new ByteArrayWrapper(EncryptionUtil.dbKey(oldKey, MasterKeyPasswordSafe.class, testKey(oldPassword))); HashMap<ByteArrayWrapper, byte[]> oldDb = new HashMap<ByteArrayWrapper, byte[]>(); - database.copyTo(oldDb); + myDatabase.copyTo(oldDb); HashMap<ByteArrayWrapper, byte[]> newDb = new HashMap<ByteArrayWrapper, byte[]>(); for (Map.Entry<ByteArrayWrapper, byte[]> e : oldDb.entrySet()) { if (testKey.equals(e.getKey())) { @@ -141,9 +136,9 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { String decryptedText = EncryptionUtil.decryptText(oldKey, e.getValue()); newDb.put(new ByteArrayWrapper(EncryptionUtil.encryptKey(newKey, decryptedKey)), EncryptionUtil.encryptText(newKey, decryptedText)); } - synchronized (database.getDbLock()) { + synchronized (myDatabase.getDbLock()) { resetMasterPassword(newPassword, encrypt); - database.putAll(newDb); + myDatabase.putAll(newDb); } return true; } @@ -153,65 +148,92 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { return TEST_PASSWORD_KEY + password; } + @NotNull @Override protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException { - Application application = ApplicationManager.getApplication(); - if (!isTestMode() && application.isHeadlessEnvironment()) { + Object key = myKey.get().get(); + if (key instanceof byte[]) return (byte[])key; + if (key instanceof PasswordSafeException && ((PasswordSafeException)key).justHappened()) throw (PasswordSafeException)key; + + if (isPasswordEncrypted()) { + try { + setMasterPassword(decryptPassword(myDatabase.getPasswordInfo())); + key = myKey.get().get(); + if (key instanceof byte[]) return (byte[])key; + } + catch (PasswordSafeException e) { + // ignore exception and ask password + } + } + + if (ApplicationManager.getApplication().isHeadlessEnvironment()) { throw new MasterPasswordUnavailableException("The provider is not available in headless environment"); } - final Ref<byte[]> result = Ref.create(key.get().get()); - if (result.isNull()) { - if (isPasswordEncrypted()) { + + if (myDatabase.isEmpty()) { + if (!MasterPasswordDialog.resetMasterPasswordDialog(project, this, requestor).showAndGet()) { + throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database."); + } + } + + key = invokeAndWait(new ThrowableComputable<Object, PasswordSafeException>() { + @Override + public Object compute() throws PasswordSafeException { + Object key = myKey.get().get(); + if (key instanceof byte[] || key instanceof PasswordSafeException && ((PasswordSafeException)key).justHappened()) { + return key; + } try { - setMasterPassword(decryptPassword(database.getPasswordInfo())); - result.set(key.get().get()); + MasterPasswordDialog.askPassword(project, MasterKeyPasswordSafe.this, requestor); } catch (PasswordSafeException e) { - // ignore exception and ask password + myKey.get().set(e); + throw e; } + return myKey.get().get(); + } + }, project == null ? Condition.FALSE : project.getDisposed()); + if (key instanceof byte[]) return (byte[])key; + if (key instanceof PasswordSafeException) throw (PasswordSafeException)key; + + throw new AssertionError(); + } + + private static final Object ourEDTLock = new Object(); + public <T, E extends Throwable> T invokeAndWait(@NotNull final ThrowableComputable<T, E> computable, @NotNull final Condition expired) throws E { + if (ApplicationManager.getApplication().isDispatchThread()) { + return computable.compute(); + } + final Ref<Throwable> exRef = Ref.create(); + final Ref<T> ref = Ref.create(); + synchronized (ourEDTLock) { + if (expired.value(null)) { + throw new ProcessCanceledException(); } - if (result.isNull()) { - final Ref<PasswordSafeException> ex = new Ref<PasswordSafeException>(); - application.invokeAndWait(new Runnable() { - public void run() { - result.set(key.get().get()); - if (result.isNull()) { - try { - if (isTestMode()) { - throw new MasterPasswordUnavailableException("Master password must be specified in test mode."); - } - if (database.isEmpty()) { - if (!MasterPasswordDialog.resetMasterPasswordDialog(project, MasterKeyPasswordSafe.this, requestor).showAndGet()) { - throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database."); - } - } - else { - MasterPasswordDialog.askPassword(project, MasterKeyPasswordSafe.this, requestor); - } - result.set(key.get().get()); - } - catch (PasswordSafeException e) { - ex.set(e); - } - catch (Exception e) { - //noinspection ThrowableInstanceNeverThrown - ex.set(new MasterPasswordUnavailableException("The problem with retrieving the password", e)); - } - } + ApplicationManager.getApplication().invokeAndWait(new Runnable() { + @Override + public void run() { + if (expired.value(null)) { + exRef.set(new ProcessCanceledException()); + return; + } + + try { + ref.set(computable.compute()); + } + catch (Throwable e) { + exRef.set(e); } - }, ModalityState.any()); - //noinspection ThrowableResultOfMethodCallIgnored - if (ex.get() != null) { - throw ex.get(); } - } + }, ModalityState.any()); } - return result.get(); + if (!exRef.isNull()) throw (E)exRef.get(); + return ref.get(); } @Override public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException { - if (database.isEmpty()) { + if (myDatabase.isEmpty()) { return null; } return super.getPassword(project, requestor, key); @@ -219,7 +241,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { @Override public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException { - if (database.isEmpty()) { + if (myDatabase.isEmpty()) { return; } super.removePassword(project, requester, key); @@ -227,17 +249,17 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { @Override protected byte[] getEncryptedPassword(byte[] key) { - return database.get(key); + return myDatabase.get(key); } @Override protected void removeEncryptedPassword(byte[] key) { - database.remove(key); + myDatabase.remove(key); } @Override protected void storeEncryptedPassword(byte[] key, byte[] encryptedPassword) { - database.put(key, encryptedPassword); + myDatabase.put(key, encryptedPassword); } @Override @@ -303,11 +325,11 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { public boolean isPasswordEncrypted() { if (!isOsProtectedPasswordSupported()) return false; - byte[] i = database.getPasswordInfo(); - return i != null && i.length > 0; + byte[] info = myDatabase.getPasswordInfo(); + return info != null && info.length > 0; } public boolean isEmpty() { - return database.isEmpty(); + return myDatabase.isEmpty(); } } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java index 4989789b4ec0..5057b0ee48d6 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java @@ -57,6 +57,7 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider { return Registry.intValue("passwordSafe.memorySafe.ttl"); } + @NotNull @Override protected byte[] key(Project project, @NotNull Class requestor) { if (key.get() == null) { diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java index 6ea43344bda4..b31599816435 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java @@ -18,6 +18,7 @@ package com.intellij.ide.passwordSafe.ui; import com.intellij.ide.passwordSafe.config.PasswordSafeSettings; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ui.DialogUtil; import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -49,7 +50,10 @@ public class PasswordPromptComponent { setTargetProviderType(type); setUserInputVisible(showUserName); if (passwordPrompt != null) myPasswordLabel.setText(passwordPrompt); - if (rememberPrompt != null) myRememberCheckBox.setText(rememberPrompt); + if (rememberPrompt != null) { + myRememberCheckBox.setText(rememberPrompt); + DialogUtil.registerMnemonic(myRememberCheckBox); + } } public JComponent getComponent() { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index b093773bc0fb..366e4e1cf4ef 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -30,10 +30,7 @@ import com.intellij.ui.GuiUtils; import com.intellij.util.ArrayUtil; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author stathik @@ -45,6 +42,19 @@ public class PluginInstaller { private PluginInstaller() { } public static boolean prepareToInstall(List<PluginNode> pluginsToInstall, List<IdeaPluginDescriptor> allPlugins) { + HashSet<PluginNode> dependant = new HashSet<PluginNode>(); + boolean install = prepareToInstall(pluginsToInstall, allPlugins, dependant); + for (PluginNode node : dependant) { + if (!pluginsToInstall.contains(node)) { + pluginsToInstall.add(node); + } + } + return install; + } + + private static boolean prepareToInstall(List<PluginNode> pluginsToInstall, + List<IdeaPluginDescriptor> allPlugins, + Set<PluginNode> installedDependant) { ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator(); final List<PluginId> pluginIds = new ArrayList<PluginId>(); @@ -58,7 +68,7 @@ public class PluginInstaller { if (pi != null) pi.setText(pluginNode.getName()); try { - result |= prepareToInstall(pluginNode, pluginIds, allPlugins); + result |= prepareToInstall(pluginNode, pluginIds, allPlugins, installedDependant); } catch (IOException e) { String title = IdeBundle.message("title.plugin.error"); @@ -72,7 +82,9 @@ public class PluginInstaller { private static boolean prepareToInstall(final PluginNode pluginNode, final List<PluginId> pluginIds, - List<IdeaPluginDescriptor> allPlugins) throws IOException { + List<IdeaPluginDescriptor> allPlugins, + Set<PluginNode> installedDependant) throws IOException { + installedDependant.add(pluginNode); // check for dependent plugins at first. if (pluginNode.getDepends() != null && pluginNode.getDepends().size() > 0) { // prepare plugins list for install @@ -122,7 +134,7 @@ public class PluginInstaller { return false; } if (proceed[0]) { - if (!prepareToInstall(depends, allPlugins)) { + if (!prepareToInstall(depends, allPlugins, installedDependant)) { return false; } } @@ -152,7 +164,7 @@ public class PluginInstaller { return false; } if (proceed[0]) { - if (!prepareToInstall(optionalDeps, allPlugins)) { + if (!prepareToInstall(optionalDeps, allPlugins, installedDependant)) { return false; } } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java index 1fcf23e79614..cc683ecb7075 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java @@ -34,15 +34,7 @@ import javax.swing.*; import javax.swing.table.TableModel; import java.util.List; -/** - * Created by IntelliJ IDEA. - * User: stathik - * Date: Oct 26, 2003 - * Time: 9:30:44 PM - * To change this template use Options | File Templates. - */ public class PluginManagerConfigurable extends BaseConfigurable implements SearchableConfigurable, Configurable.NoScroll { - @NonNls private static final String POSTPONE = "&Postpone"; public static final String ID = "preferences.pluginManager"; public static final String DISPLAY_NAME = IdeBundle.message("title.plugins"); @@ -68,10 +60,12 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc return myPluginManagerMain.getPluginTable(); } + @Override public String getDisplayName() { return DISPLAY_NAME; } + @Override public void reset() { myPluginManagerMain.reset(); //if (myAvailable) { @@ -92,10 +86,12 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc getSplitterProportions().restoreSplitterProportions(myPluginManagerMain.getMainPanel()); } + @Override public String getHelpTopic() { return ID; } + @Override public void disposeUIResources() { if (myPluginManagerMain != null) { getSplitterProportions().saveSplitterProportions(myPluginManagerMain.getMainPanel()); @@ -124,6 +120,7 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc return myAvailable ? myUISettings.getAvailableSplitterProportionsData() : myUISettings.getSplitterProportionsData(); } + @Override public JComponent createComponent() { return getOrCreatePanel().getMainPanel(); } @@ -132,6 +129,7 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc return new InstalledPluginsManagerMain(myUISettings); } + @Override public void apply() throws ConfigurationException { final String applyMessage = myPluginManagerMain.apply(); if (applyMessage != null) { @@ -186,18 +184,22 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc if (response == Messages.YES) app.restart(true); } + @Override public boolean isModified() { return myPluginManagerMain != null && myPluginManagerMain.isModified(); } + @Override @NotNull public String getId() { return getHelpTopic(); } + @Override @Nullable public Runnable enableSearch(final String option) { return new Runnable(){ + @Override public void run() { if (myPluginManagerMain == null) return; myPluginManagerMain.filter(option); diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index 931458ff8bc0..e7601a6b0fc0 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -85,6 +85,8 @@ import static com.intellij.openapi.util.text.StringUtil.isEmptyOrSpaces; */ public abstract class PluginManagerMain implements Disposable { public static final String JETBRAINS_VENDOR = "JetBrains"; + public static final NotificationGroup PLUGIN_LIFECYCLE_NOTIFICATION_GROUP = + new NotificationGroup("Plugins Lifecycle Group", NotificationDisplayType.STICKY_BALLOON, true); public static Logger LOG = Logger.getInstance("#com.intellij.ide.plugins.PluginManagerMain"); @NonNls private static final String TEXT_PREFIX = "<html><head>" + @@ -652,7 +654,7 @@ public abstract class PluginManagerMain implements Disposable { message += "<br><a href="; message += restartCapable ? "\"restart\">Restart now" : "\"shutdown\">Shutdown"; message += "</a>"; - new NotificationGroup("Plugins Lifecycle Group", NotificationDisplayType.STICKY_BALLOON, true) + PLUGIN_LIFECYCLE_NOTIFICATION_GROUP .createNotification(title, XmlStringUtil.wrapInHtml(message), NotificationType.INFORMATION, new NotificationListener() { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java index d5e320a77837..0f0b5189a7f7 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java @@ -17,7 +17,6 @@ package com.intellij.ide.plugins; import com.intellij.ide.ui.SplitterProportionsDataImpl; import com.intellij.openapi.components.*; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.ui.SplitterProportionsData; import com.intellij.openapi.util.JDOMExternalizableStringList; @@ -39,7 +38,6 @@ import javax.swing.*; } ) public class PluginManagerUISettings implements PersistentStateComponent<Element>, PerformInBackgroundOption { - private static final Logger LOG = Logger.getInstance("#com.intellij.ide.plugins.PluginManagerUISettings"); private static final SkipDefaultValuesSerializationFilters FILTERS = new SkipDefaultValuesSerializationFilters(); public int AVAILABLE_SORT_COLUMN_ORDER = SortOrder.ASCENDING.ordinal(); @@ -65,6 +63,7 @@ public class PluginManagerUISettings implements PersistentStateComponent<Element return ServiceManager.getService(PluginManagerUISettings.class); } + @Override public Element getState() { Element element = new Element("state"); XmlSerializer.serializeInto(this, element, FILTERS); @@ -76,6 +75,7 @@ public class PluginManagerUISettings implements PersistentStateComponent<Element return element; } + @Override public void loadState(final Element element) { XmlSerializer.deserializeInto(this, element); XmlSerializer.deserializeInto(mySplitterProportionsData, element); diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java index ec763a8d5a76..c03eca88ade3 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.PathUtil; import com.intellij.util.net.HttpConfigurable; @@ -45,9 +46,14 @@ public class RepositoryHelper { @NonNls public static final String PLUGIN_LIST_FILE = "availables.xml"; public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable ProgressIndicator indicator) throws Exception { + return loadPluginsFromRepository(indicator, null); + } + + public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable ProgressIndicator indicator, + BuildNumber buildnumber) throws Exception { ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance(); - String url = appInfo.getPluginsListUrl() + "?build=" + appInfo.getApiVersion(); + String url = appInfo.getPluginsListUrl() + "?build=" + (buildnumber != null ? buildnumber.asString() : appInfo.getApiVersion()); if (indicator != null) { indicator.setText2(IdeBundle.message("progress.connecting.to.plugin.manager", appInfo.getPluginManagerUrl())); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java index c60ddc44748d..cc6e16aba6c2 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,7 +70,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab myComponent.myLafComboBox.setModel(new DefaultComboBoxModel(LafManager.getInstance().getInstalledLookAndFeels())); myComponent.myLafComboBox.setRenderer(new LafComboBoxRenderer()); - Dictionary<Integer, JLabel> delayDictionary = new Hashtable<Integer, JLabel>(); + Dictionary<Integer, JComponent> delayDictionary = new Hashtable<Integer, JComponent>(); delayDictionary.put(new Integer(0), new JLabel("0")); delayDictionary.put(new Integer(1200), new JLabel("1200")); //delayDictionary.put(new Integer(2400), new JLabel("2400")); @@ -94,7 +94,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab myComponent.myAlphaModeRatioSlider.setSize(100, 50); @SuppressWarnings({"UseOfObsoleteCollectionType"}) - Dictionary<Integer, JLabel> dictionary = new Hashtable<Integer, JLabel>(); + Dictionary<Integer, JComponent> dictionary = new Hashtable<Integer, JComponent>(); dictionary.put(new Integer(0), new JLabel("0%")); dictionary.put(new Integer(50), new JLabel("50%")); dictionary.put(new Integer(100), new JLabel("100%")); diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java index 0744e377e6c5..3d84e6d7431c 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java @@ -1,4 +1,3 @@ - /* * Copyright 2000-2014 JetBrains s.r.o. * @@ -33,6 +32,12 @@ import java.awt.event.ActionEvent; public class TipDialog extends DialogWrapper{ private TipPanel myTipPanel; + @Nullable + @Override + protected String getDimensionServiceKey() { + return getClass().getName(); + } + public TipDialog(){ super(WindowManagerEx.getInstanceEx().findVisibleFrame(), true); initialize(); @@ -52,9 +57,6 @@ public class TipDialog extends DialogWrapper{ setHorizontalStretch(1.33f); setVerticalStretch(1.25f); init(); - if (getPeer() instanceof DialogWrapperPeerImpl) { - ((DialogWrapperPeerImpl)getPeer()).setAutoRequestFocus(false); - } } @NotNull diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java b/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java index 1fd6c340d073..32b03f3deb2b 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentManager; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.event.AncestorEvent; @@ -44,7 +45,7 @@ import javax.swing.event.AncestorEvent; */ public class EventLogToolWindowFactory implements ToolWindowFactory, DumbAware { @Override - public void createToolWindowContent(final Project project, ToolWindow toolWindow) { + public void createToolWindowContent(@NotNull final Project project, @NotNull ToolWindow toolWindow) { EventLog.getProjectComponent(project).initDefaultContent(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java index a7b2e7bc9d02..0d116c7a927f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java @@ -38,40 +38,33 @@ import java.util.*; )} ) public class AbbreviationManagerImpl extends AbbreviationManager implements - ExportableApplicationComponent, PersistentStateComponent<Element> { + ExportableComponent, PersistentStateComponent<Element> { private final Map<String, List<String>> myAbbreviation2ActionId = new THashMap<String, List<String>>(); private final Map<String, LinkedHashSet<String>> myActionId2Abbreviations = new THashMap<String, LinkedHashSet<String>>(); private final Map<String, LinkedHashSet<String>> myPluginsActionId2Abbreviations = new THashMap<String, LinkedHashSet<String>>(); - @Override - public void initComponent() { - - } - - @Override - public void disposeComponent() { - - } - - @NotNull - @Override - public String getComponentName() { - return "AbbreviationManager"; - } - @Nullable @Override public Element getState() { final Element actions = new Element("actions"); - final Element abbreviations = new Element("abbreviations"); - actions.addContent(abbreviations); + if (myActionId2Abbreviations.isEmpty()) { + return actions; + } + + Element abbreviations = null; for (String key : myActionId2Abbreviations.keySet()) { final LinkedHashSet<String> abbrs = myActionId2Abbreviations.get(key); final LinkedHashSet<String> pluginAbbrs = myPluginsActionId2Abbreviations.get(key); if (abbrs == pluginAbbrs || (abbrs != null && abbrs.equals(pluginAbbrs))) { continue; } + if (abbrs != null) { + if (abbreviations == null) { + abbreviations = new Element("abbreviations"); + actions.addContent(abbreviations); + } + final Element action = new Element("action"); action.setAttribute("id", key); abbreviations.addContent(action); diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java index 78043075b166..723956ef9daa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java @@ -49,6 +49,7 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.IdeFrame; import com.intellij.util.ArrayUtil; import com.intellij.util.ObjectUtils; +import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.messages.MessageBusConnection; @@ -66,7 +67,6 @@ import javax.swing.*; import javax.swing.Timer; import java.awt.*; import java.awt.event.*; -import java.lang.reflect.Constructor; import java.util.*; import java.util.List; @@ -259,9 +259,8 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat Object obj; String className = stub.getClassName(); try { - Constructor<?> constructor = Class.forName(className, true, stub.getLoader()).getDeclaredConstructor(); - constructor.setAccessible(true); - obj = constructor.newInstance(); + Class<?> aClass = Class.forName(className, true, stub.getLoader()); + obj = ReflectionUtil.newInstance(aClass); } catch (ClassNotFoundException e) { PluginId pluginId = stub.getPluginId(); diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java index a0b495726f30..529d5ba1c62f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,6 +65,8 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionToolbarImpl"); private static final List<ActionToolbarImpl> ourToolbars = new LinkedList<ActionToolbarImpl>(); + private static final String RIGHT_ALIGN_KEY = "RIGHT_ALIGN"; + public static void updateAllToolbarsImmediately() { for (ActionToolbarImpl toolbar : new ArrayList<ActionToolbarImpl>(ourToolbars)) { toolbar.updateActionsImmediately(); @@ -107,7 +109,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { private final ActionButtonLook myButtonLook = null; private final ActionButtonLook myMinimalButtonLook = new InplaceActionButtonLook(); private final DataManager myDataManager; - protected final ActionManagerEx myActionManager; + @NotNull protected final ActionManagerEx myActionManager; private Rectangle myAutoPopupRec; @@ -135,7 +137,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { @NotNull final ActionGroup actionGroup, final boolean horizontal, DataManager dataManager, - ActionManagerEx actionManager, + @NotNull ActionManagerEx actionManager, KeymapManagerEx keymapManager) { this(place, actionGroup, horizontal, false, dataManager, actionManager, keymapManager, false); } @@ -144,7 +146,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { final boolean horizontal, final boolean decorateButtons, DataManager dataManager, - ActionManagerEx actionManager, + @NotNull ActionManagerEx actionManager, KeymapManagerEx keymapManager) { this(place, actionGroup, horizontal, decorateButtons, dataManager, actionManager, keymapManager, false); } @@ -154,7 +156,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { final boolean horizontal, final boolean decorateButtons, DataManager dataManager, - ActionManagerEx actionManager, + @NotNull ActionManagerEx actionManager, KeymapManagerEx keymapManager, boolean updateActionsNow) { super(null); @@ -272,11 +274,16 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { } private void fillToolBar(final List<AnAction> actions, boolean layoutSecondaries) { + final List<AnAction> rightAligned = new ArrayList<AnAction>(); if (myAddSeparatorFirst) { add(new MySeparator()); } for (int i = 0; i < actions.size(); i++) { final AnAction action = actions.get(i); + if (action instanceof RightAlignedToolbarAction) { + rightAligned.add(action); + continue; + } // if (action instanceof Separator && isNavBar()) { // continue; // } @@ -311,18 +318,23 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { add(mySecondaryActionsButton); } - if ((ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || ActionPlaces.NAVIGATION_BAR_TOOLBAR.equals(myPlace))) { - final AnAction searchEverywhereAction = ActionManager.getInstance().getAction("SearchEverywhere"); - if (searchEverywhereAction != null) { - try { - final CustomComponentAction searchEveryWhereAction = (CustomComponentAction)searchEverywhereAction; - final JComponent searchEverywhere = searchEveryWhereAction.createCustomComponent(searchEverywhereAction.getTemplatePresentation()); - searchEverywhere.putClientProperty("SEARCH_EVERYWHERE", Boolean.TRUE); - add(searchEverywhere); - } - catch (Exception ignore) {} - } - } + for (AnAction action : rightAligned) { + JComponent button = action instanceof CustomComponentAction ? getCustomComponent(action) : createToolbarButton(action); + button.putClientProperty(RIGHT_ALIGN_KEY, Boolean.TRUE); + add(button); + } + //if ((ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || ActionPlaces.NAVIGATION_BAR_TOOLBAR.equals(myPlace))) { + // final AnAction searchEverywhereAction = ActionManager.getInstance().getAction("SearchEverywhere"); + // if (searchEverywhereAction != null) { + // try { + // final CustomComponentAction searchEveryWhereAction = (CustomComponentAction)searchEverywhereAction; + // final JComponent searchEverywhere = searchEveryWhereAction.createCustomComponent(searchEverywhereAction.getTemplatePresentation()); + // searchEverywhere.putClientProperty("SEARCH_EVERYWHERE", Boolean.TRUE); + // add(searchEverywhere); + // } + // catch (Exception ignore) {} + // } + //} } private JComponent getCustomComponent(AnAction action) { @@ -730,14 +742,18 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { throw new IllegalStateException("unknown layoutPolicy: " + myLayoutPolicy); } + if (getComponentCount() > 0 && size2Fit.width < Integer.MAX_VALUE) { - final Component component = getComponent(getComponentCount() - 1); - if (component instanceof JComponent && ((JComponent)component).getClientProperty("SEARCH_EVERYWHERE") == Boolean.TRUE) { - int max = 0; - for (int i = 0; i < bounds.size() - 2; i++) { - max = Math.max(max, bounds.get(i).height); + int maxHeight = 0; + for (int i = 0; i < bounds.size() - 2; i++) { + maxHeight = Math.max(maxHeight, bounds.get(i).height); + } + + for (int i = getComponentCount() - 1, j = 1; i > 0; i--, j++) { + final Component component = getComponent(i); + if (component instanceof JComponent && ((JComponent)component).getClientProperty(RIGHT_ALIGN_KEY) == Boolean.TRUE) { + bounds.set(bounds.size() - j, new Rectangle(size2Fit.width - j * 25, 0, 25, maxHeight)); } - bounds.set(bounds.size() - 1, new Rectangle(size2Fit.width - 25, 0, 25, max)); } } } @@ -1185,7 +1201,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar { final ActionGroup actionGroup, final boolean horizontal, final DataManager dataManager, - final ActionManagerEx actionManager, + @NotNull ActionManagerEx actionManager, final KeymapManagerEx keymapManager, JComponent parent) { super(place, actionGroup, horizontal, false, dataManager, actionManager, keymapManager, true); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 7c8acbc4c25c..46fae517170d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -781,7 +781,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App } @Override - public void restart(boolean exitConfirmed) { + public void restart(final boolean exitConfirmed) { exit(false, exitConfirmed, true, true); } @@ -801,7 +801,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App exiting = true; try { - if (!force && getDefaultModalityState() != ModalityState.NON_MODAL) { + if (!force && !exitConfirmed && getDefaultModalityState() != ModalityState.NON_MODAL) { return; } @@ -1067,8 +1067,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App private static Thread getEventQueueThread() { EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); try { - Method method = EventQueue.class.getDeclaredMethod("getDispatchThread"); - method.setAccessible(true); + Method method = ReflectionUtil.getDeclaredMethod(EventQueue.class, "getDispatchThread"); return (Thread)method.invoke(eventQueue); } catch (Exception e) { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java index ab2be68b70bd..de7a7e76aa70 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,23 +27,27 @@ import com.intellij.openapi.util.Condition; import org.jetbrains.annotations.NotNull; public class ModalityInvokatorImpl implements ModalityInvokator { + @NotNull @Override - public ActionCallback invokeLater(Runnable runnable) { + public ActionCallback invokeLater(@NotNull Runnable runnable) { return invokeLater(runnable, ApplicationManager.getApplication().getDisposed()); } + @NotNull @Override - public ActionCallback invokeLater(final Runnable runnable, @NotNull final Condition expired) { + public ActionCallback invokeLater(@NotNull final Runnable runnable, @NotNull final Condition expired) { return LaterInvocator.invokeLater(runnable, expired); } + @NotNull @Override - public ActionCallback invokeLater(final Runnable runnable, @NotNull final ModalityState state, @NotNull final Condition expired) { + public ActionCallback invokeLater(@NotNull final Runnable runnable, @NotNull final ModalityState state, @NotNull final Condition expired) { return LaterInvocator.invokeLater(runnable, state, expired); } + @NotNull @Override - public ActionCallback invokeLater(Runnable runnable, @NotNull ModalityState state) { + public ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState state) { return invokeLater(runnable, state, ApplicationManager.getApplication().getDisposed()); } }
\ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/EditorLinePainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/EditorLinePainter.java new file mode 100644 index 000000000000..420a0fdf23a7 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/EditorLinePainter.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * 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.intellij.openapi.editor; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * @author Konstantin Bulenkov + */ +public abstract class EditorLinePainter { + public static final ExtensionPointName<EditorLinePainter> EP_NAME = ExtensionPointName.create("com.intellij.editor.linePainter"); + + public abstract Collection<LineExtensionInfo> getLineExtensions(@NotNull Project project, @NotNull VirtualFile file, int lineNumber); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/LineExtensionInfo.java b/platform/platform-impl/src/com/intellij/openapi/editor/LineExtensionInfo.java new file mode 100644 index 000000000000..f84502097b10 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/LineExtensionInfo.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * 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.intellij.openapi.editor; + +import com.intellij.openapi.editor.markup.EffectType; +import org.intellij.lang.annotations.JdkConstants; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class LineExtensionInfo { + @NotNull private final String myText; + @Nullable private final Color myColor; + @Nullable private final EffectType myEffectType; + @Nullable private final Color myEffectColor; + @JdkConstants.FontStyle private final int myFontType; + + public LineExtensionInfo(@NotNull String text, + @Nullable Color color, + @Nullable EffectType effectType, + @Nullable Color effectColor, + @JdkConstants.FontStyle int fontType) { + myText = text; + myColor = color; + myEffectType = effectType; + myEffectColor = effectColor; + myFontType = fontType; + } + + @NotNull + public String getText() { + return myText; + } + + @Nullable + public Color getColor() { + return myColor; + } + + @Nullable + public EffectType getEffectType() { + return myEffectType; + } + + @Nullable + public Color getEffectColor() { + return myEffectColor; + } + + @JdkConstants.FontStyle + public int getFontType() { + return myFontType; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java index cc7b2177cd91..ea2107632122 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java @@ -30,6 +30,8 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.util.ui.MacUIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class EnterAction extends EditorAction { public EnterAction() { @@ -43,13 +45,13 @@ public class EnterAction extends EditorAction { } @Override - public void executeWriteAction(Editor editor, DataContext dataContext) { + public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) { CommandProcessor.getInstance().setCurrentCommandName(EditorBundle.message("typing.command.name")); insertNewLineAtCaret(editor); } @Override - public boolean isEnabled(Editor editor, DataContext dataContext) { + public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) { return !editor.isOneLineMode(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java index 92f025685891..76eff2bd7a54 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java @@ -57,7 +57,7 @@ public class IndentSelectionAction extends EditorAction { @Override public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) { Project project = CommonDataKeys.PROJECT.getData(dataContext); - if (isEnabled(editor, dataContext)) { + if (isEnabled(editor, caret, dataContext)) { indentSelection(editor, project); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java index 7716a9001b7e..1583bd423ff7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java @@ -18,10 +18,7 @@ package com.intellij.openapi.editor.actions; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorActionManager; @@ -30,6 +27,7 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.util.Key; import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.NotNull; /** * @author max @@ -48,13 +46,13 @@ public class SplitLineAction extends EditorAction { } @Override - public boolean isEnabled(Editor editor, DataContext dataContext) { - return getEnterHandler().isEnabled(editor, dataContext) && + public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) { + return getEnterHandler().isEnabled(editor, caret, dataContext) && !((EditorEx)editor).isEmbeddedIntoDialogWrapper(); } @Override - public void executeWriteAction(Editor editor, DataContext dataContext) { + public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) { CopyPasteManager.getInstance().stopKillRings(); final Document document = editor.getDocument(); final RangeMarker rangeMarker = @@ -77,7 +75,7 @@ public class SplitLineAction extends EditorAction { } else { DataManager.getInstance().saveInDataContext(dataContext, SPLIT_LINE_KEY, true); try { - getEnterHandler().execute(editor, dataContext); + getEnterHandler().execute(editor, caret, dataContext); } finally { DataManager.getInstance().saveInDataContext(dataContext, SPLIT_LINE_KEY, null); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java index 0302e484d00d..b2f43bf4458f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java @@ -17,6 +17,7 @@ package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.actionSystem.EditorAction; @@ -24,6 +25,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.openapi.ide.CopyPasteManager; +import org.jetbrains.annotations.NotNull; /** * @author max @@ -39,12 +41,12 @@ public class StartNewLineAction extends EditorAction { } @Override - public boolean isEnabled(Editor editor, DataContext dataContext) { - return getEnterHandler().isEnabled(editor, dataContext); + public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) { + return getEnterHandler().isEnabled(editor, caret, dataContext); } @Override - public void executeWriteAction(Editor editor, DataContext dataContext) { + public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) { CopyPasteManager.getInstance().stopKillRings(); if (editor.getDocument().getLineCount() != 0) { editor.getSelectionModel().removeSelection(); @@ -53,7 +55,7 @@ public class StartNewLineAction extends EditorAction { editor.getCaretModel().moveToOffset(lineEndOffset); } - getEnterHandler().execute(editor, dataContext); + getEnterHandler().execute(editor, caret, dataContext); } private static EditorActionHandler getEnterHandler() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java index fc2ae4031ca3..4d8c6ff2f465 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java @@ -42,8 +42,8 @@ public class StartNewLineBeforeAction extends EditorAction { } @Override - public boolean isEnabled(Editor editor, DataContext dataContext) { - return getHandler(IdeActions.ACTION_EDITOR_ENTER).isEnabled(editor, dataContext); + public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) { + return getHandler(IdeActions.ACTION_EDITOR_ENTER).isEnabled(editor, caret, dataContext); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java index a1ae088a89e2..2d7e3945ee6e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java @@ -24,11 +24,13 @@ */ package com.intellij.openapi.editor.actions; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; -import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.project.DumbAware; +import org.jetbrains.annotations.Nullable; public class UnselectWordAtCaretAction extends EditorAction implements DumbAware { public UnselectWordAtCaretAction() { @@ -42,7 +44,7 @@ public class UnselectWordAtCaretAction extends EditorAction implements DumbAware } @Override - public void execute(Editor editor, DataContext dataContext) { + public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) { } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java index 5da1077baf5c..71dee99c3514 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ public interface EditorMarkupModel extends MarkupModel { void setErrorStripeVisible(boolean val); - void setErrorStripeRenderer(ErrorStripeRenderer renderer); + void setErrorStripeRenderer(@NotNull ErrorStripeRenderer renderer); ErrorStripeRenderer getErrorStripeRenderer(); void addErrorMarkerListener(@NotNull ErrorStripeListener listener, @NotNull Disposable parent); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java index fc1f9048d31f..31b3a56d2317 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java @@ -46,13 +46,8 @@ public class EditorHeaderComponent extends JPanel { paintGradient(g, this); } - @NotNull - protected JBColor getBaseBackgroundColor() { - return new JBColor(getBackground(), JBColor.background()); - } - private void paintGradient(Graphics g, JComponent c) { - Color GRADIENT_C1 = getBaseBackgroundColor(); + Color GRADIENT_C1 = isBackgroundSet() ? getBackground() : new JBColor(getBackground(), JBColor.background()); Color GRADIENT_C2 = new JBColor(new Color(Math.max(0, GRADIENT_C1.getRed() - 0x18), Math.max(0, GRADIENT_C1.getGreen() - 0x18), Math.max(0, GRADIENT_C1.getBlue() - 0x18)), Gray._75); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index c0ffbd10aca4..6160ea58dcdf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -2765,8 +2765,25 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (hEnd >= lEnd) { FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start); if (collapsedFolderAt == null) { - drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor, - effectType, fontType, currentColor, logicalPosition); + int i = drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor, + effectType, fontType, currentColor, logicalPosition); + final VirtualFile file = getVirtualFile(); + if (myProject != null && file != null && !isOneLineMode()) { + for (EditorLinePainter painter : EditorLinePainter.EP_NAME.getExtensions()) { + Collection<LineExtensionInfo> extensions = painter.getLineExtensions(myProject, file, lIterator.getLineNumber()); + if (extensions != null && !extensions.isEmpty()) { + for (LineExtensionInfo info : extensions) { + drawStringWithSoftWraps(g, info.getText(), 0, info.getText().length(), position, clip, + info.getEffectColor() == null ? effectColor : info.getEffectColor(), + info.getEffectType() == null ? effectType : info.getEffectType(), + info.getFontType(), + info.getColor() == null ? currentColor : info.getColor(), + logicalPosition); + } + } + } + } + position.x = 0; if (position.y > clip.y + clip.height) { break; @@ -6749,10 +6766,17 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi public Insets getBorderInsets(Component c) { Container splitters = SwingUtilities.getAncestorOfClass(EditorsSplitters.class, c); boolean thereIsSomethingAbove = !SystemInfo.isMac || UISettings.getInstance().SHOW_MAIN_TOOLBAR || UISettings.getInstance().SHOW_NAVIGATION_BAR || - myProject != null && !ToolWindowManagerEx.getInstanceEx(myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty(); + toolWindowIsNotEmpty(); return splitters == null ? super.getBorderInsets(c) : new Insets(thereIsSomethingAbove ? 1 : 0, 0, 0, 0); } + public boolean toolWindowIsNotEmpty() { + if (myProject == null) return false; + ToolWindowManagerEx m = ToolWindowManagerEx.getInstanceEx(myProject); + if (m == null) return false; + return !m.getIdsOn(ToolWindowAnchor.TOP).isEmpty(); + } + @Override public boolean isBorderOpaque() { return true; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index 6ec29e58dc0b..20c08ec4ec99 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -368,7 +368,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } @Override - public void setErrorStripeRenderer(ErrorStripeRenderer renderer) { + public void setErrorStripeRenderer(@NotNull ErrorStripeRenderer renderer) { assertIsDispatchThread(); if (myErrorStripeRenderer instanceof Disposable) { Disposer.dispose((Disposable)myErrorStripeRenderer); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java index 63843a932076..64f56eb750eb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java @@ -285,7 +285,7 @@ public abstract class FileTextFieldImpl implements FileLookup, Disposable, FileT myList = new JBList(); myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() { + myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptorAdapter() { public String getTextFor(final Object value) { final LookupFile file = (LookupFile)value; @@ -298,10 +298,6 @@ public abstract class FileTextFieldImpl implements FileLookup, Disposable, FileT } - public String getTooltipFor(final Object value) { - return null; - } - public Icon getIconFor(final Object value) { final LookupFile file = (LookupFile)value; return file.getIcon(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java index 9520834b4518..30eb78cf706f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.openapi.fileEditor.ex; import com.intellij.openapi.Disposable; +import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.EditorDataProvider; import com.intellij.openapi.fileEditor.FileEditor; @@ -164,9 +165,9 @@ public abstract class FileEditorManagerEx extends FileEditorManager implements B public abstract boolean isInsideChange(); @Nullable - public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull VirtualFile file) { + public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret) { for (final EditorDataProvider dataProvider : myDataProviders) { - final Object o = dataProvider.getData(dataId, editor, file); + final Object o = dataProvider.getData(dataId, editor, caret); if (o != null) return o; } return null; diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index 091ff1171157..cce6de27545d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -621,6 +621,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt DocumentEx documentEx = (DocumentEx)document; documentEx.setReadOnly(false); LoadTextUtil.setCharsetWasDetectedFromBytes(file, null); + file.setBOM(null); // reset BOM in case we had one and the external change stripped it away documentEx.replaceText(LoadTextUtil.loadText(file), file.getModificationStamp()); documentEx.setReadOnly(!wasWritable); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index c7fa51f770d1..bab6d2b2fa4f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -1636,7 +1636,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec */ private final class MyVirtualFileListener extends VirtualFileAdapter { @Override - public void beforeFileDeletion(VirtualFileEvent e) { + public void beforeFileDeletion(@NotNull VirtualFileEvent e) { assertDispatchThread(); boolean moveFocus = moveFocusOnDelete(); @@ -1651,7 +1651,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } @Override - public void propertyChanged(VirtualFilePropertyEvent e) { + public void propertyChanged(@NotNull VirtualFilePropertyEvent e) { if (VirtualFile.PROP_NAME.equals(e.getPropertyName())) { assertDispatchThread(); final VirtualFile file = e.getFile(); @@ -1681,7 +1681,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } @Override - public void fileMoved(VirtualFileMoveEvent e) { + public void fileMoved(@NotNull VirtualFileMoveEvent e) { final VirtualFile file = e.getFile(); final VirtualFile[] openFiles = getOpenFiles(); for (final VirtualFile openFile : openFiles) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java index 5f3dd9adad22..51d044866717 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java @@ -24,18 +24,19 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.containers.HashMap; import org.jdom.Element; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Map; final class HistoryEntry{ - static final String TAG = "entry"; + @NonNls static final String TAG = "entry"; private static final String FILE_ATTR = "file"; - private static final String PROVIDER_ELEMENT = "provider"; - private static final String EDITOR_TYPE_ID_ATTR = "editor-type-id"; - private static final String SELECTED_ATTR_VALUE = "selected"; - private static final String STATE_ELEMENT = "state"; + @NonNls private static final String PROVIDER_ELEMENT = "provider"; + @NonNls private static final String EDITOR_TYPE_ID_ATTR = "editor-type-id"; + @NonNls private static final String SELECTED_ATTR_VALUE = "selected"; + @NonNls private static final String STATE_ELEMENT = "state"; public final VirtualFile myFile; /** @@ -53,7 +54,7 @@ final class HistoryEntry{ } } - public HistoryEntry(Project project, Element e) throws InvalidDataException { + public HistoryEntry(@NotNull Project project, @NotNull Element e) throws InvalidDataException { myFile = getVirtualFile(e); myProvider2State = new HashMap<FileEditorProvider, FileEditorState>(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java index 288227eb51bd..de11bd5b9a12 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java @@ -36,7 +36,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.impl.EditorHistoryManager; -import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; import com.intellij.openapi.fileTypes.FileTypeEvent; import com.intellij.openapi.fileTypes.FileTypeListener; import com.intellij.openapi.fileTypes.FileTypeManager; @@ -278,7 +277,7 @@ class TextEditorComponent extends JBLoadingPanel implements DataProvider { if (e == null) return null; if (!myProject.isDisposed()) { - final Object o = ((FileEditorManagerImpl)FileEditorManager.getInstance(myProject)).getData(dataId, e, myFile); + final Object o = FileEditorManager.getInstance(myProject).getData(dataId, e, e.getCaretModel().getCurrentCaret()); if (o != null) return o; } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java index 13a8aaecb724..8a9031986ef8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java @@ -24,6 +24,7 @@ import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.util.Clock; import com.intellij.openapi.util.Couple; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.util.containers.ConcurrentHashMap; import gnu.trove.TIntIntHashMap; @@ -63,6 +64,9 @@ public class ModifierKeyDoubleClickHandler { public void registerAction(@NotNull String actionId, int modifierKeyCode, int actionKeyCode) { + if (SystemInfo.isMac && modifierKeyCode == KeyEvent.VK_CONTROL) { + modifierKeyCode = KeyEvent.VK_META; + } final MyDispatcher dispatcher = new MyDispatcher(actionId, modifierKeyCode, actionKeyCode); IdeEventQueue.EventDispatcher oldDispatcher = myDispatchers.put(actionId, dispatcher); IdeEventQueue.getInstance().addDispatcher(dispatcher, null); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java index 1b0c17f3ab4e..44ec15003de9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java @@ -21,6 +21,7 @@ import com.intellij.ide.ui.UISettings; import com.intellij.ide.ui.search.SearchUtil; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.QuickList; +import com.intellij.openapi.actionSystem.impl.ActionMenu; import com.intellij.openapi.keymap.KeyMapBundle; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapUtil; @@ -40,12 +41,15 @@ import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.util.ui.tree.WideSelectionTreeUI; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.*; import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; import java.util.ArrayList; import java.util.Enumeration; import java.util.Set; @@ -91,7 +95,7 @@ public class ActionsTree { } } } - + } }; myTree.setRootVisible(false); @@ -99,6 +103,36 @@ public class ActionsTree { myTree.putClientProperty(WideSelectionTreeUI.STRIPED_CLIENT_PROPERTY, Boolean.TRUE); myTree.setCellRenderer(new KeymapsRenderer()); + myTree.addMouseMotionListener(new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + String description = getDescription(e); + if (description != null) { + ActionMenu.showDescriptionInStatusBar(true, myTree, description); + } + else { + ActionMenu.showDescriptionInStatusBar(false, myTree, null); + } + } + + @Nullable + private String getDescription(@NotNull MouseEvent e) { + TreePath path = myTree.getPathForLocation(e.getX(), e.getY()); + if (path == null) return null; + + DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + if (node == null) return null; + + Object userObject = node.getUserObject(); + if (!(userObject instanceof String)) return null; + + String actionId = (String)userObject; + AnAction action = ActionManager.getInstance().getActionOrStub(actionId); + if (action == null) return null; + + return action.getTemplatePresentation().getDescription(); + } + }); myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); @@ -447,6 +481,7 @@ public class ActionsTree { Icon icon = null; String text; boolean bound = false; + setToolTipText(null); if (value instanceof DefaultMutableTreeNode) { Object userObject = ((DefaultMutableTreeNode)value).getUserObject(); @@ -474,6 +509,7 @@ public class ActionsTree { if (actionIcon != null) { icon = actionIcon; } + setToolTipText(action.getTemplatePresentation().getDescription()); } else { text = actionId; @@ -521,7 +557,7 @@ public class ActionsTree { } } } - + private void paintRowData(Tree tree, Object data, Rectangle bounds, Graphics2D g) { Shortcut[] shortcuts = null; Set<String> abbreviations = null; @@ -552,7 +588,7 @@ public class ActionsTree { Color c2 = new Color(208, 200, 66); g.translate(0, bounds.y - 1); - + for (Shortcut shortcut : shortcuts) { int width = metrics.stringWidth(KeymapUtil.getShortcutText(shortcut)); UIUtil.drawSearchMatch(g, x, x + width, bounds.height, c1, c2); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java index c06dbee44c1a..429a55b2b809 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java @@ -71,7 +71,7 @@ public class ConfigurableExtensionPointUtil { idToConfigurable.put(parentId, parent.addChild(wrapper)); } else { - LOG.error("Can't find parent for " + parentId + " (" + wrapper + ")"); + LOG.debug("Can't find parent for " + parentId + " (" + wrapper + ")"); } } } @@ -79,8 +79,9 @@ public class ConfigurableExtensionPointUtil { for (final Iterator<String> iterator = idToConfigurable.keySet().iterator(); iterator.hasNext(); ) { final String key = iterator.next(); final ConfigurableWrapper wrapper = idToConfigurable.get(key); - if (wrapper.getParentId() != null) { - iterator.remove(); + final String parentId = wrapper.getParentId(); + if (parentId != null && idToConfigurable.containsKey(parentId)) { + iterator.remove(); // remove only processed parents } } ContainerUtil.addAll(result, idToConfigurable.values()); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java index f465e2d0fecb..f1411cf3551d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java @@ -18,9 +18,11 @@ package com.intellij.openapi.options.ex; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurableGroup; import com.intellij.openapi.options.OptionsBundle; +import com.intellij.openapi.options.SearchableConfigurable; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.Map.Entry; public final class MixedConfigurableGroup implements ConfigurableGroup { @@ -66,6 +68,16 @@ public final class MixedConfigurableGroup implements ConfigurableGroup { } list.add(configurable); } + ArrayList<Configurable> buildList = map.get("build"); + if (buildList != null) { + NodeConfigurable buildTools = new NodeConfigurable("build.tools"); + buildTools.add(find("MavenSettings", buildList.iterator())); + buildTools.add(find("reference.settingsdialog.project.gradle", buildList.iterator())); + buildTools.add(find("reference.settingsdialog.project.gant", buildList.iterator())); + if (buildTools.getConfigurables() != null) { + buildList.add(0, buildTools); + } + } ArrayList<ConfigurableGroup> groups = new ArrayList<ConfigurableGroup>(map.size()); groups.add(new MixedConfigurableGroup("appearance", map)); groups.add(new MixedConfigurableGroup("editor", map)); @@ -80,4 +92,18 @@ public final class MixedConfigurableGroup implements ConfigurableGroup { groups.add(other); return groups.toArray(new ConfigurableGroup[groups.size()]); } + + private static Configurable find(String id, Iterator<Configurable> iterator) { + while (iterator.hasNext()) { + Configurable configurable = iterator.next(); + if (configurable instanceof SearchableConfigurable) { + SearchableConfigurable sc = (SearchableConfigurable)configurable; + if (id.equals(sc.getId())) { + iterator.remove(); + return configurable; + } + } + } + return null; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java new file mode 100644 index 000000000000..6571c7a63746 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * 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.intellij.openapi.options.ex; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.OptionsBundle; +import com.intellij.openapi.options.SearchableConfigurable; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; + +public final class NodeConfigurable extends SearchableConfigurable.Parent.Abstract { + private final ArrayList<Configurable> myConfigurables = new ArrayList<Configurable>(); + private final String myId; + + public NodeConfigurable(@NotNull String id) { + myId = id; + } + + public void add(Configurable configurable) { + if (configurable != null) { + super.disposeUIResources(); + myConfigurables.add(configurable); + } + } + + @Override + public void disposeUIResources() { + super.disposeUIResources(); + myConfigurables.clear(); + } + + @NotNull + @Override + public String getId() { + return myId; + } + + @Nullable + @Override + public String getHelpTopic() { + return myId; + } + + @Nls + @Override + public String getDisplayName() { + return OptionsBundle.message("node.configurable." + myId + ".display.name"); + } + + @Override + protected Configurable[] buildConfigurables() { + int size = myConfigurables.size(); + return size == 0 ? null : myConfigurables.toArray(new Configurable[size]); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java index 07e5a93670e6..271539f038a0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java @@ -49,6 +49,7 @@ import com.intellij.ui.navigation.History; import com.intellij.ui.navigation.Place; import com.intellij.ui.speedSearch.ElementFilter; import com.intellij.ui.treeStructure.SimpleNode; +import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.Activatable; import com.intellij.util.ui.update.MergingUpdateQueue; @@ -87,6 +88,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat private final History myHistory = new History(this); private final OptionsTree myTree; + private final SettingsTreeView myTreeView; private final MySearchField mySearch; private final Splitter myMainSplitter; //[back/forward] JComponent myToolbarComponent; @@ -126,7 +128,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat mySearch = new MySearchField() { @Override protected void onTextKeyEvent(final KeyEvent e) { - myTree.processTextEvent(e); + if (myTreeView != null) { + myTreeView.myTree.processKeyEvent(e); + } + else { + myTree.processTextEvent(e); + } } }; @@ -144,12 +151,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat } }); - myTree = new OptionsTree(myProject, groups, getContext()) { + final KeyListener listener = new KeyListener() { @Override - protected void onTreeKeyEvent(final KeyEvent e) { + public void keyTyped(KeyEvent event) { myFilterDocumentWasChanged = false; try { - mySearch.keyEventToTextField(e); + mySearch.keyEventToTextField(event); } finally { if (myFilterDocumentWasChanged && !isFilterFieldVisible()) { @@ -157,10 +164,33 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat } } } + + @Override + public void keyPressed(KeyEvent event) { + keyTyped(event); + } + + @Override + public void keyReleased(KeyEvent event) { + keyTyped(event); + } }; + if (Registry.is("ide.file.settings.tree.new")) { + myTreeView = new SettingsTreeView(listener, getContext(), groups); + myTree = null; + } + else { + myTreeView = null; + myTree = new OptionsTree(myProject, groups, getContext()) { + @Override + protected void onTreeKeyEvent(final KeyEvent e) { + listener.keyTyped(e); + } + }; + } - getContext().addColleague(myTree); - Disposer.register(this, myTree); + getContext().addColleague(myTreeView != null ? myTreeView : myTree); + Disposer.register(this, myTreeView != null ? myTreeView : myTree); mySearch.addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { @@ -198,7 +228,8 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat @Override public Dimension getMinimumSize() { Dimension dimension = super.getMinimumSize(); - dimension.width = Math.max(myTree.getMinimumSize().width, mySearchWrapper.getPreferredSize().width); + JComponent component = myTreeView != null ? myTreeView : myTree; + dimension.width = Math.max(component.getMinimumSize().width, mySearchWrapper.getPreferredSize().width); return dimension; } }; @@ -211,7 +242,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat */ myLeftSide.add(mySearchWrapper, BorderLayout.NORTH); - myLeftSide.add(myTree, BorderLayout.CENTER); + myLeftSide.add(myTreeView != null ? myTreeView : myTree, BorderLayout.CENTER); setLayout(new BorderLayout()); @@ -233,9 +264,19 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat mySpotlightUpdate = new MergingUpdateQueue("OptionsSpotlight", 200, false, this, this, this); if (preselectedConfigurable != null) { - myTree.select(preselectedConfigurable); + if (myTreeView != null) { + myTreeView.select(preselectedConfigurable); + } + else { + myTree.select(preselectedConfigurable); + } } else { - myTree.selectFirst(); + if (myTreeView != null) { + myTreeView.selectFirst(); + } + else { + myTree.selectFirst(); + } } Toolkit.getDefaultToolkit().addAWTEventListener(this, @@ -295,12 +336,16 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat @Deprecated @Nullable public <T extends Configurable> T findConfigurable(Class<T> configurableClass) { - return myTree.findConfigurable(configurableClass); + return myTreeView != null + ? myTreeView.findConfigurable(configurableClass) + : myTree.findConfigurable(configurableClass); } @Nullable public SearchableConfigurable findConfigurableById(@NotNull String configurableId) { - return myTree.findConfigurableById(configurableId); + return myTreeView != null + ? myTreeView.findConfigurableById(configurableId) + : myTree.findConfigurableById(configurableId); } public ActionCallback clearSearchAndSelect(Configurable configurable) { @@ -318,7 +363,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat public ActionCallback select(Configurable configurable, final String text) { myFilter.refilterFor(text, false, true); - return myTree.select(configurable); + return myTreeView != null + ? myTreeView.select(configurable) + : myTree.select(configurable); } private float readProportion(final float defaultValue, final String propertyName) { @@ -367,7 +414,10 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat myOwnDetails.setContent(myContentWrapper); myOwnDetails.setBannerMinHeight(mySearchWrapper.getHeight()); myOwnDetails.setText(getBannerText(configurable)); - if (Registry.is("ide.file.settings.order.new")) { + if (myTreeView != null) { + myOwnDetails.forProject(myTreeView.findConfigurableProject(configurable)); + } + else if (Registry.is("ide.file.settings.order.new")) { myOwnDetails.forProject(myTree.getConfigurableProject(configurable)); } @@ -385,7 +435,8 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat checkModified(oldConfigurable); checkModified(configurable); - if (myTree.myBuilder.getSelectedElements().size() == 0) { + FilteringTreeBuilder builder = myTreeView != null ? myTreeView.myBuilder : myTree.myBuilder; + if (builder.getSelectedElements().size() == 0) { select(configurable).notify(result); } else { result.setDone(); @@ -507,6 +558,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat } private String[] getBannerText(Configurable configurable) { + if (myTreeView != null) { + return myTreeView.getPathNames(configurable); + } final List<Configurable> list = myTree.getPathToRoot(configurable); final String[] result = new String[list.size()]; int add = 0; @@ -795,7 +849,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat getContext().fireErrorsChanged(errors, null); if (!errors.isEmpty()) { - myTree.select(errors.keySet().iterator().next()); + if (myTreeView != null) { + myTreeView.select(errors.keySet().iterator().next()); + } + else { + myTree.select(errors.keySet().iterator().next()); + } } } @@ -835,7 +894,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat return myFiltered.contains(node.getConfigurable()) || isChildOfNameHit(node); } - return true; + return SettingsTreeView.isFiltered(myFiltered, myHits, value); } private boolean isChildOfNameHit(OptionsTree.EditorNode node) { @@ -929,7 +988,8 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat myLastSelected = current; } - final ActionCallback callback = fireUpdate(adjustSelection ? myTree.findNodeFor(toSelect) : null, adjustSelection, now); + SimpleNode node = !adjustSelection ? null : myTreeView != null ? myTreeView.findNode(toSelect) : myTree.findNodeFor(toSelect); + final ActionCallback callback = fireUpdate(node, adjustSelection, now); myFilterDocumentWasChanged = true; @@ -965,7 +1025,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat myFilter.refilterFor(filter, false, true).doWhenDone(new Runnable() { @Override public void run() { - myTree.select(config).notifyWhenDone(result); + if (myTreeView != null) { + myTreeView.select(config).notifyWhenDone(result); + } + else { + myTree.select(config).notifyWhenDone(result); + } } }); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java index e0ab24815ece..175b994122ef 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java @@ -23,6 +23,7 @@ import com.intellij.openapi.options.ConfigurableGroup; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.ex.ConfigurableWrapper; +import com.intellij.openapi.options.ex.NodeConfigurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; @@ -116,10 +117,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl } }); - final JScrollPane scrolls = ScrollPaneFactory.createScrollPane(myTree); - scrolls.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - - add(scrolls, BorderLayout.CENTER); + add(new StickySeparator(myTree), BorderLayout.CENTER); mySelection = new MergingUpdateQueue("OptionsTree", 150, false, this, this, this).setRestartTimerOnAdd(true); myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { @@ -290,7 +288,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl } class Renderer extends GroupedElementsRenderer.Tree { - + private GroupSeparator mySeparator; private JLabel myProjectIcon; private JLabel myHandle; @@ -298,7 +296,8 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl protected void layout() { myRendererComponent.setOpaqueActive(false); - myRendererComponent.add(mySeparatorComponent, BorderLayout.NORTH); + mySeparator = new GroupSeparator(); + myRendererComponent.add(Registry.is("ide.file.settings.order.new") ? mySeparator : mySeparatorComponent, BorderLayout.NORTH); final NonOpaquePanel content = new NonOpaquePanel(new BorderLayout()); myHandle = new JLabel("", SwingConstants.CENTER); @@ -325,7 +324,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl JComponent result; Color fg = UIUtil.getTreeTextForeground(); - + mySeparator.configure(null, false); final Base base = extractNode(value); if (base instanceof EditorNode) { @@ -335,6 +334,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl final DefaultMutableTreeNode prevValue = ((DefaultMutableTreeNode)value).getPreviousSibling(); if (prevValue == null || prevValue instanceof LoadingNode) { group = editor.getGroup(); + mySeparator.configure(group, false); } else { final Base prevBase = extractNode(prevValue); @@ -342,6 +342,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl final EditorNode prevEditor = (EditorNode)prevBase; if (prevEditor.getGroup() != editor.getGroup()) { group = editor.getGroup(); + mySeparator.configure(group, true); } } } @@ -404,8 +405,25 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl myTextLabel.setBorder(new EmptyBorder(1,2,1,0)); } - Project project = getConfigurableProject(base); - if (project != null && Registry.is("ide.file.settings.order.new")) { + Project project = null; + if (base != null && Registry.is("ide.file.settings.order.new")) { + SimpleNode parent = base.getParent(); + if (parent == myRoot) { + project = getConfigurableProject(base); // show icon for top-level nodes + if (base.getConfigurable() instanceof NodeConfigurable) { // special case for custom subgroups (build.tools) + Configurable[] configurables = ((NodeConfigurable)base.getConfigurable()).getConfigurables(); + if (configurables != null) { // assume that all configurables have the same project + project = getConfigurableProject(configurables[0]); + } + } + } + else if (parent instanceof Base && ((Base)parent).getConfigurable() instanceof NodeConfigurable) { + if (((Base)base.getParent()).getConfigurable() instanceof NodeConfigurable) { + project = getConfigurableProject(base); // special case for custom subgroups + } + } + } + if (project != null) { myProjectIcon.setBackground(selected ? getSelectionBackground() : getBackground()); myProjectIcon.setIcon(selected ? AllIcons.General.ProjectConfigurableSelected : AllIcons.General.ProjectConfigurable); myProjectIcon.setVisible(true); @@ -903,4 +921,97 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl } return getConfigurableProject(node.getParent()); } + + private static final class GroupSeparator extends JLabel { + public static final int SPACE = 10; + + public GroupSeparator() { + setFont(UIUtil.getLabelFont()); + setFont(getFont().deriveFont(Font.BOLD)); + } + + public void configure(ConfigurableGroup group, boolean isSpaceNeeded) { + if (group == null) { + setVisible(false); + } + else { + setVisible(true); + int bottom = UIUtil.isUnderNativeMacLookAndFeel() ? 1 : 3; + int top = isSpaceNeeded + ? bottom + SPACE + : bottom; + setBorder(BorderFactory.createEmptyBorder(top, 3, bottom, 3)); + setText(group.getDisplayName()); + } + } + } + + private static final class StickySeparator extends JComponent { + private final SimpleTree myTree; + private final JScrollPane myScroller; + private final GroupSeparator mySeparator; + + public StickySeparator(SimpleTree tree) { + myTree = tree; + myScroller = ScrollPaneFactory.createScrollPane(myTree); + myScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + mySeparator = new GroupSeparator(); + add(myScroller); + } + + @Override + public void doLayout() { + myScroller.setBounds(0, 0, getWidth(), getHeight()); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + + if (Registry.is("ide.file.settings.order.new")) { + ConfigurableGroup group = getGroup(GroupSeparator.SPACE + mySeparator.getFont().getSize()); + if (group != null && group == getGroup(-GroupSeparator.SPACE)) { + mySeparator.configure(group, false); + + Rectangle bounds = myScroller.getViewport().getBounds(); + int height = mySeparator.getPreferredSize().height; + if (bounds.height > height) { + bounds.height = height; + } + g.setColor(myTree.getBackground()); + if (g instanceof Graphics2D) { + int h = bounds.height / 3; + int y = bounds.y + bounds.height - h; + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height - h); + ((Graphics2D)g).setPaint(UIUtil.getGradientPaint( + 0, y, g.getColor(), + 0, y + h, ColorUtil.toAlpha(g.getColor(), 0))); + g.fillRect(bounds.x, y, bounds.width, h); + } + else { + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); + } + mySeparator.setSize(bounds.width - 1, bounds.height); + mySeparator.paint(g.create(bounds.x + 1, bounds.y, bounds.width - 1, bounds.height)); + } + } + } + + private ConfigurableGroup getGroup(int offset) { + TreePath path = myTree.getClosestPathForLocation(-myTree.getX(), -myTree.getY() + offset); + SimpleNode node = myTree.getNodeFor(path); + if (node instanceof FilteringTreeStructure.FilteringNode) { + Object delegate = ((FilteringTreeStructure.FilteringNode)node).getDelegate(); + while (delegate instanceof EditorNode) { + EditorNode editor = (EditorNode)delegate; + ConfigurableGroup group = editor.getGroup(); + if (group != null) { + return group; + } + delegate = editor.getParent(); + } + } + return null; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java new file mode 100644 index 000000000000..9269da7ab967 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -0,0 +1,864 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * 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.intellij.openapi.options.newEditor; + +import com.intellij.icons.AllIcons; +import com.intellij.ide.ui.search.ConfigurableHit; +import com.intellij.ide.util.treeView.NodeDescriptor; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.options.*; +import com.intellij.openapi.options.ex.ConfigurableWrapper; +import com.intellij.openapi.options.ex.NodeConfigurable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.Disposer; +import com.intellij.ui.*; +import com.intellij.ui.treeStructure.*; +import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; +import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.tree.TreeUtil; +import com.intellij.util.ui.update.MergingUpdateQueue; +import com.intellij.util.ui.update.Update; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; +import javax.swing.*; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.plaf.TreeUI; +import javax.swing.plaf.basic.BasicTreeUI; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +/** + * @author Sergey.Malenkov + */ +final class SettingsTreeView extends JComponent implements Disposable, OptionsEditorColleague { + final SimpleTree myTree; + final FilteringTreeBuilder myBuilder; + + private final OptionsEditorContext myContext; + private final MyRoot myRoot; + private final JScrollPane myScroller; + private JLabel mySeparator; + private final MyRenderer myRenderer = new MyRenderer(); + private final IdentityHashMap<Configurable, MyNode> myConfigurableToNodeMap = new IdentityHashMap<Configurable, MyNode>(); + private final MergingUpdateQueue myQueue = new MergingUpdateQueue("OptionsTree", 150, false, this, this, this).setRestartTimerOnAdd(true); + + private Configurable myQueuedConfigurable; + + SettingsTreeView(final KeyListener listener, OptionsEditorContext context, ConfigurableGroup... groups) { + myContext = context; + myRoot = new MyRoot(groups); + + myTree = new MyTree(); + myTree.getInputMap().clear(); + TreeUtil.installActions(myTree); + + myTree.setOpaque(true); + myTree.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 0)); + + myTree.setRowHeight(-1); + myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + + myTree.setCellRenderer(myRenderer); + myTree.setRootVisible(false); + myTree.setShowsRootHandles(false); + + myScroller = ScrollPaneFactory.createScrollPane(myTree); + myScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + add(myScroller); + + myTree.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + myBuilder.revalidateTree(); + } + + @Override + public void componentMoved(ComponentEvent e) { + myBuilder.revalidateTree(); + } + + @Override + public void componentShown(ComponentEvent e) { + myBuilder.revalidateTree(); + } + }); + + myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent event) { + MyNode node = extractNode(event.getNewLeadSelectionPath()); + select(node == null ? null : node.myConfigurable); + } + }); + + myTree.addKeyListener(new KeyListener() { + public void keyTyped(KeyEvent event) { + if (listener != null && isValid(event)) { + listener.keyTyped(event); + } + } + + public void keyPressed(KeyEvent event) { + if (listener != null && isValid(event)) { + listener.keyPressed(event); + } + } + + public void keyReleased(KeyEvent event) { + if (listener != null && isValid(event)) { + listener.keyReleased(event); + } + } + + private boolean isValid(KeyEvent event) { + return null == myTree.getInputMap().get(KeyStroke.getKeyStrokeForEvent(event)); + } + }); + myBuilder = new MyBuilder(new SimpleTreeStructure.Impl(myRoot)); + myBuilder.setFilteringMerge(300, null); + Disposer.register(this, myBuilder); + } + + @NotNull + String[] getPathNames(Configurable configurable) { + ArrayDeque<String> path = new ArrayDeque<String>(); + MyNode node = myConfigurableToNodeMap.get(configurable); + while (node != null) { + path.push(node.myDisplayName); + SimpleNode parent = node.getParent(); + node = parent instanceof MyNode + ? (MyNode)parent + : null; + } + return ArrayUtil.toStringArray(path); + } + + @Nullable + SimpleNode findNode(Configurable toSelect) { + return myConfigurableToNodeMap.get(toSelect); + } + + @Nullable + SearchableConfigurable findConfigurableById(@NotNull String id) { + for (Configurable configurable : myConfigurableToNodeMap.keySet()) { + if (configurable instanceof SearchableConfigurable) { + SearchableConfigurable searchable = (SearchableConfigurable)configurable; + if (id.equals(searchable.getId())) { + return searchable; + } + } + } + return null; + } + + @Nullable + <T extends UnnamedConfigurable> T findConfigurable(@NotNull Class<T> type) { + for (UnnamedConfigurable configurable : myConfigurableToNodeMap.keySet()) { + if (configurable instanceof ConfigurableWrapper) { + ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable; + configurable = wrapper.getConfigurable(); + } + if (type.isInstance(configurable)) { + return type.cast(configurable); + } + } + return null; + } + + @Nullable + Project findConfigurableProject(@Nullable Configurable configurable) { + if (configurable instanceof ConfigurableWrapper) { + ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable; + return wrapper.getExtensionPoint().getProject(); + } + return findConfigurableProject(myConfigurableToNodeMap.get(configurable)); + } + + @Nullable + private static Project findConfigurableProject(@Nullable MyNode node) { + if (node != null) { + Configurable configurable = node.myConfigurable; + if (configurable instanceof ConfigurableWrapper) { + ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable; + return wrapper.getExtensionPoint().getProject(); + } + SimpleNode parent = node.getParent(); + if (parent instanceof MyNode) { + return findConfigurableProject((MyNode)parent); + } + } + return null; + } + + @Nullable + private ConfigurableGroup findConfigurableGroupAt(int x, int y) { + TreePath path = myTree.getClosestPathForLocation(x - myTree.getX(), y - myTree.getY()); + while (path != null) { + MyNode node = extractNode(path); + if (node == null) { + return null; + } + if (node.myComposite instanceof ConfigurableGroup) { + return (ConfigurableGroup)node.myComposite; + } + path = path.getParentPath(); + } + return null; + } + + @Nullable + private static MyNode extractNode(@Nullable Object object) { + if (object instanceof TreePath) { + TreePath path = (TreePath)object; + object = path.getLastPathComponent(); + } + if (object instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)object; + object = node.getUserObject(); + } + if (object instanceof FilteringTreeStructure.FilteringNode) { + FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object; + object = node.getDelegate(); + } + return object instanceof MyNode + ? (MyNode)object + : null; + } + + static boolean isFiltered(Set<Configurable> configurables, ConfigurableHit hits, SimpleNode value) { + if (value instanceof MyNode && !configurables.contains(((MyNode)value).myConfigurable)) { + if (hits != null) { + configurables = hits.getNameFullHits(); + while (value != null) { + if (value instanceof MyNode) { + if (configurables.contains(((MyNode)value).myConfigurable)) { + return true; + } + } + value = value.getParent(); + } + } + return false; + } + return true; + } + + @Override + public void doLayout() { + myScroller.setBounds(0, 0, getWidth(), getHeight()); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + + if (mySeparator == null) { + mySeparator = new JLabel(); + mySeparator.setFont(UIUtil.getLabelFont()); + mySeparator.setFont(getFont().deriveFont(Font.BOLD)); + } + ConfigurableGroup group = findConfigurableGroupAt(0, 5 + mySeparator.getFont().getSize()); + if (group != null && group == findConfigurableGroupAt(0, -5)) { + int offset = UIUtil.isUnderNativeMacLookAndFeel() ? 1 : 3; + mySeparator.setBorder(BorderFactory.createEmptyBorder(offset, 18, offset, 3)); + mySeparator.setText(group.getDisplayName()); + + Rectangle bounds = myScroller.getViewport().getBounds(); + int height = mySeparator.getPreferredSize().height; + if (bounds.height > height) { + bounds.height = height; + } + g.setColor(myTree.getBackground()); + if (g instanceof Graphics2D) { + int h = bounds.height / 4; + int y = bounds.y + bounds.height - h; + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height - h); + ((Graphics2D)g).setPaint(UIUtil.getGradientPaint( + 0, y, g.getColor(), + 0, y + h, ColorUtil.toAlpha(g.getColor(), 0))); + g.fillRect(bounds.x, y, bounds.width, h + h); + } + else { + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); + } + mySeparator.setSize(bounds.width - 1, bounds.height); + mySeparator.paint(g.create(bounds.x + 1, bounds.y, bounds.width - 1, bounds.height)); + } + } + + void selectFirst() { + for (ConfigurableGroup eachGroup : myRoot.myGroups) { + Configurable[] kids = eachGroup.getConfigurables(); + if (kids.length > 0) { + select(kids[0]); + return; + } + } + } + + ActionCallback select(@Nullable final Configurable configurable) { + if (myBuilder.isSelectionBeingAdjusted()) { + return new ActionCallback.Rejected(); + } + final ActionCallback callback = new ActionCallback(); + myQueuedConfigurable = configurable; + myQueue.queue(new Update(this) { + public void run() { + if (configurable == myQueuedConfigurable) { + if (configurable == null) { + fireSelected(null, callback); + } + else { + myBuilder.getReady(this).doWhenDone(new Runnable() { + @Override + public void run() { + if (configurable != myQueuedConfigurable) return; + + MyNode editorNode = myConfigurableToNodeMap.get(configurable); + FilteringTreeStructure.FilteringNode editorUiNode = myBuilder.getVisibleNodeFor(editorNode); + if (editorUiNode == null) return; + + if (!myBuilder.getSelectedElements().contains(editorUiNode)) { + myBuilder.select(editorUiNode, new Runnable() { + public void run() { + fireSelected(configurable, callback); + } + }); + } + else { + myBuilder.scrollSelectionToVisible(new Runnable() { + public void run() { + fireSelected(configurable, callback); + } + }, false); + } + } + }); + } + } + } + + @Override + public void setRejected() { + super.setRejected(); + callback.setRejected(); + } + }); + return callback; + } + + private void fireSelected(Configurable configurable, ActionCallback callback) { + myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable()); + } + + @Override + public void dispose() { + myQueuedConfigurable = null; + } + + @Override + public ActionCallback onSelected(@Nullable Configurable configurable, Configurable oldConfigurable) { + return select(configurable); + } + + @Override + public ActionCallback onModifiedAdded(Configurable configurable) { + myTree.repaint(); + return new ActionCallback.Done(); + } + + @Override + public ActionCallback onModifiedRemoved(Configurable configurable) { + myTree.repaint(); + return new ActionCallback.Done(); + } + + @Override + public ActionCallback onErrorsChanged() { + return new ActionCallback.Done(); + } + + private final class MyRoot extends CachingSimpleNode { + private final ConfigurableGroup[] myGroups; + + private MyRoot(ConfigurableGroup[] groups) { + super(null); + myGroups = groups; + } + + @Override + protected SimpleNode[] buildChildren() { + if (myGroups == null || myGroups.length == 0) { + return NO_CHILDREN; + } + SimpleNode[] result = new SimpleNode[myGroups.length]; + for (int i = 0; i < myGroups.length; i++) { + result[i] = new MyNode(this, myGroups[i]); + } + return result; + } + } + + private final class MyNode extends CachingSimpleNode { + private final Configurable.Composite myComposite; + private final Configurable myConfigurable; + private final String myDisplayName; + + private MyNode(CachingSimpleNode parent, Configurable configurable) { + super(parent); + myComposite = configurable instanceof Configurable.Composite ? (Configurable.Composite)configurable : null; + myConfigurable = configurable; + String name = configurable.getDisplayName(); + myDisplayName = name != null ? name.replace("\n", " ") : "{ " + configurable.getClass().getSimpleName() + " }"; + + myConfigurableToNodeMap.put(configurable, this); + } + + private MyNode(CachingSimpleNode parent, ConfigurableGroup group) { + super(parent); + myComposite = group; + myConfigurable = null; + String name = group.getDisplayName(); + myDisplayName = name != null ? name.replace("\n", " ") : "{ " + group.getClass().getSimpleName() + " }"; + } + + @Override + protected SimpleNode[] buildChildren() { + if (myComposite == null) { + return NO_CHILDREN; + } + Configurable[] configurables = myComposite.getConfigurables(); + if (configurables == null || configurables.length == 0) { + return NO_CHILDREN; + } + SimpleNode[] result = new SimpleNode[configurables.length]; + for (int i = 0; i < configurables.length; i++) { + result[i] = new MyNode(this, configurables[i]); + if (myConfigurable != null) { + myContext.registerKid(myConfigurable, configurables[i]); + } + } + return result; + } + + @Override + public boolean isAlwaysLeaf() { + return myComposite == null; + } + + @Override + public int getWeight() { + return WeightBasedComparator.UNDEFINED_WEIGHT; + } + } + + private final class MyRenderer extends GroupedElementsRenderer.Tree { + private JLabel myNodeIcon; + private JLabel myProjectIcon; + + protected JComponent createItemComponent() { + myTextLabel = new ErrorLabel(); + return myTextLabel; + } + + @Override + protected void layout() { + myNodeIcon = new JLabel(" ", SwingConstants.RIGHT); + myProjectIcon = new JLabel(" ", SwingConstants.LEFT); + myProjectIcon.setOpaque(true); + myRendererComponent.add(BorderLayout.NORTH, mySeparatorComponent); + myRendererComponent.add(BorderLayout.CENTER, myComponent); + myRendererComponent.add(BorderLayout.WEST, myNodeIcon); + myRendererComponent.add(BorderLayout.EAST, myProjectIcon); + } + + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean focused) { + myTextLabel.setOpaque(selected); + myTextLabel.setFont(UIUtil.getLabelFont()); + + String text; + boolean hasSeparatorAbove = false; + int preferredForcedWidth = -1; + + MyNode node = extractNode(value); + if (node == null) { + text = value.toString(); + } + else { + text = node.myDisplayName; + // show groups in bold + if (myRoot == node.getParent()) { + hasSeparatorAbove = node != myRoot.getChildAt(0); + myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD)); + } + TreePath path = tree.getPathForRow(row); + if (path == null) { + if (value instanceof DefaultMutableTreeNode) { + path = new TreePath(((DefaultMutableTreeNode)value).getPath()); + } + } + int forcedWidth = 2000; + if (path != null && tree.isVisible()) { + Rectangle visibleRect = tree.getVisibleRect(); + + int nestingLevel = tree.isRootVisible() ? path.getPathCount() - 1 : path.getPathCount() - 2; + + int left = UIUtil.getTreeLeftChildIndent(); + int right = UIUtil.getTreeRightChildIndent(); + + Insets treeInsets = tree.getInsets(); + + int indent = (left + right) * nestingLevel + (treeInsets != null ? treeInsets.left + treeInsets.right : 0); + + forcedWidth = visibleRect.width > 0 ? visibleRect.width - indent : forcedWidth; + } + preferredForcedWidth = forcedWidth - 4; + } + Component result = configureComponent(text, null, null, null, selected, hasSeparatorAbove, null, preferredForcedWidth); + // update font color for modified configurables + if (!selected && node != null) { + Configurable configurable = node.myConfigurable; + if (configurable != null) { + if (myContext.getErrors().containsKey(configurable)) { + myTextLabel.setForeground(JBColor.RED); + } + else if (myContext.getModified().contains(configurable)) { + myTextLabel.setForeground(JBColor.BLUE); + } + } + } + // configure project icon + Project project = null; + if (node != null) { + SimpleNode parent = node.getParent(); + if (parent instanceof MyNode) { + if (myRoot == parent.getParent()) { + project = findConfigurableProject(node); // show icon for top-level nodes + if (node.myConfigurable instanceof NodeConfigurable) { // special case for custom subgroups (build.tools) + Configurable[] configurables = ((NodeConfigurable)node.myConfigurable).getConfigurables(); + if (configurables != null) { // assume that all configurables have the same project + project = findConfigurableProject(configurables[0]); + } + } + } + else if (((MyNode)parent).myConfigurable instanceof NodeConfigurable) { + if (((MyNode)node.getParent()).myConfigurable instanceof NodeConfigurable) { + project = findConfigurableProject(node); // special case for custom subgroups + } + } + } + } + if (project != null) { + myProjectIcon.setIcon(selected + ? AllIcons.General.ProjectConfigurableSelected + : AllIcons.General.ProjectConfigurable); + myProjectIcon.setToolTipText(OptionsBundle.message(project.isDefault() + ? "configurable.default.project.tooltip" + : "configurable.current.project.tooltip")); + myProjectIcon.setBackground(myTextLabel.getBackground()); + myProjectIcon.setVisible(true); + } + else { + myProjectIcon.setVisible(false); + } + // configure node icon + if (value instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value; + TreePath treePath = new TreePath(treeNode.getPath()); + myNodeIcon.setIcon(myTree.getHandleIcon(treeNode, treePath)); + } + else { + myNodeIcon.setIcon(null); + } + return result; + } + + + public boolean isUnderHandle(Point point) { + Point handlePoint = SwingUtilities.convertPoint(myRendererComponent, point, myNodeIcon); + Rectangle bounds = myNodeIcon.getBounds(); + return bounds.x < handlePoint.x && bounds.getMaxX() >= handlePoint.x; + } + } + + private final class MyTree extends SimpleTree { + @Override + public String getToolTipText(MouseEvent event) { + if (event != null) { + Component component = getDeepestRendererComponentAt(event.getX(), event.getY()); + if (component instanceof JLabel) { + JLabel label = (JLabel)component; + if (label.getIcon() != null) { + String text = label.getToolTipText(); + if (text != null) { + return text; + } + } + } + } + return super.getToolTipText(event); + } + + @Override + protected boolean paintNodes() { + return false; + } + + @Override + protected boolean highlightSingleNode() { + return false; + } + + @Override + public void setUI(TreeUI ui) { + TreeUI actualUI = ui; + if (!(ui instanceof MyTreeUi)) { + actualUI = new MyTreeUi(); + } + super.setUI(actualUI); + } + + @Override + protected boolean isCustomUI() { + return true; + } + + @Override + protected void configureUiHelper(TreeUIHelper helper) { + } + + @Override + public boolean getScrollableTracksViewportWidth() { + return true; + } + + + @Override + public void processKeyEvent(KeyEvent e) { + TreePath path = myTree.getSelectionPath(); + if (path != null) { + if (e.getKeyCode() == KeyEvent.VK_LEFT) { + if (isExpanded(path)) { + collapsePath(path); + return; + } + } + else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { + if (isCollapsed(path)) { + expandPath(path); + return; + } + } + } + super.processKeyEvent(e); + } + + @Override + protected void processMouseEvent(MouseEvent e) { + MyTreeUi ui = (MyTreeUi)myTree.getUI(); + boolean toggleNow = MouseEvent.MOUSE_RELEASED == e.getID() + && UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED) + && !ui.isToggleEvent(e); + + if (toggleNow || MouseEvent.MOUSE_PRESSED == e.getID()) { + TreePath path = getPathForLocation(e.getX(), e.getY()); + if (path != null) { + Rectangle bounds = getPathBounds(path); + if (bounds != null && path.getLastPathComponent() instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + boolean selected = isPathSelected(path); + boolean expanded = isExpanded(path); + Component comp = + myRenderer.getTreeCellRendererComponent(this, node, selected, expanded, node.isLeaf(), getRowForPath(path), isFocusOwner()); + + comp.setBounds(bounds); + comp.validate(); + + Point point = new Point(e.getX() - bounds.x, e.getY() - bounds.y); + if (myRenderer.isUnderHandle(point)) { + if (toggleNow) { + ui.toggleExpandState(path); + } + e.consume(); + return; + } + } + } + } + + super.processMouseEvent(e); + } + + private final class MyTreeUi extends BasicTreeUI { + + @Override + public void toggleExpandState(TreePath path) { + super.toggleExpandState(path); + } + + @Override + public boolean isToggleEvent(MouseEvent event) { + return super.isToggleEvent(event); + } + + @Override + protected boolean shouldPaintExpandControl(TreePath path, + int row, + boolean isExpanded, + boolean hasBeenExpanded, + boolean isLeaf) { + return false; + } + + @Override + protected void paintHorizontalPartOfLeg(Graphics g, + Rectangle clipBounds, + Insets insets, + Rectangle bounds, + TreePath path, + int row, + boolean isExpanded, + boolean hasBeenExpanded, + boolean isLeaf) { + + } + + @Override + protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) { + } + + @Override + public void paint(Graphics g, JComponent c) { + GraphicsUtil.setupAntialiasing(g); + super.paint(g, c); + } + } + } + + private final class MyBuilder extends FilteringTreeBuilder { + + List<Object> myToExpandOnResetFilter; + boolean myRefilteringNow; + boolean myWasHoldingFilter; + + public MyBuilder(SimpleTreeStructure structure) { + super(myTree, myContext.getFilter(), structure, new WeightBasedComparator(false)); + myTree.addTreeExpansionListener(new TreeExpansionListener() { + public void treeExpanded(TreeExpansionEvent event) { + invalidateExpansions(); + } + + public void treeCollapsed(TreeExpansionEvent event) { + invalidateExpansions(); + } + }); + } + + private void invalidateExpansions() { + if (!myRefilteringNow) { + myToExpandOnResetFilter = null; + } + } + + @Override + protected boolean isSelectable(Object object) { + return object instanceof MyNode; + } + + @Override + public boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) { + return myContext.isHoldingFilter(); + } + + @Override + public boolean isToEnsureSelectionOnFocusGained() { + return false; + } + + @Override + protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) { + final List<Object> toRestore = new ArrayList<Object>(); + if (myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) { + myToExpandOnResetFilter = myBuilder.getUi().getExpandedElements(); + } + else if (!myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) { + toRestore.addAll(myToExpandOnResetFilter); + myToExpandOnResetFilter = null; + } + + myWasHoldingFilter = myContext.isHoldingFilter(); + + ActionCallback result = super.refilterNow(preferredSelection, adjustSelection); + myRefilteringNow = true; + return result.doWhenDone(new Runnable() { + public void run() { + myRefilteringNow = false; + if (!myContext.isHoldingFilter() && getSelectedElements().isEmpty()) { + restoreExpandedState(toRestore); + } + } + }); + } + + private void restoreExpandedState(List<Object> toRestore) { + TreePath[] selected = myTree.getSelectionPaths(); + if (selected == null) { + selected = new TreePath[0]; + } + + List<TreePath> toCollapse = new ArrayList<TreePath>(); + + for (int eachRow = 0; eachRow < myTree.getRowCount(); eachRow++) { + if (!myTree.isExpanded(eachRow)) continue; + + TreePath eachVisiblePath = myTree.getPathForRow(eachRow); + if (eachVisiblePath == null) continue; + + Object eachElement = myBuilder.getElementFor(eachVisiblePath.getLastPathComponent()); + if (toRestore.contains(eachElement)) continue; + + + for (TreePath eachSelected : selected) { + if (!eachVisiblePath.isDescendant(eachSelected)) { + toCollapse.add(eachVisiblePath); + } + } + } + + for (TreePath each : toCollapse) { + myTree.collapsePath(each); + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index 27bb8eb5f245..6a37bb2fb69e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -17,7 +17,6 @@ package com.intellij.openapi.progress.impl; import com.intellij.concurrency.JobScheduler; import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ex.ApplicationEx; @@ -46,7 +45,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -public class ProgressManagerImpl extends ProgressManager implements Disposable{ +public class ProgressManagerImpl extends ProgressManager implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.impl.ProgressManagerImpl"); private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0); private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0); @@ -55,7 +54,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ private static final boolean DISABLED = "disabled".equals(System.getProperty("idea.ProcessCanceledException")); private final ScheduledFuture<?> myCheckCancelledFuture; - public ProgressManagerImpl(Application application) { + public ProgressManagerImpl() { if (DISABLED) { myCheckCancelledFuture = null; } @@ -64,7 +63,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ @Override public void run() { ourNeedToCheckCancel = true; - ProgressIndicatorProvider.ourNeedToCheckCancel = true; } }, 0, 10, TimeUnit.MILLISECONDS); } @@ -86,7 +84,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ if (ourLockedCheckCounter > 10) { ourLockedCheckCounter = 0; ourNeedToCheckCancel = true; - ProgressIndicatorProvider.ourNeedToCheckCancel = true; } } else { @@ -99,7 +96,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ public static void canceled() { ourNeedToCheckCancel = true; - ProgressIndicatorProvider.ourNeedToCheckCancel = true; } private static class NonCancelableIndicator extends EmptyProgressIndicator implements NonCancelableSection { @@ -371,6 +367,14 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ public static Future<?> runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task, @NotNull final ProgressIndicator progressIndicator, @Nullable final Runnable continuation) { + return runProcessWithProgressAsynchronously(task, progressIndicator, continuation, ModalityState.NON_MODAL); + } + + @NotNull + public static Future<?> runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task, + @NotNull final ProgressIndicator progressIndicator, + @Nullable final Runnable continuation, + @NotNull final ModalityState modalityState) { if (progressIndicator instanceof Disposable) { Disposer.register(ApplicationManager.getApplication(), (Disposable)progressIndicator); } @@ -397,7 +401,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ public void run() { task.onCancel(); } - }, ModalityState.NON_MODAL); + }, modalityState); } else { final Task.NotificationInfo notificationInfo = task.notifyFinished(); @@ -412,7 +416,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ public void run() { task.onSuccess(); } - }, ModalityState.NON_MODAL); + }, modalityState); } } }; @@ -493,10 +497,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ @Override public void dispose() { - stopCheckCanceled(); - } - - private void stopCheckCanceled() { if (myCheckCancelledFuture != null) myCheckCancelledFuture.cancel(false); } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java index b98f19b25d17..0c18cb7706d9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java @@ -61,7 +61,7 @@ public class ProgressIndicatorUtils { runWithWriteActionPriority(new ProgressIndicatorBase(), task); } - public static void runWithWriteActionPriority(final ProgressIndicator progressIndicator, final ReadTask task) { + private static void surroundWithListener(@NotNull final ProgressIndicator progressIndicator, @NotNull Runnable runnable) { final ApplicationAdapter listener = new ApplicationAdapter() { @Override public void beforeWriteActionStart(Object action) { @@ -69,45 +69,70 @@ public class ProgressIndicatorUtils { } }; final Application application = ApplicationManager.getApplication(); + application.addApplicationListener(listener); try { - application.addApplicationListener(listener); - ProgressManager.getInstance().runProcess(new Runnable(){ - @Override - public void run() { - // This read action can possible last for a long time, we want it to stop immediately on the first write access. - // For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays. - try { - application.runReadAction(new Runnable() { - @Override - public void run() { - task.computeInReadAction(progressIndicator); - } - }); - } - catch (ProcessCanceledException ignore) { - } - finally { - if (progressIndicator.isCanceled()) { - task.onCanceled(progressIndicator); - } - } - } - }, progressIndicator); + runnable.run(); } finally { application.removeApplicationListener(listener); } } + + public static void runWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) { + surroundWithListener(progressIndicator, new Runnable() { + @Override + public void run() { + runUnderProgress(progressIndicator, task); + } + }); + } + + private static void runUnderProgress(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) { + ProgressManager.getInstance().runProcess(new Runnable() { + @Override + public void run() { + // This read action can possible last for a long time, we want it to stop immediately on the first write access. + // For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays. + try { + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + task.computeInReadAction(progressIndicator); + } + }); + } + catch (ProcessCanceledException ignore) { + } + finally { + if (progressIndicator.isCanceled()) { + task.onCanceled(progressIndicator); + } + } + } + }, progressIndicator); + } + public static void scheduleWithWriteActionPriority(@NotNull final ReadTask task) { scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task); } - public static void scheduleWithWriteActionPriority(final ProgressIndicator indicator, final ReadTask task) { - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator indicator, @NotNull final ReadTask task) { + // we have to attach listeners in EDT to avoid "fire write action started while attach listeners from another thread" race condition + ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - runWithWriteActionPriority(indicator, task); + surroundWithListener(indicator, new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + runUnderProgress(indicator, task); + } + }); + } + }); } }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index a20df87718cc..308edb2d81a6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -392,7 +392,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { } private class AppIconProgress extends ProgressIndicatorBase { - double lastFraction; + private double lastFraction; @Override public void setFraction(final double fraction) { @@ -408,16 +408,18 @@ public class DumbServiceImpl extends DumbService implements Disposable { @Override public void finish(@NotNull TaskInfo task) { - UIUtil.invokeLaterIfNeeded(new Runnable() { - @Override - public void run() { - AppIcon appIcon = AppIcon.getInstance(); - if (appIcon.hideProgress(myProject, "indexUpdate")) { - appIcon.requestAttention(myProject, false); - appIcon.setOkBadge(myProject, true); + if (lastFraction != 0) { // we should call setProgress at least once before + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + AppIcon appIcon = AppIcon.getInstance(); + if (appIcon.hideProgress(myProject, "indexUpdate")) { + appIcon.requestAttention(myProject, false); + appIcon.setOkBadge(myProject, true); + } } - } - }); + }); + } } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index d1abc0816845..d1573e2adc7f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -745,16 +745,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra @Override public void windowOpened(WindowEvent e) { - if (!isModal()) { - DialogWrapper wrapper = getDialogWrapper(); - if (wrapper != null) { - JComponent component = wrapper.getPreferredFocusedComponent(); - if (component != null) { - // request focus for non-modal dialog (i.e. TipDialog) - IdeFocusManager.findInstance().requestFocus(component, true); - } - } - } if (!SystemInfo.isMacOSLion) return; Window window = e.getWindow(); if (window instanceof Dialog) { @@ -774,14 +764,9 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra queue.getKeyEventDispatcher().resetState(); } - // if (myProject != null) { - // Project project = myProject.get(); - //if (project != null && !project.isDisposed() && project.isInitialized()) { - // // IdeFocusManager.findInstanceByComponent(this).requestFocus(new MyFocusCommand(dialogWrapper), true); - //} - // } } + // Workaround for switching workspaces on dialog show if (SystemInfo.isMac && myProject != null && Registry.is("ide.mac.fix.dialog.showing") && !dialogWrapper.isModalProgress()) { final IdeFrame frame = WindowManager.getInstance().getIdeFrame(myProject.get()); AppIcon.getInstance().requestFocus(frame); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java index 9739d75be7e7..c93e69438766 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java @@ -61,6 +61,7 @@ public class PluginDownloader { private String myFileName; private String myPluginName; + private BuildNumber myBuildNumber; private File myFile; private File myOldFile; @@ -74,12 +75,18 @@ public class PluginDownloader { myPluginVersion = pluginVersion; } - public PluginDownloader(String pluginId, String pluginUrl, String pluginVersion, String fileName, String pluginName) { + public PluginDownloader(String pluginId, + String pluginUrl, + String pluginVersion, + String fileName, + String pluginName, + BuildNumber buildNumber) { myPluginId = pluginId; myPluginUrl = pluginUrl; myPluginVersion = pluginVersion; myFileName = fileName; myPluginName = pluginName; + myBuildNumber = buildNumber; } @SuppressWarnings("UnusedDeclaration") @@ -89,7 +96,7 @@ public class PluginDownloader { } public boolean prepareToInstall(ProgressIndicator pi) throws IOException { - return prepareToInstall(pi, null); + return prepareToInstall(pi, myBuildNumber); } public boolean prepareToInstall(@Nullable ProgressIndicator pi, @Nullable BuildNumber forBuildNumber) throws IOException { @@ -289,9 +296,15 @@ public class PluginDownloader { } private URLConnection openConnection(final String url) throws IOException { - final URLConnection connection = ApplicationManager.getApplication() != null - ? HttpConfigurable.getInstance().openConnection(url) - : new URL(url).openConnection(); + final URLConnection connection; + if (ApplicationManager.getApplication() != null) { + connection = HttpConfigurable.getInstance().openConnection(url); + } + else { + connection = new URL(url).openConnection(); + connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + } if (connection instanceof HttpURLConnection) { final int responseCode = ((HttpURLConnection)connection).getResponseCode(); if (responseCode != HttpURLConnection.HTTP_OK) { @@ -385,9 +398,14 @@ public class PluginDownloader { } public static PluginDownloader createDownloader(IdeaPluginDescriptor descriptor) throws UnsupportedEncodingException { + return createDownloader(descriptor, null); + } + + public static PluginDownloader createDownloader(IdeaPluginDescriptor descriptor, + BuildNumber buildNumber) throws UnsupportedEncodingException { PluginDownloader downloader = new PluginDownloader(descriptor.getPluginId().getIdString(), - UpdateChecker.getDownloadUrl(descriptor), - descriptor.getVersion(), null, descriptor.getName()); + UpdateChecker.getDownloadUrl(descriptor, buildNumber), + descriptor.getVersion(), null, descriptor.getName(), buildNumber); downloader.setDescriptor(descriptor); return downloader; } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 7e1c81ad2fbc..f1206ef190f1 100755 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -240,13 +240,13 @@ public final class UpdateChecker { updateSettings.myOutdatedPlugins.clear(); if (!toUpdate.isEmpty()) { try { - final List<IdeaPluginDescriptor> process = RepositoryHelper.loadPluginsFromRepository(indicator); + final List<IdeaPluginDescriptor> process = RepositoryHelper.loadPluginsFromRepository(indicator, buildNumber); for (IdeaPluginDescriptor loadedPlugin : process) { final PluginId pluginId = loadedPlugin.getPluginId(); final String idString = pluginId.getIdString(); if (!toUpdate.containsKey(idString)) continue; if (!downloaded.containsKey(pluginId)) { - prepareToInstall(PluginDownloader.createDownloader(loadedPlugin), buildNumber, downloaded, incompatiblePlugins, true, indicator); + prepareToInstall(PluginDownloader.createDownloader(loadedPlugin, buildNumber), buildNumber, downloaded, incompatiblePlugins, true, indicator); } } } @@ -377,7 +377,7 @@ public final class UpdateChecker { final List<IdeaPluginDescriptor> descriptors = RepositoryHelper.loadPluginsFromDescription(inputStream, indicator); for (IdeaPluginDescriptor descriptor : descriptors) { ((PluginNode)descriptor).setRepositoryName(host); - prepareToInstall(PluginDownloader.createDownloader(descriptor), buildNumber, downloaded, incompatiblePlugins, collectToUpdate, + prepareToInstall(PluginDownloader.createDownloader(descriptor, buildNumber), buildNumber, downloaded, incompatiblePlugins, collectToUpdate, indicator); } @@ -425,7 +425,7 @@ public final class UpdateChecker { if (progressIndicator != null) { progressIndicator.setText2(finalPluginUrl); } - final PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null); + final PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null, buildNumber); prepareToInstall(downloader, buildNumber, downloaded, incompatiblePlugins, collectToUpdate, indicator); } catch (IOException e) { @@ -625,11 +625,15 @@ public final class UpdateChecker { urlToCheck = url; } - HttpURLConnection connection = ApplicationManager.getApplication() != null ? - HttpConfigurable.getInstance().openHttpConnection(urlToCheck) : - (HttpURLConnection)new URL(urlToCheck).openConnection(); - connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + HttpURLConnection connection; + if (ApplicationManager.getApplication() != null) { + connection = HttpConfigurable.getInstance().openHttpConnection(urlToCheck); + } + else { + connection = (HttpURLConnection)new URL(urlToCheck).openConnection(); + connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + } connection.connect(); inputStreams[0] = connection.getInputStream(); @@ -885,7 +889,7 @@ public final class UpdateChecker { } } - static String getDownloadUrl(IdeaPluginDescriptor descriptor) throws UnsupportedEncodingException { + static String getDownloadUrl(IdeaPluginDescriptor descriptor, @Nullable BuildNumber buildNumber) throws UnsupportedEncodingException { String url = null; if (descriptor instanceof PluginNode) { url = ((PluginNode)descriptor).getDownloadUrl(); @@ -904,11 +908,13 @@ public final class UpdateChecker { String uuid = ApplicationManager.getApplication() == null ? UUID.randomUUID().toString() : getInstallationUID(PropertiesComponent.getInstance()); - String buildNumber = ApplicationManager.getApplication() != null - ? ApplicationInfo.getInstance().getApiVersion() - : ApplicationInfoImpl.getShadowInstance().getBuild().asString(); + String buildNumberAsString = buildNumber != null + ? buildNumber.asString() + : ApplicationManager.getApplication() != null + ? ApplicationInfo.getInstance().getApiVersion() + : ApplicationInfoImpl.getShadowInstance().getBuild().asString(); url = RepositoryHelper.getDownloadUrl() + URLEncoder.encode(descriptor.getPluginId().getIdString(), "UTF8") + - "&build=" + buildNumber + "&uuid=" + URLEncoder.encode(uuid, "UTF8"); + "&build=" + buildNumberAsString + "&uuid=" + URLEncoder.encode(uuid, "UTF8"); } return url; } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java index 94e287e0fdb7..97082c394aaf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java @@ -74,6 +74,8 @@ public class UpdatesXmlLoader { int followCount = 2; while(true) { cnx = requestUrl.openConnection(); + cnx.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); + cnx.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); if (cnx instanceof HttpURLConnection) { HttpURLConnection hcnx = (HttpURLConnection)cnx; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java index fbe213f20bb0..2bff2a10d5cd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ import javax.swing.*; import java.util.List; public abstract class ToolWindowManagerEx extends ToolWindowManager { - public abstract void initToolWindow(ToolWindowEP bean); + public abstract void initToolWindow(@NotNull ToolWindowEP bean); public static ToolWindowManagerEx getInstanceEx(final Project project){ return (ToolWindowManagerEx)getInstance(project); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java index c302cce7572e..867c404073d3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java @@ -203,9 +203,6 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { public ActionCallback requestFocus(@NotNull final FocusCommand command, final boolean forced) { assertDispatchThread(); - if (!forced && !command.canFocusChangeFrom(getFocusOwner())) { - return ActionCallback.REJECTED; - } if (isInternalMode) { recordCommand(command, new Throwable(), forced); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java index 71f964504102..1613953287b6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java @@ -24,8 +24,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.Divider; import com.intellij.openapi.ui.Painter; import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer; -import com.intellij.openapi.ui.popup.Balloon; -import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Weighted; import com.intellij.openapi.wm.IdeGlassPane; @@ -287,8 +285,6 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent return false; } - private MouseEvent myLastRedispatchedEvent = null; - private boolean preprocess(final MouseEvent e, final boolean motion, JRootPane eventRootPane) { try { final MouseEvent event = convertEvent(e, eventRootPane); @@ -297,25 +293,6 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent return false; } - Component c = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY()); - Balloon balloon = JBPopupFactory.getInstance().getParentBalloonFor(c); - if (balloon != null && myLastRedispatchedEvent != e) { - if (e.getID() == MouseEvent.MOUSE_PRESSED - && IdeTooltipManager.getInstance().hasCurrent() - && IdeTooltipManager.getInstance().hideCurrent(event, null, null, false)) { - //noinspection SSBasedInspection - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - myLastRedispatchedEvent = e; - IdeEventQueue.getInstance().dispatchEvent(e); - } - }); - } - return false; - } - myLastRedispatchedEvent = null; - for (EventListener each : mySortedMouseListeners) { if (motion && each instanceof MouseMotionListener) { fireMouseMotion((MouseMotionListener)each, event); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java index 8b78b1632f79..7b9a7494c640 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java @@ -87,6 +87,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { return tw; } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @@ -96,11 +97,13 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { return doRegisterToolWindow(id, parentDisposable); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) { return doRegisterToolWindow(id, null); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @@ -111,19 +114,22 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { return doRegisterToolWindow(id, parentDisposable); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable) { + @NotNull Disposable parentDisposable) { return doRegisterToolWindow(id, parentDisposable); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) { return doRegisterToolWindow(id, null); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @@ -132,6 +138,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { return doRegisterToolWindow(id, null); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, final Disposable parentDisposable, final boolean dumbAware) { @@ -152,6 +159,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { return false; } + @NotNull @Override public String[] getToolWindowIds() { return ArrayUtil.EMPTY_STRING_ARRAY; @@ -168,9 +176,10 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void invokeLater(Runnable runnable) { + public void invokeLater(@NotNull Runnable runnable) { } + @NotNull @Override public IdeFocusManager getFocusManager() { return IdeFocusManagerHeadless.INSTANCE; @@ -190,7 +199,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void initToolWindow(ToolWindowEP bean) { + public void initToolWindow(@NotNull ToolWindowEP bean) { } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java index efcdd148d57b..1fa2bd95defe 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java @@ -72,6 +72,7 @@ public final class ToolWindowImpl implements ToolWindowEx { private boolean myPlaceholderMode; private ToolWindowFactory myContentFactory; + @NotNull private ActionCallback myActivation = new ActionCallback.Done(); private final BusyObject.Impl myShowing = new BusyObject.Impl() { @Override @@ -115,18 +116,22 @@ public final class ToolWindowImpl implements ToolWindowEx { myChangeSupport.addPropertyChangeListener(l); } + @Override public final void removePropertyChangeListener(final PropertyChangeListener l) { myChangeSupport.removePropertyChangeListener(l); } + @Override public final void activate(final Runnable runnable) { activate(runnable, true); } + @Override public void activate(@Nullable final Runnable runnable, final boolean autoFocusContents) { activate(runnable, autoFocusContents, true); } + @Override public void activate(@Nullable final Runnable runnable, boolean autoFocusContents, boolean forced) { ApplicationManager.getApplication().assertIsDispatchThread(); @@ -136,6 +141,7 @@ public final class ToolWindowImpl implements ToolWindowEx { myToolWindowManager.activateToolWindow(myId, forced, autoFocusContents); getActivation().doWhenDone(new Runnable() { + @Override public void run() { myToolWindowManager.invokeLater(new Runnable() { @Override @@ -150,6 +156,7 @@ public final class ToolWindowImpl implements ToolWindowEx { }); } + @Override public final boolean isActive() { ApplicationManager.getApplication().assertIsDispatchThread(); if (myToolWindowManager.isEditorComponentActive()) return false; @@ -182,11 +189,13 @@ public final class ToolWindowImpl implements ToolWindowEx { return result; } + @Override public final void show(final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.showToolWindow(myId); if (runnable != null) { getActivation().doWhenDone(new Runnable() { + @Override public void run() { myToolWindowManager.invokeLater(runnable); } @@ -194,6 +203,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public final void hide(@Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.hideToolWindow(myId, false); @@ -202,14 +212,17 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public final boolean isVisible() { return myToolWindowManager.isToolWindowVisible(myId); } + @Override public final ToolWindowAnchor getAnchor() { return myToolWindowManager.getToolWindowAnchor(myId); } + @Override public final void setAnchor(final ToolWindowAnchor anchor, @Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setToolWindowAnchor(myId, anchor); @@ -218,11 +231,13 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public boolean isSplitMode() { ApplicationManager.getApplication().assertIsDispatchThread(); return myToolWindowManager.isSplitMode(myId); } + @Override public void setContentUiType(ToolWindowContentUiType type, @Nullable Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setContentUiType(myId, type); @@ -231,15 +246,18 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public void setDefaultContentUiType(@NotNull ToolWindowContentUiType type) { myToolWindowManager.setDefaultContentUiType(this, type); } + @Override public ToolWindowContentUiType getContentUiType() { ApplicationManager.getApplication().assertIsDispatchThread(); return myToolWindowManager.getContentUiType(myId); } + @Override public void setSplitMode(final boolean isSideTool, @Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setSideTool(myId, isSideTool); @@ -248,20 +266,24 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public final void setAutoHide(final boolean state) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setToolWindowAutoHide(myId, state); } + @Override public final boolean isAutoHide() { ApplicationManager.getApplication().assertIsDispatchThread(); return myToolWindowManager.isToolWindowAutoHide(myId); } + @Override public final ToolWindowType getType() { return myToolWindowManager.getToolWindowType(myId); } + @Override public final void setType(final ToolWindowType type, @Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setToolWindowType(myId, type); @@ -270,19 +292,23 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public final ToolWindowType getInternalType() { ApplicationManager.getApplication().assertIsDispatchThread(); return myToolWindowManager.getToolWindowInternalType(myId); } + @Override public void stretchWidth(int value) { myToolWindowManager.stretchWidth(this, value); } + @Override public void stretchHeight(int value) { myToolWindowManager.stretchHeight(this, value); } + @Override public InternalDecorator getDecorator() { return myDecorator; } @@ -297,6 +323,7 @@ public final class ToolWindowImpl implements ToolWindowEx { getDecorator().setTitleActions(actions); } + @Override public final void setAvailable(final boolean available, final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); final Boolean oldAvailable = myAvailable ? Boolean.TRUE : Boolean.FALSE; @@ -307,6 +334,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public void installWatcher(ContentManager contentManager) { new ContentManagerWatcher(this, contentManager); } @@ -316,14 +344,17 @@ public final class ToolWindowImpl implements ToolWindowEx { * <code>ContentManager</code> class. Otherwise it delegates the functionality to the * passed content manager. */ + @Override public final boolean isAvailable() { return myAvailable && myComponent != null; } + @Override public final JComponent getComponent() { return myComponent; } + @Override public ContentManager getContentManager() { return myContentManager; } @@ -332,6 +363,7 @@ public final class ToolWindowImpl implements ToolWindowEx { return myContentUI; } + @Override public final Icon getIcon() { ApplicationManager.getApplication().assertIsDispatchThread(); return myIcon; @@ -342,17 +374,20 @@ public final class ToolWindowImpl implements ToolWindowEx { return myId; } + @Override public final String getTitle() { ApplicationManager.getApplication().assertIsDispatchThread(); return getSelectedContent().getDisplayName(); } + @Override @NotNull public final String getStripeTitle() { ApplicationManager.getApplication().assertIsDispatchThread(); return ObjectUtils.notNull(myStripeTitle, myId); } + @Override public final void setIcon(final Icon icon) { ApplicationManager.getApplication().assertIsDispatchThread(); final Icon oldIcon = getIcon(); @@ -364,6 +399,7 @@ public final class ToolWindowImpl implements ToolWindowEx { myChangeSupport.firePropertyChange(PROP_ICON, oldIcon, icon); } + @Override public final void setTitle(String title) { ApplicationManager.getApplication().assertIsDispatchThread(); String oldTitle = getTitle(); @@ -371,6 +407,7 @@ public final class ToolWindowImpl implements ToolWindowEx { myChangeSupport.firePropertyChange(PROP_TITLE, oldTitle, title); } + @Override public final void setStripeTitle(@NotNull String stripeTitle) { ApplicationManager.getApplication().assertIsDispatchThread(); String oldTitle = myStripeTitle; @@ -415,18 +452,22 @@ public final class ToolWindowImpl implements ToolWindowEx { return myDecorator != null ? myDecorator.createPopupGroup() : null; } + @Override public void setDefaultState(@Nullable final ToolWindowAnchor anchor, @Nullable final ToolWindowType type, @Nullable final Rectangle floatingBounds) { myToolWindowManager.setDefaultState(this, anchor, type, floatingBounds); } + @Override public void setToHideOnEmptyContent(final boolean hideOnEmpty) { myHideOnEmptyContent = hideOnEmpty; } + @Override public boolean isToHideOnEmptyContent() { return myHideOnEmptyContent; } + @Override public boolean isDisposed() { return myContentManager.isDisposed(); } @@ -439,12 +480,15 @@ public final class ToolWindowImpl implements ToolWindowEx { myPlaceholderMode = placeholderMode; } + @Override + @NotNull public ActionCallback getActivation() { return myActivation; } - public ActionCallback setActivation(ActionCallback activation) { - if (myActivation != null && !myActivation.isProcessed() && !myActivation.equals(activation)) { + @NotNull + public ActionCallback setActivation(@NotNull ActionCallback activation) { + if (!myActivation.isProcessed() && !myActivation.equals(activation)) { myActivation.setRejected(); } @@ -467,6 +511,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } } + @Override public void showContentPopup(InputEvent inputEvent) { myContentUI.toggleContentPopup(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 555e0666f72e..95b3d54f8030 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -363,6 +363,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return IdeFocusManager.getInstance(project); } + @NotNull public Project getProject() { return myProject; } @@ -482,21 +483,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } @Override - public void initToolWindow(ToolWindowEP bean) { - ToolWindowAnchor toolWindowAnchor; - try { - toolWindowAnchor = ToolWindowAnchor.fromText(bean.anchor); - } - catch (Exception e) { - LOG.error(e); - return; - } + public void initToolWindow(@NotNull ToolWindowEP bean) { JLabel label = new JLabel("Initializing...", SwingConstants.CENTER); label.setOpaque(true); final Color treeBg = UIManager.getColor("Tree.background"); label.setBackground(ColorUtil.toAlpha(treeBg, 180)); final Color treeFg = UIUtil.getTreeForeground(); label.setForeground(ColorUtil.toAlpha(treeFg, 180)); + ToolWindowAnchor toolWindowAnchor = ToolWindowAnchor.fromText(bean.anchor); final ToolWindowFactory factory = bean.getToolWindowFactory(); final ToolWindowImpl toolWindow = (ToolWindowImpl)registerToolWindow(bean.id, label, toolWindowAnchor, myProject, DumbService.isDumbAware(factory), @@ -747,7 +741,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myActiveStack.push(id); } - if (autoFocusContents) { + if (autoFocusContents && ApplicationManager.getApplication().isActive()) { appendRequestFocusInToolWindowCmd(id, commandsList, forcedFocusRequest); } } @@ -826,6 +820,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements appendApplyWindowInfoCmd(info, commandsList); } + @NotNull @Override public String[] getToolWindowIds() { final WindowInfoImpl[] infos = myLayout.getInfos(); @@ -1087,6 +1082,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements appendApplyWindowInfoCmd(toBeShownInfo, commandsList); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, @NotNull final JComponent component, @@ -1094,6 +1090,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return registerToolWindow(id, component, anchor, false); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, @NotNull JComponent component, @@ -1102,6 +1099,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return registerToolWindow(id, component, anchor, parentDisposable, false, false); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @@ -1111,6 +1109,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return registerToolWindow(id, component, anchor, parentDisposable, canWorkInDumbMode, false); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, @NotNull JComponent component, @@ -1120,6 +1119,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return registerDisposable(id, parentDisposable, registerToolWindow(id, component, anchor, false, canCloseContents, canWorkInDumbMode)); } + @NotNull private ToolWindow registerToolWindow(@NotNull final String id, @NotNull final JComponent component, @NotNull final ToolWindowAnchor anchor, @@ -1127,11 +1127,13 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return registerToolWindow(id, component, anchor, false, false, canWorkInDumbMode); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) { return registerToolWindow(id, null, anchor, false, canCloseContent, false); } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @@ -1141,15 +1143,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } + @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, @NotNull final Disposable parentDisposable, final boolean canWorkInDumbMode) { - return registerDisposable(id, parentDisposable, registerToolWindow(id, null, anchor, false, canCloseContent, canWorkInDumbMode)); + ToolWindow window = registerToolWindow(id, null, anchor, false, canCloseContent, canWorkInDumbMode); + return registerDisposable(id, parentDisposable, window); } + @NotNull private ToolWindow registerToolWindow(@NotNull final String id, @Nullable final JComponent component, @NotNull final ToolWindowAnchor anchor, @@ -1216,7 +1221,8 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return toolWindow; } - private ToolWindow registerDisposable(final String id, @NotNull final Disposable parentDisposable, final ToolWindow window) { + @NotNull + private ToolWindow registerDisposable(@NotNull final String id, @NotNull final Disposable parentDisposable, @NotNull ToolWindow window) { Disposer.register(parentDisposable, new Disposable() { @Override public void dispose() { @@ -1353,12 +1359,13 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } @Override - public void invokeLater(final Runnable runnable) { + public void invokeLater(@NotNull final Runnable runnable) { List<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>(); commandList.add(new InvokeLaterCmd(runnable, myWindowManager.getCommandProcessor())); execute(commandList); } + @NotNull @Override public IdeFocusManager getFocusManager() { return IdeFocusManager.getInstance(myProject); diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java index b51c85bc2c18..2da812614b88 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java @@ -25,8 +25,9 @@ public interface RemoteSdkAdditionalData<T extends RemoteSdkCredentials> extends SdkAdditionalData, RemoteSdkCredentialsProducer<T>, RemoteSdkProperties { void completeInitialization(); + @Deprecated boolean isInitialized(); - + @Deprecated void setInitialized(boolean initialized); void setVagrantConnectionType(@NotNull VagrantBasedCredentialsHolder vagrantBasedCredentials); diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java index d92839e212b8..ae84919ac9ce 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java @@ -144,6 +144,16 @@ public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implemen myRemoteSdkProperties.setInitialized(initialized); } + @Override + public boolean isValid() { + return myRemoteSdkProperties.isValid(); + } + + @Override + public void setValid(boolean valid) { + myRemoteSdkProperties.setValid(valid); + } + public static boolean isRemoteSdk(@Nullable String path) { if (path != null) { return path.startsWith(SSH_PREFIX) || path.startsWith(RemoteConnectionCredentialsWrapper.VAGRANT_PREFIX) || diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java index a690afd96afc..d9cca99cce14 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java @@ -84,9 +84,19 @@ public interface RemoteSdkProperties { String getSdkId(); + /** + * isValid() is used now + * To be removed in IDEA 15 + * + * @deprecated + */ @Deprecated boolean isInitialized(); @Deprecated void setInitialized(boolean initialized); + + boolean isValid(); + + void setValid(boolean valid); } diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java index a0407d27f7e9..68e22f79c7fc 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java @@ -36,6 +36,7 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties { private static final String REMOTE_ROOTS = "REMOTE_ROOTS"; private static final String REMOTE_PATH = "REMOTE_PATH"; private static final String INITIALIZED = "INITIALIZED"; + private static final String VALID = "VALID"; private static final String PATH_MAPPINGS = "PATH_MAPPINGS"; private String mySdkId; @@ -51,6 +52,8 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties { private boolean myInitialized = false; + private boolean myValid = true; + @NotNull private PathMappingSettings myPathMappings = new PathMappingSettings(); @@ -144,6 +147,16 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties { myInitialized = initialized; } + @Override + public boolean isValid() { + return myValid; + } + + @Override + public void setValid(boolean valid) { + myValid = valid; + } + public void copyTo(RemoteSdkProperties copy) { copy.setInterpreterPath(getInterpreterPath()); copy.setHelpersPath(getHelpersPath()); @@ -152,6 +165,8 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties { copy.setRemoteRoots(getRemoteRoots()); copy.setInitialized(isInitialized()); + + copy.setValid(isValid()); } public void save(Element rootElement) { @@ -159,6 +174,7 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties { rootElement.setAttribute(HELPERS_PATH, StringUtil.notNullize(getHelpersPath())); rootElement.setAttribute(INITIALIZED, Boolean.toString(isInitialized())); + rootElement.setAttribute(VALID, Boolean.toString(isValid())); PathMappingSettings.writeExternal(rootElement, myPathMappings); @@ -177,6 +193,8 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties { setInitialized(StringUtil.parseBoolean(element.getAttributeValue(INITIALIZED), true)); + setValid(StringUtil.parseBoolean(element.getAttributeValue(VALID), true)); + setPathMappings(PathMappingSettings.readExternal(element)); } } diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java index d8b204cfd76c..1fc23e5f4055 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java @@ -54,7 +54,7 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte myTipComponent = new TipComponent(); - myTipComponent.addMouseListener(new MouseAdapter() { + MouseAdapter tipMouseAdapter = new MouseAdapter() { @Override public void mouseExited(MouseEvent e) { // don't hide the hint if mouse exited to myComponent @@ -62,7 +62,60 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte hideHint(); } } - }); + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + Point p = e.getLocationOnScreen(); + SwingUtilities.convertPointFromScreen(p, myComponent); + myComponent.dispatchEvent(new MouseWheelEvent(myComponent, + e.getID(), + e.getWhen(), + e.getModifiers(), + p.x, p.y, + e.getClickCount(), + e.isPopupTrigger(), + e.getScrollType(), + e.getScrollAmount(), + e.getWheelRotation())); + } + + @Override + public void mouseClicked(MouseEvent e) { + Point p = e.getLocationOnScreen(); + SwingUtilities.convertPointFromScreen(p, myComponent); + myComponent.dispatchEvent(new MouseEvent(myComponent, + e.getID(), + e.getWhen(), + e.getModifiers(), + p.x, p.y, + e.getClickCount(), + e.isPopupTrigger(), + e.getButton())); + } + + @Override + public void mousePressed(MouseEvent e) { + mouseClicked(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + mouseClicked(e); + } + + @Override + public void mouseMoved(MouseEvent e) { + mouseClicked(e); + } + + @Override + public void mouseDragged(MouseEvent e) { + mouseClicked(e); + } + }; + myTipComponent.addMouseListener(tipMouseAdapter); + myTipComponent.addMouseWheelListener(tipMouseAdapter); + myTipComponent.addMouseMotionListener(tipMouseAdapter); myComponent.addMouseListener( new MouseListener() { diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 513d5cedb2ab..d41d0bb5ef18 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -331,7 +331,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { Integer result = JLayeredPane.DEFAULT_LAYER; switch (myLayer) { case normal: - result = JLayeredPane.DEFAULT_LAYER; + result = JLayeredPane.POPUP_LAYER; break; case top: result = JLayeredPane.DRAG_LAYER; diff --git a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java index d5fc8dcca1ba..fe041c5ea02b 100644 --- a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.tabs.*; import com.intellij.ui.tabs.impl.JBEditorTabs; +import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.ui.tabs.impl.TabLabel; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -34,8 +35,7 @@ import java.awt.event.MouseListener; import java.util.concurrent.CopyOnWriteArraySet; public class JBTabsPaneImpl implements TabbedPane, SwingConstants { - - private final JBTabs myTabs; + private final JBTabsImpl myTabs; private final CopyOnWriteArraySet<ChangeListener> myListeners = new CopyOnWriteArraySet<ChangeListener>(); public JBTabsPaneImpl(@Nullable Project project, int tabPlacement, @NotNull Disposable parent) { @@ -64,6 +64,9 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants { maxOffset++; g2d.setPaint(UIUtil.getPanelBackground()); + if (getFirstTabOffset() > 0) { + g2d.fillRect(clip.x, clip.y, clip.x + getFirstTabOffset() - 1, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); + } g2d.fillRect(clip.x + maxOffset, clip.y, clip.width - maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); g2d.setPaint(new JBColor(Gray._181, UIUtil.getPanelBackground())); g2d.drawLine(clip.x + maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT, clip.x + clip.width, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT); @@ -77,6 +80,7 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants { super.paintSelectionAndBorder(g2d); } }; + myTabs.setFirstTabOffset(10); myTabs.addListener(new TabsListener.Adapter() { @Override diff --git a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java index aac2e77982ba..e8c6f49f8088 100644 --- a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java +++ b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java @@ -49,6 +49,7 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier { } private final LibNotify myLibNotify; + private final String myIcon; private LibNotifyWrapper() { myLibNotify = (LibNotify)Native.loadLibrary("libnotify.so.4", LibNotify.class); @@ -58,6 +59,9 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier { throw new IllegalStateException("notify_init failed"); } + String icon = AppUIUtil.findIcon(PathManager.getBinPath()); + myIcon = icon != null ? icon : "dialog-information"; + MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() { @Override @@ -69,9 +73,7 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier { @Override public void notify(@NotNull Set<String> allNames, @NotNull String name, @NotNull String title, @NotNull String description) { - String icon = AppUIUtil.findIcon(PathManager.getBinPath()); - if (icon == null) icon = "dialog-information"; - Pointer notification = myLibNotify.notify_notification_new(title, description, icon); + Pointer notification = myLibNotify.notify_notification_new(title, description, myIcon); myLibNotify.notify_notification_show(notification, null); } } diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java index c738995059dc..cbcde2d36418 100644 --- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java +++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java @@ -288,6 +288,10 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear return null; } + public void showPopup() { + manageSearchPopup(new SearchPopup("")); + } + public void hidePopup() { manageSearchPopup(null); } diff --git a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java index b596204e6ad2..eeeb90dc7ae7 100644 --- a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java +++ b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java @@ -20,7 +20,6 @@ import com.intellij.util.PairFunction; import com.intellij.util.containers.Convertor; import javax.swing.*; -import javax.swing.table.TableModel; import java.util.ListIterator; public class TableSpeedSearch extends SpeedSearchBase<JTable> { @@ -55,9 +54,8 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> { @Override protected boolean isSpeedSearchEnabled() { - JTable table = getComponent(); - boolean tableIsNotEmpty = table.getRowCount() != 0 && table.getColumnCount() != 0; - return tableIsNotEmpty && !table.isEditing() && super.isSpeedSearchEnabled(); + boolean tableIsNotEmpty = myComponent.getRowCount() != 0 && myComponent.getColumnCount() != 0; + return tableIsNotEmpty && !myComponent.isEditing() && super.isSpeedSearchEnabled(); } @Override @@ -67,16 +65,14 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> { @Override protected int getElementCount() { - final TableModel tableModel = myComponent.getModel(); - return tableModel.getRowCount() * tableModel.getColumnCount(); + return myComponent.getRowCount() * myComponent.getColumnCount(); } @Override protected void selectElement(Object element, String selectedText) { final int index = ((Integer)element).intValue(); - final TableModel model = myComponent.getModel(); - final int row = index / model.getColumnCount(); - final int col = index % model.getColumnCount(); + final int row = index / myComponent.getColumnCount(); + final int col = index % myComponent.getColumnCount(); myComponent.getSelectionModel().setSelectionInterval(row, row); myComponent.getColumnModel().getSelectionModel().setSelectionInterval(col, col); TableUtil.scrollSelectionToVisible(myComponent); @@ -87,7 +83,7 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> { final int row = myComponent.getSelectedRow(); final int col = myComponent.getSelectedColumn(); // selected row is not enough as we want to select specific cell in a large multi-column table - return row > -1 && col > -1 ? row * myComponent.getModel().getColumnCount() + col : -1; + return row > -1 && col > -1 ? row * myComponent.getColumnCount() + col : -1; } @Override @@ -98,10 +94,9 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> { @Override protected String getElementText(Object element) { final int index = ((Integer)element).intValue(); - final TableModel model = myComponent.getModel(); - int row = myComponent.convertRowIndexToModel(index / model.getColumnCount()); - int col = myComponent.convertColumnIndexToModel(index % model.getColumnCount()); - Object value = model.getValueAt(row, col); + int row = index / myComponent.getColumnCount(); + int col = index % myComponent.getColumnCount(); + Object value = myComponent.getValueAt(row, col); return myToStringConvertor.fun(value, new Cell(row, col)); } diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java index 82dd6ff085fd..595a93db592f 100644 --- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java @@ -1,6 +1,5 @@ - /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +44,7 @@ public class ContentImpl extends UserDataHolderBase implements Content { private JComponent myComponent; private Icon myIcon; private final PropertyChangeSupport myChangeSupport = new PropertyChangeSupport(this); - private ContentManager myManager = null; + private ContentManager myManager; private boolean myIsLocked = false; private boolean myPinnable = true; private Icon myLayeredIcon = new LayeredIcon(2); @@ -294,6 +293,7 @@ public class ContentImpl extends UserDataHolderBase implements Content { return myPlace; } + @Override @NonNls public String toString() { StringBuilder sb = new StringBuilder("Content name=").append(myDisplayName); diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java index b6e739692ede..d0b110f083bf 100644 --- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.ui.content.impl; +import com.intellij.ide.DataManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataProvider; @@ -32,13 +33,15 @@ import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.content.*; import com.intellij.ui.switcher.SwitchProvider; import com.intellij.ui.switcher.SwitchTarget; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.SmartList; + import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.EventListenerList; import java.awt.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -55,21 +58,21 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene private static final Logger LOG = Logger.getInstance("#com.intellij.ui.content.impl.ContentManagerImpl"); private ContentUI myUI; - private final ArrayList<Content> myContents; - private EventListenerList myListeners; - private List<Content> mySelection = new ArrayList<Content>(); + private final List<Content> myContents = new ArrayList<Content>(); + private final List<ContentManagerListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); + private final List<Content> mySelection = new ArrayList<Content>(); private final boolean myCanCloseContents; - private MyContentComponent myContentComponent; - private MyFocusProxy myFocusProxy; - private JPanel myComponent; - + private Wrapper.FocusHolder myFocusProxy; + private MyNonOpaquePanel myComponent; private final Set<Content> myContentWithChangedComponent = new HashSet<Content>(); private boolean myDisposed; private final Project myProject; + private final List<DataProvider> dataProviders = new SmartList<DataProvider>(); + /** * WARNING: as this class adds listener to the ProjectManager which is removed on projectClosed event, all instances of this class * must be created on already OPENED projects, otherwise there will be memory leak! @@ -77,8 +80,6 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene public ContentManagerImpl(@NotNull ContentUI contentUI, boolean canCloseContents, @NotNull Project project) { myProject = project; myCanCloseContents = canCloseContents; - myContents = new ArrayList<Content>(); - myListeners = new EventListenerList(); myUI = contentUI; myUI.setManager(this); @@ -95,15 +96,18 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene @Override public JComponent getComponent() { if (myComponent == null) { - myComponent = new NonOpaquePanel(new BorderLayout()); + myComponent = new MyNonOpaquePanel(); + + myFocusProxy = new Wrapper.FocusHolder(); + myFocusProxy.setOpaque(false); + myFocusProxy.setPreferredSize(new Dimension(0, 0)); - myFocusProxy = new MyFocusProxy(); - myContentComponent = new MyContentComponent(); - myContentComponent.setContent(myUI.getComponent()); - myContentComponent.setFocusCycleRoot(true); + MyContentComponent contentComponent = new MyContentComponent(); + contentComponent.setContent(myUI.getComponent()); + contentComponent.setFocusCycleRoot(true); myComponent.add(myFocusProxy, BorderLayout.NORTH); - myComponent.add(myContentComponent, BorderLayout.CENTER); + myComponent.add(contentComponent, BorderLayout.CENTER); } return myComponent; } @@ -117,58 +121,51 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene return busyObject != null ? busyObject.getReady(requestor) : new ActionCallback.Done(); } - private class MyContentComponent extends NonOpaquePanel implements DataProvider, SwitchProvider { - - private final List<DataProvider> myProviders = new ArrayList<DataProvider>(); - - public void addProvider(final DataProvider provider) { - myProviders.add(provider); + private class MyNonOpaquePanel extends NonOpaquePanel implements DataProvider { + public MyNonOpaquePanel() { + super(new BorderLayout()); } @Override @Nullable - public Object getData(@NonNls final String dataId) { - if (PlatformDataKeys.CONTENT_MANAGER.is(dataId)) return ContentManagerImpl.this; - if (PlatformDataKeys.NONEMPTY_CONTENT_MANAGER.is(dataId) && getContentCount() > 1) { + public Object getData(@NonNls String dataId) { + if (PlatformDataKeys.CONTENT_MANAGER.is(dataId) || PlatformDataKeys.NONEMPTY_CONTENT_MANAGER.is(dataId) && getContentCount() > 1) { return ContentManagerImpl.this; } - for (DataProvider each : myProviders) { - final Object data = each.getData(dataId); - if (data != null) return data; + for (DataProvider dataProvider : dataProviders) { + Object data = dataProvider.getData(dataId); + if (data != null) { + return data; + } } if (myUI instanceof DataProvider) { return ((DataProvider)myUI).getData(dataId); } - return null; + DataProvider provider = DataManager.getDataProvider(this); + return provider == null ? null : provider.getData(dataId); } + } + private class MyContentComponent extends NonOpaquePanel implements SwitchProvider { @Override public List<SwitchTarget> getTargets(boolean onlyVisible, boolean originalProvider) { if (myUI instanceof SwitchProvider) { return ((SwitchProvider)myUI).getTargets(onlyVisible, false); } - return new ArrayList<SwitchTarget>(); + return new SmartList<SwitchTarget>(); } @Override public SwitchTarget getCurrentTarget() { - if (myUI instanceof SwitchProvider) { - return ((SwitchProvider)myUI).getCurrentTarget(); - } - - return null; + return myUI instanceof SwitchProvider ? ((SwitchProvider)myUI).getCurrentTarget() : null; } @Override public JComponent getComponent() { - if (myUI instanceof SwitchProvider) { - return myUI.getComponent(); - } - - return this; + return myUI instanceof SwitchProvider ? myUI.getComponent() : this; } @Override @@ -177,35 +174,23 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene } } - private class MyFocusProxy extends Wrapper.FocusHolder implements DataProvider { - private MyFocusProxy() { - setOpaque(false); - setPreferredSize(new Dimension(0, 0)); - } - - @Override - @Nullable - public Object getData(@NonNls final String dataId) { - return myContentComponent.getData(dataId); - } - } - @Override public void addContent(@NotNull Content content, final int order) { - addContent(content, null, order); + doAddContent(content, order); } @Override public void addContent(@NotNull Content content) { - addContent(content, null, -1); + doAddContent(content, -1); } @Override public void addContent(@NotNull final Content content, final Object constraints) { - addContent(content, constraints, -1); + doAddContent(content, -1); } - private void addContent(@NotNull final Content content, final Object constraints, final int index) { + private void doAddContent(@NotNull final Content content, final int index) { + ApplicationManager.getApplication().assertIsDispatchThread(); if (myContents.contains(content)) return; ((ContentImpl)content).setManager(this); @@ -227,24 +212,26 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene @Override public boolean removeContent(@NotNull Content content, final boolean dispose) { - return removeContent(content, true, dispose); + return removeContent(content, true, dispose).isDone(); } @NotNull @Override public ActionCallback removeContent(@NotNull Content content, boolean dispose, final boolean trackFocus, final boolean forcedFocus) { final ActionCallback result = new ActionCallback(); - _removeContent(content, true, dispose).doWhenDone(new Runnable() { + removeContent(content, true, dispose).doWhenDone(new Runnable() { @Override public void run() { if (trackFocus) { Content current = getSelectedContent(); if (current != null) { setSelectedContent(current, true, true, !forcedFocus); - } else { + } + else { result.setDone(); } - } else { + } + else { result.setDone(); } } @@ -253,11 +240,9 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene return result; } - private boolean removeContent(final Content content, boolean trackSelection, boolean dispose) { - return _removeContent(content, trackSelection, dispose).isDone(); - } - - private ActionCallback _removeContent(Content content, boolean trackSelection, boolean dispose) { + @NotNull + private ActionCallback removeContent(@NotNull Content content, boolean trackSelection, boolean dispose) { + ApplicationManager.getApplication().assertIsDispatchThread(); int indexToBeRemoved = getIndexOfContent(content); if (indexToBeRemoved == -1) return new ActionCallback.Rejected(); @@ -604,43 +589,39 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene @Override public void addContentManagerListener(@NotNull ContentManagerListener l) { - myListeners.add(ContentManagerListener.class, l); + myListeners.add(0,l); } @Override public void removeContentManagerListener(@NotNull ContentManagerListener l) { - myListeners.remove(ContentManagerListener.class, l); + myListeners.remove(l); } private void fireContentAdded(Content content, int newIndex, ContentManagerEvent.ContentOperation operation) { ContentManagerEvent event = new ContentManagerEvent(this, content, newIndex, operation); - ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class); - for (ContentManagerListener listener : listeners) { + for (ContentManagerListener listener : myListeners) { listener.contentAdded(event); } } private void fireContentRemoved(Content content, int oldIndex, ContentManagerEvent.ContentOperation operation) { ContentManagerEvent event = new ContentManagerEvent(this, content, oldIndex, operation); - ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class); - for (ContentManagerListener listener : listeners) { + for (ContentManagerListener listener : myListeners) { listener.contentRemoved(event); } } private void fireSelectionChanged(Content content, ContentManagerEvent.ContentOperation operation) { ContentManagerEvent event = new ContentManagerEvent(this, content, myContents.indexOf(content), operation); - ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class); - for (ContentManagerListener listener : listeners) { + for (ContentManagerListener listener : myListeners) { listener.selectionChanged(event); } } private boolean fireContentRemoveQuery(Content content, int oldIndex, ContentManagerEvent.ContentOperation operation) { ContentManagerEvent event = new ContentManagerEvent(this, content, oldIndex, operation); - ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class); - for (ContentManagerListener listener : listeners) { + for (ContentManagerListener listener : myListeners) { listener.contentRemoveQuery(event); if (event.isConsumed()) { return false; @@ -692,13 +673,13 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene @Override public void addDataProvider(@NotNull final DataProvider provider) { - myContentComponent.addProvider(provider); + dataProviders.add(provider); } @Override - public void propertyChange(final PropertyChangeEvent evt) { - if (Content.PROP_COMPONENT.equals(evt.getPropertyName())) { - myContentWithChangedComponent.add((Content)evt.getSource()); + public void propertyChange(@NotNull PropertyChangeEvent event) { + if (Content.PROP_COMPONENT.equals(event.getPropertyName())) { + myContentWithChangedComponent.add((Content)event.getSource()); } } @@ -718,10 +699,10 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene myDisposed = true; myContents.clear(); - mySelection = null; + mySelection.clear(); myContentWithChangedComponent.clear(); myUI = null; - myListeners = null; + myListeners.clear(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index e50403abef45..a967245c9224 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -487,22 +487,24 @@ public class AbstractPopup implements JBPopup { if (dominantArea != null) { final Component focusedComponent = getWndManager().getFocusedComponent(myProject); - Window window = SwingUtilities.windowForComponent(focusedComponent); - JLayeredPane layeredPane; - if (window instanceof JFrame) { - layeredPane = ((JFrame)window).getLayeredPane(); - } - else if (window instanceof JDialog) { - layeredPane = ((JDialog)window).getLayeredPane(); - } - else if (window instanceof JWindow) { - layeredPane = ((JWindow)window).getLayeredPane(); - } - else { - throw new IllegalStateException("cannot find parent window: project=" + myProject + "; window=" + window); - } + if (focusedComponent != null) { + Window window = SwingUtilities.windowForComponent(focusedComponent); + JLayeredPane layeredPane; + if (window instanceof JFrame) { + layeredPane = ((JFrame)window).getLayeredPane(); + } + else if (window instanceof JDialog) { + layeredPane = ((JDialog)window).getLayeredPane(); + } + else if (window instanceof JWindow) { + layeredPane = ((JWindow)window).getLayeredPane(); + } + else { + throw new IllegalStateException("cannot find parent window: project=" + myProject + "; window=" + window); + } - return relativePointWithDominantRectangle(layeredPane, dominantArea); + return relativePointWithDominantRectangle(layeredPane, dominantArea); + } } return JBPopupFactory.getInstance().guessBestPopupLocation(dataContext); @@ -777,7 +779,9 @@ public class AbstractPopup implements JBPopup { Rectangle original = new Rectangle(targetBounds); if (myLocateWithinScreen) { - ScreenUtil.moveRectangleToFitTheScreen(targetBounds); + if (myMovable) { + ScreenUtil.moveRectangleToFitTheScreen(targetBounds); + } } if (myMouseOutCanceller != null) { diff --git a/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java b/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java index 5d657487f6a5..1428ffc9b29d 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java @@ -16,7 +16,7 @@ package com.intellij.ui.popup.list; import com.intellij.icons.AllIcons; -import com.intellij.openapi.ui.popup.ListItemDescriptor; +import com.intellij.openapi.ui.popup.ListItemDescriptorAdapter; import com.intellij.openapi.ui.popup.ListPopupStep; import com.intellij.ui.ColorUtil; import com.intellij.util.ui.UIUtil; @@ -27,18 +27,13 @@ public class PopupListElementRenderer extends GroupedItemsListRenderer { private final ListPopupImpl myPopup; public PopupListElementRenderer(final ListPopupImpl aPopup) { - super(new ListItemDescriptor() { + super(new ListItemDescriptorAdapter() { @Override public String getTextFor(Object value) { return aPopup.getListStep().getTextFor(value); } @Override - public String getTooltipFor(Object value) { - return null; - } - - @Override public Icon getIconFor(Object value) { return aPopup.getListStep().getIconFor(value); } |