GUI: added changeable card popup mode for chats/logs by card name clicks (alternative to mouse wheel from game cards);

other: fixed duplicated chat popups in game, added miss error logs from popup related code, added additional checks for good code usage;
This commit is contained in:
Oleg Agafonov 2023-11-26 12:48:41 +04:00
parent 785f6973b9
commit 4500b79008
12 changed files with 129 additions and 70 deletions

View file

@ -9,8 +9,10 @@ import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.adapters.MageActionCallback;
import mage.client.plugins.impl.Plugins;
import mage.client.util.ClientDefaultSettings;
import mage.utils.SystemUtil;
import mage.view.CardView;
import javax.swing.*;
import java.awt.*;
import java.util.UUID;
@ -24,26 +26,28 @@ import java.util.UUID;
* - call "onMouseEntered" to prepare;
* - call "onMouseMoved" to draw;
* - call "onMouseExited" to hide;
* - call "onMouseWheel" to switch between text and image modes;
* <p>
* Hints:
* - for game GUI: you must init with gameId (otherwise you can't see it)
* - for non-game GUI: no needs in gameId or bigCard (bigCard is a panel with card image)
* - if you want to show card immediately then use init + onMouseEntered + onMouseMoved
* - if you want to switch text/image mode then use onMouseWheel
* <p>
* Auto-location modes:
* - default: popup container will be put inside parent container
* - near mouse: popup container will be put near mouse position (example: popup over chat messages)
* - default: popup container will be put inside parent container (example: popup over cards in game or deck editor)
* - near mouse: popup container will be put near mouse position (example: popup over chat messages or game logs)
*
* @author JayDi85
*/
public class VirtualCardInfo {
CardView cardView;
MageCard cardComponent;
BigCard bigCard;
MageActionCallback actionCallback;
TransferData data = new TransferData();
Dimension cardDimension = null;
int viewMode = 1; // workaround to simulate mouse wheel for switch card view mode (text/image styles)
public VirtualCardInfo() {
super();
@ -103,6 +107,8 @@ public class VirtualCardInfo {
}
public boolean prepared() {
SystemUtil.ensureRunInGUISwingThread();
return this.cardView != null
&& this.cardComponent != null
&& this.actionCallback != null;
@ -117,10 +123,6 @@ public class VirtualCardInfo {
data.setLocationOnScreen(newPoint);
}
public void onMouseEntered() {
onMouseMoved(null);
}
public void onMouseEntered(Point newLocation) {
if (!prepared()) {
return;
@ -145,6 +147,19 @@ public class VirtualCardInfo {
this.actionCallback.mouseMoved(null, this.data);
}
public void onMouseWheel(Point newLocation) {
if (!prepared()) {
return;
}
if (newLocation != null) {
updateLocation(newLocation);
}
this.viewMode = -this.viewMode; // simulate diff mouse wheel moves
this.actionCallback.mouseWheelMoved(this.viewMode, this.data);
}
public void onMouseExited() {
if (!prepared()) {
return;

View file

@ -415,10 +415,6 @@ public class ChatPanelBasic extends javax.swing.JPanel {
}
}
public void enableHyperlinks() {
txtConversation.enableHyperlinksAndCardPopups();
}
private void txtMessageKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtMessageKeyTyped
handleKeyTyped(evt);
}//GEN-LAST:event_txtMessageKeyTyped

View file

@ -21,10 +21,7 @@ import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.*;
/**
* GUI: chats with html and hints popup support for objects
@ -51,7 +48,10 @@ public class ColorPane extends JEditorPane {
}
private void addHyperlinkHandlers() {
addHyperlinkListener(e -> ThreadUtils.threadPool2.submit(() -> {
if (Arrays.stream(getHyperlinkListeners()).findAny().isPresent()) {
throw new IllegalStateException("Wrong code usage: popup links support enabled already");
}
addHyperlinkListener(e -> ThreadUtils.threadPoolPopups.submit(() -> {
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_TOOLTIPS_DELAY, 300) == 0) {
// if disabled
return;
@ -111,13 +111,23 @@ public class ColorPane extends JEditorPane {
cardInfo.init(cardView, this.bigCard, this.gameId);
cardInfo.setTooltipDelay(CHAT_TOOLTIP_DELAY_MS);
cardInfo.setPopupAutoLocationMode(TransferData.PopupAutoLocationMode.PUT_NEAR_MOUSE_POSITION);
cardInfo.onMouseEntered(MouseInfo.getPointerInfo().getLocation());
cardInfo.onMouseMoved(MouseInfo.getPointerInfo().getLocation());
SwingUtilities.invokeLater(() -> {
cardInfo.onMouseEntered(MouseInfo.getPointerInfo().getLocation());
cardInfo.onMouseMoved(MouseInfo.getPointerInfo().getLocation());
});
}
}
if (e.getEventType() == EventType.ACTIVATED) {
SwingUtilities.invokeLater(() -> {
cardInfo.onMouseWheel(MouseInfo.getPointerInfo().getLocation());
});
}
if (e.getEventType() == EventType.EXITED) {
cardInfo.onMouseExited();
SwingUtilities.invokeLater(() -> {
cardInfo.onMouseExited();
});
}
}));

View file

@ -1951,7 +1951,6 @@ public final class GamePanel extends javax.swing.JPanel {
gameChatPanel.setConnectedChat(userChatPanel);
gameChatPanel.disableInput();
gameChatPanel.setMinimumSize(new java.awt.Dimension(100, 48));
gameChatPanel.enableHyperlinks();
jSplitPane2 = new javax.swing.JSplitPane();
handContainer = new HandPanel();
handCards = new HashMap<>();

View file

@ -32,7 +32,6 @@ import org.mage.plugins.card.images.ImageCache;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.*;
@ -188,7 +187,7 @@ public class MageActionCallback implements ActionCallback {
private void showCardHintPopup(final TransferData data, final Component parentComponent, final Point parentPoint) {
MageCard cardPanel = data.getComponent().getTopPanelRef();
ThreadUtils.threadPool2.submit(new Runnable() {
ThreadUtils.threadPoolPopups.submit(new Runnable() {
@Override
public void run() {
ThreadUtils.sleep(tooltipDelay);
@ -482,7 +481,7 @@ public class MageActionCallback implements ActionCallback {
cancelHidingEnlagedCard();
Component parentComponent = SwingUtilities.getRoot(cardPanel);
if (parentComponent == null) {
// virtual card (example: show card popup in non cards panel like PickChoiceDialog)
// virtual card (example: show card popup in non cards panel like PickChoiceDialog or chat )
parentComponent = MageFrame.getDesktop();
}
Point parentPoint = parentComponent.getLocationOnScreen();
@ -571,8 +570,7 @@ public class MageActionCallback implements ActionCallback {
}
@Override
public void mouseWheelMoved(MouseWheelEvent e, TransferData data) {
int notches = e.getWheelRotation();
public void mouseWheelMoved(int mouseWheelRotation, TransferData data) {
if (enlargedWindowState != EnlargedWindowState.CLOSED) {
// same move direction will be ignored, opposite direction closes the enlarged window
if (enlargeredViewOpened != null && new Date().getTime() - enlargeredViewOpened.getTime() > 1000) {
@ -580,17 +578,18 @@ public class MageActionCallback implements ActionCallback {
hideEnlargedCard();
handleMouseMoveOverNewCard(data);
} else if (enlargeMode == EnlargeMode.NORMAL) {
if (notches > 0) {
if (mouseWheelRotation > 0) {
hideEnlargedCard();
handleMouseMoveOverNewCard(data);
}
} else if (notches < 0) {
} else if (mouseWheelRotation < 0) {
hideEnlargedCard();
handleMouseMoveOverNewCard(data);
}
return;
}
if (notches < 0) {
if (mouseWheelRotation < 0) {
// move up - show normal image
enlargeCard(EnlargeMode.NORMAL);
} else {
@ -648,7 +647,7 @@ public class MageActionCallback implements ActionCallback {
private void displayEnlargedCard(final CardView cardView, final TransferData data) {
MageCard cardPanel = data.getComponent().getTopPanelRef();
ThreadUtils.threadPool3.submit(() -> {
ThreadUtils.threadPoolPopups.submit(() -> {
if (cardView == null) {
return;
}
@ -677,12 +676,19 @@ public class MageActionCallback implements ActionCallback {
final Component popupContainer = MageFrame.getUI().getComponent(mageComponentCardPreviewContainer);
Component cardPreviewPane = MageFrame.getUI().getComponent(mageComponentCardPreviewPane);
Component parentComponent = SwingUtilities.getRoot(cardPanel);
if (parentComponent == null) {
// virtual card (example: show card popup in non cards panel like PickChoiceDialog or chat )
parentComponent = MageFrame.getDesktop();
}
if (cardPreviewPane != null && parentComponent != null) {
Point parentPoint = parentComponent.getLocationOnScreen();
if (DebugUtil.GUI_POPUP_CONTAINER_DRAW_DEBUG_BORDER) {
((JComponent) cardPreviewPane).setBorder(BorderFactory.createLineBorder(Color.green));
}
data.setLocationOnScreen(cardPanel.getCardLocationOnScreen().getCardPoint());
if (data.getLocationOnScreen() == null) {
// in virtual mode you can't get here cause cardPanel hidden
data.setLocationOnScreen(cardPanel.getCardLocationOnScreen().getCardPoint());
}
Point location = preparePopupContainerLocation(popupContainer, cardPreviewPane, data, parentPoint, parentComponent);
popupContainer.setLocation(location);

View file

@ -106,7 +106,7 @@ public class LinePool {
}
logLineStats();
}
ThreadUtils.threadPool.submit(() -> {
ThreadUtils.threadPoolSounds.submit(() -> {
synchronized (LinePool.this) {
try {
if (!line.isOpen()) {

View file

@ -744,7 +744,7 @@ public abstract class CardPanel extends MagePermanent implements ComponentListen
data.setComponent(this);
data.setCard(this.getGameCard());
data.setGameId(this.gameId);
callback.mouseWheelMoved(e, data);
callback.mouseWheelMoved(e.getWheelRotation(), data);
}
/**