This commit is contained in:
sojamo 2014-08-15 11:19:30 +08:00
parent b4ac76712b
commit e056913c43
15 changed files with 283 additions and 124 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
/bin/
/distribution/
/reference/
/test/
/src-js/
.svn/

165
README.md
View File

@ -1,13 +1,13 @@
# ControlP5
ControlP5 is a library written by Andreas Schlegel for the programming environment [processing](http://www.processing.org). ControlP5 is a GUI and controller library for processing that can be used in authoring, application mode.
ControlP5 is a library written by Andreas Schlegel for the programming environment [Processing](http://www.processing.org). ControlP5 is a GUI and controller library for processing that can be used in authoring, application mode.
The range of available controllers includes Slider, Button, Toggle, Knob, Textfield, RadioButton, Checkbox, Lists amongst others. These controllers can be easily added to a processing sketch, or displayed inside a separate control window. They can be organized in tabs or groups as well as rendered into PGraphics buffers. The state of a controller can be saved to file in JSON format.
## Getting Started
To get started, a simple example that will create a slider and automatically link its value to variable v1.
To get started, a simple example that demonstrates how to create a slider and automatically link its value to variable v1.
```java
@ -44,15 +44,167 @@ To get started, a simple example that will create a slider and automatically lin
```
## How does ControlP5 work?
ControlP5 provides a range of controllers, each controller comes with an example which is located inside the examples/controllers folder. This is a good place to get started with ControlP5.
### Instantiate ControlP5
To create an instance of ControlP5, you need to call ControlP5's constructor and pass a reference of your sketch as argument, in most cases this will happen inside setup() and the argument and the argument for the constructor call is _this_, the reference to the current sketch object.
```java
import controlP5.*;
ControlP5 cp5;
void setup() {
cp5 = new ControlP5(this);
}
```
Alternatively, ControlP5 can be instantiated from other places as well for example from another object. Here, just as before, you need to pass a sketch reference as argument when instantiating the ControlP5 object.
```java
import controlP5.*;
GUI gui;
void setup() {
gui = new GUI(this);
}
class GUI {
ControlP5 cp5;
GUI(ControlP5 theControlP5) {
cp5 = new ControlP5(theControlP5);
}
}
```
### Adding Controllers
To add controllers to a ControlP5 object, use the add function followed by the name of the Controller, for example to add a Slider use cp5.addSlider("mySlider"). Here function addSlider takes one argument which is the unique name of the controller to be added. In case a controller with the same name is already registered with ControlP5, the old controller will be overriden - this is then indicated and printed as a warning message in the console. All default add functions are implemented with class ControlP5Base; have a look at its source code for further reference.
```java
import controlP5.*;
ControlP5 cp5;
void setup() {
size(400,400);
cp5 = new ControlP5(this);
cp5.addSlider("mySlider");
cp5.addButton("myButton");
}
void draw() {}
```
The example above adds 2 controllers to your sketch and renders them on top of your sketch. To adjust the size, position, color, etc. ControlP5 uses [method chaining](http://en.wikipedia.org/wiki/Method_chaining) and [setter](http://en.wikipedia.org/wiki/Mutator_method) functions. For example setPosition(x,y) will change the position of a controller, setSize(width,height) will change the size of a controller; the naming convention is straight forward, a function does what it says, and the same goes for the other setters and getters as well. For further reference and overview, start with browsing the source code of class Controller and its implementations, furthermore have a look at the documentation.
```java
import controlP5.*;
ControlP5 cp5;
void setup() {
size(400,400);
cp5 = new ControlP5(this);
cp5.addSlider("mySlider").setPosition(20,20).setSize(200,20);
cp5.addButton("myButton").setPosition(20,60).setSize(100,40);
}
void draw() {}
```
### Accessing Controllers
### Event Handling
#### ControlEvent
#### Callbacks
#### Linking a variable or function to a Controller
#### Customised event handling
### Bring a Controller to the front
To change the order of controllers, use Controller.bringToFront() which will position the controller on top of all others. See example [ControlP5bringToFront](examples/use/ControlP5bringToFront/ControlP5bringToFront.pde)
### Grouping Controllers
#### Tab
#### Group
#### Window
### What do all these Controllers do?
- **Accordion** use an accordion to arrange multiple groups in vertical order
- **Bang** triggers an event on press without passing a value
- **Button** triggers an event and passes on a value
- **ButtonBar** a horizontal multi-button bar
- **Canvas**
- CheckBox
- ColorPicker
- ColorWheel
- **DropdownList** (use ScrollableList instead)
- Group
- **ListBox** (use ScrollableList instead)
- Knob
- Matrix
- Numberbox
- RadioButton
- Range
- **ScrollableList**
- **Slider** a number slider, can be horizontal or vertical
- Slider2D
- Spacer
- **Tab** arrange controllers inside a range of tabs
- **Textfield** a field for single line text input
- **Textarea** a multi line area for text output
- Textlabel
- **Toggle** switches between 2 states, true and false.
### What else is there?
- Chart
- FrameRate
- Pointer
- Println
### Rendering
#### Default rendering
##### Customised rendering
### Saving and loading states
### Removing Controllers
### Deprecated
#### My code worked before now it doesn't anymore
#### Tooltip, MultiList, DropdownList, ListBox
## History
ControlP5 is a project that started in 2006 as a very simple UI for controlling Processing parameters for better debugging, testing and interaction purposes. Starting from only 3 controllers its controller base has grown up to around 30 controllers and over 70 examples. A history of controlP5 versions is available at [google code downloads](https://code.google.com/p/controlp5/downloads/list?can=1&q=&colspec=Filename+Summary+Uploaded+ReleaseDate+Size+DownloadCount). This library has been widely used by processing user in academic, research and professional environments for prototyping and tool development.
ControlP5 is a project that started in 2006 as a very simple UI for controlling Processing parameters for better debugging, testing and interaction purposes. Starting from only 3 controllers its controller base has grown up to around 30 controllers and over 70 examples. A history of controlP5 versions is available on [google code downloads](https://code.google.com/p/controlp5/downloads/list?can=1&q=&colspec=Filename+Summary+Uploaded+ReleaseDate+Size+DownloadCount). This library has been widely used by processing user in academic, research and professional environments for prototyping and tool development.
### Why is controlP5's source code so convoluted and bloated
### Why is controlP5's source code so convoluted and bloated
ControlP5 has been in development for over 9 years and started as a small GUI library for Processing. Over the years both Processing and ControlP5 have grown substantially and as part of that journey many changes have been applied to both. From a ControlP5 perspective some changes were due to changes made to Processing's API and source code, other changes were due to additional controller implementations, extended functionality, user feedback and reuqests. Since writing controlP5 from scratch was a learning process for myself in itself, a proper initial strategy for the software architecture of the library was missing. When it became apparent that a proper architecture would have made the development much easier and comfortable it was already too late, I had to comply to the piles of code I had created. Would I do things differently now? yes I would.
ControlP5 has been in development for over 9 years and started as a small GUI library for Processing. Over the years both Processing and ControlP5 have grown substantially and as part of that journey many changes have been applied to both. From a ControlP5 perspective some changes were due to changes made to Processing's API and source code, other changes were due to additional controller implementations, extended functionality, user feedback and reuqests. Since writing controlP5 from scratch was a learning process for myself in itself, a proper initial strategy for the software architecture of the library was missing. When it became apparent that a proper architecture would have made the development much easier and comfortable it was already too late, I had to comply to the piles of code I had created. Would I do things differently now? yes I would.
## Font rendering
@ -63,5 +215,4 @@ Why is the bit-font so blurry? it used to be crisp. Let me blame this on the Ope
## Javascript
Currently there is no javascript version of ControlP5, though I had started implementing a slimmed down version for processing.js but since it is currently unclear which javascript version - processing.js or p5.js - will become the default js version of processing, controlP5.js is on hold. There is a tendency that p5.js will become the primary javascript environment
Currently there is no javascript version of ControlP5, though I had started implementing a slimmed down version for processing.js but since it is currently unclear which javascript version - processing.js or p5.js - will become the default js version of processing, controlP5.js is on hold. There is a tendency that p5.js will become the primary javascript environment

View File

@ -55,7 +55,6 @@ void setup() {
;
customize(d2); // customize the second list
d2.setIndex(10);
}
@ -65,9 +64,6 @@ void customize(DropdownList ddl) {
ddl.setItemHeight(20);
ddl.setBarHeight(15);
ddl.getCaptionLabel().set("dropdown");
ddl.getCaptionLabel().style().marginTop = 3;
ddl.getCaptionLabel().style().marginLeft = 3;
ddl.getValueLabel().style().marginTop = 3;
for (int i=0;i<40;i++) {
ddl.addItem("item "+i, i);
}

View File

@ -59,12 +59,9 @@ void setup() {
l.getCaptionLabel().toUpperCase(true);
l.getCaptionLabel().set("A Listbox");
l.getCaptionLabel().setColor(0xffff0000);
l.getCaptionLabel().style().marginTop = 3;
l.getValueLabel().style().marginTop = 3;
for (int i=0;i<80;i++) {
ListBoxItem lbi = l.addItem("item "+i, i);
lbi.setColorBackground(0xffff0000);
l.addItem("item "+i, i);
l.getItem("item "+i).put("color", new CColor().setBackground(0xffff0000).setBackground(0xffff8800));
}
}

View File

@ -17,14 +17,14 @@ ControlP5 cp5;
int myColorBackground = color(0,0,0);
RadioButton r;
RadioButton r1, r2;
void setup() {
size(700,400);
cp5 = new ControlP5(this);
r = cp5.addRadioButton("radioButton")
.setPosition(20,160)
r1 = cp5.addRadioButton("radioButton")
.setPosition(100,180)
.setSize(40,20)
.setColorForeground(color(120))
.setColorActive(color(255))
@ -38,13 +38,14 @@ void setup() {
.addItem("250",5)
;
for(Toggle t:r.getItems()) {
for(Toggle t:r1.getItems()) {
t.getCaptionLabel().setColorBackground(color(255,80));
t.getCaptionLabel().style().moveMargin(-7,0,0,-3);
t.getCaptionLabel().style().movePadding(7,0,0,3);
t.getCaptionLabel().style().backgroundWidth = 45;
t.getCaptionLabel().style().backgroundHeight = 13;
t.getCaptionLabel().getStyle().moveMargin(-7,0,0,-3);
t.getCaptionLabel().getStyle().movePadding(7,0,0,3);
t.getCaptionLabel().getStyle().backgroundWidth = 45;
t.getCaptionLabel().getStyle().backgroundHeight = 13;
}
}
@ -55,18 +56,18 @@ void draw() {
void keyPressed() {
switch(key) {
case('0'): r.deactivateAll(); break;
case('1'): r.activate(0); break;
case('2'): r.activate(1); break;
case('3'): r.activate(2); break;
case('4'): r.activate(3); break;
case('5'): r.activate(4); break;
case('0'): r1.deactivateAll(); break;
case('1'): r1.activate(0); break;
case('2'): r1.activate(1); break;
case('3'): r1.activate(2); break;
case('4'): r1.activate(3); break;
case('5'): r1.activate(4); break;
}
}
void controlEvent(ControlEvent theEvent) {
if(theEvent.isFrom(r)) {
if(theEvent.isFrom(r1)) {
print("got an event from "+theEvent.getName()+"\t");
for(int i=0;i<theEvent.getGroup().getArrayValue().length;i++) {
print(int(theEvent.getGroup().getArrayValue()[i]));

View File

@ -0,0 +1,55 @@
import controlP5.*;
ControlP5 cp5;
void setup() {
size(700, 400);
cp5 = new ControlP5(this);
CallbackListener toFront = new CallbackListener() {
public void controlEvent(CallbackEvent theEvent) {
theEvent.getController().bringToFront();
((ScrollableList)theEvent.getController()).open();
}
};
CallbackListener close = new CallbackListener() {
public void controlEvent(CallbackEvent theEvent) {
((ScrollableList)theEvent.getController()).close();
}
};
cp5.addScrollableList("myList1")
.setPosition(100, 100)
.addItems(new String[] {"a-1","b-1","c-1","d-1","e-1"})
.onEnter(toFront)
.onLeave(close)
.setWidth(200)
.setItemHeight(20)
.setBarHeight(20)
.setBackgroundColor(color(128))
.setHeight(100)
.close()
;
cp5.addScrollableList("myList2")
.setPosition(100, 125)
.addItems(new String[] {"a-2","b-2","c-2","d-2","e-2"})
.onEnter(toFront)
.onLeave(close)
.setWidth(200)
.setItemHeight(20)
.setBarHeight(20)
.setBackgroundColor(color(128))
.setHeight(100)
.setColor(ControlP5.THEME_RED)
.close()
;
}
void draw() {
background(220);
}

View File

@ -15,15 +15,15 @@
<property name="author" value="Andreas Schlegel"/>
<property name="copyright" value="(c) 2006-2014"/>
<property name="libraryName" value="controlP5"/>
<property name="versionNumber" value="2.2.1"/>
<property name="versionNumber" value="2.2.2"/>
<property name="yourLink" value="http://www.sojamo.de" />
<property name="keywords" value="gui, ui, controller, interface, user interface" />
<property name="tested:platform" value="osx, windows, linux" />
<property name="tested:processingVersion" value="2.0" />
<property name="tested:processingVersion" value="2.2.1" />
<property name="tested:dependencies" value="none" />
<property name="source:host" value="google code" />
<property name="source:url" value="http://code.google.com/p/controlp5" />
<property name="source:repository" value="http://code.google.com/p/controlp5/source/browse/" />
<property name="source:host" value="github" />
<property name="source:url" value="https://github.com/sojamo/controlp5" />
<property name="source:repository" value="https://github.com/sojamo/controlp5/tree/master/src" />

View File

@ -0,0 +1,4 @@
for d in $HOME/Documents/workspace/controlp5/examples/use/*/; do
echo "$d"
processing-java --sketch="$d" --output=/tmp/processing-test --force --build
done

View File

@ -35,6 +35,7 @@ package controlP5;
*/
@SuppressWarnings( "rawtypes" ) public class Accordion extends ControlGroup< Accordion > {
protected int spacing = 1;
protected int minHeight = 100;
protected int itemheight;

View File

@ -72,12 +72,10 @@ public class Button extends Controller< Button > {
}
@Override protected void onEnter( ) {
System.out.println("enter button "+this.getName( )+" "+x(getPosition( ))+" "+y(getPosition( ))+" | "+" "+x(getAbsolutePosition( ))+" "+y(getAbsolutePosition( )));
isActive = true;
}
@Override protected void onLeave( ) {
System.out.println("leave button "+this.getName( )+" "+x(getPosition( ))+" "+y(getPosition( ))+" | "+" "+x(getAbsolutePosition( ))+" "+y(getAbsolutePosition( )));
isActive = false;
setIsInside( false ); // TODO setIsInside needs to be set false here if we remove setIsInside from activate; see below.
}

View File

@ -1344,6 +1344,7 @@ public abstract class Controller< T > implements ControllerInterface< T > , CDra
return me;
}
/**
* @param theValue float
*/

View File

@ -38,9 +38,9 @@ import processing.event.KeyEvent;
*/
public abstract class ControllerGroup< T > implements ControllerInterface< T > , ControlP5Constants , ControlListener {
protected float[] position = new float[2];
protected float[] positionBuffer = new float[2];
protected float[] absolutePosition = new float[2];
protected float[] position = new float[ 2 ];
protected float[] positionBuffer = new float[ 2 ];
protected float[] absolutePosition = new float[ 2 ];
protected ControllerList controllers;
protected List< ControlListener > _myControlListener;
// protected ControlWindow _myControlWindow;

View File

@ -13,7 +13,7 @@ public class Spacer extends Controller< Spacer > {
protected Spacer( ControlP5 theControlP5 , ControllerGroup< ? > theParent , String theName , float theX , float theY , int theWidth , int theHeight ) {
super( theControlP5 , theParent , theName , theX , theY , theWidth , theHeight );
_myControllerView = new SeparatorView( );
_myControllerView = new SpacerView( );
}
public Spacer setWeight( int theWeight ) {
@ -26,7 +26,7 @@ public class Spacer extends Controller< Spacer > {
return this;
}
private class SeparatorView implements ControllerView< Spacer > {
private class SpacerView implements ControllerView< Spacer > {
public void display( PGraphics g , Spacer c ) {
g.fill( c.getColor( ).getForeground( ) );

View File

@ -9,6 +9,7 @@ import java.util.Map;
import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PGraphics;
import processing.event.Event;
import processing.event.KeyEvent;
/**
@ -63,13 +64,13 @@ public class Textfield extends Controller< Textfield > {
protected List< Integer > ignorelist;
protected LinkedList< String > _myHistory;
protected int _myHistoryIndex;
protected boolean changed;
protected int len = 0;
protected int offset = 2;
protected int margin = 2;
protected boolean isPasswordMode;
protected boolean autoclear = true;
protected int _myColorCursor = 0x88ffffff;
private PGraphics buffer;
public enum InputFilter {
INTEGER(Arrays.asList( '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' )), FLOAT(Arrays.asList( '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '.' )), BITFONT(Arrays.asList( '\n' , '\r' , ' ' , '!' , '"' , '#' , '$' , '%' ,
@ -107,10 +108,9 @@ public class Textfield extends Controller< Textfield > {
public Textfield( ControlP5 theControlP5 , ControllerGroup< ? > theParent , String theName , String theDefaultValue , int theX , int theY , int theWidth , int theHeight ) {
super( theControlP5 , theParent , theName , theX , theY , theWidth , theHeight );
_myCaptionLabel = new Label( cp5 , theName.toUpperCase( ) , 0 , 0 , color.getCaptionLabel( ) );
_myValueLabel.setFont( cp5.controlFont == cp5.defaultFont ? cp5.defaultFontForText : cp5.controlFont );
_myCaptionLabel.align( ControlP5.LEFT , ControlP5.BOTTOM_OUTSIDE );
_myCaptionLabel.setPaddingX( 0 );
@ -128,6 +128,8 @@ public class Textfield extends Controller< Textfield > {
_myHistory = new LinkedList< String >( );
_myHistory.addFirst( "" );
setSize( getWidth( ) , getHeight( ) );
keyMapping = new HashMap< Integer , TextfieldCommand >( );
keyMapping.put( ENTER , new Enter( ) );
keyMapping.put( DEFAULT , new InsertCharacter( ) );
@ -146,7 +148,6 @@ public class Textfield extends Controller< Textfield > {
ignorelist.add( COMMANDKEY );
setInputFilter( DEFAULT );
changed = true;
}
@ -162,7 +163,6 @@ public class Textfield extends Controller< Textfield > {
public Textfield setFocus( boolean theValue ) {
isTexfieldActive = isActive = theValue;
changed = true;
return this;
}
@ -228,13 +228,11 @@ public class Textfield extends Controller< Textfield > {
@Override protected void updateFont( ControlFont theControlFont ) {
super.updateFont( theControlFont );
changed = true;
}
public Textfield setValue( String theText ) {
_myTextBuffer = new StringBuffer( theText );
setIndex( _myTextBuffer.length( ) );
changed = true;
return this;
}
@ -294,11 +292,14 @@ public class Textfield extends Controller< Textfield > {
return this;
}
@Override public Textfield setSize( int theWidth , int theHeight ) {
super.setSize( theWidth , theHeight );
buffer = cp5.papplet.createGraphics( getWidth( ) , getHeight( ) );
return this;
}
@Override public void draw( PGraphics theGraphics ) {
if ( changed ) {
updateLabel( theGraphics );
changed = false;
}
theGraphics.pushStyle( );
theGraphics.fill( color.getBackground( ) );
theGraphics.pushMatrix( );
@ -310,23 +311,20 @@ public class Textfield extends Controller< Textfield > {
theGraphics.pushMatrix( );
theGraphics.pushStyle( );
if ( _myTextBufferIndexPosition > len - offset ) {
// theApplet.textAlign(PApplet.RIGHT);
_myValueLabel.textAlign = PApplet.RIGHT;
theGraphics.translate( getWidth( ) - margin , 0 );
if ( isTexfieldActive ) {
theGraphics.rect( 0 , 0 , cursorWidth , getHeight( ) );
}
} else {
// theApplet.textAlign(PApplet.LEFT);
_myValueLabel.textAlign = PApplet.LEFT;
theGraphics.translate( margin , 0 );
if ( isTexfieldActive ) {
theGraphics.rect( PApplet.max( 0 , PApplet.min( _myTextBufferIndexPosition , getWidth( ) - margin ) ) , 0 , cursorWidth , getHeight( ) );
}
}
buffer.beginDraw( );
buffer.background( 0 , 0 );
final String text = passCheck( getText( ) );
final int textWidth = ControlFont.getWidthFor( text.substring( 0 , _myTextBufferIndex ) , _myValueLabel , buffer );
final int dif = PApplet.max( textWidth - _myValueLabel.getWidth( ) , 0 );
final int _myTextBufferIndexPosition = ControlFont.getWidthFor( text.substring( 0 , _myTextBufferIndex ) , _myValueLabel , buffer );
_myValueLabel.setText( text );
_myValueLabel.draw( buffer , -dif , 0 , this );
buffer.noStroke( );
buffer.fill( _myColorCursor );
buffer.rect( PApplet.max( 1 , PApplet.min( _myTextBufferIndexPosition , _myValueLabel.getWidth( ) - 3 ) ) , 0 , 1 , getHeight( ) );
buffer.endDraw( );
theGraphics.image( buffer , 0 , 0 );
_myValueLabel.draw( theGraphics , 0 , 0 , this );
theGraphics.popStyle( );
theGraphics.popMatrix( );
@ -340,56 +338,6 @@ public class Textfield extends Controller< Textfield > {
theGraphics.popStyle( );
}
private void updateLabel( PGraphics theApplet ) {
if ( _myInputFilter == InputFilter.BITFONT ) {
setInputFilter( DEFAULT );
}
String str = passCheck( getText( ) );
String t1 = str;
int off = margin * 2;
int ww = ControlFont.getWidthFor( str , _myValueLabel , theApplet );
if ( ( ww < getWidth( ) - off ) ) {
_myTextBufferIndexPosition = ControlFont.getWidthFor( t1.substring( 0 , _myTextBufferIndex ) , _myValueLabel , theApplet );
len = getWidth( );
} else {
char[] c = str.toCharArray( );
int mx = 0;
int n = 0;
for ( int i = 0 ; i < c.length ; i++ ) {
n += theApplet.textWidth( c[ i ] );
if ( n > _myValueLabel.getWidth( ) - off ) {
break;
}
len = n;
mx++;
}
t1 = "";
n = 0;
// this is messed up and occasionally throws ArrayIndexOutOfBounds Exceptions
// sometimes the beginning of the text is not in order when text length exceeds
// length of textfield.
// needs fixing. TODO
for ( int i = PApplet.max( mx , _myTextBufferIndex - 1 ) ; i >= 0 ; i-- ) {
try {
n += theApplet.textWidth( c[ i ] );
} catch ( Exception e ) {}
try {
t1 = c[ i ] + t1;
if ( n >= _myValueLabel.getWidth( ) - off - 4 ) {
_myTextBufferOverflow = str.indexOf( t1 );
break;
}
} catch(java.lang.ArrayIndexOutOfBoundsException ex) {
//System.out.println("java.lang.ArrayIndexOutOfBoundsException");
}
}
int strn = PApplet.max( 0 , PApplet.min( t1.length( ) , _myTextBufferIndex - _myTextBufferOverflow ) );
_myTextBufferIndexPosition = ControlFont.getWidthFor( t1.substring( 0 , strn ) , _myValueLabel , theApplet );
}
_myValueLabel.setText( t1 );
changed = false;
}
private String passCheck( String label ) {
if ( !isPasswordMode ) {
return label;
@ -431,12 +379,10 @@ public class Textfield extends Controller< Textfield > {
private Textfield setIndex( int theIndex ) {
_myTextBufferIndex = theIndex;
changed = true;
return this;
}
interface TextfieldCommand {
void execute( );
}
@ -484,14 +430,14 @@ public class Textfield extends Controller< Textfield > {
class MoveLeft implements TextfieldCommand {
public void execute( ) {
setIndex( ( cp5.isMetaDown( ) ) ? 0 : PApplet.max( 0 , _myTextBufferIndex - 1 ) );
setIndex( ( ( cp5.modifiers & Event.META ) > 0 ) ? 0 : PApplet.max( 0 , _myTextBufferIndex - 1 ) );
}
}
class MoveRight implements TextfieldCommand {
public void execute( ) {
setIndex( ( cp5.isMetaDown( ) ) ? _myTextBuffer.length( ) : PApplet.min( _myTextBuffer.length( ) , _myTextBufferIndex + 1 ) );
setIndex( ( ( cp5.modifiers & Event.META ) > 0 ) ? _myTextBuffer.length( ) : PApplet.min( _myTextBuffer.length( ) , _myTextBufferIndex + 1 ) );
}
}

View File

@ -1,3 +1,11 @@
2014-07-21 Andreas Schlegel <andi at sojamo.de>
* src controlP5.Textfield:
making use of a graphics buffer now, simplifies cursor position calculation and
prevents from throwing an ArrayIndexOutOfBoundsException which could occasionally
happen with previous versions.
2014-07-17 Andreas Schlegel <andi at sojamo.de>
* version 2.2.1