From 60367ff4ca3c3e8832b2d2db24461b059a67fa62 Mon Sep 17 00:00:00 2001 From: tc-wleite Date: Wed, 13 Sep 2023 13:17:50 -0300 Subject: [PATCH] '#1866: Custom renderer for bookmarks cell in the main table. --- .../java/iped/app/ui/BookmarksManager.java | 6 +- .../java/iped/app/ui/TableCellRenderer.java | 50 +++++- .../ui/bookmarks/BookmarkCellRenderer.java | 155 ++++++++++++++++++ ...rsManager.java => BookmarkColorsUtil.java} | 2 +- .../iped/app/ui/bookmarks/BookmarkIcon.java | 2 +- 5 files changed, 202 insertions(+), 13 deletions(-) create mode 100644 iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkCellRenderer.java rename iped-app/src/main/java/iped/app/ui/bookmarks/{BookmarkColorsManager.java => BookmarkColorsUtil.java} (99%) diff --git a/iped-app/src/main/java/iped/app/ui/BookmarksManager.java b/iped-app/src/main/java/iped/app/ui/BookmarksManager.java index 3184271924..98a6bc2873 100644 --- a/iped-app/src/main/java/iped/app/ui/BookmarksManager.java +++ b/iped-app/src/main/java/iped/app/ui/BookmarksManager.java @@ -73,7 +73,7 @@ import org.slf4j.LoggerFactory; import iped.app.ui.bookmarks.BookmarkAndKey; -import iped.app.ui.bookmarks.BookmarkColorsManager; +import iped.app.ui.bookmarks.BookmarkColorsUtil; import iped.app.ui.bookmarks.BookmarkEditDialog; import iped.app.ui.bookmarks.BookmarkListRenderer; import iped.data.IItem; @@ -448,7 +448,7 @@ public void actionPerformed(final ActionEvent evt) { multiBookmarks.newBookmark(name); multiBookmarks.setBookmarkComment(name, comment); multiBookmarks.setBookmarkColor(name, - BookmarkColorsManager.getInitialColor(multiBookmarks.getUsedColors(), name)); + BookmarkColorsUtil.getInitialColor(multiBookmarks.getUsedColors(), name)); updateList(); } list.clearSelection(); @@ -515,7 +515,7 @@ public void actionPerformed(final ActionEvent evt) { if (newColor != null && !newColor.equals(currentColor)) { multiBookmarks.setBookmarkColor(currentName, newColor); changed = true; - BookmarkColorsManager.storeNameToColor(currentName, newColor); + BookmarkColorsUtil.storeNameToColor(currentName, newColor); } if (changed) { diff --git a/iped-app/src/main/java/iped/app/ui/TableCellRenderer.java b/iped-app/src/main/java/iped/app/ui/TableCellRenderer.java index 52cee31f00..f2b8937133 100644 --- a/iped-app/src/main/java/iped/app/ui/TableCellRenderer.java +++ b/iped-app/src/main/java/iped/app/ui/TableCellRenderer.java @@ -19,6 +19,8 @@ package iped.app.ui; import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.io.IOException; import javax.swing.Icon; @@ -28,6 +30,7 @@ import org.apache.lucene.document.Document; +import iped.app.ui.bookmarks.BookmarkCellRenderer; import iped.app.ui.bookmarks.BookmarkIcon; import iped.data.IItemId; import iped.data.IMultiBookmarks; @@ -37,6 +40,8 @@ public class TableCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; + private boolean customPaint; + private BookmarkCellRenderer bookmarkCellRenderer; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, @@ -48,21 +53,35 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole int col = table.convertColumnIndexToModel(column); TableModel model = table.getModel(); String colName = model.getColumnName(col); + Icon icon = null; String toopTip = null; - if (model instanceof SearchResultTableModel && colName.equalsIgnoreCase(BookmarkIcon.columnName)) { - setText(""); - if (value != null) { + customPaint = false; + + if (model instanceof SearchResultTableModel) { + if (colName.equalsIgnoreCase(ResultTableModel.BOOKMARK_COL)) { String str = (String) value; if (!str.isEmpty()) { - toopTip = str; IMultiBookmarks multiBookmarks = App.get().appCase.getMultiBookmarks(); - icon = BookmarkIcon.getIcon(multiBookmarks, str); + if (bookmarkCellRenderer == null) { + bookmarkCellRenderer = new BookmarkCellRenderer(); + } + bookmarkCellRenderer.setBookmarks(multiBookmarks, str); + customPaint = true; } - } - } else if (model instanceof SearchResultTableModel) { - if (colName.equalsIgnoreCase(IndexItem.NAME) + } else if (colName.equalsIgnoreCase(BookmarkIcon.columnName)) { + setText(""); + if (value != null) { + String str = (String) value; + if (!str.isEmpty()) { + toopTip = str; + IMultiBookmarks multiBookmarks = App.get().appCase.getMultiBookmarks(); + icon = BookmarkIcon.getIcon(multiBookmarks, str); + } + } + + } else if (colName.equalsIgnoreCase(IndexItem.NAME) || colName.equalsIgnoreCase(LocalizedProperties.getLocalizedField(IndexItem.NAME)) || (model instanceof DuplicatesTableModel && (colName.equalsIgnoreCase(IndexItem.PATH) || colName.equalsIgnoreCase(LocalizedProperties.getLocalizedField(IndexItem.PATH))))) { @@ -89,4 +108,19 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole return this; } + + @Override + protected void paintComponent(Graphics g) { + if (customPaint) { + Graphics2D g2 = (Graphics2D) g; + int w = getWidth(); + int h = getHeight(); + g2.setBackground(getBackground()); + g2.clearRect(0, 0, w, h); + g2.setFont(getFont()); + bookmarkCellRenderer.paint(g2, w, h); + } else { + super.paintComponent(g); + } + } } diff --git a/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkCellRenderer.java b/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkCellRenderer.java new file mode 100644 index 0000000000..b25b81e9f9 --- /dev/null +++ b/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkCellRenderer.java @@ -0,0 +1,155 @@ +package iped.app.ui.bookmarks; + +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.RenderingHints.Key; +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.Map; + +import iped.data.IMultiBookmarks; + +public class BookmarkCellRenderer { + private static final RenderingHints renderingHints; + + private String[] names; + private Color[] colors; + private final Map clippedNamesMemo = new HashMap(); + private int maxSpacing; + private String lastStr; + + static { + Map hints = new HashMap(); + hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + hints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); + hints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + hints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); + renderingHints = new RenderingHints(hints); + } + + public void setBookmarks(IMultiBookmarks bookmarks, String str) { + boolean strChanged = false; + if (!str.equals(lastStr)) { + strChanged = true; + if (str.indexOf(" | ") < 0) { + if (names == null || names.length != 1) { + names = new String[] { str }; + } else { + names[0] = str; + } + } else { + names = str.split(" \\| "); + } + lastStr = str; + } + if (colors == null || colors.length < names.length) { + colors = new Color[names.length]; + } + for (int i = 0; i < names.length; i++) { + Color c = bookmarks.getBookmarkColor(names[i]); + colors[i] = c == null ? BookmarkStandardColors.defaultColor : c; + } + if (strChanged) { + maxSpacing = Integer.MAX_VALUE; + clippedNamesMemo.clear(); + } + } + + private synchronized ClippedString[] getClippedNames(FontMetrics fm, Graphics2D g, int w) { + if (w > maxSpacing) { + w = maxSpacing; + } + ClippedString[] cs = clippedNamesMemo.get(w); + if (cs == null) { + cs = new ClippedString[names.length]; + int x = 0; + for (int i = 0; i < names.length; i++) { + String s = names[i].trim(); + Rectangle2D rc = fm.getStringBounds(s, g); + int rw = (int) rc.getWidth() + 6; + cs[i] = new ClippedString(s, rw); + x += rw + 1; + } + x--; + if (x <= w) { + maxSpacing = w = x; + } else { + String el = "..."; + int used = x; + int minW = 8; + while (used > w) { + int idx = -1; + int maxW = minW; + for (int i = 0; i < names.length; i++) { + ClippedString a = cs[i]; + if (a.w > maxW && !a.str.isEmpty()) { + maxW = a.w; + idx = i; + } + } + if (idx == -1) { + break; + } + ClippedString a = cs[idx]; + if (a.str.length() <= 1) { + a.str = ""; + } else if (a.str.endsWith(el)) { + if (a.str.length() <= el.length() + 1) { + a.str = a.str.substring(0, 1).trim(); + } else { + a.str = a.str.substring(0, a.str.length() - 1 - el.length()).trim() + el; + } + } else { + a.str = a.str.substring(0, a.str.length() - 1).trim() + el; + } + if (a.str.isEmpty()) { + a.w = minW; + } else { + Rectangle2D rc = fm.getStringBounds(a.str, g); + int rw = (int) rc.getWidth() + 6; + if (rw < minW) { + rw = minW; + a.str = ""; + } + a.w = rw; + } + used -= maxW - a.w; + } + } + clippedNamesMemo.put(w, cs); + } + return cs; + } + + public void paint(Graphics2D g, int w, int h) { + RenderingHints saveHints = g.getRenderingHints(); + g.setRenderingHints(renderingHints); + FontMetrics fm = g.getFontMetrics(); + ClippedString[] cn = getClippedNames(fm, g, w); + int y = (int) ((h - fm.getHeight()) / 2.0 + fm.getAscent()); + int x = 0; + for (int i = 0; i < cn.length; i++) { + ClippedString cs = cn[i]; + Color c = colors[i]; + g.setColor(c); + g.fillRoundRect(x, 1, cs.w, h - 1, h / 2, h / 2); + g.setColor(BookmarkColorsUtil.getForeground(c)); + g.drawString(cs.str, x + 3, y); + x += cs.w + 1; + } + g.setRenderingHints(saveHints); + } + + private class ClippedString { + String str; + int w; + + ClippedString(String str, int w) { + this.str = str; + this.w = w; + } + } +} diff --git a/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkColorsManager.java b/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkColorsUtil.java similarity index 99% rename from iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkColorsManager.java rename to iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkColorsUtil.java index 34e41d2868..df2774ba58 100644 --- a/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkColorsManager.java +++ b/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkColorsUtil.java @@ -20,7 +20,7 @@ import iped.utils.IOUtil; -public class BookmarkColorsManager { +public class BookmarkColorsUtil { private static final String colorsMemoFile = System.getProperty("user.home") + "/.iped/bkmclr.dat"; private static Map colorsMemo = Collections.synchronizedMap(new LinkedHashMap()); diff --git a/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkIcon.java b/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkIcon.java index 6ee0a87307..0bee4ef486 100644 --- a/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkIcon.java +++ b/iped-app/src/main/java/iped/app/ui/bookmarks/BookmarkIcon.java @@ -96,7 +96,7 @@ private BookmarkIcon(Color color, Boolean checked) { this.color = color; this.colors = null; this.checked = checked; - this.checkedColor = BookmarkColorsManager.getForeground(color); + this.checkedColor = BookmarkColorsUtil.getForeground(color); } @Override