/* * This file is part of WebLookAndFeel library. * * WebLookAndFeel library is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * WebLookAndFeel 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with WebLookAndFeel library. If not, see . */ package com.alee.laf.progressbar; import com.alee.global.StyleConstants; import com.alee.laf.WebLookAndFeel; import com.alee.utils.GraphicsUtils; import com.alee.utils.LafUtils; import com.alee.utils.SwingUtils; import com.alee.utils.ThreadUtils; import com.alee.utils.laf.ShapeProvider; import com.alee.utils.swing.AncestorAdapter; import com.alee.utils.swing.BorderMethods; import com.alee.utils.swing.WebTimer; import javax.swing.*; import javax.swing.event.AncestorEvent; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicProgressBarUI; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * User: mgarin Date: 28.04.11 Time: 15:05 */ public class WebProgressBarUI extends BasicProgressBarUI implements ShapeProvider, BorderMethods { private static final int indeterminateStep = 20; private static final int determinateAnimationWidth = 120; private static final AffineTransform moveX = new AffineTransform (); static { moveX.translate ( indeterminateStep * 2, 0 ); } private Color bgTop = WebProgressBarStyle.bgTop; private Color bgBottom = WebProgressBarStyle.bgBottom; private Color progressTopColor = WebProgressBarStyle.progressTopColor; private Color progressBottomColor = WebProgressBarStyle.progressBottomColor; private Color indeterminateBorder = WebProgressBarStyle.indeterminateBorder; private Color highlightWhite = WebProgressBarStyle.highlightWhite; private Color highlightDarkWhite = WebProgressBarStyle.highlightDarkWhite; private int round = WebProgressBarStyle.round; private int innerRound = WebProgressBarStyle.innerRound; private int shadeWidth = WebProgressBarStyle.shadeWidth; private boolean paintIndeterminateBorder = WebProgressBarStyle.paintIndeterminateBorder; private int preferredProgressWidth = WebProgressBarStyle.preferredProgressWidth; private final int determinateAnimationPause = 1500; private int animationLocation = 0; private WebTimer animator = null; private PropertyChangeListener propertyChangeListener; @SuppressWarnings ("UnusedParameters") public static ComponentUI createUI ( final JComponent c ) { return new WebProgressBarUI (); } @Override public void installUI ( final JComponent c ) { super.installUI ( c ); // Default settings SwingUtils.setOrientation ( progressBar ); LookAndFeel.installProperty ( progressBar, WebLookAndFeel.OPAQUE_PROPERTY, Boolean.FALSE ); progressBar.setBorderPainted ( false ); progressBar.setForeground ( Color.DARK_GRAY ); // Updating border updateBorder (); // Change listeners propertyChangeListener = new PropertyChangeListener () { @Override public void propertyChange ( final PropertyChangeEvent evt ) { updateAnimator ( progressBar ); } }; progressBar.addPropertyChangeListener ( "indeterminate", propertyChangeListener ); progressBar.addPropertyChangeListener ( "enabled", propertyChangeListener ); updateAnimator ( progressBar ); c.addAncestorListener ( new AncestorAdapter () { @Override public void ancestorAdded ( final AncestorEvent event ) { updateAnimator ( progressBar ); } @Override public void ancestorRemoved ( final AncestorEvent event ) { updateAnimator ( progressBar ); } } ); } @Override public void uninstallUI ( final JComponent c ) { c.removePropertyChangeListener ( propertyChangeListener ); if ( animator != null ) { animator.stop (); } super.uninstallUI ( c ); } /** * {@inheritDoc} */ @Override public void updateBorder () { if ( progressBar != null ) { // Preserve old borders if ( SwingUtils.isPreserveBorders ( progressBar ) ) { return; } progressBar.setBorder ( LafUtils.createWebBorder ( shadeWidth + 1, shadeWidth + 1, shadeWidth + 1, shadeWidth + 1 ) ); } } public int getRound () { return round; } public void setRound ( final int round ) { this.round = round; } public int getInnerRound () { return innerRound; } public void setInnerRound ( final int innerRound ) { this.innerRound = innerRound; } public int getShadeWidth () { return shadeWidth; } public void setShadeWidth ( final int shadeWidth ) { this.shadeWidth = shadeWidth; updateBorder (); } public boolean isPaintIndeterminateBorder () { return paintIndeterminateBorder; } public void setPaintIndeterminateBorder ( final boolean paintIndeterminateBorder ) { this.paintIndeterminateBorder = paintIndeterminateBorder; } public int getPreferredProgressWidth () { return preferredProgressWidth; } public void setPreferredProgressWidth ( final int preferredProgressWidth ) { this.preferredProgressWidth = preferredProgressWidth; } public Color getBgTop () { return bgTop; } public void setBgTop ( final Color bgTop ) { this.bgTop = bgTop; } public Color getBgBottom () { return bgBottom; } public void setBgBottom ( final Color bgBottom ) { this.bgBottom = bgBottom; } public Color getProgressTopColor () { return progressTopColor; } public void setProgressTopColor ( final Color progressTopColor ) { this.progressTopColor = progressTopColor; } public Color getProgressBottomColor () { return progressBottomColor; } public void setProgressBottomColor ( final Color progressBottomColor ) { this.progressBottomColor = progressBottomColor; } public Color getIndeterminateBorder () { return indeterminateBorder; } public void setIndeterminateBorder ( final Color indeterminateBorder ) { this.indeterminateBorder = indeterminateBorder; } public Color getHighlightWhite () { return highlightWhite; } public void setHighlightWhite ( final Color highlightWhite ) { this.highlightWhite = highlightWhite; } public Color getHighlightDarkWhite () { return highlightDarkWhite; } public void setHighlightDarkWhite ( final Color highlightDarkWhite ) { this.highlightDarkWhite = highlightDarkWhite; } @Override public Shape provideShape () { return LafUtils.getWebBorderShape ( progressBar, getShadeWidth (), getRound () ); } private void updateAnimator ( final JProgressBar progressBar ) { if ( animator != null ) { animator.stop (); } if ( SwingUtils.getWindowAncestor ( progressBar ) != null && progressBar.isShowing () ) { if ( progressBar.isEnabled () ) { if ( progressBar.isIndeterminate () ) { animationLocation = 0; animator = new WebTimer ( "WebProgressBarUI.animator", StyleConstants.animationDelay, new ActionListener () { @Override public void actionPerformed ( final ActionEvent e ) { if ( animationLocation < indeterminateStep * 2 - 1 ) { animationLocation++; } else { animationLocation = 0; } SwingUtilities.invokeLater ( new Runnable () { @Override public void run () { progressBar.repaint (); } } ); } } ); animator.setUseEventDispatchThread ( false ); } else { animationLocation = -determinateAnimationWidth; animator = new WebTimer ( "WebProgressBarUI.animator", StyleConstants.animationDelay, new ActionListener () { @Override public void actionPerformed ( final ActionEvent e ) { if ( animationLocation < getProgressWidth () ) { animationLocation += 15; refresh ( progressBar ); } else { animationLocation = -determinateAnimationWidth; refresh ( progressBar ); ThreadUtils.sleepSafely ( determinateAnimationPause ); } } private void refresh ( final JProgressBar progressBar ) { if ( !progressBar.isIndeterminate () && progressBar.getValue () > progressBar.getMinimum () ) { SwingUtilities.invokeLater ( new Runnable () { @Override public void run () { progressBar.repaint (); } } ); } } } ); } animator.setUseEventDispatchThread ( false ); animator.start (); } } } @Override protected Dimension getPreferredInnerHorizontal () { final Dimension ph = super.getPreferredInnerHorizontal (); ph.width = preferredProgressWidth; return ph; } @Override protected Dimension getPreferredInnerVertical () { final Dimension pv = super.getPreferredInnerVertical (); pv.height = preferredProgressWidth; return pv; } @Override public void paint ( final Graphics g, final JComponent c ) { final Object aa = GraphicsUtils.setupAntialias ( g ); super.paint ( g, c ); GraphicsUtils.restoreAntialias ( g, aa ); } @Override protected void paintIndeterminate ( final Graphics g, final JComponent c ) { final Graphics2D g2d = ( Graphics2D ) g; // Outer border paintProgressBarBorder ( c, g2d ); // Indeterminate view final Shape is = getProgressShape ( c ); final Shape oldClip = g2d.getClip (); final Area newClip = new Area ( is ); newClip.intersect ( new Area ( oldClip ) ); g2d.setClip ( newClip ); final GeneralPath bs = getIndeterminateProgressShape ( c ); final AffineTransform at = new AffineTransform (); at.translate ( animationLocation, 0 ); bs.transform ( at ); int x = 0; while ( x < c.getWidth () - shadeWidth * 2 - 4 - 1 + indeterminateStep * 2 ) { g2d.setPaint ( new GradientPaint ( 0, shadeWidth, progressTopColor, 0, c.getHeight () - shadeWidth, progressBottomColor ) ); g2d.fill ( bs ); if ( paintIndeterminateBorder ) { g2d.setPaint ( indeterminateBorder ); g2d.draw ( bs ); } x += indeterminateStep * 2; bs.transform ( moveX ); } if ( progressBar.isStringPainted () && progressBar.getString () != null && progressBar.getString ().trim ().length () > 0 ) { final int tw = g2d.getFontMetrics ().stringWidth ( progressBar.getString () ); final float percentage = ( float ) tw / ( progressBar.getWidth () * 2 ); final float start = 0.5f - percentage; final float end = 0.5f + percentage; g2d.setPaint ( new LinearGradientPaint ( 0, 0, progressBar.getWidth (), 0, new float[]{ start / 2, start, end, end + ( 1f - end ) / 2 }, new Color[]{ StyleConstants.transparent, highlightWhite, highlightWhite, StyleConstants.transparent } ) ); g2d.fill ( is ); } g2d.setClip ( oldClip ); // Inner border if ( c.isEnabled () ) { GraphicsUtils.drawShade ( g2d, is, StyleConstants.shadeColor, shadeWidth ); } g2d.setPaint ( c.isEnabled () ? Color.GRAY : Color.LIGHT_GRAY ); g2d.draw ( is ); // Text drawProgressBarText ( g2d ); } @Override protected void paintDeterminate ( final Graphics g, final JComponent c ) { final Graphics2D g2d = ( Graphics2D ) g; // Outer border paintProgressBarBorder ( c, g2d ); // Progress bar if ( progressBar.getValue () > progressBar.getMinimum () ) { final Shape is = getInnerProgressShape ( c ); if ( c.isEnabled () ) { GraphicsUtils.drawShade ( g2d, is, StyleConstants.shadeColor, shadeWidth ); } if ( progressBar.getOrientation () == JProgressBar.HORIZONTAL ) { g2d.setPaint ( new GradientPaint ( 0, shadeWidth, progressTopColor, 0, c.getHeight () - shadeWidth, progressBottomColor ) ); } else { if ( progressBar.getComponentOrientation ().isLeftToRight () ) { g2d.setPaint ( new GradientPaint ( shadeWidth, 0, progressTopColor, c.getWidth () - shadeWidth, 0, progressBottomColor ) ); } else { g2d.setPaint ( new GradientPaint ( shadeWidth, 0, progressBottomColor, c.getWidth () - shadeWidth, 0, progressTopColor ) ); } } g2d.fill ( is ); // Running highlight if ( c.isEnabled () ) { final Shape oldClip = g2d.getClip (); final Area newClip = new Area ( is ); newClip.intersect ( new Area ( oldClip ) ); g2d.setClip ( newClip ); if ( progressBar.getOrientation () == JProgressBar.HORIZONTAL ) { g2d.setPaint ( new RadialGradientPaint ( shadeWidth * 2 + animationLocation + determinateAnimationWidth / 2, progressBar.getHeight () / 2, determinateAnimationWidth / 2, new float[]{ 0f, 1f }, new Color[]{ highlightDarkWhite, StyleConstants.transparent } ) ); } else { if ( progressBar.getComponentOrientation ().isLeftToRight () ) { g2d.setPaint ( new RadialGradientPaint ( c.getWidth () / 2, c.getHeight () - shadeWidth * 2 - animationLocation - determinateAnimationWidth / 2, determinateAnimationWidth / 2, new float[]{ 0f, 1f }, new Color[]{ highlightDarkWhite, StyleConstants.transparent } ) ); } else { g2d.setPaint ( new RadialGradientPaint ( c.getWidth () / 2, shadeWidth * 2 + animationLocation + determinateAnimationWidth / 2, determinateAnimationWidth / 2, new float[]{ 0f, 1f }, new Color[]{ highlightDarkWhite, StyleConstants.transparent } ) ); } } g2d.fill ( is ); g2d.setClip ( oldClip ); } // Border g2d.setPaint ( c.isEnabled () ? Color.GRAY : Color.LIGHT_GRAY ); g2d.draw ( is ); } // Text drawProgressBarText ( g2d ); } private void drawProgressBarText ( final Graphics2D g2d ) { if ( progressBar.isStringPainted () ) { if ( progressBar.getOrientation () == JProgressBar.VERTICAL ) { g2d.translate ( progressBar.getWidth () / 2, progressBar.getHeight () / 2 ); g2d.rotate ( ( progressBar.getComponentOrientation ().isLeftToRight () ? -1 : 1 ) * Math.PI / 2 ); g2d.translate ( -progressBar.getWidth () / 2, -progressBar.getHeight () / 2 ); } final String string = progressBar.getString (); final Point ts = LafUtils.getTextCenterShear ( g2d.getFontMetrics (), string ); if ( !progressBar.isEnabled () ) { g2d.setPaint ( Color.WHITE ); g2d.drawString ( string, progressBar.getWidth () / 2 + ts.x + 1, progressBar.getHeight () / 2 + ts.y + 1 ); } g2d.setPaint ( progressBar.isEnabled () ? progressBar.getForeground () : StyleConstants.disabledTextColor ); g2d.drawString ( string, progressBar.getWidth () / 2 + ts.x, progressBar.getHeight () / 2 + ts.y ); if ( progressBar.getOrientation () == JProgressBar.VERTICAL ) { g2d.rotate ( ( progressBar.getComponentOrientation ().isLeftToRight () ? 1 : -1 ) * Math.PI / 2 ); } } } private void paintProgressBarBorder ( final JComponent c, final Graphics2D g2d ) { final Shape bs = getProgressShape ( c ); if ( c.isEnabled () ) { GraphicsUtils.drawShade ( g2d, bs, StyleConstants.shadeColor, shadeWidth ); } if ( progressBar.getOrientation () == JProgressBar.HORIZONTAL ) { g2d.setPaint ( new GradientPaint ( 0, shadeWidth, bgTop, 0, c.getHeight () - shadeWidth, bgBottom ) ); } else { g2d.setPaint ( new GradientPaint ( shadeWidth, 0, bgTop, c.getWidth () - shadeWidth, 0, bgBottom ) ); } g2d.fill ( bs ); g2d.setPaint ( c.isEnabled () ? Color.GRAY : Color.LIGHT_GRAY ); g2d.draw ( bs ); } private Shape getProgressShape ( final JComponent c ) { if ( round > 0 ) { return new RoundRectangle2D.Double ( shadeWidth, shadeWidth, c.getWidth () - shadeWidth * 2 - 1, c.getHeight () - shadeWidth * 2 - 1, round * 2, round * 2 ); } else { return new Rectangle2D.Double ( shadeWidth, shadeWidth, c.getWidth () - shadeWidth * 2 - 1, c.getHeight () - shadeWidth * 2 - 1 ); } } private Shape getInnerProgressShape ( final JComponent c ) { final int progress = getProgressWidth (); if ( progressBar.getOrientation () == JProgressBar.HORIZONTAL ) { if ( innerRound > 0 ) { return new RoundRectangle2D.Double ( shadeWidth * 2, shadeWidth * 2, progress - 1, c.getHeight () - shadeWidth * 4 - 1, innerRound * 2, innerRound * 2 ); } else { return new Rectangle2D.Double ( shadeWidth * 2, shadeWidth * 2, progress - 1, c.getHeight () - shadeWidth * 4 - 1 ); } } else { if ( progressBar.getComponentOrientation ().isLeftToRight () ) { if ( innerRound > 0 ) { return new RoundRectangle2D.Double ( shadeWidth * 2, c.getHeight () - progress - shadeWidth * 2, c.getWidth () - shadeWidth * 4 - 1, progress - 1, innerRound * 2, innerRound * 2 ); } else { return new Rectangle2D.Double ( shadeWidth * 2, c.getHeight () - progress - shadeWidth * 2, c.getWidth () - shadeWidth * 4 - 1, progress - 1 ); } } else { if ( innerRound > 0 ) { return new RoundRectangle2D.Double ( shadeWidth * 2, shadeWidth * 2, c.getWidth () - shadeWidth * 4 - 1, progress - 1, innerRound * 2, innerRound * 2 ); } else { return new Rectangle2D.Double ( shadeWidth * 2, shadeWidth * 2, c.getWidth () - shadeWidth * 4 - 1, progress - 1 ); } } } } private int getProgressWidth () { final int progress; if ( progressBar.isIndeterminate () ) { if ( progressBar.getOrientation () == JProgressBar.HORIZONTAL ) { progress = progressBar.getWidth () - shadeWidth * 4; } else { progress = progressBar.getHeight () - shadeWidth * 4; } } else { if ( progressBar.getOrientation () == JProgressBar.HORIZONTAL ) { progress = ( int ) ( ( float ) ( progressBar.getWidth () - shadeWidth * 4 ) * ( ( float ) ( progressBar.getValue () - progressBar.getMinimum () ) / ( float ) ( progressBar.getMaximum () - progressBar.getMinimum () ) ) ); } else { progress = ( int ) ( ( float ) ( progressBar.getHeight () - shadeWidth * 4 ) * ( ( float ) ( progressBar.getValue () - progressBar.getMinimum () ) / ( float ) ( progressBar.getMaximum () - progressBar.getMinimum () ) ) ); } } return progress; } private GeneralPath getIndeterminateProgressShape ( final JComponent c ) { // Small inner // GeneralPath gp = new GeneralPath ( GeneralPath.WIND_EVEN_ODD ); // gp.moveTo ( shadeWidth * 2 - indeterminateStep * 2, c.getHeight () - shadeWidth*2 - 1 ); // gp.lineTo ( shadeWidth * 2 - indeterminateStep, shadeWidth*2 ); // gp.lineTo ( shadeWidth * 2, shadeWidth*2 ); // gp.lineTo ( shadeWidth * 2 - indeterminateStep, c.getHeight () - shadeWidth*2 - 1 ); // gp.closePath (); // return gp; // Large inner // GeneralPath gp = new GeneralPath ( GeneralPath.WIND_EVEN_ODD ); // gp.moveTo ( shadeWidth * 2 - indeterminateStep * 2, c.getHeight () - shadeWidth * 2 ); // gp.lineTo ( shadeWidth * 2 - indeterminateStep, shadeWidth * 2 - 1 ); // gp.lineTo ( shadeWidth * 2, shadeWidth * 2 - 1 ); // gp.lineTo ( shadeWidth * 2 - indeterminateStep, c.getHeight () - shadeWidth * 2 ); // gp.closePath (); // return gp; // Outer final GeneralPath gp = new GeneralPath ( GeneralPath.WIND_EVEN_ODD ); gp.moveTo ( shadeWidth * 2 - indeterminateStep * 2, c.getHeight () - shadeWidth - 1 ); gp.lineTo ( shadeWidth * 2 - indeterminateStep, shadeWidth ); gp.lineTo ( shadeWidth * 2, shadeWidth ); gp.lineTo ( shadeWidth * 2 - indeterminateStep, c.getHeight () - shadeWidth - 1 ); gp.closePath (); return gp; } }