Skip to content

Commit 8269a6e

Browse files
author
dave
committed
#74 #55 fixing up the callback facilities before release.
1 parent 85407b5 commit 8269a6e

File tree

4 files changed

+110
-15
lines changed

4 files changed

+110
-15
lines changed

src/tcMenu.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ void MenuManager::setupForEditing(MenuItem* item) {
249249
if(!notifyEditStarting(item)) return;
250250
auto* boolItem = (BooleanMenuItem*)item;
251251
boolItem->setBoolean(!boolItem->getBoolean());
252+
notifyEditEnd(item);
252253
}
253254
else if (ty == MENUTYPE_SCROLLER_VALUE) {
254255
if(!notifyEditStarting(item)) return;
@@ -305,15 +306,10 @@ MenuManager::MenuManager() : structureNotifier() {
305306
this->eepromRef = nullptr;
306307
}
307308

308-
void MenuManager::addMenuAfter(MenuItem *existing, MenuItem* toAdd) {
309-
if(existing->getNext()) {
310-
toAdd->setNext(nullptr);
311-
existing->setNext(toAdd);
312-
}
313-
else {
314-
toAdd->setNext(existing->getNext());
315-
existing->setNext(toAdd);
316-
}
309+
void MenuManager::addMenuAfter(MenuItem *existing, MenuItem* toAdd, bool silent) {
310+
toAdd->setNext(existing->getNext());
311+
existing->setNext(toAdd);
312+
if(!silent) notifyStructureChanged();
317313
}
318314

319315
void MenuManager::addChangeNotification(MenuManagerObserver *observer) {

src/tcMenu.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,15 +291,16 @@ class MenuManager {
291291

292292
/**
293293
* Adds a menu item into the tree directly after the existing item provided. Never add an item that's already in
294-
* the tree. Don't forget to call menuStructureChanged() after you're done adding items
294+
* the tree. Don't forget that if you use silent, to call menuStructureChanged() after you're done adding items.
295295
* @param existing where in the tree the new item is to be added.
296296
* @param toAdd the item that should be added, must not be in the tree already.
297+
* @param silent do not run the structure changed callback.
297298
*/
298-
void addMenuAfter(MenuItem* existing, MenuItem* toAdd);
299+
void addMenuAfter(MenuItem* existing, MenuItem* toAdd, bool silent = false);
299300

300301
/**
301302
* Call this method after making any structural change to the menu tree. For example adding a new menu item,
302-
* changing the item name or size parameters, modifying an info block, etc.
303+
* changing the item name or static data such as size parameters. For example: modifying an items name, etc.
303304
*/
304305
void notifyStructureChanged();
305306

tests/tcMenuCoreTests/menuManagerTests.cpp

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#ifndef MENU_MANAGER_TEST_H
2-
#define MENU_MANAGER_TEST_H
31

42
#include <AUnit.h>
53
#include <MockIoAbstraction.h>
@@ -71,4 +69,103 @@ test(saveAndLoadFromMenu) {
7169
assertFalse(eeprom.hasErrorOccurred());
7270
}
7371

74-
#endif
72+
class TestMenuMgrObserver : public MenuManagerObserver {
73+
private:
74+
bool structureChangedCalled{};
75+
bool editStartedCalled{};
76+
bool editEndedCalled{};
77+
bool startReturnValue{};
78+
public:
79+
TestMenuMgrObserver() = default;
80+
81+
void setStartReturn(bool toReturn) { startReturnValue = toReturn; }
82+
83+
void reset() {
84+
structureChangedCalled = editStartedCalled = editEndedCalled = false;
85+
}
86+
87+
void structureHasChanged() override {
88+
structureChangedCalled = true;
89+
}
90+
91+
bool menuEditStarting(MenuItem *item) override {
92+
editStartedCalled = true;
93+
return startReturnValue;
94+
}
95+
96+
void menuEditEnded(MenuItem *item) override {
97+
editEndedCalled = true;
98+
}
99+
100+
bool didTriggerStructure() const { return structureChangedCalled; }
101+
bool didTriggerStartEdit() const { return editStartedCalled; }
102+
bool didTriggerEndEdit() const { return editEndedCalled; }
103+
} menuMgrObserver;
104+
105+
const PROGMEM AnyMenuInfo testActionInfo = { "ActTest", 2394, 0xffff, 0, NO_CALLBACK };
106+
ActionMenuItem testActionItem(&testActionInfo, nullptr);
107+
108+
const PROGMEM AnyMenuInfo testActionInfo2 = { "ActTest", 2394, 0xffff, 0, NO_CALLBACK };
109+
ActionMenuItem testActionItem2(&testActionInfo2, nullptr);
110+
111+
test(addingItemsAndMenuCallbacks) {
112+
menuMgr.setRootMenu(&textMenuItem1);
113+
menuMgr.initWithoutInput(&noRenderer, &textMenuItem1);
114+
menuMgr.addChangeNotification(&menuMgrObserver);
115+
116+
// first we add some menu items at the end of the menu and test the structure change call is made
117+
menuMgr.addMenuAfter(&menuNumTwoDp, &testActionItem, true);
118+
assertFalse(menuMgrObserver.didTriggerStructure());
119+
menuMgr.addMenuAfter(&menuNumTwoDp, &testActionItem2);
120+
assertTrue(menuMgrObserver.didTriggerStructure());
121+
122+
assertEqual(&testActionItem2, menuNumTwoDp.getNext());
123+
assertEqual(&testActionItem, testActionItem2.getNext());
124+
assertTrue(testActionItem.getNext() == nullptr);
125+
126+
// put back as it was before.
127+
menuNumTwoDp.setNext(nullptr);
128+
129+
// now we test that when editing a bool, we get a commit callback.
130+
menuMgrObserver.reset();
131+
menuMgrObserver.setStartReturn(true);
132+
auto currentMenuValue = boolItem1.getBoolean();
133+
menuMgr.valueChanged(1); // boolItem1
134+
assertTrue(boolItem1.isActive());
135+
menuMgr.onMenuSelect(false);
136+
137+
assertTrue(menuMgrObserver.didTriggerEndEdit());
138+
assertTrue(menuMgrObserver.didTriggerStartEdit());
139+
assertTrue(boolItem1.getBoolean() != currentMenuValue);
140+
141+
// and now we test that when we return false in the start edit callback, we do not start editing.
142+
menuMgrObserver.reset();
143+
menuMgrObserver.setStartReturn(false);
144+
menuMgr.onMenuSelect(false);
145+
assertTrue(menuMgrObserver.didTriggerStartEdit());
146+
assertFalse(menuMgrObserver.didTriggerEndEdit());
147+
assertTrue(boolItem1.getBoolean() != currentMenuValue);
148+
149+
// now we move on to test an enum (integer) item and ensure we get the edit callbacks.
150+
menuMgrObserver.reset();
151+
menuMgrObserver.setStartReturn(true);
152+
menuMgr.valueChanged(2); // select menuEnum1
153+
menuMgr.onMenuSelect(false); // start edit
154+
assertTrue(menuMgrObserver.didTriggerStartEdit());
155+
assertTrue(menuEnum1.isEditing());
156+
157+
menuMgr.valueChanged(1); // we are now editing, change the actual enum
158+
menuMgr.onMenuSelect(false); // stop editing
159+
assertTrue(menuMgrObserver.didTriggerEndEdit());
160+
assertEqual((uint16_t)1, menuEnum1.getCurrentValue());
161+
162+
// lastly try an enum item that does not go into editing because the callback returned false.
163+
menuMgrObserver.reset();
164+
menuMgrObserver.setStartReturn(false);
165+
menuMgr.valueChanged(2); // menuEnum1
166+
menuMgr.onMenuSelect(false);
167+
assertTrue(menuMgrObserver.didTriggerStartEdit());
168+
assertFalse(menuEnum1.isEditing());
169+
170+
}
171+

tests/tcMenuCoreTests/tcMenuFixtures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define _TCMENU_FIXTURES_H_
33

44
#include "tcUtil.h"
5+
#include "MenuItems.h"
56
#include "RuntimeMenuItem.h"
67

78
const PGM_TCM AnalogMenuInfo minfoNumTwoDp = { "TwoDpNum", 23, 32, 30000, NO_CALLBACK, 0, 100, "" };

0 commit comments

Comments
 (0)