mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
avoid NPE if project frame is not yet set
GitOrigin-RevId: db67484a2e317d111c9d5c5c0730b19154c4efdb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b8987fdeaa
commit
e88ef6402a
@@ -96,4 +96,7 @@ public abstract class WindowManager {
|
||||
public abstract boolean isFullScreenSupportedInCurrentOS();
|
||||
|
||||
public abstract void requestUserAttention(@NotNull IdeFrame frame, boolean critical);
|
||||
|
||||
public void updateDefaultFrameInfoOnProjectClose(@NotNull Project project) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.project.ProjectManagerListener
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
import com.intellij.openapi.project.impl.*
|
||||
import com.intellij.openapi.project.impl.ProjectUiFrameAllocator
|
||||
import com.intellij.openapi.project.impl.ProjectUiFrameManager
|
||||
import com.intellij.openapi.project.impl.createNewProjectFrame
|
||||
import com.intellij.openapi.startup.StartupManager
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
@@ -275,7 +277,9 @@ open class RecentProjectsManagerBase : RecentProjectsManager(), PersistentStateC
|
||||
val appInfo = ApplicationInfoEx.getInstanceEx()
|
||||
info.displayName = getProjectDisplayName(project)
|
||||
info.projectWorkspaceId = project.stateStore.projectWorkspaceId
|
||||
info.frame = ProjectFrameBounds.getInstance(project).frameInfoHelper.info
|
||||
ProjectFrameBounds.getInstance(project).frameInfoHelper.info?.let {
|
||||
info.frame = it
|
||||
}
|
||||
info.build = appInfo!!.build.asString()
|
||||
info.productionCode = appInfo.build.productCode
|
||||
info.eap = appInfo.isEAP
|
||||
@@ -538,11 +542,15 @@ open class RecentProjectsManagerBase : RecentProjectsManager(), PersistentStateC
|
||||
LOG.warn("Cannot find frameHelper for ${project.name} to update frame info")
|
||||
return
|
||||
}
|
||||
val frame = frameHelper.frame
|
||||
if (frame == null) {
|
||||
LOG.warn("frameHelper.frame is null, cannot ${project.name} to update frame info")
|
||||
return
|
||||
}
|
||||
|
||||
val workspaceId = project.stateStore.projectWorkspaceId
|
||||
|
||||
// ensure that last closed project frame bounds will be used as newly created project frame bounds (if will be no another focused opened project)
|
||||
val frameInfo = ProjectFrameBounds.getInstance(project).getActualFrameInfoInDeviceSpace(frameHelper, windowManager)
|
||||
val frameInfo = ProjectFrameBounds.getInstance(project).getActualFrameInfoInDeviceSpace(frameHelper, frame, windowManager)
|
||||
val path = getProjectPath(project)
|
||||
synchronized(stateLock) {
|
||||
val info = state.additionalInfo.get(path)
|
||||
@@ -554,13 +562,13 @@ open class RecentProjectsManagerBase : RecentProjectsManager(), PersistentStateC
|
||||
info.frame = frameInfo
|
||||
}
|
||||
info.projectWorkspaceId = workspaceId
|
||||
info.frameTitle = frameHelper.frame?.title
|
||||
info.frameTitle = frame.title
|
||||
}
|
||||
}
|
||||
|
||||
LOG.runAndLogException {
|
||||
if (writLastProjectInfo) {
|
||||
writeInfoFile(frameInfo, frameHelper.frame ?: return@runAndLogException)
|
||||
writeInfoFile(frameInfo, frame)
|
||||
}
|
||||
|
||||
if (workspaceId != null && Registry.`is`("ide.project.loading.show.last.state")) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
@@ -11,7 +11,7 @@ import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.wm.impl.ProjectFrameBounds;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
|
||||
import com.intellij.projectImport.ProjectAttachProcessor;
|
||||
import com.intellij.ui.IdeUICustomization;
|
||||
@@ -28,7 +28,7 @@ public final class CloseProjectAction extends AnAction implements DumbAware {
|
||||
assert project != null;
|
||||
|
||||
// ensure that last closed project frame bounds will be used as newly created project frame bounds (if will be no another focused opened project)
|
||||
ProjectFrameBounds.getInstance(project).updateDefaultFrameInfoOnProjectClose();
|
||||
WindowManager.getInstance().updateDefaultFrameInfoOnProjectClose(project);
|
||||
|
||||
ProjectManagerEx.getInstanceEx().closeAndDispose(project);
|
||||
// RecentProjectsManager cannot distinguish close as part of exit (no need to remove project),
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.awt.Point
|
||||
import java.awt.Rectangle
|
||||
import java.awt.peer.ComponentPeer
|
||||
import java.awt.peer.FramePeer
|
||||
import javax.swing.JFrame
|
||||
|
||||
internal class FrameInfoHelper {
|
||||
companion object {
|
||||
@@ -43,26 +44,28 @@ internal class FrameInfoHelper {
|
||||
this.info = info
|
||||
}
|
||||
|
||||
fun updateFrameInfo(frame: ProjectFrameHelper) {
|
||||
info = updateFrameInfo(frame, null, info)
|
||||
fun updateFrameInfo(frameHelper: ProjectFrameHelper, frame: JFrame) {
|
||||
info = updateFrameInfo(frameHelper, frame, null, info)
|
||||
}
|
||||
|
||||
fun getModificationCount(): Long {
|
||||
return info?.modificationCount ?: 0
|
||||
}
|
||||
|
||||
fun updateAndGetModificationCount(project: Project, lastNormalFrameBounds: Rectangle?, windowManager: WindowManagerImpl): Long {
|
||||
val frame = windowManager.getFrameHelper(project) ?: return getModificationCount()
|
||||
return updateAndGetModificationCount(frame, lastNormalFrameBounds, windowManager)
|
||||
fun update(project: Project, lastNormalFrameBounds: Rectangle?, windowManager: WindowManagerImpl) {
|
||||
val frameHelper = windowManager.getFrameHelper(project) ?: return
|
||||
updateAndGetInfo(frameHelper, frameHelper.frame ?: return, lastNormalFrameBounds, windowManager)
|
||||
}
|
||||
|
||||
fun updateAndGetModificationCount(frame: ProjectFrameHelper, lastNormalFrameBounds: Rectangle?, windowManager: WindowManagerImpl): Long {
|
||||
val newInfo = updateFrameInfo(frame, lastNormalFrameBounds, info)
|
||||
updateDefaultFrameInfoInDeviceSpace(windowManager, newInfo)
|
||||
fun updateAndGetInfo(frameHelper: ProjectFrameHelper,
|
||||
frame: JFrame,
|
||||
lastNormalFrameBounds: Rectangle?,
|
||||
windowManager: WindowManagerImpl): FrameInfo {
|
||||
val newInfo = updateFrameInfo(frameHelper, frame, lastNormalFrameBounds, info)
|
||||
windowManager.defaultFrameInfoHelper.copyFrom(newInfo)
|
||||
info = newInfo
|
||||
|
||||
isDirty = false
|
||||
return getModificationCount()
|
||||
return newInfo
|
||||
}
|
||||
|
||||
fun copyFrom(newInfo: FrameInfo) {
|
||||
@@ -74,8 +77,7 @@ internal class FrameInfoHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateFrameInfo(frameHelper: ProjectFrameHelper, lastNormalFrameBounds: Rectangle?, oldFrameInfo: FrameInfo?): FrameInfo {
|
||||
val frame = frameHelper.frame!!
|
||||
internal fun updateFrameInfo(frameHelper: ProjectFrameHelper, frame: JFrame, lastNormalFrameBounds: Rectangle?, oldFrameInfo: FrameInfo?): FrameInfo {
|
||||
var extendedState = frame.extendedState
|
||||
if (SystemInfoRt.isMac) {
|
||||
// java 11
|
||||
@@ -112,9 +114,4 @@ private fun updateFrameInfo(frameHelper: ProjectFrameHelper, lastNormalFrameBoun
|
||||
frameInfo.fullScreen = isInFullScreen
|
||||
}
|
||||
return frameInfo
|
||||
}
|
||||
|
||||
internal fun updateDefaultFrameInfoInDeviceSpace(windowManager: WindowManagerImpl, newInfo: FrameInfo) {
|
||||
// see comment in the myFrameStateListener about chicken and egg problem
|
||||
windowManager.defaultFrameInfoHelper.copyFrom(newInfo)
|
||||
}
|
||||
@@ -5,14 +5,14 @@ import com.intellij.openapi.components.BaseState
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import com.intellij.util.xmlb.annotations.Property
|
||||
import com.intellij.util.xmlb.annotations.Tag
|
||||
import java.awt.Frame
|
||||
import java.awt.Rectangle
|
||||
import javax.swing.JFrame
|
||||
|
||||
@Service
|
||||
class ProjectFrameBounds(private val project: Project) {
|
||||
internal class ProjectFrameBounds {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(project: Project) = project.service<ProjectFrameBounds>()
|
||||
@@ -21,29 +21,8 @@ class ProjectFrameBounds(private val project: Project) {
|
||||
internal val frameInfoHelper = FrameInfoHelper()
|
||||
private var pendingBounds: Rectangle? = null
|
||||
|
||||
/**
|
||||
* Maybe outdated. You must always check isDirty if you need actual info.
|
||||
*/
|
||||
internal fun getFrameInfoInDeviceSpace() = frameInfoHelper.info
|
||||
|
||||
internal fun getActualFrameInfoInDeviceSpace(frame: ProjectFrameHelper, windowManager: WindowManagerImpl): FrameInfo {
|
||||
val result = frameInfoHelper.info
|
||||
if (frameInfoHelper.isDirty || result == null) {
|
||||
frameInfoHelper.updateAndGetModificationCount(frame, pendingBounds, windowManager)
|
||||
return frameInfoHelper.info!!
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun updateDefaultFrameInfoOnProjectClose() {
|
||||
val windowManager = WindowManager.getInstance() as WindowManagerImpl
|
||||
if (frameInfoHelper.isDirty || frameInfoHelper.info == null) {
|
||||
// not really required, because will be applied during project save on close
|
||||
frameInfoHelper.updateAndGetModificationCount(project, pendingBounds, windowManager)
|
||||
}
|
||||
else {
|
||||
updateDefaultFrameInfoInDeviceSpace(windowManager, frameInfoHelper.info ?: return)
|
||||
}
|
||||
internal fun getActualFrameInfoInDeviceSpace(frameHelper: ProjectFrameHelper, frame: JFrame, windowManager: WindowManagerImpl): FrameInfo {
|
||||
return frameInfoHelper.updateAndGetInfo(frameHelper, frame, pendingBounds, windowManager)
|
||||
}
|
||||
|
||||
fun markDirty(bounds: Rectangle?) {
|
||||
|
||||
@@ -411,7 +411,7 @@ open class ToolWindowManagerImpl(val project: Project) : ToolWindowManagerEx(),
|
||||
|
||||
if (toolWindowPane == null) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
LOG.warn("ProjectFrameAllocator is not used - use ProjectManager.openProject to open project in a correct way")
|
||||
LOG.error("ProjectFrameAllocator is not used - use ProjectManager.openProject to open project in a correct way")
|
||||
}
|
||||
|
||||
val toolWindowsPane = init((WindowManager.getInstance() as WindowManagerImpl).allocateFrame(project))
|
||||
|
||||
@@ -93,7 +93,7 @@ class WindowManagerImpl : WindowManagerEx(), PersistentStateComponentWithModific
|
||||
// Cannot mark as dirty and compute later, because to convert user space info to device space,
|
||||
// we need graphicsConfiguration, but we can get graphicsConfiguration only from frame,
|
||||
// but later, when getStateModificationCount or getState is called, may be no frame at all.
|
||||
defaultFrameInfoHelper.updateFrameInfo(frameHelper)
|
||||
defaultFrameInfoHelper.updateFrameInfo(frameHelper, frame)
|
||||
}
|
||||
else if (!project.isDisposed) {
|
||||
ProjectFrameBounds.getInstance(project).markDirty(if (isMaximized(extendedState)) null else bounds)
|
||||
@@ -302,6 +302,9 @@ class WindowManagerImpl : WindowManagerEx(), PersistentStateComponentWithModific
|
||||
frame.addComponentListener(frameStateListener)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is not used in a normal conditions. Only in case of violation and early access to ToolWindowManager.
|
||||
*/
|
||||
fun allocateFrame(project: Project,
|
||||
projectFrameHelperFactory: Supplier<out ProjectFrameHelper> = Supplier {
|
||||
ProjectFrameHelper(createNewProjectFrame(forceDisableAutoRequestFocus = false, frameInfo = null), null)
|
||||
@@ -323,15 +326,13 @@ class WindowManagerImpl : WindowManagerEx(), PersistentStateComponentWithModific
|
||||
return frame
|
||||
}
|
||||
|
||||
private fun allocateNewFrame(project: Project, frame: ProjectFrameHelper) {
|
||||
frame.init()
|
||||
private fun allocateNewFrame(project: Project, frameHelper: ProjectFrameHelper) {
|
||||
frameHelper.init()
|
||||
|
||||
var frameInfo = ProjectFrameBounds.getInstance(project).getFrameInfoInDeviceSpace()
|
||||
if (frameInfo?.bounds == null) {
|
||||
val lastFocusedProject = IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project
|
||||
if (lastFocusedProject != null) {
|
||||
frameInfo = ProjectFrameBounds.getInstance(lastFocusedProject).getActualFrameInfoInDeviceSpace(frame, this)
|
||||
}
|
||||
var frameInfo: FrameInfo? = null
|
||||
val lastFocusedProjectFrame = IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project?.let { getFrameHelper(it) }
|
||||
if (lastFocusedProjectFrame != null) {
|
||||
frameInfo = getFrameInfoByFrameHelper(lastFocusedProjectFrame)
|
||||
if (frameInfo?.bounds == null) {
|
||||
frameInfo = defaultFrameInfoHelper.info
|
||||
}
|
||||
@@ -344,19 +345,19 @@ class WindowManagerImpl : WindowManagerEx(), PersistentStateComponentWithModific
|
||||
}
|
||||
val bounds = frameInfo.bounds
|
||||
if (bounds != null) {
|
||||
frame.frame!!.bounds = FrameBoundsConverter.convertFromDeviceSpaceAndFitToScreen(bounds)
|
||||
frameHelper.frame!!.bounds = FrameBoundsConverter.convertFromDeviceSpaceAndFitToScreen(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
frame.setProject(project)
|
||||
projectToFrame.put(project, frame)
|
||||
val uiFrame = frame.frame!!
|
||||
frameHelper.setProject(project)
|
||||
projectToFrame.put(project, frameHelper)
|
||||
val uiFrame = frameHelper.frame!!
|
||||
if (frameInfo != null) {
|
||||
uiFrame.extendedState = frameInfo.extendedState
|
||||
}
|
||||
uiFrame.isVisible = true
|
||||
if (isFullScreenSupportedInCurrentOs() && frameInfo != null && frameInfo.fullScreen) {
|
||||
frame.toggleFullScreen(true)
|
||||
frameHelper.toggleFullScreen(true)
|
||||
}
|
||||
|
||||
uiFrame.addComponentListener(frameStateListener)
|
||||
@@ -476,6 +477,12 @@ class WindowManagerImpl : WindowManagerEx(), PersistentStateComponentWithModific
|
||||
}
|
||||
|
||||
override fun isFullScreenSupportedInCurrentOS() = isFullScreenSupportedInCurrentOs()
|
||||
|
||||
override fun updateDefaultFrameInfoOnProjectClose(project: Project) {
|
||||
val frameHelper = getFrameHelper(project) ?: return
|
||||
val frameInfo = getFrameInfoByFrameHelper(frameHelper) ?: return
|
||||
defaultFrameInfoHelper.copyFrom(frameInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun calcAlphaModelSupported(): Boolean {
|
||||
@@ -544,4 +551,8 @@ private fun getIdeFrame(component: Component): IdeFrame? {
|
||||
is IdeFrame -> component
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFrameInfoByFrameHelper(frameHelper: ProjectFrameHelper): FrameInfo? {
|
||||
return updateFrameInfo(frameHelper, frameHelper.frame ?: return null, null, null)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user