Forum: Projekte & Code Mal wieder: Menüs programmieren


von Fabi O. (efpegea)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

es geht wie in so vielen anderen Beiträgen hier mal wieder um ein Menü. 
Allerdings hat mich bisher kein anderer Beitrag hier wirklich weiter 
gebracht. Deshalb habe ich nun etwas eigenes ausgedacht, was meine 
Anforderungen erfüllt.
Ich möchte nämlich auf keinen Fall in irgendwelche undefinierten 
Zustände (Arraygrenzen etc.) laufen, und möglichst komfortabel die 
Menüstruktur einpflegen können.

Dazu ist mir folgendes eingefallen: Ein Menüpunkt als Struct 
beschreiben, ihm einen Namen zur Anzeige geben, die Nachbarn auf 
gleicher Menü-Ebene sowie in der darüber und darunter über Zeiger 
vermerken, Reaktionen auf jeweilige Eingabe über Funktionszeiger.
Das Struct dazu sieht folgendermaßen aus:
1
 typedef const struct MENU_ITEM {
2
    const char *name;
3
    const struct MENU_ITEM *up, *down, *left, *right;
4
    void(*f_up)(const struct MENU_ITEM**), (*f_down)(const struct MENU_ITEM**), 
5
(*f_left)(const struct MENU_ITEM**), (*f_right)(const struct MENU_ITEM**);
6
}menu_item_t;

Eine Beispielinitalisierung sähe dann so aus:
1
 menu_item_t menu01 = {"Motor", &menu03, &menu02, NULL, NULL, std_up, std_down, std_left, show_motor_value};

Dabei sind die 'std_'-Funktionen als Standard vordefiniert und 
verschieben sich (den Pointer) quasi selbst auf eine andere Menü-Ebene. 
Das sähe dann wie folgt aus:
1
 void std_up(menu_item_t** self) {
2
    if((*self)->up) (*self) = (*self)->up;
3
    return;
4
}
Der Vorteil ist, dass auch auf der untersten Menü-Ebene - wo wirklich 
was gemacht und nicht nur navigiert werden soll - die Funktionspointer 
sehr einfach zu setzen sind, und dann die Aktionen ausgeführt werden.
Außerdem erachte ich es als Vorteil einfach die 'std_'-Funktionen als 
default hinzuschreiben, und wenn kein Nachbar existier (NULL), dann 
stürzt auch nichts ab.
Damit finde ich die Menü-Einprogrammierung recht komfortabel.

Um das ganze vielleicht noch einmal ein bisschen klarer zu mache, hänge 
ich nochmal ein kleines Beispielprojekt an.

Nun zu meinen Fragen: Ist das vom Programmierstil her halbwegs in 
Ordnung? Sollte man irgendwas komplett anders machen? Andere Ideen?

Ach ja, wenn ich das Programm dann auf den AVR portiere, wo es 
eigentlich laufen soll, würde ich die Menü-Struktur natürlich mit PROMEM 
ins Flasch verfrachten.

Danke schonmal für Tipps und Anregungen,

eFPeGeA

von W.S. (Gast)


Lesenswert?

Du denkst wie viele Leute hier viel zu prozedural. Denke lieber in 
objektorientierten und ereignisgesteuerten Kategorien. Und denke auch 
lieber nicht "Ich will jetzt ein Menüsystem bauen" sondern "Ich will den 
Bildschirm mit Dingen füllen, die was darstellen, die auf Ereignisse 
reagieren können und zwischen denen ich navigieren kann".

Das wird auf lange Sicht ein sowohl sparsames als auch mächtiges System.

W.S.

von Julian W. (julian-w) Benutzerseite


Lesenswert?

W.S. schrieb:
> Denke lieber in objektorientierten und ereignisgesteuerten Kategorien

Ich denke da landet man dann aber sehr schnell bei C++ was bei 8bit 
Mikrocontrollern eventuell nicht so dolle ist...

von Walter T. (nicolas)


Lesenswert?

Und sieh direkt vor, den Inhalt Deines Menüs im Flash unterzubringen. 
Mir hat das bei meinen Menüstrukturen beinahe 1k RAM eingespart.

von Fabi O. (efpegea)


Lesenswert?

W.S. schrieb:
> Du denkst wie viele Leute hier viel zu prozedural. Denke lieber in
> objektorientierten und ereignisgesteuerten Kategorien. Und denke auch
> lieber nicht "Ich will jetzt ein Menüsystem bauen" sondern "Ich will den
> Bildschirm mit Dingen füllen, die was darstellen, die auf Ereignisse
> reagieren können und zwischen denen ich navigieren kann".
>
> Das wird auf lange Sicht ein sowohl sparsames als auch mächtiges System.
>
> W.S.

Wie julian-w schon sagt, möchte ich bei reinem C bleiben und nicht auf 
C++ portieren, da es auf einem 8-bit AVR laufen soll. Während ich mir 
das überlegt habe, kamen mir auch dauernd Ideen, wie man das in C++ 
elegant lösen könnte. Aus dieser Denkweise heraus bin ich dann 
wahrscheinlich auch auf den Pointer 'self' gekommen.

Wenn denn C++ sparsam auf einem 8-bit AVR umsetzbar wäre, würde ich das 
auch liebend gerne machen. Leider ist dem meines Wissens nicht so.

Nicolas S. schrieb:
> Und sieh direkt vor, den Inhalt Deines Menüs im Flash unterzubringen.
> Mir hat das bei meinen Menüstrukturen beinahe 1k RAM eingespart.

Wie ich bereits im ersten Beitrag schrieb, würde ich bei Portierung auf 
den AVR auf jeden Fall alle Menü-Elemente in den Flash ablegen und nicht 
ins RAM. Alles andere wäre ja ziemliche Verschwendung. Hatte jetzt nur 
zum Proof-of-Concept am PC keine Lust das alles über den Präprozessor zu 
unterscheiden.

Weitere Anregungen, Tips etc.?!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.