Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2136 - 1
/*****************************************************************************
2
 *   Copyright (C) 2013 Oliver Gemesi                                        *
3
 *                                                                           *
4
 *   This program is free software; you can redistribute it and/or modify    *
5
 *   it under the terms of the GNU General Public License as published by    *
6
 *   the Free Software Foundation; either version 2 of the License.          *
7
 *                                                                           *
8
 *   This program is distributed in the hope that it will be useful,         *
9
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
10
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
11
 *   GNU General Public License for more details.                            *
12
 *                                                                           *
13
 *   You should have received a copy of the GNU General Public License       *
14
 *   along with this program; if not, write to the                           *
15
 *   Free Software Foundation, Inc.,                                         *
16
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.               *
17
 *****************************************************************************/
18
 
19
//############################################################################
20
//# HISTORY  menuctrl.c
21
//#
22
//# 11.06.2014 OG
23
//# - add: MenuCtrl_GetMenuIndex()
24
//#
25
//# 31.05.2014 OG
26
//# - chg: MenuCtrl_Refresh() - umgestellt auf PKT_KeylineUpDown()
27
//#
28
//# 14.05.2014 OG
29
//# - chg: include "../mk/paramset.h" geaendert auf "../mksettings/paramset.h"
30
//# - chg: include "../mk/mkparameters.h" geaendert auf "../mksettings/mkparameters.h"
31
//#
32
//# 11.05.2014 OG
33
//# - add: MenuCtrl_SetTitleFromParentItem()
34
//# - add: MenuCtrl_GetItemText(), MenuCtrl_IsItemTextPGM()
35
//# - chg: _MenuCtrl_Error() - auf PKT_Popup_P() umgestellt, Layout geaendert und
36
//#        einen neuen Fehler (NOPARENTMENU) hinzugefuegt
37
//#
38
//# 09.05.2014 OG
39
//# - fix: MenuCtrl_Refresh() Anzeige von deaktivierten MK-Parametern (Favoriten)
40
//#        Wenn MK-Paramketer-Menueeintraege deaktiviert sind werden sie vom
41
//#        aktuellen MK-Parameterset nicht unterstuetzt - dennoch wurde der
42
//#        aktuelle Wert des MK-Parameters im Menuepunkt (ganz rechts) angezeigt.
43
//#        Das ist jetzt behoben - es wird kein Wert angezeigt (stattdessen "***")
44
//#        und auch keine entsprechende editParam-Funktionen aufgerufen.
45
//#
46
//# 07.05.2014 OG
47
//# - add: MenuCtrl_PushSeparatorID()
48
//#
49
//# 06.05.2014 OG
50
//# - chg: MenuCtrl_Refresh() Keyline leicht angepasst
51
//# - chg: 'not possible' Anzeige (bei deaktiviertem Item) umgestellt auf
52
//#        PKT_Popup_P()
53
//# - add: MenuCtrl_GetItemIdByIndex(), MenuCtrl_GetItemCount()
54
//#
55
//# 05.05.2014 OG
56
//# - chg: MenuCtrl_Control()
57
//#        -> Unterstuetzung fuer: MenuCtrl_SetMove() - Menueeintraege verschieben
58
//# - chg: MenuCtrl_Refresh() - Anpassung Slider fuer MenuCtrl_SetDelete()
59
//# - add: MenuCtrl_SetDelete(), MenuCtrl_SetMove()
60
//# - add: _MenuCtrl_SwapItem()
61
//# - add: die Datenstruktur vom Menue wurde erweitert um die Eigenschaften
62
//#        canMove und canDelete
63
//#
64
//# 17.04.2014 OG
65
//# - chg: MENUCTRL_MAXITEMS von 22 auf 28 erhoeht
66
//#
67
//# 30.03.2014 OG
68
//# - del: MenuCtrl_PushML_P(), MenuCtrl_PushML() (Umstellung Sprachen abgeschlossen)
69
//# - add: MenuCtrl_PushML2(), MenuCtrl_PushML2_P() fuer Umstellung von 3 auf 2 Sprachen
70
//#
71
//# 29.03.2014 OG
72
//# - chg: default MENUDEFAULT_SHOWBATT auf true umgestellt (=PKT-Batterie anzeigen)
73
//# - chg: MenuCtrl_Control() umgestellt auf clear_key_all()
74
//#
75
//# 24.03.2014 OG
76
//# - add: MenuCtrl_PushSeparator() - fuegt eine Trennlinie im Menue ein
77
//# - chg: MenuCtrl_Refresh() Codeoptimierung bzgl. topspace/Zeile loeschen/Slider
78
//# - fix: MenuCtrl_Control() es wurde zuoft ein Screen-Refresh durchgefuehrt
79
//#
80
//# 23.03.2014 OG
81
//# - add: Unterstuetzung fuer MK-Parameter-Edit (mkparameters.c)
82
//# - chg: MenuCtrl_Refresh() Unterstuetzung fuer MENU_PARAMEDIT
83
//# - add: MenuCtrl_PushParamEdit()
84
//# - add: paramset.h und mkparameters.h
85
//#
86
//# 04.03.2014 OG
87
//# - fix: MenuCtrl_Refresh() bei einem blauen Display (das ist wohl schneller
88
//#        in der Anzeige als das S/W-Display) flackerte der Menue-Slider
89
//#
90
//# 17.02.2014 OG
91
//# - add: MenuCtrl_SetTopSpace()
92
//# - chg: MenuCtrl_Refresh() angepasst auf MenuCtrl_SetTopSpace()
93
//#
94
//# 15.02.2014 OG
95
//# - add: MenuCtrl_ItemSelect()
96
//#
97
//# 01.02.2014 OG
98
//# - chg: MENUCTRL_MAXITEMS von 16 auf 22 fuer MK_parameters
99
//# - fix: _MenuCtrl_Error() Anzeigezeit von Menu-Errors auf 8 Sekunden verlaengert
100
//#        und Anzeige von "menuctrl.c"
101
//#
102
//# 07.07.2013 OG
103
//# - add: MenuCtrl_ItemMarkR() - Markiert einen Menueeintrag mit einem Haken am ENDE (Rechts)
104
//#
105
//# 24.05.2013 OG
106
//# - chg: MenuCtrl_Push... Funktionen vereinheitlicht mit internen Aenderungen
107
//#        betrifft externe Funktionsaufrufe die geändert wurden
108
//# - chg: MenuCtrl_Refresh() Anpassungen und Optimierung
109
//# - add: MenuCtrl_ItemMark()
110
//# - del: MenuCtrl_PushSimple_P(), MenuCtrl_PushSimple()
111
//#
112
//# 23.05.2013 OG
113
//# - add: MenuCtrl_PushSimple_P(), MenuCtrl_PushSimple()
114
//# - fix: MenuCtrl_Control() Eventcode Rueckgabe bei KEY_ENTER
115
//#
116
//# 22.05.2013 OG
117
//# - fix: nach Aufruf einer Menuefunktion in MenuCtrl_Control() jetzt
118
//#        get_key_press(KEY_ALL)
119
//#
120
//# 21.05.2013 OG
121
//# - add: MenuCtrl_ShowLevel()
122
//#
123
//# 20.05.2013 OG
124
//# - chg: MenuCtrl_Control() wieder mit get_key_press(KEY_ALL) ergaenzt
125
//#        wenn aufgerufen mit MENUCTRL_EVENT oder erster Aufruf mit RETURN
126
//#
127
//# 20.05.2013 OG
128
//# - chg: Space am Anfang der Titelanzeige
129
//#
130
//# 19.05.2013 OG
131
//# - add: define MENU_SHOWLEVEL mit dem der aktuelle Menuelevel in der
132
//#        Titelzeile angezeigt werden kann
133
//# - fix: Redraw-Logik bei MENUCTRL_RETURN
134
//# - chg: MenuCtrl_Control() erweitert um PKT_Update()
135
//#
136
//# 18.05.2013 OG - NEU
137
//############################################################################
138
 
139
#include "../cpu.h"
140
#include <avr/io.h>
141
#include <inttypes.h>
142
#include <stdlib.h>
143
#include <avr/pgmspace.h>
144
#include <avr/wdt.h>
145
#include <util/delay.h>
146
#include <string.h>         // memset
147
#include <stdarg.h>
148
 
149
#include "../main.h"
150
#include "../lcd/lcd.h"
151
#include "../eeprom/eeprom.h"
152
#include "../messages.h"
153
#include "../lipo/lipo.h"
154
#include "../menu.h"
155
#include "../pkt/pkt.h"
156
#include "../mksettings/paramset.h"
157
#include "../mksettings/mkparameters.h"
158
#include "menuctrl.h"
159
 
160
 
161
//#############################################################################################
162
//# internal defines & structs
163
//#############################################################################################
164
 
165
#define MENU_SHOWLEVEL          false   // Anzeige der Menue-Verschachtelungstiefe in der Titelzeile
166
                                        // zeigt dem Benutzer wie weit er wieder zurueckspringen muss
167
                                        // um in das Hauptmenue zu kommen
168
 
169
#define MENUDEFAULT_CYCLE       false   // cycle: wenn Menue am Ende dann wieder zum Anfang
170
#define MENUDEFAULT_SHOWBATT    true    // showbatt: zeigt PKT-Batterie im Menuetitel ganz rechts
171
#define MENUDEFAULT_BEEP        true    // beep: wenn Cursor ueber Ende/Anfang
172
 
173
 
174
#define MENUCTRL_MAXMENUES  6           // Anzahl max. verschachlteter Menues
175
//#define MENUCTRL_MAXITEMS   22          // Anzahl max. Menu-Items pro Menue (verbraucht Speicher)
176
//#define MENUCTRL_MAXITEMS   28          // Anzahl max. Menu-Items pro Menue (verbraucht Speicher)
177
#define MENUCTRL_MAXITEMS   34          // Anzahl max. Menu-Items pro Menue (verbraucht Speicher)
178
#define ERROR_NOMENU        1           // Errorcode
179
#define ERROR_MAXMENU       2           // Errorcode
180
#define ERROR_MAXITEM       3           // Errorcode
181
#define ERROR_NOITEM        4           // Errorcode
182
#define ERROR_NOPARENTMENU  5           // Errorcode
183
 
184
//-----------------------------------------------------------
185
// typedef: scrollbox_key_t
186
//-----------------------------------------------------------
187
typedef struct
188
{
189
    uint8_t     active;             // Taste aktiv? (true/false)
190
    const char  *text;              // Tastentext
191
    void (*func)(void);             // ggf. Funktions-Pointer (0=keine Funktion)
192
}  menue_key_t;
193
 
194
 
195
//---------------------------
196
// typedef: einzelnes Menueitem
197
//---------------------------
198
typedef struct
199
{
200
    uint8_t     id;
201
    uint8_t     type;               // MENU_ITEM, MENU_SUB, MENU_PARAMEDIT
202
    uint8_t     disabled;           // true / false  (deaktiviert einen Menuepunkt)
203
    uint8_t     mark;               // true / false  (markiert einen Menuepunkt Links '*')
204
    uint8_t     markR;              // true / false  (markiert einen Menuepunkt Rechts)
205
    uint8_t     textPGM;            // true / false (true = text in PROGMEN; false = text im RAM)
206
    uint8_t     textcount;          // 1 .. NUM_LANG
207
    const char *text[NUM_LANG];     // de, en, nl  (NUM_LANG aus messages.h)
208
    void (*func)(void);
209
}  menue_item_t;
210
 
211
 
212
//---------------------------
213
// typedef: Menueitem Liste
214
//---------------------------
215
typedef struct
216
{
217
    uint8_t         active;         // aktives item
218
    uint8_t         itemcount;      // Anzahl Items
219
    uint8_t         scroll_pos;     // aktuelle obere Anzeigezeile
220
    uint8_t         display_pos;    // aktuelle obere Anzeigezeile
221
    uint8_t         topspace;       // obere Leerzeilen - default=0 (Vorsicht! ggf. nur bedingt einsetzbar bei Menues die ohne scrollen auskommen!)
222
    uint8_t         firstredraw;    // true / false  (flag fuer ein erstes redraw bei MENUCTRL_RETURN)
223
    uint8_t         cycle;          // true / false
224
    uint8_t         showbatt;       // true / false
225
    uint8_t         beep;           // true / false
226
    uint8_t         canMove;        // true / false
227
    uint8_t         canDelete;      // false/0 = kein entfernen; true/1 = entfernen mit Nachfrage; 2 = entfernen ohne Nachfrage
228
    uint8_t         titlePGM;       // true / false
229
    const char      *title;         // Menuetitel (oberste Zeile) (ggf. Multisprache machen?)
230
    uint8_t         lastkey;        // verwendet von GetKey()
231
    menue_key_t     key_enter;
232
    menue_key_t     key_enter_long;
233
    menue_key_t     key_esc;
234
    menue_key_t     key_esc_long;
235
    menue_item_t    item[MENUCTRL_MAXITEMS];
236
}  menue_t;
237
 
238
uint8_t showlevel = MENU_SHOWLEVEL; // Anzeige Menulevel in der Titelanzeige
239
int8_t  midx = -1;                  // aktives Menue; -1 = kein Menue
240
menue_t menu[MENUCTRL_MAXMENUES];   // Stack fuer n geschachltete Menues
241
 
242
 
243
 
244
//#############################################################################################
245
//# PRIVAT funcs
246
//#############################################################################################
247
 
248
 
249
//--------------------------------------------------------------
250
// INTERN
251
//--------------------------------------------------------------
252
void _MenuCtrl_Error( uint8_t error )
253
{
254
    const char *pStr = NULL;
255
 
256
    switch( error )
257
    {
258
        case ERROR_NOMENU:          pStr = PSTR("NOMENU");       break;
259
        case ERROR_MAXMENU:         pStr = PSTR("MAXMENU");      break;
260
        case ERROR_MAXITEM:         pStr = PSTR("MAXITEM");      break;
261
        case ERROR_NOITEM:          pStr = PSTR("NOITEM");       break;
262
        case ERROR_NOPARENTMENU:    pStr = PSTR("NOPARENTMENU"); break;
263
    }
264
 
265
    set_beep( 1000, 0x000f, BeepNormal);                                    // Beep Error
266
    PKT_Popup_P( 10000, PSTR("menuctrl.c"), 0, PSTR("* ERROR *"), pStr );   // 10000 = max. 100 Sekunden anzeigen
267
}
268
 
269
 
270
//--------------------------------------------------------------
271
// INTERN
272
//--------------------------------------------------------------
273
int8_t _MenuCtrl_FindItem( uint8_t itemid )
274
{
275
    int8_t i;
276
 
277
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return -1; }
278
 
279
    for( i=0; i<menu[midx].itemcount; i++)
280
    {
281
        if( itemid == menu[midx].item[i].id )
282
        {
283
            return i;   // found: return index
284
        }
285
    }
286
    return -1;          // not found
287
}
288
 
289
 
290
//--------------------------------------------------------------
291
// INTERN
292
//--------------------------------------------------------------
293
void _MenuCtrl_CalcDisplayPos( void )
294
{
295
    int8_t i;
296
 
297
    i = menu[midx].active - menu[midx].display_pos;
298
 
299
    if( i < 0 )
300
        menu[midx].display_pos = menu[midx].active;
301
    else if( i > 5 )
302
        menu[midx].display_pos = (menu[midx].active - 5);
303
}
304
 
305
 
306
//--------------------------------------------------------------
307
// INTERN
308
//--------------------------------------------------------------
309
void _MenuCtrl_Beep( void )
310
{
311
    if( menu[midx].beep )
312
        set_beep( 25, 0xffff, BeepNormal );
313
}
314
 
315
 
316
//--------------------------------------------------------------
317
// INTERN
318
// Dreieckstausch von zwei Menuepunkten.
319
// Wird verwendet um Menueitems zu verschieben.
320
//--------------------------------------------------------------
321
void _MenuCtrl_SwapItem( uint8_t itemindex_1, uint8_t itemindex_2 )
322
{
323
    menue_item_t tmpItem;
324
 
325
    memcpy( &tmpItem                      , &menu[midx].item[itemindex_1], sizeof(menue_item_t) );
326
    memcpy( &menu[midx].item[itemindex_1] , &menu[midx].item[itemindex_2], sizeof(menue_item_t) );
327
    memcpy( &menu[midx].item[itemindex_2] , &tmpItem, sizeof(menue_item_t) );
328
}
329
 
330
 
331
 
332
//#############################################################################################
333
//# PUBLIC funcs
334
//#############################################################################################
335
 
336
 
337
//--------------------------------------------------------------
338
// MenuCtrl_Create()
339
//--------------------------------------------------------------
340
void MenuCtrl_Create( void )
341
{
342
    if( midx >= MENUCTRL_MAXMENUES) { _MenuCtrl_Error( ERROR_MAXMENU ); return; }
343
 
344
    midx++;
345
    memset( &menu[midx], 0, sizeof(menue_t) );
346
    menu[midx].cycle        = MENUDEFAULT_CYCLE;
347
    menu[midx].showbatt     = MENUDEFAULT_SHOWBATT;
348
    menu[midx].beep         = MENUDEFAULT_BEEP;
349
}
350
 
351
 
352
//--------------------------------------------------------------
353
// MenuCtrl_Destroy()
354
//--------------------------------------------------------------
355
void MenuCtrl_Destroy( void )
356
{
357
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
358
 
359
    midx--;
360
}
361
 
362
 
363
//--------------------------------------------------------------
364
// MenuCtrl_ShowLevel( value )
365
//
366
// Diese Einstellung ist Global und wirkt sich direkt auf alle
367
// Menues aus!
368
// Man kann das also nicht fuer einzelne Menues ein-/ausschalten.
369
//
370
// Parameter:
371
//   value: true / false
372
//--------------------------------------------------------------
373
void MenuCtrl_ShowLevel( uint8_t value )
374
{
375
    showlevel = value;
376
}
377
 
378
 
379
//--------------------------------------------------------------
380
// MenuCtrl_SetTitle_P( *title )
381
//
382
// Parameter:
383
//   title: Menuetitel; Zeiger auf String PROGMEM
384
//--------------------------------------------------------------
385
void MenuCtrl_SetTitle_P( const char *title )
386
{
387
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
388
 
389
    menu[midx].title    = title;
390
    menu[midx].titlePGM = true;
391
}
392
 
393
 
394
//--------------------------------------------------------------
395
// MenuCtrl_SetTitle( *title )
396
//
397
// Parameter:
398
//   title: Menuetitel; Zeiger auf String im RAM
399
//--------------------------------------------------------------
400
void MenuCtrl_SetTitle( const char *title )
401
{
402
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
403
 
404
    menu[midx].title    = title;
405
    menu[midx].titlePGM = false;
406
}
407
 
408
 
409
 
410
//--------------------------------------------------------------
411
// MenuCtrl_SetTitleFromParentItem()
412
//
413
// setzte anhand des uebergeordneten Menuepunktes (dem aufrufenden
414
// Menuepunkt) den Titel des neuen Menues
415
//
416
// wird u.a. verwendet in setup.c
417
//--------------------------------------------------------------
418
void MenuCtrl_SetTitleFromParentItem( void )
419
{
420
    uint8_t     lang;
421
    const char *pStr;
422
    uint8_t     mparent;
423
 
424
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU );       return; }
425
    if( midx < 1)   { _MenuCtrl_Error( ERROR_NOPARENTMENU ); return; }
426
 
427
    mparent = midx-1;
428
 
429
    //--------------------------
430
    // Sprache: Multilanguage oder 0 wenn wenn nur ein Text
431
    //--------------------------
432
    lang = (menu[mparent].item[ menu[mparent].active ].textcount == 1) ? 0 : Config.DisplayLanguage;
433
 
434
    //--------------------------
435
    // Text vom uebergeordneten Menuepunkt
436
    //--------------------------
437
    pStr = menu[mparent].item[ menu[mparent].active ].text[lang];
438
 
439
    //--------------------------
440
    // Titel setzen
441
    //--------------------------
442
    if( menu[mparent].item[ menu[mparent].active ].textPGM )
443
    {
444
        MenuCtrl_SetTitle_P( pStr );
445
    }
446
    else
447
    {
448
        MenuCtrl_SetTitle( pStr );
449
    }
450
}
451
 
452
 
453
 
454
//--------------------------------------------------------------
455
// MenuCtrl_SetCycle( value )
456
//
457
// Parameter:
458
//   value: true / false
459
//--------------------------------------------------------------
460
void MenuCtrl_SetCycle( uint8_t value )
461
{
462
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
463
 
464
    menu[midx].cycle    = value;
465
}
466
 
467
 
468
 
469
//--------------------------------------------------------------
470
// MenuCtrl_SetBeep( value )
471
//
472
// Parameter:
473
//   value: true / false
474
//--------------------------------------------------------------
475
void MenuCtrl_SetBeep( uint8_t value )
476
{
477
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
478
 
479
    menu[midx].beep = value;
480
}
481
 
482
 
483
 
484
//--------------------------------------------------------------
485
// MenuCtrl_SetMove( value )
486
//
487
// Schaltet in einem Menue die Moeglichkeit ein Menueeintraege nach
488
// oben oder nach unten zu verschieben.
489
// Zum verschieden eines Menueeintrages muessen die PLUS/MINUS Tasten
490
// lange gedrueckt werden.
491
//
492
// Parameter:
493
//   value: true / false (Default: false)
494
//--------------------------------------------------------------
495
void MenuCtrl_SetMove( uint8_t value )
496
{
497
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
498
 
499
    menu[midx].canMove = value;
500
}
501
 
502
 
503
//--------------------------------------------------------------
504
// MenuCtrl_SetDelete( value )
505
//
506
// Schaltet in einem Menue die Moeglichkeit ein Menueeintraege zu loeschen.
507
// Zum loeschen eines Menueeintrages muss dann die ganz rechte 'OK' Taste
508
// lange gedrueckt werden.
509
//
510
// Parameter:
511
//   value: true / false (Default: false)
512
//--------------------------------------------------------------
513
void MenuCtrl_SetDelete( uint8_t value )
514
{
515
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
516
 
517
    menu[midx].canDelete = value;
518
}
519
 
520
 
521
//--------------------------------------------------------------
522
// MenuCtrl_SetShowBatt( value )
523
//
524
// Parameter:
525
//   value: true / false
526
//--------------------------------------------------------------
527
void MenuCtrl_SetShowBatt( uint8_t value )
528
{
529
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
530
 
531
    menu[midx].showbatt = value;
532
}
533
 
534
 
535
 
536
//--------------------------------------------------------------
537
// MenuCtrl_SetTopSpace( n )
538
//
539
// fuegt oben im Menue n Leerzeichen ein um Abstand vom Menuetitel
540
// zu erhalten
541
//
542
// ACHTUNG! Das funktioniert nur mit Menues die nicht Scrollen!
543
// -> also weniger als 6 Eintraege haben (je nach Anzahl von TopSpace)
544
//
545
// ACHTUNG! Keine Absicherung bzgl. obigem Warnpunkt! Das kann man
546
// zwar machen - ist aber aktuell nicht so!
547
//
548
// Parameter:
549
//   value: 0..n  Anzahl der Leerzeilen ueber dem Menue
550
//--------------------------------------------------------------
551
void MenuCtrl_SetTopSpace( uint8_t n )
552
{
553
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }
554
 
555
    menu[midx].topspace = n;
556
}
557
 
558
 
559
 
560
//--------------------------------------------------------------
561
// MenuCtrl_SetKey( key, *keytext, *keyfunc )
562
//
563
// Parameter:
564
//   key    : KEY_ENTER, KEY_ENTER_LONG, KEY_ESC, KEY_ESC_LONG
565
//   keytext: Pointer auf Text PROGMEM oder NOTEXT (=0)
566
//   keyfunc: Pointer auf Funktion oder NOFUNC (=0)
567
//--------------------------------------------------------------
568
void MenuCtrl_SetKey( uint8_t key, const char *keytext, void (*keyfunc)(void) )
569
{
570
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }        // kein aktives Menue
571
 
572
    if( key == KEY_ENTER )
573
    {
574
        menu[midx].key_enter.active     = true;
575
        menu[midx].key_enter.text       = keytext;
576
        menu[midx].key_enter.func       = keyfunc;
577
    }
578
 
579
    if( key == KEY_ENTER_LONG )
580
    {
581
        menu[midx].key_enter_long.active = true;
582
        menu[midx].key_enter_long.text  = keytext;
583
        menu[midx].key_enter_long.func  = keyfunc;
584
    }
585
 
586
    if( key == KEY_ESC )
587
    {
588
        menu[midx].key_esc.active       = true;
589
        menu[midx].key_esc.text         = keytext;
590
        menu[midx].key_esc.func         = keyfunc;
591
    }
592
 
593
    if( key == KEY_ESC_LONG )
594
    {
595
        menu[midx].key_esc_long.active  = true;
596
        menu[midx].key_esc_long.text    = keytext;
597
        menu[midx].key_esc_long.func    = keyfunc;
598
    }
599
}
600
 
601
 
602
//--------------------------------------------------------------
603
// key = MenuCtrl_GetKey()
604
//
605
// Rueckgabe:
606
//   key: z.B. KEY_ENTER oder KEY_ENTER_LONG
607
//--------------------------------------------------------------
608
uint8_t MenuCtrl_GetKey( void )
609
{
610
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return 0; }      // kein aktives Menue
611
 
612
    return menu[midx].lastkey;
613
}
614
 
615
 
616
 
617
//--------------------------------------------------------------
618
// menuindex = MenuCtrl_GetMenuIndex()
619
//
620
// gibt den aktuellen Menuindex zurueck
621
//
622
// Rueckgabe:
623
//   menuindex: <0 = keine Menue (-1)
624
//              =0 = Hauptmenue (Toplevel)
625
//              >0 = Untermenue Level
626
//--------------------------------------------------------------
627
int8_t MenuCtrl_GetMenuIndex( void )
628
{
629
    return midx;
630
}
631
 
632
 
633
 
634
//--------------------------------------------------------------
635
// itemid = MenuCtrl_GetItemId()
636
//
637
// gibt die itemID des aktuell angewaehlten Menuepunktes zurueck
638
//
639
// Rueckgabe:
640
//   itemid:
641
//--------------------------------------------------------------
642
uint8_t MenuCtrl_GetItemId( void )
643
{
644
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return 0; }      // kein aktives Menue
645
 
646
    return menu[midx].item[ menu[midx].active ].id;
647
}
648
 
649
 
650
 
651
//--------------------------------------------------------------
652
// itemid = MenuCtrl_GetItemIdByIndex( index )
653
//
654
// damit koennen die aktuell vorhanden itemID's der Menuepunkte
655
// ermittelt wenn im Menue via SetMove oder SetDelete Menuepunkte
656
// durch den Benutzer verschoben oder geloescht wurden.
657
//
658
// Parameter:
659
//   index: von 0..itemcount-1
660
//--------------------------------------------------------------
661
uint8_t MenuCtrl_GetItemIdByIndex( uint8_t index )
662
{
663
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return 0; }      // kein aktives Menue
664
 
665
    if( (menu[midx].itemcount == 0) || (index > menu[midx].itemcount-1) )   return 0;   // index ausserhalb aktiver Menuepunkte
666
 
667
    return menu[midx].item[ index ].id;
668
}
669
 
670
 
671
 
672
//--------------------------------------------------------------
673
// num = MenuCtrl_GetItemCount()
674
//
675
// gibt die Anzahl der Menuepunkte zurueck
676
//
677
// Rueckgabe:
678
//   num: Anzahl der Menuepunkte
679
//--------------------------------------------------------------
680
uint8_t MenuCtrl_GetItemCount( void )
681
{
682
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return 0; }      // kein aktives Menue
683
 
684
    return menu[midx].itemcount;
685
}
686
 
687
 
688
//--------------------------------------------------------------
689
// textPtr = MenuCtrl_GetItemText()
690
//
691
// gibt einen Pointer auf den Text des aktuellen Menuepunktes zurueck
692
//
693
// ACHTUNG! Der Pointer kann auf RAM oder auch auf PGM zeigen!
694
//
695
// Um herauszufinden auf welchen Bereich der Pointer zeigt kann
696
// MenuCtrl_IsItemTextPGM() verwendet werden.
697
//
698
// Rueckgabe:
699
//   textPtr:  in RAM oder PGM
700
//--------------------------------------------------------------
701
const char * MenuCtrl_GetItemText( void )
702
{
703
    uint8_t lang;
704
 
705
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return 0; }      // kein aktives Menue
706
 
707
    //--------------------------
708
    // Sprache: Multilanguage oder 0 wenn wenn nur ein Text
709
    //--------------------------
710
    lang = (menu[midx].item[ menu[midx].active ].textcount == 1) ? 0 : Config.DisplayLanguage;
711
 
712
    return menu[midx].item[ menu[midx].active ].text[lang];
713
}
714
 
715
 
716
 
717
//--------------------------------------------------------------
718
// isPGM = MenuCtrl_IsItemTextPGM()
719
//
720
// gibt true/false zurueck je nachdem der Text von MenuCtrl_GetItemText()
721
// im Progmem (=true) oder im RAM (=false) ist
722
//
723
// Rueckgabe:
724
//   isPGM: true / false (true = text in PROGMEN; false = text im RAM)
725
//--------------------------------------------------------------
726
uint8_t MenuCtrl_IsItemTextPGM( void )
727
{
728
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return 0; }      // kein aktives Menue
729
 
730
    return menu[midx].item[ menu[midx].active ].textPGM;
731
}
732
 
733
 
734
 
735
//--------------------------------------------------------------
736
// MenuCtrl_ItemSelect( itemid )
737
//
738
// aktiviert einen Menuepunkt / setzt den Menue-Cursor darauf
739
//
740
// die Funktion ist nicht durchgetestet, funktioniert aber
741
// in MKSettings_Menu() / mkparameters.c
742
//
743
// es kann sein das es zu Problemen kommt wenn das Menue
744
// scrollt (mehr als 6 Menueeintraege)
745
//
746
// Parameter:
747
//   itemid: ID des Menuitems
748
//--------------------------------------------------------------
749
void MenuCtrl_ItemSelect( uint8_t itemid )
750
{
751
    int8_t i;
752
 
753
    i = _MenuCtrl_FindItem( itemid );
754
 
755
    if( i >= 0 )
756
    {
757
        menu[midx].active = i;
758
    }
759
}
760
 
761
 
762
//--------------------------------------------------------------
763
// MenuCtrl_ItemActive( itemid, value )
764
//
765
// Parameter:
766
//   itemid: ID des Menuitems
767
//   value : true / false
768
//--------------------------------------------------------------
769
void MenuCtrl_ItemActive( uint8_t itemid, uint8_t value )
770
{
771
    int8_t i;
772
 
773
    i = _MenuCtrl_FindItem( itemid );
774
 
775
    if( i >= 0 )
776
    {
777
        menu[midx].item[i].disabled = !value;
778
    }
779
}
780
 
781
 
782
//--------------------------------------------------------------
783
// MenuCtrl_ItemMark( itemid, value )
784
//
785
// Markiert einen Menueeintrag mit einem '*' am Anfang (Links).
786
// Wird u.a. von BT_SelectDevice() (setup.c) verwendet
787
//
788
// Parameter:
789
//   itemid: ID des Menuitems
790
//   value : true / false
791
//--------------------------------------------------------------
792
void MenuCtrl_ItemMark( uint8_t itemid, uint8_t value )
793
{
794
    int8_t i;
795
 
796
    i = _MenuCtrl_FindItem( itemid );
797
 
798
    if( i >= 0 )
799
    {
800
        menu[midx].item[i].mark = value;
801
    }
802
}
803
 
804
 
805
//--------------------------------------------------------------
806
// MenuCtrl_ItemMarkR( itemid, value )
807
//
808
// Markiert einen Menueeintrag mit einem Haken am ENDE (Rechts).
809
// Wird u.a. von ... (setup.c) verwendet
810
//
811
// Parameter:
812
//   itemid: ID des Menuitems
813
//   value : true / false
814
//--------------------------------------------------------------
815
void MenuCtrl_ItemMarkR( uint8_t itemid, uint8_t value )
816
{
817
    int8_t i;
818
 
819
    i = _MenuCtrl_FindItem( itemid );
820
 
821
    if( i >= 0 )
822
    {
823
        menu[midx].item[i].markR = value;
824
    }
825
}
826
 
827
 
828
//--------------------------------------------------------------
829
// INTERN
830
//
831
// fuer: MenuCtrl_PushML_P(), MenuCtrl_Push()
832
//--------------------------------------------------------------
833
void _MenuCtrl_Push( uint8_t useprogmem, uint8_t numlang, uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), ... )
834
{
835
    va_list ap;
836
    uint8_t idx;
837
    uint8_t i;
838
 
839
    if( midx < 0  )                                 { _MenuCtrl_Error( ERROR_NOMENU );  return; }
840
    if( menu[midx].itemcount >= MENUCTRL_MAXITEMS ) { _MenuCtrl_Error( ERROR_MAXITEM ); return; }
841
    //if( numlang > NUM_LANG )                      { _MenuCtrl_Error( ERROR_MAXLANG ); return; }
842
 
843
    idx = menu[midx].itemcount;
844
 
845
    menu[midx].item[idx].id       = itemid;
846
    menu[midx].item[idx].type     = itemtype;   // MENU_ITEM, MENU_SUB
847
    menu[midx].item[idx].mark     = false;
848
    menu[midx].item[idx].func     = menufunc;
849
    menu[midx].item[idx].textPGM  = useprogmem;
850
    menu[midx].item[idx].textcount= numlang;
851
 
852
    va_start(ap, menufunc);
853
 
854
    for( i=0; i<numlang; i++)
855
    {
856
        menu[midx].item[idx].text[i]  = va_arg( ap, const char *);
857
    }
858
 
859
    va_end(ap);
860
 
861
    menu[midx].itemcount++;
862
}
863
 
864
 
865
//--------------------------------------------------------------
866
// MenuCtrl_PushML2_P( itemid, itemtype, *menufunc, *text_de, *text_en, *text_nl )
867
//
868
// MultiLanguage Texte fuer 2 Sprachen (DE, EN)
869
// PROGMEN Version
870
//
871
// Parameter:
872
//   itemid  : ID des Menueitems
873
//   itemtype: MENU_ITEM oder MENU_SUB (bei MENU_SUB wird noch ein ">" angezeigt)
874
//   menufunc: Pointer auf Funktion oder NOFUNC (=0) wenn keine Funktion
875
//   texte   : alles Zeiger auf PROGMEM
876
//--------------------------------------------------------------
877
void MenuCtrl_PushML2_P( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text_de, const char *text_en )
878
{
879
  //_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
880
    _MenuCtrl_Push( true, NUM_LANG, itemid, itemtype, menufunc, text_de, text_en );
881
}
882
 
883
 
884
//--------------------------------------------------------------
885
// MenuCtrl_PushML2( itemid, itemtype, *menufunc, *text_de, *text_en, *text_nl )
886
//
887
// MultiLanguage Texte fuer 2 Sprachen (DE, EN)
888
// RAM Version
889
//
890
// Parameter:
891
//   itemid  : ID des Menueitems
892
//   itemtype: MENU_ITEM oder MENU_SUB (bei MENU_SUB wird noch ein ">" angezeigt)
893
//   menufunc: Pointer auf Funktion oder NOFUNC (=0) wenn keine Funktion
894
//   texte   : alles Zeiger auf RAM
895
//--------------------------------------------------------------
896
void MenuCtrl_PushML2( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text_de, const char *text_en )
897
{
898
  //_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
899
    _MenuCtrl_Push( false, NUM_LANG, itemid, itemtype, menufunc, text_de, text_en );
900
}
901
 
902
 
903
//--------------------------------------------------------------
904
//--------------------------------------------------------------
905
void MenuCtrl_Push_P( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text )
906
{
907
  //_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
908
    _MenuCtrl_Push( true, 1, itemid, itemtype, menufunc, text );
909
}
910
 
911
 
912
//--------------------------------------------------------------
913
//--------------------------------------------------------------
914
void MenuCtrl_Push( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text )
915
{
916
  //_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
917
    _MenuCtrl_Push( false, 1, itemid, itemtype, menufunc, text );
918
}
919
 
920
 
921
//--------------------------------------------------------------
922
// Spezialfunktion fuer mkparameters.c !
923
//
924
// -> siehe: mkparameters.c / Menu_EditCategory()
925
//
926
// ACHTUNG!
927
// Die externe Variable paramEditItem muss in mkparameters.c
928
// vor Aufruf dieser Funktion richtig initialisiert sein!
929
// Ich habe darauf verzichtet hier nochmal ein find_paramEditItem()
930
// aufzurufen um Speicherplatz zu sparen.
931
//--------------------------------------------------------------
932
void MenuCtrl_PushParamEdit( uint8_t paramID )
933
{
934
  //_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
935
    _MenuCtrl_Push( true, 2, paramID, MENU_PARAMEDIT, NOFUNC, paramEditItem.title_de, paramEditItem.title_en );
936
}
937
 
938
 
939
 
940
//--------------------------------------------------------------
941
// MenuCtrl_PushSeparator()
942
//
943
// fuegt eine Trennlinie im Menue ein
944
// (die itemID ist dabei 0)
945
//--------------------------------------------------------------
946
void MenuCtrl_PushSeparator( void )
947
{
948
  //_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
949
    _MenuCtrl_Push( true, 0, 0, MENU_SEPARATOR, NOFUNC );
950
}
951
 
952
 
953
 
954
//--------------------------------------------------------------
955
// MenuCtrl_PushSeparatorID( itemId )
956
//
957
// fuegt eine Trennlinie im Menue ein mit einer eigenen itemID
958
//--------------------------------------------------------------
959
void MenuCtrl_PushSeparatorID( uint8_t itemid )
960
{
961
  //_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
962
    _MenuCtrl_Push( true, 0, itemid, MENU_SEPARATOR, NOFUNC );
963
}
964
 
965
 
966
 
967
//--------------------------------------------------------------
968
// MenuCtrl_Refresh( mode )
969
//
970
// Parameter:
971
//   mode: MENU_REDRAW || MENU_REFRESH
972
//--------------------------------------------------------------
973
void MenuCtrl_Refresh( uint8_t mode )
974
{
975
    uint8_t y;
976
    uint8_t item;
977
    uint8_t sh;
978
    uint8_t sy;
979
    uint8_t actchar;
980
    uint8_t markchar;
981
    uint8_t markcharR;
982
    uint8_t lang;
983
 
984
    if( midx < 0)   { _MenuCtrl_Error( ERROR_NOMENU ); return; }            // kein Menue vorhanden
985
 
986
    if( mode == MENU_REDRAW )
987
    {
988
        //--------------------------
989
        // Clear
990
        //--------------------------
991
        lcd_frect( 0,  8, 6, 47, 0);                                        // Clear: ganz linke Spalte des Sliders
992
        lcd_frect( 127-2, 0, 2, 63, 0);                                     // Clear: ganz rechts 2 Pixel
993
 
994
        //--------------------------
995
        // Titel
996
        //--------------------------
997
        if( menu[midx].title != 0 )
998
        {
999
            if( showlevel )
1000
            {
1001
                if( menu[midx].titlePGM )
1002
                    lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR("  %19S"), menu[midx].title );
1003
                else
1004
                    lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR("  %19s"), menu[midx].title );
1005
 
1006
                writex_ndigit_number_u( 0, 0, midx, 1, 0, MINVERS, 1,0);    // Menuelevel zeigen
1007
            }
1008
            else
1009
            {
1010
                if( menu[midx].titlePGM )
1011
                    lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR(" %20S"), menu[midx].title );
1012
                else
1013
                    lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR(" %20s"), menu[midx].title );
1014
            }
1015
        }
1016
        else
1017
            lcd_frect( 0, 0, 128, 7, 1);                                       // Titel: Leerzeile
1018
 
1019
 
1020
        //--------------------------
1021
        // Keyline Beschriftung
1022
        //--------------------------
1023
        lcdx_cls_row( 7, MNORMAL, 0);
1024
        PKT_KeylineUpDown( 1, 7,  0,0);
1025
        lcd_printp_at( 12, 7, strGet(KEYLINE4), MNORMAL);
1026
 
1027
 
1028
        // Taste: KEY_ENTER
1029
        if( menu[midx].key_enter.active && menu[midx].key_enter.text != 0 )
1030
        {
1031
            lcdx_printf_at_P( 17, 7, MNORMAL, 0,0 , PSTR("%4S"), menu[midx].key_enter.text );
1032
        }
1033
 
1034
        // Taste: KEY_ESC
1035
        if( menu[midx].key_esc.active && menu[midx].key_esc.text != 0 )
1036
        {
1037
            lcdx_printf_at_P( 12, 7, MNORMAL, 0,0 , PSTR("%5S"), menu[midx].key_esc.text );
1038
        }
1039
    }
1040
 
1041
 
1042
    //--------------------------
1043
    // PKT Batterie Anzeige
1044
    //--------------------------
1045
    if( menu[midx].showbatt )
1046
    {
1047
        show_Lipo();
1048
    }
1049
 
1050
 
1051
    //--------------------------
1052
    // Zeilen
1053
    //--------------------------
1054
    for( y=0; y<6; y++)
1055
    {
1056
        item = y + menu[midx].display_pos;
1057
 
1058
        if( item < menu[midx].itemcount )
1059
        {
1060
            //--------------------------
1061
            // char: aktuelle Auswahl
1062
            //--------------------------
1063
            actchar = ' ';
1064
            if( item == menu[midx].active )
1065
            {
1066
                if( menu[midx].item[item].disabled )    actchar = 0x15;         // aktuelle Auswahl: Pfeil disabled
1067
                else                                    actchar = 0x1d;         // aktuelle Auswahl: Pfeil
1068
            }
1069
 
1070
            //--------------------------
1071
            // char: markiert
1072
            //--------------------------
1073
            markchar = ' ';
1074
            if( menu[midx].item[item].mark ) markchar = '*';
1075
 
1076
            //--------------------------
1077
            // char: markiert RECHTS
1078
            //--------------------------
1079
            markcharR = ' ';
1080
            if( menu[midx].item[item].type == MENU_SUB ) markcharR = 0x1d;
1081
            if( menu[midx].item[item].markR )            markcharR = SYMBOL_CHECK;
1082
 
1083
            //--------------------------
1084
            // Sprache: Multilanguage oder 0 wenn wenn nur ein Text
1085
            //--------------------------
1086
            lang = (menu[midx].item[item].textcount == 1) ? 0 : Config.DisplayLanguage;
1087
 
1088
            //--------------------------
1089
            // Ausgabe: RAM oder PROGMEM
1090
            //--------------------------
1091
            if( MENU_SEPARATOR == menu[midx].item[item].type )
1092
            {
1093
                lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%18S")  , actchar, markchar, PSTR("") );
1094
                lcd_frect( 6*3, ((y+1)*8)+3, 124-(6*3), 0, 1);                                  // Trennlinie
1095
            }
1096
            else if( MENU_PARAMEDIT == menu[midx].item[item].type )
1097
            {
1098
                // SPEZIELL fuer mkparameters.c - zeigt die paramID-Bezeichnung inkl. dem aktuellen WERT an!
1099
                strcpy_P( mkparam_strValueBuffer, PSTR("***"));                                     // Vorbelegung von mkparam_strValueBuffer
1100
                if( !menu[midx].item[item].disabled )                                               // nur wenn Menuepunkt nicht deaktiviert (disabled = paramID nicht vorhanden)
1101
                {                                                                                   //   -> ermittle den aktuellen Wert der paramID fuer Anzeige
1102
                    find_paramEditItem( menu[midx].item[item].id );                                 // paramID suchen (Ergebnis in Variable 'paramEditItem')
1103
                    paramEditItem.editfunc( paramEditItem.paramID, MKPARAM_SHORTVALUE );            // Wert von paramID in mkparam_strValueBuffer darstellen
1104
                }
1105
                lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%14S %3s")  , actchar, markchar, menu[midx].item[item].text[lang], mkparam_strValueBuffer );
1106
            }
1107
            else
1108
            {
1109
                // Anmerkung zu menu[midx].topspace: NUR fuer Menues OHNE scrollen!!
1110
                if( menu[midx].item[item].textPGM )
1111
                {
1112
                    // String im PGM
1113
                    if( menu[midx].item[item].type == MENU_SUB || menu[midx].item[item].markR )
1114
                        lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%16S%c "), actchar, markchar, menu[midx].item[item].text[lang], markcharR );
1115
                    else
1116
                        lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%17S ")  , actchar, markchar, menu[midx].item[item].text[lang] );
1117
                }
1118
                else
1119
                {
1120
                    // String im RAM
1121
                    if( menu[midx].item[item].type == MENU_SUB || menu[midx].item[item].markR )
1122
                        lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%16s%c "), actchar, markchar, menu[midx].item[item].text[lang], markcharR );
1123
                    else
1124
                        lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%17s ")  , actchar, markchar, menu[midx].item[item].text[lang] );
1125
                }
1126
            }
1127
 
1128
        } // end: if( item < menu[midx].itemcount )
1129
 
1130
 
1131
        //--------------------------
1132
        // evtl. Leerzeile loeschen
1133
        //--------------------------
1134
        if( (y < menu[midx].topspace) || (item >= menu[midx].itemcount+menu[midx].topspace) )
1135
        {
1136
            lcd_frect( 6, (y+1)*8, 128-6, 7, 0);                                    // Zeile loeschen
1137
        }
1138
 
1139
    }
1140
 
1141
 
1142
    //--------------------------
1143
    // Slider
1144
    //--------------------------
1145
    #define SLIDERH   45                                                            // Finetuning der Slider-Hoehe
1146
 
1147
    lcd_frect( 0,  8+1, 1, SLIDERH, 0);                                             // Slider: full Clear
1148
 
1149
    if( menu[midx].itemcount > 6 )                                                  // Slider nur bei mehr als 6 Menueitems
1150
    {
1151
        // Slider: 7 zeilen * 8 pixel = 56 pixel
1152
        sh = (SLIDERH * 6) / menu[midx].itemcount;                                  // Slider: Hoehe
1153
        sh = (sh > SLIDERH) ? SLIDERH : sh;
1154
 
1155
        sy = 8+(menu[midx].display_pos * (SLIDERH-sh)) / (menu[midx].itemcount-6);  // Slider: Position
1156
 
1157
        //lcd_frect( 0,  8+1, 1, SLIDERH, 0);                                       // Slider: full Clear    (flackert auf blauen Display!)
1158
        //lcd_frect( 0, 8+1, 1, sy-(8), 0);                                         // Slider: Clear / oben  (nicht mehr notwendig da Aenderung am Refresh)
1159
        //lcd_frect( 0, sy+1+sh+1, 1, SLIDERH-(sh-sy+1), 0);                        // Slider: Clear / unten (nicht mehr notwendig da Aenderung am Refresh)
1160
        lcd_frect( 0, sy+1, 1, sh, 1);                                              // Slider: Draw
1161
    }
1162
}
1163
 
1164
 
1165
 
1166
//--------------------------------------------------------------
1167
// event = MenuCtrl_Control( ctrlmode )
1168
//
1169
// Parameter:
1170
//   ctrlmode: MENUCTRL_EVENT || MENUCTRL_RETURN
1171
//
1172
// Rueckgabe:
1173
//   event: MENUEVENT_NONE || MENUEVENT_ITEM || MENUEVENT_KEY
1174
//--------------------------------------------------------------
1175
uint8_t MenuCtrl_Control( uint8_t ctrlmode )
1176
{
1177
    uint8_t menu_event;
1178
    uint8_t refreshmode;
1179
    uint8_t item;
1180
    uint8_t wahl;
1181
    uint8_t i;
1182
    uint8_t goUp    = false;
1183
    uint8_t goDown  = false;
1184
 
1185
    if( midx < 0)                   { _MenuCtrl_Error( ERROR_NOMENU ); return 0; }              // kein Menue vorhanden
1186
    if( menu[midx].itemcount == 0)  { _MenuCtrl_Error( ERROR_NOITEM ); return 0; }              // kein Menueitem vorhanden
1187
 
1188
 
1189
    // bei MENUCTRL_RETURN muss man ggf. selber fuer ein Redraw sorgen
1190
    // (beim ersten Aufruf wird es jedoch dennoch erzwungen)
1191
    if( ctrlmode == MENUCTRL_EVENT || !menu[midx].firstredraw )
1192
    {
1193
        MenuCtrl_Refresh( MENU_REDRAW );
1194
        menu[midx].firstredraw = true;
1195
    }
1196
 
1197
    clear_key_all();
1198
 
1199
    do
1200
    {
1201
        menu_event         = MENUEVENT_NONE;
1202
        menu[midx].lastkey = KEY_NONE;
1203
        refreshmode        = false;
1204
 
1205
        //--------------------------
1206
        // Pruefe PKT Update oder
1207
        // andere PKT-Aktion
1208
        //--------------------------
1209
        if( PKT_CtrlHook() )                                                                    // Update vom Updatetool angefordert?
1210
        {
1211
            refreshmode = MENU_REDRAW;
1212
        }
1213
 
1214
        //--------------------------
1215
        // PKT Batterie Anzeige
1216
        //--------------------------
1217
        if( menu[midx].showbatt )
1218
        {
1219
            show_Lipo();
1220
        }
1221
 
1222
 
1223
        //--------------------------
1224
        // Cursor: nach oben (UP)
1225
        //--------------------------
1226
        //+++++
1227
        // UP - Verschiebemodus AKTIV
1228
        //+++++
1229
        if( menu[midx].canMove )
1230
        {
1231
            if( get_key_long(1 << KEY_MINUS) )
1232
            {
1233
                if( (menu[midx].active > 0) && (menu[midx].itemcount > 0) )
1234
                {
1235
                    _MenuCtrl_SwapItem( menu[midx].active, menu[midx].active-1 );
1236
                    goUp = true;
1237
                }
1238
                else _MenuCtrl_Beep();                                                           // am oberen Ende angelangt
1239
            }
1240
 
1241
            if( get_key_short(1 << KEY_MINUS) )     // up
1242
            {
1243
                goUp = true;
1244
            }
1245
        }   // end: UP - Verschiebemodus AKTIV
1246
 
1247
 
1248
        //+++++
1249
        // UP - Verschiebemodus NICHT aktiv
1250
        //+++++
1251
        if( !menu[midx].canMove )     // up
1252
        {
1253
            if( get_key_press(1 << KEY_MINUS) || get_key_long_rpt_sp((1 << KEY_MINUS),2) )      // up
1254
            {
1255
                goUp = true;
1256
            }
1257
        }   // end: UP - Verschiebemodus NICHT aktiv
1258
 
1259
 
1260
        //+++++
1261
        // UP - goUp
1262
        //+++++
1263
        if( goUp )     // up
1264
        {
1265
            refreshmode = MENU_REFRESH;
1266
            if( (menu[midx].active > 0)  && (menu[midx].itemcount > 0) )
1267
            {
1268
                menu[midx].active--;
1269
            }
1270
            else if( menu[midx].cycle )
1271
            {
1272
                menu[midx].active = menu[midx].itemcount-1;
1273
            }
1274
            else
1275
            {
1276
                _MenuCtrl_Beep();                                                               // am oberen Ende angelangt
1277
            }
1278
            _MenuCtrl_CalcDisplayPos();
1279
        }
1280
 
1281
 
1282
        //--------------------------
1283
        // Cursor: nach unten (DOWN)
1284
        //--------------------------
1285
        //+++++
1286
        // DOWN - Verschiebemodus AKTIV
1287
        //+++++
1288
        if( menu[midx].canMove )
1289
        {
1290
            if( get_key_long(1 << KEY_PLUS) )
1291
            {
1292
                if( menu[midx].active < menu[midx].itemcount-1 )
1293
                {
1294
                    _MenuCtrl_SwapItem( menu[midx].active, menu[midx].active+1 );
1295
                    goDown = true;
1296
                }
1297
                else _MenuCtrl_Beep();                                                           // am unteren Ende angelangt
1298
            }
1299
 
1300
            if( get_key_short(1 << KEY_PLUS) )     // up
1301
            {
1302
                goDown = true;
1303
            }
1304
        }   // end: DOWN - Verschiebemodus AKTIV
1305
 
1306
 
1307
        //+++++
1308
        // DOWN - Verschiebemodus NICHT aktiv
1309
        //+++++
1310
        if( !menu[midx].canMove )     // up
1311
        {
1312
            if( get_key_press(1 << KEY_PLUS) || get_key_long_rpt_sp((1 << KEY_PLUS),2) )     // up
1313
            {
1314
                goDown = true;
1315
            }
1316
        }   // end: DOWN - Verschiebemodus NICHT aktiv
1317
 
1318
 
1319
        //+++++
1320
        // DOWN - goDown
1321
        //+++++
1322
        if( goDown )     // down
1323
        {
1324
            refreshmode = MENU_REFRESH;
1325
            if( menu[midx].active < menu[midx].itemcount-1 )
1326
            {
1327
                menu[midx].active++;
1328
            }
1329
            else if( menu[midx].cycle )
1330
            {
1331
                menu[midx].active = 0;
1332
            }
1333
            else
1334
            {
1335
                _MenuCtrl_Beep();                                                           // am unteren Ende angelangt
1336
            }
1337
            _MenuCtrl_CalcDisplayPos();
1338
        }
1339
 
1340
 
1341
        //--------------------------
1342
        //--------------------------
1343
        item    = menu[midx].active;
1344
        goUp    = false;
1345
        goDown  = false;
1346
 
1347
 
1348
        //--------------------------
1349
        // KEY_ENTER
1350
        //--------------------------
1351
        if( get_key_short(1 << KEY_ENTER) )
1352
        {
1353
            refreshmode = MENU_REFRESH;
1354
            // todo: keyfunc
1355
            if( menu[midx].item[item].type == MENU_SEPARATOR )
1356
            {
1357
                // do nothing
1358
            }
1359
            else if( menu[midx].item[item].disabled )
1360
            {
1361
                set_beep( 200, 0x00ff, BeepNormal);                             // Beep
1362
                PKT_Popup_P( 200, strGet(STR_MENUCTRL_NOTPOSSIBLE),0,0,0);      // "nicht möglich!"
1363
                refreshmode = MENU_REDRAW;
1364
            }
1365
            else if( menu[midx].item[item].func != NOFUNC )
1366
            {
1367
                menu[midx].item[item].func();
1368
                refreshmode = MENU_REDRAW;
1369
            }
1370
            else if( menu[midx].key_enter.func != NOFUNC )
1371
            {
1372
                menu[midx].key_enter.func();
1373
                refreshmode = MENU_REDRAW;
1374
            }
1375
            else
1376
            {
1377
                menu[midx].lastkey = KEY_ENTER;
1378
                menu_event = MENUEVENT_ITEM;
1379
            }
1380
        }
1381
 
1382
 
1383
        //--------------------------
1384
        // KEY_ENTER_LONG (Deletemodus AKTIV)
1385
        //
1386
        // loescht einen Menueeintrag
1387
        //--------------------------
1388
        if( menu[midx].canDelete && get_key_long(1 << KEY_ENTER) && (menu[midx].itemcount > 0) )
1389
        {
1390
            wahl = 1;
1391
            if( menu[midx].canDelete == 1 )                                     // ==1 -> mit Nachfrage
1392
            {
1393
                set_beep( 200, 0xffff, BeepNormal);                             // Beep
1394
                PKT_Popup_P( 0, strGet(STR_MENUCTRL_DELASK),PSTR(""),0,0);      // "Eintrag entfernen?"
1395
                lcd_printp_at( 12, 7, strGet(YESNO), MINVERS);
1396
 
1397
                wahl = 0;
1398
                while( !wahl )
1399
                {
1400
                    if( get_key_short(1<<KEY_ESC) )   wahl = 1;                 // "Ja"
1401
                    if( get_key_short(1<<KEY_ENTER) ) wahl = 2;                 // "Nein"
1402
                }
1403
                refreshmode = MENU_REDRAW;
1404
            }
1405
 
1406
            if( wahl==1 )
1407
            {
1408
                for( i=menu[midx].active; i<menu[midx].itemcount-1; i++)
1409
                {
1410
                    _MenuCtrl_SwapItem( i, i+1 );
1411
                }
1412
                menu[midx].itemcount--;
1413
 
1414
                if( (menu[midx].display_pos > 0)  &&   (menu[midx].display_pos+6 > menu[midx].itemcount)  )
1415
                {
1416
                    menu[midx].display_pos--;
1417
                    menu[midx].active--;
1418
                }
1419
 
1420
                if( menu[midx].active >= menu[midx].itemcount )
1421
                    menu[midx].active = menu[midx].itemcount-1;
1422
 
1423
                _MenuCtrl_CalcDisplayPos();
1424
                refreshmode = MENU_REDRAW;
1425
 
1426
                if( menu[midx].canDelete == 2 )                                 // ==2 -> direkt loeschen, ohne Nachfrage
1427
                {
1428
                    set_beep( 200, 0xffff, BeepNormal);                         // Beep
1429
                    PKT_Popup_P( 200, strGet(STR_MENUCTRL_DELITEM),0,0,0);      // "Eintrag entfernt!"
1430
                }
1431
            }
1432
        }
1433
 
1434
 
1435
        //--------------------------
1436
        // KEY_ENTER_LONG (NICHT Deletemodus)
1437
        //--------------------------
1438
        if( !menu[midx].canDelete && menu[midx].key_enter_long.active && get_key_long(1 << KEY_ENTER) )
1439
        {
1440
            refreshmode = MENU_REFRESH;
1441
            if( menu[midx].key_enter_long.func != NOFUNC )
1442
            {
1443
                menu[midx].key_enter_long.func();
1444
                refreshmode = MENU_REDRAW;
1445
            }
1446
            else
1447
            {
1448
                menu_event = MENUEVENT_KEY;
1449
                menu[midx].lastkey = KEY_ENTER_LONG;
1450
            }
1451
        }
1452
 
1453
 
1454
        //--------------------------
1455
        // KEY_ESC_LONG
1456
        //--------------------------
1457
        if( menu[midx].key_esc_long.active && get_key_long(1 << KEY_ESC) )
1458
        {
1459
            refreshmode = MENU_REFRESH;
1460
            if( menu[midx].key_esc_long.func != NOFUNC )
1461
            {
1462
                menu[midx].key_esc_long.func();
1463
                refreshmode = MENU_REDRAW;
1464
            }
1465
            else
1466
            {
1467
                menu_event = MENUEVENT_KEY;
1468
                menu[midx].lastkey = KEY_ESC_LONG;
1469
            }
1470
        }
1471
 
1472
 
1473
        //--------------------------
1474
        // KEY_ESC
1475
        //--------------------------
1476
        if( get_key_short(1 << KEY_ESC) )
1477
        {
1478
            refreshmode = MENU_REFRESH;
1479
            if( menu[midx].key_esc.func != NOFUNC )
1480
            {
1481
                menu[midx].key_esc.func();
1482
                refreshmode = MENU_REDRAW;
1483
            }
1484
            else
1485
            {
1486
                menu_event = MENUEVENT_KEY;
1487
                menu[midx].lastkey = KEY_ESC;
1488
            }
1489
        }
1490
 
1491
        if( refreshmode )
1492
        {
1493
            MenuCtrl_Refresh( refreshmode );
1494
            clear_key_all();
1495
        }
1496
    }
1497
    while ( menu_event == MENUEVENT_NONE && ctrlmode == MENUCTRL_EVENT );
1498
 
1499
    return menu_event;
1500
}
1501