ArduinoMenu icon indicating copy to clipboard operation
ArduinoMenu copied to clipboard

Custom Two Line Output

Open davidbitton opened this issue 7 years ago • 17 comments

I created my own in and out MenuIO files; jetiboxIn and jetiBoxOut. I used the serialIn and serialOut as examples to work from. I need to be able to replicate this type of output

pic

Each "window" if you will is two lines. I have to set the text for each line separately by calling jetiEx.SetJetiboxText(JetiExProtocol::LINE1, 0) and jetiEx.SetJetiboxText(JetiExProtocol::LINE2, 0). Where I'm stumbling on is setCursor and write. It's unclear in io.h and io.cpp how these are called. I decided to create two panels; one for each line like this:

#include "jetiboxOut.h"

namespace Menu {

    constMEM panel jetibox_panels[] MEMMODE = {{0, 0, 16, 1},{0, 1, 16, 1}};
    navNode *jetibox_nodes[sizeof(jetibox_panels) / sizeof(panel)];
    panelsList jetibox_panel_list(
        jetibox_panels, 
        jetibox_nodes,
        sizeof(jetibox_panels) / sizeof(panel)
    );

} // namespace Menu

How does ArduinoMenu uses multiple panels in lieu of a single two line panel? How is the text being passed to write? Is it one char at a time? Should I be keeping track of my "cursor" and copy each incoming char in write into the subsequent position in my output buffer? How does ArduinoMenu respect the defined width in chars of the given panels? Does it make more sense to have a single two line panel? Most windows are a label above and a choice or toggle on the 2nd line. I'd like to keep this as KISS as possible. Thanks!

davidbitton avatar Feb 28 '18 20:02 davidbitton

yes, it is one character at a time due to its text-mode origins. panels are for isolating menus inside boxes (positioning and size) however menu is line based (again text origins), however you can control the height of a lines in pixels, not a single line but all lines on a given gfx menuOut and you can customize how items print, so they internally can use the 2 lines. also, because you can customize how items print themselves you can print in other way than the single character at a time and can customize so for whole classes of items, not just one. However that does not help the fact that centrally the menu system controls position and scrolls based on single lines.

you can simulate screen replacement by using custom print and a line height that corresponds to your device height.

neu-rah avatar Feb 28 '18 20:02 neu-rah

thinking on an lcd (2 lines) and as you have already done a driver you case is viable. the driver should use the full screen (2 lines), but should inform a size of one single line.

all elements have to be custom drawn (or driver reworked to use sencond line as an extension of the single, but in this case the titles would all have to had the same length)

you can then provide a sequence of menu levels where all options of one level should lead to the same next level, see reuse example

neu-rah avatar Feb 28 '18 21:02 neu-rah

I went back to the library and I think lcdOut.h and the cursorOut base class are more appropriate for what I'm doing based on the fact that the target device is an LCD. I can manage a char* buffer for each line and copy chars into the buffer as they come in via write, using setCursor to keep track of where I'm at. How does the library manage removing chars at each cursor position? Do I need to override more than just write? Is the library just calling clear before updating what's on a given "line"? Am I sure that if I'm using a cursorOut derivative that setCursor will be called? Since I'm using my own type, a fair amount of my setup is without macros; as per the noMacros demo. Thanks.

davidbitton avatar Feb 28 '18 21:02 davidbitton

lcd driver prints a blanks line I think and gfx draw a filled rectangle to clear line before print

neu-rah avatar Feb 28 '18 21:02 neu-rah

In looking at the implementation of Write in the Arduino core,

/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    if (write(*buffer++)) n++;
    else break;
  }
  return n;
}

I can see the fact that each char is placed into the buffer.

davidbitton avatar Feb 28 '18 21:02 davidbitton

@neu-rah what about setCursor? Will that be called? Does occur in the cursorOut base class?

davidbitton avatar Feb 28 '18 21:02 davidbitton

Is the code calling fill? That does call SetCursor and Write.

davidbitton avatar Feb 28 '18 21:02 davidbitton

yes code calls clearLine, setCursor, fill and write

neu-rah avatar Feb 28 '18 21:02 neu-rah

correction: for your menu to work ok and reflect selected values some dynamic position would be required (as navigation system clears positioning when entering a menu) or i can implement some flag to not reset as this menu type has no ramifications

also: can use first line as menu title and second line as menu options, no need for special driver, but still needs positioning to selected option when entering a menu (if that happens after nav system cleanup)

neu-rah avatar Feb 28 '18 22:02 neu-rah

marking this as enhancement as it is a clear case where 2D nav could be used (not implemented yet) because usually you have to click to edit values, only menus can change selection without the need of initial click.

Instead of using menu prompts and tricky navigation positioning this could be better achieved by using fields (fields preserve values), however they require the initial click to edit.

except if we have more than 2 navigation buttons and a different navigation core (2D)

neu-rah avatar Mar 01 '18 00:03 neu-rah

All the Jetibox has for nav is four buttons; up, down, left, and right. For example if you change a choice, you would navigate to the end then press the down button to save the config settings.

davidbitton avatar Mar 01 '18 01:03 davidbitton

yes, understand that and while navigating the "pipe" each stage has to preserve its state with 4 buttons there's no need to select or click to edit, just change settings.

this kind of navigation is not yet implemented, there are codes for up/down/left/right and even a nav2D flag on navRoot class, but not much more.

https://github.com/neu-rah/ArduinoMenu/blob/master/src/nav.h#L95

it was leaved this way because the menu is already over-sized for medium avr's like the atmega328. The idea then was to leave this to next version along with deep review of IO and also a modular navigation core to slim down simple menus and only load whats needed... as you see its a pile of work and this might take a while (help appreciated, anyone?). However I will take a look of whats needed and if its viable on this version... will post here.

neu-rah avatar Mar 01 '18 02:03 neu-rah

Obviously I'll help.

davidbitton avatar Mar 01 '18 02:03 davidbitton

what mcu are you using?

neu-rah avatar Mar 01 '18 02:03 neu-rah

I'm using a Mini Pro with a 328p. However I can use anything. I am looking at the SAMD51G19A now. Then arduino-core for the D51 was just released.

davidbitton avatar Mar 01 '18 03:03 davidbitton

almost there, dev branch is using new input method (for version 5). Swapping the menu root (as in here https://github.com/neu-rah/ArduinoMenu/issues/166) is not enough to this case as focused item still need to be made active and state preserved, working on it...

neu-rah avatar Apr 02 '18 14:04 neu-rah

Sounds great. I'll keep an eye out.

davidbitton avatar Apr 02 '18 16:04 davidbitton