mirror of
https://github.com/sojamo/controlp5
synced 2024-11-16 11:17:56 +01:00
562 lines
16 KiB
Java
Executable File
562 lines
16 KiB
Java
Executable File
package main.java.src2.main.java.controlP5.controlP5;
|
|
|
|
/**
|
|
* controlP5 is a processing gui library.
|
|
*
|
|
* 2006-2015 by Andreas Schlegel
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1
|
|
* of the License, or (at your option) any later version.
|
|
* This 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General
|
|
* Public License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA
|
|
*
|
|
* @author Andreas Schlegel (http://www.sojamo.de)
|
|
* @modified ##date##
|
|
* @version ##version##
|
|
*
|
|
*/
|
|
|
|
import java.util.Iterator;
|
|
import java.util.LinkedHashMap;
|
|
|
|
import processing.core.PApplet;
|
|
import processing.core.PGraphics;
|
|
|
|
/**
|
|
* Use charts to display float array data as line chart, yet experimental, but see the
|
|
* ControlP5chart example for more details.
|
|
*
|
|
* @example controllers/ControlP5chart
|
|
*/
|
|
public class Chart extends Controller< Chart > {
|
|
|
|
public final static int LINE = 0;
|
|
public final static int BAR = 1;
|
|
public final static int BAR_CENTERED = 2;
|
|
public final static int HISTOGRAM = 3;
|
|
public final static int PIE = 4;
|
|
public final static int AREA = 5;
|
|
|
|
protected final LinkedHashMap< String , ChartDataSet > _myDataSet;
|
|
protected float resolution = 1;
|
|
protected float strokeWeight = 1;
|
|
protected float _myMin = 0;
|
|
protected float _myMax = 1;
|
|
|
|
/**
|
|
* Convenience constructor to extend Chart.
|
|
*
|
|
* @example use/ControlP5extendController
|
|
* @param theControlP5
|
|
* @param theName
|
|
*/
|
|
public Chart( ControlP5 theControlP5 , String theName ) {
|
|
this( theControlP5 , theControlP5.getDefaultTab( ) , theName , 0 , 0 , 200 , 100 );
|
|
theControlP5.register( theControlP5.papplet , theName , this );
|
|
}
|
|
|
|
protected Chart( ControlP5 theControlP5 , ControllerGroup< ? > theParent , String theName , float theX , float theY , int theWidth , int theHeight ) {
|
|
super( theControlP5 , theParent , theName , theX , theY , theWidth , theHeight );
|
|
setRange( 0 , theHeight );
|
|
_myDataSet = new LinkedHashMap< String , ChartDataSet >( );
|
|
getCaptionLabel( ).align( LEFT, BOTTOM_OUTSIDE ).paddingX = 0;
|
|
|
|
}
|
|
|
|
public Chart setRange( float theMin , float theMax ) {
|
|
_myMin = theMin;
|
|
_myMax = theMax;
|
|
return this;
|
|
}
|
|
|
|
public Chart setColors( String theSetIndex , int ... theColors ) {
|
|
getDataSet( ).get( theSetIndex ).setColors( theColors );
|
|
return this;
|
|
}
|
|
|
|
public Chart addData( ChartData theItem ) {
|
|
return addData( getFirstDataSetIndex( ) , theItem );
|
|
}
|
|
|
|
private String getFirstDataSetIndex( ) {
|
|
return getDataSet( ).keySet( ).iterator( ).next( );
|
|
}
|
|
|
|
private String getLastDataSetIndex( ) {
|
|
Iterator< String > it = getDataSet( ).keySet( ).iterator( );
|
|
String last = null;
|
|
while ( it.hasNext( ) ) {
|
|
last = it.next( );
|
|
}
|
|
return last;
|
|
}
|
|
|
|
public Chart addData( String theSetIndex , ChartData theItem ) {
|
|
getDataSet( theSetIndex ).add( theItem );
|
|
return this;
|
|
}
|
|
|
|
public Chart addData( float theValue ) {
|
|
ChartData cdi = new ChartData( theValue );
|
|
getDataSet( getFirstDataSetIndex( ) ).add( cdi );
|
|
return this;
|
|
}
|
|
|
|
public Chart addData( String theSetIndex , float theValue ) {
|
|
ChartData cdi = new ChartData( theValue );
|
|
getDataSet( theSetIndex ).add( cdi );
|
|
return this;
|
|
}
|
|
|
|
public Chart addData( ChartDataSet theChartData , float theValue ) {
|
|
ChartData cdi = new ChartData( theValue );
|
|
theChartData.add( cdi );
|
|
return this;
|
|
}
|
|
|
|
// array operations see syntax
|
|
// http://www.w3schools.com/jsref/jsref_obj_array.asp
|
|
|
|
/**
|
|
* adds a new float at the beginning of the data set.
|
|
*/
|
|
public Chart unshift( float theValue ) {
|
|
return unshift( getFirstDataSetIndex( ) , theValue );
|
|
}
|
|
|
|
public Chart unshift( String theSetIndex , float theValue ) {
|
|
if ( getDataSet( theSetIndex ).size( ) > ( getWidth() / resolution ) ) {
|
|
removeLast( theSetIndex );
|
|
}
|
|
return addFirst( theSetIndex , theValue );
|
|
}
|
|
|
|
public Chart push( float theValue ) {
|
|
return push( getFirstDataSetIndex( ) , theValue );
|
|
}
|
|
|
|
public Chart push( String theSetIndex , float theValue ) {
|
|
if ( getDataSet( theSetIndex ).size( ) > ( getWidth() / resolution ) ) {
|
|
removeFirst( theSetIndex );
|
|
}
|
|
return addLast( theSetIndex , theValue );
|
|
}
|
|
|
|
public Chart addFirst( float theValue ) {
|
|
return addFirst( getFirstDataSetIndex( ) , theValue );
|
|
}
|
|
|
|
public Chart addFirst( String theSetIndex , float theValue ) {
|
|
ChartData cdi = new ChartData( theValue );
|
|
getDataSet( theSetIndex ).add( 0 , cdi );
|
|
return this;
|
|
}
|
|
|
|
public Chart addLast( float theValue ) {
|
|
return addLast( getFirstDataSetIndex( ) , theValue );
|
|
}
|
|
|
|
public Chart addLast( String theSetIndex , float theValue ) {
|
|
ChartData cdi = new ChartData( theValue );
|
|
getDataSet( theSetIndex ).add( cdi );
|
|
return this;
|
|
}
|
|
|
|
public Chart removeLast( ) {
|
|
return removeLast( getFirstDataSetIndex( ) );
|
|
}
|
|
|
|
public Chart removeLast( String theSetIndex ) {
|
|
return removeData( theSetIndex , getDataSet( theSetIndex ).size( ) - 1 );
|
|
}
|
|
|
|
public Chart removeFirst( ) {
|
|
return removeFirst( getFirstDataSetIndex( ) );
|
|
}
|
|
|
|
public Chart removeFirst( String theSetIndex ) {
|
|
return removeData( theSetIndex , 0 );
|
|
}
|
|
|
|
public Chart removeData( ChartData theItem ) {
|
|
removeData( getFirstDataSetIndex( ) , theItem );
|
|
return this;
|
|
}
|
|
|
|
public Chart removeData( String theSetIndex , ChartData theItem ) {
|
|
getDataSet( theSetIndex ).remove( theItem );
|
|
return this;
|
|
}
|
|
|
|
public Chart removeData( int theItemIndex ) {
|
|
removeData( getFirstDataSetIndex( ) , theItemIndex );
|
|
return this;
|
|
}
|
|
|
|
public Chart removeData( String theSetIndex , int theItemIndex ) {
|
|
if ( getDataSet( theSetIndex ).size( ) < 1 ) {
|
|
return this;
|
|
}
|
|
getDataSet( theSetIndex ).remove( theItemIndex );
|
|
return this;
|
|
}
|
|
|
|
public Chart setData( int theItemIndex , ChartData theItem ) {
|
|
getDataSet( getFirstDataSetIndex( ) ).set( theItemIndex , theItem );
|
|
return this;
|
|
}
|
|
|
|
public Chart setData( String theSetItem , int theItemIndex , ChartData theItem ) {
|
|
getDataSet( theSetItem ).set( theItemIndex , theItem );
|
|
return this;
|
|
}
|
|
|
|
public Chart addDataSet( String theName ) {
|
|
getDataSet( ).put( theName , new ChartDataSet( theName ) );
|
|
return this;
|
|
}
|
|
|
|
public Chart setDataSet( ChartDataSet theItems ) {
|
|
setDataSet( getFirstDataSetIndex( ) , theItems );
|
|
return this;
|
|
}
|
|
|
|
public Chart setDataSet( String theSetIndex , ChartDataSet theChartData ) {
|
|
getDataSet( ).put( theSetIndex , theChartData );
|
|
return this;
|
|
}
|
|
|
|
public Chart removeDataSet( String theIndex ) {
|
|
getDataSet( ).remove( theIndex );
|
|
return this;
|
|
}
|
|
|
|
public Chart setData( float ... theValues ) {
|
|
setData( getFirstDataSetIndex( ) , theValues );
|
|
return this;
|
|
}
|
|
|
|
public Chart setData( String theSetIndex , float ... theValues ) {
|
|
if ( getDataSet( ).get( theSetIndex ).size( ) != theValues.length ) {
|
|
getDataSet( ).get( theSetIndex ).clear( );
|
|
for ( int i = 0 ; i < theValues.length ; i++ ) {
|
|
getDataSet( ).get( theSetIndex ).add( new ChartData( 0 ) );
|
|
}
|
|
}
|
|
int n = 0;
|
|
resolution = ( float ) getWidth() / ( getDataSet( ).get( theSetIndex ).size( ) - 1 );
|
|
for ( float f : theValues ) {
|
|
getDataSet( ).get( theSetIndex ).get( n++ ).setValue( f );
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public Chart updateData( float ... theValues ) {
|
|
return setData( theValues );
|
|
}
|
|
|
|
public Chart updateData( String theSetIndex , float ... theValues ) {
|
|
return setData( theSetIndex , theValues );
|
|
}
|
|
|
|
public LinkedHashMap< String , ChartDataSet > getDataSet( ) {
|
|
return _myDataSet;
|
|
}
|
|
|
|
public ChartDataSet getDataSet( String theIndex ) {
|
|
return getDataSet( ).get( theIndex );
|
|
}
|
|
|
|
public float[] getValuesFrom( String theIndex ) {
|
|
return getDataSet( theIndex ).getValues( );
|
|
}
|
|
|
|
public ChartData getData( String theIndex , int theItemIndex ) {
|
|
return getDataSet( theIndex ).get( theItemIndex );
|
|
}
|
|
|
|
public int size( ) {
|
|
return getDataSet( ).size( );
|
|
}
|
|
|
|
@Override
|
|
public void onEnter( ) {
|
|
}
|
|
|
|
@Override
|
|
public void onLeave( ) {
|
|
}
|
|
|
|
@Override
|
|
public Chart setValue( float theValue ) {
|
|
// TODO Auto-generated method stub
|
|
return this;
|
|
}
|
|
|
|
public Chart setStrokeWeight( float theWeight ) {
|
|
strokeWeight = theWeight;
|
|
for ( ChartDataSet c : getDataSet( ).values( ) ) {
|
|
c.setStrokeWeight( theWeight );
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public float getStrokeWeight( ) {
|
|
return strokeWeight;
|
|
}
|
|
|
|
/**
|
|
* ?
|
|
*
|
|
* @param theValue
|
|
* @return
|
|
*/
|
|
public Chart setResolution( int theValue ) {
|
|
resolution = theValue;
|
|
return this;
|
|
}
|
|
|
|
public int getResolution( ) {
|
|
return ( int ) resolution;
|
|
}
|
|
|
|
/**
|
|
* @exclude
|
|
*/
|
|
@Override
|
|
@ControlP5.Invisible
|
|
public Chart updateDisplayMode( int theMode ) {
|
|
return updateViewMode( theMode );
|
|
}
|
|
|
|
/**
|
|
* @exclude
|
|
*/
|
|
@ControlP5.Invisible
|
|
public Chart updateViewMode( int theMode ) {
|
|
_myDisplayMode = theMode;
|
|
switch ( theMode ) {
|
|
case ( DEFAULT ):
|
|
_myControllerView = new ChartViewPie( );
|
|
break;
|
|
case ( IMAGE ):
|
|
// _myDisplay = new ChartImageDisplay();
|
|
break;
|
|
case ( SPRITE ):
|
|
// _myDisplay = new ChartSpriteDisplay();
|
|
break;
|
|
case ( CUSTOM ):
|
|
default:
|
|
break;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public class ChartViewBar implements ControllerView< Chart > {
|
|
|
|
public void display( PGraphics theGraphics , Chart theController ) {
|
|
theGraphics.pushStyle( );
|
|
theGraphics.fill( getColor( ).getBackground( ) );
|
|
theGraphics.rect( 0 , 0 , getWidth( ) , getHeight( ) );
|
|
theGraphics.noStroke( );
|
|
|
|
Iterator< String > it = getDataSet( ).keySet( ).iterator( );
|
|
String index = null;
|
|
float o = 0;
|
|
while ( it.hasNext( ) ) {
|
|
index = it.next( );
|
|
float s = getDataSet( index ).size( );
|
|
for ( int i = 0 ; i < s ; i++ ) {
|
|
theGraphics.fill( getDataSet( index ).getColor( i ) );
|
|
float ww = ( ( getWidth() / s ) );
|
|
float hh = PApplet.map( getDataSet( index ).get( i ).getValue( ) , _myMin , _myMax , 0 , getHeight( ) );
|
|
theGraphics.rect( o + i * ww , getHeight( ) , ( ww / getDataSet( ).size( ) ) , -PApplet.min( getHeight( ) , PApplet.max( 0 , hh ) ) );
|
|
}
|
|
o += ( ( getWidth() / s ) ) / getDataSet( ).size( );
|
|
}
|
|
theGraphics.popStyle( );
|
|
}
|
|
}
|
|
|
|
public class ChartViewBarCentered implements ControllerView< Chart > {
|
|
|
|
public void display( PGraphics theGraphics , Chart theController ) {
|
|
theGraphics.pushStyle( );
|
|
theGraphics.fill( getColor( ).getBackground( ) );
|
|
theGraphics.rect( 0 , 0 , getWidth( ) , getHeight( ) );
|
|
theGraphics.noStroke( );
|
|
|
|
Iterator< String > it = getDataSet( ).keySet( ).iterator( );
|
|
String index = null;
|
|
float o = 0;
|
|
int n = 4;
|
|
int off = ( getDataSet( ).size( ) - 1 ) * n;
|
|
while ( it.hasNext( ) ) {
|
|
index = it.next( );
|
|
int s = getDataSet( index ).size( );
|
|
float step = ( float ) getWidth() / ( float ) ( s );
|
|
float ww = step - ( getWidth() % step );
|
|
ww -= 1;
|
|
ww = PApplet.max( 1 , ww );
|
|
|
|
for ( int i = 0 ; i < s ; i++ ) {
|
|
theGraphics.fill( getDataSet( index ).getColor( i ) );
|
|
ww = ( ( getWidth() / s ) * 0.5f );
|
|
float hh = PApplet.map( getDataSet( index ).get( i ).getValue( ) , _myMin , _myMax , 0 , getHeight( ) );
|
|
theGraphics.rect( -off / 2 + o + i * ( ( getWidth() / s ) ) + ww / 2 , getHeight( ) , ww , -PApplet.min( getHeight( ) , PApplet.max( 0 , hh ) ) );
|
|
}
|
|
o += n;
|
|
}
|
|
theGraphics.popStyle( );
|
|
}
|
|
}
|
|
|
|
public class ChartViewLine implements ControllerView< Chart > {
|
|
|
|
public void display( PGraphics theGraphics , Chart theController ) {
|
|
|
|
theGraphics.pushStyle( );
|
|
theGraphics.fill( getColor( ).getBackground( ) );
|
|
theGraphics.rect( 0 , 0 , getWidth( ) , getHeight( ) );
|
|
theGraphics.noFill( );
|
|
Iterator< String > it = getDataSet( ).keySet( ).iterator( );
|
|
String index = null;
|
|
while ( it.hasNext( ) ) {
|
|
index = it.next( );
|
|
theGraphics.stroke( getDataSet( index ).getColor( 0 ) );
|
|
theGraphics.strokeWeight( getDataSet( index ).getStrokeWeight( ) );
|
|
|
|
theGraphics.beginShape( );
|
|
float res = ( ( float ) getWidth( ) ) / ( getDataSet( index ).size( ) - 1 );
|
|
for ( int i = 0 ; i < getDataSet( index ).size( ) ; i++ ) {
|
|
float hh = PApplet.map( getDataSet( index ).get( i ).getValue( ) , _myMin , _myMax , getHeight( ) , 0 );
|
|
theGraphics.vertex( i * res , PApplet.min( getHeight( ) , PApplet.max( 0 , hh ) ) );
|
|
}
|
|
theGraphics.endShape( );
|
|
}
|
|
theGraphics.noStroke( );
|
|
theGraphics.popStyle( );
|
|
getCaptionLabel( ).draw( theGraphics , 0 , 0 , theController );
|
|
}
|
|
}
|
|
|
|
public class ChartViewArea implements ControllerView< Chart > {
|
|
|
|
public void display( PGraphics theGraphics , Chart theController ) {
|
|
|
|
theGraphics.pushStyle( );
|
|
theGraphics.fill( getColor( ).getBackground( ) );
|
|
theGraphics.rect( 0 , 0 , getWidth( ) , getHeight( ) );
|
|
theGraphics.noStroke( );
|
|
|
|
Iterator< String > it = getDataSet( ).keySet( ).iterator( );
|
|
String index = null;
|
|
while ( it.hasNext( ) ) {
|
|
index = it.next( );
|
|
float res = ( ( float ) getWidth( ) ) / ( getDataSet( index ).size( ) - 1 );
|
|
|
|
theGraphics.fill( getDataSet( index ).getColor( 0 ) );
|
|
theGraphics.beginShape( );
|
|
theGraphics.vertex( 0 , getHeight( ) );
|
|
|
|
for ( int i = 0 ; i < getDataSet( index ).size( ) ; i++ ) {
|
|
float hh = PApplet.map( getDataSet( index ).get( i ).getValue( ) , _myMin , _myMax , getHeight( ) , 0 );
|
|
theGraphics.vertex( i * res , PApplet.min( getHeight( ) , PApplet.max( 0 , hh ) ) );
|
|
}
|
|
theGraphics.vertex( getWidth( ) , getHeight( ) );
|
|
theGraphics.endShape( PApplet.CLOSE );
|
|
}
|
|
theGraphics.noStroke( );
|
|
theGraphics.popStyle( );
|
|
}
|
|
}
|
|
|
|
public class ChartViewPie implements ControllerView< Chart > {
|
|
|
|
public void display( PGraphics theGraphics , Chart theController ) {
|
|
theGraphics.pushStyle( );
|
|
theGraphics.pushMatrix( );
|
|
|
|
Iterator< String > it = getDataSet( ).keySet( ).iterator( );
|
|
String index = null;
|
|
while ( it.hasNext( ) ) {
|
|
index = it.next( );
|
|
float total = 0;
|
|
for ( int i = 0 ; i < getDataSet( index ).size( ) ; i++ ) {
|
|
total += getDataSet( index ).get( i ).getValue( );
|
|
}
|
|
|
|
float segment = TWO_PI / total;
|
|
float angle = -HALF_PI;
|
|
|
|
theGraphics.noStroke( );
|
|
for ( int i = 0 ; i < getDataSet( index ).size( ) ; i++ ) {
|
|
theGraphics.fill( getDataSet( index ).getColor( i ) );
|
|
float nextAngle = angle + getDataSet( index ).get( i ).getValue( ) * segment;
|
|
|
|
// a tiny offset to even out render artifacts when in smooth() mode.
|
|
float a = PApplet.max( 0 , PApplet.map( getWidth( ) , 0 , 200 , 0.05f , 0.01f ) );
|
|
|
|
theGraphics.arc( 0 , 0 , getWidth( ) , getHeight( ) , angle - a , nextAngle );
|
|
angle = nextAngle;
|
|
}
|
|
theGraphics.translate( 0 , ( getHeight( ) + 10 ) );
|
|
}
|
|
theGraphics.popMatrix( );
|
|
theGraphics.popStyle( );
|
|
}
|
|
}
|
|
|
|
public Chart setView( int theType ) {
|
|
switch ( theType ) {
|
|
case ( PIE ):
|
|
setView( new ChartViewPie( ) );
|
|
break;
|
|
case ( LINE ):
|
|
setView( new ChartViewLine( ) );
|
|
break;
|
|
case ( BAR ):
|
|
setView( new ChartViewBar( ) );
|
|
break;
|
|
case ( BAR_CENTERED ):
|
|
setView( new ChartViewBarCentered( ) );
|
|
break;
|
|
case ( AREA ):
|
|
setView( new ChartViewArea( ) );
|
|
break;
|
|
default:
|
|
System.out.println( "Sorry, this ChartView does not exist" );
|
|
break;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public String getInfo( ) {
|
|
return "type:\tChart\n" + super.toString( );
|
|
}
|
|
|
|
@Override
|
|
public String toString( ) {
|
|
return super.toString( ) + " [ " + getValue( ) + " ]" + " Chart " + "(" + this.getClass( ).getSuperclass( ) + ")";
|
|
}
|
|
|
|
}
|
|
|
|
/* NOTES what is the difference in meaning between chart and graph
|
|
* http://answers.yahoo.com/question/index?qid=20090101193325AA3mgMl
|
|
*
|
|
* more charts to implement: from https://vimeo.com/groups/oaod/videos/60013194 (44:40) scatter
|
|
* plot, star plot, histogram, dendrogram, box plot, physical map, tree, 2d 3d isosurfaces table,
|
|
* half matrix, graph, hierarchical pie, line graph, numeric matrix, heat map, permutation matrix
|
|
* bar graph, radial graph, */
|