GP-1981 - Fixed table header rendering

This commit is contained in:
dragonmacher
2022-07-26 19:24:54 -04:00
committed by ghidragon
parent 5d51845cca
commit cd4ab3a156
7 changed files with 200 additions and 244 deletions
@@ -224,6 +224,10 @@ public class GHelpBroker extends DefaultHelpBroker {
private void initializeUIComponents(Container contentPane) { 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 editor pane can be changed out from under us, such as when the UI is updated when
// the theme changes // the theme changes
Component[] components = contentPane.getComponents(); Component[] components = contentPane.getComponents();
@@ -243,6 +247,7 @@ public class GHelpBroker extends DefaultHelpBroker {
new HelpViewSearcher(jHelp, helpModel); new HelpViewSearcher(jHelp, helpModel);
installActions(jHelp); installActions(jHelp);
initialized = true;
} }
void reload() { void reload() {
@@ -22,6 +22,7 @@ import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel; import java.awt.image.ColorModel;
import java.util.Objects; import java.util.Objects;
import ghidra.util.WebColors;
import ghidra.util.datastruct.WeakStore; import ghidra.util.datastruct.WeakStore;
public class GColor extends Color implements Refreshable { public class GColor extends Color implements Refreshable {
@@ -101,11 +102,6 @@ public class GColor extends Color implements Refreshable {
return delegate.darker(); return delegate.darker();
} }
@Override
public int hashCode() {
return Objects.hash(id, alpha);
}
@Override @Override
public String toString() { public String toString() {
Color c = delegate; Color c = delegate;
@@ -115,6 +111,19 @@ public class GColor extends Color implements Refreshable {
c.getClass().getSimpleName() + rgb + "]"; 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 @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == 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 */ /** 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 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( private static final Icon HELP_ICON = ResourceManager.getScaledIcon(
ResourceManager.loadImage("images/info_small.png"), HELP_ICON_HEIGHT, HELP_ICON_HEIGHT); ResourceManager.loadImage("images/info_small.png"), HELP_ICON_HEIGHT, HELP_ICON_HEIGHT);
private static final Icon HELP_HOVERED_ICON = private static final Icon HELP_HOVERED_ICON =
@@ -206,7 +206,7 @@ public class GTableHeader extends JTableHeader {
} }
if (columnFilterToolTip != null) { if (columnFilterToolTip != null) {
ttBuilder.append("<br><b>Filters: </b"); ttBuilder.append("<br><hr width=80%><b>Filters: </b");
ttBuilder.append(columnFilterToolTip); ttBuilder.append(columnFilterToolTip);
} }
@@ -223,12 +223,6 @@ public class GTableHeader extends JTableHeader {
if (prefWidth > cellWidth) { if (prefWidth > cellWidth) {
return column.getHeaderValue().toString(); 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 // handle the case where the user has specifically added a tooltip string
if (component instanceof JComponent) { if (component instanceof JComponent) {
@@ -17,103 +17,149 @@ package docking.widgets.table;
import java.awt.*; import java.awt.*;
import java.awt.font.TextAttribute; import java.awt.font.TextAttribute;
import java.awt.geom.Rectangle2D;
import java.text.AttributedString; import java.text.AttributedString;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.Border;
import javax.swing.table.*; import javax.swing.table.*;
import docking.theme.GColor; import docking.theme.GColor;
import docking.widgets.label.GDLabel;
import resources.*; import resources.*;
import resources.icons.EmptyIcon; import resources.icons.EmptyIcon;
import resources.icons.TranslateIcon; import resources.icons.TranslateIcon;
/** public class GTableHeaderRenderer extends DefaultTableCellRenderer {
* The header renderer for GhidraTable.
* If the table model implements <code>SortedTableModel</code>, then private static final Color SORT_NUMBER_FG_COLOR = new GColor("color.fg");
* 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 {
private static final int PADDING_FOR_COLUMN_NUMBER = 10; 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 = private static final Icon UP_ICON =
ResourceManager.getScaledIcon(Icons.SORT_ASCENDING_ICON, 14, 14); ResourceManager.getScaledIcon(Icons.SORT_ASCENDING_ICON, 14, 14);
private static final Icon DOWN_ICON = private static final Icon DOWN_ICON =
ResourceManager.getScaledIcon(Icons.SORT_DESCENDING_ICON, 14, 14); ResourceManager.getScaledIcon(Icons.SORT_DESCENDING_ICON, 14, 14);
private static final int DEFAULT_MIN_HEIGHT = UP_ICON.getIconHeight(); 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 = private static final Icon FILTER_ICON =
ResourceManager.getScaledIcon(ResourceManager.loadImage("images/filter_off.png"), 12, 12); ResourceManager.getScaledIcon(ResourceManager.loadImage("images/filter_off.png"), 12, 12);
private JLabel textLabel = new GDLabel(); private Icon primaryIcon = EMPTY_ICON;
private JLabel iconLabel = new GDLabel(); private Icon helpIcon = EMPTY_ICON;
private Icon helpIcon = null;
private CustomPaddingBorder customBorder;
protected boolean isPaintingPrimarySortColumn; protected boolean isPaintingPrimarySortColumn;
public GTableHeaderRenderer() { private TableCellRenderer delegate;
super();
textLabel.setHorizontalTextPosition(SwingConstants.LEFT); @Override
iconLabel.setHorizontalAlignment(SwingConstants.RIGHT); 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()); Component rendererComponent =
add(textLabel, BorderLayout.CENTER); delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
add(iconLabel, BorderLayout.EAST);
// controls spacing on multiple platforms int modelIndex = table.convertColumnIndexToModel(column);
customBorder = new CustomPaddingBorder(); TableModel model = table.getModel();
setBorder(customBorder); 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 @Override
// overridden to paint our help icon over the other components public void setBounds(int x, int y, int w, int h) {
protected void paintChildren(Graphics g) { super.setBounds(x, y, w, h);
super.paintChildren(g); ((Component) delegate).setBounds(x, y, w, h);
paintHelpIcon(g);
} }
private void paintHelpIcon(Graphics g) { @Override
if (helpIcon == null) { public void paint(Graphics g) {
return;
JLabel label = (JLabel) delegate;
String text = label.getText();
String clippedText = checkForClipping(label, text);
if (!text.equals(clippedText)) {
label.setText(clippedText);
} }
Point paintPoint = getHelpIconLocation(); label.paint(g);
helpIcon.paintIcon(this, g, paintPoint.x, paintPoint.y);
// 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() { 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 // we want the icon on the right-hand size of the header, at the top
int primaryWidth = iconLabel.getWidth(); int x = right - helpIconWidth - offset;
int overlayWidth = helpIcon.getIconWidth(); int y = offset; // down a bit
return new Point(x, y);
// 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);
} }
@Override @Override
// overridden to enforce a minimum height for the icon we use // overridden to enforce a minimum height for the icon we use
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize(); Dimension preferredSize = super.getPreferredSize();
if (delegate != null) {
return ((Component) delegate).getPreferredSize();
}
Border currentBorder = getBorder(); Border currentBorder = getBorder();
int minHeight = DEFAULT_MIN_HEIGHT; int minHeight = DEFAULT_MIN_HEIGHT;
if (currentBorder != null) { if (currentBorder != null) {
@@ -124,47 +170,19 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
return preferredSize; 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) { private Icon getIcon(TableModel model, int columnModelIndex) {
Icon icon = null; Icon icon = null;
if (model instanceof SortedTableModel) { if (model instanceof SortedTableModel) {
icon = getSortIcon(icon, columnModelIndex, model); icon = getSortIcon(icon, columnModelIndex, model);
} }
if (isColumnFiltered(model, columnModelIndex)) { 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) { private Icon combineIcons(Icon icon1, Icon icon2) {
@@ -174,9 +192,16 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
if (icon2 == null) { if (icon2 == null) {
return icon1; return icon1;
} }
MultiIcon icon = new MultiIcon(new EmptyIcon(28, 14));
icon.addIcon(icon2); int padding = 2;
icon.addIcon(new TranslateIcon(icon1, 14, 0)); 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; return icon;
} }
@@ -192,66 +217,26 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
return tableFilter.hasColumnFilter(columnModelIndex); return tableFilter.hasColumnFilter(columnModelIndex);
} }
private void setOuterBorder(CustomPaddingBorder border, int column) { private Icon getHelpIcon(JTable table, int currentColumnIndex) {
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 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(); JTableHeader tableHeader = table.getTableHeader();
if (!(tableHeader instanceof GTableHeader)) { if (!(tableHeader instanceof GTableHeader)) {
helpIcon = null; return EMPTY_ICON;
return;
} }
GTableHeader tooltipTableHeader = (GTableHeader) tableHeader; GTableHeader tooltipTableHeader = (GTableHeader) tableHeader;
int hoveredColumnIndex = tooltipTableHeader.getHoveredHeaderColumnIndex(); int hoveredColumnIndex = tooltipTableHeader.getHoveredHeaderColumnIndex();
if (hoveredColumnIndex != currentColumnIndex) { if (hoveredColumnIndex != currentColumnIndex) {
helpIcon = null; return EMPTY_ICON;
return;
} }
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) { private Icon getSortIcon(Icon icon, int realIndex, TableModel model) {
SortedTableModel sortedModel = (SortedTableModel) model; SortedTableModel sortedModel = (SortedTableModel) model;
TableSortState columnSortStates = sortedModel.getTableSortState(); TableSortState columnSortStates = sortedModel.getTableSortState();
@@ -311,75 +296,36 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
return icon; return icon;
} }
/** private int getIconStartY(int iconHeight) {
* 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;
}
boolean isTextOccluded() { int height = getHeight();
return textLabel.getPreferredSize().getWidth() > textLabel.getWidth(); int middle = height / 2;
} int halfHeight = iconHeight / 2;
int y = middle - halfHeight;
private Border createOSSpecificBorder() { return y;
if (paintAquaHeaders()) {
return new EmptyBorder(1, 2, 1, 2);
}
return new EmptyBorder(0, 2, 0, 2);
} }
//================================================================================================== //==================================================================================================
// Inner Classes // 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 class NumberPainterIcon implements Icon {
private final int iconWidth; private final int iconWidth;
private int numberWidth;
private final int iconHeight; private final int iconHeight;
private final String numberText; private final String numberText;
public NumberPainterIcon(int width, int height, String numberText) { public NumberPainterIcon(int width, int height, String numberText) {
iconWidth = width; this.iconWidth = width;
iconHeight = height; this.iconHeight = height;
this.numberText = numberText; 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 @Override
@@ -389,35 +335,36 @@ public class GTableHeaderRenderer extends JPanel implements TableCellRenderer {
@Override @Override
public int getIconWidth() { public int getIconWidth() {
return iconWidth; return iconWidth + numberWidth;
} }
@Override @Override
public void paintIcon(Component c, Graphics g, int x, int y) { public void paintIcon(Component c, Graphics g, int x, int y) {
int fontSize = 12; int fontSize = 12;
String fontFamily = "arial"; String fontFamily = "arial";
Font font = new Font(fontFamily, Font.BOLD, fontSize); Font font = new Font(fontFamily, Font.BOLD, fontSize);
g.setFont(font); g.setFont(font);
FontMetrics fontMetrics = g.getFontMetrics(); FontMetrics fontMetrics = g.getFontMetrics();
Rectangle2D stringBounds = fontMetrics.getStringBounds(numberText, g);
int numberWidth = (int) stringBounds.getWidth();
int numberHeight = fontMetrics.getAscent(); int numberHeight = fontMetrics.getAscent();
int insetPadding = 2; int padding = 2;
// draw the number on the right... // draw the number on the right...
int startX = x + (iconWidth - numberWidth) - insetPadding; int startX = x + (iconWidth - numberWidth) + padding;
// ...and in the upper portion // ...and at the same start y as the sort icon
int textBaseline = numberHeight; int iconY = getIconStartY(iconHeight);
int textBaseline = iconY + numberHeight - padding;
AttributedString as = new AttributedString(numberText); 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.WEIGHT, TextAttribute.WEIGHT_BOLD);
as.addAttribute(TextAttribute.FAMILY, fontFamily); as.addAttribute(TextAttribute.FAMILY, fontFamily);
as.addAttribute(TextAttribute.SIZE, (float) fontSize); as.addAttribute(TextAttribute.SIZE, (float) fontSize);
g.drawString(as.getIterator(), startX, textBaseline); g.drawString(as.getIterator(), startX, textBaseline);
} }
} }
@@ -20,6 +20,8 @@ import java.util.stream.Collectors;
import org.jdom.Element; import org.jdom.Element;
import docking.theme.GColor;
import docking.theme.GThemeDefaults.Colors.Palette;
import docking.widgets.table.*; import docking.widgets.table.*;
import docking.widgets.table.constraint.ColumnConstraint; import docking.widgets.table.constraint.ColumnConstraint;
import docking.widgets.table.constraint.TableFilterContext; import docking.widgets.table.constraint.TableFilterContext;
@@ -230,16 +232,19 @@ public class ColumnBasedTableFilter<R> implements TableFilter<R> {
// //
private String getHtmlRepresentation(List<ColumnConstraintSet<R, ?>> filters) { private String getHtmlRepresentation(List<ColumnConstraintSet<R, ?>> filters) {
StringBuilder buf = new StringBuilder(); 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>"); buf.append("<tr>");
// The first row has an empty first column // The first row has an empty first column
// so that additional rows can display an "AND" // so that additional rows can display an "AND"
buf.append("<td></td><td>"); buf.append("<td></td><td>");
buf.append(filters.get(0).getHtmlRepresentation()); buf.append(filters.get(0).getHtmlRepresentation());
buf.append("</td></tr>"); buf.append("</td></tr>");
GColor gray = Palette.GRAY;
String grayHex = gray.toHexString();
for (int i = 1; i < filters.size(); i++) { for (int i = 1; i < filters.size(); i++) {
buf.append("<tr><td style=\"color:gray\"> " + filters.get(i).getLogicOperation() + buf.append("<tr><td style=\"color:").append(grayHex).append("\"> ");
"&nbsp;</td><td>"); buf.append(filters.get(i).getLogicOperation());
buf.append("&nbsp;</td><td>");
buf.append(filters.get(i).getHtmlRepresentation()); buf.append(filters.get(i).getHtmlRepresentation());
buf.append("</td></tr>"); buf.append("</td></tr>");
} }
@@ -19,6 +19,8 @@ import java.util.*;
import org.apache.commons.collections4.CollectionUtils; 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.DiscoverableTableUtils;
import docking.widgets.table.RowObjectTableModel; import docking.widgets.table.RowObjectTableModel;
import docking.widgets.table.constraint.*; 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 * 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()} * inside the HTML representation of the entire filter. See {@link ColumnBasedTableFilter#getHtmlRepresentation()}
* for a description of the table format. * for a description of the table format.
* @return the html
*/ */
String getHtmlRepresentation() { String getHtmlRepresentation() {
StringBuilder builder = new StringBuilder(); StringBuilder buf = new StringBuilder();
builder.append("<table valign=top cellpadding=0 cellspacing=0>"); buf.append("<table valign=top cellpadding=0 cellspacing=0>");
builder.append("<tr><td style=\"color:#990099\">"); buf.append("<tr><td style=\"font-weight:bold\">");
builder.append(model.getColumnName(columnIndex)); buf.append(model.getColumnName(columnIndex));
builder.append("&nbsp;"); buf.append("&nbsp;");
builder.append("</td>"); buf.append("</td>");
builder.append("<td>"); buf.append("<td>");
builder.append(getHtmlRepresentation(constraints.get(0))); buf.append(getHtmlRepresentation(constraints.get(0)));
builder.append("<td></tr>"); buf.append("<td></tr>");
GColor gray = Palette.GRAY;
String grayHex = gray.toHexString();
for (int i = 1; i < constraints.size(); i++) { for (int i = 1; i < constraints.size(); i++) {
builder.append("<tr><td style=\"color:gray;text-align:center\">or</td>"); buf.append("<tr><td style=\"color:").append(grayHex);
builder.append("<td >"); buf.append("; text-align:center\">or</td>");
builder.append(getHtmlRepresentation(constraints.get(i))); buf.append("<td >");
builder.append("</td></tr>"); buf.append(getHtmlRepresentation(constraints.get(i)));
buf.append("</td></tr>");
} }
builder.append("</table>"); buf.append("</table>");
return builder.toString(); return buf.toString();
} }
private String getHtmlRepresentation(ColumnConstraint<?> columnConstraint) { private String getHtmlRepresentation(ColumnConstraint<?> columnConstraint) {
@@ -209,7 +216,7 @@ public class ColumnConstraintSet<R, T> {
if (quoteValue) { if (quoteValue) {
buf.append("\""); buf.append("\"");
} }
buf.append("<span style=\"color: blue\">"); buf.append("<span style=\"font-weight:bold\">");
buf.append(columnConstraint.getConstraintValueString()); buf.append(columnConstraint.getConstraintValueString());
buf.append("</span>"); buf.append("</span>");
if (quoteValue) { if (quoteValue) {
@@ -141,17 +141,6 @@ public class HTMLUtilities {
public static String HTML_SPACE = "&nbsp;"; public static String HTML_SPACE = "&nbsp;";
public static String HTML_NEW_LINE = BR; 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. * Marks the given text as HTML in order to be rendered thusly by Java widgets.
* *