diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java index 654d0b75ae..3cdefa6907 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java @@ -86,38 +86,27 @@ public class ByteViewerPanel extends JPanel implements LayoutModel, LayoutListen editColor = ByteViewerComponentProvider.CHANGED_VALUE_COLOR; } - /** - * Return the size that this component would like to be. - */ @Override public Dimension getPreferredSize() { - Dimension dim = getSize(); - // calculate dimension - int width = 0; - int height = 20 * fontHeight + statusPanel.getHeight(); - if (dim != null) { - height += dim.height; + int rowCount = 20; + int rowsHeight = rowCount * fontHeight; + int defaultHeight = rowsHeight + statusPanel.getHeight(); + + if (viewList.isEmpty()) { + // add 20 for border layout vertical gap + int width = statusPanel.getPreferredSize().width + 20; + return new Dimension(width, defaultHeight); } - boolean addHeight = true; + + int width = indexPanel.getPreferredSize().width; + int height = defaultHeight; for (ByteViewerComponent c : viewList) { - Dimension d = c.getPreferredSize(); - width += d.width; - width += 2; // for separator - if (addHeight) { - height += d.height; - addHeight = false; - } + width += d.width + 2; // +2 for separator + height = Math.max(d.height, defaultHeight); } - if (width == 0) { - width = statusPanel.getPreferredSize().width + 20; // add 20 for - // border layout vertical gap - } - else { - width += indexPanel.getPreferredSize().width; - } return new Dimension(width, height); } @@ -126,9 +115,6 @@ public class ByteViewerPanel extends JPanel implements LayoutModel, LayoutListen super.paintComponent(g); } - ////////////////////////////////////////////////////////////////////////// - // ** package-level methods ** - ////////////////////////////////////////////////////////////////////////// void setCurrentCursorColor(Color c) { currentCursorColor = c; for (ByteViewerComponent comp : viewList) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DetachedWindowNode.java b/Ghidra/Framework/Docking/src/main/java/docking/DetachedWindowNode.java index 4d130f1dd1..5a8584d83f 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DetachedWindowNode.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DetachedWindowNode.java @@ -37,13 +37,12 @@ import ghidra.util.bean.GGlassPane; class DetachedWindowNode extends WindowNode { private Window window; - //private String title; private Node child; - private Rectangle bounds; private StatusBar statusBar; private JComponent childComp; private DropTargetHandler dropTargetHandler; private DropTargetFactory dropTargetFactory; + private Rectangle restoreBounds = new Rectangle(); /** * Constructs a new WindowNode @@ -59,7 +58,6 @@ class DetachedWindowNode extends WindowNode { this.child = child; this.dropTargetFactory = factory; child.parent = this; - bounds = new Rectangle(0, 0, 0, 0); } /** @@ -76,20 +74,20 @@ class DetachedWindowNode extends WindowNode { this.parent = parent; this.dropTargetFactory = factory; - //title = elem.getAttributeValue("TITLE"); int x = Integer.parseInt(elem.getAttributeValue("X_POS")); int y = Integer.parseInt(elem.getAttributeValue("Y_POS")); int width = Integer.parseInt(elem.getAttributeValue("WIDTH")); int height = Integer.parseInt(elem.getAttributeValue("HEIGHT")); - bounds = new Rectangle(x, y, width, height); + restoreBounds = new Rectangle(x, y, width, height); Element childElement = (Element) elem.getChildren().get(0); child = processChildElement(childElement, mgr, this, list); - } - void setInitialLocation(int x, int y) { - bounds.x = x; - bounds.y = y; + void setInitialBounds(Rectangle r) { + if (r == null) { + r = new Rectangle(); + } + restoreBounds = r; } void updateTitle() { @@ -366,32 +364,51 @@ class DetachedWindowNode extends WindowNode { } }); - adjustBounds(); - + Rectangle bounds = getNewBounds(window); window.setBounds(bounds); window.setVisible(true); } - /** - * Ensures the bounds of this window have a valid location and size - */ - private void adjustBounds() { + private Rectangle getNewBounds(Window newWindow) { - if (bounds.height == 0 || bounds.width == 0) { + Rectangle updatedBounds = new Rectangle(restoreBounds); + if (updatedBounds.isEmpty()) { + // No bounds to restore; pick something reasonable window.pack(); - Dimension d = window.getSize(); - bounds.height = d.height; - bounds.width = d.width; + Dimension d = newWindow.getSize(); + updatedBounds.height = d.height; + updatedBounds.width = d.width; } + else { + + // Update the desired window bounds for the size of the component. The window size + // has to account for things like the menu and toolbars. These value were picked + // through trial-and-error. + int nonComponentWidth = 12; + int nonComponentHeight = 120; + + updatedBounds.width += nonComponentWidth; + updatedBounds.height += nonComponentHeight; + } + + ensureValidLocation(updatedBounds); + + WindowUtilities.ensureEntirelyOnScreen(newWindow, updatedBounds); + + return updatedBounds; + } + + private void ensureValidLocation(Rectangle r) { Window activeWindow = winMgr.getActiveWindow(); - Point p = bounds.getLocation(); + Point p = r.getLocation(); if (p.x == 0 && p.y == 0) { - p = WindowUtilities.centerOnScreen(activeWindow, bounds.getSize()); - bounds.setLocation(p); + // assume that 0,0 means that we have not yet been placed at any preferred location + p = WindowUtilities.centerOnScreen(activeWindow, r.getSize()); + r.setLocation(p); } - WindowUtilities.ensureOnScreen(activeWindow, bounds); + WindowUtilities.ensureOnScreen(activeWindow, r); } private JFrame createFrame() { @@ -434,7 +451,7 @@ class DetachedWindowNode extends WindowNode { void updateDialog() { if (window != null && childComp != null) { - bounds = window.getBounds(); + restoreBounds = window.getBounds(); winMgr.getMainWindow().requestFocus(); getContentPane().remove(childComp); window.dispose(); @@ -465,7 +482,7 @@ class DetachedWindowNode extends WindowNode { } } else if (window != null) { - bounds = window.getBounds(); + restoreBounds = window.getBounds(); window.setVisible(false); window.dispose(); window = null; @@ -557,14 +574,14 @@ class DetachedWindowNode extends WindowNode { @Override Element saveToXML() { if (window != null) { - bounds = window.getBounds(); + restoreBounds = window.getBounds(); } Element root = new Element("WINDOW_NODE"); - root.setAttribute("X_POS", "" + bounds.x); - root.setAttribute("Y_POS", "" + bounds.y); - root.setAttribute("WIDTH", "" + bounds.width); - root.setAttribute("HEIGHT", "" + bounds.height); + root.setAttribute("X_POS", "" + restoreBounds.x); + root.setAttribute("Y_POS", "" + restoreBounds.y); + root.setAttribute("WIDTH", "" + restoreBounds.width); + root.setAttribute("HEIGHT", "" + restoreBounds.height); root.addContent(child.saveToXML()); return root; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java b/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java index cd73733aea..b3e3655ac5 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/RootNode.java @@ -150,9 +150,7 @@ class RootNode extends WindowNode { void setToolName(String toolName) { this.toolName = toolName; windowWrapper.setTitle(toolName); - Iterator it = detachedWindows.iterator(); - while (it.hasNext()) { - DetachedWindowNode windowNode = it.next(); + for (DetachedWindowNode windowNode : detachedWindows) { windowNode.updateTitle(); } @@ -186,9 +184,7 @@ class RootNode extends WindowNode { void setIcon(ImageIcon icon) { Image iconImage = icon.getImage(); setFrameIcon(windowWrapper.getParentFrame(), iconImage); - Iterator it = detachedWindows.iterator(); - while (it.hasNext()) { - DetachedWindowNode windowNode = it.next(); + for (DetachedWindowNode windowNode : detachedWindows) { windowNode.setIcon(iconImage); } } @@ -206,9 +202,7 @@ class RootNode extends WindowNode { WindowUtilities.ensureOnScreen(mainWindow); } - Iterator it = detachedWindows.iterator(); - while (it.hasNext()) { - DetachedWindowNode windowNode = it.next(); + for (DetachedWindowNode windowNode : detachedWindows) { windowNode.setVisible(state); } } @@ -224,14 +218,31 @@ class RootNode extends WindowNode { * @param loc the location for the new window. */ void addToNewWindow(ComponentPlaceholder placeholder, Point loc) { + DockableComponent component = placeholder.getComponent(); + Dimension placeholderSize = null; + if (component != null) { + Dimension size = component.getSize(); + Dimension preferredSize = component.getPreferredSize(); + + placeholderSize = new Dimension(size); + int area = size.width * size.height; + int preferredArea = preferredSize.width * preferredSize.height; + if (preferredArea > area) { + placeholderSize.width = preferredSize.width; + placeholderSize.height = preferredSize.height; + } + } + ComponentNode node = new ComponentNode(winMgr); placeholder.setNode(node); node.parent = this; DetachedWindowNode windowNode = new DetachedWindowNode(winMgr, this, node, dropTargetFactory); - if (loc != null) { - windowNode.setInitialLocation(loc.x, loc.y); - } + + Point location = loc == null ? new Point() : loc; + Dimension size = placeholderSize == null ? new Dimension() : placeholderSize; + windowNode.setInitialBounds(new Rectangle(location, size)); + detachedWindows.add(windowNode); placeholder.getNode().add(placeholder); placeholder.requestFocusWhenReady(); @@ -302,9 +313,7 @@ class RootNode extends WindowNode { if (child != null && child.contains(info)) { return windowWrapper.getWindow(); } - Iterator iter = detachedWindows.iterator(); - while (iter.hasNext()) { - DetachedWindowNode winNode = iter.next(); + for (DetachedWindowNode winNode : detachedWindows) { if (winNode.contains(info)) { return winNode.getWindow(); } @@ -319,9 +328,7 @@ class RootNode extends WindowNode { if (invalid) { clearContextTypes(); updateChild(); - Iterator it = detachedWindows.iterator(); - while (it.hasNext()) { - DetachedWindowNode windowNode = it.next(); + for (DetachedWindowNode windowNode : detachedWindows) { windowNode.update(); } invalid = false; @@ -332,9 +339,7 @@ class RootNode extends WindowNode { } void updateDialogs() { - Iterator it = detachedWindows.iterator(); - while (it.hasNext()) { - DetachedWindowNode windowNode = it.next(); + for (DetachedWindowNode windowNode : detachedWindows) { windowNode.updateDialog(); } } @@ -438,9 +443,7 @@ class RootNode extends WindowNode { if (child != null) { root.addContent(child.saveToXML()); } - Iterator it = detachedWindows.iterator(); - while (it.hasNext()) { - DetachedWindowNode windowNode = it.next(); + for (DetachedWindowNode windowNode : detachedWindows) { root.addContent(windowNode.saveToXML()); } return root; @@ -555,9 +558,7 @@ class RootNode extends WindowNode { rootDropTargetHandler.dispose(); } - Iterator it = detachedWindows.iterator(); - while (it.hasNext()) { - DetachedWindowNode windowNode = it.next(); + for (DetachedWindowNode windowNode : detachedWindows) { notifyWindowRemoved(windowNode); windowNode.dispose(); } @@ -571,9 +572,7 @@ class RootNode extends WindowNode { if (child != null && child.contains(info)) { return true; } - Iterator iter = detachedWindows.iterator(); - while (iter.hasNext()) { - DetachedWindowNode winNode = iter.next(); + for (DetachedWindowNode winNode : detachedWindows) { if (winNode.contains(info)) { return true; } @@ -606,9 +605,7 @@ class RootNode extends WindowNode { statusBar.clearStatusMessages(); - Iterator iter = detachedWindows.iterator(); - while (iter.hasNext()) { - DetachedWindowNode winNode = iter.next(); + for (DetachedWindowNode winNode : detachedWindows) { winNode.clearStatusMessages(); } } @@ -620,9 +617,7 @@ class RootNode extends WindowNode { statusBar.setStatusText(text); - Iterator iter = detachedWindows.iterator(); - while (iter.hasNext()) { - DetachedWindowNode winNode = iter.next(); + for (DetachedWindowNode winNode : detachedWindows) { winNode.setStatusText(text); } }