mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
Improve display of chat messages for app
This commit is contained in:
@@ -6,6 +6,7 @@ import java.awt.Rectangle;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
import javax.swing.ScrollPaneConstants;
|
import javax.swing.ScrollPaneConstants;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
@@ -15,6 +16,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.gui.framework.SDisplayUtil;
|
import forge.gui.framework.SDisplayUtil;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
|
import forge.net.ChatMessage;
|
||||||
import forge.net.IOnlineChatInterface;
|
import forge.net.IOnlineChatInterface;
|
||||||
import forge.net.IRemote;
|
import forge.net.IRemote;
|
||||||
import forge.net.event.MessageEvent;
|
import forge.net.event.MessageEvent;
|
||||||
@@ -132,7 +134,7 @@ public enum FNetOverlay implements IOnlineChatInterface {
|
|||||||
public void show() {
|
public void show() {
|
||||||
show(null);
|
show(null);
|
||||||
}
|
}
|
||||||
public void show(final String message) {
|
public void show(final ChatMessage message) {
|
||||||
if (!hasBeenShown) {
|
if (!hasBeenShown) {
|
||||||
hasBeenShown = true;
|
hasBeenShown = true;
|
||||||
loadLocation();
|
loadLocation();
|
||||||
@@ -144,7 +146,7 @@ public enum FNetOverlay implements IOnlineChatInterface {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
txtLog.setText(message);
|
txtLog.setText(message.getFormattedMessage());
|
||||||
}
|
}
|
||||||
window.setVisible(true);
|
window.setVisible(true);
|
||||||
}
|
}
|
||||||
@@ -203,7 +205,7 @@ public enum FNetOverlay implements IOnlineChatInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMessage(final String message) {
|
public void addMessage(final ChatMessage message) {
|
||||||
txtLog.append(message);
|
txtLog.append(message.getFormattedMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import forge.gui.framework.EDocID;
|
|||||||
import forge.gui.framework.ICDoc;
|
import forge.gui.framework.ICDoc;
|
||||||
import forge.menus.IMenuProvider;
|
import forge.menus.IMenuProvider;
|
||||||
import forge.menus.MenuUtil;
|
import forge.menus.MenuUtil;
|
||||||
|
import forge.net.ChatMessage;
|
||||||
import forge.net.NetConnectUtil;
|
import forge.net.NetConnectUtil;
|
||||||
import forge.screens.home.CHomeUI;
|
import forge.screens.home.CHomeUI;
|
||||||
import forge.screens.home.CLobby;
|
import forge.screens.home.CLobby;
|
||||||
@@ -55,7 +56,7 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final String result = NetConnectUtil.host(VSubmenuOnlineLobby.SINGLETON_INSTANCE, FNetOverlay.SINGLETON_INSTANCE);
|
final ChatMessage result = NetConnectUtil.host(VSubmenuOnlineLobby.SINGLETON_INSTANCE, FNetOverlay.SINGLETON_INSTANCE);
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -79,7 +80,7 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final String result = NetConnectUtil.join(url, VSubmenuOnlineLobby.SINGLETON_INSTANCE, FNetOverlay.SINGLETON_INSTANCE);
|
final ChatMessage result = NetConnectUtil.join(url, VSubmenuOnlineLobby.SINGLETON_INSTANCE, FNetOverlay.SINGLETON_INSTANCE);
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
package forge.screens.online;
|
package forge.screens.online;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
|
||||||
|
|
||||||
|
import forge.Graphics;
|
||||||
|
import forge.assets.FSkinColor;
|
||||||
|
import forge.assets.FSkinFont;
|
||||||
|
import forge.assets.TextRenderer;
|
||||||
|
import forge.assets.FSkinColor.Colors;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
|
import forge.net.ChatMessage;
|
||||||
import forge.net.IOnlineChatInterface;
|
import forge.net.IOnlineChatInterface;
|
||||||
import forge.net.IRemote;
|
import forge.net.IRemote;
|
||||||
import forge.net.event.MessageEvent;
|
import forge.net.event.MessageEvent;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.FScreen;
|
import forge.screens.FScreen;
|
||||||
|
import forge.toolbox.FDisplayObject;
|
||||||
import forge.toolbox.FEvent;
|
import forge.toolbox.FEvent;
|
||||||
import forge.toolbox.FEvent.FEventHandler;
|
import forge.toolbox.FEvent.FEventHandler;
|
||||||
import forge.toolbox.FChoiceList;
|
import forge.toolbox.FScrollPane;
|
||||||
import forge.toolbox.FTextField;
|
import forge.toolbox.FTextField;
|
||||||
import forge.util.Utils;
|
import forge.util.Utils;
|
||||||
|
|
||||||
@@ -22,7 +28,7 @@ public class OnlineChatScreen extends FScreen implements IOnlineChatInterface {
|
|||||||
|
|
||||||
private IRemote gameClient;
|
private IRemote gameClient;
|
||||||
private final ForgePreferences prefs = FModel.getPreferences();
|
private final ForgePreferences prefs = FModel.getPreferences();
|
||||||
private final FChoiceList<String> lstLog = add(new FChoiceList<String>(new ArrayList<String>()));
|
private final ChatLog lstLog = add(new ChatLog());
|
||||||
private final FTextField txtSendMessage = add(new FTextField());
|
private final FTextField txtSendMessage = add(new FTextField());
|
||||||
|
|
||||||
public OnlineChatScreen() {
|
public OnlineChatScreen() {
|
||||||
@@ -44,7 +50,11 @@ public class OnlineChatScreen extends FScreen implements IOnlineChatInterface {
|
|||||||
txtSendMessage.setText("");
|
txtSendMessage.setText("");
|
||||||
|
|
||||||
if (gameClient != null) {
|
if (gameClient != null) {
|
||||||
gameClient.send(new MessageEvent(prefs.getPref(FPref.PLAYER_NAME), message));
|
String source = prefs.getPref(FPref.PLAYER_NAME);
|
||||||
|
if (lstLog.getChildCount() % 2 == 1) {
|
||||||
|
source = "RemoteGuy"; //TODO: Remove this
|
||||||
|
}
|
||||||
|
gameClient.send(new MessageEvent(source, message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,9 +75,103 @@ public class OnlineChatScreen extends FScreen implements IOnlineChatInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMessage(String message) {
|
public void addMessage(ChatMessage message) {
|
||||||
lstLog.addItem(message);
|
lstLog.addMessage(message);
|
||||||
lstLog.scrollToBottom();
|
|
||||||
Gdx.graphics.requestRendering();
|
Gdx.graphics.requestRendering();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ChatLog extends FScrollPane {
|
||||||
|
@Override
|
||||||
|
protected ScrollBounds layoutAndGetScrollBounds(float visibleWidth, float visibleHeight) {
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
float inset = 6 * PADDING;
|
||||||
|
float bubbleWidth = visibleWidth - inset;
|
||||||
|
|
||||||
|
for (FDisplayObject obj : getChildren()) {
|
||||||
|
ChatMessageBubble bubble = (ChatMessageBubble)obj;
|
||||||
|
if (bubble.isLocal) { //right-align local messages
|
||||||
|
bubble.setBounds(x + inset, y, bubbleWidth, bubble.getPreferredHeight(bubbleWidth));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bubble.setBounds(x, y, bubbleWidth, bubble.getPreferredHeight(bubbleWidth));
|
||||||
|
}
|
||||||
|
y += bubble.getHeight() + PADDING;
|
||||||
|
}
|
||||||
|
return new ScrollBounds(visibleWidth, y - PADDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMessage(ChatMessage message) {
|
||||||
|
add(new ChatMessageBubble(message));
|
||||||
|
revalidate();
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ChatMessageBubble extends FDisplayObject {
|
||||||
|
private static final FSkinFont FONT = FSkinFont.get(12);
|
||||||
|
private static final FSkinColor LOCAL_COLOR = FSkinColor.get(Colors.CLR_ZEBRA);
|
||||||
|
private static final FSkinColor REMOTE_COLOR = LOCAL_COLOR.getContrastColor(-20);
|
||||||
|
private static final FSkinColor MESSAGE_COLOR = FSkinColor.get(Colors.CLR_TEXT);
|
||||||
|
private static final FSkinColor SOURCE_COLOR = MESSAGE_COLOR.alphaColor(0.75f);
|
||||||
|
private static final FSkinColor TIMESTAMP_COLOR = MESSAGE_COLOR.alphaColor(0.5f);
|
||||||
|
private static final FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS);
|
||||||
|
private static final float BORDER_THICKNESS = Utils.scale(1);
|
||||||
|
private static final float TEXT_INSET = Utils.scale(5);
|
||||||
|
private static final float TRIANGLE_WIDTH = Utils.scale(5);
|
||||||
|
|
||||||
|
private final ChatMessage message;
|
||||||
|
private final boolean isLocal;
|
||||||
|
private final String header;
|
||||||
|
private final TextRenderer textRenderer = new TextRenderer();
|
||||||
|
|
||||||
|
private ChatMessageBubble(ChatMessage message0) {
|
||||||
|
message = message0;
|
||||||
|
isLocal = message.isLocal();
|
||||||
|
if (isLocal || message.getSource() == null) {
|
||||||
|
header = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
header = message.getSource() + ":";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPreferredHeight(float width) {
|
||||||
|
float height = FONT.getCapHeight() + 4 * TEXT_INSET + TRIANGLE_WIDTH;
|
||||||
|
if (header != null) {
|
||||||
|
height += FONT.getLineHeight() + TEXT_INSET;
|
||||||
|
}
|
||||||
|
height += textRenderer.getWrappedBounds(message.getMessage(), FONT, width - 2 * TEXT_INSET).height;
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Graphics g) {
|
||||||
|
float x = isLocal ? 0 : TRIANGLE_WIDTH;
|
||||||
|
float y = TEXT_INSET;
|
||||||
|
float w = getWidth() - TRIANGLE_WIDTH;
|
||||||
|
float h = getHeight() - TEXT_INSET;
|
||||||
|
FSkinColor color = isLocal ? LOCAL_COLOR : REMOTE_COLOR;
|
||||||
|
HAlignment horzAlignment = isLocal ? HAlignment.RIGHT : HAlignment.LEFT;
|
||||||
|
|
||||||
|
g.fillRect(color, x, y, w, h);
|
||||||
|
g.drawRect(BORDER_THICKNESS, BORDER_COLOR, x, y, w, h);
|
||||||
|
|
||||||
|
x += TEXT_INSET;
|
||||||
|
y += TEXT_INSET;
|
||||||
|
w -= 2 * TEXT_INSET;
|
||||||
|
|
||||||
|
if (!isLocal && message.getSource() != null) {
|
||||||
|
float sourceHeight = FONT.getLineHeight();
|
||||||
|
g.drawText(message.getSource() + ":", FONT, SOURCE_COLOR, x, y, w, sourceHeight, false, horzAlignment, true);
|
||||||
|
y += sourceHeight + TEXT_INSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
float timestampHeight = FONT.getCapHeight();
|
||||||
|
g.drawText(message.getTimestamp(), FONT, TIMESTAMP_COLOR, x, h - timestampHeight, w, timestampHeight, false, horzAlignment, true);
|
||||||
|
|
||||||
|
h -= y + timestampHeight + TEXT_INSET;
|
||||||
|
textRenderer.drawText(g, message.getMessage(), FONT, MESSAGE_COLOR, x, y, w, h, y, h, true, horzAlignment, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import forge.FThreads;
|
|||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.interfaces.ILobbyView;
|
import forge.interfaces.ILobbyView;
|
||||||
import forge.match.GameLobby;
|
import forge.match.GameLobby;
|
||||||
|
import forge.net.ChatMessage;
|
||||||
import forge.net.IOnlineChatInterface;
|
import forge.net.IOnlineChatInterface;
|
||||||
import forge.net.IOnlineLobby;
|
import forge.net.IOnlineLobby;
|
||||||
import forge.net.NetConnectUtil;
|
import forge.net.NetConnectUtil;
|
||||||
@@ -51,7 +52,7 @@ public class OnlineLobbyScreen extends LobbyScreen implements IOnlineLobby {
|
|||||||
LoadingOverlay.show(caption, new Runnable() {
|
LoadingOverlay.show(caption, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final String result;
|
final ChatMessage result;
|
||||||
final IOnlineChatInterface chatInterface = (IOnlineChatInterface)OnlineScreen.Chat.getScreen();
|
final IOnlineChatInterface chatInterface = (IOnlineChatInterface)OnlineScreen.Chat.getScreen();
|
||||||
if (joinServer) {
|
if (joinServer) {
|
||||||
result = NetConnectUtil.join(url, OnlineLobbyScreen.this, chatInterface);
|
result = NetConnectUtil.join(url, OnlineLobbyScreen.this, chatInterface);
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ package forge.net;
|
|||||||
|
|
||||||
public interface IOnlineChatInterface {
|
public interface IOnlineChatInterface {
|
||||||
void setGameClient(IRemote iRemote);
|
void setGameClient(IRemote iRemote);
|
||||||
void addMessage(String message);
|
void addMessage(ChatMessage message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package forge.net;
|
package forge.net;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.GuiBase;
|
import forge.GuiBase;
|
||||||
@@ -41,7 +38,7 @@ public class NetConnectUtil {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String host(final IOnlineLobby onlineLobby, final IOnlineChatInterface chatInterface) {
|
public static ChatMessage host(final IOnlineLobby onlineLobby, final IOnlineChatInterface chatInterface) {
|
||||||
final int port = ForgeProfileProperties.getServerPort();
|
final int port = ForgeProfileProperties.getServerPort();
|
||||||
final FServerManager server = FServerManager.getInstance();
|
final FServerManager server = FServerManager.getInstance();
|
||||||
final ServerGameLobby lobby = new ServerGameLobby();
|
final ServerGameLobby lobby = new ServerGameLobby();
|
||||||
@@ -72,7 +69,7 @@ public class NetConnectUtil {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public final void message(final String source, final String message) {
|
public final void message(final String source, final String message) {
|
||||||
chatInterface.addMessage(formatMessage(source, message));
|
chatInterface.addMessage(new ChatMessage(source, message));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public final void close() {
|
public final void close() {
|
||||||
@@ -84,7 +81,7 @@ public class NetConnectUtil {
|
|||||||
public final void send(final NetEvent event) {
|
public final void send(final NetEvent event) {
|
||||||
if (event instanceof MessageEvent) {
|
if (event instanceof MessageEvent) {
|
||||||
final MessageEvent message = (MessageEvent) event;
|
final MessageEvent message = (MessageEvent) event;
|
||||||
chatInterface.addMessage(formatMessage(message.getSource(), message.getMessage()));
|
chatInterface.addMessage(new ChatMessage(message.getSource(), message.getMessage()));
|
||||||
server.broadcast(event);
|
server.broadcast(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +94,7 @@ public class NetConnectUtil {
|
|||||||
|
|
||||||
view.update(true);
|
view.update(true);
|
||||||
|
|
||||||
return String.format("Hosting on port %d.", port);
|
return new ChatMessage(null, String.format("Hosting on port %d.", port));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyHostedServerUrl() {
|
public static void copyHostedServerUrl() {
|
||||||
@@ -107,7 +104,7 @@ public class NetConnectUtil {
|
|||||||
SOptionPane.showMessageDialog("Share the following URL with anyone who wishes to join your server. It has been copied to your clipboard for convenience.\n\n" + url, "Server URL", SOptionPane.INFORMATION_ICON);
|
SOptionPane.showMessageDialog("Share the following URL with anyone who wishes to join your server. It has been copied to your clipboard for convenience.\n\n" + url, "Server URL", SOptionPane.INFORMATION_ICON);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String join(final String url, final IOnlineLobby onlineLobby, final IOnlineChatInterface chatInterface) {
|
public static ChatMessage join(final String url, final IOnlineLobby onlineLobby, final IOnlineChatInterface chatInterface) {
|
||||||
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
||||||
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", gui);
|
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", gui);
|
||||||
onlineLobby.setClient(client);
|
onlineLobby.setClient(client);
|
||||||
@@ -118,7 +115,7 @@ public class NetConnectUtil {
|
|||||||
client.addLobbyListener(new ILobbyListener() {
|
client.addLobbyListener(new ILobbyListener() {
|
||||||
@Override
|
@Override
|
||||||
public final void message(final String source, final String message) {
|
public final void message(final String source, final String message) {
|
||||||
chatInterface.addMessage(formatMessage(source, message));
|
chatInterface.addMessage(new ChatMessage(source, message));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public final void update(final GameLobbyData state, final int slot) {
|
public final void update(final GameLobbyData state, final int slot) {
|
||||||
@@ -154,20 +151,6 @@ public class NetConnectUtil {
|
|||||||
|
|
||||||
client.connect(hostname, port);
|
client.connect(hostname, port);
|
||||||
|
|
||||||
return String.format("Connected to %s:%d", hostname, port);
|
return new ChatMessage(null, String.format("Connected to %s:%d", hostname, port));
|
||||||
}
|
|
||||||
|
|
||||||
private final static SimpleDateFormat inFormat = new SimpleDateFormat("HH:mm:ss");
|
|
||||||
|
|
||||||
public static String formatMessage(final String source, final String message) {
|
|
||||||
final String now = inFormat.format(new Date());
|
|
||||||
final String toAdd;
|
|
||||||
if (source == null) {
|
|
||||||
toAdd = String.format("%n[%s] %s", now, message);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
toAdd = String.format("%n[%s] %s: %s", now, source, message);
|
|
||||||
}
|
|
||||||
return toAdd;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user