Jump to content

Buttons: one callback for multiple sources


Recommended Posts

Posted

Hi,

I'm implementing an on-screen keypad with buttons and I've stumbled on a problem. I have 12 buttons ([0..9] and a few control) and I want to register them with the same callback. At the callback I want to find out which button was pressed, but I'm unable to figure it out. In my callback I get a (void)* param and a Gevent; as far as I can tell all the button source can't be determined with the Gevent functions.

My second thought was to add a custom variable to the Button on initialisation which can then be querried from the Gevent, but which of them are used internally and which are available for custom data?

I'd like to add that I implemented it without buttons (use screen locations as in the Notepad example and get "button" events by filtering the touch coordinates) but I've abandoned that approach because the code turned out rather messy.

regards,

Fred

Posted

You should be able to retrieve the button information from the gevent structure that you get passed in your callback:


void _callback(void* param, GEvent *pe)
{
...
((GEventGWinButton *)pe)->button
...
}

It's exactly the same as you do when handling the returned GEvent from geventEventWait() within the main(). Note that I did not try this code and it comes completely out of my mind. I'm on the bus.

I hope that helps a bit.

~ Tectu

Posted

Hi,

works like a charm, here's some code if anyone wants to try it:


//Keypad settings
#define KEYPAD_X 550 //keypad left border
#define KEYPAD_Y 100 //keypad top
#define KEYPAD_WIDTH 225 //
#define KEYPAD_HEIGHT 300 //
#define GLOBALVALUE_X 550
#define GLOBALVALUE_Y 60
#define GLOBALVALUE_WIDTH 225
#define GLOBALVALUE_HEIGHT 40

//variables needed:
//globals keypad
GButtonObject keypadGlobalsButton[12];
GHandle keypadGlobalsButtonHandle[12];
GSourceHandle keypadGlobalsButtonSource[12];
char* keypadGlobalsStrings[12] = {"1","2","3","4","5","6","7","8","9","BACK","0","CLR"};
GListener keypadGlobalsCB;

//the variable we're editing
static uint32_t globalEditValue = 0;

font_t fontLarger;

void printGlobalVar(void){
char globalValueText[12];

chprintftostring(globalValueText, "%u", globalEditValue);
gdispFillStringBox(GLOBALVALUE_X, GLOBALVALUE_Y, GLOBALVALUE_WIDTH, GLOBALVALUE_HEIGHT, globalValueText, fontLarger, Yellow, DarkGreen, justifyCenter);
gdispDrawBox(GLOBALVALUE_X, GLOBALVALUE_Y, GLOBALVALUE_WIDTH, GLOBALVALUE_HEIGHT, Green);
}

//The shared button handler
void keypadGlobalsButtonHandler(void *param, GEvent *pe){
GHandle pressed = ((GEventGWinButton *)pe)->button;
uint8_t i = 0;

for(i = 0; i < 12; i++){
if(pressed == keypadGlobalsButtonHandle[i]){
break;
}
}
if(i == 9){//backspace .. divide by 10
globalEditValue /= 10;
}else if(i == 11){//clear
globalEditValue = 0;
}else if(i < 9){//x = 1..9, y(n+1) = 10*y(n) + x
globalEditValue = 10 * globalEditValue + i + 1;
}else if(i == 10){//x = 0, y(n+1) = 10*y(n)
globalEditValue *= 10;
}
printGlobalVar();
}

//alloc of the buttons
void createGlobalsKeypadButtons(void){
uint8_t x, y, i = 0;
fontLarger = gdispOpenFont("Larger Double");
geventListenerInit(&keypadGlobalsCB);
keypadGlobalsCB.callback = &keypadGlobalsButtonHandler;

//draw keypad: 0..9, backsp, "." and assign button
for(y = 0; y < 4; y++){
for(x = 0; x < 3; x++){
keypadGlobalsButtonHandle[i] = gwinCreateButton(&keypadGlobalsButton[i], KEYPAD_X + x * 75 + 3, KEYPAD_Y + y * 75 + 3, 70, 70, fontLarger, GBTN_NORMAL);
gwinSetButtonText(keypadGlobalsButtonHandle[i], keypadGlobalsStrings[i], FALSE);
keypadGlobalsButtonSource[i] = gwinGetButtonSource(keypadGlobalsButtonHandle[i]);
geventAttachSource(&keypadGlobalsCB, keypadGlobalsButtonSource[i], 0);//attach listener
gwinAttachButtonMouse(keypadGlobalsButtonHandle[i], 0);
i++;
}
}
}

//buttons de-activation
void disableGlobalsKeypad(void){
uint8_t i = 0;
GButtonObject *gb;

for(i = 0; i < 12; i++){
if(keypadGlobalsButtonHandle[i] != NULL){
gb = &keypadGlobalsButton[i];
gb->gwin.enabled = FALSE;
}
}
}

//buttons activation
void enableGlobalsKeypad(uint8_t draw){
uint8_t i = 0;
GButtonObject *gb;

if(draw == TRUE){//start with a lightgrey square background
gdispFillArea(KEYPAD_X, KEYPAD_Y, KEYPAD_WIDTH, KEYPAD_HEIGHT, LightGray);
}
for(i = 0; i < 12; i++){
if(keypadGlobalsButtonHandle[i] != NULL){
gb = &keypadGlobalsButton[i];
gb->gwin.enabled = TRUE;
if(draw == TRUE){
gwinButtonDraw(keypadGlobalsButtonHandle[i]);
}
}
}
}

In your init code call createGlobalsKeypadButtons(); followed by disableGlobalsKeypad();

The buttons are allocated, listening and calling the callback but they're not drawn - disableGlobalsKeypad() disables them altogether without destroying them. When you're ready to draw them you clear the screen and call enableGlobalsKeypad(TRUE);

BTW, everything is called xxxGlobalsxxx because I use this to edit and update global variables during runtime. If you have many buttons, don't forget to adjust GEVENT_MAX_SOURCE_LISTENERS.

regards,

Fred

Posted

I'm thinking about that, I'm currently implementing a second keypad to edit the RTC time/date and it would be nice to be able to reuse the code. But it's proving difficult to cover these two examples with the same code. I think I'll implement them seperately and see how they can be brought together in a widget.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...