mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
GT-2855 - fix list cell renderering sizing
This commit is contained in:
parent
538cbc1226
commit
131228a250
@ -32,9 +32,13 @@ import docking.widgets.list.GList;
|
||||
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 GhidraFileChooser chooser;
|
||||
private DirectoryListModel model;
|
||||
private FileListCellRenderer cellRenderer;
|
||||
private JLabel listEditorLabel;
|
||||
private JTextField listEditorField;
|
||||
private JPanel listEditor;
|
||||
@ -52,7 +56,7 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
|
||||
private void build() {
|
||||
|
||||
setLayoutOrientation(JList.VERTICAL_WRAP);
|
||||
setCellRenderer(new FileListCellRenderer(chooser));
|
||||
setCellRenderer((cellRenderer = new FileListCellRenderer(getFont(), chooser)));
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
@ -281,36 +285,6 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
|
||||
setSelectedIndices(indices);
|
||||
}
|
||||
|
||||
// overridden to account for the renderers insets, to avoid clipping
|
||||
@Override
|
||||
public void setFixedCellWidth(int width) {
|
||||
|
||||
int fullWidth = width;
|
||||
ListCellRenderer<? super File> renderer = getCellRenderer();
|
||||
if (renderer instanceof JComponent) {
|
||||
JComponent c = (JComponent) renderer;
|
||||
Insets insets = c.getInsets();
|
||||
fullWidth += insets.left + insets.right;
|
||||
}
|
||||
|
||||
super.setFixedCellWidth(fullWidth);
|
||||
}
|
||||
|
||||
// overridden to account for the renderers insets, to avoid clipping
|
||||
@Override
|
||||
public void setFixedCellHeight(int height) {
|
||||
|
||||
int fullHeight = height;
|
||||
ListCellRenderer<? super File> renderer = getCellRenderer();
|
||||
if (renderer instanceof JComponent) {
|
||||
JComponent c = (JComponent) renderer;
|
||||
Insets insets = c.getInsets();
|
||||
fullHeight += insets.top + insets.bottom;
|
||||
}
|
||||
|
||||
super.setFixedCellHeight(fullHeight);
|
||||
}
|
||||
|
||||
private boolean isEditing() {
|
||||
return (editedFile != null);
|
||||
}
|
||||
@ -367,6 +341,37 @@ 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.
|
||||
*/
|
||||
void recomputeListCellDimensions(List<File> files) {
|
||||
files = (files != null) ? files : model.getAllFiles();
|
||||
Dimension cellDims =
|
||||
cellRenderer.computePlainTextListCellDimensions(this, files, 0, DEFAULT_ICON_SIZE);
|
||||
if (cellDims.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();
|
||||
cellDims.width =
|
||||
parentSize.width - (insets != null ? insets.right + insets.left : 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
cellDims.width += DEFAULT_ICON_SIZE + WIDTH_PADDING;
|
||||
}
|
||||
setFixedCellWidth(cellDims.width);
|
||||
setFixedCellHeight(cellDims.height + HEIGHT_PADDING);
|
||||
}
|
||||
|
||||
/*junit*/ JTextField getListEditorText() {
|
||||
return listEditorField;
|
||||
}
|
||||
|
@ -74,6 +74,10 @@ class DirectoryListModel extends AbstractListModel<File> {
|
||||
return fileList.indexOf(file);
|
||||
}
|
||||
|
||||
public List<File> getAllFiles() {
|
||||
return new ArrayList<>(fileList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return fileList.size();
|
||||
|
@ -16,6 +16,7 @@
|
||||
package docking.widgets.filechooser;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JList;
|
||||
@ -28,9 +29,11 @@ class FileListCellRenderer extends GListCellRenderer<File> {
|
||||
private GhidraFileChooser chooser;
|
||||
private GhidraFileChooserModel model;
|
||||
|
||||
public FileListCellRenderer(GhidraFileChooser chooser) {
|
||||
public FileListCellRenderer(Font font, GhidraFileChooser chooser) {
|
||||
super(font);
|
||||
this.chooser = chooser;
|
||||
this.model = chooser.getModel();
|
||||
setShouldAlternateRowBackgroundColors(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,9 +88,6 @@ public class GhidraFileChooser extends DialogComponentProvider
|
||||
static final String NEW_FOLDER = "New Folder";
|
||||
|
||||
private static final int PAD = 5;
|
||||
private static final int DEFAULT_ICON_SIZE = 16;
|
||||
private static final int HEIGHT_PADDING = 5;
|
||||
private static final int WIDTH_PADDING = 14;
|
||||
|
||||
private static Icon refreshIcon = Icons.REFRESH_ICON;
|
||||
private static Icon backIcon = ResourceManager.loadImage("images/left.png");
|
||||
@ -555,18 +552,11 @@ public class GhidraFileChooser extends DialogComponentProvider
|
||||
private JScrollPane buildDirectoryList() {
|
||||
directoryListModel = new DirectoryListModel();
|
||||
|
||||
// SCR 3392 - 12/7/07
|
||||
// initially added to resize the cells of the list when the new files are
|
||||
// inserted into the list (like when creating a single new folder)
|
||||
directoryListModel.addListDataListener(new ListDataListener() {
|
||||
@Override
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
int size = directoryListModel.getSize();
|
||||
List<File> fileList = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
fileList.add(directoryListModel.getFile(i));
|
||||
}
|
||||
computeListCellDimensions(fileList);
|
||||
// called when the list changes because a new file is inserted (ie. create new folder action)
|
||||
directoryList.recomputeListCellDimensions(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -850,42 +840,6 @@ public class GhidraFileChooser extends DialogComponentProvider
|
||||
return worker.isBusy();
|
||||
}
|
||||
|
||||
private void computeListCellDimensions(List<File> files) {
|
||||
|
||||
Font font = directoryList.getFont();
|
||||
FontMetrics metrics = directoryList.getFontMetrics(font);
|
||||
|
||||
int maxWidth = getDefaultMaxWidth(files, metrics);
|
||||
|
||||
directoryList.setFixedCellWidth(maxWidth + DEFAULT_ICON_SIZE + WIDTH_PADDING);
|
||||
int rowHeight = Math.max(metrics.getHeight(), DEFAULT_ICON_SIZE);
|
||||
directoryList.setFixedCellHeight(rowHeight + HEIGHT_PADDING);
|
||||
}
|
||||
|
||||
private int getDefaultMaxWidth(List<File> theFiles, FontMetrics metrics) {
|
||||
int maxWidth = 0;
|
||||
if (theFiles.size() > 0) {
|
||||
for (File file : theFiles) {
|
||||
maxWidth = Math.max(maxWidth, metrics.stringWidth(getDisplayName(file)));
|
||||
}
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
Dimension scrollSize = directoryScroll.getSize();
|
||||
if (scrollSize.width == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Border border = directoryScroll.getBorder();
|
||||
if (border != null) {
|
||||
Insets borderInsets = border.getBorderInsets(directoryScroll);
|
||||
if (borderInsets != null) {
|
||||
scrollSize.width -= (borderInsets.right + borderInsets.left);
|
||||
}
|
||||
}
|
||||
return scrollSize.width - WIDTH_PADDING - DEFAULT_ICON_SIZE;
|
||||
}
|
||||
|
||||
String getDisplayName(File file) {
|
||||
if (file != null) {
|
||||
if (GhidraFileChooser.MY_COMPUTER.equals(getCurrentDirectory())) {
|
||||
@ -906,8 +860,10 @@ public class GhidraFileChooser extends DialogComponentProvider
|
||||
}
|
||||
|
||||
private void setDirectoryList(File directory, List<File> files) {
|
||||
// if the visible listing is still the same directory as this incoming list of files
|
||||
if (currentDirectory().equals(directory)) {
|
||||
computeListCellDimensions(files);
|
||||
// recompute list cell dims before causing an update to the model
|
||||
directoryList.recomputeListCellDimensions(files);
|
||||
directoryTableModel.setFiles(files);
|
||||
directoryTable.scrollRectToVisible(new Rectangle(0, 0, 0, 0));
|
||||
directoryListModel.setFiles(files);
|
||||
|
@ -16,6 +16,7 @@
|
||||
package docking.widgets.list;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.swing.*;
|
||||
@ -121,4 +122,31 @@ public class GListCellRenderer<E> extends AbstractGCellRenderer implements ListC
|
||||
protected void configureFont(JList<? extends E> list, ListModel<? extends E> model, int index) {
|
||||
setFont(defaultFont);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width, height necessary to display the largest element in this list.
|
||||
* <p>
|
||||
* Useful for setting a JList's fixed cell width and height to the actual necessary size.
|
||||
* <p>
|
||||
* NOTE: the items and the renderer must be in plain text mode, not HTML rendering mode.
|
||||
*
|
||||
* @param list the JList that uses this cell renderer
|
||||
* @param items the items to measure
|
||||
* @param minWidth the minimum width that can be returned
|
||||
* @param minHeight the minimum height that can be returned
|
||||
* @return a new Dimension containing a width and height value necessary to display the largest
|
||||
* element in the list
|
||||
*/
|
||||
public Dimension computePlainTextListCellDimensions(JList<? extends E> list,
|
||||
List<E> items,
|
||||
int minWidth, int minHeight) {
|
||||
configureFont(list, list.getModel(), 0);
|
||||
FontMetrics metrics = getFontMetrics(getFont());
|
||||
int maxWidth = minWidth;
|
||||
for (E item : items) {
|
||||
String text = getItemText(item).toString();
|
||||
maxWidth = Math.max(maxWidth, metrics.stringWidth(text));
|
||||
}
|
||||
return new Dimension(maxWidth, Math.max(metrics.getHeight(), minHeight));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user