mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Fixed the GFilterTable to have the selection notification include when
the selection is cleared
This commit is contained in:
parent
41c453c545
commit
d68e9bbab8
5 changed files with 152 additions and 99 deletions
|
@ -17,7 +17,6 @@ package ghidra.app.plugin.core.calltree;
|
|||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
@ -27,7 +26,7 @@ import javax.swing.tree.TreePath;
|
|||
import docking.ActionContext;
|
||||
import docking.WindowPosition;
|
||||
import docking.action.*;
|
||||
import docking.util.GraphicsUtils;
|
||||
import docking.resources.icons.NumberIcon;
|
||||
import docking.widgets.dialogs.NumberInputDialog;
|
||||
import docking.widgets.label.GLabel;
|
||||
import docking.widgets.tree.*;
|
||||
|
@ -1283,97 +1282,6 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
|
|||
}
|
||||
}
|
||||
|
||||
private class NumberIcon implements Icon {
|
||||
private String number;
|
||||
private float bestFontSize = -1;
|
||||
|
||||
NumberIcon(int number) {
|
||||
this.number = Integer.toString(number);
|
||||
}
|
||||
|
||||
void setNumber(int number) {
|
||||
this.number = Integer.toString(number);
|
||||
bestFontSize = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
g.setColor(Color.WHITE);
|
||||
g.fillRect(x, y, getIconWidth(), getIconHeight());
|
||||
g.setColor(new Color(0xb5d5ff));
|
||||
g.drawRect(x, y, getIconWidth(), getIconHeight());
|
||||
|
||||
float fontSize = getMaxFontSize(g, getIconWidth() - 1, getIconHeight());
|
||||
Font originalFont = g.getFont();
|
||||
Font textFont = originalFont.deriveFont(fontSize).deriveFont(Font.BOLD);
|
||||
g.setFont(textFont);
|
||||
|
||||
FontMetrics fontMetrics = g.getFontMetrics(textFont);
|
||||
Rectangle2D stringBounds = fontMetrics.getStringBounds(number, g);
|
||||
int textHeight = (int) stringBounds.getHeight();
|
||||
int iconHeight = getIconHeight();
|
||||
int space = y + iconHeight - textHeight;
|
||||
int halfSpace = space >> 1;
|
||||
int baselineY = y + iconHeight - halfSpace;// - halfTextHeight;// + halfTextHeight;
|
||||
|
||||
int textWidth = (int) stringBounds.getWidth();
|
||||
int iconWidth = getIconWidth();
|
||||
int halfWidth = iconWidth >> 1;
|
||||
int halfTextWidth = textWidth >> 1;
|
||||
int baselineX = x + halfWidth - halfTextWidth;
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
JComponent jc = null;
|
||||
if (c instanceof JComponent) {
|
||||
jc = (JComponent) c;
|
||||
}
|
||||
GraphicsUtils.drawString(jc, g, number, baselineX, baselineY);
|
||||
}
|
||||
|
||||
private float getMaxFontSize(Graphics g, int width, int height) {
|
||||
if (bestFontSize > 0) {
|
||||
return bestFontSize;
|
||||
}
|
||||
|
||||
float size = 12f;
|
||||
Font font = g.getFont().deriveFont(size); // reasonable default
|
||||
if (textFitsInFont(g, font, width, height)) {
|
||||
bestFontSize = size;
|
||||
return bestFontSize;
|
||||
}
|
||||
|
||||
do {
|
||||
size--;
|
||||
font = g.getFont().deriveFont(size);
|
||||
}
|
||||
while (!textFitsInFont(g, font, width, height));
|
||||
|
||||
bestFontSize = Math.max(1f, size);
|
||||
return bestFontSize;
|
||||
}
|
||||
|
||||
private boolean textFitsInFont(Graphics g, Font font, int width, int height) {
|
||||
FontMetrics fontMetrics = g.getFontMetrics(font);
|
||||
int textWidth = fontMetrics.stringWidth(number);
|
||||
if (textWidth > width) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int textHeight = fontMetrics.getHeight();
|
||||
return textHeight < height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
private class PendingRootNode extends GTreeNode {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package docking.resources.icons;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import docking.util.GraphicsUtils;
|
||||
|
||||
/**
|
||||
* An icon that paints the given number
|
||||
*/
|
||||
public class NumberIcon implements Icon {
|
||||
|
||||
private String number;
|
||||
private float bestFontSize = -1;
|
||||
|
||||
public NumberIcon(int number) {
|
||||
this.number = Integer.toString(number);
|
||||
}
|
||||
|
||||
public void setNumber(int number) {
|
||||
this.number = Integer.toString(number);
|
||||
bestFontSize = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
g.setColor(Color.WHITE);
|
||||
g.fillRect(x, y, getIconWidth(), getIconHeight());
|
||||
g.setColor(new Color(0xb5d5ff));
|
||||
g.drawRect(x, y, getIconWidth(), getIconHeight());
|
||||
|
||||
float fontSize = getMaxFontSize(g, getIconWidth() - 1, getIconHeight());
|
||||
Font originalFont = g.getFont();
|
||||
Font textFont = originalFont.deriveFont(fontSize).deriveFont(Font.BOLD);
|
||||
g.setFont(textFont);
|
||||
|
||||
FontMetrics fontMetrics = g.getFontMetrics(textFont);
|
||||
Rectangle2D stringBounds = fontMetrics.getStringBounds(number, g);
|
||||
int textHeight = (int) stringBounds.getHeight();
|
||||
int iconHeight = getIconHeight();
|
||||
int space = y + iconHeight - textHeight;
|
||||
int halfSpace = space >> 1;
|
||||
int baselineY = y + iconHeight - halfSpace;// - halfTextHeight;// + halfTextHeight;
|
||||
|
||||
int textWidth = (int) stringBounds.getWidth();
|
||||
int iconWidth = getIconWidth();
|
||||
int halfWidth = iconWidth >> 1;
|
||||
int halfTextWidth = textWidth >> 1;
|
||||
int baselineX = x + (halfWidth - halfTextWidth);
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
JComponent jc = null;
|
||||
if (c instanceof JComponent) {
|
||||
jc = (JComponent) c;
|
||||
}
|
||||
GraphicsUtils.drawString(jc, g, number, baselineX, baselineY);
|
||||
}
|
||||
|
||||
private float getMaxFontSize(Graphics g, int width, int height) {
|
||||
if (bestFontSize > 0) {
|
||||
return bestFontSize;
|
||||
}
|
||||
|
||||
float size = 12f;
|
||||
Font font = g.getFont().deriveFont(size); // reasonable default
|
||||
if (textFitsInFont(g, font, width, height)) {
|
||||
bestFontSize = size;
|
||||
return bestFontSize;
|
||||
}
|
||||
|
||||
do {
|
||||
size--;
|
||||
font = g.getFont().deriveFont(size);
|
||||
}
|
||||
while (!textFitsInFont(g, font, width, height));
|
||||
|
||||
bestFontSize = Math.max(1f, size);
|
||||
return bestFontSize;
|
||||
}
|
||||
|
||||
private boolean textFitsInFont(Graphics g, Font font, int width, int height) {
|
||||
|
||||
// padding so the text does not touch the border
|
||||
int padding = 2;
|
||||
FontMetrics fontMetrics = g.getFontMetrics(font);
|
||||
int textWidth = fontMetrics.stringWidth(number) + padding;
|
||||
if (textWidth > width) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int textHeight = fontMetrics.getHeight();
|
||||
return textHeight < height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return 16;
|
||||
}
|
||||
}
|
|
@ -70,7 +70,7 @@ public class GFilterTable<ROW_OBJECT> extends JPanel {
|
|||
private void addTableSelectionListener(GTable gTable) {
|
||||
gTable.getSelectionModel().addListSelectionListener(e -> {
|
||||
if (!e.getValueIsAdjusting()) {
|
||||
rowSelected();
|
||||
rowSelectionChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ public class GFilterTable<ROW_OBJECT> extends JPanel {
|
|||
|
||||
public void clearSelection() {
|
||||
table.clearSelection();
|
||||
table.getSelectionManager().clearSavedSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,19 +164,31 @@ public class GFilterTable<ROW_OBJECT> extends JPanel {
|
|||
listeners.remove(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that an item was selected.
|
||||
*/
|
||||
protected void rowSelected() {
|
||||
private void rowSelectionChanged() {
|
||||
ROW_OBJECT selectedObject = null;
|
||||
if (table.getSelectedRow() >= 0) {
|
||||
selectedObject = getSelectedRowObject();
|
||||
}
|
||||
|
||||
if (selectedObject == null) {
|
||||
rowSelectionCleared();
|
||||
return; // can happen for transient events
|
||||
}
|
||||
|
||||
rowSelected(selectedObject);
|
||||
}
|
||||
|
||||
protected void rowSelectionCleared() {
|
||||
for (ObjectSelectedListener<ROW_OBJECT> l : listeners) {
|
||||
l.objectSelected(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that an item was selected
|
||||
* @param selectedObject the selected row object
|
||||
*/
|
||||
protected void rowSelected(ROW_OBJECT selectedObject) {
|
||||
for (ObjectSelectedListener<ROW_OBJECT> l : listeners) {
|
||||
l.objectSelected(selectedObject);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,16 @@
|
|||
*/
|
||||
package docking.widgets.table;
|
||||
|
||||
/**
|
||||
* An interface for clients to know when an object is selected and when the selection is cleared
|
||||
*
|
||||
* @param <T> the object type
|
||||
*/
|
||||
public interface ObjectSelectedListener<T> {
|
||||
|
||||
/**
|
||||
* When an object is select; null if the selection is cleared
|
||||
* @param t the object selected or null
|
||||
*/
|
||||
public void objectSelected(T t);
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ public class HTMLUtilities {
|
|||
* @param text the text to check
|
||||
* @return true if the text cannot be correctly broken into lines
|
||||
*/
|
||||
private static boolean isUnbreakableHTML(String text) {
|
||||
public static boolean isUnbreakableHTML(String text) {
|
||||
if (text.contains(HTML_SPACE) && !text.contains(" ")) {
|
||||
// this can happen if the client has called a method on this class that turns spaces
|
||||
// to the HTML_SPACE
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue