* UI: added cell hints to player's list in lobby, fixed header hints;

This commit is contained in:
Oleg Agafonov 2019-01-21 01:10:01 +04:00
parent dd5856e02c
commit 91a3328907
6 changed files with 217 additions and 163 deletions

View file

@ -0,0 +1,41 @@
package mage.client.table;
/**
* @author JayDi85
*/
public class ColumnInfo {
private Integer index;
private Integer width;
private String headerName;
private String headerHint;
private Class colClass;
public ColumnInfo(Integer index, Integer width, Class colClass, String headerName, String headerHint) {
this.index = index;
this.width = width;
this.colClass = colClass;
this.headerName = headerName;
this.headerHint = headerHint;
}
public Integer getIndex() {
return index;
}
public Integer getWidth() {
return width;
}
public String getHeaderName() {
return headerName;
}
public String getHeaderHint() {
return headerHint;
}
public Class getColClass() {
return colClass;
}
}

View file

@ -0,0 +1,57 @@
package mage.client.table;
import mage.client.util.GUISizeHelper;
import javax.swing.*;
import javax.swing.table.JTableHeader;
import java.awt.event.MouseEvent;
/**
* @author JayDi85
*/
public class MageTable extends JTable {
private TableInfo tableInfo;
public MageTable(TableInfo tableInfo) {
this.tableInfo = tableInfo;
}
@Override
public String getToolTipText(MouseEvent e) {
// default tooltip for cells
String tip = null;
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
rowIndex = getRowSorter().convertRowIndexToModel(rowIndex);
int colIndex = columnAtPoint(p);
try {
tip = getValueAt(rowIndex, colIndex).toString();
} catch (RuntimeException e1) {
//catch null pointer exception if mouse is over an empty line
}
return GUISizeHelper.textToHtmlWithSize(tip, GUISizeHelper.tableFont);
}
@Override
protected JTableHeader createDefaultTableHeader() {
// default tooltip for headers
return new JTableHeader(columnModel) {
public String getToolTipText(MouseEvent e) {
// html tooltip
java.awt.Point p = e.getPoint();
int index = columnModel.getColumnIndexAtX(p.x);
int realIndex = columnModel.getColumn(index).getModelIndex();
String tip = tableInfo.getColumnByIndex(realIndex).getHeaderHint();
if (tip == null) {
tip = tableInfo.getColumnByIndex(realIndex).getHeaderName();
}
return GUISizeHelper.textToHtmlWithSize(tip, GUISizeHelper.tableFont);
}
};
}
}

View file

@ -1,13 +1,5 @@
/*
* ChatPanel.java
*
* Created on 15-Dec-2009, 11:04:31 PM
*/
package mage.client.table; package mage.client.table;
import mage.client.MageFrame;
import mage.client.chat.ChatPanelBasic; import mage.client.chat.ChatPanelBasic;
import mage.client.util.GUISizeHelper; import mage.client.util.GUISizeHelper;
import mage.client.util.MageTableRowSorter; import mage.client.util.MageTableRowSorter;
@ -16,18 +8,15 @@ import mage.client.util.gui.countryBox.CountryCellRenderer;
import mage.remote.MageRemoteException; import mage.remote.MageRemoteException;
import mage.view.RoomUsersView; import mage.view.RoomUsersView;
import mage.view.UsersView; import mage.view.UsersView;
import net.java.balloontip.utils.ToolTipUtils;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader; import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel; import javax.swing.table.TableColumnModel;
import java.awt.*; import java.awt.*;
import java.awt.event.MouseEvent; import java.util.ArrayList;
import java.awt.event.MouseMotionAdapter; import java.util.Collection;
import java.util.*;
import java.util.List; import java.util.List;
import static mage.client.chat.ChatPanelBasic.CHAT_ALPHA; import static mage.client.chat.ChatPanelBasic.CHAT_ALPHA;
@ -35,20 +24,45 @@ import static mage.client.dialog.PreferencesDialog.KEY_USERS_COLUMNS_ORDER;
import static mage.client.dialog.PreferencesDialog.KEY_USERS_COLUMNS_WIDTH; import static mage.client.dialog.PreferencesDialog.KEY_USERS_COLUMNS_WIDTH;
/** /**
* * @author BetaSteward_at_googlemail.com, nantuko, JayDi85
* @author BetaSteward_at_googlemail.com, nantuko
*/ */
public class PlayersChatPanel extends javax.swing.JPanel { public class PlayersChatPanel extends javax.swing.JPanel {
private final List<String> players = new ArrayList<>(); private final List<String> players = new ArrayList<>();
private final UserTableModel userTableModel; private final UserTableModel userTableModel;
private static final int[] DEFAULT_COLUMNS_WIDTH = {20, 100, 40, 40, 40, 100, 40, 100, 80, 80}; private static final TableInfo tableInfo = new TableInfo()
.addColumn(0, 20, Icon.class, "Flag", null)
.addColumn(1, 100, String.class, "Players",
"<b>User name</b>"
+ "<br>(the number behind the header text is the number of users online)")
.addColumn(2, 40, Integer.class, "Constructed Rating", null)
.addColumn(3, 40, Integer.class, "Limited Rating", null)
.addColumn(4, 40, String.class, "Matches",
"<b>Number of matches the user played so far</b>"
+ "<br>Q = number of matches quit"
+ "<br>I = number of matches lost because of idle timeout"
+ "<br>T = number of matches lost because of match timeout")
.addColumn(5, 100, Integer.class, "MQP",
"<b>Percent-Ratio of matches played related to matches quit</b>"
+ "<br>this calculation does not include tournament matches")
.addColumn(6, 40, String.class, "Tourneys",
"<b>Number of tournaments the user played so far</b>"
+ "<br>D = number of tournaments left during draft phase"
+ "<br>C = number of tournaments left during constructing phase"
+ "<br>R = number of tournaments left during rounds")
.addColumn(7, 100, Integer.class, "TQP",
"<b>Percent-Ratio of tournament matches played related to tournament matches quit</b>"
+ "<br>this calculation does not include non tournament matches")
.addColumn(8, 80, String.class, "Games",
"<b>Current activities of the player</b>"
+ "<BR>the header itself shows the number of currently active games"
+ "<BR>T: = number of games threads "
+ "<BR><i>(that can vary from active games because of sideboarding or crashed games)</i>"
+ "<BR>limt: the maximum of games the server is configured to"
+ "<BR><i>(if the number of started games exceed that limit, the games have to wait"
+ "<BR>until active games end)</i>")
.addColumn(9, 80, String.class, "Ping", null);
/*
* Creates new form ChatPanel
*
*/
public PlayersChatPanel() { public PlayersChatPanel() {
userTableModel = new UserTableModel(); // needs to be set before initComponents(); userTableModel = new UserTableModel(); // needs to be set before initComponents();
@ -60,8 +74,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
jTablePlayers.setRowSorter(new MageTableRowSorter(userTableModel)); jTablePlayers.setRowSorter(new MageTableRowSorter(userTableModel));
setGUISize(); setGUISize();
TableUtil.setColumnWidthAndOrder(jTablePlayers, DEFAULT_COLUMNS_WIDTH, KEY_USERS_COLUMNS_WIDTH, KEY_USERS_COLUMNS_ORDER); TableUtil.setColumnWidthAndOrder(jTablePlayers, tableInfo.getColumnsWidth(), KEY_USERS_COLUMNS_WIDTH, KEY_USERS_COLUMNS_ORDER);
userTableModel.initHeaderTooltips();
jTablePlayers.setDefaultRenderer(Icon.class, new CountryCellRenderer()); jTablePlayers.setDefaultRenderer(Icon.class, new CountryCellRenderer());
@ -122,7 +135,6 @@ public class PlayersChatPanel extends javax.swing.JPanel {
class UserTableModel extends AbstractTableModel { class UserTableModel extends AbstractTableModel {
private final String[] columnNames = new String[]{"Loc", "Players", "Constructed Rating", "Limited Rating", "Matches", "MQP", "Tourneys", "TQP", "Games", "Connection"};
private UsersView[] players = new UsersView[0]; private UsersView[] players = new UsersView[0];
public void loadData(Collection<RoomUsersView> roomUserInfoList) throws MageRemoteException { public void loadData(Collection<RoomUsersView> roomUserInfoList) throws MageRemoteException {
@ -131,9 +143,9 @@ public class PlayersChatPanel extends javax.swing.JPanel {
JTableHeader th = jTablePlayers.getTableHeader(); JTableHeader th = jTablePlayers.getTableHeader();
TableColumnModel tcm = th.getColumnModel(); TableColumnModel tcm = th.getColumnModel();
tcm.getColumn(jTablePlayers.convertColumnIndexToView(1)).setHeaderValue("Players (" + this.players.length + ')'); tcm.getColumn(jTablePlayers.convertColumnIndexToView(tableInfo.getColumnByName("Players").getIndex())).setHeaderValue("Players (" + this.players.length + ')');
tcm.getColumn(jTablePlayers.convertColumnIndexToView(8)).setHeaderValue( tcm.getColumn(jTablePlayers.convertColumnIndexToView(tableInfo.getColumnByName("Games").getIndex())).setHeaderValue("Games "
"Games " + roomUserInfo.getNumberActiveGames() + roomUserInfo.getNumberActiveGames()
+ (roomUserInfo.getNumberActiveGames() != roomUserInfo.getNumberGameThreads() ? " (T:" + roomUserInfo.getNumberGameThreads() : " (") + (roomUserInfo.getNumberActiveGames() != roomUserInfo.getNumberGameThreads() ? " (T:" + roomUserInfo.getNumberGameThreads() : " (")
+ " limit: " + roomUserInfo.getNumberMaxGames() + ')'); + " limit: " + roomUserInfo.getNumberMaxGames() + ')');
th.repaint(); th.repaint();
@ -147,117 +159,44 @@ public class PlayersChatPanel extends javax.swing.JPanel {
@Override @Override
public int getColumnCount() { public int getColumnCount() {
return columnNames.length; return tableInfo.getColumns().size();
} }
@Override @Override
public Object getValueAt(int arg0, int arg1) { public Object getValueAt(int rowIndex, int colIndex) {
switch (arg1) { switch (colIndex) {
case 0: case 0:
return players[arg0].getFlagName(); return players[rowIndex].getFlagName();
case 1: case 1:
return players[arg0].getUserName(); return players[rowIndex].getUserName();
case 2: case 2:
return players[arg0].getConstructedRating(); return players[rowIndex].getConstructedRating();
case 3: case 3:
return players[arg0].getLimitedRating(); return players[rowIndex].getLimitedRating();
case 4: case 4:
return players[arg0].getMatchHistory(); return players[rowIndex].getMatchHistory();
case 5: case 5:
return players[arg0].getMatchQuitRatio(); return players[rowIndex].getMatchQuitRatio();
case 6: case 6:
return players[arg0].getTourneyHistory(); return players[rowIndex].getTourneyHistory();
case 7: case 7:
return players[arg0].getTourneyQuitRatio(); return players[rowIndex].getTourneyQuitRatio();
case 8: case 8:
return players[arg0].getInfoGames(); return players[rowIndex].getInfoGames();
case 9: case 9:
return players[arg0].getInfoPing(); return players[rowIndex].getInfoPing();
} }
return ""; return "";
} }
public void initHeaderTooltips() {
ColumnHeaderToolTips tips = new ColumnHeaderToolTips();
for (int c = 0; c < jTablePlayers.getColumnCount(); c++) {
String tooltipText = "";
switch (c) {
case 0:
tooltipText = "<HTML><b>The flag the user has assigned to his profile</b>"
+ "<br>You can assign the flag in the connect to server dialog window";
break;
case 1:
tooltipText = "<HTML><b>Name of the user</b>"
+ "<br>(the number behind the header text is the number of currently connected users to the server)";
break;
case 2:
tooltipText = "<HTML><b>Constructed player rating</b>";
break;
case 3:
tooltipText = "<HTML><b>Limited player rating</b>";
break;
case 4:
tooltipText = "<HTML><b>Number of matches the user played so far</b>"
+ "<br>Q = number of matches quit"
+ "<br>I = number of matches lost because of idle timeout"
+ "<br>T = number of matches lost because of match timeout";
break;
case 5:
tooltipText = "<HTML><b>Percent-Ratio of matches played related to matches quit</b>"
+ "<br>this calculation does not include tournament matches";
break;
case 6:
tooltipText = "<HTML><b>Number of tournaments the user played so far</b>"
+ "<br>D = number of tournaments left during draft phase"
+ "<br>C = number of tournaments left during constructing phase"
+ "<br>R = number of tournaments left during rounds";
break;
case 7:
tooltipText = "<HTML><b>Percent-Ratio of tournament matches played related to tournament matches quit</b>"
+ "<br>this calculation does not include non tournament matches";
break;
case 8:
tooltipText = "<HTML><b>Current activities of the player</b>"
+ "<BR>the header itself shows the number of currently active games"
+ "<BR>T: = number of games threads "
+ "<BR><i>(that can vary from active games because of sideboarding or crashed games)</i>"
+ "<BR>limt: the maximum of games the server is configured to"
+ "<BR><i>(if the number of started games exceed that limit, the games have to wait"
+ "<BR>until active games end)</i>";
break;
case 9:
tooltipText = "<HTML><b>Latency of the user's connection to the server</b>";
break;
}
tips.setToolTip(c, tooltipText);
}
JTableHeader header = jTablePlayers.getTableHeader();
header.addMouseMotionListener(tips);
}
@Override @Override
public String getColumnName(int columnIndex) { public String getColumnName(int columnIndex) {
String colName = ""; return tableInfo.getColumnByIndex(columnIndex).getHeaderName();
if (columnIndex <= getColumnCount()) {
colName = columnNames[columnIndex];
}
return colName;
} }
@Override @Override
public Class getColumnClass(int columnIndex) { public Class getColumnClass(int columnIndex) {
switch (columnIndex) { return tableInfo.getColumnByIndex(columnIndex).getColClass();
case 0:
return Icon.class;
case 2:
case 3:
case 5:
case 7:
return Integer.class;
default:
return String.class;
}
} }
@Override @Override
@ -279,7 +218,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
jSpinner1 = new javax.swing.JSpinner(); jSpinner1 = new javax.swing.JSpinner();
jSplitPane1 = new javax.swing.JSplitPane(); jSplitPane1 = new javax.swing.JSplitPane();
jScrollPanePlayers = new javax.swing.JScrollPane(); jScrollPanePlayers = new javax.swing.JScrollPane();
jTablePlayers = new javax.swing.JTable(); jTablePlayers = new MageTable(tableInfo);
jTabbedPaneText = new javax.swing.JTabbedPane(); jTabbedPaneText = new javax.swing.JTabbedPane();
jScrollPaneTalk = new mage.client.chat.ChatPanelSeparated(); jScrollPaneTalk = new mage.client.chat.ChatPanelSeparated();
jScrollPaneSystem = new javax.swing.JScrollPane(); jScrollPaneSystem = new javax.swing.JScrollPane();
@ -332,14 +271,14 @@ public class PlayersChatPanel extends javax.swing.JPanel {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE) .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jSplitPane1) .addComponent(jSplitPane1)
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -350,6 +289,7 @@ public class PlayersChatPanel extends javax.swing.JPanel {
this.players.clear(); this.players.clear();
} }
} }
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private mage.client.components.ColorPane colorPaneSystem; private mage.client.components.ColorPane colorPaneSystem;
private javax.swing.JScrollPane jScrollPanePlayers; private javax.swing.JScrollPane jScrollPanePlayers;
@ -358,45 +298,6 @@ public class PlayersChatPanel extends javax.swing.JPanel {
private javax.swing.JSpinner jSpinner1; private javax.swing.JSpinner jSpinner1;
private javax.swing.JSplitPane jSplitPane1; private javax.swing.JSplitPane jSplitPane1;
private javax.swing.JTabbedPane jTabbedPaneText; private javax.swing.JTabbedPane jTabbedPaneText;
private javax.swing.JTable jTablePlayers; private MageTable jTablePlayers;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
static class ColumnHeaderToolTips extends MouseMotionAdapter {
int curCol;
final Map<Integer, String> tips = new HashMap<>();
public void setToolTip(Integer mCol, String tooltip) {
if (tooltip == null) {
tips.remove(mCol);
} else {
tips.put(mCol, tooltip);
}
}
@Override
public void mouseMoved(MouseEvent evt) {
JTableHeader header = (JTableHeader) evt.getSource();
JTable table = header.getTable();
TableColumnModel colModel = table.getColumnModel();
int vColIndex = colModel.getColumnIndexAtX(evt.getX());
TableColumn col = null;
if (vColIndex >= 0) {
col = colModel.getColumn(table.convertColumnIndexToModel(vColIndex));
}
if (table.convertColumnIndexToModel(vColIndex) != curCol) {
if (col != null) {
MageFrame.getInstance().getBalloonTip().setAttachedComponent(header);
JLabel content = new JLabel(tips.get(table.convertColumnIndexToModel(vColIndex)));
content.setFont(GUISizeHelper.balloonTooltipFont);
MageFrame.getInstance().getBalloonTip().setContents(content);
ToolTipUtils.balloonToToolTip(MageFrame.getInstance().getBalloonTip(), 600, 10000);
} else {
MageFrame.getInstance().getBalloonTip().setTextContents("");
}
curCol = table.convertColumnIndexToModel(vColIndex);
}
}
}
} }

View file

@ -0,0 +1,47 @@
package mage.client.table;
import java.util.ArrayList;
import java.util.List;
/**
* @author JayDi85
*/
public class TableInfo {
private List<ColumnInfo> columns = new ArrayList<>();
public TableInfo() {
}
public TableInfo addColumn(Integer index, Integer width, Class colClass, String headerName, String headerHint) {
this.columns.add(new ColumnInfo(index, width, colClass, headerName, headerHint));
return this;
}
public int[] getColumnsWidth() {
return this.columns.stream().mapToInt(ColumnInfo::getIndex).toArray();
}
public List<ColumnInfo> getColumns() {
return this.columns;
}
public ColumnInfo getColumnByIndex(int index) {
for (ColumnInfo col : this.columns) {
if (col.getIndex().equals(index)) {
return col;
}
}
return null;
}
public ColumnInfo getColumnByName(String name) {
for (ColumnInfo col : this.columns) {
if (col.getHeaderName().equals(name)) {
return col;
}
}
return null;
}
}

View file

@ -8,6 +8,7 @@ package mage.client.util;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
import java.util.Locale;
import javax.swing.JMenu; import javax.swing.JMenu;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JPopupMenu; import javax.swing.JPopupMenu;
@ -178,4 +179,11 @@ public final class GUISizeHelper {
} }
} }
} }
public static String textToHtmlWithSize(String text, Font font) {
if (text != null && !text.toLowerCase(Locale.ENGLISH).startsWith("<html>")) {
return "<html><p style=\"font-size: " + font.getSize() + ";\">" + text + "</p>";
}
return text;
}
} }

View file

@ -418,7 +418,7 @@ public final class Main {
File[] files = directory.listFiles( File[] files = directory.listFiles(
(dir, name) -> name.endsWith(".game") (dir, name) -> name.endsWith(".game")
); );
if(files != null) { if (files != null) {
for (File file : files) { for (File file : files) {
file.delete(); file.delete();
} }