Added new feature to MenuRow to allow custom callback for State

Note: there's some bug in the menu render code that doesn't like state strings
that are longer than 4 characters + NULL. So, the current code will clip any
state string that is longer than 4 characters. We need to look into this 5
character limit. It's a bug.
This commit is contained in:
ZappoMan 2013-04-13 15:18:19 -07:00
parent 27165be902
commit e921d06877
4 changed files with 56 additions and 13 deletions

View file

@ -117,6 +117,14 @@ int MenuColumn::addRow(const char* rowName, MenuRowCallback callback) {
return 0;
}
int MenuColumn::addRow(const char* rowName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback) {
MenuRow* row;
row = new MenuRow(rowName, callback, stateNameCallback);
rows.push_back(*row);
delete row;
return 0;
}
int MenuColumn::getMaxRowWidth() {
float scale = 0.09;
int mono = 0;
@ -148,7 +156,6 @@ void MenuColumn::render(int yOffset, int menuHeight, int lineHeight) {
}
int y = menuHeight + lineHeight / 2 ;
char* rowName;
int columnWidth = 0;
for (unsigned int i = 0; i < rows.size(); ++i) {
rowName = rows[i].getName();
drawtext(leftPosition + SPACE_BEFORE_ROW_NAME, y+5 + yOffset, scale, 0, 1.0, mono, rowName, 0, 0, 0);

View file

@ -27,6 +27,7 @@ public:
void render(int yOffset, int menuHeight, int lineHeight);
void renderMouseOver(int yOffset);
int addRow(const char* rowName, MenuRowCallback callback);
int addRow(const char* rowName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback);
int getMaxRowWidth();
private:
char columnName[MAX_COLUMN_NAME];

View file

@ -16,14 +16,28 @@
#include "MenuColumn.h"
#include "Menu.h"
MenuRow::MenuRow() {
MenuRow::MenuRow() :
callback(NULL),
stateNameCallback(NULL) {
}
MenuRow::MenuRow(const char * columnName, MenuRowCallback callback) {
MenuRow::MenuRow(const char * columnName, MenuRowCallback callback) :
callback(callback),
stateNameCallback(NULL) {
int length = std::min(MAX_COLUMN_NAME - 5,(int) strlen(columnName));
strncpy(this->rowName, columnName, length);
memcpy(this->rowName + length, " \0", 5);
this->callback = callback;
rowWidth = 0;
}
MenuRow::MenuRow(const char * columnName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback) :
callback(callback),
stateNameCallback(stateNameCallback) {
int length = std::min(MAX_COLUMN_NAME - 5,(int) strlen(columnName));
strncpy(this->rowName, columnName, length);
// note: it would be good to also include the initial state
memcpy(this->rowName + length, " \0", 5);
rowWidth = 0;
}
@ -31,19 +45,35 @@ MenuRow::~MenuRow() {
}
void MenuRow::call() {
callback(-2);
callback(MENU_ROW_PICKED);
}
char* MenuRow::getName() {
int length = (int) strlen(this->rowName) - 4;
int currentValue = callback(-1);
if (currentValue == 0) {
memcpy(this->rowName + length, " OFF\0", 5);
} else if (currentValue == 1) {
memcpy(this->rowName + length, " ON \0", 5);
} else {
memcpy(this->rowName + length, " \0", 5);
}
int currentValue = callback(MENU_ROW_GET_VALUE);
// If the MenuRow has a custom stateNameCallback function, then call it to get a string
// to display in the menu. Otherwise, use the default implementation.
if (stateNameCallback != NULL) {
const char* stateName = stateNameCallback(currentValue);
int stateNameLength = strlen(stateName);
printf("MenuRow::getName() stateName=%s stateNameLength=%d\n",stateName,stateNameLength);
// XXXBHG - BUG!!! - only 5 characters?? someplace else hard coded? for some reason, we end up
// with memory corruption down the line, if we allow these states to be longer than 5 characters
// including the NULL termination.
strncpy(this->rowName + length, stateName,4); // only 4 chars
memcpy(this->rowName + length + 5, "\0", 0); // null terminate!!
} else {
if (currentValue == 0) {
memcpy(this->rowName + length, " OFF\0", 5);
} else if (currentValue == 1) {
memcpy(this->rowName + length, " ON \0", 5);
} else {
memcpy(this->rowName + length, " \0", 5);
}
}
return this->rowName;
}

View file

@ -12,13 +12,17 @@
const int MAX_COLUMN_NAME = 50;
const int SPACE_BETWEEN_COLUMNS = 20;
const int SPACE_BEFORE_ROW_NAME = 10;
const int MENU_ROW_PICKED = -2;
const int MENU_ROW_GET_VALUE = -1;
typedef int(*MenuRowCallback)(int);
typedef const char*(*MenuStateNameCallback)(int);
class MenuRow {
public:
MenuRow();
MenuRow(const char* rowName, MenuRowCallback callback);
MenuRow(const char* rowName, MenuRowCallback callback, MenuStateNameCallback stateNameCallback);
~MenuRow();
void call();
char * getName();
@ -28,6 +32,7 @@ private:
char rowName[MAX_COLUMN_NAME];
int rowWidth;
MenuRowCallback callback;
MenuStateNameCallback stateNameCallback;
};
#endif /* defined(__hifi__MenuRow__) */