#include #include "config.h" #include "config_pins.h" #include "lcd.h" #include "states.h" template void array_print(Array *arr) { Serial.print(F("Array length: ")); Serial.print(arr->size()); Serial.println(F(" contents:")); for (int i = 0; i < arr->size(); i++) { Serial.print(i); Serial.print(F(": ")); Serial.println(arr->at(i)->getTitle()); } } template void array_insert_at_pos(Array *arr, T value, size_t pos) { // make additional space arr->push_back(value); if ((pos >= arr->max_size()) || (pos >= arr->size())) { // we can not shift it to the given position return; } for (int i = arr->size() - 2; i >= pos; i--) { arr->at(i + 1) = arr->at(i); } arr->at(pos) = value; } // -------------------------------------- StateMenu::StateMenu(State *_parent, bool _show_parent) : State(_parent) { show_parent = _show_parent; menuPos = 0; menuOff = 0; } void StateMenu::setChild(State *_child) { children.push_back(_child); } void StateMenu::addChild(State *_child, int pos) { if (pos < 0) { setChild(_child); } else { array_insert_at_pos(&children, _child, pos); } } void StateMenu::enterState(void) { display(); } void StateMenu::display(void) { lcd_clear(); lcd_set_heading(getTitle()); int size = children.size(); if (show_parent) { size++; } for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < size); i++) { String s; if (i == menuPos) { s = F("> "); } else { s = F(" "); } if (i == children.size()) { s += getParent()->getTitle(); } else { s += children.at(i)->getTitle(); } lcd_set_menu_text(i - menuOff, s.c_str()); } } void StateMenu::inState(struct StateMachineInput smi) { int size = children.size(); if (show_parent) { size++; } if (smi.encoder != 0) { menuPos -= smi.encoder; while (menuPos < 0) { menuPos += size; } while (menuPos >= size) { menuPos -= size; } while (menuPos < menuOff) { menuOff--; } while (menuPos >= (menuOff + lcd_text_lines())) { menuOff++; } display(); } if (smi.click) { if (menuPos == children.size()) { menuPos = 0; menuOff = 0; states_go_to(getParent()); } else { states_go_to(children.at(menuPos)); } } } // -------------------------------------- StateDynamicMenu::StateDynamicMenu(State *_parent) : State(_parent) { menuPos = 0; menuOff = 0; prefix = ""; countFunc = NULL; getFunc = NULL; callFunc = NULL; } void StateDynamicMenu::dataCount(CountFuncPtr count) { countFunc = count; } void StateDynamicMenu::dataGet(GetFuncPtr get) { getFunc = get; } void StateDynamicMenu::dataCall(CallFuncPtr call) { callFunc = call; } void StateDynamicMenu::display(void) { lcd_clear(); lcd_set_heading(getTitle()); for (int i = menuOff; (i < menuOff + lcd_text_lines()) && (i < count + 1); i++) { String s; if (i == menuPos) { s = F("> "); } else { s = F(" "); } if (i == count) { s += getParent()->getTitle(); } else { s += contents.at(i); } lcd_set_menu_text(i - menuOff, s.c_str()); } } void StateDynamicMenu::setPrefix(String pre) { prefix = pre; } void StateDynamicMenu::enterState(void) { // cache all entries on entering state if (countFunc != NULL) { count = countFunc(); } else { count = 0; } contents.clear(); for (int i = 0; i < count; i++) { if (getFunc != NULL) { contents.push_back(prefix + String(getFunc(i))); } else { contents.push_back(prefix + String(i + 1)); } } display(); } void StateDynamicMenu::inState(StateMachineInput smi) { if (smi.encoder != 0) { menuPos -= smi.encoder; while (menuPos < 0) { menuPos += count + 1; } while (menuPos >= count + 1) { menuPos -= count + 1; } while (menuPos < menuOff) { menuOff--; } while (menuPos >= (menuOff + lcd_text_lines())) { menuOff++; } display(); } if (smi.click) { if (menuPos == count) { menuPos = 0; menuOff = 0; states_go_to(getParent()); } else { if (callFunc != NULL) { callFunc(menuPos); } } } }