mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-21 18:01:57 +08:00
GP-1981 - Fixed table header rendering
This commit is contained in:
@@ -224,6 +224,10 @@ public class GHelpBroker extends DefaultHelpBroker {
|
||||
|
||||
private void initializeUIComponents(Container contentPane) {
|
||||
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// the editor pane can be changed out from under us, such as when the UI is updated when
|
||||
// the theme changes
|
||||
Component[] components = contentPane.getComponents();
|
||||
@@ -243,6 +247,7 @@ public class GHelpBroker extends DefaultHelpBroker {
|
||||
new HelpViewSearcher(jHelp, helpModel);
|
||||
|
||||
installActions(jHelp);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void reload() {
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.util.WebColors;
|
||||
import ghidra.util.datastruct.WeakStore;
|
||||
|
||||
public class GColor extends Color implements Refreshable {
|
||||
@@ -101,11 +102,6 @@ public class GColor extends Color implements Refreshable {
|
||||
return delegate.darker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Color c = delegate;
|
||||
@@ -115,6 +111,19 @@ public class GColor extends Color implements Refreshable {
|
||||
c.getClass().getSimpleName() + rgb + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this color as a hex string that starts with '#'
|
||||
* @return the hex string
|
||||
*/
|
||||
public String toHexString() {
|
||||
return WebColors.toString(this, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
||||
@@ -38,7 +38,7 @@ public class GTableHeader extends JTableHeader {
|
||||
/** This is the cursor used by BasicTableHeaderUI to tell the user they can resize a column */
|
||||
private static final Cursor RESIZE_CURSOR = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
|
||||
|
||||
private static final int HELP_ICON_HEIGHT = 8;
|
||||
public static final int HELP_ICON_HEIGHT = 8;
|
||||
private static final Icon HELP_ICON = ResourceManager.getScaledIcon(
|
||||
ResourceManager.loadImage("images/info_small.png"), HELP_ICON_HEIGHT, HELP_ICON_HEIGHT);
|
||||
private static final Icon HELP_HOVERED_ICON =
|
||||
@@ -206,7 +206,7 @@ public class GTableHeader extends JTableHeader {
|
||||
}
|
||||
|
||||
if (columnFilterToolTip != null) {
|
||||
ttBuilder.append("<br><b>Filters: </b");
|
||||
ttBuilder.append("<br><hr width=80%><b>Filters: </b");
|
||||
ttBuilder.append(columnFilterToolTip);
|
||||
|
||||
}
|
||||
@@ -223,12 +223,6 @@ public class GTableHeader extends JTableHeader {
|
||||
if (prefWidth > cellWidth) {
|
||||
return column.getHeaderValue().toString();
|
||||
}
|
||||
if (component instanceof GTableHeaderRenderer) {
|
||||
GTableHeaderRenderer gthr = (GTableHeaderRenderer) component;
|
||||
if (gthr.isTextOccluded()) {
|
||||
return column.getHeaderValue().toString();
|
||||
}
|
||||
}
|
||||
|
||||
// handle the case where the user has specifically added a tooltip string
|
||||
if (component instanceof JComponent) {
|
||||
|
||||
+148
-201
@@ -17,103 +17,149 @@ package docking.widgets.table;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.text.AttributedString;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.table.*;
|
||||
|
||||
import docking.theme.GColor;
|
||||
import docking.widgets.label.GDLabel;
|
||||
import resources.*;
|
||||
import resources.icons.EmptyIcon;
|
||||
import resources.icons.TranslateIcon;
|
||||
|
||||
/**
|
||||
* The header renderer for GhidraTable.
|
||||
* If the table model implements <code>SortedTableModel</code>, then
|
||||
* an icon will be displayed in the header of the currently sorted
|
||||
* column representing ascending and descending order.
|
||||
*/
|
||||
public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
|
||||
public class GTableHeaderRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
private static final Color SORT_NUMBER_FG_COLOR = new GColor("color.fg");
|
||||
|
||||
private static final int PADDING_FOR_COLUMN_NUMBER = 10;
|
||||
//@formatter:off
|
||||
public static final Color GRADIENT_START_COLOR = new GColor("color.bg.tableheader.gradient.start");
|
||||
public static final Color GRADIENT_END_COLOR = new GColor("color.bg.tableheader.gradient.end");
|
||||
public static final Color GRADIENT_START_PRIMARY_COLOR = new GColor("color.bg.tableheader.gradient.start.primary");
|
||||
public static final Color GRADIENT_END_PRIMARY_COLOR= new GColor("color.bg.tableheader.gradient.end.primary");
|
||||
//@formatter:on
|
||||
|
||||
// static {
|
||||
// Gui.registerAltColor(GThemeDefaults.DARK, GRADIENT_START_ID, new Color(20, 20, 20));
|
||||
// Gui.registerAltColor(GThemeDefaults.DARK, GRADIENT_END_ID, new Color(40, 40, 40));
|
||||
// }
|
||||
|
||||
private static final Icon UP_ICON =
|
||||
ResourceManager.getScaledIcon(Icons.SORT_ASCENDING_ICON, 14, 14);
|
||||
private static final Icon DOWN_ICON =
|
||||
ResourceManager.getScaledIcon(Icons.SORT_DESCENDING_ICON, 14, 14);
|
||||
private static final int DEFAULT_MIN_HEIGHT = UP_ICON.getIconHeight();
|
||||
|
||||
private static final Icon EMPTY_ICON = new EmptyIcon(0, 0);
|
||||
private static final Icon FILTER_ICON =
|
||||
ResourceManager.getScaledIcon(ResourceManager.loadImage("images/filter_off.png"), 12, 12);
|
||||
|
||||
private JLabel textLabel = new GDLabel();
|
||||
private JLabel iconLabel = new GDLabel();
|
||||
private Icon helpIcon = null;
|
||||
private CustomPaddingBorder customBorder;
|
||||
private Icon primaryIcon = EMPTY_ICON;
|
||||
private Icon helpIcon = EMPTY_ICON;
|
||||
protected boolean isPaintingPrimarySortColumn;
|
||||
|
||||
public GTableHeaderRenderer() {
|
||||
super();
|
||||
private TableCellRenderer delegate;
|
||||
|
||||
textLabel.setHorizontalTextPosition(SwingConstants.LEFT);
|
||||
iconLabel.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
|
||||
textLabel.setBorder(createOSSpecificBorder());
|
||||
JTableHeader header = table.getTableHeader();
|
||||
delegate = header.getDefaultRenderer();
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(textLabel, BorderLayout.CENTER);
|
||||
add(iconLabel, BorderLayout.EAST);
|
||||
Component rendererComponent =
|
||||
delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
|
||||
// controls spacing on multiple platforms
|
||||
customBorder = new CustomPaddingBorder();
|
||||
setBorder(customBorder);
|
||||
int modelIndex = table.convertColumnIndexToModel(column);
|
||||
TableModel model = table.getModel();
|
||||
VariableColumnTableModel variableModel = VariableColumnTableModel.from(model);
|
||||
if (variableModel != null) {
|
||||
String text = variableModel.getColumnDisplayName(modelIndex);
|
||||
if (rendererComponent instanceof JLabel) {
|
||||
((JLabel) rendererComponent).setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
primaryIcon = getIcon(model, modelIndex);
|
||||
helpIcon = getHelpIcon(table, column);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
// overridden to paint our help icon over the other components
|
||||
protected void paintChildren(Graphics g) {
|
||||
super.paintChildren(g);
|
||||
paintHelpIcon(g);
|
||||
public void setBounds(int x, int y, int w, int h) {
|
||||
super.setBounds(x, y, w, h);
|
||||
((Component) delegate).setBounds(x, y, w, h);
|
||||
}
|
||||
|
||||
private void paintHelpIcon(Graphics g) {
|
||||
if (helpIcon == null) {
|
||||
return;
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
|
||||
JLabel label = (JLabel) delegate;
|
||||
String text = label.getText();
|
||||
String clippedText = checkForClipping(label, text);
|
||||
if (!text.equals(clippedText)) {
|
||||
label.setText(clippedText);
|
||||
}
|
||||
|
||||
Point paintPoint = getHelpIconLocation();
|
||||
helpIcon.paintIcon(this, g, paintPoint.x, paintPoint.y);
|
||||
label.paint(g);
|
||||
|
||||
// paint our items after the delegate call so that we paint on top
|
||||
super.paint(g);
|
||||
}
|
||||
|
||||
private String checkForClipping(JLabel label, String text) {
|
||||
|
||||
Point helpPoint = getHelpIconLocation();
|
||||
int padding = 10;
|
||||
int iconStartX = helpPoint.x - primaryIcon.getIconWidth() - padding;
|
||||
|
||||
FontMetrics metrics = label.getFontMetrics(label.getFont());
|
||||
int horizontalAlignment = label.getHorizontalAlignment();
|
||||
Rectangle bounds = label.getBounds();
|
||||
int availableWidth = iconStartX + primaryIcon.getIconWidth();
|
||||
if (horizontalAlignment == CENTER) {
|
||||
availableWidth = iconStartX - padding;
|
||||
}
|
||||
|
||||
String clippedText = SwingUtilities.layoutCompoundLabel(
|
||||
label,
|
||||
metrics,
|
||||
text,
|
||||
primaryIcon,
|
||||
label.getVerticalAlignment(),
|
||||
label.getHorizontalAlignment(),
|
||||
label.getVerticalTextPosition(),
|
||||
label.getHorizontalTextPosition(),
|
||||
new Rectangle(0, 0, availableWidth, bounds.height),
|
||||
new Rectangle(iconStartX, 0, primaryIcon.getIconWidth(), bounds.height),
|
||||
new Rectangle(0, 0, iconStartX, bounds.height),
|
||||
label.getIconTextGap());
|
||||
return clippedText;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintChildren(Graphics g) {
|
||||
|
||||
// The help icon paints at the end of the cell; place the main icon to the left of that
|
||||
Point helpPoint = getHelpIconLocation();
|
||||
int offset = 4;
|
||||
int x = helpPoint.x - primaryIcon.getIconWidth() - offset;
|
||||
int y = getIconStartY(primaryIcon.getIconHeight());
|
||||
primaryIcon.paintIcon(this, g, x, y);
|
||||
|
||||
helpIcon.paintIcon(this, g, helpPoint.x, helpPoint.y);
|
||||
}
|
||||
|
||||
private Point getHelpIconLocation() {
|
||||
|
||||
int right = getWidth();
|
||||
int offset = 2;
|
||||
int helpIconWidth = GTableHeader.HELP_ICON_HEIGHT;
|
||||
|
||||
// we want the icon on the right-hand size of the header, at the top
|
||||
int primaryWidth = iconLabel.getWidth();
|
||||
int overlayWidth = helpIcon.getIconWidth();
|
||||
|
||||
// this point is relative to the iconLabel...
|
||||
Point paintPoint = new Point(primaryWidth - overlayWidth, 0);
|
||||
|
||||
// ...make the point relative to the parent (this renderer)
|
||||
return SwingUtilities.convertPoint(iconLabel, paintPoint, this);
|
||||
int x = right - helpIconWidth - offset;
|
||||
int y = offset; // down a bit
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
// overridden to enforce a minimum height for the icon we use
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension preferredSize = super.getPreferredSize();
|
||||
if (delegate != null) {
|
||||
return ((Component) delegate).getPreferredSize();
|
||||
}
|
||||
|
||||
Border currentBorder = getBorder();
|
||||
int minHeight = DEFAULT_MIN_HEIGHT;
|
||||
if (currentBorder != null) {
|
||||
@@ -124,47 +170,19 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
|
||||
return preferredSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
|
||||
boolean hasFocus, int row, int column) {
|
||||
|
||||
isPaintingPrimarySortColumn = false; // reset
|
||||
Icon icon = null;
|
||||
String text = (value == null) ? "" : value.toString();
|
||||
|
||||
JTableHeader header = table.getTableHeader();
|
||||
setForeground(header.getForeground());
|
||||
setFont(header.getFont());
|
||||
|
||||
// remap the column index to the models column index
|
||||
int modelIndex = table.convertColumnIndexToModel(column);
|
||||
TableModel model = table.getModel();
|
||||
|
||||
icon = getIcon(model, modelIndex);
|
||||
|
||||
VariableColumnTableModel variableModel = VariableColumnTableModel.from(model);
|
||||
if (variableModel != null) {
|
||||
text = variableModel.getColumnDisplayName(modelIndex);
|
||||
}
|
||||
updateHelpIcon(table, column, icon);
|
||||
iconLabel.setIcon(icon);
|
||||
textLabel.setText(text);
|
||||
|
||||
setOuterBorder(customBorder, column);
|
||||
|
||||
setOpaque(false);
|
||||
return this;
|
||||
}
|
||||
|
||||
private Icon getIcon(TableModel model, int columnModelIndex) {
|
||||
Icon icon = null;
|
||||
if (model instanceof SortedTableModel) {
|
||||
icon = getSortIcon(icon, columnModelIndex, model);
|
||||
}
|
||||
if (isColumnFiltered(model, columnModelIndex)) {
|
||||
icon = combineIcons(icon, FILTER_ICON);
|
||||
icon = combineIcons(FILTER_ICON, icon);
|
||||
}
|
||||
return icon;
|
||||
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
return EMPTY_ICON;
|
||||
}
|
||||
|
||||
private Icon combineIcons(Icon icon1, Icon icon2) {
|
||||
@@ -174,9 +192,16 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
|
||||
if (icon2 == null) {
|
||||
return icon1;
|
||||
}
|
||||
MultiIcon icon = new MultiIcon(new EmptyIcon(28, 14));
|
||||
icon.addIcon(icon2);
|
||||
icon.addIcon(new TranslateIcon(icon1, 14, 0));
|
||||
|
||||
int padding = 2;
|
||||
int w1 = icon1.getIconWidth();
|
||||
int w2 = icon2.getIconWidth();
|
||||
int h1 = icon1.getIconHeight();
|
||||
int fullWidth = w1 + padding + w2;
|
||||
MultiIcon icon = new MultiIcon(new EmptyIcon(fullWidth, h1));
|
||||
icon.addIcon(icon1);
|
||||
int rightShift = w1 + padding;
|
||||
icon.addIcon(new TranslateIcon(icon2, rightShift, 0));
|
||||
return icon;
|
||||
}
|
||||
|
||||
@@ -192,66 +217,26 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
|
||||
return tableFilter.hasColumnFilter(columnModelIndex);
|
||||
}
|
||||
|
||||
private void setOuterBorder(CustomPaddingBorder border, int column) {
|
||||
if (paintAquaHeaders()) {
|
||||
if (column == 0) {
|
||||
customBorder.setOuterBorder(new NoSidesLineBorder(Color.GRAY));
|
||||
return;
|
||||
}
|
||||
customBorder.setOuterBorder(new NoRightSideLineBorder(Color.GRAY));
|
||||
}
|
||||
else {
|
||||
customBorder.setOuterBorder(UIManager.getBorder("TableHeader.cellBorder"));
|
||||
}
|
||||
}
|
||||
private Icon getHelpIcon(JTable table, int currentColumnIndex) {
|
||||
|
||||
private boolean paintAquaHeaders() {
|
||||
return true;
|
||||
// For now we always use the custom --it actually makes the various LaFs look nicer
|
||||
// return DockingWindowsLookAndFeelUtils.isUsingAquaUI(getUI());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
|
||||
Paint backgroundColor = getBackgroundPaint();
|
||||
Paint oldPaint = g2d.getPaint();
|
||||
|
||||
g2d.setPaint(backgroundColor);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
|
||||
g2d.setPaint(oldPaint);
|
||||
super.paintComponent(g);
|
||||
}
|
||||
|
||||
protected Paint getBackgroundPaint() {
|
||||
Color startColor =
|
||||
isPaintingPrimarySortColumn ? GRADIENT_START_PRIMARY_COLOR : GRADIENT_START_COLOR;
|
||||
Color endColor =
|
||||
isPaintingPrimarySortColumn ? GRADIENT_END_PRIMARY_COLOR : GRADIENT_END_COLOR;
|
||||
|
||||
return new GradientPaint(0, 0, startColor, 0, getHeight() - 11, endColor, true);
|
||||
}
|
||||
|
||||
private void updateHelpIcon(JTable table, int currentColumnIndex, Icon icon) {
|
||||
JTableHeader tableHeader = table.getTableHeader();
|
||||
if (!(tableHeader instanceof GTableHeader)) {
|
||||
helpIcon = null;
|
||||
return;
|
||||
return EMPTY_ICON;
|
||||
}
|
||||
|
||||
GTableHeader tooltipTableHeader = (GTableHeader) tableHeader;
|
||||
int hoveredColumnIndex = tooltipTableHeader.getHoveredHeaderColumnIndex();
|
||||
if (hoveredColumnIndex != currentColumnIndex) {
|
||||
helpIcon = null;
|
||||
return;
|
||||
return EMPTY_ICON;
|
||||
}
|
||||
|
||||
helpIcon = tooltipTableHeader.getHelpIcon();
|
||||
Icon icon = tooltipTableHeader.getHelpIcon();
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
return EMPTY_ICON;
|
||||
}
|
||||
|
||||
// checked before this method is called
|
||||
private Icon getSortIcon(Icon icon, int realIndex, TableModel model) {
|
||||
SortedTableModel sortedModel = (SortedTableModel) model;
|
||||
TableSortState columnSortStates = sortedModel.getTableSortState();
|
||||
@@ -311,75 +296,36 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if sorted in ascending order, false if descending.
|
||||
* @return true if sorted in ascending order, false if descending
|
||||
*/
|
||||
public boolean isSortedAscending() {
|
||||
return iconLabel.getIcon() == UP_ICON;
|
||||
}
|
||||
private int getIconStartY(int iconHeight) {
|
||||
|
||||
boolean isTextOccluded() {
|
||||
return textLabel.getPreferredSize().getWidth() > textLabel.getWidth();
|
||||
}
|
||||
|
||||
private Border createOSSpecificBorder() {
|
||||
if (paintAquaHeaders()) {
|
||||
return new EmptyBorder(1, 2, 1, 2);
|
||||
}
|
||||
return new EmptyBorder(0, 2, 0, 2);
|
||||
int height = getHeight();
|
||||
int middle = height / 2;
|
||||
int halfHeight = iconHeight / 2;
|
||||
int y = middle - halfHeight;
|
||||
return y;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
private class CustomPaddingBorder extends CompoundBorder {
|
||||
private CustomPaddingBorder() {
|
||||
insideBorder = createOSSpecificBorder();
|
||||
}
|
||||
|
||||
void setOuterBorder(Border border) {
|
||||
outsideBorder = border;
|
||||
}
|
||||
}
|
||||
|
||||
private class NoRightSideLineBorder extends LineBorder {
|
||||
NoRightSideLineBorder(Color color) {
|
||||
super(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
|
||||
// take advantage of our clipping by telling our parent to paint at a point that will
|
||||
// be clipped
|
||||
super.paintBorder(c, g, x, y, width + 1, height);
|
||||
}
|
||||
}
|
||||
|
||||
private class NoSidesLineBorder extends LineBorder {
|
||||
NoSidesLineBorder(Color color) {
|
||||
super(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
|
||||
// take advantage of our clipping by telling our parent to paint at a point that will
|
||||
// be clipped
|
||||
super.paintBorder(c, g, x - 1, y, width + 5, height);
|
||||
}
|
||||
}
|
||||
|
||||
private class NumberPainterIcon implements Icon {
|
||||
|
||||
private final int iconWidth;
|
||||
private int numberWidth;
|
||||
private final int iconHeight;
|
||||
private final String numberText;
|
||||
|
||||
public NumberPainterIcon(int width, int height, String numberText) {
|
||||
iconWidth = width;
|
||||
iconHeight = height;
|
||||
this.iconWidth = width;
|
||||
this.iconHeight = height;
|
||||
this.numberText = numberText;
|
||||
|
||||
int fontSize = 12;
|
||||
String fontFamily = "arial";
|
||||
Font font = new Font(fontFamily, Font.BOLD, fontSize);
|
||||
FontMetrics fontMetrics = getFontMetrics(font);
|
||||
numberWidth = fontMetrics.stringWidth(numberText);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -389,35 +335,36 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return iconWidth;
|
||||
return iconWidth + numberWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
|
||||
int fontSize = 12;
|
||||
String fontFamily = "arial";
|
||||
Font font = new Font(fontFamily, Font.BOLD, fontSize);
|
||||
g.setFont(font);
|
||||
FontMetrics fontMetrics = g.getFontMetrics();
|
||||
Rectangle2D stringBounds = fontMetrics.getStringBounds(numberText, g);
|
||||
int numberWidth = (int) stringBounds.getWidth();
|
||||
int numberHeight = fontMetrics.getAscent();
|
||||
|
||||
int insetPadding = 2;
|
||||
int padding = 2;
|
||||
|
||||
// draw the number on the right...
|
||||
int startX = x + (iconWidth - numberWidth) - insetPadding;
|
||||
int startX = x + (iconWidth - numberWidth) + padding;
|
||||
|
||||
// ...and in the upper portion
|
||||
int textBaseline = numberHeight;
|
||||
// ...and at the same start y as the sort icon
|
||||
int iconY = getIconStartY(iconHeight);
|
||||
int textBaseline = iconY + numberHeight - padding;
|
||||
|
||||
AttributedString as = new AttributedString(numberText);
|
||||
as.addAttribute(TextAttribute.FOREGROUND, Color.BLACK);
|
||||
as.addAttribute(TextAttribute.FOREGROUND, SORT_NUMBER_FG_COLOR);
|
||||
as.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
|
||||
as.addAttribute(TextAttribute.FAMILY, fontFamily);
|
||||
as.addAttribute(TextAttribute.SIZE, (float) fontSize);
|
||||
|
||||
g.drawString(as.getIterator(), startX, textBaseline);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-3
@@ -20,6 +20,8 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import docking.theme.GColor;
|
||||
import docking.theme.GThemeDefaults.Colors.Palette;
|
||||
import docking.widgets.table.*;
|
||||
import docking.widgets.table.constraint.ColumnConstraint;
|
||||
import docking.widgets.table.constraint.TableFilterContext;
|
||||
@@ -230,16 +232,19 @@ public class ColumnBasedTableFilter<R> implements TableFilter<R> {
|
||||
//
|
||||
private String getHtmlRepresentation(List<ColumnConstraintSet<R, ?>> filters) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<table valign=top cellspacing=5 cellpadding=0 >");
|
||||
buf.append("<table valign=top cellspacing=5 cellpadding=0>");
|
||||
buf.append("<tr>");
|
||||
// The first row has an empty first column
|
||||
// so that additional rows can display an "AND"
|
||||
buf.append("<td></td><td>");
|
||||
buf.append(filters.get(0).getHtmlRepresentation());
|
||||
buf.append("</td></tr>");
|
||||
GColor gray = Palette.GRAY;
|
||||
String grayHex = gray.toHexString();
|
||||
for (int i = 1; i < filters.size(); i++) {
|
||||
buf.append("<tr><td style=\"color:gray\"> " + filters.get(i).getLogicOperation() +
|
||||
" </td><td>");
|
||||
buf.append("<tr><td style=\"color:").append(grayHex).append("\"> ");
|
||||
buf.append(filters.get(i).getLogicOperation());
|
||||
buf.append(" </td><td>");
|
||||
buf.append(filters.get(i).getHtmlRepresentation());
|
||||
buf.append("</td></tr>");
|
||||
}
|
||||
|
||||
+23
-16
@@ -19,6 +19,8 @@ import java.util.*;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import docking.theme.GColor;
|
||||
import docking.theme.GThemeDefaults.Colors.Palette;
|
||||
import docking.widgets.table.DiscoverableTableUtils;
|
||||
import docking.widgets.table.RowObjectTableModel;
|
||||
import docking.widgets.table.constraint.*;
|
||||
@@ -178,25 +180,30 @@ public class ColumnConstraintSet<R, T> {
|
||||
* Returns an HTML representation of this constraint set in a tabular form. It will be used
|
||||
* inside the HTML representation of the entire filter. See {@link ColumnBasedTableFilter#getHtmlRepresentation()}
|
||||
* for a description of the table format.
|
||||
* @return the html
|
||||
*/
|
||||
String getHtmlRepresentation() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("<table valign=top cellpadding=0 cellspacing=0>");
|
||||
builder.append("<tr><td style=\"color:#990099\">");
|
||||
builder.append(model.getColumnName(columnIndex));
|
||||
builder.append(" ");
|
||||
builder.append("</td>");
|
||||
builder.append("<td>");
|
||||
builder.append(getHtmlRepresentation(constraints.get(0)));
|
||||
builder.append("<td></tr>");
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<table valign=top cellpadding=0 cellspacing=0>");
|
||||
buf.append("<tr><td style=\"font-weight:bold\">");
|
||||
buf.append(model.getColumnName(columnIndex));
|
||||
buf.append(" ");
|
||||
buf.append("</td>");
|
||||
buf.append("<td>");
|
||||
buf.append(getHtmlRepresentation(constraints.get(0)));
|
||||
buf.append("<td></tr>");
|
||||
|
||||
GColor gray = Palette.GRAY;
|
||||
String grayHex = gray.toHexString();
|
||||
for (int i = 1; i < constraints.size(); i++) {
|
||||
builder.append("<tr><td style=\"color:gray;text-align:center\">or</td>");
|
||||
builder.append("<td >");
|
||||
builder.append(getHtmlRepresentation(constraints.get(i)));
|
||||
builder.append("</td></tr>");
|
||||
buf.append("<tr><td style=\"color:").append(grayHex);
|
||||
buf.append("; text-align:center\">or</td>");
|
||||
buf.append("<td >");
|
||||
buf.append(getHtmlRepresentation(constraints.get(i)));
|
||||
buf.append("</td></tr>");
|
||||
}
|
||||
builder.append("</table>");
|
||||
return builder.toString();
|
||||
buf.append("</table>");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String getHtmlRepresentation(ColumnConstraint<?> columnConstraint) {
|
||||
@@ -209,7 +216,7 @@ public class ColumnConstraintSet<R, T> {
|
||||
if (quoteValue) {
|
||||
buf.append("\"");
|
||||
}
|
||||
buf.append("<span style=\"color: blue\">");
|
||||
buf.append("<span style=\"font-weight:bold\">");
|
||||
buf.append(columnConstraint.getConstraintValueString());
|
||||
buf.append("</span>");
|
||||
if (quoteValue) {
|
||||
|
||||
@@ -141,17 +141,6 @@ public class HTMLUtilities {
|
||||
public static String HTML_SPACE = " ";
|
||||
public static String HTML_NEW_LINE = BR;
|
||||
|
||||
public static final String MAROON = "#990000";
|
||||
public static final String GREEN = "#009900";
|
||||
public static final String BLUE = "#000099";
|
||||
public static final String PURPLE = "#990099";
|
||||
public static final String DARK_CYAN = "#009999";
|
||||
public static final String OLIVE = "#999900";
|
||||
public static final String ORANGE = "#FF9900";
|
||||
public static final String PINK = "#FF9999";
|
||||
public static final String YELLOW = "#FFFF00";
|
||||
public static final String GRAY = "#888888";
|
||||
|
||||
/**
|
||||
* Marks the given text as HTML in order to be rendered thusly by Java widgets.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user