package org.roussev.hiena.gui;
/*
* Copyright 2009 Hiena Mp3 Player http://code.google.com/p/hiena-mp3-player/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Enumeration;
import java.util.Vector;
import java.awt.MediaTracker;
import java.awt.Image;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.AlphaComposite;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.awt.event.FocusListener;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.net.URL;
//--
public final class XTransitionButton extends javax.swing.JPanel implements FocusListener, MouseListener, TransitionListener, KeyListener {
private static final int UP = 0;
private static final int DOWN = 1;
int position = UP;
private boolean focusable = true;
boolean releasable = true;
private boolean _enabled = true;
boolean toggle;
int toggleActions = 0;
private boolean firstInit = true;
boolean mouseOver;
boolean pressed;
boolean enableFireActionPerformed = true;
// Event Source Management
private final Vector actionListeners;
final String label;
//--
private Image bg;
private Image btn;
//--
private int width;
private int height;
private ImageData iData;
private ImagePressData iDataPress;
final TransitionThread animator;
final TransitionThread animatorPress;
//--------------------------------------
private XTransitionButton(String label) {
//
setDoubleBuffered(true);
this.label = label;
// Initialize Event Source Management
actionListeners = new Vector();
// Initialize Mouse Input Management
this.addMouseListener(this);
// Initialize Focus Management
this.addFocusListener(this);
// Initialize Keyboard Input Management
this.addKeyListener(this);
animator = new TransitionThread(this);
animatorPress = new TransitionThread(this);
}
//-----------------------------------------------
public XTransitionButton(String label, String[] url) {
this(label);
if(url.length < 4) {
throw new ArrayIndexOutOfBoundsException(
"\n ------------------------------" +
"\n -- Error loading images. " +
"\n -- 4 images are needed for XTransitionButton." +
"\n -- Usage:" +
"\n -- \t String[] url = {" +
"\n -- \t\t \"/img.gif\"" +
"\n -- \t\t \"/img_OVER.gif\"" +
"\n -- \t\t \"/img_PRESSED.gif\"" +
"\n -- \t\t \"/img_BACKGROUND.gif\"" +
"\n -- \t }" +
"\n ------------------------------"
);
}
setImages(url[0], url[1], url[2], url[3]);
}
//-----------------------------------------------
public XTransitionButton(String label, URL[] url) {
this(label);
if(url.length < 4) {
throw new ArrayIndexOutOfBoundsException(
"\n ------------------------------" +
"\n -- Error loading images. " +
"\n -- 4 images are needed for XTransitionButton." +
"\n -- Usage:" +
"\n -- \t URL[] url = {" +
"\n -- \t\t url_img" +
"\n -- \t\t url_img_OVER" +
"\n -- \t\t url_img_PRESSED" +
"\n -- \t\t url_img_BACKGROUND" +
"\n -- \t }" +
"\n ------------------------------"
);
}
setImages(url[0], url[1], url[2], url[3]);
}
//-----------------------------------------------
private final void setImages(URL url, URL url_over, URL url_down, URL url_bg) {
//--- url = "resources/name.gif" ---
//final URLClassLoader urlLoader = (URLClassLoader)getClass().getClassLoader();
//final Image img = toolkit.createImage(urlLoader.findResource(url));
final MediaTracker md = new MediaTracker(this);
final Toolkit toolkit = getToolkit();
btn = toolkit.createImage( url);
final Image btn_over = toolkit.createImage( url_over );
final Image btn_down = toolkit.createImage( url_down );
bg = toolkit.createImage( url_bg );
md.addImage(btn, 0);
md.addImage(btn_over, 1);
md.addImage(btn_down, 2);
md.addImage(bg, 3);
try {
md.waitForAll();
if (md.isErrorAny()) { System.out.println("Error loading image "); }
} catch (Exception ex) { ex.printStackTrace(); }
width = btn.getWidth(this);
height = btn.getHeight(this);
setSize( getPreferredSize());
iData = new ImageData( btn_over);
iDataPress = new ImagePressData( btn_down);
}
//-----------------------------------------------
private final void setImages(String url, String url_over, String url_down, String url_bg) {
setImages(
getClass().getResource(url),
getClass().getResource(url_over),
getClass().getResource(url_down),
getClass().getResource(url_bg)
);
}
//--------------------------------------
public final void addActionListener(ActionListener li) {
actionListeners.addElement(li);
}
//--------------------------------------
public final void removeActionListener(ActionListener li) {
actionListeners.removeElement(li);
}
//--------------------------------------
protected final void fireActionPerformed(ActionEvent evt) {
final Enumeration e = actionListeners.elements();
while ( e.hasMoreElements() ) {
final ActionListener li = (ActionListener)e.nextElement();
li.actionPerformed(evt);
}
}
//-----------------------------------------------
public final Dimension getMinimumSize(){
return getPreferredSize();
}
public final Dimension getMaximumSize(){
return getPreferredSize();
}
public final Dimension getPreferredSize(){
return new Dimension(btn.getWidth(this), btn.getHeight(this));
}
//--------------------------------------
public final boolean isFocusable() {
return focusable;
}
public final void setFocusable(boolean focusable) {
this.focusable = focusable;
super.setFocusable(focusable);
}
//-----------------------------------------------------------
public final Graphics2D createGraphics2D(/*int width, int height,*/ Graphics g) {
Graphics2D g2 = (Graphics2D) g;
//g2.setBackground(getBackground());
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
//g2.clearRect(0, 0, width, height);
return g2;
}
//-----------------------------------------------------------
private final void drawAlpha(ImageData id, Graphics2D g2) {
final AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, id.alpha);
g2.setComposite(ac);
//g2.setPaint( id.paint);
//g2.translate( id.x, id.y);
g2.drawImage( id.image, 0, 0, this);
//g2.translate( -id.x, -id.y);
}
//-----------------------------------------------------------
private final void drawAlphaPress(ImagePressData id, Graphics2D g2) {
final AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, id.alpha);
g2.setComposite(ac);
//g2.setPaint( id.paint);
//g2.translate( id.x, id.y);
g2.drawImage( id.image, 0, 0, this);
//g2.translate( -id.x, -id.y);
}
//-----------------------------------------------------------
public final void paint(Graphics g) {
//final Dimension d = getSize();
if (firstInit) {
repaint();
firstInit = false;
}
if ( !animatorPress.isInterrupted()) {
iDataPress.step();
}
else if ( !animator.isInterrupted()) {
iData.step();
}
final Graphics2D g2 = createGraphics2D(/*d.width, d.height,*/ g);
g2.drawImage( bg, 0, 0, this);
g2.drawImage( btn, 0, 0, this);
drawAlpha(iData, g2);
drawAlphaPress(iDataPress, g2);
g2.dispose();
}
//--------------------------------------
public final void set_Enabled(boolean _enabled) {
this._enabled = _enabled;
}
public final boolean is_Enabled() {
return _enabled;
}
public final void setReleasable(boolean x) {
this.releasable = x;
if(!releasable) {
setToggle(true);
}
}
public final void setToggle(boolean x) {
this.toggle = x;
}
public final void setPressed(boolean boo) {
if(!boo) {
if( toggle && pressed) {
animatorPress.start();
animator.start();
}
}
else {
if( !pressed) {
pressAlphaDirection = ON;
position = UP;
pressed = true;
enableFireActionPerformed = false;
animatorPress.start();
}
}
}
//-----------------------------------------------------------
public final void mouseClicked(java.awt.event.MouseEvent e) {
}
public final void mouseEntered(java.awt.event.MouseEvent e) {
mouseOver = true;
if(!pressed) {
animator.start();
}
}
public final void mouseExited(java.awt.event.MouseEvent e) {
mouseOver = false;
if(!pressed) {
animator.start();
}
}
//---
public final void mousePressed(java.awt.event.MouseEvent e) {
requestFocus();
if(_enabled) {
if(releasable) {
pressAlphaDirection = ON;
position = UP;
pressed = true;
enableFireActionPerformed = true;
animatorPress.start();
}
else if(position == UP ) {
pressed = true;
enableFireActionPerformed = true;
animatorPress.start();
}
}
}
public final void mouseReleased(java.awt.event.MouseEvent e) {
}
//--------------------------------------
public void focusGained(java.awt.event.FocusEvent focusEvent) {
mouseEntered(null);
}
public void focusLost(java.awt.event.FocusEvent focusEvent) {
mouseExited(null);
}
//--------------------------------------
public void keyPressed(java.awt.event.KeyEvent ev) {
if (ev.getKeyCode() == KeyEvent.VK_SPACE || ev.getKeyCode() == KeyEvent.VK_ENTER ) {
mousePressed(null);
}
}
public void keyReleased(java.awt.event.KeyEvent ev) {
}
public void keyTyped(java.awt.event.KeyEvent keyEvent) {
}
//--------------------------------------
//==================================================================
int pressAlphaDirection = ON;
private static final int ON = 0;
private static final int OFF = 1;
private final class ImagePressData {
private static final double STEP_DOWN = 0.15;
private static final double STEP_UP = 0.1;
private static final float ALPHA_MIN = 0.0f;
private static final float ALPHA_MAX = 1.0f;
final Image image;
float alpha = ALPHA_MIN;
//---------------------------------
public ImagePressData(Image image) {
this.image = image;
}
//---------------------------------
public final void reset() {
alpha = ALPHA_MIN;
pressAlphaDirection = ON;
}
//---------------------------------
public final void step() {
//----------- in -- [0.0 -> 1.0]
if (pressAlphaDirection == ON) {
if ((alpha += STEP_DOWN) >= ALPHA_MAX ) {
pressAlphaDirection = OFF;
alpha = ALPHA_MAX;
}
if(alpha == ALPHA_MAX && pressed) {
if(!releasable) {
animatorPress.stop();
position = DOWN;
} else if(toggle) {
if( toggleActions%2==0 ) {
animatorPress.stop();
position = DOWN;
}
else {
setPressed(false);
}
toggleActions++;
}
if(enableFireActionPerformed) {
fireActionPerformed( new ActionEvent(this, ActionEvent.ACTION_PERFORMED, label) );
}
} else {
animatorPress.start();
}
if(!pressed) {
pressAlphaDirection = OFF;
pressed = false;
}
}
//----------- out -- [1.0 -> 0.0]
else if (pressAlphaDirection == OFF) {
if ((alpha -= STEP_UP) <= ALPHA_MIN) {
pressAlphaDirection = ON;
alpha = ALPHA_MIN;
}
if(alpha == ALPHA_MIN && !pressed) {
animatorPress.stop();
position = UP;
} else {
animatorPress.start();
}
if(pressed) {
pressAlphaDirection = ON;
pressed = false;
}
}
} //-- end of step
}//----- end of ImagePressData
//==================================================================
private final class ImageData {
private static final double STEP = 0.1;
private static final float ALPHA_MIN = 0.0f;
private static final float ALPHA_MAX = 1.0f;
final Image image;
float alpha = ALPHA_MIN;
private int alphaDirection = ON;
//---------------------------------
public ImageData(Image image) {
this.image = image;
}
//---------------------------------
public final void reset() {
alpha = ALPHA_MIN;
alphaDirection = ON;
}
//---------------------------------
public final void step() {
//----------- in -- [0.0 -> 1.0]
if (alphaDirection == ON) {
if ((alpha += STEP) >= ALPHA_MAX ) {
alphaDirection = OFF;
alpha = ALPHA_MAX;
}
if(alpha == ALPHA_MAX && mouseOver) {
animator.stop();
} else {
animator.start();
}
if(!mouseOver) {
alphaDirection = OFF;
}
}
//----------- out -- [1.0 -> 0.0]
else if (alphaDirection == OFF) {
if ((alpha -= STEP) <= ALPHA_MIN) {
alphaDirection = ON;
alpha = ALPHA_MIN;
}
if(alpha == ALPHA_MIN && !mouseOver) {
animator.stop();
} else {
animator.start();
}
if(mouseOver) {
alphaDirection = ON;
}
}
} //-- end of step
}//----- end of ImageData
//---------------------------------------------------------
}