Skip to content

Commit 3890411

Browse files
committed
#324, #308 remove active and edit flags on item, move work around in the renderer.
1 parent 47801de commit 3890411

22 files changed

+277
-275
lines changed

examples/avr/keyboardEthernetShield/keyboardEthernetShield.ino

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ void setup() {
9393
// of the widget is fixed, and the height field instead indicates the first custom character for the first icon.
9494
renderer.setFirstWidget(&connectedWidget);
9595

96+
// we can choose which way RGB items should present, either has HEX_HTML or DECIMAL
97+
Rgb32MenuItem::setRgbPrintMode(HEX_HTML);
98+
9699
setupMenu();
97100

98101
auto* authenticator = reinterpret_cast<EepromAuthenticatorManager*>(menuMgr.getAuthenticator());

examples/avr/keyboardEthernetShield/tcMenuLiquidCrystal.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,25 +79,25 @@ int calculateOffset(GridPosition::GridJustification just, int totalLen, const ch
7979
void copyIntoBuffer(char* buffer, const char* source, int offset, int bufferLen) {
8080
auto len = strlen(source);
8181
for(size_t i=0; i<len; i++) {
82-
auto pos = offset+i;
83-
if(pos >= bufferLen) return;
82+
size_t pos = offset+i;
83+
if(pos >= (size_t)bufferLen) return;
8484
buffer[pos] = source[i];
8585
}
8686
}
8787

88-
void LiquidCrystalRenderer::drawMenuItem(GridPositionRowCacheEntry* entry, Coord where, Coord areaSize, bool /*ignored*/) {
88+
void LiquidCrystalRenderer::drawMenuItem(GridPositionRowCacheEntry* entry, Coord where, Coord areaSize, const DrawingFlags& drawingFlags) {
8989
auto* theItem = entry->getMenuItem();
9090
theItem->setChanged(false);
9191
char sz[21];
9292

9393
if(entry->getPosition().getJustification() == GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) {
94-
buffer[0] = theItem->isEditing() ? editChar : (theItem->isActive() ? forwardChar : ' ');
94+
buffer[0] = drawingFlags.isEditing() ? editChar : (drawingFlags.isActive() ? forwardChar : ' ');
9595
lcd->setCursor(where.x, where.y);
9696
int offs = 1;
9797
uint8_t finalPos = theItem->copyNameToBuffer(buffer, offs, bufferSize);
9898
for(uint8_t i = finalPos; i < uint8_t(areaSize.x); ++i) buffer[i] = 32;
9999
buffer[bufferSize] = 0;
100-
copyMenuItemValue(theItem, sz, sizeof sz);
100+
copyMenuItemValue(theItem, sz, sizeof sz, drawingFlags.isActive());
101101
uint8_t count = strlen(sz);
102102
int cpy = bufferSize - count;
103103
strcpy(buffer + cpy, sz);
@@ -116,12 +116,12 @@ void LiquidCrystalRenderer::drawMenuItem(GridPositionRowCacheEntry* entry, Coord
116116
if(itemNeedsValue(entry->getPosition().getJustification())) {
117117
sz[valueStart] = 32;
118118
valueStart++;
119-
copyMenuItemValue(entry->getMenuItem(), sz + valueStart, sizeof(sz) - valueStart);
119+
copyMenuItemValue(entry->getMenuItem(), sz + valueStart, sizeof(sz) - valueStart, drawingFlags.isActive());
120120
serlogF2(SER_TCMENU_DEBUG, "Value ", sz);
121121
}
122122
int position = calculateOffset(entry->getPosition().getJustification(), int(areaSize.x) + 1, sz);
123123
copyIntoBuffer(&buffer[1], sz, position, bufferSize);
124-
buffer[0] = theItem->isEditing() ? editChar : (theItem->isActive() ? forwardChar : ' ');
124+
buffer[0] = drawingFlags.isEditing() ? editChar : (drawingFlags.isActive() ? forwardChar : ' ');
125125
buffer[min(uint8_t(areaSize.x + 1), bufferSize)] = 0;
126126
lcd->setCursor(where.x, where.y);
127127
if(theItem == menuMgr.getCurrentEditor() && menuMgr.getEditorHints().getEditorRenderingType() != CurrentEditorRenderingHints::EDITOR_REGULAR) {

examples/avr/keyboardEthernetShield/tcMenuLiquidCrystal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class LiquidCrystalRenderer : public BaseGraphicalRenderer {
5050

5151
void drawingCommand(RenderDrawingCommand command) override;
5252
void drawWidget(Coord where, TitleWidget* widget, color_t colorFg, color_t colorBg) override;
53-
void drawMenuItem(GridPositionRowCacheEntry* entry, Coord where, Coord areaSize, bool drawAll) override;
53+
void drawMenuItem(GridPositionRowCacheEntry* entry, Coord where, Coord areaSize, const DrawingFlags& drawAll) override;
5454
void fillWithBackgroundTo(int endPoint) override;
5555

5656
ItemDisplayPropertiesFactory &getDisplayPropertiesFactory() override { return propertiesFactory; }

src/BaseDialog.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ void MenuBasedDialog::internalSetVisible(bool visible) {
289289
factory.addGridPosition(&btn2Item, GridPosition(GridPosition::DRAW_TEXTUAL_ITEM, GridPosition::JUSTIFY_RIGHT_NO_VALUE, 2, 2, row, 0));
290290
factory.addGridPosition(&bufferItem, GridPosition(GridPosition::DRAW_TEXTUAL_ITEM, GridPosition::JUSTIFY_LEFT_VALUE_ONLY, 1, 0));
291291

292-
auto toMakeActive = (lastBtnVal == 0 && btn1Item.isActive()) ? &btn1Item : &btn2Item;
292+
auto toMakeActive = (lastBtnVal == 0 && renderer->getActiveItem() == &btn1Item) ? &btn1Item : &btn2Item;
293293
menuMgr.navigateToMenu(&backItem, toMakeActive, true);
294294
}
295295
else {
@@ -317,11 +317,6 @@ void MenuBasedDialog::resetDialogFields() {
317317
bufferItem.setReadOnly(true);
318318
btn1Item.setNext(&btn2Item);
319319
addedMenuItems = 0;
320-
321-
backItem.setActive(false);
322-
bufferItem.setActive(false);
323-
btn1Item.setActive(false);
324-
btn2Item.setActive(false);
325320
}
326321

327322
void withMenuDialogIfAvailable(DialogInitialiser dlgFn) {

src/BaseRenderers.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,23 @@ class RenderingMenuMgrObserver : public MenuManagerObserver {
3535
} menuMgrListener;
3636

3737

38-
BaseMenuRenderer::BaseMenuRenderer(int bufferSize, RendererType rType) : MenuRenderer(rType, bufferSize) {
38+
BaseMenuRenderer::BaseMenuRenderer(int bufferSize, RendererType rType, uint8_t displayNum) : MenuRenderer(rType, bufferSize) {
3939
ticksToReset = 0;
4040
lastOffset = 0;
41+
displayNumber = displayNum;
4142
resetValInTicks = 30 * TC_DISPLAY_UPDATES_PER_SECOND;
42-
renderCallback = nullptr;
43+
renderCallback = nullptr;
4344
renderFnPressType = RPRESS_NONE;
4445
redrawMode = MENUDRAW_COMPLETE_REDRAW;
4546
this->lastOffset = 0;
4647
this->firstWidget = nullptr;
4748
this->dialog = nullptr;
4849
displayTakenMode = NOT_TAKEN_OVER;
4950
updatesPerSecond = TC_DISPLAY_UPDATES_PER_SECOND;
50-
MenuRenderer::theInstance = this;
51+
// if this is the default display, it becomes the static (IE global) instance for dialogs etc.
52+
if(displayNum == 0) {
53+
MenuRenderer::theInstance = this;
54+
}
5155
}
5256

5357
void BaseMenuRenderer::initialise() {
@@ -151,6 +155,14 @@ void BaseMenuRenderer::setFirstWidget(TitleWidget* widget) {
151155
this->redrawMode = MENUDRAW_COMPLETE_REDRAW;
152156
}
153157

158+
uint8_t BaseMenuRenderer::setActiveItem(MenuItem* item) {
159+
if(!item) return 0;
160+
if(activeItem) activeItem->setChanged(true);
161+
item->setChanged(true);
162+
activeItem = item;
163+
return findItemIndex(menuMgr.getCurrentMenu(), item);
164+
}
165+
154166
int BaseMenuRenderer::findItemIndex(MenuItem *root, MenuItem *toFind) {
155167
uint8_t i = 0;
156168
MenuItem *itm = root;
@@ -165,18 +177,7 @@ int BaseMenuRenderer::findItemIndex(MenuItem *root, MenuItem *toFind) {
165177
}
166178

167179
int BaseMenuRenderer::findActiveItem(MenuItem *root) {
168-
uint8_t i = 0;
169-
MenuItem *itm = root;
170-
while (itm != nullptr) {
171-
if (itm->isVisible()) {
172-
if (itm->isActive() || itm->isEditing()) {
173-
return i;
174-
}
175-
i++;
176-
}
177-
itm = itm->getNext();
178-
}
179-
return 0;
180+
return findItemIndex(menuMgr.getCurrentMenu(), activeItem);
180181
}
181182

182183
uint8_t BaseMenuRenderer::itemCount(MenuItem* item, bool includeNonVisible) {

src/BaseRenderers.h

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -285,22 +285,23 @@ class BaseMenuRenderer : public MenuRenderer, Executable {
285285
protected:
286286
uint8_t lastOffset;
287287
uint8_t updatesPerSecond;
288+
uint8_t displayNumber = 0;
289+
MenuRedrawState redrawMode;
288290
uint16_t ticksToReset;
289291
uint16_t resetValInTicks;
290-
MenuRedrawState redrawMode;
291292
TitleWidget* firstWidget;
292293
CustomDrawing *customDrawing;
293-
DisplayTakeoverMode displayTakenMode;
294294
BaseDialog* dialog;
295-
295+
DisplayTakeoverMode displayTakenMode;
296296
RenderPressMode renderFnPressType;
297297
RendererCallbackFn renderCallback;
298+
MenuItem* activeItem = nullptr;
298299
public:
299300
/**
300301
* constructs the renderer with a given buffer size
301302
* @param bufferSize size of text buffer to create
302303
*/
303-
BaseMenuRenderer(int bufferSize, RendererType rType = RENDER_TYPE_BASE);
304+
BaseMenuRenderer(int bufferSize, RendererType rType = RENDER_TYPE_BASE, uint8_t displayNum = 0);
304305

305306
/**
306307
* Destructs the class removing the allocated buffer
@@ -400,13 +401,6 @@ class BaseMenuRenderer : public MenuRenderer, Executable {
400401
*/
401402
virtual MenuItem *getMenuItemAtIndex(MenuItem *pItem, uint8_t idx);
402403

403-
/**
404-
* Find the active item offset in the list
405-
* @param root the root item
406-
* @return the position 0 based.
407-
*/
408-
virtual int findActiveItem(MenuItem* root);
409-
410404
/**
411405
* Find an item's offset in a given root, safely returns 0.
412406
* @param root the root item
@@ -423,6 +417,24 @@ class BaseMenuRenderer : public MenuRenderer, Executable {
423417
*/
424418
virtual uint8_t itemCount(MenuItem* item, bool includeNonVisible);
425419

420+
/**
421+
* Set the active index to a new menu item, the active item is the one that is selected for editing and
422+
* other display purposes. You must never pass null to this method, and you are returned the index in the array
423+
* that is now selected.
424+
* @return the active item index.
425+
*/
426+
virtual uint8_t setActiveItem(MenuItem* item);
427+
428+
MenuItem* getActiveItem() { return activeItem; }
429+
430+
/**
431+
* Find the active item offset in the list
432+
* @param root the root item
433+
* @return the position 0 based.
434+
*/
435+
int findActiveItem(MenuItem* root);
436+
437+
426438
/**
427439
* For menu systems that support title widgets, this will allow the first widget.
428440
* @param the first widget in a chain of widgets linked by next pointer.
@@ -469,6 +481,8 @@ class BaseMenuRenderer : public MenuRenderer, Executable {
469481
*/
470482
void invalidateAll() { redrawMode = MENUDRAW_COMPLETE_REDRAW; }
471483

484+
static BaseMenuRenderer* getInstance() { return reinterpret_cast<BaseMenuRenderer *>(theInstance); }
485+
472486
protected:
473487
/**
474488
* set up a countdown to default back to the submenu

src/EepromItemStorage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ bool loadMenuItem(EepromAbstraction* eeprom, MenuItem* theItem, uint16_t magicKe
189189

190190
void triggerAllChangedCallbacks() {
191191
getParentRootAndVisit(menuMgr.getRoot(), [](MenuItem* item) {
192-
if(item->isChanged() && item->getEepromPosition() != 0xffff) {
192+
if(item->isChanged(0) && item->getEepromPosition() != 0xffff) {
193193
item->triggerCallback();
194194
}
195195
});

src/MenuItems.cpp

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,6 @@ void MenuItem::setSendRemoteNeeded(uint8_t remoteNo, bool needed) {
2727
bitWrite(flags, (remoteNo + (int)MENUITEM_REMOTE_SEND0), (needed && !isLocalOnly()));
2828
}
2929

30-
void MenuItem::setEditing(bool active) {
31-
bool isEditOnEntry = isEditing();
32-
bitWrite(flags, MENUITEM_EDITING, active);
33-
setChanged(true);
34-
if (isMenuRuntimeMultiEdit(this) && !active && isEditOnEntry) {
35-
auto* item = reinterpret_cast<EditableMultiPartMenuItem*>(this);
36-
item->stopMultiEdit();
37-
}
38-
}
39-
4030
void MenuItem::setSendRemoteNeededAll() {
4131
// make sure local only fields are never marked for sending.
4232
if(isLocalOnly()) clearSendRemoteNeededAll();
@@ -119,9 +109,10 @@ uint16_t MenuItem::getEepromPosition() const
119109
return isInfoProgMem() ? get_info_uint(&info->eepromAddr) : info->eepromAddr;
120110
}
121111

122-
void MenuItem::setActive(bool active) {
123-
bitWrite(flags, MENUITEM_ACTIVE, active);
124-
setChanged(true);
112+
void MenuItem::setChanged(bool changed) {
113+
flags = flags | MENUITEM_ALL_CHANGE;
114+
if(isLocalOnly()) return;
115+
flags = flags | MENUITEM_ALL_REMOTES;
125116
}
126117

127118
// on avr boards we store all info structures in progmem, so we need this code to
@@ -320,19 +311,19 @@ const char NO_STR[] PGM_TCM = TXT_BOOL_NO_TEXT;
320311
const char TRUE_STR[] PGM_TCM = TXT_BOOL_TRUE_TEXT;
321312
const char FALSE_STR[] PGM_TCM= TXT_BOOL_FALSE_TEXT;
322313

323-
void copyMenuItemNameAndValue(const MenuItem* item, char* buffer, size_t bufferSize, char additionalSep) {
314+
void copyMenuItemNameAndValue(const MenuItem* item, char* buffer, size_t bufferSize, char additionalSep, bool active) {
324315
item->copyNameToBuffer(buffer, bufferSize);
325316
if(additionalSep != 0) appendChar(buffer, additionalSep, bufferSize);
326317
appendChar(buffer, ' ', bufferSize);
327318

328319
int pos = strlen(buffer);
329-
copyMenuItemValue(item, buffer + pos, bufferSize - pos);
320+
copyMenuItemValue(item, buffer + pos, bufferSize - pos, active);
330321
}
331322

332323
const char CHECKED_STR[] PROGMEM = "[X]";
333324
const char UNCHECKED_STR[] PROGMEM = "[ ]";
334325

335-
void copyMenuItemValue(const MenuItem* item, char* buffer, size_t bufferSize) {
326+
void copyMenuItemValue(const MenuItem* item, char* buffer, size_t bufferSize, bool active) {
336327
buffer[0] = 0;
337328
if(item->getMenuType() == MENUTYPE_ENUM_VALUE) {
338329
auto* enItem = reinterpret_cast<const EnumMenuItem*>(item);
@@ -372,12 +363,12 @@ void copyMenuItemValue(const MenuItem* item, char* buffer, size_t bufferSize) {
372363
}
373364
else if(item->getMenuType() == MENUTYPE_BACK_VALUE) {
374365
buffer[0]=0;
375-
if(item->isActive()) {
366+
if(active) {
376367
strncpy(buffer, "[..]", bufferSize);
377368
}
378369
}
379370
else if(item->getMenuType() == MENUTYPE_TITLE_ITEM) {
380-
if(reinterpret_cast<const tcgfx::RuntimeTitleMenuItem*>(item)->getCallback() && item->isActive()) {
371+
if(reinterpret_cast<const tcgfx::RuntimeTitleMenuItem*>(item)->getCallback() && active) {
381372
strncpy(buffer, "...", bufferSize);
382373
} else buffer[0] = 0;
383374
}
@@ -387,9 +378,9 @@ void copyMenuItemValue(const MenuItem* item, char* buffer, size_t bufferSize) {
387378
}
388379
}
389380

390-
void copyMenuItemValueDefault(const MenuItem* item, char* buffer, size_t bufferSize, const char* defValue) {
381+
void copyMenuItemValueDefault(const MenuItem* item, char* buffer, size_t bufferSize, const char* defValue, bool active) {
391382
buffer[0]=0;
392-
copyMenuItemValue(item, buffer, bufferSize);
383+
copyMenuItemValue(item, buffer, bufferSize, active);
393384
if(strlen(buffer)==0) {
394385
strncpy(buffer, defValue, bufferSize);
395386
buffer[bufferSize - 1] = 0;

0 commit comments

Comments
 (0)