fixed memory leak: actions of TabbedPaneWrapper no more hang on IdeaRootFrame.clientProperties

This commit is contained in:
Eugene Zhuravlev
2005-01-14 21:33:14 +03:00
parent f42dc4f5c3
commit eaf70ce2f2
12 changed files with 72 additions and 13 deletions
@@ -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 <code>sourceAction</code>.
*
@@ -252,6 +252,7 @@ public class BreakpointsConfigurationDialogFactory {
protected void dispose() {
apply();
if (myPanel != null) {
myTabbedPane.uninstallKeyboardNavigation();
myLastSelectedTabIndex = myTabbedPane.getSelectedIndex();
myPanel.removeAll();
myPanel = null;
@@ -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();
@@ -710,6 +710,9 @@ public class AllFileTemplatesConfigurable implements Configurable, ApplicationCo
myEditor = null;
myEditorComponent = null;
}
if (myTabbedPane != null) {
myTabbedPane.uninstallKeyboardNavigation();
}
myMainPanel = null;
}
@@ -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() {
@@ -343,6 +343,9 @@ public class TreeClassChooserDialog extends DialogWrapper {
myBuilder.dispose();
myBuilder = null;
}
if (myTabbedPane != null) {
myTabbedPane.uninstallKeyboardNavigation();
}
super.dispose();
}
@@ -44,7 +44,7 @@ final class EditorTabbedContainer extends TabbedPaneWrapper {
}
protected JComponent createTabbedPaneHolder() {
protected TabbedPaneHolder createTabbedPaneHolder() {
return new MyTabbedPaneHolder();
}
@@ -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++) {
@@ -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();
@@ -183,6 +183,7 @@ public class ModuleEditor {
myEditors.clear();
if (myTabbedPane != null) {
myTabbedPane.uninstallKeyboardNavigation();
mySelectedTabName = getSelectedTabName();
myTabbedPane = null;
}
+41 -11
View File
@@ -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<UnregisterCommand> myRegistrars = new ArrayList<UnregisterCommand>();
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<UnregisterCommand> 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);
}
}
}
@@ -236,7 +236,7 @@ public class TabbedPaneContentUI implements ContentUI, PropertyChangeListener {
return new MyTabbedPane(tabPlacement);
}
protected JComponent createTabbedPaneHolder() {
protected TabbedPaneHolder createTabbedPaneHolder() {
return new MyTabbedPaneHolder();
}