workcraft/workcraft

View on GitHub
workcraft/WorkcraftCore/src/org/workcraft/utils/GuiUtils.java

Summary

Maintainability
A
1 hr
Test Coverage
package org.workcraft.utils;

import info.clearthought.layout.TableLayout;
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.Document;
import org.workcraft.dom.visual.SizeHelper;
import org.workcraft.gui.tools.GraphEditor;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.font.LineMetrics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

public class GuiUtils {

    private static final float BUTTON_PREFERRED_ASPECT_RATIO = 4.0f;

    public static JPanel createLabeledComponent(JComponent component, String labelText) {
        return createLabeledComponent(component, labelText, BorderLayout.WEST);
    }

    public static JPanel createLabeledComponent(JComponent component, String labelText, Object labelPosition) {
        JPanel result = new JPanel(createBorderLayout());
        result.add(new JLabel(labelText), labelPosition);
        result.add(component, BorderLayout.CENTER);
        return result;
    }

    public static JPanel createDialogButtonsPanel() {
        return new JPanel(new FlowLayout(FlowLayout.RIGHT, SizeHelper.getLayoutHGap(), SizeHelper.getLayoutVGap()));
    }

    public static void centerAndSizeToParent(Window frame, Window parent) {
        if ((frame != null) && (parent != null)) {
            Dimension parentSize = parent.getSize();
            frame.setSize(2 * parentSize.width / 3, 2 * parentSize.height / 3);
            frame.setLocationRelativeTo(parent);
        }
    }

    public static void drawEditorMessage(GraphEditor editor, Graphics2D g, Color color, String message) {
        if (message != null) {
            g.setFont(UIManager.getFont("Button.font"));
            Rectangle r = g.getFont().getStringBounds(message, g.getFontRenderContext()).getBounds();
            r.x = editor.getWidth() / 2 - r.width / 2;
            r.y = editor.getHeight() - 20 - r.height;
            g.setColor(new Color(240, 240, 240, 192));
            g.fillRoundRect(r.x - 10, r.y - 10, r.width + 20, r.height + 20, 5, 5);
            g.setColor(new Color(224, 224, 224));
            g.drawRoundRect(r.x - 10, r.y - 10, r.width + 20, r.height + 20, 5, 5);
            g.setColor(color);
            LineMetrics lm = g.getFont().getLineMetrics(message, g.getFontRenderContext());
            g.drawString(message, r.x, r.y + r.height - (int) (lm.getDescent()));
        }
    }

    public static BufferedImage loadImageFromResource(String path) throws IOException {
        URL res = ClassLoader.getSystemResource(path);
        if (res == null) {
            throw new IOException("Resource not found: " + path);
        }
        return ImageIO.read(res);
    }

    private static ImageIcon createIconFromSVG(String path, int width, int height) {
        try {
            System.setProperty("org.apache.batik.warn_destination", "false");
            Document document;

            String parser = XMLResourceDescriptor.getXMLParserClassName();
            SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);

            document = f.createDocument(ClassLoader.getSystemResource(path).toString());

            UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
            BridgeContext bridgeContext = new BridgeContext(userAgentAdapter);
            GVTBuilder builder = new GVTBuilder();

            GraphicsNode graphicsNode = builder.build(bridgeContext, document);

            double sizeY = bridgeContext.getDocumentSize().getHeight();
            double sizeX = bridgeContext.getDocumentSize().getWidth();

            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();

            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

            double scaleX = (width - 1) / sizeX;
            double scaleY = (height - 1) / sizeY;
            double scale = Math.min(scaleX, scaleY);
            g2d.scale(scale, scale);
            g2d.translate(0.5, 0.5);

            graphicsNode.paint(g2d);
            g2d.dispose();
            return new ImageIcon(bufferedImage);
        } catch (Throwable e) {
            System.err.println("Failed to load SVG file " + path);
            return null;
        }
    }

    public static ImageIcon createIconFromSVG(String svgPath) {
        int iconSize = SizeHelper.getToolIconSize();
        return createIconFromSVG(svgPath, iconSize, iconSize);
    }

    public static Cursor createCursorFromSVG(String svgPath) {
        ImageIcon icon = createIconFromSVG(svgPath);
        return createCursorFromIcon(icon, svgPath);
    }

    public static Cursor createCursorFromIcon(ImageIcon icon, String name) {
        int iconSize = icon.getIconWidth();
        int crossLength = (int) Math.round(0.2 * iconSize);
        int crossWidth = (int) Math.round(0.08 * iconSize);
        int crossGap = (int) Math.round(0.05 * iconSize);
        int iconOffset = crossLength + crossGap + crossWidth + crossGap;
        Image cursorImage = new BufferedImage(iconSize + iconOffset, iconSize + iconOffset, BufferedImage.TYPE_INT_ARGB);
        Graphics g = cursorImage.getGraphics();
        Image iconImage = icon.getImage().getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH);
        g.drawImage(iconImage, iconOffset, iconOffset, null);
        int posClose = crossLength + crossGap;
        int posFar = posClose + crossWidth + crossGap;
        g.setColor(Color.BLACK);
        g.fillRect(posClose, 0, crossWidth, crossLength);
        g.fillRect(posClose, posFar, crossWidth, crossLength);
        g.fillRect(0, posClose, crossLength, crossWidth);
        g.fillRect(posFar, posClose, crossLength, crossWidth);
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        int offset = posClose + (int) Math.round(0.5 * crossWidth);
        Point hotSpot = new Point(offset, offset);
        return toolkit.createCustomCursor(cursorImage, hotSpot, name);
    }

    public static JButton createIconButton(String svgPath, String toolTip, ActionListener action) {
        ImageIcon icon = createIconFromSVG(svgPath);
        JButton button = createIconButton(icon, toolTip);
        button.addActionListener(action);
        return button;
    }

    public static JButton createIconButton(Icon icon, String toolTip) {
        JButton button = new JButton();
        decorateButton(button, icon, toolTip);
        return button;
    }

    public static JToggleButton createIconToggleButton(Icon icon, String toolTip) {
        JToggleButton result = new JToggleButton(icon);
        result.setToolTipText(toolTip);
        result.setMargin(new Insets(0, 0, 0, 0));
        int iconSize = SizeHelper.getToolIconSize();
        Insets insets = result.getInsets();
        int minSize = iconSize + Math.max(insets.left + insets.right, insets.top + insets.bottom);
        result.setPreferredSize(new Dimension(minSize, minSize));
        return result;
    }

    public static void decorateButton(AbstractButton button, Icon icon, String toolTip) {
        button.setIcon(icon);
        button.setToolTipText(toolTip);
        button.setMargin(new Insets(0, 0, 0, 0));
        int iconSize = SizeHelper.getToolIconSize();
        Insets insets = button.getInsets();
        int minSize = iconSize + Math.max(insets.left + insets.right, insets.top + insets.bottom);
        button.setPreferredSize(new Dimension(minSize, minSize));
    }

    public static JButton createDialogButton(String text) {
        return new JButton(text) {
            @Override
            public Dimension getPreferredSize() {
                Dimension dimension = super.getPreferredSize();
                int h = dimension.height;
                int w = Math.max(dimension.width, Math.round(BUTTON_PREFERRED_ASPECT_RATIO * h));
                return new Dimension(w, h);
            }
        };
    }

    public static FlowLayout createFlowLayout() {
        return new FlowLayout(FlowLayout.LEFT, SizeHelper.getLayoutHGap(), SizeHelper.getLayoutVGap());
    }

    public static FlowLayout createNogapFlowLayout() {
        return new FlowLayout(FlowLayout.LEFT, 0, 0);
    }

    public static BorderLayout createBorderLayout() {
        return new BorderLayout(SizeHelper.getLayoutHGap(), SizeHelper.getLayoutVGap());
    }

    public static TableLayout createTableLayout(double[] columnSizes, double[] rowSizes) {
        TableLayout result = new TableLayout(new double[][]{columnSizes, rowSizes});
        result.setHGap(SizeHelper.getLayoutHGap());
        result.setVGap(SizeHelper.getLayoutVGap());
        return result;
    }

    public static GridLayout createNogapGridLayout(int rows, int cols) {
        return new GridLayout(rows, cols);
    }

    public static void setButtonPanelLayout(JPanel panel, Dimension buttonSize) {
        FlowLayout layout = new FlowLayout();
        panel.setLayout(layout);
        int hGap = layout.getHgap();
        int vGap = layout.getVgap();
        int buttonWidth = (int) Math.round(buttonSize.getWidth() + hGap);
        int buttonHeight = (int) Math.round(buttonSize.getHeight() + vGap);
        int buttonCount = panel.getComponentCount();
        Dimension panelSize = new Dimension(buttonWidth * buttonCount + hGap, buttonHeight + vGap);
        panel.setPreferredSize(panelSize);
        panel.setMaximumSize(panelSize);
    }

    public static Component createHGap() {
        return Box.createHorizontalStrut(SizeHelper.getLayoutHGap());
    }

    public static Component createVGap() {
        return Box.createVerticalStrut(SizeHelper.getLayoutVGap());
    }

    public static Border getEmptyBorder() {
        int gap = (int) Math.round(0.2 * SizeHelper.getBaseSize());
        return new EmptyBorder(gap, gap, gap, gap);
    }

    public static Border getEmptyLeftRightBorder() {
        int gap = (int) Math.round(0.2 * SizeHelper.getBaseSize());
        return new EmptyBorder(0, gap, 0, gap);
    }

    public static Border getGapBorder() {
        int vGap = SizeHelper.getLayoutVGap();
        int hGap = SizeHelper.getLayoutHGap();
        return new EmptyBorder(vGap, hGap, vGap, hGap);
    }

    public static Border getTitledBorder(String title) {
        return new CompoundBorder(new TitledBorder(title), getGapBorder());
    }

    public static Border getContentPanelBorder() {
        int vGap = SizeHelper.getLayoutVGap();
        int hGap = SizeHelper.getLayoutHGap();
        return new EmptyBorder(vGap, hGap, 0, hGap);
    }

    public static Border getTableCellBorder() {
        int vGap = SizeHelper.getCellVGap();
        int hGap = SizeHelper.getCellHGap();
        return new EmptyBorder(vGap, hGap, vGap, hGap);
    }

    public static Color getTableCellBackgroundColor() {
        return UIManager.getColor("Table.background");
    }

    public static Border getTableHeaderBorder() {
        return UIManager.getBorder("TableHeader.cellBorder");
    }

    public static Color getTableHeaderBackgroundColor() {
        return UIManager.getColor("TableHeader.background");
    }

    public static void paintBackgroundColor(Graphics g, Rectangle rect, Color color) {
        if (!ColorUtils.isOpaque(color)) {
            paintCheckedPattern(g, rect);
        }
        g.setColor(color);
        g.fillRect(rect.x, rect.y, rect.width, rect.height);
    }

    public static void paintCheckedPattern(Graphics g, Rectangle rect) {
        g.setClip(rect);
        g.setColor(Color.WHITE);
        g.fillRect(rect.x, rect.y, rect.width, rect.height);
        g.setColor(Color.GRAY);
        int size = SizeHelper.getCheckPatternSize();
        int doubleSize = 2 * size;
        int x = 0;
        while (x < rect.width) {
            int y = 0;
            while (y < rect.height) {
                g.fillRect(x, y, size, size);
                g.fillRect(x + size, y + size, size, size);
                y += doubleSize;
            }
            x += doubleSize;
        }
        g.setClip(null);
    }

    public static int getLabelTextWidth(JLabel label) {
        Border border = label.getBorder();
        Insets borderInsets = border == null ? new Insets(0, 0, 0, 0) : border.getBorderInsets(label);

        String text = label.getText();
        FontMetrics fontMetrics = label.getFontMetrics(label.getFont());
        int textWidth = (text == null) || (fontMetrics == null) ? 0 : fontMetrics.stringWidth(text);

        return textWidth + borderInsets.left + borderInsets.right;
    }

    public static double getTableColumnTextWidth(JTable table, int col) {
        TableColumn column = table.getColumnModel().getColumn(col);
        Dimension spacing = table.getIntercellSpacing();
        return column.getWidth() - spacing.getWidth();
    }

    public static void setColumnHeader(JTable table, int col, String text) {
        JTableHeader tableHeader = table.getTableHeader();
        TableColumnModel columnModel = tableHeader.getColumnModel();
        if ((col >= 0) && (col < columnModel.getColumnCount())) {
            TableColumn tableColumn = columnModel.getColumn(col);
            tableColumn.setHeaderValue(text);
            tableHeader.repaint();
        }
    }

    public static void setColumnWidth(JTable table, int col, int width) {
        JTableHeader tableHeader = table.getTableHeader();
        TableColumnModel columnModel = tableHeader.getColumnModel();
        if ((col >= 0) && (col < columnModel.getColumnCount())) {
            TableColumn tableColumn = columnModel.getColumn(col);
            tableColumn.setMaxWidth(width);
            tableColumn.setMinWidth(width);
            tableHeader.repaint();
        }
    }

    public static void refreshTable(JTable table) {
        table.tableChanged(new TableModelEvent(table.getModel()));
    }

    public static void boundWindow(Window window, Rectangle preferredBounds, Rectangle restrictionBounds) {
        int width = Math.min(preferredBounds.width, restrictionBounds.width);
        int height = Math.min(preferredBounds.height, restrictionBounds.height);
        int x = Math.max(preferredBounds.x, restrictionBounds.x);
        int y = Math.max(preferredBounds.y, restrictionBounds.y);
        x = Math.min(x, restrictionBounds.x + restrictionBounds.width - width);
        y = Math.min(y, restrictionBounds.y + restrictionBounds.height - height);
        window.setBounds(x, y, width, height);
    }

}