An Introduction To Programming With Processing

Returning data from a function

Every function declared in a sketch that does not use void, must return data matching the type that the function has been datatyped as. In our example the user defined function we are creating has been datatyped as a boolean and as a result we need a means of returning boolean data back to the program in a useful way. This boolean value that is returned back to the program, is what we will use in our main program to let us know that when the value returned from the function is true that the mouse is over the button and when the value is returned as false we can safely conclude from this information that the mouse is not hovering over the button. First we are going to declare another variable in the global scope and datatype it as a boolean, add the following global variable to your sketch:
boolean mouseOverButton; 
Now we'll use this variable in our user defined function to return a boolean back to the main program.
boolean overButton(){
  if (mouseX >= buttonXPos && mouseX <= buttonXPos +  sliderFd.width && mouseY >= margin && mouseY <= margin +   sliderFd.height){
         mouseOverButton = true;
         cursor(HAND);
         //Returns true back to main program
         return mouseOverButton;
     }else{
       mouseOverButton = false;
       cursor(ARROW);
       //Returns false back to main program
       return mouseOverButton;
     }
}  
Returning data back to the main program is actually really easy and is simply a means of using the return keyword followed by the data you want to return which must match the same type as that of the function. Basically, our function is checking in the conditional if the mouse is within the range defined therein, if it is then it sets the mouseOverButton variable which has been declared in global space and datatyped as boolean to true with a simple assignment statement. We then use the cursor() function to change the mouse icon from the default ARROW to a HAND. This function also accepts parameters CROSS, MOVE, TEXT, WAIT and can also accept a PImage as a parameter. Now when the cursor is over the slider button it will change to a hand icon, giving the user a visual clue that they are hovering over a clickable element. If we where to leave the function at this point and not add an else structure, Processing would give us an error when trying to compile this sketch. This is because every user defined function must return data of it's specific type, meaning that in our case when the mouse is not over the slider button and we did not have an else structure capturing this possibility at that point our function would not be returning any data back to the main program. This is why it is important that we add an else structure to this if() structure, so that we can set the mouseOverButton variable to false, and subsequently return the correct data back to the main program. This also gives us an opportunity to change the cursor back to an arrow, indicating to the user that their mouse is no longer over a clickable element.

Our function declaration and definition is now complete and we can use it in our main program. Calls to user defined functions are as easy as calls to Processing's API functions. Add the following statement to the draw() structure.
overButton();
Now Processing will run the function at every frame and set the mouseOverButton variable within the overButton() function to true or false appropriately, update the cursor and return the correct value datatyped back to our main program, which we will soon put to use.

Dragging the slider button

mouseDragged() is a built-in Processing function that provides a structure to which we can add statements each time the mouse is dragged. A dragging operation qualifies as a user clicking and dragging a mouse button anywhere in the Display Window, when this happens the mouseDragged() function will be called once, and it's structure will be executed. As a result because the mouseDragged() function is not called repeatedly for each frame that the mouse is being dragged, we will use the mouseDragged() function to set a variable called buttonDrag to true indicating that the mouse is currently being dragged, this variable will then be used in the draw() structure, within an if() statement which causes the slider button to follow the mouse when the buttonDrag variable is true and remain stationary when it is false. When the user releases the mouse we will use a call to the mouseReleased() built-in Processing function (which structurally works in a similar way to the mouseDragged() function) to set the variable, buttonDrag to false within the mouseReleased() structure. What this means is that when the if() statement in draw() checks the status of this variable it will now be returned as false causing the slider button to remain stationary. In other words, we already have a function that tells us if the mouse is over the button or not, we will now add two more functions that will tell us whether the user's mouse is attempting to drag the button and whether it has been released. Mouse related functions usually follow the end of the draw() structure and should not be mixed amongst user defined functions. We'll start by declaring the buttonDrag boolean in global space:

boolean buttonDrag;
We will then use the buttonDrag variable within a mouseDragged() function. remember to place all mouse related functions together and not between user defined functions:
void mouseDragged(){
  if (mouseOverButton){
    buttonDrag = true;
  }
}
This simple function is run once the user clicks a mouse button and starts to drag, then the function will check if the mouse is over the slider button as mouseOverButton is returned to our main program via our overButton() user defined function. If the mouse is over the slider button and the user has clicked and dragged in the Display Window, then we can safely conclude that the user is trying to click and drag the slider button. As a result we set the buttonDrag variable to true. Now we can use this variable in our main program to update the position of the button slider in the draw() structure. Firstly we will start by commenting out the following statement as it is no longer needed for testing, as we are ready to implement the actual code:
//buttonXPos = width/2 – sliderBk.width/2;
The following statement will replace it:
if(buttonDrag){
    buttonXPos = mouseX - sliderFd.width/2;
  }
This if() statement will form the basis of the program's control flow used to control the movement of the slider button. If you were to run the script at this stage you might notice that although you can now click and drag the button, there are a few new issues that need tending to:
  • 1. The slider button now starts at the 0 X position, and subsequently needs to be constrained to the region that the sliderBd object covers.
  • 2. When the button is dragged it can be dragged well beyond the sliderBd region, so this operation also requires constraints.
  • 3. Once the button is released it continues to follow the mouse.