diff --git a/openapi/src/com/intellij/openapi/actionSystem/AnAction.java b/openapi/src/com/intellij/openapi/actionSystem/AnAction.java
index 1d3f2518c7e9..6accb07a8735 100644
--- a/openapi/src/com/intellij/openapi/actionSystem/AnAction.java
+++ b/openapi/src/com/intellij/openapi/actionSystem/AnAction.java
@@ -123,6 +123,15 @@ public abstract class AnAction {
}
}
+ public final void unregisterCustomShortcutSet(JComponent component){
+ if (component != null){
+ ArrayList actionList = (ArrayList)component.getClientProperty(ourClientProperty);
+ if (actionList != null){
+ actionList.remove(this);
+ }
+ }
+ }
+
/**
* Copies template presentation and shortcuts set from sourceAction.
*
diff --git a/source/com/intellij/debugger/ui/breakpoints/BreakpointsConfigurationDialogFactory.java b/source/com/intellij/debugger/ui/breakpoints/BreakpointsConfigurationDialogFactory.java
index 95be88fb6018..217529b21821 100644
--- a/source/com/intellij/debugger/ui/breakpoints/BreakpointsConfigurationDialogFactory.java
+++ b/source/com/intellij/debugger/ui/breakpoints/BreakpointsConfigurationDialogFactory.java
@@ -252,6 +252,7 @@ public class BreakpointsConfigurationDialogFactory {
protected void dispose() {
apply();
if (myPanel != null) {
+ myTabbedPane.uninstallKeyboardNavigation();
myLastSelectedTabIndex = myTabbedPane.getSelectedIndex();
myPanel.removeAll();
myPanel = null;
diff --git a/source/com/intellij/execution/impl/RunConfigurable.java b/source/com/intellij/execution/impl/RunConfigurable.java
index 59aa88920881..da778c87b09e 100644
--- a/source/com/intellij/execution/impl/RunConfigurable.java
+++ b/source/com/intellij/execution/impl/RunConfigurable.java
@@ -158,6 +158,9 @@ class RunConfigurable extends BaseConfigurable {
}
public void disposeUIResources() {
+ if (myTabbedPane != null) {
+ myTabbedPane.uninstallKeyboardNavigation();
+ }
for (int i = 0; i < myTabs.length; i++) {
final ConfigurationTab tab = myTabs[i];
tab.disposeUIResources();
diff --git a/source/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java b/source/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
index 43c83a9f8115..62f91f3fe136 100644
--- a/source/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
+++ b/source/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
@@ -710,6 +710,9 @@ public class AllFileTemplatesConfigurable implements Configurable, ApplicationCo
myEditor = null;
myEditorComponent = null;
}
+ if (myTabbedPane != null) {
+ myTabbedPane.uninstallKeyboardNavigation();
+ }
myMainPanel = null;
}
diff --git a/source/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/source/com/intellij/ide/projectView/impl/ProjectViewImpl.java
index e61793067ded..3e54ba53bd30 100644
--- a/source/com/intellij/ide/projectView/impl/ProjectViewImpl.java
+++ b/source/com/intellij/ide/projectView/impl/ProjectViewImpl.java
@@ -431,6 +431,9 @@ public final class ProjectViewImpl extends ProjectView implements JDOMExternaliz
myProject = null;
myStructureViewWrapper.dispose();
myStructureViewWrapper = null;
+ if (myTabbedPane != null) {
+ myTabbedPane.uninstallKeyboardNavigation();
+ }
}
private JComponent getComponent() {
diff --git a/source/com/intellij/ide/util/TreeClassChooserDialog.java b/source/com/intellij/ide/util/TreeClassChooserDialog.java
index a8f7ac1f2dcc..98bf1341cfcd 100644
--- a/source/com/intellij/ide/util/TreeClassChooserDialog.java
+++ b/source/com/intellij/ide/util/TreeClassChooserDialog.java
@@ -343,6 +343,9 @@ public class TreeClassChooserDialog extends DialogWrapper {
myBuilder.dispose();
myBuilder = null;
}
+ if (myTabbedPane != null) {
+ myTabbedPane.uninstallKeyboardNavigation();
+ }
super.dispose();
}
diff --git a/source/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java b/source/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
index 92f644d30e35..7f856f7556d3 100644
--- a/source/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
+++ b/source/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
@@ -44,7 +44,7 @@ final class EditorTabbedContainer extends TabbedPaneWrapper {
}
- protected JComponent createTabbedPaneHolder() {
+ protected TabbedPaneHolder createTabbedPaneHolder() {
return new MyTabbedPaneHolder();
}
diff --git a/source/com/intellij/openapi/options/ex/ExplorerSettingsEditor.java b/source/com/intellij/openapi/options/ex/ExplorerSettingsEditor.java
index f7a5c80821a0..5e31b4037649 100644
--- a/source/com/intellij/openapi/options/ex/ExplorerSettingsEditor.java
+++ b/source/com/intellij/openapi/options/ex/ExplorerSettingsEditor.java
@@ -156,6 +156,9 @@ public class ExplorerSettingsEditor extends DialogWrapper {
}
protected final void dispose() {
+ if (myGroupTabs != null) {
+ myGroupTabs.uninstallKeyboardNavigation();
+ }
rememberLastUsedPage();
for (int i = 0; i < myGroups.length; i++) {
diff --git a/source/com/intellij/openapi/projectRoots/ui/SdkEditor.java b/source/com/intellij/openapi/projectRoots/ui/SdkEditor.java
index 345f5ff46565..a42cbaca6863 100644
--- a/source/com/intellij/openapi/projectRoots/ui/SdkEditor.java
+++ b/source/com/intellij/openapi/projectRoots/ui/SdkEditor.java
@@ -227,6 +227,9 @@ public class SdkEditor implements Configurable{
}
public void disposeUIResources(){
+ if (myTabbedPane != null) {
+ myTabbedPane.uninstallKeyboardNavigation();
+ }
myMainPanel = null;
for (Iterator it = myAdditionalDataConfigurables.keySet().iterator(); it.hasNext();) {
final SdkType sdkType = (SdkType)it.next();
diff --git a/source/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java b/source/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java
index a948d0ab035d..79010337cfaa 100644
--- a/source/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java
+++ b/source/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java
@@ -183,6 +183,7 @@ public class ModuleEditor {
myEditors.clear();
if (myTabbedPane != null) {
+ myTabbedPane.uninstallKeyboardNavigation();
mySelectedTabName = getSelectedTabName();
myTabbedPane = null;
}
diff --git a/source/com/intellij/ui/TabbedPaneWrapper.java b/source/com/intellij/ui/TabbedPaneWrapper.java
index c0fe126bf19f..88915a143eda 100644
--- a/source/com/intellij/ui/TabbedPaneWrapper.java
+++ b/source/com/intellij/ui/TabbedPaneWrapper.java
@@ -18,6 +18,8 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
/**
* @author Anton Katilin
@@ -26,6 +28,7 @@ import java.lang.reflect.Method;
public class TabbedPaneWrapper {
protected final TabbedPane myTabbedPane;
protected final JComponent myTabbedPaneHolder;
+ private final java.util.List myRegistrars = new ArrayList();
public TabbedPaneWrapper(){
this(SwingConstants.TOP);
@@ -65,7 +68,7 @@ public class TabbedPaneWrapper {
myTabbedPane.removeChangeListener(listener);
}
- protected JComponent createTabbedPaneHolder() {
+ protected TabbedPaneHolder createTabbedPaneHolder() {
return new TabbedPaneHolder();
}
@@ -240,9 +243,10 @@ public class TabbedPaneWrapper {
/**
* Installs tab navigation via IdeActions.ACTION_NEXT_TAB and IdeActions.ACTION_PREVIOUS_TAB shortcuts.
+ * In order to avoid memory leaks, the uninstallKeyboardNavigation() method should be called when the TabbedPane is not needed anymore
*/
public final void installKeyboardNavigation(){
- final AnAction nextTabAction=new AnAction() {
+ final AnAction nextTabAction = new AnAction() {
{
setEnabledInModalContext(true);
}
@@ -254,22 +258,26 @@ public class TabbedPaneWrapper {
setSelectedIndex(index);
}
};
+ final JComponent component = getComponent();
nextTabAction.registerCustomShortcutSet(
ActionManager.getInstance().getAction(IdeActions.ACTION_NEXT_TAB).getShortcutSet(),
- getComponent()
+ component
);
+ myRegistrars.add(new UnregisterCommand(nextTabAction, component));
// make action work in modal dialog box
SwingUtilities.invokeLater(new Runnable() {
public void run() {
- JRootPane rootPane = SwingUtilities.getRootPane(getComponent());
+ JRootPane rootPane = SwingUtilities.getRootPane(component);
if (rootPane != null) {
nextTabAction.registerCustomShortcutSet(
- ActionManager.getInstance().getAction(IdeActions.ACTION_NEXT_TAB).getShortcutSet(),
- rootPane);
+ ActionManager.getInstance().getAction(IdeActions.ACTION_NEXT_TAB).getShortcutSet(), rootPane
+ );
+ myRegistrars.add(new UnregisterCommand(nextTabAction, rootPane));
}
}
});
- final AnAction previousTabAction=new AnAction() {
+
+ final AnAction previousTabAction = new AnAction() {
{
setEnabledInModalContext(true);
}
@@ -283,22 +291,30 @@ public class TabbedPaneWrapper {
};
previousTabAction.registerCustomShortcutSet(
ActionManager.getInstance().getAction(IdeActions.ACTION_PREVIOUS_TAB).getShortcutSet(),
- getComponent()
+ component
);
+ myRegistrars.add(new UnregisterCommand(previousTabAction, component));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
- JRootPane rootPane = SwingUtilities.getRootPane(getComponent());
+ JRootPane rootPane = SwingUtilities.getRootPane(component);
if (rootPane != null) {
previousTabAction.registerCustomShortcutSet(
- ActionManager.getInstance().getAction(IdeActions.ACTION_PREVIOUS_TAB).getShortcutSet(),
- rootPane
+ ActionManager.getInstance().getAction(IdeActions.ACTION_PREVIOUS_TAB).getShortcutSet(), rootPane
);
+ myRegistrars.add(new UnregisterCommand(previousTabAction, rootPane));
}
}
});
}
+ public final void uninstallKeyboardNavigation(){
+ for (Iterator it = myRegistrars.iterator(); it.hasNext();) {
+ it.next().unregister();
+ }
+ myRegistrars.clear();
+ }
+
public final String getTitleAt(final int i) {
return myTabbedPane.getTitleAt(i);
}
@@ -555,4 +571,18 @@ public class TabbedPaneWrapper {
return requestDefaultFocus();
}
}
+
+ private static class UnregisterCommand {
+ private final AnAction myAction;
+ private final JComponent myComponent;
+
+ public UnregisterCommand(AnAction action, JComponent component) {
+ myAction = action;
+ myComponent = component;
+ }
+
+ public void unregister() {
+ myAction.unregisterCustomShortcutSet(myComponent);
+ }
+ }
}
diff --git a/source/com/intellij/ui/content/TabbedPaneContentUI.java b/source/com/intellij/ui/content/TabbedPaneContentUI.java
index 03c6b7ccfc97..162233ac33ca 100644
--- a/source/com/intellij/ui/content/TabbedPaneContentUI.java
+++ b/source/com/intellij/ui/content/TabbedPaneContentUI.java
@@ -236,7 +236,7 @@ public class TabbedPaneContentUI implements ContentUI, PropertyChangeListener {
return new MyTabbedPane(tabPlacement);
}
- protected JComponent createTabbedPaneHolder() {
+ protected TabbedPaneHolder createTabbedPaneHolder() {
return new MyTabbedPaneHolder();
}