GUI: fixed not working card popup near screen border, improved card popup for chat and choose dialogs;

This commit is contained in:
Oleg Agafonov 2023-11-25 17:27:59 +04:00
parent 7475ee922a
commit 63290d3ed6
8 changed files with 85 additions and 15 deletions

View file

@ -43,6 +43,7 @@ import mage.interfaces.callback.CallbackClient;
import mage.interfaces.callback.ClientCallback;
import mage.remote.Connection;
import mage.remote.Connection.ProxyType;
import mage.util.DebugUtil;
import mage.utils.MageVersion;
import mage.view.GameEndView;
import mage.view.UserRequestMessage;
@ -417,6 +418,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
popupContainer.setLayout(null);
popupContainer.add(cardInfoPane);
popupContainer.setVisible(false);
if (DebugUtil.GUI_POPUP_CONTAINER_DRAW_DEBUG_BORDER) {
popupContainer.setBorder(BorderFactory.createLineBorder(Color.red));
}
desktopPane.add(popupContainer, JLayeredPane.POPUP_LAYER);
UI.addComponent(MageComponents.POPUP_CONTAINER, popupContainer);

View file

@ -29,6 +29,10 @@ import java.util.UUID;
* - 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
* <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)
*
* @author JayDi85
*/
@ -90,6 +94,10 @@ public class VirtualCardInfo {
data.setTooltipDelay(tooltipDelay);
}
public void setPopupAutoLocationMode(TransferData.PopupAutoLocationMode mode) {
data.setPopupAutoLocationMode(mode);
}
public CardView getCardView() {
return this.cardView;
}
@ -125,10 +133,6 @@ public class VirtualCardInfo {
this.actionCallback.mouseEntered(null, this.data);
}
public void onMouseMoved() {
onMouseMoved(null);
}
public void onMouseMoved(Point newLocation) {
if (!prepared()) {
return;
@ -145,6 +149,7 @@ public class VirtualCardInfo {
if (!prepared()) {
return;
}
this.actionCallback.mouseExited(null, this.data);
}
}

View file

@ -1,5 +1,6 @@
package mage.client.components;
import mage.cards.action.TransferData;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.client.cards.BigCard;
@ -109,6 +110,7 @@ public class ColorPane extends JEditorPane {
if (cardView != null) {
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());
}

View file

@ -7,6 +7,7 @@ import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import mage.cards.action.TransferData;
import mage.choices.Choice;
import mage.choices.ChoiceHintType;
import mage.client.MageFrame;
@ -238,6 +239,7 @@ public class PickChoiceDialog extends MageDialog {
CardView cardView = new CardView(new DungeonView(Dungeon.createDungeon(cardName)));
cardInfo.init(cardView, this.bigCard, this.gameId);
}
cardInfo.setPopupAutoLocationMode(TransferData.PopupAutoLocationMode.PUT_NEAR_MOUSE_POSITION);
cardInfo.onMouseEntered(MouseInfo.getPointerInfo().getLocation());
} else {

View file

@ -21,6 +21,7 @@ import mage.client.util.gui.GuiDisplayUtil;
import mage.components.CardInfoPane;
import mage.constants.EnlargeMode;
import mage.constants.Zone;
import mage.util.DebugUtil;
import mage.utils.ThreadUtils;
import mage.view.CardView;
import mage.view.PermanentView;
@ -48,7 +49,7 @@ import java.util.concurrent.TimeUnit;
* Only ONE action callback possible for the app
* <p>
* If you want to process card events in your component then use CardEventProducer, see example with mouseClicked here
*
* <p>
* If you want virtual popup hint (without real card) then use VirtualCardInfo
*
* @author Nantuko, noxx, JayDi85
@ -167,13 +168,17 @@ public class MageActionCallback implements ActionCallback {
if (data.getLocationOnScreen() == null) {
data.setLocationOnScreen(cardPanel.getCardLocationOnScreen().getCardPoint());
}
int newLocationX = (int) data.getLocationOnScreen().getX() + data.getPopupOffsetX();
int newLocationY = (int) data.getLocationOnScreen().getY() + data.getPopupOffsetY() + 40;
PopupFactory factory = PopupFactory.getSharedInstance();
data.getPopupText().updateText();
tooltipPopup = factory.getPopup(cardPanel, data.getPopupText(), (int) data.getLocationOnScreen().getX() + data.getPopupOffsetX(), (int) data.getLocationOnScreen().getY() + data.getPopupOffsetY() + 40);
tooltipPopup = factory.getPopup(cardPanel, data.getPopupText(), newLocationX, newLocationY);
tooltipPopup.show();
// hack to get popup to resize to fit text
// hack to get popup to resize to fit text TODO: wtf?! Can be removed?
tooltipPopup.hide();
tooltipPopup = factory.getPopup(cardPanel, data.getPopupText(), (int) data.getLocationOnScreen().getX() + data.getPopupOffsetX(), (int) data.getLocationOnScreen().getY() + data.getPopupOffsetY() + 40);
tooltipPopup = factory.getPopup(cardPanel, data.getPopupText(), newLocationX, newLocationY);
tooltipPopup.show();
} else {
showCardHintPopup(data, parentComponent, parentPoint);
@ -218,9 +223,11 @@ public class MageActionCallback implements ActionCallback {
data.setLocationOnScreen(cardPanel.getCardLocationOnScreen().getCardPoint());
}
Point location = new Point((int) data.getLocationOnScreen().getX() + data.getPopupOffsetX() - 40, (int) data.getLocationOnScreen().getY() + data.getPopupOffsetY() - 40);
location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, infoPane, parentComponent);
location.translate(-parentPoint.x, -parentPoint.y);
if (DebugUtil.GUI_POPUP_CONTAINER_DRAW_DEBUG_BORDER) {
((JComponent) infoPane).setBorder(BorderFactory.createLineBorder(Color.green));
}
Point location = preparePopupContainerLocation(popupContainer, infoPane, data, parentPoint, parentComponent);
popupContainer.setLocation(location);
popupContainer.setVisible(true);
c.repaint();
@ -672,10 +679,12 @@ public class MageActionCallback implements ActionCallback {
Component parentComponent = SwingUtilities.getRoot(cardPanel);
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());
Point location = new Point((int) data.getLocationOnScreen().getX() + data.getPopupOffsetX() - 40, (int) data.getLocationOnScreen().getY() + data.getPopupOffsetY() - 40);
location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, cardPreviewPane, parentComponent);
location.translate(-parentPoint.x, -parentPoint.y);
Point location = preparePopupContainerLocation(popupContainer, cardPreviewPane, data, parentPoint, parentComponent);
popupContainer.setLocation(location);
popupContainer.setVisible(true);
@ -717,6 +726,37 @@ public class MageActionCallback implements ActionCallback {
});
}
private Point preparePopupContainerLocation(Component popupContainer, Component popupComponent, TransferData data, Point parentPoint, Component parentComponent) {
Point location;
switch (data.getPopupAutoLocationMode()) {
case PUT_INSIDE_PARENT: {
location = new Point((int) data.getLocationOnScreen().getX() + data.getPopupOffsetX() - 40, (int) data.getLocationOnScreen().getY() + data.getPopupOffsetY() - 40);
location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, popupComponent, parentComponent);
location.translate(-parentPoint.x, -parentPoint.y);
break;
}
case PUT_NEAR_MOUSE_POSITION: {
location = MouseInfo.getPointerInfo().getLocation();
boolean hasRightSpace = location.x + popupContainer.getWidth() < parentComponent.getX() + parentComponent.getWidth();
boolean hasBottomSpace = location.y + popupContainer.getHeight() < parentComponent.getY() + parentComponent.getHeight();
if (!hasRightSpace) {
location.setLocation(location.x - popupContainer.getWidth(), location.y);
}
if (!hasBottomSpace) {
location.setLocation(location.x, location.y - popupContainer.getHeight());
}
break;
}
default:
throw new IllegalArgumentException("Unsupport auto-location " + data.getPopupAutoLocationMode());
}
location.translate(-parentPoint.x, -parentPoint.y);
return location;
}
private void displayCardInfo(CardView card, Image image, BigCard bigCard) {
if (image instanceof BufferedImage) {
// XXX: scaled to fit width

View file

@ -11,7 +11,7 @@ import mage.view.CardView;
import org.mage.card.arcane.UI;
/**
* Card info pane for displaying card rules. Supports drawing mana symbols.
* GUI: card info pane for displaying card rules (example: text mode for popup card). Supports drawing mana symbols.
*
* @author nantuko
*/