controlp5/src/controlP5/Tooltip.java

437 lines
11 KiB
Java
Executable File

package controlP5;
import java.util.HashMap;
import java.util.Map;
import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PVector;
/**
* A tooltip can be registered for individual controllers
* and is activated on rollover.
*
* @example controllers/ControlP5tooltip
*
*/
public class Tooltip {
private ControllerView< ? > _myView;
private PVector position = new PVector( );
private PVector currentPosition = new PVector( );
private PVector previousPosition = new PVector( );
private PVector offset = new PVector( );
private Controller< ? > _myController;
private long startTime = 0;
private long _myDelayInMillis = 500;
private int _myMode = ControlP5.INACTIVE;
private int _myHeight = 20;
private int _myBackgroundColor = 0xffffffb4;
private int _myMaxAlpha = 255;
private int _myAlpha = 0;
private Map< Controller< ? > , String > map;
private Label _myLabel;
private boolean enabled = true;
private int _myBorder;
private ControlP5 cp5;
private int _myAlignH = ControlP5.RIGHT;
private int _myColor = 0x00000000;
Tooltip( ControlP5 theControlP5 ) {
cp5 = theControlP5;
position = new PVector( -1000 , -1000 );
currentPosition = new PVector( );
previousPosition = new PVector( );
offset = new PVector( 0 , 24 , 0 );
map = new HashMap< Controller< ? > , String >( );
_myLabel = new Label( cp5 , "tooltip" );
_myLabel.setColor( _myColor );
_myLabel.setPadding( 0 , 0 );
setView( new TooltipView( ) );
setBorder( 4 );
}
/**
* sets the border of the tooltip, the default border is
* 4px.
*
* @param theValue
* @return Tooltip
*/
public Tooltip setBorder( int theValue ) {
_myBorder = theValue;
_myLabel.getStyle( ).setMargin( _myBorder , _myBorder , _myBorder , _myBorder );
return this;
}
/**
* returns the value of the border
*
* @return
*/
public int getBorder( ) {
return _myBorder;
}
/**
* sets the transparency of the default background,
* default value is 200
*
* @param theValue
* @return Tooltip
*/
public Tooltip setAlpha( int theValue ) {
_myMaxAlpha = theValue;
return this;
}
private void updateText( String theText ) {
int n = 1;
for ( char c : theText.toCharArray( ) ) {
if ( c == '\n' ) {
n++;
}
}
if ( _myLabel.getHeight( ) != _myLabel.getLineHeight( ) * n ) {
_myLabel.setHeight( _myLabel.getLineHeight( ) * n );
}
_myLabel.set( theText );
}
/**
* TODO see below
* @param theWindow
*/
void draw( ControlWindow theWindow ) {
/*
if ( enabled ) {
if ( _myMode >= ControlP5.WAIT ) {
previousPosition.set( currentPosition );
currentPosition.set( theWindow.mouseX , theWindow.mouseY , 0 );
if ( _myController != null ) {
if ( _myController.getControlWindow( ).equals( theWindow ) ) {
switch ( _myMode ) {
case ( ControlP5.WAIT ):
if ( moved( ) ) {
startTime = System.nanoTime( );
}
if ( System.nanoTime( ) > startTime + ( _myDelayInMillis * 1000000 ) ) {
position.set( currentPosition );
_myAlignH = ControlP5.RIGHT;
if ( position.x > ( _myController.getControlWindow( ).papplet( ).width - ( getWidth( ) + 20 ) ) ) {
position.sub( new PVector( getWidth( ) , 0 , 0 ) );
_myAlignH = ControlP5.LEFT;
}
_myMode = ControlP5.FADEIN;
startTime = System.nanoTime( );
_myAlpha = 0;
}
break;
case ( ControlP5.FADEIN ):
float t1 = System.nanoTime( ) - startTime;
_myAlpha = ( int ) PApplet.map( t1 , 0 , 200 * 1000000 , 0 , _myMaxAlpha );
if ( _myAlpha >= 250 ) {
_myMode = ControlP5.IDLE;
_myAlpha = 255;
}
break;
case ( ControlP5.IDLE ):
break;
case ( ControlP5.FADEOUT ):
float t2 = System.nanoTime( ) - startTime;
_myAlpha = ( int ) PApplet.map( t2 , 0 , 200 * 1000000 , _myMaxAlpha , 0 );
if ( _myAlpha <= 0 ) {
_myMode = ControlP5.DONE;
}
break;
case ( ControlP5.DONE ):
_myController = null;
_myMode = ControlP5.INACTIVE;
position.set( -1000 , -1000 , 0 );
}
_myAlpha = PApplet.max( 0 , PApplet.min( _myAlpha , _myMaxAlpha ) );
if ( _myMode >= ControlP5.WAIT ) {
_myAlpha = ( _myMode == ControlP5.WAIT ) ? 0 : _myAlpha;
theWindow.papplet( ).pushMatrix( );
theWindow.papplet( ).translate( position.x , position.y );
theWindow.papplet( ).translate( offset.x , offset.y );
// TODO should request the current PGraphics element, not only the PApplet context. What if we render into a PGraphics buffer?
_myView.display( theWindow.papplet( ).g , null );
theWindow.papplet( ).popMatrix( );
}
if ( _myMode < ControlP5.FADEOUT ) {
if ( moved( ) ) {
deactivate( 0 );
}
}
}
}
}
}
*/
}
private boolean moved( ) {
return PApplet.abs( PApplet.dist( previousPosition.x , previousPosition.y , currentPosition.x , currentPosition.y ) ) > 1;
}
/**
* A tooltip is activated when entered by the mouse,
* after a given delay time the Tooltip starts to fade
* in. Use setDelay(long) to adjust the default delay
* time of 1000 millis.
*
* @param theMillis
* @return Tooltip
*/
public Tooltip setDelay( long theMillis ) {
_myDelayInMillis = theMillis;
return this;
}
/**
* a Tooltip is activated when the mouse enters a
* controller.
*
* @param theController
*/
protected void activate( Controller< ? > theController ) {
if ( map.containsKey( theController ) ) {
startTime = System.nanoTime( );
_myController = theController;
currentPosition.set( theController.getControlWindow( ).mouseX , theController.getControlWindow( ).mouseY , 0 );
updateText( map.get( _myController ) );
_myMode = ControlP5.WAIT;
}
}
protected void deactivate( ) {
deactivate( 1 );
}
protected void deactivate( int theNum ) {
if ( theNum == 0 ) {
if ( _myMode >= ControlP5.IDLE ) {
if ( _myMode < ControlP5.FADEOUT )
startTime = System.nanoTime( );
_myMode = ControlP5.FADEOUT;
}
} else {
_myMode = ( _myMode >= ControlP5.IDLE ) ? ControlP5.FADEOUT : ControlP5.DONE;
}
}
/**
* A custom view can be set for a Tooltip. The default
* view class can be found at the bottom of the Tooltip
* source.
*
* @see controlP5.ControllerView
* @param theDisplay
* @return Tooltip
*/
public Tooltip setView( ControllerView< ? > theDisplay ) {
_myView = theDisplay;
return this;
}
/**
* registers a controller with the Tooltip, when
* activating the tooltip for a particular controller,
* the registered text (second parameter) will be
* displayed.
*
* @param theController
* @param theText
* @return Tooltip
*/
public Tooltip register( Controller< ? > theController , String theText ) {
map.put( theController , theText );
theController.registerProperty( "setTooltipEnabled" , "isTooltipEnabled" );
return this;
}
public Tooltip register( String theControllerName , String theText ) {
Controller< ? > c = cp5.getController( theControllerName );
if ( c == null ) {
return this;
}
map.put( c , theText );
c.registerProperty( "setTooltipEnabled" , "isTooltipEnabled" );
return this;
}
/**
* removes a controller from the tooltip
*
* @param theController
* @return Tooltip
*/
public Tooltip unregister( Controller< ? > theController ) {
map.remove( theController );
theController.removeProperty( "setTooltipEnabled" , "isTooltipEnabled" );
return this;
}
public Tooltip unregister( String theControllerName ) {
Controller< ? > c = cp5.getController( theControllerName );
if ( c == null ) {
return this;
}
return unregister( c );
}
/**
* with the default display, the width of the tooltip is
* set automatically, therefore setWidth() does not have
* any effect without changing the default display to a
* custom ControllerView.
*
* @see controlP5.ControllerView
* @see controlP5.Tooltip#setDisplay(ControllerView)
* @return Tooltip
*/
public Tooltip setWidth( int theWidth ) {
// TODO
// _myWidth = theWidth;
return this;
}
public int getWidth( ) {
return _myLabel.getWidth( );
}
/**
* @see controlP5.Tooltip#setWidth(int)
* @param theHeight
* @return Tooltip
*/
public Tooltip setHeight( int theHeight ) {
ControlP5.logger( ).warning( "Tooltip.setHeight is disabled with this version" );
_myHeight = theHeight;
return this;
}
/**
* adds an offset to the position of the controller
* relative to the mouse cursor's position. default
* offset is (10,20)
*
* @param theX
* @param theY
* @return Tooltip
*/
public Tooltip setPositionOffset( float theX , float theY ) {
offset.x = theX;
offset.y = theY;
return this;
}
/**
* disables the Tooltip on a global level, when
* disabled, tooltip will not respond to any registered
* controller. to disable a tooltip for aparticular
* controller, used unregister(Controller)
*
* @see controlP5.Tooltip#unregister(Controller)
* @return Tooltip
*/
public Tooltip disable( ) {
enabled = false;
return this;
}
/**
* in case the tooltip is disabled, use enable() to turn
* the tooltip back on.
*
* @return Tooltip
*/
public Tooltip enable( ) {
enabled = true;
return this;
}
/**
* check if the tooltip is enabled or disabled
*
* @return boolean
*/
public boolean isEnabled( ) {
return enabled;
}
/**
* sets the Label to a custom label and replaces the
* default label.
*
* @param theLabel
* @return Tooltip
*/
public Tooltip setLabel( Label theLabel ) {
_myLabel = theLabel;
return this;
}
/**
* returns the current Label
*
* @return Label
*/
public Label getLabel( ) {
return _myLabel;
}
/**
* sets the background color of the tooltip, the default
* color is a dark grey
*
* @param theColor
* @return Tooltip
*/
public Tooltip setColorBackground( int theColor ) {
_myBackgroundColor = theColor;
return this;
}
/**
* sets the text color of the tooltip's label, the
* default color is a white
*
* @param theColor
* @return Tooltip
*/
public Tooltip setColorLabel( int theColor ) {
_myColor = theColor;
_myLabel.setColor( theColor );
return this;
}
class TooltipView implements ControllerView< Controller< ? >> {
public void display( PGraphics theGraphics , Controller< ? > theController ) {
_myHeight = _myLabel.getHeight( );
theGraphics.fill( _myBackgroundColor , _myAlpha );
theGraphics.rect( 0 , 0 , getWidth( ) + _myBorder * 2 , _myHeight + _myBorder * 2 );
theGraphics.pushMatrix( );
if ( _myAlignH == ControlP5.RIGHT ) {
theGraphics.translate( 6 , 0 );
} else {
theGraphics.translate( getWidth( ) - 6 , 0 );
}
theGraphics.triangle( 0 , 0 , 4 , -4 , 8 , 0 );
theGraphics.popMatrix( );
int a = ( int ) ( PApplet.map( _myAlpha , 0 , _myMaxAlpha , 0 , 255 ) );
_myLabel.setColor( a << 24 | ( _myColor >> 16 ) << 16 | ( _myColor >> 8 ) << 8 | ( _myColor >> 0 ) << 0 );
_myLabel.draw( theGraphics , 0 , 0 , theController );
}
}
}