IDEA-97696 Custom tool windows layout is lost on exiting IDE with closed projects

(cherry picked from commit 984cdfb)
This commit is contained in:
Vassiliy
2013-11-26 09:48:01 +04:00
committed by Vassiliy Kudryashov
parent 20b26a146e
commit ef475ea3b5
3 changed files with 75 additions and 53 deletions
@@ -163,7 +163,7 @@ public class FileBasedStorage extends XmlElementStorage {
@Override
protected void doSave() throws StateStorageException {
if (myBlockSavingTheContent) {
if (myBlockSavingTheContentCausedByRead || myBlockSavingTheContentCausedByWrite) {
return;
}
if (ApplicationManager.getApplication().isUnitTestMode() && myFile != null && StringUtil.startsWithChar(myFile.getPath(), '$')) {
@@ -248,7 +248,8 @@ public class FileBasedStorage extends XmlElementStorage {
@Override
@Nullable
protected Document loadDocument() throws StateStorageException {
myBlockSavingTheContent = false;
myBlockSavingTheContentCausedByRead = false;
myBlockSavingTheContentCausedByWrite = false;
try {
VirtualFile file = getVirtualFile();
if (file == null || file.isDirectory() || !file.isValid()) {
@@ -271,7 +272,7 @@ public class FileBasedStorage extends XmlElementStorage {
@Nullable
private Document processReadException(@Nullable final Exception e) {
boolean contentTruncated = e == null;
myBlockSavingTheContent = isProjectOrModuleFile() && !contentTruncated;
myBlockSavingTheContentCausedByRead = isProjectOrModuleFile() && !contentTruncated;
if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
if (e != null) {
LOG.info(e);
@@ -51,7 +51,8 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
protected final StreamProvider myStreamProvider;
protected final String myFileSpec;
private final ComponentRoamingManager myComponentRoamingManager;
protected boolean myBlockSavingTheContent = false;
protected boolean myBlockSavingTheContentCausedByRead = false;
protected boolean myBlockSavingTheContentCausedByWrite = false;
protected int myUpToDateHash = -1;
protected int myProviderUpToDateHash = -1;
private boolean mySavingDisabled = false;
@@ -270,13 +271,15 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
try {
setState(componentName, DefaultStateSerializer.serializeState(state, storageSpec));
myBlockSavingTheContentCausedByWrite = false;
}
catch (WriteExternalException e) {
myBlockSavingTheContentCausedByWrite = true;
LOG.debug(e);
}
}
private synchronized void setState(final String componentName, final Element element) {
private synchronized void setState(@NotNull String componentName, @NotNull Element element) {
if (element.getAttributes().isEmpty() && element.getChildren().isEmpty()) {
return;
}
@@ -325,7 +328,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
private boolean _needsSave(int hash) {
if (myBlockSavingTheContent) {
if (myBlockSavingTheContentCausedByRead || myBlockSavingTheContentCausedByWrite) {
return false;
}
@@ -374,7 +377,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
public final void save() throws StateStorageException {
assert mySession == this;
if (myBlockSavingTheContent) {
if (myBlockSavingTheContentCausedByRead || myBlockSavingTheContentCausedByWrite) {
return;
}
@@ -27,13 +27,12 @@ import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.NamedJDOMExternalizable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.StatusBar;
@@ -67,7 +66,11 @@ import java.util.Set;
* @author Anton Katilin
* @author Vladimir Kondratyev
*/
public final class WindowManagerImpl extends WindowManagerEx implements ApplicationComponent, NamedJDOMExternalizable {
@State(
name = "WindowManager",
roamingType = RoamingType.GLOBAL,
storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/window.manager.xml")})
public final class WindowManagerImpl extends WindowManagerEx implements ApplicationComponent, PersistentStateComponent<Element> {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowManagerImpl");
@NonNls public static final String FULL_SCREEN = "ide.frame.full.screen";
@@ -689,12 +692,9 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat
return myCommandProcessor;
}
public final String getExternalFileName() {
return "window.manager";
}
public final void readExternal(final Element element) {
final Element frameElement = element.getChild(FRAME_ELEMENT);
@Override
public void loadState(Element state) {
final Element frameElement = state.getChild(FRAME_ELEMENT);
if (frameElement != null) {
myFrameBounds = loadFrameBounds(frameElement);
try {
@@ -708,7 +708,7 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat
}
}
final Element desktopElement = element.getChild(DesktopLayout.TAG);
final Element desktopElement = state.getChild(DesktopLayout.TAG);
if (desktopElement != null) {
myLayout.readExternal(desktopElement);
}
@@ -743,43 +743,61 @@ public final class WindowManagerImpl extends WindowManagerEx implements Applicat
return bounds;
}
public final void writeExternal(final Element element) {
// Save frame bounds
final Element frameElement = new Element(FRAME_ELEMENT);
element.addContent(frameElement);
final Project[] projects = ProjectManager.getInstance().getOpenProjects();
final Project project = projects.length > 0 ? projects[0] : null;
final IdeFrameImpl frame = getFrame(project);
if (frame != null) {
int extendedState = frame.getExtendedState();
if (SystemInfo.isMacOSLion) {
@SuppressWarnings("deprecation") ComponentPeer peer = frame.getPeer();
if (peer instanceof FramePeer) {
// frame.state is not updated by jdk so get it directly from peer
extendedState = ((FramePeer)peer).getState();
}
}
boolean isMaximized = extendedState == Frame.MAXIMIZED_BOTH ||
isFullScreenSupportedInCurrentOS() && frame.isInFullScreen();
boolean usePreviousBounds = isMaximized &&
myFrameBounds != null &&
frame.getBounds().contains(new Point((int)myFrameBounds.getCenterX(), (int)myFrameBounds.getCenterY()));
Rectangle rectangle = usePreviousBounds ? myFrameBounds : frame.getBounds();
frameElement.setAttribute(X_ATTR, Integer.toString(rectangle.x));
frameElement.setAttribute(Y_ATTR, Integer.toString(rectangle.y));
frameElement.setAttribute(WIDTH_ATTR, Integer.toString(rectangle.width));
frameElement.setAttribute(HEIGHT_ATTR, Integer.toString(rectangle.height));
if (!(frame.isInFullScreen() && SystemInfo.isAppleJvm)) {
frameElement.setAttribute(EXTENDED_STATE_ATTR, Integer.toString(extendedState));
}
// Save default layout
final Element layoutElement = new Element(DesktopLayout.TAG);
element.addContent(layoutElement);
myLayout.writeExternal(layoutElement);
@Nullable
@Override
public Element getState() {
Element frameState = getFrameState();
if (frameState == null) {
return null;
}
Element state = new Element("state");
state.addContent(frameState);
// Save default layout
Element layoutElement = new Element(DesktopLayout.TAG);
state.addContent(layoutElement);
myLayout.writeExternal(layoutElement);
return state;
}
private Element getFrameState() {
// Save frame bounds
final Project[] projects = ProjectManager.getInstance().getOpenProjects();
if (projects.length == 0) {
return null;
}
Project project = projects[0];
final IdeFrameImpl frame = getFrame(project);
if (frame == null) {
return null;
}
final Element frameElement = new Element(FRAME_ELEMENT);
int extendedState = frame.getExtendedState();
if (SystemInfo.isMacOSLion) {
@SuppressWarnings("deprecation") ComponentPeer peer = frame.getPeer();
if (peer instanceof FramePeer) {
// frame.state is not updated by jdk so get it directly from peer
extendedState = ((FramePeer)peer).getState();
}
}
boolean isMaximized = extendedState == Frame.MAXIMIZED_BOTH ||
isFullScreenSupportedInCurrentOS() && frame.isInFullScreen();
boolean usePreviousBounds = isMaximized &&
myFrameBounds != null &&
frame.getBounds().contains(new Point((int)myFrameBounds.getCenterX(), (int)myFrameBounds.getCenterY()));
Rectangle rectangle = usePreviousBounds ? myFrameBounds : frame.getBounds();
frameElement.setAttribute(X_ATTR, Integer.toString(rectangle.x));
frameElement.setAttribute(Y_ATTR, Integer.toString(rectangle.y));
frameElement.setAttribute(WIDTH_ATTR, Integer.toString(rectangle.width));
frameElement.setAttribute(HEIGHT_ATTR, Integer.toString(rectangle.height));
if (!(frame.isInFullScreen() && SystemInfo.isAppleJvm)) {
frameElement.setAttribute(EXTENDED_STATE_ATTR, Integer.toString(extendedState));
}
return frameElement;
}
public final DesktopLayout getLayout() {