Skip to content

Commit f6ec1c9

Browse files
authored
Hovering over deck name in lobby displays comment from .dck file (#10263)
* hover over name in deck selector displays comment from .dck * minor regex cleanup
1 parent 75942bc commit f6ec1c9

2 files changed

Lines changed: 132 additions & 1 deletion

File tree

forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import forge.gui.UiCommand;
2828
import forge.gui.framework.FScreen;
2929
import forge.item.InventoryItem;
30+
import forge.itemmanager.views.DeckNameCommentRenderer;
3031
import forge.itemmanager.views.ItemCellRenderer;
3132
import forge.itemmanager.views.ItemListView;
3233
import forge.itemmanager.views.ItemTableColumn;
@@ -90,11 +91,21 @@ public void setup(final ItemManagerConfig config0) {
9091

9192
Map<ColumnDef, ItemTableColumn> colOverrides = null;
9293
if (config0.getCols().containsKey(ColumnDef.DECK_ACTIONS)) {
94+
colOverrides = new HashMap<>();
9395
final ItemTableColumn column = new ItemTableColumn(new ItemColumn(config0.getCols().get(ColumnDef.DECK_ACTIONS)));
9496
column.setCellRenderer(new DeckActionsRenderer());
95-
colOverrides = new HashMap<>();
9697
colOverrides.put(ColumnDef.DECK_ACTIONS, column);
9798
}
99+
100+
if (config0.getCols().containsKey(ColumnDef.NAME)) {
101+
if (colOverrides == null) {
102+
colOverrides = new HashMap<>();
103+
}
104+
final ItemTableColumn nameColumn = new ItemTableColumn(new ItemColumn(config0.getCols().get(ColumnDef.NAME)));
105+
nameColumn.setCellRenderer(new DeckNameCommentRenderer());
106+
colOverrides.put(ColumnDef.NAME, nameColumn);
107+
}
108+
98109
super.setup(config0, colOverrides);
99110

100111
if (isStringOnly != wasStringOnly) {
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Forge: Play Magic: the Gathering.
3+
* Copyright (C) 2011 Forge Team
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package forge.itemmanager.views;
19+
20+
import java.awt.Component;
21+
import java.util.Map.Entry;
22+
23+
import javax.swing.JLabel;
24+
import javax.swing.JTable;
25+
26+
27+
import org.apache.commons.lang3.StringUtils;
28+
29+
import forge.deck.Deck;
30+
import forge.deck.DeckProxy;
31+
32+
/**
33+
* NAME column renderer for {@link forge.itemmanager.DeckManager}: shows deck display name and
34+
* uses the deck file comment as the cell tooltip when present.
35+
*/
36+
@SuppressWarnings("serial")
37+
public final class DeckNameCommentRenderer extends ItemCellRenderer {
38+
39+
private static final int TOOLTIP_WRAP_WIDTH = 72;
40+
41+
@Override
42+
public Component getTableCellRendererComponent(final JTable table, final Object value,
43+
final boolean isSelected, final boolean hasFocus, final int row, final int column) {
44+
final JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
45+
final DeckProxy proxy = deckProxyFromRow(table, row);
46+
if (proxy == null) {
47+
lbl.setToolTipText(null);
48+
return lbl;
49+
}
50+
final Deck deck = proxy.getDeck();
51+
final String comment = deck != null ? deck.getComment() : null;
52+
final String trimmed = StringUtils.trimToNull(comment);
53+
if (trimmed != null) {
54+
lbl.setToolTipText(toHtmlWrappedTooltip(trimmed));
55+
} else {
56+
lbl.setToolTipText(null);
57+
}
58+
return lbl;
59+
}
60+
61+
private static DeckProxy deckProxyFromRow(final JTable table, final int row) {
62+
if (!(table.getModel() instanceof ItemListView.ItemTableModel)) {
63+
return null;
64+
}
65+
final ItemListView<?>.ItemTableModel tm = (ItemListView<?>.ItemTableModel) table.getModel();
66+
final Entry<?, Integer> entry = tm.rowToItem(row);
67+
if (entry != null && entry.getKey() instanceof DeckProxy) {
68+
return (DeckProxy) entry.getKey();
69+
}
70+
return null;
71+
}
72+
73+
private static String toHtmlWrappedTooltip(final String comment) {
74+
final String[] lines = comment.split("[\r\n]", -1);
75+
final StringBuilder out = new StringBuilder("<html>");
76+
for (int i = 0; i < lines.length; i++) {
77+
if (i > 0) {
78+
out.append("<br/>");
79+
}
80+
appendWrappedEscapedLine(out, lines[i]);
81+
}
82+
out.append("</html>");
83+
return out.toString();
84+
}
85+
86+
private static void appendWrappedEscapedLine(final StringBuilder out, final String line) {
87+
final String escaped = escapeHtml(line);
88+
if (escaped.isEmpty()) {
89+
return;
90+
}
91+
String remaining = escaped;
92+
boolean first = true;
93+
while (remaining.length() > TOOLTIP_WRAP_WIDTH) {
94+
int breakAt = remaining.lastIndexOf(' ', TOOLTIP_WRAP_WIDTH);
95+
if (breakAt <= 0) {
96+
breakAt = TOOLTIP_WRAP_WIDTH;
97+
}
98+
if (!first) {
99+
out.append("<br/>");
100+
}
101+
out.append(remaining, 0, breakAt);
102+
if (breakAt < remaining.length() && remaining.charAt(breakAt) == ' ') {
103+
remaining = remaining.substring(breakAt + 1);
104+
} else {
105+
remaining = remaining.substring(breakAt);
106+
}
107+
first = false;
108+
}
109+
if (!remaining.isEmpty()) {
110+
if (!first) {
111+
out.append("<br/>");
112+
}
113+
out.append(remaining);
114+
}
115+
}
116+
117+
private static String escapeHtml(final String s) {
118+
return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;");
119+
}
120+
}

0 commit comments

Comments
 (0)