mirror of
https://github.com/magefree/mage.git
synced 2025-12-24 20:41:58 -08:00
GUI: added card popup support in feedback/choice panel (related to #9609)
This commit is contained in:
parent
550e97e1e3
commit
1dc040a2c9
3 changed files with 197 additions and 177 deletions
|
|
@ -1,158 +1,17 @@
|
|||
package mage.client.components;
|
||||
|
||||
import mage.cards.action.TransferData;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.cards.BigCard;
|
||||
import mage.client.cards.VirtualCardInfo;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.game.GamePanel;
|
||||
import mage.game.command.Plane;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.GameLog;
|
||||
import mage.utils.ThreadUtils;
|
||||
import mage.view.CardView;
|
||||
import mage.view.PlaneView;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent.EventType;
|
||||
import javax.swing.text.SimpleAttributeSet;
|
||||
import javax.swing.text.html.HTMLDocument;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* GUI: chats with html and hints popup support for objects
|
||||
* GUI: component for display chats and game logs. Support html, mana symbols and popups.
|
||||
*
|
||||
* @author nantuko, JayDi85
|
||||
*/
|
||||
public class ColorPane extends JEditorPane {
|
||||
|
||||
final HTMLEditorKit kit = new HTMLEditorKit();
|
||||
final HTMLDocument doc = new HTMLDocument();
|
||||
|
||||
private static final int CHAT_TOOLTIP_DELAY_MS = 50; // cards popup from chat must be fast all time
|
||||
|
||||
// cards popup info
|
||||
private boolean hyperlinkEnabled = false;
|
||||
VirtualCardInfo cardInfo = new VirtualCardInfo();
|
||||
UUID gameId = null;
|
||||
BigCard bigCard = null;
|
||||
|
||||
public class ColorPane extends MageEditorPane {
|
||||
|
||||
public ColorPane() {
|
||||
this.setEditorKit(kit);
|
||||
this.setDocument(doc);
|
||||
}
|
||||
|
||||
private void addHyperlinkHandlers() {
|
||||
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;
|
||||
}
|
||||
|
||||
// finds extra data in html element like object_id, alternative_name, etc
|
||||
Map<String, String> extraData = new HashMap<>();
|
||||
if (e.getSourceElement() instanceof HTMLDocument.RunElement) {
|
||||
HTMLDocument.RunElement el = (HTMLDocument.RunElement) e.getSourceElement();
|
||||
Enumeration attNames = el.getAttributeNames();
|
||||
while (attNames.hasMoreElements()) {
|
||||
Object attName = attNames.nextElement();
|
||||
Object attValue = el.getAttribute(attName);
|
||||
// custom attributes in SimpleAttributeSet element
|
||||
if (attValue instanceof SimpleAttributeSet) {
|
||||
SimpleAttributeSet attReal = (SimpleAttributeSet) attValue;
|
||||
Enumeration attRealNames = attReal.getAttributeNames();
|
||||
while (attRealNames.hasMoreElements()) {
|
||||
Object attRealName = attRealNames.nextElement();
|
||||
Object attRealValue = attReal.getAttribute(attRealName);
|
||||
String name = attRealName.toString();
|
||||
String value = attRealValue.toString();
|
||||
extraData.put(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try object first
|
||||
CardView needCard = null;
|
||||
GamePanel gamePanel = MageFrame.getGame(this.gameId);
|
||||
if (gamePanel != null) {
|
||||
UUID needObjectId = UUID.fromString(extraData.getOrDefault("object_id", ""));
|
||||
needCard = gamePanel.getLastGameData().findCard(needObjectId);
|
||||
}
|
||||
|
||||
String cardName = e.getDescription().substring(1);
|
||||
String alternativeName = CardUtil.urlDecode(extraData.getOrDefault("alternative_name", ""));
|
||||
if (!alternativeName.isEmpty()) {
|
||||
cardName = alternativeName;
|
||||
}
|
||||
|
||||
if (e.getEventType() == EventType.ENTERED) {
|
||||
// show real object by priority (workable card hints and actual info)
|
||||
CardView cardView = needCard;
|
||||
|
||||
// if no game object found then show default card
|
||||
if (cardView == null) {
|
||||
CardInfo card = CardRepository.instance.findCards(cardName).stream().findFirst().orElse(null);
|
||||
if (card != null) {
|
||||
cardView = new CardView(card.getMockCard());
|
||||
}
|
||||
}
|
||||
|
||||
// plane
|
||||
if (cardView == null) {
|
||||
Plane plane = Plane.createPlaneByFullName(cardName);
|
||||
if (plane != null) {
|
||||
cardView = new CardView(new PlaneView(plane));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add other objects like dungeon, emblem, commander
|
||||
|
||||
if (cardView != null) {
|
||||
cardInfo.init(cardView, this.bigCard, this.gameId);
|
||||
cardInfo.setTooltipDelay(CHAT_TOOLTIP_DELAY_MS);
|
||||
cardInfo.setPopupAutoLocationMode(TransferData.PopupAutoLocationMode.PUT_NEAR_MOUSE_POSITION);
|
||||
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) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
cardInfo.onMouseExited();
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
cardInfo.onMouseExited();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setGameData(UUID gameId, BigCard bigCard) {
|
||||
this.gameId = gameId;
|
||||
this.bigCard = bigCard;
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -169,26 +28,6 @@ public class ColorPane extends JEditorPane {
|
|||
add(jPanel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
// must use append to enable popup/hyperlinks support
|
||||
super.setText("");
|
||||
append(text);
|
||||
}
|
||||
|
||||
public void append(String text) {
|
||||
try {
|
||||
if (hyperlinkEnabled) {
|
||||
text = GameLog.injectPopupSupport(text);
|
||||
}
|
||||
kit.insertHTML(doc, doc.getLength(), text, 0, 0, null);
|
||||
int len = getDocument().getLength();
|
||||
setCaretPosition(len);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A little trick to paint black background under the text.
|
||||
*
|
||||
|
|
@ -208,10 +47,4 @@ public class ColorPane extends JEditorPane {
|
|||
public void paintComponent(Graphics g) {
|
||||
super.paintChildren(g);
|
||||
}
|
||||
|
||||
public void enableHyperlinksAndCardPopups() {
|
||||
hyperlinkEnabled = true;
|
||||
addHyperlinkHandlers();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,183 @@
|
|||
package mage.client.components;
|
||||
|
||||
import mage.cards.action.TransferData;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.cards.BigCard;
|
||||
import mage.client.cards.VirtualCardInfo;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.game.GamePanel;
|
||||
import mage.game.command.Plane;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.GameLog;
|
||||
import mage.utils.ThreadUtils;
|
||||
import mage.view.CardView;
|
||||
import mage.view.PlaneView;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.text.SimpleAttributeSet;
|
||||
import javax.swing.text.html.HTMLDocument;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* GUI: improved editor pane with html, hyperlinks/popup support
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class MageEditorPane extends JEditorPane {
|
||||
|
||||
private static final int CHAT_TOOLTIP_DELAY_MS = 50; // cards popup from chat must be fast all time
|
||||
final HTMLEditorKit kit = new HTMLEditorKit();
|
||||
final HTMLDocument doc;
|
||||
|
||||
MageEditorPane() {
|
||||
super();
|
||||
// merge with UI.setHTMLEditorKit
|
||||
this.setEditorKit(kit);
|
||||
this.doc = (HTMLDocument) this.getDocument(); // HTMLEditorKit must creates HTMLDocument, os use it here
|
||||
}
|
||||
|
||||
// cards popup info
|
||||
private boolean hyperlinkEnabled = false;
|
||||
VirtualCardInfo cardInfo = new VirtualCardInfo();
|
||||
UUID gameId = null;
|
||||
BigCard bigCard = null;
|
||||
|
||||
public void setGameData(UUID gameId, BigCard bigCard) {
|
||||
this.gameId = gameId;
|
||||
this.bigCard = bigCard;
|
||||
}
|
||||
|
||||
private void addHyperlinkHandlers() {
|
||||
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;
|
||||
}
|
||||
|
||||
// finds extra data in html element like object_id, alternative_name, etc
|
||||
Map<String, String> extraData = new HashMap<>();
|
||||
if (e.getSourceElement() instanceof HTMLDocument.RunElement) {
|
||||
HTMLDocument.RunElement el = (HTMLDocument.RunElement) e.getSourceElement();
|
||||
Enumeration attNames = el.getAttributeNames();
|
||||
while (attNames.hasMoreElements()) {
|
||||
Object attName = attNames.nextElement();
|
||||
Object attValue = el.getAttribute(attName);
|
||||
// custom attributes in SimpleAttributeSet element
|
||||
if (attValue instanceof SimpleAttributeSet) {
|
||||
SimpleAttributeSet attReal = (SimpleAttributeSet) attValue;
|
||||
Enumeration attRealNames = attReal.getAttributeNames();
|
||||
while (attRealNames.hasMoreElements()) {
|
||||
Object attRealName = attRealNames.nextElement();
|
||||
Object attRealValue = attReal.getAttribute(attRealName);
|
||||
String name = attRealName.toString();
|
||||
String value = attRealValue.toString();
|
||||
extraData.put(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try object first
|
||||
CardView needCard = null;
|
||||
GamePanel gamePanel = MageFrame.getGame(this.gameId);
|
||||
if (gamePanel != null) {
|
||||
UUID needObjectId = UUID.fromString(extraData.getOrDefault("object_id", ""));
|
||||
needCard = gamePanel.getLastGameData().findCard(needObjectId);
|
||||
}
|
||||
|
||||
String cardName = e.getDescription().substring(1);
|
||||
String alternativeName = CardUtil.urlDecode(extraData.getOrDefault("alternative_name", ""));
|
||||
if (!alternativeName.isEmpty()) {
|
||||
cardName = alternativeName;
|
||||
}
|
||||
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.ENTERED) {
|
||||
// show real object by priority (workable card hints and actual info)
|
||||
CardView cardView = needCard;
|
||||
|
||||
// if no game object found then show default card
|
||||
if (cardView == null) {
|
||||
CardInfo card = CardRepository.instance.findCards(cardName).stream().findFirst().orElse(null);
|
||||
if (card != null) {
|
||||
cardView = new CardView(card.getMockCard());
|
||||
}
|
||||
}
|
||||
|
||||
// plane
|
||||
if (cardView == null) {
|
||||
Plane plane = Plane.createPlaneByFullName(cardName);
|
||||
if (plane != null) {
|
||||
cardView = new CardView(new PlaneView(plane));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add other objects like dungeon, emblem, commander
|
||||
|
||||
if (cardView != null) {
|
||||
cardInfo.init(cardView, this.bigCard, this.gameId);
|
||||
cardInfo.setTooltipDelay(CHAT_TOOLTIP_DELAY_MS);
|
||||
cardInfo.setPopupAutoLocationMode(TransferData.PopupAutoLocationMode.PUT_NEAR_MOUSE_POSITION);
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
cardInfo.onMouseEntered(MouseInfo.getPointerInfo().getLocation());
|
||||
cardInfo.onMouseMoved(MouseInfo.getPointerInfo().getLocation());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
cardInfo.onMouseWheel(MouseInfo.getPointerInfo().getLocation());
|
||||
});
|
||||
}
|
||||
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.EXITED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
cardInfo.onMouseExited();
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
// TODO: add popup mouse wheel here?
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
cardInfo.onMouseExited();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String text) {
|
||||
// must use append to enable popup/hyperlinks support
|
||||
super.setText("");
|
||||
append(text);
|
||||
}
|
||||
|
||||
public void append(String text) {
|
||||
try {
|
||||
if (hyperlinkEnabled) {
|
||||
text = GameLog.injectPopupSupport(text);
|
||||
}
|
||||
kit.insertHTML(doc, doc.getLength(), text, 0, 0, null);
|
||||
int len = getDocument().getLength();
|
||||
setCaretPosition(len);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void enableHyperlinksAndCardPopups() {
|
||||
hyperlinkEnabled = true;
|
||||
addHyperlinkHandlers();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,19 +8,21 @@ import org.mage.card.arcane.ManaSymbols;
|
|||
import org.mage.card.arcane.UI;
|
||||
|
||||
/**
|
||||
* Component for displaying text in mage. Supports drawing mana symbols.
|
||||
* GUI: component for displaying text in feedback panel. Support html, mana symbols and popups.
|
||||
*
|
||||
* @author nantuko
|
||||
*/
|
||||
public class MageTextArea extends JEditorPane {
|
||||
public class MageTextArea extends MageEditorPane {
|
||||
|
||||
private String currentText;
|
||||
private int currentPanelWidth;
|
||||
|
||||
public MageTextArea() {
|
||||
UI.setHTMLEditorKit(this);
|
||||
super();
|
||||
setEditable(false);
|
||||
setBackground(new Color(0, 0, 0, 0)); // transparent background
|
||||
setFocusable(false);
|
||||
enableHyperlinksAndCardPopups();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -32,16 +34,18 @@ public class MageTextArea extends JEditorPane {
|
|||
if (text == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(text.equals(currentText) && panelWidth == currentPanelWidth)
|
||||
if (text.equals(currentText) && panelWidth == currentPanelWidth) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentText = text;
|
||||
currentPanelWidth = panelWidth;
|
||||
|
||||
// prepare text format as header and details texts
|
||||
|
||||
final StringBuilder buffer = new StringBuilder(512);
|
||||
// Dialog is a java logical font family, so it should work on all systems
|
||||
buffer.append("<html><body style='font-family:Dialog;font-size:");
|
||||
buffer.append("<body style='font-family:Dialog;font-size:");
|
||||
buffer.append(GUISizeHelper.gameDialogAreaFontSizeBig);
|
||||
buffer.append("pt;margin:3px 3px 3px 3px;color: #FFFFFF'><b><center>");
|
||||
|
||||
|
|
@ -54,11 +58,11 @@ public class MageTextArea extends JEditorPane {
|
|||
if (!text.isEmpty()) {
|
||||
buffer.append(basicText);
|
||||
}
|
||||
|
||||
buffer.append("</b></center></body></html>");
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
String promptText = buffer.toString();
|
||||
System.out.println(promptText);
|
||||
MageTextArea.super.setText(promptText);
|
||||
// in case the text don't fit in the panel a tooltip with the text is added
|
||||
if (panelWidth > 0 && MageTextArea.this.getPreferredSize().getWidth() > panelWidth) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue