package magic.ui.widget.message;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import magic.ui.screen.duel.game.SwingGameController;
import magic.ui.theme.Theme;
import magic.ui.utility.MagicStyle;
import magic.ui.FontsAndBorders;
import magic.utility.MagicSystem;
@SuppressWarnings("serial")
public class TextLabel extends JPanel {
private static final int SPACE_WIDTH = 3;
private static final int LINE_HEIGHT = 16;
private static final Map<?, ?> desktopHintsMap;
static {
final Toolkit tk = Toolkit.getDefaultToolkit();
desktopHintsMap = (Map<?, ?>) (tk.getDesktopProperty("awt.font.desktophints"));
}
private final SwingGameController controller;
private final int maxWidth;
private final boolean center;
private final List<TComponent> components = new ArrayList<>();
private boolean isMouseMoveBusy = false;
private TextComponent activeComponent = null;
// CTR
public TextLabel(String text, Font aFont, int maxWidth, boolean center, Color aColor, SwingGameController aController) {
this.maxWidth = maxWidth;
this.center = center;
this.controller = aController;
setOpaque(false);
setLayout(null);
final boolean isUserPromptText = controller == null;
final Color interactiveColor = isUserPromptText ? Color.BLACK : Color.BLUE;
TComponentBuilder.buildTComponents(components, text, this, aFont, aColor, interactiveColor);
layoutTComponents();
if (!isUserPromptText) {
setMouseListeners();
}
}
// CTR
public TextLabel(String text, int maxWidth, boolean center) {
this(text, FontsAndBorders.FONT1, maxWidth, center, MagicStyle.getTheme().getColor(Theme.COLOR_CHOICE_FOREGROUND), null);
}
private void setMouseListeners() {
addMouseListener(new MouseAdapter() {
private boolean dispatchMouseEvent() {
return (activeComponent == null
|| (activeComponent != null && !activeComponent.isInteractive()));
}
private boolean isLeftClick(MouseEvent e) {
return SwingUtilities.isLeftMouseButton(e);
}
// so StackButton works when it is a selectable choice.
private void doDispatchEvent(MouseEvent ev) {
ev.getComponent().getParent().getParent().getParent().dispatchEvent(ev);
}
@Override
public void mouseExited(MouseEvent e) {
doMouseExitAction();
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
@Override
public void mousePressed(MouseEvent ev) {
if (isLeftClick(ev) && dispatchMouseEvent()) {
doDispatchEvent(ev);
}
}
@Override
public void mouseReleased(MouseEvent ev) {
if (isLeftClick(ev)) {
if (dispatchMouseEvent()) {
doDispatchEvent(ev);
} else {
doMouseClickAction();
}
}
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
doMouseMoveAction(e.getPoint());
}
});
}
private void doMouseClickAction() {
if (activeComponent != null && controller != null) {
controller.showMagicCardImage(activeComponent.getCardId());
}
}
private void doMouseExitAction() {
clearActiveComponent();
refreshTComponentHighlight();
}
private void clearActiveComponent() {
if (controller != null) {
controller.hideInfoNoDelay();
if (activeComponent != null) {
controller.highlightCard(activeComponent.getCardId(), false);
}
}
activeComponent = null;
}
private void doMouseMoveAction(Point pt) {
if (isMouseMoveBusy) {
return;
}
if (activeComponent != null && activeComponent.getBounds().contains(pt)) {
return;
}
isMouseMoveBusy = true;
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
clearActiveComponent();
for (final TComponent c : components) {
if (c instanceof TextComponent && c.getBounds().contains(pt)) {
activeComponent = (TextComponent) c;
if (activeComponent.isInteractive()) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
controller.highlightCard(activeComponent.getCardId(), true);
} else {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
break;
}
}
refreshTComponentHighlight();
isMouseMoveBusy = false;
}
private void layoutTComponents() {
int x = 0;
int y = 0;
for (final TComponent component : components) {
if (component == TComponentBuilder.SPACE_COMPONENT) {
x += SPACE_WIDTH;
} else if (component == TComponentBuilder.BREAK_COMPONENT) {
x = 0;
y += LINE_HEIGHT;
} else {
final Dimension csize = component.getPreferredSize();
if (component.requiresNewLine() && x + csize.width > maxWidth) {
x = 0;
y += LINE_HEIGHT;
}
component.setLocation(x, y + (LINE_HEIGHT - csize.height));
x += csize.width;
}
}
final Insets insets = getInsets();
setPreferredSize(new Dimension(
maxWidth - insets.left + insets.right,
y + LINE_HEIGHT + insets.top + insets.bottom));
}
@Override
public void paintComponent(final Graphics g) {
if (desktopHintsMap != null) {
((Graphics2D) g).addRenderingHints(desktopHintsMap);
}
final Dimension size = getPreferredSize();
final int cx = center ? (getWidth() - maxWidth) / 2 : 0;
final int cy = center ? (getHeight() - size.height) / 2 : 0;
for (final TComponent c : components) {
if (c == activeComponent && MagicSystem.isDevMode()) {
highlightTComponent(c, g, cx, cy);
}
c.paint(this, g, cx, cy);
}
}
private void highlightTComponent(TComponent c, Graphics g, int cx, int cy) {
final Rectangle r = c.getBounds();
if (c.isInteractive()) {
g.setColor(MagicStyle.getRolloverColor());
g.fillRect(r.x + cx, r.y + cy, r.width, r.height);
} else {
g.setColor(Color.LIGHT_GRAY);
g.drawRect(r.x + cx, r.y + cy, r.width, r.height);
}
}
private void refreshTComponentHighlight() {
if (MagicSystem.isDevMode()) {
repaint();
}
}
}