Still leaks - can't find Project with focus when 4th project closed.

This commit is contained in:
JohnHake 2020-03-01 17:37:12 -08:00
parent 1910030993
commit 373206dbd8
3 changed files with 78 additions and 26 deletions

View File

@ -8,26 +8,36 @@ package org.intellij.sdk.maxOpenPrj;
*/ */
public class ProjectCountingService { public class ProjectCountingService {
// Sets the maximum allowed number of opened projects. // Sets the maximum allowed number of opened projects.
private final int MAX_OPEN_PRJ_LIMIT = 3; private final static int MAX_OPEN_PRJ_LIMIT = 3;
// The count of open projects must always be >= 0 // The count of open projects must always be >= 0
private int openProjectCount = 0; private int myOpenProjectCount = 0;
public void incrProjectCount() { public void incrProjectCount() {
if (openProjectCount < 0) { myOpenProjectCount = verifyProjectCount(myOpenProjectCount);
openProjectCount = 0; myOpenProjectCount++;
}
openProjectCount++;
} }
public void decrProjectCount() { public void decrProjectCount() {
openProjectCount--; myOpenProjectCount--;
if (openProjectCount < 0) { myOpenProjectCount = verifyProjectCount(myOpenProjectCount);
openProjectCount = 0;
}
} }
public boolean projectLimitExceeded() { public boolean projectLimitExceeded() {
return openProjectCount > MAX_OPEN_PRJ_LIMIT; return myOpenProjectCount > MAX_OPEN_PRJ_LIMIT;
}
public int getProjectCount() {
return myOpenProjectCount;
}
/**
* Anti-bugging to ensure the count of open projects never goes below zero.
* @param openProjectCount The count of currently open projects
* @return 0 if openProjectCount<0
* openProjectCount otherwise
*/
private int verifyProjectCount(int openProjectCount) {
return openProjectCount<0 ? 0 : openProjectCount;
} }
} }

View File

@ -6,6 +6,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManagerListener; import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.ui.Messages;
import org.intellij.sdk.utils.SdkBalloonHelper; import org.intellij.sdk.utils.SdkBalloonHelper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -15,7 +16,7 @@ import org.jetbrains.annotations.NotNull;
* Depends on org.intellij.sdk.utils.SdkBalloonHelper * Depends on org.intellij.sdk.utils.SdkBalloonHelper
*/ */
public class ProjectOpenCloseListener implements ProjectManagerListener { public class ProjectOpenCloseListener implements ProjectManagerListener {
private static final String MAX_OPEN_PROJ_DISCLAIM = "This is an IntelliJ Platform SDK demo.<br><br>"; private static final String MAX_OPEN_PROJ_DISCLAIM = "\nThis is an IntelliJ Platform SDK demo message.\n\n";
/** /**
* Invoked on project open. * Invoked on project open.

View File

@ -7,12 +7,17 @@ import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.openapi.wm.impl.WindowManagerImpl;
import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import javax.swing.*; import javax.swing.*;
import java.awt.*;
/** /**
* This is just a utility class to help communicate the state of this plugin using Popups * This is just a utility class to help communicate the state of this plugin using Popups
@ -27,23 +32,17 @@ public class SdkBalloonHelper {
/** /**
* This method constructs a Balloon-type popup and displays it in the middle of a Project window. * This method constructs a Balloon-type popup and displays it in the middle of a Project window.
* Adds the Balloon to the Project's Disposer
* *
* @param project The Project to host the Balloon. * @param project The Project to host the Balloon.
* @param title A short description of what the Balloon conveys * @param title A short description of what the Balloon conveys
* @param message Detailed information * @param message Detailed information to display in HTML format
*/ */
public void showBalloon(@Nullable Project project, @NotNull String title, @NotNull String message) { public void showBalloon(@Nullable Project project, @NotNull String title, @NotNull String message) {
// Ensure the project is open. If not, use the next youngest one to show the balloon
Project displayProject = findValidProject(project);
if (displayProject == null) return;
// Verify the place to put the balloon // Create a component to hold the message in HTML format
JRootPane pane = getProjectRootPane(displayProject);
if (pane == null) return;
// Construct the balloon
JLabel component = new JLabel("<html>" + message + "</html>"); JLabel component = new JLabel("<html>" + message + "</html>");
// Construct the balloon using the component
final Balloon balloon = JBPopupFactory.getInstance().createBalloonBuilder(component) final Balloon balloon = JBPopupFactory.getInstance().createBalloonBuilder(component)
.setShadow(true) .setShadow(true)
.setHideOnClickOutside(true) .setHideOnClickOutside(true)
@ -53,8 +52,18 @@ public class SdkBalloonHelper {
.setFadeoutTime(6000) .setFadeoutTime(6000)
.createBalloon(); .createBalloon();
// Register it for disposal with the project that will display it // Ensure the project is open. If not, find a visible Project to display the balloon.
Disposer.register(displayProject, balloon); Project displayProject = findValidProject(project);
if (displayProject == null) return;
// Get the UI element to display the balloon
JRootPane pane = getProjectRootPane(displayProject);
if (pane == null) return;
// This is a special case for the message when closing a project.
// The closed project is no longer visible, so the next...
// Consequently register it for disposal with the project that will display it
// Disposer.register(displayProject, balloon);
// Show the balloon in the middle of the project's window - it will disappear per the animation // Show the balloon in the middle of the project's window - it will disappear per the animation
balloon.showInCenterOf(pane); balloon.showInCenterOf(pane);
@ -73,11 +82,43 @@ public class SdkBalloonHelper {
@Nullable @Nullable
private Project findValidProject(@Nullable Project dodgyProject) { private Project findValidProject(@Nullable Project dodgyProject) {
Project validProject = dodgyProject; Project validProject = dodgyProject;
if ((validProject == null) || !validProject.isOpen()) { if ((dodgyProject == null) || !dodgyProject.isOpen()) {
// Find the next most-recently opened Project that is still open. // Find the next most-recently opened Project that is still open.
IdeFocusManager focusManager = IdeFocusManager.getGlobalInstance();
IdeFrame ideFrameFromFocusMgr = focusManager.getLastFocusedFrame();
Project focusMgrProject = ideFrameFromFocusMgr.getProject();
System.out.println("\n\nFocus Mgr last focused frame -> project: " + focusMgrProject.toString() + "\n");
final WindowManager windowManager = WindowManagerImpl.getInstance();
IdeFrame[] allIdeFrames = windowManager.getAllProjectFrames();
for (int i=0; i<allIdeFrames.length; i++) {
System.out.println(String.format("Win Mgr IdeFrames[%d] -> project: %s", i, allIdeFrames[i].getProject().toString()));
}
String outcome = String.format("\n\nUsing Win Mgr getIdeFrame(null): ");
String focusProject;
IdeFrame focusFrame = windowManager.getIdeFrame(null);
if (focusFrame != null) {
focusProject = String.format("%s", focusFrame.getProject().toString());
} else {
focusProject = String.format("No focused project found");
}
System.out.println(outcome + focusProject);
outcome = String.format("\n\nUsing Win Mgr findFrameFor(null): ");
focusFrame = ((WindowManagerImpl) windowManager).findFrameFor(null);
if (focusFrame != null) {
focusProject = String.format("%s", focusFrame.getProject().toString());
} else {
focusProject = String.format("No focused project found");
}
System.out.println(outcome + focusProject);
ProjectManager projectManager = ProjectManager.getInstance(); ProjectManager projectManager = ProjectManager.getInstance();
Project[] allProjects = projectManager.getOpenProjects(); Project[] allProjects = projectManager.getOpenProjects();
validProject = allProjects.length > 0 ? allProjects[allProjects.length - 1] : null; validProject = allProjects.length > 0 ? allProjects[allProjects.length - 1] : null;
System.out.println("\n\nProjMgr allProjects[last]: " + validProject.toString());
} }
return validProject; return validProject;
} }