u8g2_selection_list.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. u8g2_selection_list.c
  3. selection list with scroll option
  4. Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
  5. Copyright (c) 2016, olikraus@gmail.com
  6. All rights reserved.
  7. Redistribution and use in source and binary forms, with or without modification,
  8. are permitted provided that the following conditions are met:
  9. * Redistributions of source code must retain the above copyright notice, this list
  10. of conditions and the following disclaimer.
  11. * Redistributions in binary form must reproduce the above copyright notice, this
  12. list of conditions and the following disclaimer in the documentation and/or other
  13. materials provided with the distribution.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  15. CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  16. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  17. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  19. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  24. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  26. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "u8g2.h"
  29. #define MY_BORDER_SIZE 1
  30. /*
  31. Draw a string at x,y
  32. Center string within w (left adjust if w < pixel len of s)
  33. Side effects:
  34. u8g2_SetFontDirection(u8g2, 0);
  35. u8g2_SetFontPosBaseline(u8g2);
  36. */
  37. void u8g2_DrawUTF8Line(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, const char *s, uint8_t border_size, uint8_t is_invert)
  38. {
  39. u8g2_uint_t d, str_width;
  40. u8g2_uint_t fx, fy, fw, fh;
  41. /* only horizontal strings are supported, so force this here */
  42. u8g2_SetFontDirection(u8g2, 0);
  43. /* revert y position back to baseline ref */
  44. y += u8g2->font_calc_vref(u8g2);
  45. /* calculate the width of the string in pixel */
  46. str_width = u8g2_GetUTF8Width(u8g2, s);
  47. /* calculate delta d within the box */
  48. d = 0;
  49. if ( str_width < w )
  50. {
  51. d = w;
  52. d -=str_width;
  53. d /= 2;
  54. }
  55. else
  56. {
  57. w = str_width;
  58. }
  59. /* caluclate text box */
  60. fx = x;
  61. fy = y - u8g2_GetAscent(u8g2) ;
  62. fw = w;
  63. fh = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2) ;
  64. /* draw the box, if inverted */
  65. u8g2_SetDrawColor(u8g2, 1);
  66. if ( is_invert )
  67. {
  68. u8g2_DrawBox(u8g2, fx, fy, fw, fh);
  69. }
  70. /* draw the frame */
  71. while( border_size > 0 )
  72. {
  73. fx--;
  74. fy--;
  75. fw +=2;
  76. fh +=2;
  77. u8g2_DrawFrame(u8g2, fx, fy, fw, fh );
  78. border_size--;
  79. }
  80. if ( is_invert )
  81. {
  82. u8g2_SetDrawColor(u8g2, 0);
  83. }
  84. else
  85. {
  86. u8g2_SetDrawColor(u8g2, 1);
  87. }
  88. /* draw the text */
  89. u8g2_DrawUTF8(u8g2, x+d, y, s);
  90. /* revert draw color */
  91. u8g2_SetDrawColor(u8g2, 1);
  92. }
  93. /*
  94. draw several lines at position x,y.
  95. lines are stored in s and must be separated with '\n'.
  96. lines can be centered with respect to "w"
  97. if s == NULL nothing is drawn and 0 is returned
  98. returns the number of lines in s multiplied with line_height
  99. */
  100. u8g2_uint_t u8g2_DrawUTF8Lines(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t line_height, const char *s)
  101. {
  102. uint8_t i;
  103. uint8_t cnt;
  104. u8g2_uint_t yy = 0;
  105. cnt = u8x8_GetStringLineCnt(s);
  106. //printf("str=%s\n", s);
  107. //printf("cnt=%d, y=%d, line_height=%d\n", cnt, y, line_height);
  108. for( i = 0; i < cnt; i++ )
  109. {
  110. //printf(" i=%d, y=%d, line_height=%d\n", i, y, line_height);
  111. u8g2_DrawUTF8Line(u8g2, x, y, w, u8x8_GetStringLineStart(i, s), 0, 0);
  112. y+=line_height;
  113. yy+=line_height;
  114. }
  115. return yy;
  116. }
  117. /*
  118. selection list with string line
  119. returns line height
  120. */
  121. static u8g2_uint_t u8g2_draw_selection_list_line(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, uint8_t idx, const char *s) U8G2_NOINLINE;
  122. static u8g2_uint_t u8g2_draw_selection_list_line(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, uint8_t idx, const char *s)
  123. {
  124. //u8g2_uint_t yy;
  125. uint8_t border_size = 0;
  126. uint8_t is_invert = 0;
  127. u8g2_uint_t line_height = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2)+MY_BORDER_SIZE;
  128. /* calculate offset from display upper border */
  129. //yy = idx;
  130. //yy -= u8sl->first_pos;
  131. //yy *= line_height;
  132. //yy += y;
  133. /* check whether this is the current cursor line */
  134. if ( idx == u8sl->current_pos )
  135. {
  136. border_size = MY_BORDER_SIZE;
  137. is_invert = 1;
  138. }
  139. /* get the line from the array */
  140. s = u8x8_GetStringLineStart(idx, s);
  141. /* draw the line */
  142. if ( s == NULL )
  143. s = "";
  144. u8g2_DrawUTF8Line(u8g2, MY_BORDER_SIZE, y, u8g2_GetDisplayWidth(u8g2)-2*MY_BORDER_SIZE, s, border_size, is_invert);
  145. return line_height;
  146. }
  147. void u8g2_DrawSelectionList(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, const char *s)
  148. {
  149. uint8_t i;
  150. for( i = 0; i < u8sl->visible; i++ )
  151. {
  152. y += u8g2_draw_selection_list_line(u8g2, u8sl, y, i+u8sl->first_pos, s);
  153. }
  154. }
  155. /*
  156. title: NULL for no title, valid str for title line. Can contain mutliple lines, separated by '\n'
  157. start_pos: default position for the cursor, first line is 1.
  158. sl: string list (list of strings separated by \n)
  159. returns 0 if user has pressed the home key
  160. returns the selected line if user has pressed the select key
  161. side effects:
  162. u8g2_SetFontDirection(u8g2, 0);
  163. u8g2_SetFontPosBaseline(u8g2);
  164. */
  165. uint8_t u8g2_UserInterfaceSelectionList(u8g2_t *u8g2, const char *title, uint8_t start_pos, const char *sl)
  166. {
  167. u8sl_t u8sl;
  168. u8g2_uint_t yy;
  169. uint8_t event;
  170. u8g2_uint_t line_height = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2)+MY_BORDER_SIZE;
  171. uint8_t title_lines = u8x8_GetStringLineCnt(title);
  172. uint8_t display_lines;
  173. if ( start_pos > 0 ) /* issue 112 */
  174. start_pos--; /* issue 112 */
  175. if ( title_lines > 0 )
  176. {
  177. display_lines = (u8g2_GetDisplayHeight(u8g2)-3) / line_height;
  178. u8sl.visible = display_lines;
  179. u8sl.visible -= title_lines;
  180. }
  181. else
  182. {
  183. display_lines = u8g2_GetDisplayHeight(u8g2) / line_height;
  184. u8sl.visible = display_lines;
  185. }
  186. u8sl.total = u8x8_GetStringLineCnt(sl);
  187. u8sl.first_pos = 0;
  188. u8sl.current_pos = start_pos;
  189. if ( u8sl.current_pos >= u8sl.total )
  190. u8sl.current_pos = u8sl.total-1;
  191. if ( u8sl.first_pos+u8sl.visible <= u8sl.current_pos )
  192. u8sl.first_pos = u8sl.current_pos-u8sl.visible+1;
  193. u8g2_SetFontPosBaseline(u8g2);
  194. for(;;)
  195. {
  196. u8g2_FirstPage(u8g2);
  197. do
  198. {
  199. yy = u8g2_GetAscent(u8g2);
  200. if ( title_lines > 0 )
  201. {
  202. yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title);
  203. u8g2_DrawHLine(u8g2, 0, yy-line_height- u8g2_GetDescent(u8g2) + 1, u8g2_GetDisplayWidth(u8g2));
  204. yy += 3;
  205. }
  206. u8g2_DrawSelectionList(u8g2, &u8sl, yy, sl);
  207. } while( u8g2_NextPage(u8g2) );
  208. #ifdef U8G2_REF_MAN_PIC
  209. return 0;
  210. #endif
  211. for(;;)
  212. {
  213. event = u8x8_GetMenuEvent(u8g2_GetU8x8(u8g2));
  214. if ( event == U8X8_MSG_GPIO_MENU_SELECT )
  215. return u8sl.current_pos+1; /* +1, issue 112 */
  216. else if ( event == U8X8_MSG_GPIO_MENU_HOME )
  217. return 0; /* issue 112: return 0 instead of start_pos */
  218. else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_DOWN )
  219. {
  220. u8sl_Next(&u8sl);
  221. break;
  222. }
  223. else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_UP )
  224. {
  225. u8sl_Prev(&u8sl);
  226. break;
  227. }
  228. }
  229. }
  230. }