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.awt.Graphics; import java.awt.Color; import java.awt.Image; import java.awt.Dimension; import java.awt.MediaTracker; import java.awt.Toolkit; import java.awt.Rectangle; import java.util.Vector; import java.util.Enumeration; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.net.URL; /** * <pre> * <b>AtaProgressSlider</b> is a custom progress Slider. Features: * - showing the current progress * - slider available with mouse, key and focus support. * </pre> * * @author * */ public final class XProgressSlider extends java.awt.Panel { private Color progressColor = new Color(0xAEAEFF); private boolean showProgress = true; private Rectangle progressRectangle = new Rectangle(0, 2); private int progressWidth = getMinProgressWidth() ; private int DOT_WIDTH ; private int DOT_HEIGHT ; private int CANVAS_WIDTH ; private int CANVAS_HEIGHT ; private int eX, eY; private int eXprevios; private int dotX = getMinDotX(), dotY = progressRectangle.y; private boolean mouseEnter = false; private boolean mouseUp = true; private boolean keyPressed = false; private boolean draggable = false; private boolean hasListeners = true; private boolean focusable = true; //---------- // Event Source Management private final Vector actionListeners; private String label; //----------- private Image imgOff; private Image dot; private Image dot_; private Image bgSlider; private Graphics gOff; //------------------------------------------------------- public XProgressSlider(String label, String[] url, boolean hasListeners) { this.hasListeners = hasListeners; this.label = label; if(hasListeners) initListeners(); // Initialize Event Source Management actionListeners = new Vector(); if(url.length < 3) { throw new ArrayIndexOutOfBoundsException( "\n ------------------------------" + "\n -- Error loading images. " + "\n -- 3 images are needed for XProgressSlider." + "\n -- Usage:" + "\n -- \t String[] url = {" + "\n -- \t\t \"/img_arrow.gif\"" + "\n -- \t\t \"/img_arrow_OVER.gif\"" + "\n -- \t\t \"/img_slider_BACKGROUND.gif\"" + "\n -- \t }" + "\n ------------------------------" ); } setImages( url[0], url[1], url[2]); setSliderPercent(0); } //------------------------------------------------------- public XProgressSlider(String label, String[] url, boolean hasListeners, Rectangle progressRectangle) { this( label, url, hasListeners); this.progressRectangle = progressRectangle; final double medium = progressRectangle.y + (double)progressRectangle.height/2.0; dotY = (int)(medium - (double)DOT_HEIGHT/2.0); dotX = getMinDotX(); } //------------------------------------------------------- public XProgressSlider(String label, URL[] url, boolean hasListeners) { this.hasListeners = hasListeners; this.label = label; if(hasListeners) initListeners(); // Initialize Event Source Management actionListeners = new Vector(); if(url.length < 3) { throw new ArrayIndexOutOfBoundsException( "\n ------------------------------" + "\n -- Error loading images. " + "\n -- 3 images are needed for XProgressSlider." + "\n -- Usage:" + "\n -- \t URL[] url = {" + "\n -- \t\t url_img_arrow" + "\n -- \t\t url_img_arrow_OVER" + "\n -- \t\t url_img_slider_BACKGROUND" + "\n -- \t }" + "\n ------------------------------" ); } setImages( url[0], url[1], url[2]); setSliderPercent(0); } //------------------------------------------------------- public XProgressSlider(String label, URL[] url, boolean hasListeners, Rectangle progressRectangle) { this( label, url, hasListeners); this.progressRectangle = progressRectangle; final double medium = progressRectangle.y + (double)progressRectangle.height/2.0; dotY = (int)(medium - (double)DOT_HEIGHT/2.0); dotX = getMinDotX(); } //----------------------------------------------- private final void setImages(URL urlDot, URL urlDot_, URL urlBg) { final MediaTracker md = new MediaTracker(this); final Toolkit toolkit = getToolkit(); dot = toolkit.createImage( urlDot ); dot_ = toolkit.createImage( urlDot_ ); bgSlider = toolkit.createImage( urlBg ); md.addImage(dot, 0); md.addImage(dot_, 1); md.addImage(bgSlider, 2); try { md.waitForAll(); if (md.isErrorAny()) { System.out.println("Error loading image "); } } catch (Exception ex) { ex.printStackTrace(); } CANVAS_WIDTH = bgSlider.getWidth(this); CANVAS_HEIGHT = bgSlider.getHeight(this); DOT_WIDTH = dot.getWidth(this); DOT_HEIGHT = dot.getHeight(this); setSize( getPreferredSize()); } //----------------------------------------------- private final void setImages(String urlDot, String urlDot_, String urlBg) { setImages( getClass().getResource(urlDot), getClass().getResource(urlDot_), getClass().getResource(urlBg) ); } //------------------------------------------------------- private final void initListeners() { this.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { doMouseEntered(); } public void mouseExited(java.awt.event.MouseEvent evt) { doMouseExited(); } public void mousePressed(java.awt.event.MouseEvent evt) { doMousePressed(evt); } public void mouseReleased(java.awt.event.MouseEvent evt) { doMouseReleased(); } }); this.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseMoved(java.awt.event.MouseEvent evt) { doMouseMoved(evt); } public void mouseDragged(java.awt.event.MouseEvent evt) { doMouseDragged(evt); } }); this.addFocusListener( new java.awt.event.FocusAdapter(){ public void focusGained(java.awt.event.FocusEvent evt) { doFocusGained(); } public void focusLost(java.awt.event.FocusEvent evt) { doFocusLost(); } }); this.addKeyListener( new java.awt.event.KeyAdapter(){ public void keyPressed(java.awt.event.KeyEvent evt) { doKeyPressed(evt); } public void keyReleased(java.awt.event.KeyEvent evt) { doKeyReleased(); } }); } //------------------------------------------------------- public final void updateSlider(){ if(mouseEnter){ update( getGraphics() ); } } //------------------------------------------------------- public final void update(Graphics g) { gOff = null; imgOff = null; // create the offscreen buffer and associated Graphics imgOff = createImage( this.CANVAS_WIDTH, this.CANVAS_HEIGHT ); gOff = imgOff.getGraphics(); // clear the exposed area gOff.setColor(getBackground()); gOff.fillRect(0,0, this.CANVAS_WIDTH, this.CANVAS_HEIGHT); gOff.setColor(getForeground()); // do normal redraw paint(gOff); // transfer offscreen to window g.drawImage(imgOff, 0, 0, this); imgOff.flush(); } //------------------------------------------------------- public final void paint(Graphics g){ g.drawImage( bgSlider, 0, 0, this); drawProgress(g); drawDot(g); // Focus Management /*if (hasFocus && focusable) { g.setColor(FOCUS_COLOR); g.drawRect( 0, 0, CANVAS_WIDTH - 1, CANVAS_HEIGHT - 1 ); }*/ g.dispose(); } //------------------------------------------------------- private final void drawProgress(Graphics g ){ if(showProgress){ g.setColor( progressColor ); g.fillRect( progressRectangle.x, progressRectangle.y, progressWidth, progressRectangle.height ); } } //------------------------------------------------------- private final void drawDot(Graphics g ){ if( insideDot(eX,eY) || draggable ) g.drawImage( dot_, dotX, dotY, this); else g.drawImage( dot, dotX, dotY, this); if(!mouseEnter) g.drawImage( dot, dotX, dotY, this); if(keyPressed) g.drawImage( dot_, dotX, dotY, this); } //------------------------------------------------------- public final int getPercent(){ int dotCenter = dotX + (int)Math.round(DOT_WIDTH / 2); int sliderSize = CANVAS_WIDTH - 2*progressRectangle.x; int x = (int)Math.round( (dotCenter*100) / sliderSize ); x = ( dotX <= progressRectangle.x)? 0 : x; x = ( dotX >= CANVAS_WIDTH - DOT_WIDTH - progressRectangle.x)? 100 : x; return x; } //------------------------------------------------------- private final int getMinDotX(){ return (progressRectangle.x - DOT_WIDTH/2); } private final int getMaxDotX(){ return (CANVAS_WIDTH - getMinDotX() - DOT_WIDTH); } //------------------------------------------------------- private final int getMinProgressWidth(){ return (progressRectangle.x); } private final int getMaxProgressWidth(){ return (CANVAS_WIDTH - 2*progressRectangle.x); } //------------------------------------------------------- public final void setSliderPercent(int percent){ dotX = getMinDotX() + (percent*(CANVAS_WIDTH - 2*progressRectangle.x))/100 ; //if( dotX > getMaxDotX()) dotX = getMaxDotX(); //else if( dotX < getMinDotX()) dotX = getMinDotX(); repaint(); } //------------------------------------------------------- public final void setProgressPercent(int percent){// progressWidth = (percent*(CANVAS_WIDTH - 2*progressRectangle.x ))/100; if( progressWidth > getMaxProgressWidth()) progressWidth = getMaxProgressWidth(); repaint(); } //------------------------------------------------------- public final void setProgressColor(Color c) { this.progressColor = c; } //------------------------------------------------------- // Set the progress line to be visible public final void setShowProgress( boolean showProgress) { this.showProgress = showProgress; } //------------------------------------------------------- final void doKeyPressed(java.awt.event.KeyEvent evt) { keyPressed = true; // Key Model Management if (evt.getKeyCode() == KeyEvent.VK_RIGHT || evt.getKeyCode() == KeyEvent.VK_UP ) { fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, label)); if( dotX < CANVAS_WIDTH - DOT_WIDTH - progressRectangle.x ){ eX ++; dotX ++; repaint(); } } else if (evt.getKeyCode() == KeyEvent.VK_LEFT || evt.getKeyCode() == KeyEvent.VK_DOWN ) { fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, label)); if( dotX > progressRectangle.x ){ eX --; dotX --; repaint(); } } } //----------------------------------- final void doKeyReleased() { keyPressed = false; repaint(); } //------------------------------------------------------- final void doFocusGained() { keyPressed = true; repaint(); } //----------------------------------- final void doFocusLost() { keyPressed = false; repaint(); } //------------------------------------------------------- final void doMouseEntered() { mouseEnter = true; } //----------------------------------- final void doMouseExited() { mouseEnter = false; keyPressed = false; repaint(); } //----------------------------------- final void doMouseReleased() { mouseUp = true; setDraggable( eX, eY ); } //----------------------------------- final void doMousePressed(java.awt.event.MouseEvent evt) { mouseUp = false; eX = evt.getX(); eY = evt.getY(); setDraggable( eX, eY ); if( insideDraggCanvas(eX) ){ dotX = eX - (int)Math.round(DOT_WIDTH/2); //===if( dotX > CANVAS_WIDTH - DOT_WIDTH - progressRectangle.x) //=== dotX = CANVAS_WIDTH - DOT_WIDTH - progressRectangle.x; fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, label)); repaint(); } } //----------------------------------- final void doMouseMoved(java.awt.event.MouseEvent evt) { eX = evt.getX() ; eY = evt.getY() ; eXprevios = eX; setDraggable( eX, eY ); repaint(); } //----------------------------------- final void doMouseDragged(java.awt.event.MouseEvent evt) { eX = evt.getX(); eY = evt.getY(); int currentDotX = dotX + eX-eXprevios ; if( currentDotX >= getMinDotX() && currentDotX <= getMaxDotX() ) { dotX += eX-eXprevios ; } //else if ( currentDotX < progressRectangle.x ) { // //===dotX = progressRectangle.x; //} //else { // //===dotX = CANVAS_WIDTH - DOT_WIDTH - progressRectangle.x; //} eXprevios = eX; fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, label)); repaint(); } //------------------------------------------------------- private final void setDraggable(int x, int y){ if( insideDot( x, y) && mouseEnter ){ draggable = true; } else { draggable = false; } } //------------------------------------------------------- private final boolean insideDot(int x, int y){ return ( x >= dotX && x <= (dotX + DOT_WIDTH) && y > dotY && y <= (dotY + DOT_HEIGHT) ); } //------------------------------------------------------- private final boolean insideDraggCanvas(int x){ return ( x >= progressRectangle.x && x <= CANVAS_WIDTH - progressRectangle.x ); } //------------------------------------------------------- public final void addActionListener(ActionListener li) { actionListeners.addElement(li); } //-------------------------------------- public final void removeActionListener(ActionListener li) { actionListeners.removeElement(li); } //-------------------------------------- protected final void fireActionPerformed(ActionEvent ev) { Enumeration en = actionListeners.elements(); while ( en.hasMoreElements() ) { ActionListener li = (ActionListener)en.nextElement(); li.actionPerformed(ev); } } //------------------------------------------------------- public final void setLabel(String l) { label = l; repaint(); } public final String getLabel() { return label; } //-------------------------------------- public final boolean isFocusable() { if(hasListeners) { return focusable; } else { return false; } } public final void setFocusable(boolean focusable) { this.focusable = focusable; super.setFocusable(focusable); } //------------------------------------------------------- public final Dimension getPreferredSize() { return getMinimumSize(); } public final Dimension getMinimumSize() { return new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT); } public final Dimension getMaximumSize() { return getMinimumSize(); } //------------------------------------------------------- }