OfxGui: utf-8 and reacting on ofxButton press?

I am using:

$ (cd openFrameworks/; git log -1 --decorate | head -3)
commit 16eca45a1d45a6a98621756cabad0e2a9b85ff44 (HEAD, origin/master, origin/HEAD, master)
Author: arturo castro <arturo@openframeworks.cc>
Date:   Sat Sep 19 12:18:44 2015 +0200
$ cat /etc/issue
Ubuntu 14.04.3 LTS \n \l

I have prepared the following example, first by running the command line project generator:

openFrameworks/apps/projectGenerator/commandLine/bin/projectGenerator \
-a"ofxGui" -o"openFrameworks" \
openFrameworks/examples/addons/guiBtnTest

… and then replacing the ofApp.{cpp,h} in examples/addons/guiBtnTest/src with these files:

ofApp.h:

#pragma once

#include "ofMain.h"
#include "ofxGui.h" //addon here too

class ofApp : public ofBaseApp{

  public:
    void setup();
    void update();
    void draw();

    ofxButton testButton;
    void testButtonChange(bool & inval);
    ofxToggle testToggle;
    void testToggleChange(bool & inval);
    ofParameter<bool> testBoolParam;
    void testBoolParamChange(bool & inval);
    ofxPanel gui;

    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y );
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void mouseEntered(int x, int y);
    void mouseExited(int x, int y);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);

};

ofApp.cpp:

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){

  ofSetVerticalSync(true);
  ofSetLogLevel(OF_LOG_NOTICE);

  // this **** line causes:
  /*
ofEvent.h:407:93: error: no matching function for call to ‘ofEvent<void>::make_function(ofApp*&, void (ofApp::*&)(bool&), int&)’
   ofBaseEvent<of::priv::Function<void>,Mutex>::remove(make_function(listener,method,priority));
ofEvent.h:402:90: note: candidates are:
...
  */
  //testButton.addListener(this, &ofApp::testButtonChange); //****

  testToggle.addListener(this, &ofApp::testToggleChange);
  testBoolParam.addListener(this, &ofApp::testBoolParamChange);

  gui.setup("my panel"); // most of the time you don't need a name but don't forget to call setup
  gui.add(testButton.setup("testButton ← !"));
  gui.add(testToggle.setup("testToggle ← !", true));
  gui.add(testBoolParam.set("testBoolParam ← !", true));
}

//--------------------------------------------------------------
void ofApp::testButtonChange(bool & inval){
  if (inval) {
    ofLogNotice() << "testButtonChange: true" << endl;
  } else {
    ofLogNotice() << "testButtonChange: false" << endl;
  }
}

//--------------------------------------------------------------
void ofApp::testToggleChange(bool & inval){
  if (inval) {
    ofLogNotice() << "testToggleChange: true" << endl;
  } else {
    ofLogNotice() << "testToggleChange: false" << endl;
  }
}

//--------------------------------------------------------------
void ofApp::testBoolParamChange(bool & inval){
  if (inval) {
    ofLogNotice() << "testBoolParamChange: true" << endl;
  } else {
    ofLogNotice() << "testBoolParamChange: false" << endl;
  }
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
  ofBackgroundGradient(ofColor::white, ofColor::gray);
  gui.draw();
}

void ofApp::keyPressed(int key){}
void ofApp::keyReleased(int key){}
void ofApp::mouseMoved(int x, int y ){}
void ofApp::mouseDragged(int x, int y, int button){}
void ofApp::mousePressed(int x, int y, int button){}
void ofApp::mouseReleased(int x, int y, int button){}
void ofApp::mouseEntered(int x, int y){}
void ofApp::mouseExited(int x, int y){}
void ofApp::windowResized(int w, int h){}
void ofApp::gotMessage(ofMessage msg){}
void ofApp::dragEvent(ofDragInfo dragInfo){}

Then I build and run with:

cd openFrameworks/examples/addons/guiBtnTest/
make -j 2 Release
MESA_GL_VERSION_OVERRIDE=2.1 ./bin/guiBtnTest

The application looks something like this:

As you can see, I can relatively easily get reaction on clicks from ofxToggle and ofParameter<bool>, simply by calling addListener. However, the same is not valid for ofxButton - as soon as I try to addListener to it - I get compilation errors of the error: no matching function for call type (try uncommenting the **** line in ofApp.cpp).

So, my questions are:

  • Is it possible somehow to receive an event/trigger on press and release of ofxButton in ofxGui? If so, how?
  • The text used in the app is "test* ← !"; as you can see, there is an utf-8 arrow ‘’ in there, however, it is not rendered in the app. Is it possible to get extended utf-8 characters in ofxGui widgets - and if so, how?

Thanks in advance for any answers,
Cheers!

Well, I got a bit further - I consulted again openFrameworks/examples/gui/guiExample, and it turns out you have to use void arguments in the function that is going to be a listener for ofxButton, you cannot use a bool like for ofxToggle. So with these changes:

in ofApp.h:

void testButtonChange(); //(bool & inval);

in ofApp.cpp:

testButton.addListener(this, &ofApp::testButtonChange); //****
...
void ofApp::testButtonChange(){
  ofLogNotice() << "testButtonChange: release" << endl;
}

… finally I managed to get a response from click of ofxButton.

Unfortunately, it only reacts on button release, and not on button press.

So, my question is now - can I get ofxButton to react somehow on mouse press? (And also, still would like to know on the status of utf-8 display here with ofxGui)

  • no, you can’t get the pressed event, buttons usually trigger the click event on released which is what you usually need. if you need something different you can create a new version of ofxButton, ofxButtonPress? which triggers the event on pressed instead of released or triggers both using a boolean event instead of a void one

  • no, utf8 is not supported yet for rendering text in OF. there’s already a pull request, that won’t make it into 0.9, which will add support for utf8. even with that the default font for ofxGui is very limitied and won’t have support for utf8. you can change the default font by calling

ofxBaseGui::loadFont("someutf8font.ttf",fontSize);

but as i said this won’t work until after 0.9

1 Like

Many thanks for the response, @arturo - good to have my questions answered! Cheers!


EDIT: Well, I managed to make an alternate class for ofxButton that reacts on press and release. It is basically just a copy-paste of ofxButton, with some methods set to public, and with a changed valueChanged method; probably not the right best practice, but worksforme for the time being - and maybe it helps someone:

class ofxButtonB : public ofxToggle{
  friend class ofPanel;
public:
  ofxButtonB(){ value.setSerializable(false); }
  ~ofxButtonB(){ }
  ofEvent<void> triggerEvent;
  //~ ofParameter<bool> value; // ofxToggle.h; protected; don't replace here, else events are messed
  bool myval;
  template<class ListenerClass, typename ListenerMethod>
  void addListener(ListenerClass * listener, ListenerMethod method){
    ofAddListener(triggerEvent,listener,method);
  }
  template<class ListenerClass, typename ListenerMethod>
  void removeListener(ListenerClass * listener, ListenerMethod method){
    ofRemoveListener(triggerEvent,listener,method);
  }
  ofxButtonB* setup(const std::string& toggleName, float width = defaultWidth, float height = defaultHeight) {
    setName(toggleName);
    b.x = 0; b.y = 0; b.width = width; b.height = height;
    bGuiActive = false; value = false;
    checkboxRect.set(1, 1, b.height - 2, b.height - 2);
    registerMouseEvents(); value.addListener(this,&ofxButtonB::valueChanged);
    return this;
  }
  bool mouseReleased(ofMouseEventArgs & args){
    bool attended = setValue(args.x, args.y, false);
    bGuiActive = false;
    if(attended){ return true; } else { return false; }
  }
  bool mouseMoved(ofMouseEventArgs & args){ return ofxToggle::mouseMoved(args); }
  bool mousePressed(ofMouseEventArgs & args){ return ofxToggle::mousePressed(args); }
  bool mouseDragged(ofMouseEventArgs & args){ return ofxToggle::mouseDragged(args); }
  void valueChanged(bool & v){
    ofLogNotice() << "valueChanged" << v << endl;
    myval = v;
    //if(!v){
      ofNotifyEvent(triggerEvent, this);
    //}
  }
}; // expected ‘;’ after class definition

It is written like this so you can directly paste it ofApp.h; the listener is again void, like in original ofxButton, but now there is a public property myval so you can retrieve the press state, say like so:

void ofApp::testButtonChange(){
  ofLogNotice() << "testButtonChange: release" << testButton.myval ;
}