Exclusive (Single/Radio Option) Toggle Button Class. How to reset to the old color & the old labels?

edited November 2013 in Questions about Code

UPDATED: November 4, 2013

Hi Everyone,

I working on a code for an Exclusive Toggle Button class ( ExclusiveToggleButton). Using this class you can create a set of buttons from which only one can be selected at any given time. The basic code seems to work fine except a couple of issues that i can not resolve.

I kindly ask you to help me with two issues:

  1. .resetOneLbl() and resetLbls() does not work properly. I would like to be able to go back and reset to the original label. (NOT SOLVED, function .resetOneLbl() does not work unless the btn2 is toggled, resetLbls()does not work at all.)

  2. .resetClr() does not work properly. It does not reset to the color that was initially specified in the class; you have to put the specific color inside the function void resetClr(){... for it to work. Do you think there could be the other way? (I believe it is SOLVED, thanks to @Chrisir)

  3. Any suggestions regarding the further tweaks & improvements of the code are very much welcome.

Note, it is important that the code runs smoothly both in Java and in JavaScript modes (any web browser).

Here is the ExclusiveToggleButton class code with some button examples:

/**
 * ExclusiveToggleButton Class (v2.03)
 * by  inarts (2013/Oct)
 *
 * forum.processing.org/two/discussion/928/
 */

ExclusiveToggleButton btn1;
ExclusiveToggleButton btn2;

String btn1Lbl = "Option"; 
String btn1LblN = "Font Size"; 
int btn1Num = 6; 
String[] btn1Lbls  = new String[btn1Num]  ; 
String[] btn1LblsN = new String[btn1Num]  ; 
String[] btn2Lbls = new String[] {
  "OLD: Labels & Colors", "NEW: Labels & Colors"
};

int bW= 80;
int bH = 30; 
int bX = 20; 
int bY = 15;
int sY = 100; 
int sX = 10; 
color[] c = {
  #CFF09E, #A8DBA8, #79BD9A, #3B8686, #0B486B, #53777A, #09263D
};
color nBgClr = c[4];
color nFgClr = c[0];
color sBgClr = c[3]; 
color sFgClr = c[2];

void setup()
{
  size(640, 768);         
  background(0xFF809070);
  for (int i = 0; i < btn1Num; i++) {
    btn1Lbls[i] = btn1Lbl + " " + (i+1);
  };
  for (int i = 0; i < btn1Num; i++) {
    btn1LblsN[i] = btn1LblN + " " + (i+1);
  };
  btn1 = new ExclusiveToggleButton(btn1Lbls, bX, bY, bW, bH, sX);
  btn2 = new ExclusiveToggleButton(btn2Lbls, bX, bY+sY, 3*bW, bH, sX*3);
}
void draw() {
  drawColorBg();
  drawNumbers(); 
  drawButtons();
}

void mousePressed() {
  btn1.onMouse();
  btn2.onMouse();
}

void drawColorBg() {
  if (btn2.selected==0) {
    background(c[5]);
    btn1.resetClr();
    btn2.resetClr();
//    btn1.resetLbls();
  }
  else if (btn2.selected==1) {
    background(c[6]);
    btn1.changeLbls(btn1LblsN);
    btn1.changeSelectClr(sBgClr, sFgClr);
    btn1.changeNormClr(nBgClr, nFgClr);
    btn2.changeSelectClr(sBgClr, sFgClr);
    btn2.changeNormClr(nBgClr, nFgClr);
  }
  else {
    background(c[5]);
  }
}
void drawButtons() {
  btn1.render(); 
  btn2.render();
}

void drawNumbers() {
  for (int i = 0; i <btn1Lbls.length ; i++) {
    if (btn1.selected!=i) {
      btn1.resetOneLbl(i);
    }
    if (btn1.selected==i) {
      pushStyle(); 
      fill(200); 
      textSize(30*(i+1));
      textAlign(CENTER, CENTER);  
      text(i+1, width/2, height/2);
      btn1.changeOneLbl(i, "GOT "+i);
      popStyle();
    }
  }
} 



class ExclusiveToggleButton
{
  String[] lbls;
  String[] lblsO; 
  int x0, y0, dx, dy;
  int sX; 
  int selected; 
  color nBgC   = color(170);
  color nTxtC   = color(30);
  color sBgC = color(30); 
  color sTxtC = color(255);
  color nBgCO;
  color nTxtCO;
  color sBgCO; 
  color sTxtCO;

  ExclusiveToggleButton(String[] lbls, int x0, int y0, int dx, int dy, int sX) {
    this.lbls        = lbls;
    this.lblsO       = lbls; 
    this.sX          = sX; 
    this.x0          = x0; 
    this.y0          = y0; 
    this.dx          = dx; 
    this.dy          = dy;
    this.nBgCO       = nBgC;
    this.nTxtCO      = nTxtC;
    this.sBgCO       = sBgC; 
    this.sTxtCO      = sTxtC;
    selected         = 100;
  }

  void render() {
    pushStyle(); 
    textSize(12);
    textAlign(CENTER, CENTER);
    stroke(0);
    strokeWeight(1);
    for (int i = 0; i < lbls.length; i++) {
      if (i==selected) {
        fill(sBgC);
        rect(x0 + i*(dx+sX), y0, dx, dy);
        fill(sTxtC);
        text(lbls[i], x0 + i*(dx+sX) + dx/2, y0 + dy/2);
      } 
      else {
        fill(nBgC);
        rect(x0 + i*(dx+sX), y0, dx, dy);
        fill(nTxtC);
        text(lbls[i], x0 + i*(dx+sX) + dx/2, y0 + dy/2);
      }
    }
   popStyle(); 
  }

//  void resetLbls() {
//    this.lbls =  lblsO;
//  }

  void changeLbls(String[] newLbls) {
    this.lbls = newLbls;
  }

  void changeOneLbl(int idx, String newLbl) {
    this.lbls[idx] = newLbl;
  }

  void changeSelectClr(color sBgC, color sTxtC) {
    this.sBgC   = sBgC;
    this.sTxtC  = sTxtC;
  }
  void changeNormClr(color nBgC, color nTxtC) {
    this.nBgC   = nBgC;
    this.nTxtC  = nTxtC;
  }


  void resetClr() {
    this.sBgC   = sBgCO;
    this.sTxtC  = sTxtCO;
    this.nBgC   = nBgCO;
    this.nTxtC  = nTxtCO;
  }

  void resetOneLbl(int idx) {
    this.lbls[idx] = lblsO[idx];
  }

  void onMouse() {
    int indexOver = getIndexOver(mouseX, mouseY);
    if (indexOver < 0) return;
    selected = indexOver;
    redraw();
  }
  int getIndexOver(int px, int py) {
    for (int i = 0; i < lbls.length; i++) {
      int x1 = x0 + i*(dx+sX);
      if (px < x1) continue;
      if (py < y0) continue;
      if (px - x1 > dx) continue;
      if (py - y0 > dy) continue;
      return i;
    }
    return -1;
  }
}

Answers

  • Answer ✓

    (2)

    just make some vars oldColors.... in the class and in the constructor copy them into oldColors.... - and then you can retrieve them freely later

    (1)

    for the original lable you can go the same way

  • edited November 2013

    I guess it makes more sense to have a regular Button class.
    Then create a wrapper class which will instantiate any amount of those objects and overseer them!
    Then it's enough to have a field there to establish which 1 is the active "radio" Button. If any of course! \ ^_^/

  • edited November 2013

    I updated the code above with some improvements.

    @Chrisir, thanks for the suggestion. I was able to solve the oldColors issue, but not the resetLbls, unfortunately.

    @GoToLoop, thanks for your excellent suggestion. Your solution sounds exactly what I am looking for but I have not yet been able to write a proper "wrapper class which will instantiate any amount of those objects and overseer them" in order to establish a group of buttons with one active radio Button. I will try to look for a sample code, however, if you have any suggestions where to find such example, please, let me know.

  • Answer ✓

    For now, most I've got is a simple Button class w/ 2 colors for on/off states.
    You can check it out at the post below: (*)

    http://forum.processing.org/two/discussion/256/animated-buttons

  • edited November 2013

    @GoToLoop, thanks a lot!

    It is a slightly different kind of code that I am looking for, but I think I can get some great ideas from it and/or try to adopt it to my purpose.

    In your sample code each buttons appears independent (work on their own and toggling one button does not switch off the other ones, or am I mistaken?).

    Furthermore, we encounter the same problems as before (with a TextBox class) that Firefox browser (JavaScript mode) does not like the "shortened" versions of for loop andif statement.

  • edited November 2013 Answer ✓

    Work on their own and toggling one button does not switch off the other ones, or am I mistaken?

    You aren't! Even though only 1 is active at a given time, it's b/c each 1 is away from each other, w/o overlapping!
    Otherwise, any overlapping Button objects would be selected at the same time! 8-X

    Callback function mouseMoved() is responsible to call checkHovering() method for each Button
    to determine whether that's currently being mouse-hovered or not! >-)

    In your case, which isn't by hovering btw, once determined a Button has been clicked at, you gotta call a separate function
    which will reset some internal boolean field (I've used isHovering in my example) to false for all Button objects.
    Only then set to true the corresponding selected Button. Well, at least that's the approach I liked best! :ar!

    ... that Firefox browser (JavaScript mode) does not like the "shortened" versions of for loop and if statement.

    I've never heard about "shortened" version for if block! [-X

    Now about the "enhanced" for loop has a little bug which shows up about Firefox 18 and up. That was fixed "centuries" ago.
    But I've never seen a new stable release from PJS devs since I started using Processing!!! :-w

    Anyways, that bug is restricted to enhanced for loops when regular arrays are used for iteration.
    For the other Iterable class structures, no problems at all! :bz

    Just replace ->

    for (Button b: btns)   b.display();
    

    for ->

    for (int b=0; b!=BTN; btns[b++].display());
    
  • @GoToLoop, you are absolutely write about the if block!!! my apologies!

    And thanks so much for the explanation above! (*)

Sign In or Register to comment.