From e921d068771fe03ea824e41052653e3277f78c22 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 13 Apr 2013 15:18:19 -0700 Subject: [PATCH] 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. --- interface/src/MenuColumn.cpp | 9 +++++- interface/src/MenuColumn.h | 1 + interface/src/MenuRow.cpp | 54 ++++++++++++++++++++++++++++-------- interface/src/MenuRow.h | 5 ++++ 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/interface/src/MenuColumn.cpp b/interface/src/MenuColumn.cpp index 8c8548ea05..94e8595c8b 100644 --- a/interface/src/MenuColumn.cpp +++ b/interface/src/MenuColumn.cpp @@ -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); diff --git a/interface/src/MenuColumn.h b/interface/src/MenuColumn.h index c712ac64a1..3b1b59affd 100644 --- a/interface/src/MenuColumn.h +++ b/interface/src/MenuColumn.h @@ -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]; diff --git a/interface/src/MenuRow.cpp b/interface/src/MenuRow.cpp index 495ca29987..910edf07b7 100644 --- a/interface/src/MenuRow.cpp +++ b/interface/src/MenuRow.cpp @@ -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; } diff --git a/interface/src/MenuRow.h b/interface/src/MenuRow.h index 8bca2a462d..638ffde125 100644 --- a/interface/src/MenuRow.h +++ b/interface/src/MenuRow.h @@ -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__) */