menu.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*
  2. menu.c
  3. */
  4. #include "menu.h"
  5. /*================================================*/
  6. void menu_DrawEdgePixel(menu_t *menu, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
  7. {
  8. w--;
  9. h--;
  10. u8g2_DrawPixel(menu->u8g2, x,y);
  11. u8g2_DrawPixel(menu->u8g2, x+w,y);
  12. u8g2_DrawPixel(menu->u8g2, x,y+h);
  13. u8g2_DrawPixel(menu->u8g2, x+w,y+h);
  14. }
  15. void menu_ClearEdgePixel(menu_t *menu, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
  16. {
  17. u8g2_SetDrawColor(menu->u8g2, 0);
  18. menu_DrawEdgePixel(menu, x, y, w, h);
  19. u8g2_SetDrawColor(menu->u8g2, 1);
  20. }
  21. void menu_DrawBoxFocus(menu_t *menu, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
  22. {
  23. u8g2_SetDrawColor(menu->u8g2, 2);
  24. u8g2_DrawBox(menu->u8g2, x, y, w, h);
  25. menu_ClearEdgePixel(menu, x, y, w, h);
  26. }
  27. void menu_DrawFrameFocus(menu_t *menu, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
  28. {
  29. menu_DrawEdgePixel(menu, x, y, w, h);
  30. x--;
  31. y--;
  32. w+=2;
  33. h+=2;
  34. u8g2_DrawFrame(menu->u8g2, x, y, w, h);
  35. menu_ClearEdgePixel(menu, x, y, w, h);
  36. }
  37. /*================================================*/
  38. /* this function must be the last function in the list. it also marks the end of a list */
  39. int me_cb_null(menu_t *menu, const me_t *me, uint8_t msg)
  40. {
  41. return 0;
  42. }
  43. /*
  44. Name: me_cb_wd_toggle
  45. Val: uint8_t *
  46. Arg: Not used
  47. */
  48. int me_cb_big_toggle(menu_t *menu, const me_t *me, uint8_t msg)
  49. {
  50. uint8_t val = *(uint8_t *)(me->val);
  51. u8g2_uint_t x, y, w, h, w2;
  52. w = 16;
  53. w2 = 6;
  54. h = 10;
  55. x = me->x;
  56. y = me->y;
  57. switch(msg)
  58. {
  59. case ME_MSG_IS_FOCUS:
  60. return 1;
  61. case ME_MSG_DRAW_FOCUS:
  62. menu_DrawFrameFocus(menu, x-1, y-1, w+2, h+2);
  63. return 1;
  64. case ME_MSG_SELECT:
  65. {
  66. val++;
  67. if ( val > 1 )
  68. val = 0;
  69. *(uint8_t *)(me->val) = val;
  70. }
  71. return 1;
  72. case ME_MSG_DRAW:
  73. menu_DrawFrameFocus(menu, x+1,y+1,w-2,h-2);
  74. if ( val == 0 )
  75. {
  76. menu_DrawFrameFocus(menu, x+3,y+3,w2-2,h-6);
  77. }
  78. else
  79. {
  80. menu_DrawBoxFocus(menu, x+w/2,y+2,w2,h-4);
  81. }
  82. return 1;
  83. }
  84. return 0;
  85. }
  86. /*
  87. Name: me_cb_wd_toggle
  88. Val: uint8_t *
  89. Arg: char *
  90. */
  91. int me_cb_wd_toggle(menu_t *menu, const me_t *me, uint8_t msg)
  92. {
  93. uint8_t val = *(uint8_t *)(me->val);
  94. u8g2_uint_t x, y, w, h;
  95. u8g2_SetFont(menu->u8g2, MENU_SMALL_FONT);
  96. w = 13;
  97. h = u8g2_GetAscent(menu->u8g2)+2;
  98. x = me->x-2;
  99. y = me->y - u8g2_GetAscent(menu->u8g2)-1;
  100. switch(msg)
  101. {
  102. case ME_MSG_IS_FOCUS:
  103. return 1;
  104. case ME_MSG_DRAW_FOCUS:
  105. menu_DrawFrameFocus(menu, x, y, w, h);
  106. return 1;
  107. case ME_MSG_SELECT:
  108. {
  109. val++;
  110. if ( val > 1 )
  111. val = 0;
  112. *(uint8_t *)(me->val) = val;
  113. }
  114. return 1;
  115. case ME_MSG_DRAW:
  116. u8g2_DrawUTF8(menu->u8g2, me->x, me->y, (const char *)(me->arg));
  117. if ( val > 0 )
  118. {
  119. menu_DrawBoxFocus(menu, x,y,w,h);
  120. }
  121. //u8g2_DrawRFrame(menu->u8g2, x, y, w, h, 1);
  122. return 1;
  123. }
  124. return 0;
  125. }
  126. /*
  127. Name: me_cb_0_9
  128. Val: uint8_t *
  129. */
  130. int me_cb_0_9(menu_t *menu, const me_t *me, uint8_t msg)
  131. {
  132. switch(msg)
  133. {
  134. case ME_MSG_IS_FOCUS:
  135. return 1;
  136. case ME_MSG_DRAW_FOCUS:
  137. menu_DrawBoxFocus(menu,
  138. me->x,
  139. me->y - u8g2_GetAscent(menu->u8g2)-1,
  140. u8g2_GetGlyphWidth(menu->u8g2, '0'),
  141. u8g2_GetAscent(menu->u8g2) + 2);
  142. return 1;
  143. case ME_MSG_SELECT:
  144. {
  145. uint8_t val = *(uint8_t *)(me->val);
  146. val++;
  147. if ( val > 9 )
  148. val = 0;
  149. *(uint8_t *)(me->val) = val;
  150. }
  151. return 1;
  152. case ME_MSG_DRAW:
  153. u8g2_SetFont(menu->u8g2, MENU_BIG_NUM);
  154. u8g2_DrawGlyph(menu->u8g2, me->x, me->y, *(uint8_t *)(me->val) + '0');
  155. return 1;
  156. }
  157. return 0;
  158. }
  159. int me_cb_0_9_ro(menu_t *menu, const me_t *me, uint8_t msg)
  160. {
  161. if ( msg == ME_MSG_IS_FOCUS )
  162. return 0;
  163. return me_cb_0_9(menu, me, msg);
  164. }
  165. /*
  166. Name: me_cb_0_5
  167. Val: uint8_t *
  168. */
  169. int me_cb_0_5(menu_t *menu, const me_t *me, uint8_t msg)
  170. {
  171. switch(msg)
  172. {
  173. case ME_MSG_SELECT:
  174. {
  175. uint8_t val = *(uint8_t *)(me->val);
  176. val++;
  177. if ( val > 5 )
  178. val = 0;
  179. *(uint8_t *)(me->val) = val;
  180. }
  181. return 1;
  182. }
  183. return me_cb_0_9(menu, me, msg);
  184. }
  185. /*
  186. Name: me_cb_0_23
  187. Val: uint8_t *
  188. */
  189. int me_cb_0_23(menu_t *menu, const me_t *me, uint8_t msg)
  190. {
  191. char s[4];
  192. switch(msg)
  193. {
  194. case ME_MSG_IS_FOCUS:
  195. return 1;
  196. case ME_MSG_DRAW_FOCUS:
  197. menu_DrawBoxFocus(menu,
  198. me->x,
  199. me->y - u8g2_GetAscent(menu->u8g2)-1,
  200. u8g2_GetGlyphWidth(menu->u8g2, '0')*2,
  201. u8g2_GetAscent(menu->u8g2) + 2);
  202. return 1;
  203. case ME_MSG_SELECT:
  204. {
  205. uint8_t val = *(uint8_t *)(me->val);
  206. val++;
  207. if ( val > 23 )
  208. val = 0;
  209. *(uint8_t *)(me->val) = val;
  210. }
  211. return 1;
  212. case ME_MSG_DRAW:
  213. u8g2_SetFont(menu->u8g2, MENU_BIG_NUM);
  214. s[0] = *(uint8_t *)(me->val);
  215. s[1] = s[0];
  216. s[1] %= 10;
  217. s[1] += '0';
  218. s[0] /= 10;
  219. s[0] += '0';
  220. s[2] = '\0';
  221. u8g2_DrawUTF8(menu->u8g2, me->x, me->y, s);
  222. return 1;
  223. }
  224. return 0;
  225. }
  226. int me_cb_0_23_ro(menu_t *menu, const me_t *me, uint8_t msg)
  227. {
  228. if ( msg == ME_MSG_IS_FOCUS )
  229. return 0;
  230. return me_cb_0_23(menu, me, msg);
  231. }
  232. /*
  233. Name: me_cb_0_55
  234. Val: uint8_t *
  235. */
  236. int me_cb_0_55(menu_t *menu, const me_t *me, uint8_t msg)
  237. {
  238. switch(msg)
  239. {
  240. case ME_MSG_SELECT:
  241. {
  242. uint8_t val = *(uint8_t *)(me->val);
  243. val+=5;
  244. if ( val > 55 )
  245. val = 0;
  246. *(uint8_t *)(me->val) = val;
  247. }
  248. return 1;
  249. }
  250. return me_cb_0_23(menu, me, msg);
  251. }
  252. /*
  253. Name: me_cb_1_12
  254. Val: uint8_t *
  255. */
  256. int me_cb_1_12(menu_t *menu, const me_t *me, uint8_t msg)
  257. {
  258. switch(msg)
  259. {
  260. case ME_MSG_SELECT:
  261. {
  262. uint8_t val = *(uint8_t *)(me->val);
  263. val++;
  264. if ( val > 12 )
  265. val = 1;
  266. *(uint8_t *)(me->val) = val;
  267. }
  268. return 1;
  269. }
  270. return me_cb_0_23(menu, me, msg);
  271. }
  272. /*
  273. Name: me_cb_1_31
  274. Val: uint8_t *
  275. */
  276. int me_cb_1_31(menu_t *menu, const me_t *me, uint8_t msg)
  277. {
  278. switch(msg)
  279. {
  280. case ME_MSG_SELECT:
  281. {
  282. uint8_t val = *(uint8_t *)(me->val);
  283. val++;
  284. if ( val > 31 )
  285. val = 1;
  286. *(uint8_t *)(me->val) = val;
  287. }
  288. return 1;
  289. }
  290. return me_cb_0_23(menu, me, msg);
  291. }
  292. /*
  293. Name: me_cb_label
  294. can not get focus
  295. Arg: char *
  296. */
  297. int me_cb_num_label(menu_t *menu, const me_t *me, uint8_t msg)
  298. {
  299. switch(msg)
  300. {
  301. case ME_MSG_IS_FOCUS:
  302. case ME_MSG_DRAW_FOCUS:
  303. case ME_MSG_SELECT:
  304. break;
  305. case ME_MSG_DRAW:
  306. u8g2_SetFont(menu->u8g2, MENU_BIG_NUM);
  307. u8g2_DrawUTF8(menu->u8g2, me->x, me->y, (char *)(me->arg) );
  308. return 1;
  309. }
  310. return 0;
  311. }
  312. /*
  313. Name: me_cb_button_full_line
  314. Val: callback function
  315. Arg: char *
  316. */
  317. int me_cb_button_full_line(menu_t *menu, const me_t *me, uint8_t msg)
  318. {
  319. int r = 0;
  320. switch(msg)
  321. {
  322. case ME_MSG_IS_FOCUS:
  323. return 1;
  324. case ME_MSG_DRAW_FOCUS:
  325. menu_DrawBoxFocus(menu,
  326. 0,
  327. me->y - u8g2_GetAscent(menu->u8g2)-1,
  328. u8g2_GetDisplayWidth(menu->u8g2) ,
  329. u8g2_GetAscent(menu->u8g2) - u8g2_GetDescent(menu->u8g2) +1);
  330. r = 1;
  331. break;
  332. case ME_MSG_DRAW:
  333. u8g2_SetFont(menu->u8g2, MENU_NORMAL_FONT);
  334. u8g2_DrawUTF8(menu->u8g2, me->x, me->y, (char *)(me->arg) );
  335. r = 1;
  336. break;
  337. }
  338. /* pass all messages except for the IS_FOCUS also to the callback function */
  339. if ( me->val != NULL )
  340. return ((me_cb)(me->val))(menu, me, msg) | r;
  341. return r;
  342. }
  343. /*
  344. Name: me_cb_button_full_line
  345. Val: callback function
  346. Arg: char *
  347. */
  348. int me_cb_button_half_line(menu_t *menu, const me_t *me, uint8_t msg)
  349. {
  350. int r = 0;
  351. switch(msg)
  352. {
  353. case ME_MSG_IS_FOCUS:
  354. return 1;
  355. case ME_MSG_DRAW_FOCUS:
  356. menu_DrawBoxFocus(menu,
  357. me->x,
  358. me->y - u8g2_GetAscent(menu->u8g2)-1,
  359. u8g2_GetDisplayWidth(menu->u8g2)/2,
  360. u8g2_GetAscent(menu->u8g2) - u8g2_GetDescent(menu->u8g2) +1);
  361. r = 1;
  362. break;
  363. case ME_MSG_DRAW:
  364. u8g2_SetFont(menu->u8g2, MENU_NORMAL_FONT);
  365. u8g2_DrawUTF8(menu->u8g2, me->x+4, me->y, (char *)(me->arg) );
  366. r = 1;
  367. break;
  368. }
  369. /* pass all messages except for the IS_FOCUS also to the callback function */
  370. if ( me->val != NULL )
  371. return ((me_cb)(me->val))(menu, me, msg) | r;
  372. return r;
  373. }
  374. /*
  375. Name: me_cb_button_empty
  376. Val: callback function
  377. Arg: not used
  378. */
  379. int me_cb_button_empty(menu_t *menu, const me_t *me, uint8_t msg)
  380. {
  381. if ( msg == ME_MSG_IS_FOCUS )
  382. return 1;
  383. if ( me->val != NULL )
  384. return ((me_cb)(me->val))(menu, me, msg);
  385. return 0;
  386. }
  387. /*
  388. Name: me_cb_label
  389. can not get focus
  390. Arg: char *
  391. */
  392. int me_cb_label(menu_t *menu, const me_t *me, uint8_t msg)
  393. {
  394. switch(msg)
  395. {
  396. case ME_MSG_IS_FOCUS:
  397. case ME_MSG_DRAW_FOCUS:
  398. case ME_MSG_SELECT:
  399. break;
  400. case ME_MSG_DRAW:
  401. u8g2_SetFont(menu->u8g2, MENU_NORMAL_FONT);
  402. u8g2_DrawUTF8(menu->u8g2, me->x, me->y, (char *)(me->arg) );
  403. return 1;
  404. }
  405. return 0;
  406. }
  407. /*
  408. Name: me_cb_button_full_line
  409. Val: callback function
  410. Arg: bitmap
  411. */
  412. int me_cb_16x16_bitmap_button(menu_t *menu, const me_t *me, uint8_t msg)
  413. {
  414. int r = 0;
  415. switch(msg)
  416. {
  417. case ME_MSG_IS_FOCUS:
  418. return 1;
  419. case ME_MSG_DRAW_FOCUS:
  420. menu_DrawFrameFocus(menu,
  421. me->x-1,
  422. me->y-1,
  423. 16+2,
  424. 16+2);
  425. r = 1;
  426. break;
  427. case ME_MSG_DRAW:
  428. u8g2_DrawXBM(menu->u8g2, me->x, me->y, 16, 16, (const uint8_t *)(me->arg));
  429. r = 1;
  430. break;
  431. }
  432. /* pass all messages except for the IS_FOCUS also to the callback function */
  433. if ( me->val != NULL )
  434. return ((me_cb)(me->val))(menu, me, msg) | r;
  435. return r;
  436. }
  437. /*================================================*/
  438. /* call menu element from menu->current_index */
  439. int menu_CallME(menu_t *menu, uint8_t msg)
  440. {
  441. const me_t *me;
  442. me = menu->me_list+menu->current_index;
  443. return me->cb(menu, me, msg);
  444. }
  445. /* stay on current focus if valid, move to next valid focus */
  446. static void menu_CalcNextValidFocus(menu_t *menu) U8G2_NOINLINE;
  447. static void menu_CalcNextValidFocus(menu_t *menu)
  448. {
  449. for(;;)
  450. {
  451. menu->current_index = menu->focus_index;
  452. if ( menu->current_index >= menu->me_count )
  453. break;
  454. if ( menu_CallME(menu, ME_MSG_IS_FOCUS) != 0 )
  455. break;
  456. menu->focus_index++;
  457. }
  458. }
  459. /* advance current focus to the next element */
  460. void menu_NextFocus(menu_t *menu)
  461. {
  462. menu->focus_index++;
  463. if ( menu->focus_index >= menu->me_count )
  464. menu->focus_index = 0;
  465. menu_CalcNextValidFocus(menu);
  466. }
  467. /* send select message to the element which has the current focus */
  468. void menu_Select(menu_t *menu)
  469. {
  470. menu->current_index = menu->focus_index;
  471. menu_CallME(menu, ME_MSG_SELECT);
  472. }
  473. void menu_SetMEList(menu_t *menu, const me_t *me_list, uint16_t initial_focus)
  474. {
  475. menu->me_list = me_list;
  476. menu->me_count = 0;
  477. while( me_list[menu->me_count].cb != me_cb_null )
  478. menu->me_count++;
  479. menu->focus_index = 0;
  480. menu_CalcNextValidFocus(menu);
  481. while( initial_focus > 0 )
  482. {
  483. menu_NextFocus(menu);
  484. initial_focus--;
  485. }
  486. menu->radio_index = menu->me_count;
  487. }
  488. me_t melist_emty[] =
  489. {
  490. { me_cb_null, NULL, 0, 0 }
  491. };
  492. void menu_Init(menu_t *menu, u8g2_t *u8g2)
  493. {
  494. menu->u8g2 = u8g2;
  495. menu_SetMEList(menu, melist_emty, 0);
  496. }
  497. void menu_Draw(menu_t *menu)
  498. {
  499. for( menu->current_index = 0; menu->current_index < menu->me_count; menu->current_index++ )
  500. {
  501. menu_CallME(menu, ME_MSG_DRAW);
  502. if ( menu->current_index == menu->focus_index )
  503. {
  504. menu_CallME(menu, ME_MSG_DRAW_FOCUS);
  505. }
  506. }
  507. u8g2_DrawHLine(menu->u8g2, 0, 32, 128);
  508. }