mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-3958 - Update how un-maximized window bounds are tracked
This commit is contained in:
parent
fc9e495c6c
commit
3de35623bd
1 changed files with 98 additions and 31 deletions
|
@ -28,6 +28,7 @@ import org.jdom.Element;
|
|||
import generic.util.WindowUtilities;
|
||||
import ghidra.framework.OperatingSystem;
|
||||
import ghidra.framework.Platform;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.bean.GGlassPane;
|
||||
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||
import ghidra.util.datastruct.WeakSet;
|
||||
|
@ -427,16 +428,13 @@ class RootNode extends WindowNode {
|
|||
Element saveToXML() {
|
||||
Element root = new Element(ROOT_NODE_ELEMENT_NAME);
|
||||
JFrame frame = windowWrapper.getParentFrame();
|
||||
// Save un-maximized/un-iconified bounds rather than e.g. whole screen if maximized
|
||||
int state = frame.getExtendedState(); // Remember current state
|
||||
frame.setExtendedState(JFrame.NORMAL); // Un-maximize & un-iconify
|
||||
Rectangle r = frame.getBounds(); // The un-maximized & un-iconified bounds
|
||||
frame.setExtendedState(state); // Revert to original state
|
||||
Rectangle r = getSaveableBounds();
|
||||
root.setAttribute("X_POS", "" + r.x);
|
||||
root.setAttribute("Y_POS", "" + r.y);
|
||||
root.setAttribute("WIDTH", "" + r.width);
|
||||
root.setAttribute("HEIGHT", "" + r.height);
|
||||
root.setAttribute("EX_STATE", "" + state);
|
||||
root.setAttribute("EX_STATE", "" + frame.getExtendedState());
|
||||
|
||||
if (child != null) {
|
||||
root.addContent(child.saveToXML());
|
||||
}
|
||||
|
@ -448,6 +446,18 @@ class RootNode extends WindowNode {
|
|||
return root;
|
||||
}
|
||||
|
||||
private Rectangle getSaveableBounds() {
|
||||
|
||||
Rectangle bounds = windowWrapper.getLastBounds();
|
||||
if (bounds != null) {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
// This implies the user has never maximized the window; just use the window bounds.
|
||||
JFrame frame = windowWrapper.getParentFrame();
|
||||
return frame.getBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the component hierarchy from the given XML JDOM element.
|
||||
* <p>
|
||||
|
@ -478,7 +488,15 @@ class RootNode extends WindowNode {
|
|||
Rectangle bounds = new Rectangle(x, y, width, height);
|
||||
WindowUtilities.ensureOnScreen(frame, bounds);
|
||||
frame.setBounds(bounds);
|
||||
windowWrapper.setLastBounds(bounds);
|
||||
|
||||
Swing.runLater(() -> {
|
||||
// On some systems setting the bounds will interfere with setting the extended state.
|
||||
// Run this later to ensure the extended state is applied after setting the bounds.
|
||||
// Executing in this order allows the bounds we set above to be used when the user
|
||||
// transitions out of the maximized state.
|
||||
frame.setExtendedState(extendedState);
|
||||
});
|
||||
|
||||
List<ComponentPlaceholder> restoredPlaceholders = new ArrayList<>();
|
||||
Iterator<?> elementIterator = rootNodeElement.getChildren().iterator();
|
||||
|
@ -611,29 +629,64 @@ class RootNode extends WindowNode {
|
|||
//==================================================================================================
|
||||
|
||||
/** Interface to wrap JDialog and JFrame so that they can be used by one handle */
|
||||
private interface SwingWindowWrapper {
|
||||
boolean isVisible();
|
||||
private abstract class SwingWindowWrapper {
|
||||
|
||||
boolean isModal();
|
||||
/**
|
||||
* The last known non-maximized window bounds
|
||||
*/
|
||||
private Rectangle lastBounds;
|
||||
|
||||
void validate();
|
||||
abstract boolean isVisible();
|
||||
|
||||
Container getContentPane();
|
||||
abstract boolean isModal();
|
||||
|
||||
void setJMenuBar(JMenuBar menuBar);
|
||||
abstract void validate();
|
||||
|
||||
void dispose();
|
||||
abstract Container getContentPane();
|
||||
|
||||
Window getWindow();
|
||||
abstract void setJMenuBar(JMenuBar menuBar);
|
||||
|
||||
JFrame getParentFrame();
|
||||
abstract void dispose();
|
||||
|
||||
void setTitle(String title);
|
||||
abstract Window getWindow();
|
||||
|
||||
String getTitle();
|
||||
abstract JFrame getParentFrame();
|
||||
|
||||
abstract void setTitle(String title);
|
||||
|
||||
abstract String getTitle();
|
||||
|
||||
/**
|
||||
* Stores the given bounds if they are not the maximized bounds
|
||||
* @param bounds the bounds
|
||||
*/
|
||||
public void setLastBounds(Rectangle bounds) {
|
||||
Rectangle screenBounds = WindowUtilities.getScreenBounds(getWindow());
|
||||
if (screenBounds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
private class JDialogWindowWrapper implements SwingWindowWrapper {
|
||||
Rectangle boundsSize = new Rectangle(bounds.getSize());
|
||||
Rectangle screenSize = new Rectangle(screenBounds.getSize());
|
||||
if (boundsSize.contains(screenSize)) {
|
||||
// This can happen when the bounds being set are the full screen bounds. We only
|
||||
// wish to save the non-maximized bounds.
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastBounds = bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last non-maximized frame bounds
|
||||
* @return the bounds
|
||||
*/
|
||||
public Rectangle getLastBounds() {
|
||||
return lastBounds;
|
||||
}
|
||||
}
|
||||
|
||||
private class JDialogWindowWrapper extends SwingWindowWrapper {
|
||||
|
||||
private final JDialog wrappedDialog;
|
||||
private final SwingWindowWrapper parentFrame;
|
||||
|
@ -663,9 +716,16 @@ class RootNode extends WindowNode {
|
|||
public void windowActivated(WindowEvent e) {
|
||||
winMgr.setActive(wrappedDialog, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowStateChanged(WindowEvent e) {
|
||||
// this is called when transitioning in and out of the full-screen state
|
||||
setLastBounds(wrappedDialog.getBounds());
|
||||
}
|
||||
};
|
||||
|
||||
dialog.addWindowListener(windowListener);
|
||||
dialog.addWindowStateListener(windowListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -686,6 +746,11 @@ class RootNode extends WindowNode {
|
|||
return wrappedDialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JFrame getParentFrame() {
|
||||
return parentFrame.getParentFrame();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return wrappedDialog.isVisible();
|
||||
|
@ -701,11 +766,6 @@ class RootNode extends WindowNode {
|
|||
wrappedDialog.validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JFrame getParentFrame() {
|
||||
return parentFrame.getParentFrame();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(String title) {
|
||||
wrappedDialog.setTitle(title);
|
||||
|
@ -722,7 +782,7 @@ class RootNode extends WindowNode {
|
|||
}
|
||||
}
|
||||
|
||||
private class JFrameWindowWrapper implements SwingWindowWrapper {
|
||||
private class JFrameWindowWrapper extends SwingWindowWrapper {
|
||||
|
||||
private final JFrame wrappedFrame;
|
||||
private WindowAdapter windowListener;
|
||||
|
@ -763,8 +823,16 @@ class RootNode extends WindowNode {
|
|||
public void windowDeiconified(WindowEvent e) {
|
||||
winMgr.deIconify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowStateChanged(WindowEvent e) {
|
||||
// this is called when transitioning in and out of the full-screen state
|
||||
setLastBounds(wrappedFrame.getBounds());
|
||||
}
|
||||
};
|
||||
|
||||
wrappedFrame.addWindowListener(windowListener);
|
||||
wrappedFrame.addWindowStateListener(windowListener);
|
||||
|
||||
wrappedFrame.setSize(800, 400);
|
||||
}
|
||||
|
@ -786,6 +854,11 @@ class RootNode extends WindowNode {
|
|||
return wrappedFrame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JFrame getParentFrame() {
|
||||
return wrappedFrame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return wrappedFrame.isVisible();
|
||||
|
@ -801,11 +874,6 @@ class RootNode extends WindowNode {
|
|||
wrappedFrame.validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JFrame getParentFrame() {
|
||||
return wrappedFrame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(String title) {
|
||||
wrappedFrame.setTitle(title);
|
||||
|
@ -820,7 +888,6 @@ class RootNode extends WindowNode {
|
|||
public boolean isModal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void addDockingWindowListener(DockingWindowListener listener) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue