ClickableGroup Class Demo and Documentation

Display sketch code: ClickableGroupDemo.pde

The demo of ClickableGroup includes two ComboBoxes, a Button, a Menu and MenuBar, and a ScrollSketch. We will discuss it more later.

The ClickableGroup is designed to simplify the handling of a number of Clickable items in the mouseReleased() and draw() methods in the user's sketch. Typically all the Clickable items are made part of the ClickableGroup. This is strongly recommended because it greatly simplifies working with Clickable items.

Although there are numerous similarities, a ClickableGroup differs from a ButtonGroup in the following ways:
* It can include any Clickable item.
* It is not Clickable although items in it can be clicked.
* It does not have a selected item.

Important note: Before one creates a ClickableGroup, one creates an array of Clickable items. The code typically looks something like this:

// Create Clickable items:  item1, item2, item3, ...
...
// Create the array of Clickable items and then the ClickableGroup
Clickable[] clickArray = {item1, item2, item3, ...};
ClickableGroup clickGrp = new ClickableGroup(clickArray);

(This coding has to be changed if any of the Clickable items is created in the setup() method. For example, this will happen if one creates an array of buttons. See An Example With an Array of Clickables for a simple example.

When setting up the array of Clickable items, one must make sure that if one item could ever overlap another item, it must be listed after any item it might cover. This is rarely a problem unless the group contains any of the following:
* ComboBox
* Menu
* ScrollSketch
* A draggable item
When a ComboBox or a Menu drops its drop down list, it might cover some other Clickable item. A ScrollSketch scrollbar might cover hidden parts of the sketch. Items in ClickableGroup are drawn in the order listed in the array but checking for clicks is done in reverse order. Thus if items overlap, the last item drawn will be on the top and will get any click on it. Thus the following ordering is appropriate:
* A whole sketch ClickablePanel created with its third constructor (if used).
* other Clickable items
* ComboBoxes (with any box that might be covered by another, listed first)
* the menu bar (if used)
* Menus (These should never overlap so any order is OK)
* ScrollSketch
Because one ComboBox's pull down list may cover another ComboBox, their ordering is important. Typically one can list them in a bottom up order.

In the above example, the drop down menu can cover parts of both ComboBoxes and the Button. The upper ComboBox can cover parts of the second ComboBox and the Button, The second ComboBox can cover parts of the Button. Hence, the items are ordered in the array for the ClickableGroup:






  1. The button
  2. The lower combo box
  3. The upper combo box
  4. The menu bar
  5. The menu
  6. The ScrollSketch

class ClickableGroup

A ClickableGroup itself is not Clickable although the items in it are.

Fields

Clickable[] itemArray - The array of Clickable items in the group.
boolean clicked - True if some item in the group has been clicked.
int clickedItemNum - The number (subscript) of the last item clicked.
Clickable clickedItem - The last item clicked.
** ClickableGroup(Clickable[] anItemArray)
- Creates a group of Clickables that can be processed as group. It is very similar to a ButtonGroup except that it does not inherit from Clickable and there is no selected item. However, there is a clicked item.
** void display()
- Calling the ClickableGroup's display() will draw all the items in the group.
** boolean checkForClick()
- This method must be called* and can only be called in the user's mouseReleased() method (or a submethod). When a button is clicked, the method searches for the item that is under the mouse cursor in reverse order by using each item's checkForClick() method. (This order is used so it recognizes the item that is on top (most recently drawn).) It also assumes that every item's "isOver()" will be called to determine if the item was the clicked item. When the clicked item is discovered, it sets "clickedItemNum" and "clicked".
*Exception: After a drag, one should call dragger's endDrag() method instead.
** boolean hasBeenClicked()
- To check for clicks, this method must be called and can only be called in the user's draw() method or a submethod. Sets the "clicked" field for the ClickableGroup and the clicked item to false indicating that the item no longer needs processing.
** boolean isOver()
- isOver returns true if the cursor is over any member of the ClickableGroup. The clicked item is recorded in class fields. Searches entire group in reverse order. When it finds the item that the cursor is over, "stillSearching_" is set false which prevent items underneath the clicked item from thinking they have been clicked.
** int getClickedItemNum()
- getClickedItem returns the subscript of the group item that has been most recently clicked. If nothing has been clicked, it returns NONE_CLICKED.
** Clickable getClickedItem()
- Returns the most recently clicked item or null if none were clicked.
** String getClickedItemLabel()
- Returns the label of the most recently clicked item or "*" if nothing was clicked.
** int groupLength()
- Returns the number of items in the ClickableGroup.

Method use codes:

** This constructor or method is designed to be called in the user sketch.

* This method is normally not called in the user's sketch unless the Clickable item was not been included in a ClickableGroup. ClickableGroup automatically uses the method as needed. Exception: This method may be needed if the user is extending Clickable with a new class.

# This constructor or method is rarely used in the user program. In Java, it would probably marked "private". Clickable, ScrollBar, and some other abstract constructors would never be called directly by the user sketch because they do nothing useful unless the user is extending a class.

Return to the top of the page

Example code using a ClickableGroup

Assume that item0, item1, and item2 are Clickable items created as global fields. Then the ClickableGroup can be created as a global field.

Clickable[] clickArray = {item0, item1, item2};
ClickableGroup clickGrp = new ClickableGroup{clickArray};

But if any of the items is created in setup(), then the array and group must be created in setup() as well after they are created. See An Example With an Array of Clickables

The group's checkForClick() methods must be called in mouseReleased(). (The mouse released method is somewhat more complicated if any Draggable items are used.) It is often convenient to have draw() call a method like updateClickableItems() to process clicked items.

void mouseReleased() {
  clickGrp.checkForClick();
}  // mouseReleased

void draw() {
  ...
  updateClickableItems();  // updateClickableItems() can simplify draw() significantly
  ...
  clickGrp.display();
  ...
} // end of draw

There are a couple of ways to process actions associated with Clickable items. One way uses switch statement.

void updateClickableItems() {
  int itemNum;
   ...
  clickGrp.isOver();
  if (clickGrp.hasBeenClicked()) {
    itemNum = clickGrp.getClickedItemNum();
    switch (itemNum) {
      case 0:  // process item0
          ...       // You can use the item's names (e.g. item0) in the switch
          break;
      case 1:  // process item1
          ...
          break;
      case 2:  // process item2
          ...
          break;
    } // end of switch
  } // end of if
} // end of updateClickableItems

The difficulty with the first method is that if the items in the ClickableGroup change, the item numbers may change. Hence, an alternative to using the switch statement may be useful. Pay close attention to the setup() method.

void updateClickableItems() {
  Clickable item;
   ...
  clickGrp.isOver();
  if (clickGrp.hasBeenClicked()) {
    item = clickGrp.getClickedItem();
    if (item == item0) {
         ...
    } else if (item == item1) {
         ...
    }  ...
    ...
  }
} // end of updateClickableItems

Return to the top of the page

An Example With an Array of Clickables

If one wants to use an array of ClickableItems, the coding is a little different. The problem is that the array cannot completely defined in the global setup and needs to done in setup(). Elements cannot be added to the array of Clickables until they are created and the ClickableGroup cannot be created before the array is created. The above example has an array of buttons. Here is the code for the sketch.

int NUM = 3;
Button[] btnArray = new Button[NUM+1];
CircleButton circleBtn = new CircleButton(25, 135, 7, "Circle Button",
                              #DDDDDD, #BBBBBB, #DD00DD, #BB00BB);
Clickable[] clickArray = new Clickable[NUM+1];
ClickableGroup clickGrp;

String msg;

void setup() {
  size(300, 160);
  smooth();
  frameRate(10);
  int i;
  for (i = 0; i < NUM; i++) {
    btnArray[i] = new Button(20, 40 + 25*i, 70, 20, "Button " + i,
                              #DDDDDD, #BBBBBB, #DD00DD, #BB00BB);
    clickArray[i] = btnArray[i];
  }
  clickArray[NUM] = circleBtn;
  clickGrp = new ClickableGroup(clickArray);
  msg = "Click a button";
} // setup

void draw() {
  background(#FFFFAA);   // background color
  updateGrp();
  text("Array Demo", 120, 15);
  text(msg, 120, 100);
  clickGrp.display();
}  // draw

void updateGrp() {
  Clickable item;
  clickGrp.isOver();
  if (clickGrp.hasBeenClicked()) {
    item = clickGrp.getClickedItem();
    msg = "You clicked " + item.getLabel();
  }
} // updateGrp

void mouseReleased() {
  clickGrp.checkForClick();
}  // mouseReleased
There is a slight variation that is sometimes useful. The statement
Clickable[] clickArray = new Clickable[NUM+1];
could be replaced by
Clickable[] clickArray = {btnArray[0], btnArray[1], btnArray[2], circleBtn};
Then the statement
  clickArray[NUM] = circleBtn;
in setup() can be omitted as that assignment has already been made. However, because the btnArray elements are not created until they are in setup(), they only serve as place holders when declarring clickArray.

Return to the top of the page

Revised: 04/11/2014