Package de.sciss.swingosc

Source Code of de.sciss.swingosc.MonoSlider

/*
*  MonoSlider.java
*  SwingOSC
*
*  Copyright (c) 2005-2011 Hanns Holger Rutz. All rights reserved.
*
*  This software 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 2, june 1991 of the License, or (at your option) any later version.
*
*  This software 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 (gpl.txt) along with this software; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
*  For further information, please contact Hanns Holger Rutz at
*  contact@sciss.de
*
*
*  Changelog:
*    28-Oct-06  created from SliderBase
*/

package de.sciss.swingosc;

import java.awt.Color;
import java.awt.Image;
import java.awt.Insets;
import java.awt.MediaTracker;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import javax.swing.event.MouseInputAdapter;

/**
*  Abstract superclass of range and 2D sliders.
*  Sliders can be horizontal and/or vertically slideable,
*  they can have a horizontal or vertical extent.
*  All values are normalized to the interval [0...1]
*  where vertical coordinates are flipped (1 = top margin,
*  0 = bottom margin).
*
@author    Hanns Holger Rutz
@version  0.59, 25-Feb-08
*/
public abstract class MonoSlider
extends SliderBase
{
  protected float  knobX    = 0.0f;
  protected float  knobY    = 0.0f;
  protected float  knobWidth  = 0.0f;
  protected float  knobHeight  = 0.0f;

  private boolean    hsEnabled;
  private boolean    vsEnabled;
  protected boolean  hrEnabled;
  protected boolean  vrEnabled;
 
  protected static final MultiplyImageFilter fltKnobD =
    new MultiplyImageFilter( 0xFF, 0xFF, 0xFF, 0x7F );
 
  protected Color  colrKnob  = null;
  protected Color  colrKnobD  = null;
  protected final MediumLightImageFilter fltKnob;

  protected MonoSlider()
  {
    super();

    fltKnob      = new MediumLightImageFilter();
   
    final MouseAdapter ma = new MouseAdapter();
    addMouseListener( ma );
    addMouseMotionListener( ma );
}
 
  protected MonoSlider( boolean hsEnabled, boolean vsEnabled,
              boolean hrEnabled, boolean vrEnabled )
  {
    this();

    this.hsEnabled  = hsEnabled;
    this.vsEnabled  = vsEnabled;
    this.hrEnabled  = hrEnabled;
    this.vrEnabled  = vrEnabled;
  }
 
  /**
   *  Adjust the horizontal minimum value or position
   *
   *  @param  x  the new x or horizontal min value
   *
   *  @warning    the value is not checked for valid range;
   *        be sure that 0 <= x <= 1 - knobWidth;
   *        be sure to use snap( x ) if a stepSize was
   *        specified
   */
  public void setKnobX( float x )
  {
    knobX  = x;
    repaint();
  }

  /**
   *  Adjust the vertical minimum value or position
   *
   *  @param  y  the new y or vertical min value
   *
   *  @warning    the value is not checked for valid range;
   *        be sure that 0 <= y <= 1 - knobHeight;
   *        be sure to use snap( y ) if a stepSize was
   *        specified
   */
  public void setKnobY( float y )
  {
    knobY  = y;
    repaint();
  }
 
  /**
   *  Adjust the horizontal extent
   *
   *  @param  w  the new horizontal knob extent
   *
   *  @warning  the value is not checked for valid range;
   *        be sure that knobX <= w <= 1 - knobX;
   *        be sure to use snap( w ) if a stepSize was
   *        specified
   */
  public void setKnobWidth( float w )
  {
    knobWidth  = w;
    repaint();
  }
 
  /**
   *  Adjust the vertical extent
   *
   *  @param  h  the new vertical knob extent
   *
   *  @warning    the value is not checked for valid range;
   *        be sure that knobY <= h <= 1 - knobY;
   *        be sure to use snap( h ) if a stepSize was
   *        specified
   */
  public void setKnobHeight( float h )
  {
    knobHeight  = h;
    repaint();
  }
 
  /**
   *  Adjust the colour of the knob or handle.
   *
   *  @param  c  the new colour or <code>null</code> to
   *        have a clear knob. The colour may have
   *        an alpha component other than 0xFF
   */
  public void setKnobColor( Color c )
  {
    colrKnob  = c;
    if( c != null ) {
//      if( c.getAlpha() == 0xFF ) {
        fltKnob.setColor( c );
//      } else {
//        final float w = (float) c.getAlpha() / 0xFF;
//        final int add = 0xFF - c.getAlpha();
//        fltKnob.setColor( new Color(  (int) (c.getRed() * w + add),
//                      (int) (c.getGreen() * w + add),
//                      (int) (c.getBlue() * w + add) ));
//      }
    }
    repaint();
  }
 
  /**
   *  Queries the horizontal minimum value or position
   *
   *  @return  the current x position
   */
  public float getKnobX()
  {
    return knobX;
  }

  /**
   *  Queries the vertical minimum value or position
   *
   *  @return  the current y position
   */
  public float getKnobY()
  {
    return knobY;
  }
 
  /**
   *  Queries the horizontal knob extent
   *
   *  @return  the current horizontal width
   */
  public float getKnobWidth()
  {
    return knobWidth;
  }
 
  /**
   *  Queries the vertical knob extent
   *
   *  @return  the current vertical height
   */
  public float getKnobHeight()
  {
    return knobHeight;
  }
 
  /**
   *  Adjusts the horizontal slideability.
   *  Note: subclasses may have a hardcoded slideability
   *  and changing it can result in painting artifacts
   *
   *  @param  onOff  <code>true</code> to allow the knob to
   *          be horizontally moved
   */
  public void setHorizontalSlideEnabled( boolean onOff )
  {
    hsEnabled = onOff;
  }
 
  /**
   *  Adjusts the vertical slideability
   *  Note: subclasses may have a hardcoded slideability
   *  and changing it can result in painting artifacts
   *
   *  @param  onOff  <code>true</code> to allow the knob to
   *          be vertically moved
   */
  public void setVerticalSlideEnabled( boolean onOff )
  {
    vsEnabled = onOff;
  }
 
  /**
   *  Queries the horizontal slideability
   *
   *  @return  <code>true</code> if the knob can be horizontally moved
   */
  public boolean getHorizontalSlideEnabled()
  {
    return hsEnabled;
  }
 
  /**
   *  Queries the vertical slideability
   *
   *  @return  <code>true</code> if the knob can be vertically moved
   */
  public boolean getVerticalSlideEnabled()
  {
    return vsEnabled;
  }
 
  /**
   *  Adjusts the horizontal resizeability.
   *  Note: subclasses may have a hardcoded resizeability
   *  and changing it can result in painting artifacts
   *
   *  @param  onOff  <code>true</code> to allow the knob to
   *          be horizontally resized
   */
  public void setHorizontalResizeEnabled( boolean onOff )
  {
    hrEnabled = onOff;
  }
 
  /**
   *  Adjusts the vertical resizeability.
   *  Note: subclasses may have a hardcoded resizeability
   *  and changing it can result in painting artifacts
   *
   *  @param  onOff  <code>true</code> to allow the knob to
   *          be vertically resized
   */
  public void setVerticalResizeEnabled( boolean onOff )
  {
    vrEnabled = onOff;
  }
 
  /**
   *  Queries the horizontal resizeability
   *
   *  @return  <code>true</code> if the knob can be horizontally resized
   */
  public boolean getHorizontalResizeEnabled()
  {
    return hrEnabled;
  }
 
  /**
   *  Queries the vertical resizeability
   *
   *  @return  <code>true</code> if the knob can be vertically resized
   */
  public boolean getVerticalResizeEnabled()
  {
    return vrEnabled;
  }
 
  protected void setKnobTo( Point2D p )
  {
    final float x, y;
   
    if( hsEnabled ) {
      x = snap( Math.max( 0f, Math.min( 1.0f, (float) p.getX() )));
    } else {
      x = knobX;
    }
    if( vsEnabled ) {
      y = snap( Math.max( 0f, Math.min( 1.0f, (float) p.getY() )));
    } else {
      y = knobY;
    }
   
    if( (x != knobX) || (y != knobY) ||
      (knobWidth != 0f) || (knobHeight != 0f) ) {

      knobX     = x;
      knobY     = y;
      knobWidth  = 0f;
      knobHeight  = 0f;
      repaint();
      fireActionPerformed();
    }
  }
 
  protected void resizeKnobTo( Point2D p, float fixX, float fixY )
  {
    final float resizeX, resizeY;
    final float newKnobX, newKnobY, newKnobW, newKnobH;
   
    if( hsEnabled ) {
      resizeX   = snap( Math.max( 0f, Math.min( 1.0f, (float) p.getX() )));
    } else {
      resizeX   = knobX;
      fixX    = knobX;
    }
    if( vsEnabled ) {
      resizeY   = snap( Math.max( 0f, Math.min( 1.0f, (float) p.getY() )));
    } else {
      resizeY   = knobY;
      fixY    = knobY;
    }
   
    newKnobX = Math.min( fixX, resizeX );
    newKnobY = Math.min( fixY, resizeY );
    newKnobW = Math.abs( fixX - resizeX );
    newKnobH = Math.abs( fixY - resizeY );
   
    if( (newKnobX != knobX) || (newKnobY != knobY) ||
      (newKnobW != knobWidth) || (newKnobH != knobHeight) ) {

      knobX     = newKnobX;
      knobY     = newKnobY;
      knobWidth  = newKnobW;
      knobHeight  = newKnobH;
      repaint();
      fireActionPerformed();
    }
  }
 
  protected void moveKnobTo( float x, float y )
  {
    if( hsEnabled ) {
      x = snap( Math.max( 0f, Math.min( 1.0f - knobWidth, x )));
    } else {
      x = knobX;
    }
    if( vsEnabled ) {
      y = snap( Math.max( 0f, Math.min( 1.0f - knobHeight, y )));
    } else {
      y = knobY;
    }
   
    if( (x != knobX) || (y != knobY) ) {
      knobX     = x;
      knobY     = y;
      repaint();
      fireActionPerformed();
    }
  }
   
  protected abstract Insets getValueInsets();
 
  protected Point2D screenToVirtual( Point p )
  {
    final Insets ins = getValueInsets();
   
    return new Point2D.Float( (float) (p.x - ins.left) / (getWidth() - ins.left - ins.right),
                 1.0f - (float) (p.y - ins.top) / (getHeight() - ins.top - ins.bottom) );
  }
 
  protected boolean knobContains( Point2D p )
  {
    return( (!hsEnabled || ((p.getX() >= knobX) && (p.getX() < knobX + knobWidth))) &&
          (!vsEnabled || ((p.getY() >= knobY) && (p.getY() < knobY + knobHeight)))
    );
  }
 
  protected void waitForImage( Image img )
  {
    final MediaTracker mt = new MediaTracker( this );
    mt.addImage( img, 0 );
    try {
      mt.waitForAll();
    } catch( InterruptedException e1 ) { /* ignored */ }
  }

//   ---------------- internal classes ----------------

  private class MouseAdapter
  extends MouseInputAdapter
  {
    private boolean   pressed   = false;
    private boolean   moving    = false;
    private float    dragFixX;
    private float    dragFixY;
   
    protected MouseAdapter() { /* empty */ }
   
    public void mousePressed( MouseEvent e )
    {
      if( !isEnabled() ) return;

      requestFocus();

      if( e.isControlDown() ) return;

      pressed = true;
     
      final Point2D vPt = screenToVirtual( e.getPoint() );
       
      if( e.isShiftDown() && (hrEnabled || vrEnabled) ) {
        if( hrEnabled ) {
          if( Math.abs( vPt.getX() - knobX ) <
            Math.abs( knobX + knobWidth - vPt.getX() )) {
           
            dragFixX = knobX + knobWidth;
          } else {
            dragFixX = knobX;
          }
        }
        if( vrEnabled ) {
          if( Math.abs( vPt.getY() - knobY ) <
            Math.abs( knobY + knobHeight - vPt.getY() )) {
           
            dragFixY = knobY + knobHeight;
          } else {
            dragFixY = knobY;
          }
        }
        resizeKnobTo( vPt, dragFixX, dragFixY );
       
      } else if( e.isAltDown() || !(hrEnabled || vrEnabled) ||
        !knobContains( vPt )) {
       
        setKnobTo( vPt );
        dragFixX = knobX;
        dragFixY = knobY;
      } else {
        moving   = true;
        dragFixX = (float) vPt.getX() - knobX;
        dragFixY = (float) vPt.getY() - knobY;
      }
    }
   
    public void mouseReleased( MouseEvent e )
    {
      pressed   = false;
      moving    = false;
    }
   
    public void mouseDragged( MouseEvent e )
    {
      if( !pressed || !isEnabled() ) return;
     
      final Point2D vPt = screenToVirtual( e.getPoint() );
     
      if( moving ) {
        moveKnobTo( (float) vPt.getX() - dragFixX, (float) vPt.getY() - dragFixY );
      } else if( hrEnabled || vrEnabled ) {
        resizeKnobTo( vPt, dragFixX, dragFixY );
      } else {
        setKnobTo( vPt );
      }
    }
   
    public void mouseMoved( MouseEvent e )
    {
      // on mac, ctrl+press and moving will
      // not generate mouseDragged messages
      // but mouseMoved instead
      mouseDragged( e );
    }
  }
}
TOP

Related Classes of de.sciss.swingosc.MonoSlider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.