com.alee.extended.image.WebImageGallery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weblaf-ui Show documentation
Show all versions of weblaf-ui Show documentation
WebLaf is a Java Swing Look and Feel and extended components library for cross-platform applications
/*
* 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.extended.image;
import com.alee.global.StyleConstants;
import com.alee.managers.style.StyleId;
import com.alee.laf.scroll.WebScrollPane;
import com.alee.managers.hotkey.Hotkey;
import com.alee.utils.GraphicsUtils;
import com.alee.utils.ImageUtils;
import com.alee.utils.LafUtils;
import com.alee.utils.SwingUtils;
import com.alee.utils.swing.WebTimer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
/**
* @author Mikle Garin
*/
public class WebImageGallery extends JComponent
{
private final int spacing = 20;
private int imageLength = 200;
private final int borderWidth = 3;
private final float fadeHeight = 0.7f;
private final int opacity = 125;
private final Color light = new Color ( 128, 128, 128 );
private final Color selectedLight = new Color ( 255, 255, 255 );
private final Color transparent = new Color ( 128, 128, 128, 0 );
private final Color selectedTransparent = new Color ( 255, 255, 255, 0 );
private int maxWidth = 0;
private int maxHeight = 0;
private final List images = new ArrayList ();
private final List reflections = new ArrayList ();
private final List descriptions = new ArrayList ();
// private List sizes = new ArrayList ( );
private int preferredColumnCount = 4;
private boolean scrollOnSelection = true;
private int selectedIndex = -1;
private int oldSelectedIndex = -1;
private float progress = 0f;
private WebTimer reflectionMover = null;
private WebScrollPane view;
public WebImageGallery ()
{
super ();
SwingUtils.setOrientation ( this );
setFocusable ( true );
setFont ( new JLabel ().getFont ().deriveFont ( Font.BOLD ) );
final MouseAdapter mouseAdapter = new MouseAdapter ()
{
@Override
public void mousePressed ( final MouseEvent e )
{
if ( SwingUtilities.isLeftMouseButton ( e ) )
{
WebImageGallery.this.requestFocusInWindow ();
for ( int i = 0; i < images.size (); i++ )
{
if ( getImageRect ( i ).contains ( e.getPoint () ) )
{
setSelectedIndex ( i );
break;
}
}
}
}
@Override
public void mouseWheelMoved ( final MouseWheelEvent e )
{
final int index = getSelectedIndex ();
final int maxIndex = images.size () - 1;
final int wheelRotation = e.getWheelRotation ();
int newIndex;
if ( wheelRotation > 0 )
{
newIndex = index + wheelRotation;
while ( newIndex > maxIndex )
{
newIndex -= images.size ();
}
}
else
{
newIndex = index + wheelRotation;
while ( newIndex < 0 )
{
newIndex += images.size ();
}
}
setSelectedIndex ( newIndex );
}
};
addMouseListener ( mouseAdapter );
addMouseWheelListener ( mouseAdapter );
addKeyListener ( new KeyAdapter ()
{
@Override
public void keyPressed ( final KeyEvent e )
{
if ( images.size () > 0 )
{
final int si = getSelectedIndex ();
if ( Hotkey.LEFT.isTriggered ( e ) )
{
setSelectedIndex ( si == -1 || si == 0 ? images.size () - 1 : si - 1 );
}
else if ( Hotkey.RIGHT.isTriggered ( e ) )
{
setSelectedIndex ( si == -1 || si == images.size () - 1 ? 0 : si + 1 );
}
else if ( Hotkey.HOME.isTriggered ( e ) )
{
setSelectedIndex ( 0 );
}
else if ( Hotkey.END.isTriggered ( e ) )
{
setSelectedIndex ( images.size () - 1 );
}
}
}
} );
}
public List getImages ()
{
return images;
}
public int getPreferredColumnCount ()
{
return preferredColumnCount;
}
public void setPreferredColumnCount ( final int preferredColumnCount )
{
this.preferredColumnCount = preferredColumnCount;
}
public WebScrollPane getView ()
{
return getView ( null );
}
public WebScrollPane getView ( final StyleId scrollStyleId )
{
if ( view == null )
{
view = new WebScrollPane ( scrollStyleId, WebImageGallery.this )
{
@Override
public Dimension getPreferredSize ()
{
final int columns = Math.min ( images.size (), preferredColumnCount );
final JScrollBar hsb = getHorizontalScrollBar ();
final int sbh = hsb != null && hsb.isShowing () ? hsb.getPreferredSize ().height : 0;
return new Dimension ( spacing * ( columns + 1 ) + columns * maxWidth,
WebImageGallery.this.getPreferredSize ().height + sbh );
}
};
view.setHorizontalScrollBarPolicy ( WebScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
view.setVerticalScrollBarPolicy ( WebScrollPane.VERTICAL_SCROLLBAR_NEVER );
final InputMap im = view.getInputMap ( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
im.put ( KeyStroke.getKeyStroke ( "UP" ), "none" );
im.put ( KeyStroke.getKeyStroke ( "DOWN" ), "none" );
im.put ( KeyStroke.getKeyStroke ( "LEFT" ), "none" );
im.put ( KeyStroke.getKeyStroke ( "RIGHT" ), "none" );
}
return view;
}
public int getImageLength ()
{
return imageLength;
}
public void setImageLength ( final int imageLength )
{
this.imageLength = imageLength;
}
public boolean isScrollOnSelection ()
{
return scrollOnSelection;
}
public void setScrollOnSelection ( final boolean scrollOnSelection )
{
this.scrollOnSelection = scrollOnSelection;
}
public int getSelectedIndex ()
{
return selectedIndex;
}
public void setSelectedIndex ( final int selectedIndex )
{
if ( this.selectedIndex == selectedIndex )
{
return;
}
this.oldSelectedIndex = this.selectedIndex;
this.selectedIndex = selectedIndex;
repaint ();
if ( scrollOnSelection )
{
final Rectangle rect = getImageRect ( selectedIndex );
SwingUtils.scrollSmoothly ( getView (), rect.x + rect.width / 2 - WebImageGallery.this.getVisibleRect ().width / 2, rect.y );
}
moveReflection ();
}
private void moveReflection ()
{
if ( reflectionMover != null && reflectionMover.isRunning () )
{
reflectionMover.stop ();
}
progress = 0f;
reflectionMover = new WebTimer ( "WebImageGallery.reflectionMoveTimer", StyleConstants.fps48, new ActionListener ()
{
@Override
public void actionPerformed ( final ActionEvent e )
{
if ( progress < 1f )
{
progress += 0.08f;
progress = Math.min ( progress, 1f );
WebImageGallery.this.repaint ();
}
else
{
reflectionMover.stop ();
}
}
} );
reflectionMover.start ();
}
public Rectangle getImageRect ( final int index )
{
final int iconWidth = images.get ( index ).getIconWidth ();
final int iconHeight = images.get ( index ).getIconHeight ();
final Dimension ps = getPreferredSize ();
final int x = ( getWidth () > ps.width ? ( getWidth () - ps.width ) / 2 : 0 ) + spacing +
( maxWidth + spacing ) * index + maxWidth / 2;
final int y = getHeight () / 2 - spacing / 2 - iconHeight / 2;
return new Rectangle ( x - iconWidth / 2, y - iconHeight / 2, iconWidth, iconHeight );
}
public void addImage ( final ImageIcon image )
{
addImage ( 0, image );
}
public void addImage ( final int index, final ImageIcon image )
{
try
{
final ImageIcon previewIcon = ImageUtils.createPreviewIcon ( image, imageLength );
final int rWidth = previewIcon.getIconWidth ();
final int rHeight = previewIcon.getIconHeight ();
final BufferedImage reflection = ImageUtils.createCompatibleImage ( rWidth, rHeight, Transparency.TRANSLUCENT );
final Graphics2D g2d = reflection.createGraphics ();
GraphicsUtils.setupAntialias ( g2d );
g2d.drawImage ( previewIcon.getImage (), 0, 0, null );
g2d.setComposite ( AlphaComposite.getInstance ( AlphaComposite.DST_IN ) );
g2d.setPaint ( new GradientPaint ( 0, rHeight * ( 1f - fadeHeight ), new Color ( 0, 0, 0, 0 ), 0, rHeight,
new Color ( 0, 0, 0, opacity ) ) );
g2d.fillRect ( 0, 0, rWidth, rHeight );
g2d.dispose ();
images.add ( index, previewIcon );
descriptions.add ( index, image.getIconWidth () + " x " + image.getIconHeight () + " px" );
reflections.add ( index, reflection );
}
catch ( final Throwable e )
{
// todo Handle out of memory
}
recalculateMaxSizes ();
updateContainer ();
}
public void removeImage ( final ImageIcon image )
{
if ( images.contains ( image ) )
{
removeImage ( images.indexOf ( image ) );
}
}
public void removeImage ( final int index )
{
if ( index >= 0 && index < images.size () )
{
final boolean wasSelected = getSelectedIndex () == index;
images.remove ( index );
descriptions.remove ( index );
reflections.remove ( index ).flush ();
recalculateMaxSizes ();
updateContainer ();
if ( wasSelected && images.size () > 0 )
{
setSelectedIndex ( index < images.size () ? index : index - 1 );
}
}
}
private void updateContainer ()
{
if ( getParent () instanceof JComponent )
{
( ( JComponent ) getParent () ).revalidate ();
}
repaint ();
}
private void recalculateMaxSizes ()
{
for ( final ImageIcon icon : images )
{
maxWidth = Math.max ( maxWidth, icon.getIconWidth () );
maxHeight = Math.max ( maxHeight, icon.getIconHeight () );
}
}
@Override
protected void paintComponent ( final Graphics g )
{
super.paintComponent ( g );
final int height = getHeight ();
final int width = getWidth ();
final Graphics2D g2d = ( Graphics2D ) g;
final Object aa = GraphicsUtils.setupAntialias ( g2d );
g2d.setPaint ( new GradientPaint ( 0, 0, Color.black, 0, height, Color.darkGray ) );
g2d.fillRect ( 0, 0, width, height );
final Rectangle vr = getVisibleRect ();
final Dimension ps = getPreferredSize ();
final Composite oldComposite = g2d.getComposite ();
for ( int i = 0; i < images.size (); i++ )
{
if ( !getImageRect ( i ).intersects ( vr ) )
{
continue;
}
final ImageIcon icon = images.get ( i );
final BufferedImage bi = ImageUtils.getBufferedImage ( icon );
final int imageWidth = icon.getIconWidth ();
final int imageHeight = icon.getIconHeight ();
final int x = ( getWidth () > ps.width ? ( getWidth () - ps.width ) / 2 : 0 ) + spacing +
( maxWidth + spacing ) * i + maxWidth / 2;
final int y = height / 2 - spacing / 2 - imageHeight / 2;
final int y2 = height / 2 + spacing / 2 + imageHeight / 2;
// Initial image
final float add = selectedIndex == i ? progress * 0.4f : ( oldSelectedIndex == i ? 0.4f - progress * 0.4f : 0 );
g2d.setComposite ( AlphaComposite.getInstance ( AlphaComposite.SRC_OVER, 0.6f + add ) );
g2d.drawImage ( bi, x - imageWidth / 2, y - imageHeight / 2, null );
g2d.setPaint ( selectedIndex == i ? Color.WHITE : Color.GRAY );
Area gp = new Area ( new RoundRectangle2D.Double ( x - imageWidth / 2 - borderWidth, y - imageHeight / 2 - borderWidth,
imageWidth + borderWidth * 2, imageHeight + borderWidth * 2, borderWidth * 2, borderWidth * 2 ) );
gp.subtract ( new Area ( new Rectangle ( x - imageWidth / 2, y - imageHeight / 2, imageWidth, imageHeight ) ) );
g2d.fill ( gp );
g2d.setComposite ( oldComposite );
// Info text
if ( selectedIndex == i || oldSelectedIndex == i )
{
final float opacity = selectedIndex == i ? progress : 1f - progress;
g2d.setComposite ( AlphaComposite.getInstance ( AlphaComposite.SRC_OVER, opacity ) );
g2d.setPaint ( Color.WHITE );
final String infoText = descriptions.get ( i );
final Point ts = LafUtils.getTextCenterShift ( g2d.getFontMetrics (), infoText );
g2d.drawString ( infoText, x + ts.x, getHeight () / 2 + spacing / 2 + ts.y );
g2d.setComposite ( oldComposite );
}
// Reflection
final int rWidth = imageWidth + borderWidth * 2;
final int rHeight = imageHeight + borderWidth * 2;
final int addition = selectedIndex == i ? Math.round ( progress * spacing ) :
( oldSelectedIndex == i ? spacing - Math.round ( progress * spacing ) : 0 );
if ( reflections.get ( i ) != null )
{
g2d.drawImage ( reflections.get ( i ), x - imageWidth / 2, y2 + imageHeight / 2 + addition, imageWidth, -imageHeight,
null );
}
gp = new Area ( new RoundRectangle2D.Double ( x - rWidth / 2, y2 - rHeight / 2 + addition, rWidth, rHeight, borderWidth * 2,
borderWidth * 2 ) );
gp.subtract ( new Area (
new Rectangle ( x - rWidth / 2 + borderWidth, y2 - rHeight / 2 + addition + borderWidth, rWidth - borderWidth * 2,
rHeight - borderWidth * 2 ) ) );
g2d.setPaint ( new GradientPaint ( 0, y2 - imageHeight / 2 + addition, selectedIndex == i ? selectedLight : light, 0,
y2 - imageHeight / 2 + addition + imageHeight * fadeHeight, selectedIndex == i ? selectedTransparent : transparent ) );
g2d.fill ( gp );
}
GraphicsUtils.restoreAntialias ( g2d, aa );
}
@Override
public Dimension getPreferredSize ()
{
return new Dimension ( spacing * ( images.size () + 1 ) + maxWidth * images.size (), spacing * 3 + maxHeight * 2 );
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy