Package com.explodingpixels.macwidgets

Source Code of com.explodingpixels.macwidgets.HudWindow$BottomPanel

package com.explodingpixels.macwidgets;

import com.explodingpixels.widgets.WindowDragger;
import com.explodingpixels.widgets.WindowUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
* <p>
* An implementation of an OS X Transparent Panel, also known as a Heads Up Display (HUD). For a
* full descrption of what a Transparent Panel is, see the <a href="http://developer.apple.com/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGWindows/chapter_18_section_6.html#//apple_ref/doc/uid/20000961-SW24">Transparent Panels</a>
* section of Apple's Human Interface Guidelines.
* </p>
* <p>
* HUD's are designed to offer a lightweight way to unobtrusivley offer controls to the user. The window
* looks like this:
* <br>
* <img src="../../../../graphics/HeadsUpDisplay.png">
* <br>
* <p>
* As Apple points out, this component is not appropriate for all situations and should be used
* judiciously.
* </p>
*/
public class HudWindow {

    private final JDialog fDialog;

    private JComponent fContentPane;

    private final TitlePanel fTitlePanel;

    private final HudPanel fHudPanel = new HudPanel();

    private final BottomPanel fBottomPanel;

    private static final int ROUNDED_RECT_DIAMETER = 16;

    /**
     * Creates a Heads Up Display style window.
     */
    public HudWindow() {
        this("");
    }

    /**
     * Creates a Heads Up Display style window.
     *
     * @param title the title to use for this window.
     */
    public HudWindow(String title) {
        this(title, null);
    }

    /**
     * Creates a Heads Up Display style window.
     *
     * @param title the title to use for this window.
     * @param owner the {@link Frame} that this HUD is parented to. Can be null.
     */
    public HudWindow(String title, Frame owner) {
        fDialog = new JDialog(owner);
        fDialog.setTitle(title);
        fTitlePanel = new TitlePanel(title, createCloseButtonActionListener());
        fBottomPanel = new BottomPanel(fDialog);
        init();
    }

    private void init() {
        // indicate that this frame should not make all the content draggable. by default, when you
        // set the opacity to 0 (like we do below) this property automatically gets set to true.
        // also note that this client property must be set *before* changing the opacity (not sure
        // why).
        fDialog.getRootPane().putClientProperty("apple.awt.draggableWindowBackground", Boolean.FALSE);

        fDialog.setUndecorated(true);
        fDialog.setBackground(new Color(0, 0, 0, 0));

        fHudPanel.add(fTitlePanel, BorderLayout.NORTH);
//        fHudPanel.add(fBottomPanel, BorderLayout.SOUTH);

        // set the backing frame's content pane.
        fDialog.setContentPane(fHudPanel);
        // set the HUD panel's content pane to a blank JPanel by default.
        JPanel panel = new JPanel();
        panel.setOpaque(false);
        setContentPane(panel);

        // listen to the frame's title property so that we can update the label rendering the title.
        fDialog.addPropertyChangeListener("title", createTitlePropertyChangeListener());

        WindowUtils.createAndInstallRepaintWindowFocusListener(fDialog);
        // listen for focus changes in the window so that we can update the focus state of the title
        // panel (e.g. the font color).
        fTitlePanel.addPropertyChangeListener(
                WindowUtils.FRAME_ACTIVE_PROPERTY, createFrameFocusPropertyChangeListener());
        new WindowDragger(fDialog, fTitlePanel);
    }

    /**
     * Gets the {@link JDialog} backing this {@code HudWindow}.
     *
     * @return the {@code JDialog} backing this {@code HudWindow}.
     */
    public JDialog getJDialog() {
        return fDialog;
    }

    /**
     * Gets the {@link JComponent} to add content to.
     *
     * @return the container to add content to.
     */
    public JComponent getContentPane() {
        return fContentPane;
    }

    /**
     * Sets the {@link JComponent} to use as the container for this {@code HudWindow}'s content.
     *
     * @param contentPane the container for this {@code HudWindow}'s content.
     */
    public void setContentPane(JComponent contentPane) {
        // remove the old content pane if there was one.
        if (fContentPane != null) {
            fHudPanel.remove(fContentPane);
        }
        fContentPane = contentPane;
        fHudPanel.add(fContentPane, BorderLayout.CENTER);
    }

    private PropertyChangeListener createTitlePropertyChangeListener() {
        return new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                fTitlePanel.setTitle(fDialog.getTitle());
            }
        };
    }

    private PropertyChangeListener createFrameFocusPropertyChangeListener() {
        return new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                fTitlePanel.updateFocusState();
            }
        };
    }

    private ActionListener createCloseButtonActionListener() {
        return new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // simulate clicking the "real" close button on a window.
                fDialog.dispatchEvent(new WindowEvent(fDialog, WindowEvent.WINDOW_CLOSING));
            }
        };
    }

    private static class TitlePanel extends JPanel {

        private static final Color FONT_COLOR = new Color(255, 255, 255, 255);

        private static final Color UNFOCUSED_FONT_COLOR = new Color(0xcccccc);

        private static final Color HIGHLIGHT = new Color(255, 255, 255, 25);

        private static final Color TOP_BACKGROUND_TOP = new Color(255, 255, 255, 59);

        private static final Color TOP_BACKGROUND_BOTTOM = new Color(196, 196, 196, 59);

        private static final Color BOTTOM_BACKGROUND = new Color(255, 255, 255, 30);

        private static final Color UNFOCUSED_BACKGROUND = new Color(0, 0, 0, 10);

        private static final Icon CLOSE_ICON = new ImageIcon(
                TitlePanel.class.getResource(
                        "/com/explodingpixels/macwidgets/images/close.png"));

        private static final Icon CLOSE_HOVER_ICON = new ImageIcon(
                TitlePanel.class.getResource(
                        "/com/explodingpixels/macwidgets/images/close_hover.png"));

        private static final Icon CLOSE_PRESSED_ICON = new ImageIcon(
                TitlePanel.class.getResource(
                        "/com/explodingpixels/macwidgets/images/close_pressed.png"));

        private final JButton fCloseButton = new JButton(CLOSE_ICON);

        private final JLabel fLabel;

        private TitlePanel(String title, ActionListener closeButtonActionListener) {
            fLabel = new JLabel(title, SwingConstants.CENTER);
            fLabel.setFont(fLabel.getFont().deriveFont(Font.BOLD, 11.0f));

            fCloseButton.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
            fCloseButton.setVerticalAlignment(SwingConstants.CENTER);
            fCloseButton.setOpaque(false);
            fCloseButton.setFocusable(false);
            fCloseButton.setBorderPainted(false);
            fCloseButton.setContentAreaFilled(false);
            fCloseButton.setRolloverIcon(CLOSE_HOVER_ICON);
            fCloseButton.setPressedIcon(CLOSE_PRESSED_ICON);
            fCloseButton.addActionListener(closeButtonActionListener);

            setOpaque(false);
            setPreferredSize(new Dimension(-1, 20));
            updateFocusState();

            setLayout(new BorderLayout());
            add(fCloseButton, BorderLayout.WEST);
            add(fLabel, BorderLayout.CENTER);
            add(MacWidgetFactory.createSpacer(
                    fCloseButton.getPreferredSize().width, 0), BorderLayout.EAST);
        }

        private void setTitle(String title) {
            fLabel.setText(title);
        }

        private void updateFocusState() {
            Boolean focused = (Boolean) getClientProperty(WindowUtils.FRAME_ACTIVE_PROPERTY);
            fLabel.setForeground(focused == null || focused ? FONT_COLOR : UNFOCUSED_FONT_COLOR);
        }

        @Override
        protected void paintComponent(Graphics g) {
            // create a copy of the graphics object and turn on anti-aliasing.
            Graphics2D graphics2d = (Graphics2D) g.create();
            graphics2d.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // calculate the point in the title bar at which to change the background color.
            int midPointY = ROUNDED_RECT_DIAMETER / 2 + 3;

            // if the window has focus, draw a shiny title bar.
            // else draw a flat background.
            if (WindowUtils.isParentWindowFocused(this)) {
                // 1. The top half --------------------------------------------------------------//
                // create and set the shiny paint.
                GradientPaint paint =
                        new GradientPaint(0, 0, TOP_BACKGROUND_TOP, 0, midPointY, TOP_BACKGROUND_BOTTOM);
                graphics2d.setPaint(paint);
                // create a rounded rectangle area as big as the entire title bar, then subtract
                // off the bottom half (roughly) in order to have perfectly square edges.
                Area titleArea = new Area(new Area(new RoundRectangle2D.Double(
                        0, 0, getWidth(), getHeight(), ROUNDED_RECT_DIAMETER, ROUNDED_RECT_DIAMETER)));
                titleArea.subtract(new Area(new Rectangle(0, midPointY, getWidth(), midPointY)));
                // draw the top half of the title bar (the shine).
                graphics2d.fill(titleArea);
                // 2. The bottom half -----------------------------------------------------------//
                // draw the bottom half of the title bar.
                int bottomHeight = getHeight() - midPointY;
                graphics2d.setColor(BOTTOM_BACKGROUND);
                graphics2d.fillRect(0, midPointY, getWidth(), bottomHeight);
            } else {
                // create an area that has rounded corners at the top and square corners at the
                // bottom.
                graphics2d.setColor(UNFOCUSED_BACKGROUND);
                Area titleArea = new Area(new Area(new RoundRectangle2D.Double(
                        0, 0, getWidth(), getHeight(), ROUNDED_RECT_DIAMETER, ROUNDED_RECT_DIAMETER)));
                titleArea.subtract(new Area(
                        new Rectangle(0, midPointY, getWidth(), midPointY)));
                graphics2d.fill(titleArea);
                graphics2d.setColor(HIGHLIGHT);
                graphics2d.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1);
            }

            graphics2d.dispose();
        }

    }

    private static class HudPanel extends JPanel {

        private static final Color HIGHLIGHT = new Color(255, 255, 255, 59);

        private static final Color HIGHLIGHT_BOTTOM = new Color(255, 255, 255, 25);

        private static final Color BACKGROUND = new Color(30, 30, 30, 216);

        private HudPanel() {
            setLayout(new BorderLayout());
            setOpaque(false);
        }

        @Override
        protected void paintBorder(Graphics g) {
            // create a copy of the graphics object and turn on anti-aliasing.
            Graphics2D graphics2d = (Graphics2D) g.create();
            graphics2d.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // paint a border around the window that fades slightly to give a more pleasnt highlight
            // to the window edges.
            GradientPaint paint = new GradientPaint(0, 0, HIGHLIGHT, 0, getHeight(), HIGHLIGHT_BOTTOM);
            graphics2d.setPaint(paint);
            graphics2d.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, ROUNDED_RECT_DIAMETER,
                    ROUNDED_RECT_DIAMETER);

            graphics2d.dispose();
        }

        @Override
        protected void paintComponent(Graphics g) {
            // create a copy of the graphics object and turn on anti-aliasing.
            Graphics2D graphics2d = (Graphics2D) g.create();
            graphics2d.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            graphics2d.setComposite(AlphaComposite.Src);

            // draw the rounded rectangle background of the window.
            graphics2d.setColor(BACKGROUND);
            graphics2d.fillRoundRect(0, 0, getWidth(), getHeight(),
                    ROUNDED_RECT_DIAMETER, ROUNDED_RECT_DIAMETER);
            // tell the shadow to revalidate.
            getRootPane().putClientProperty("apple.awt.windowShadow.revalidateNow", new Object());

            graphics2d.dispose();
        }

    }

    private static class BottomPanel extends JPanel {

        private static final Icon RESIZE_ICON = new ImageIcon(
                TitlePanel.class.getResource(
                        "/com/explodingpixels/macwidgets/images/resize_corner_dark.png"));

        private final Window fWindow;

        private final JLabel fResizeCorner = new JLabel(RESIZE_ICON);

        private int fXOffsetToWindowEdge;

        private int fYOffsetToWidnowEdge;

        public BottomPanel(Window window) {
            super(new FlowLayout(SwingConstants.RIGHT));
            fWindow = window;
            add(fResizeCorner);
            fResizeCorner.addMouseListener(createMouseListener());
            fResizeCorner.addMouseMotionListener(createMouseMotionListener());
        }

        private MouseAdapter createMouseListener() {
            return new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    Point windowPoint =
                            SwingUtilities.convertPoint(fResizeCorner, e.getPoint(), fWindow);
                    fXOffsetToWindowEdge = fWindow.getWidth() - windowPoint.x;
                    fYOffsetToWidnowEdge = fWindow.getHeight() - windowPoint.y;
                }
            };
        }

        private MouseMotionListener createMouseMotionListener() {
            return new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    Point windowPoint = SwingUtilities.convertPoint(fResizeCorner, e.getPoint(), fWindow);
                    fWindow.setSize(windowPoint.x + fXOffsetToWindowEdge,
                            windowPoint.y + fYOffsetToWidnowEdge);

                }
            };
        }

    }
}
TOP

Related Classes of com.explodingpixels.macwidgets.HudWindow$BottomPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.