package org.mage.card.arcane; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Font; import java.awt.Image; import java.awt.Insets; import java.awt.Point; import java.awt.Toolkit; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JToggleButton; import javax.swing.JViewport; import javax.swing.ScrollPaneConstants; import javax.swing.UIManager; import javax.swing.ViewportLayout; import javax.swing.border.Border; import javax.swing.border.TitledBorder; import javax.swing.text.Element; import javax.swing.text.StyleConstants; import javax.swing.text.View; import javax.swing.text.ViewFactory; import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.ImageView; /** * UI utility functions. */ public final class UI { private static final ConcurrentMap<URI, Image> imageCache = new ConcurrentHashMap<>(); public static JToggleButton getToggleButton () { JToggleButton button = new JToggleButton(); button.setMargin(new Insets(2, 4, 2, 4)); return button; } public static JButton getButton () { JButton button = new JButton(); button.setMargin(new Insets(2, 4, 2, 4)); return button; } public static void setTitle (JPanel panel, String title) { Border border = panel.getBorder(); if (border instanceof TitledBorder) { ((TitledBorder) panel.getBorder()).setTitle(title); panel.repaint(); } else { panel.setBorder(BorderFactory.createTitledBorder(title)); } } public static ImageIcon getImageIcon (String path) { try { InputStream stream; stream = UI.class.getResourceAsStream(path); if (stream == null && new File(path).exists()) { stream = new FileInputStream(path); } if (stream == null) { throw new RuntimeException("Image not found: " + path); } byte[] data = new byte[stream.available()]; stream.read(data); return new ImageIcon(data); } catch (IOException ex) { throw new RuntimeException("Error reading image: " + path); } } public static void setHTMLEditorKit (JEditorPane editorPane) { editorPane.getDocument().putProperty("imageCache", imageCache); // Read internally by ImageView, but never written. editorPane.setEditorKit(new HTMLEditorKit() { private static final long serialVersionUID = -54602188235105448L; @Override public ViewFactory getViewFactory () { return new HTMLFactory() { @Override public View create(Element elem) { Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute); if (o instanceof HTML.Tag) { HTML.Tag kind = (HTML.Tag) o; if (Objects.equals(kind, HTML.Tag.IMG)) { return new ImageView(elem) { @Override public URL getImageURL() { URL url = super.getImageURL(); URI uri = null; try { uri = url.toURI(); } catch (URISyntaxException ex) { } // Put an image into the cache to be read by other ImageView methods. if (uri != null && imageCache.get(uri) == null) { imageCache.put(uri, Toolkit.getDefaultToolkit().createImage(url)); } return url; } }; } } return super.create(elem); } }; } }); } public static void setVerticalScrollingView (JScrollPane scrollPane, final Component view) { final JViewport viewport = new JViewport(); viewport.setLayout(new ViewportLayout() { private static final long serialVersionUID = 7701568740313788935L; @Override public void layoutContainer (Container parent) { viewport.setViewPosition(new Point(0, 0)); Dimension viewportSize = viewport.getSize(); int width = viewportSize.width; int height = Math.max(view.getPreferredSize().height, viewportSize.height); viewport.setViewSize(new Dimension(width, height)); } }); viewport.setView(view); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setViewport(viewport); } public static String getDisplayManaCost (String manaCost) { // A pipe in the cost means "process left of the pipe as the card color, but display right of the pipe as the cost". int pipePosition = manaCost.indexOf("{|}"); if (pipePosition != -1) { manaCost = manaCost.substring(pipePosition + 3); } return manaCost; } public static void invokeLater (Runnable runnable) { EventQueue.invokeLater(runnable); } public static void invokeAndWait (Runnable runnable) { if (EventQueue.isDispatchThread()) { runnable.run(); return; } try { EventQueue.invokeAndWait(runnable); } catch (InterruptedException ex) { } catch (InvocationTargetException ex) { throw new RuntimeException(ex); } } public static void setSystemLookAndFeel () { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { System.err.println("Error setting look and feel:"); ex.printStackTrace(); } } public static void setDefaultFont (Font font) { for (Object key : Collections.list(UIManager.getDefaults().keys())) { Object value = UIManager.get(key); if (value instanceof javax.swing.plaf.FontUIResource) { UIManager.put(key, font); } } } }