mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fixed memory leak: actions of TabbedPaneWrapper no more hang on IdeaRootFrame.clientProperties
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user