Controller 001 alpha : Advanced features

The getValueIsAdjusting() method

For components such as sliders, arcballs and spinners, it's possible to know when they are adjusting (when a user is interacting with them), as in the following example:

Controller controller;

void setup()
{
  size(200, 200);
  framerate(25);

  lights();
  noStroke();

  controller = new Controller(this, "arcballs: 1");
}

void loop()
{
  background(102);

  translate(width / 2, height / 2);

  float[] aa = controller.arcball.getValue();
  rotate(aa[0], aa[1], aa[2], aa[3]);

  if (controller.arcball.getValueIsAdjusting())
  {
    fill(0, 255, 0);
  }
  else
  {
    fill(255, 0, 0);
  }

  box(85);
}

launch example

The rotation of a cube is controlled by an arcball. While the arcball is being adjusted, the color of the cube is different.

An alternative way of implementing this is to use events: adjustable components are generating events (with the following messages: ADJUSTING or ADJUSTED) corresponding respectivelly to the beginning and the end of an interaction.

The getIndex() and getGroup() methods

Some of the components are coming in group (horizontal sliders, vertical sliders, spinners, toggle buttons). When handling events, it can be useful to determine from which group and with which index inside that group the generating component is, as in the following example:

Controller controller;
BFont font;
int b;

void setup()
{
  size(200, 200);
  framerate(25);
  background(0);
  fill(255, 160, 0);

  font = loadFont("OCR-B.vlw.gz");
  textFont(font, 128);
  textMode(ALIGN_CENTER);

  controller = new Controller(this, "togglebuttons: 8");
  controller.togglebuttons.get(0).setSelected(true);
  for (int i = 0; i < 8; i++)
  {
    controller.togglebuttons.get(i).setLegend(String.valueOf(1 << i));
  }
}

void loop()
{
  background(0);
  text(nf(b, 3), width / 2, height / 2 + 36);
}

void controllerUpdated(ControllerEvent e)
{
  if (e.getSource().getGroup() == controller.togglebuttons)
  {
    if (e.getMessage() == "SELECTED")
    {
      b |= 1 << e.getSource().getIndex();
    }
    else if (e.getMessage() == "DESELECTED")
    {
      b &= ~(1 << e.getSource().getIndex());
    }
  }
}

launch example

The binary combined state of 8 toggle buttons is producing a number between 0 and 255. When one of the button is generating an event, the getGroup() method is determining from which group it is, and the getIndex() method is returning the index of the button within that group (sorted from top-to-bottom).

The Java classes behind the components

Here are the classes used by each type of component (they all extend the XComponent class):

Sliders (horizontal & vertical)XSlider
ArcballXArcball
SpinnersXSpinner
Toggle ButtonsXToggleButton

This information can be useful when "casting" is required, as in the following:

Controller controller;
BFont font;
int n1, n2;

void setup()
{
  size(200, 200);
  framerate(25);

  font = loadFont("OCR-B.vlw.gz");
  textFont(font, 128);
  textMode(ALIGN_CENTER);
  
  controller = new Controller(this, "hsliders: 4; vsliders: 4");
}

void loop()
{
  background(32, 0, 127);

  fill(160, 160, 0);
  text(nf(n1, 3), width / 2, 88);

  rect(0, height / 2, width, height / 2);
  fill(32, 0, 127);
  text(nf(n2, 3), width / 2, 188);
}

void controllerUpdated(ControllerEvent e)
{
  if (e.getMessage() == "VALUE")
  {
    XSlider source = (XSlider) e.getSource();

    if (e.getSource().getGroup() == controller.hsliders)
    {
      n1 = (int) round(source.getValue() * 100);  // when converting floats to ints, it's better to do rounding before
    }
    else if (e.getSource().getGroup() == controller.vsliders)
    {
      n2 = (int) round(source.getValue() * 100);
    }
  }
}

launch example

Two numbers are displayed on screen. The number at the top is controlled by 4 horizontal sliders (the last slider adjusted is setting the value of the displayed number). The same logic is applied to the number at the bottom which is controlled by 4 vertical sliders.

At some point, we use getSource() to retrieve which component is responsible for the current event, but what we get is considered by Java as an instance of XComponent. It is therefore necessary to "cast" to XSlider in order to be able to invoke the getValue() method (which is not a member of XComponent, but of XSlider) later on.

See the Component reference for a summary of all the methods of the different component classes.

top  |  home  |  bagel papa poule : tookit