GP-31 - fix Ghidra File chooser rendering on high dpi displays

Filename display in the directory list mode were getting incorrectly
truncated and shown with ellipses on high DPI display mode.

The previous method was to manually calculate the necessary width of the
directory list's cell renderer, but for some reason we were getting
slightly different values when measuring strings when doing it in our
code vs when swing's JLabel was painting, possible causing our manually
sized cell renderer to be a few pixels too small.

This fix is to yank all that out and let swing measure each element of
the list to determine the necessary width.

Also fixes the directory list cell renderer to inherit the
-Dfont.size.override=XX setting from its parent panel instead of
reseting the font back to non-overidden default.
This commit is contained in:
dev747368 2020-07-09 14:01:17 -04:00
parent 2ecde972c6
commit c759dd1609
4 changed files with 25 additions and 68 deletions

View file

@ -25,8 +25,6 @@ import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import docking.event.mouse.GMouseListenerAdapter;
import docking.widgets.AutoLookup;
@ -37,12 +35,10 @@ import ghidra.util.exception.AssertException;
class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryModelIf {
private static final int DEFAULT_ICON_SIZE = 16;
private static final int WIDTH_PADDING = 14;
private static final int HEIGHT_PADDING = 5;
private static final int MIN_HEIGHT_PADDING = 5;
private GhidraFileChooser chooser;
private DirectoryListModel model;
private FileListCellRenderer cellRenderer;
private JLabel listEditorLabel;
private JTextField listEditorField;
private JPanel listEditor;
@ -50,35 +46,37 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
/** The file being edited */
private File editedFile;
DirectoryList(GhidraFileChooser chooser, DirectoryListModel model) {
/**
* Create a new DirectoryList instance.
*
* @param chooser the {@link GhidraFileChooser} this instance is nested in
* @param model the {@link DirectoryListModel}
* @param font the parent component's font, used to calculate row height in the list once
*/
DirectoryList(GhidraFileChooser chooser, DirectoryListModel model, Font font) {
super(model);
this.chooser = chooser;
this.model = model;
build();
build(font);
}
private void build() {
private void build(Font font) {
setLayoutOrientation(JList.VERTICAL_WRAP);
cellRenderer = new FileListCellRenderer(getFont(), chooser);
FileListCellRenderer cellRenderer = new FileListCellRenderer(chooser);
setCellRenderer(cellRenderer);
model.addListDataListener(new ListDataListener() {
@Override
public void contentsChanged(ListDataEvent e) {
// called when the list changes because a new file is inserted (ie. create new folder action)
recomputeListCellDimensions(null);
}
@Override
public void intervalAdded(ListDataEvent e) {
recomputeListCellDimensions(null);
}
@Override
public void intervalRemoved(ListDataEvent e) {
// don't care
}
});
// Enable the list to calculate the width of the cells on its own, but manually
// specify the height to ensure some padding between rows.
// We need the parent component's Font instead of using our
// own #getFont() because we are not a child of the parent yet and
// the font may be set to something other than the default.
FontMetrics metrics = cellRenderer.getFontMetrics(font);
setFixedCellHeight(
Math.max(metrics.getHeight(), DEFAULT_ICON_SIZE) +
Math.max(metrics.getHeight() / 3, MIN_HEIGHT_PADDING));
setFixedCellWidth(-1);
addMouseListener(new GMouseListenerAdapter() {
@Override
@ -392,36 +390,6 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
}
}
/**
* Resizes this list's cell dimensions based on the string widths found in the supplied
* list of files.
* <p>
* If there there are no files, uses the JScrollPane that contains us for the cellwidth.
*
* @param files list of files to use to resize the list's fixed cell dimensions. If null, uses
* the model's current set of files.
*/
private void recomputeListCellDimensions(List<File> files) {
files = (files != null) ? files : model.getAllFiles();
Dimension d =
cellRenderer.computePlainTextListCellDimensions(this, files, 0, DEFAULT_ICON_SIZE);
if (d.width == 0 && getParent() != null) {
// special case: if there were no files to measure, use the containing JScrollPane's
// width
if (getParent().getParent() instanceof JScrollPane) {
JScrollPane parent = (JScrollPane) getParent().getParent();
Dimension parentSize = parent.getSize();
Insets insets = parent.getInsets();
d.width = parentSize.width - (insets != null ? insets.right + insets.left : 0);
}
}
else {
d.width += DEFAULT_ICON_SIZE + WIDTH_PADDING;
}
setFixedCellWidth(d.width);
setFixedCellHeight(d.height + HEIGHT_PADDING);
}
/*junit*/ JTextField getListEditorText() {
return listEditorField;
}

View file

@ -16,7 +16,6 @@
package docking.widgets.filechooser;
import java.awt.Component;
import java.awt.Font;
import java.io.File;
import javax.swing.JList;
@ -29,8 +28,7 @@ class FileListCellRenderer extends GListCellRenderer<File> {
private GhidraFileChooser chooser;
private GhidraFileChooserModel model;
public FileListCellRenderer(Font font, GhidraFileChooser chooser) {
super(font);
public FileListCellRenderer(GhidraFileChooser chooser) {
this.chooser = chooser;
this.model = chooser.getModel();
setShouldAlternateRowBackgroundColors(false);

View file

@ -572,7 +572,7 @@ public class GhidraFileChooser extends DialogComponentProvider
private JScrollPane buildDirectoryList() {
directoryListModel = new DirectoryListModel();
directoryList = new DirectoryList(this, directoryListModel);
directoryList = new DirectoryList(this, directoryListModel, rootPanel.getFont());
directoryList.setName("LIST");
directoryList.setBackground(BACKGROUND_COLOR);

View file

@ -60,15 +60,6 @@ public class GListCellRenderer<E> extends AbstractGCellRenderer implements ListC
setShouldAlternateRowBackgroundColors(false);
}
/**
* Constructs a new GListCellRenderer using the specified font.
* @param f the font to use when rendering text in the lists' cells
*/
public GListCellRenderer(Font f) {
this();
setFont(f);
}
/**
* Return the cell renderer text
* @param value Cell object value