package mage.client.components; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.font.FontRenderContext; import javax.swing.JPanel; import mage.client.util.Command; /** * Image button with hover. * * @author nantuko */ public class HoverButton extends JPanel implements MouseListener { static final int TOP_TEXT_IMAGE_GAP = 3; private Image image; private Image hoverImage; private Image disabledImage; private Image selectedImage; protected Image overlayImage; private Rectangle imageSize; private Rectangle buttonSize; private String text; private boolean textAlwaysVisible = false; private int textOffsetY = 0; private int textOffsetButtonY = 2; private int textOffsetX = -1; private int topTextOffsetX = -1; private Dimension overlayImageSize; private String topText; private Image topTextImage; private Image topTextImageRight; private boolean isHovered = false; private boolean isSelected = false; private boolean drawSet = false; private String set = null; private Command observer = null; private Command onHover = null; private Color textColor = Color.white; private final Color textBGColor = Color.black; static final Font textFont = new Font("Arial", Font.PLAIN, 12); static final Font textFontMini = new Font("Arial", Font.PLAIN, 11); static final Font textSetFontBoldMini = new Font("Arial", Font.BOLD, 12); static final Font textSetFontBold = new Font("Arial", Font.BOLD, 14); private boolean useMiniFont = false; private boolean alignTextLeft = false; public HoverButton(String text, Image image, Rectangle size) { this(text, image, image, null, image, size); if (image == null) { throw new IllegalArgumentException("Image can't be null"); } } public HoverButton(String text, Image image, Image hover, Image disabled, Rectangle size) { this(text, image, hover, null, disabled, size); } public HoverButton(String text, Image image, Image hover, Image selected, Image disabled, Rectangle size) { this.image = image; this.hoverImage = hover; this.selectedImage = selected; this.disabledImage = disabled; this.imageSize = size; this.text = text; setOpaque(false); addMouseListener(this); } public HoverButton(HoverButton button) { this(button.text, button.image, button.hoverImage, button.selectedImage, button.disabledImage, button.imageSize); } @Override public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; if (isEnabled()) { if (isHovered || textAlwaysVisible) { g.drawImage(hoverImage, 0, 0, imageSize.width, imageSize.height, this); if (text != null) { if (textColor != null) { g2d.setColor(textColor); } if (useMiniFont) { g2d.setFont(textFontMini); } else { g2d.setFont(textFont); } textOffsetX = calculateOffset(g2d); g2d.drawString(text, textOffsetX, textOffsetY); } } else { g.drawImage(image, 0, 0, imageSize.width, imageSize.height, this); } if (isSelected) { if (selectedImage != null) { g.drawImage(selectedImage, 0, 0, imageSize.width, imageSize.height, this); } else { System.err.println("No selectedImage for button."); } } } else { g.drawImage(disabledImage, 0, 0, imageSize.width, imageSize.height, this); } if (topText != null) { if (useMiniFont) { g2d.setFont(textFontMini); } else { g2d.setFont(textFont); } topTextOffsetX = calculateOffsetForTop(g2d, topText); g2d.setColor(textBGColor); g2d.drawString(topText, topTextOffsetX + 1, 14); g2d.setColor(textColor); g2d.drawString(topText, topTextOffsetX, 13); } if (topTextImage != null) { g.drawImage(topTextImage, 4, 3, this); } if (topTextImageRight != null) { g.drawImage(topTextImageRight, this.getWidth() - 20, 3, this); } if (overlayImage != null) { g.drawImage(overlayImage, (imageSize.width - overlayImageSize.width) / 2, 10, this); } else if (set != null) { // draw only if it is not current tab if (!drawSet) { g2d.setFont(textSetFontBoldMini); g2d.drawString(set, 5, 25); } } if (drawSet && set != null) { g2d.setFont(textSetFontBold); int w = (int) (getWidth() / 2.0); int h = (int) (getHeight() / 2.0); int dy = overlayImage == null ? 15 : 25; g2d.translate(w + 5, h + dy); g2d.rotate(-Math.PI / 2.0); g2d.drawString(set, 0, 0); } } private int calculateOffset(Graphics2D g2d) { if (textOffsetX == -1) { // calculate once FontRenderContext frc = g2d.getFontRenderContext(); int textWidth = (int) textFont.getStringBounds(text, frc).getWidth(); if (textWidth > buttonSize.width) { g2d.setFont(textFontMini); useMiniFont = true; frc = g2d.getFontRenderContext(); textWidth = (int) textFontMini.getStringBounds(text, frc).getWidth(); } if (alignTextLeft) { textOffsetX = 0; } else { textOffsetX = (imageSize.width - textWidth) / 2; } } return textOffsetX; } private int calculateOffsetForTop(Graphics2D g2d, String text) { if (topTextOffsetX == -1) { // calculate once FontRenderContext frc = g2d.getFontRenderContext(); int textWidth = (int) textFont.getStringBounds(text, frc).getWidth(); int neededImageWidth = (topTextImage == null ? 0 : topTextImage.getWidth(this)); int availableXWidth = imageSize.width - neededImageWidth; topTextOffsetX = (availableXWidth - textWidth) / 2 + neededImageWidth; } return topTextOffsetX; } public void setTextColor(Color textColor) { this.textColor = textColor; } public void setOverlayImage(Image image) { this.overlayImage = image; this.overlayImageSize = new Dimension(image.getWidth(null), image.getHeight(null)); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { isHovered = true; this.repaint(); if (onHover != null) { onHover.execute(); } } @Override public void mouseExited(MouseEvent e) { isHovered = false; this.repaint(); } @Override public void mousePressed(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { if (isEnabled() && observer != null) { observer.execute(); } } } @Override public void mouseReleased(MouseEvent e) { } public void setObserver(Command observer) { this.observer = observer; } public void setOnHover(Command onHover) { this.onHover = onHover; } @Override public void setBounds(Rectangle r) { super.setBounds(r); this.textOffsetY = r.height - this.textOffsetButtonY; this.buttonSize = r; } @Override public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); this.textOffsetY = height - this.textOffsetButtonY; this.buttonSize = new Rectangle(x, y, width, height); } public void setTextOffsetButtonY(int textOffsetButtonY) { this.textOffsetButtonY = textOffsetButtonY; } public boolean isSelected() { return isSelected; } public void setSelected(boolean isSelected) { this.isSelected = isSelected; } public void changeSelected() { this.isSelected = !this.isSelected; } public void setText(String text) { this.text = text; } public void setSet(String set) { this.set = set; } public void drawSet() { this.drawSet = true; } public void update(String text, Image image, Image hover, Image selected, Image disabled, Rectangle size) { this.image = image; this.hoverImage = hover; this.selectedImage = selected; this.disabledImage = disabled; this.imageSize = size; this.text = text; repaint(); } public void execute() { if (isEnabled() && observer != null) { observer.execute(); } } public void setTopText(String topText) { this.topText = topText; } public void setTopTextImage(Image topTextImage) { this.topTextImage = topTextImage; this.textOffsetX = -1; // rest for new clculation } public void setTopTextImageRight(Image topTextImage) { this.topTextImageRight = topTextImage; } public void setTextAlwaysVisible(boolean textAlwaysVisible) { this.textAlwaysVisible = textAlwaysVisible; } public void setAlignTextLeft(boolean alignTextLeft) { this.alignTextLeft = alignTextLeft; } }