All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jdesktop.swingx.plaf.basic.BasicStatusBarUI Maven / Gradle / Ivy

/*
 * $Id: BasicStatusBarUI.java 3249 2009-02-04 19:53:56Z kschaefe $
 *
 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package org.jdesktop.swingx.plaf.basic;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;

import org.jdesktop.swingx.JXStatusBar;
import org.jdesktop.swingx.JXStatusBar.Constraint;
import org.jdesktop.swingx.plaf.StatusBarUI;
import org.jdesktop.swingx.plaf.UIManagerExt;

/**
 *
 * @author rbair
 * @author Karl Schaefer
 */
public class BasicStatusBarUI extends StatusBarUI {
    private class Handler implements MouseListener, MouseMotionListener, PropertyChangeListener {
        private Window window = SwingUtilities.getWindowAncestor(statusBar);
        private int handleBoundary = getHandleBoundary();
        private boolean validPress = false;
        private Point startingPoint;
        
        private int getHandleBoundary() {
            Border border = statusBar.getBorder();
            
            if (border == null || !statusBar.isResizeHandleEnabled()) {
                return 0;
            }
            
            if (statusBar.getComponentOrientation().isLeftToRight()) {
                return border.getBorderInsets(statusBar).right;
            } else {
                return border.getBorderInsets(statusBar).left;
            }
        }
        
        private boolean isHandleAreaPoint(Point point) {
            if (window == null || window.isMaximumSizeSet()) {
                return false;
            }
            
            if (statusBar.getComponentOrientation().isLeftToRight()) {
                return point.x >= statusBar.getWidth() - handleBoundary;
            } else {
                return point.x <= handleBoundary;
            }
        }
        
        /**
         * {@inheritDoc}
         */
        public void mouseClicked(MouseEvent e) {
            //does nothing
        }

        /**
         * {@inheritDoc}
         */
        public void mouseEntered(MouseEvent e) {
            if (isHandleAreaPoint(e.getPoint())) {
                if (statusBar.getComponentOrientation().isLeftToRight()) {
                    window.setCursor(Cursor.getPredefinedCursor(
                            Cursor.SE_RESIZE_CURSOR));
                } else {
                    window.setCursor(Cursor.getPredefinedCursor(
                            Cursor.SW_RESIZE_CURSOR));
                }
            } else {
                window.setCursor(null);
            }
        }

        /**
         * {@inheritDoc}
         */
        public void mouseExited(MouseEvent e) {
            if (!validPress) {
                window.setCursor(null);
            }
        }

        /**
         * {@inheritDoc}
         */
        public void mousePressed(MouseEvent e) {
            validPress = SwingUtilities.isLeftMouseButton(e) && isHandleAreaPoint(e.getPoint()); 
            startingPoint = e.getPoint();
            SwingUtilities.convertPointToScreen(startingPoint, statusBar);
        }

        /**
         * {@inheritDoc}
         */
        public void mouseReleased(MouseEvent e) {
            validPress = !SwingUtilities.isLeftMouseButton(e);
            window.validate();
            window.setCursor(null);
        }

        /**
         * {@inheritDoc}
         */
        public void mouseDragged(MouseEvent e) {
            if (validPress) {
                Rectangle wb = window.getBounds();
                Point p = e.getPoint();
                SwingUtilities.convertPointToScreen(p, statusBar);
                
                wb.height += (p.y - startingPoint.y);
                if (statusBar.getComponentOrientation().isLeftToRight()) {
                    wb.width += (p.x - startingPoint.x);
                } else {
                    wb.x += (p.x - startingPoint.x);
                    wb.width += (startingPoint.x - p.x);
                }
                
                window.setBounds(wb);
                window.validate();
                startingPoint = p;
            }
        }

        /**
         * {@inheritDoc}
         */
        public void mouseMoved(MouseEvent e) {
            if (isHandleAreaPoint(e.getPoint())) {
                if (statusBar.getComponentOrientation().isLeftToRight()) {
                    window.setCursor(Cursor.getPredefinedCursor(
                            Cursor.SE_RESIZE_CURSOR));
                } else {
                    window.setCursor(Cursor.getPredefinedCursor(
                            Cursor.SW_RESIZE_CURSOR));
                }
            } else {
                window.setCursor(null);
            }
        }

        /**
         * {@inheritDoc}
         */
        public void propertyChange(PropertyChangeEvent evt) {
            if ("ancestor".equals(evt.getPropertyName())) {
                window = SwingUtilities.getWindowAncestor(statusBar);
                
                boolean useResizeHandle = statusBar.getParent() != null
                        && statusBar.getRootPane() != null
                        && (statusBar.getParent() == statusBar.getRootPane()
                        || statusBar.getParent() == statusBar.getRootPane().getContentPane());
                statusBar.setResizeHandleEnabled(useResizeHandle);
            } else if ("border".equals(evt.getPropertyName())) {
                handleBoundary = getHandleBoundary();
            } else if ("componentOrientation".equals(evt.getPropertyName())) {
                handleBoundary = getHandleBoundary();
            } else if ("resizeHandleEnabled".equals(evt.getPropertyName())) {
                //TODO disable handle display
                handleBoundary = getHandleBoundary();
            }
        }
    }
    
    public static final String AUTO_ADD_SEPARATOR = new StringBuffer("auto-add-separator").toString();
    /**
     * Used to help reduce the amount of trash being generated
     */
    private static Insets TEMP_INSETS;
    /**
     * The one and only JXStatusBar for this UI delegate
     */
    protected JXStatusBar statusBar;
    
    protected MouseListener mouseListener;
    
    protected MouseMotionListener mouseMotionListener;
    
    protected PropertyChangeListener propertyChangeListener;
    
    private Handler handler;
    
    /** Creates a new instance of BasicStatusBarUI */
    public BasicStatusBarUI() {
    }
    
    /**
     * Returns an instance of the UI delegate for the specified component.
     * Each subclass must provide its own static createUI
     * method that returns an instance of that UI delegate subclass.
     * If the UI delegate subclass is stateless, it may return an instance
     * that is shared by multiple components.  If the UI delegate is
     * stateful, then it should return a new instance per component.
     * The default implementation of this method throws an error, as it
     * should never be invoked.
     */
    public static ComponentUI createUI(JComponent c) {
        return new BasicStatusBarUI();
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void installUI(JComponent c) {
        assert c instanceof JXStatusBar;
        statusBar = (JXStatusBar)c;
        
        installDefaults(statusBar);
        installListeners(statusBar);
        
        // only set the layout manager if the layout manager of the component is
        // null or a UIResource. Do not replace custom layout managers.
        LayoutManager m = statusBar.getLayout();
        if (m == null || m instanceof UIResource) {
            statusBar.setLayout(createLayout());
        }
    }
    
    protected void installDefaults(JXStatusBar sb) {
        //only set the border if it is an instanceof UIResource
        //In other words, only replace the border if it has not been
        //set by the developer. UIResource is the flag we use to indicate whether
        //the value was set by the UIDelegate, or by the developer.
        Border b = statusBar.getBorder();
        if (b == null || b instanceof UIResource) {
            statusBar.setBorder(createBorder());
        }
        
        LookAndFeel.installProperty(sb, "opaque", Boolean.TRUE);
    }
    
    private Handler getHandler() {
        if (handler == null) {
            handler = new Handler();
        }
        
        return handler;
    }
    
    /**
     * Creates a {@code MouseListener} which will be added to the 
     * status bar. If this method returns null then it will not 
     * be added to the status bar.
     * 

* Subclasses may override this method to return instances of their own * MouseEvent handlers. * * @return an instance of a {@code MouseListener} or null */ protected MouseListener createMouseListener() { return getHandler(); } /** * Creates a {@code MouseMotionListener} which will be added to the * status bar. If this method returns null then it will not * be added to the status bar. *

* Subclasses may override this method to return instances of their own * MouseEvent handlers. * * @return an instance of a {@code MouseMotionListener} or null */ protected MouseMotionListener createMouseMotionListener() { return getHandler(); } /** * Creates a {@code PropertyChangeListener} which will be added to the * status bar. If this method returns null then it will not * be added to the status bar. *

* Subclasses may override this method to return instances of their own * PropertyChangeEvent handlers. * * @return an instance of a {@code PropertyChangeListener} or null */ protected PropertyChangeListener createPropertyChangeListener() { return getHandler(); } /** * Create and install the listeners for the status bar. * This method is called when the UI is installed. */ protected void installListeners(JXStatusBar sb) { if ((mouseListener = createMouseListener()) != null) { statusBar.addMouseListener(mouseListener); } if ((mouseMotionListener = createMouseMotionListener()) != null) { statusBar.addMouseMotionListener(mouseMotionListener); } if ((propertyChangeListener = createPropertyChangeListener()) != null) { statusBar.addPropertyChangeListener(propertyChangeListener); } } /** * {@inheritDoc} */ @Override public void uninstallUI(JComponent c) { assert c instanceof JXStatusBar; uninstallDefaults(statusBar); uninstallListeners(statusBar); if (statusBar.getLayout() instanceof UIResource) { statusBar.setLayout(null); } } protected void uninstallDefaults(JXStatusBar sb) { if (sb.getBorder() instanceof UIResource) { sb.setBorder(null); } } /** * Remove the installed listeners from the status bar. * The number and types of listeners removed in this method should be * the same that were added in installListeners */ protected void uninstallListeners(JXStatusBar sb) { if (mouseListener != null) { statusBar.removeMouseListener(mouseListener); } if (mouseMotionListener != null) { statusBar.removeMouseMotionListener(mouseMotionListener); } if (propertyChangeListener != null) { statusBar.removePropertyChangeListener(propertyChangeListener); } } @Override public void paint(Graphics g, JComponent c) { //paint the background if opaque if (statusBar.isOpaque()) { Graphics2D g2 = (Graphics2D)g; paintBackground(g2, statusBar); } if (includeSeparators()) { //now paint the separators TEMP_INSETS = getSeparatorInsets(TEMP_INSETS); for (int i=0; i constraints = new HashMap(); public void addLayoutComponent(String name, Component comp) {addLayoutComponent(comp, null);} public void removeLayoutComponent(Component comp) {constraints.remove(comp);} public Dimension minimumLayoutSize(Container parent) {return preferredLayoutSize(parent);} public Dimension maximumLayoutSize(Container target) {return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);} public float getLayoutAlignmentX(Container target) {return .5f;} public float getLayoutAlignmentY(Container target) {return .5f;} public void invalidateLayout(Container target) {} public void addLayoutComponent(Component comp, Object constraint) { //we accept an Insets, a ResizeBehavior, or a Constraint. if (constraint instanceof Insets) { constraint = new Constraint((Insets)constraint); } else if (constraint instanceof Constraint.ResizeBehavior) { constraint = new Constraint((Constraint.ResizeBehavior)constraint); } constraints.put(comp, (Constraint)constraint); } public Dimension preferredLayoutSize(Container parent) { Dimension prefSize = new Dimension(); int count = 0; for (Component comp : constraints.keySet()) { Constraint c = constraints.get(comp); Dimension d = comp.getPreferredSize(); int prefWidth = 0; if (c != null) { Insets i = c.getInsets(); d.width += i.left + i.right; d.height += i.top + i.bottom; prefWidth = c.getFixedWidth(); } prefSize.height = Math.max(prefSize.height, d.height); prefSize.width += Math.max(d.width, prefWidth); //If this is not the last component, add extra space between each //component (for the separator). count++; if (includeSeparators() && constraints.size() < count) { prefSize.width += getSeparatorWidth(); } } Insets insets = parent.getInsets(); prefSize.height += insets.top + insets.bottom; prefSize.width += insets.left + insets.right; return prefSize; } public void layoutContainer(Container parent) { /* * Layout algorithm: * If the parent width is less than the sum of the preferred * widths of the components (including separators), where * preferred width means either the component preferred width + * constraint insets, or fixed width + constraint insets, then * simply layout the container from left to right and let the * right hand components flow off the parent. * * Otherwise, lay out each component according to its preferred * width except for components with a FILL constraint. For these, * resize them evenly for each FILL constraint. */ //the insets of the parent component. Insets parentInsets = parent.getInsets(); //the available width for putting components. int availableWidth = parent.getWidth() - parentInsets.left - parentInsets.right; if (includeSeparators()) { //remove from availableWidth the amount of space the separators will take availableWidth -= (parent.getComponentCount() - 1) * getSeparatorWidth(); } //the preferred widths of all of the components -- where preferred //width mean the preferred width after calculating fixed widths and //constraint insets int[] preferredWidths = new int[parent.getComponentCount()]; int sumPreferredWidths = 0; for (int i=0; i sumPreferredWidths) { //the number of components with a fill constraint int numFilledComponents = 0; for (Component comp : parent.getComponents()) { Constraint c = constraints.get(comp); if (c != null && c.getResizeBehavior() == Constraint.ResizeBehavior.FILL) { numFilledComponents++; } } if (numFilledComponents > 0) { //calculate the share of free space each FILL component will take availableWidth -= sumPreferredWidths; double weight = 1.0 / (double)numFilledComponents; int share = (int)(availableWidth * weight); int remaining = numFilledComponents; for (int i=0; i 1) { preferredWidths[i] += share; availableWidth -= share; } else { preferredWidths[i] += availableWidth; } remaining--; } } } } //now lay out the components int nextX = parentInsets.left; int height = parent.getHeight() - parentInsets.top - parentInsets.bottom; for (int i=0; i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy