LCDGFX LCD display driver  1.2.0
Lightweight graphics library for SSD1306, SSD1325, SSD1327, SSD1331, SSD1351, SH1106, SH1107, IL9163, ST7735, ST7789, ILI9341, PCD8544 displays over I2C/SPI
menu.h
Go to the documentation of this file.
1 /*
2  MIT License
3 
4  Copyright (c) 2020,2022, Alexey Dynda
5 
6  Permission is hereby granted, free of charge, to any person obtaining a copy
7  of this software and associated documentation files (the "Software"), to deal
8  in the Software without restriction, including without limitation the rights
9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  copies of the Software, and to permit persons to whom the Software is
11  furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in all
14  copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  SOFTWARE.
23 */
28 #ifndef _LCDGFX_MENU_H_
29 #define _LCDGFX_MENU_H_
30 
31 #include "nano_gfx_types.h"
32 #include "canvas/point.h"
33 #include "canvas/rect.h"
34 #include "canvas/font.h"
35 
36 #ifndef lcd_gfx_min
37 
38 #define lcd_gfx_min(x, y) ((x) < (y) ? (x) : (y))
39 #endif
40 
41 #ifndef lcd_gfx_max
42 
43 #define lcd_gfx_max(x, y) ((x) > (y) ? (x) : (y))
44 #endif
45 
55 {
56 public:
66  LcdGfxMenu(const char **items, uint8_t count, const NanoRect &rect = {});
67 
74  template <typename D> void show(D &d);
75 
81  void down();
82 
88  void up();
89 
94  uint8_t selection();
95 
96  void setSelection(uint8_t s);
97 
103  void setRect(const NanoRect &rect = {});
104 
108  uint8_t size();
109 
113  template <typename D> void updateSize(D &d)
114  {
115  if ( !menu.width )
116  {
117  menu.width = d.width() - menu.left;
118  }
119  if ( !menu.height )
120  {
121  menu.height = d.height() - menu.top;
122  }
123  }
124 
125 private:
126  SAppMenu menu;
127 
128  template <typename D> uint8_t getMaxScreenItems(D &d)
129  {
130  return (menu.height - 16) / d.getFont().getHeader().height;
131  }
132 
133  template <typename D> uint8_t calculateScrollPosition(D &d, uint8_t selection)
134  {
135  if ( selection < menu.scrollPosition )
136  {
137  return selection;
138  }
139  else if ( selection - menu.scrollPosition > getMaxScreenItems(d) - 1 )
140  {
141  return selection - getMaxScreenItems(d) + 1;
142  }
143  return menu.scrollPosition;
144  }
145 
146  template <typename D> void drawMenuItem(D &d, uint8_t index)
147  {
148  if ( index == menu.selection )
149  {
150  d.invertColors();
151  }
152  lcdint_t item_top = 8 + menu.top + (index - menu.scrollPosition) * d.getFont().getHeader().height;
153  uint16_t color = d.getColor();
154  d.setColor(0x0000);
155  d.fillRect(menu.left + 8 + d.getFont().getTextSize(menu.items[index]), item_top, menu.width + menu.left - 9,
156  item_top + d.getFont().getHeader().height - 1);
157  d.setColor(color);
158  d.printFixed(menu.left + 8, item_top, menu.items[index], STYLE_NORMAL);
159  if ( index == menu.selection )
160  {
161  d.invertColors();
162  }
163  }
164 
165  template <typename D> void drawScrollIndicators(D &d, uint8_t maxItems)
166  {
167  uint16_t color = d.getColor();
168  lcdint_t borderTop = 4 + menu.top;
169  lcdint_t borderBot = menu.height + menu.top - 5;
170  lcdint_t itemsTop = 8 + menu.top;
171  lcdint_t itemsBot = itemsTop + maxItems * d.getFont().getHeader().height;
172  lcdint_t cx = menu.left + menu.width / 2;
173 
174  // Clear and draw up arrow area
175  d.setColor(0x0000);
176  d.fillRect(5 + menu.left, borderTop + 1, menu.width + menu.left - 6, itemsTop - 1);
177  if ( menu.scrollPosition > 0 )
178  {
179  d.setColor(color);
180  d.drawHLine(cx, borderTop + 1, cx);
181  d.drawHLine(cx - 1, borderTop + 2, cx + 1);
182  d.drawHLine(cx - 2, borderTop + 3, cx + 2);
183  }
184 
185  // Clear and draw down arrow area
186  d.setColor(0x0000);
187  d.fillRect(5 + menu.left, itemsBot, menu.width + menu.left - 6, borderBot - 1);
188  if ( menu.scrollPosition + maxItems < menu.count )
189  {
190  d.setColor(color);
191  d.drawHLine(cx - 2, borderBot - 3, cx + 2);
192  d.drawHLine(cx - 1, borderBot - 2, cx + 1);
193  d.drawHLine(cx, borderBot - 1, cx);
194  }
195 
196  // Scrollbar track on right edge
197  lcdint_t sbX = menu.width + menu.left - 8;
198  lcdint_t sbH = itemsBot - itemsTop - 1;
199  if ( sbH > 4 )
200  {
201  lcdint_t thumbH = lcd_gfx_max((lcdint_t)2, (lcdint_t)(sbH * maxItems / menu.count));
202  lcdint_t maxScroll = menu.count - maxItems;
203  lcdint_t thumbY = itemsTop;
204  if ( maxScroll > 0 )
205  {
206  thumbY = itemsTop + (lcdint_t)((long)(sbH - thumbH) * menu.scrollPosition / maxScroll);
207  }
208  // Clear track area then draw thumb
209  d.setColor(0x0000);
210  d.fillRect(sbX, itemsTop, sbX + 1, itemsTop + sbH);
211  d.setColor(color);
212  d.fillRect(sbX, thumbY, sbX + 1, thumbY + thumbH);
213  }
214  d.setColor(color);
215  }
216 };
217 
218 template <typename D> void LcdGfxMenu::show(D &d)
219 {
220  updateSize(d);
221  d.drawRect(4 + menu.left, 4 + menu.top, menu.width + menu.left - 5, menu.height + menu.top - 5);
222  menu.scrollPosition = this->calculateScrollPosition(d, menu.selection);
223  uint8_t maxItems = getMaxScreenItems(d);
224  for ( uint8_t i = menu.scrollPosition; i < lcd_gfx_min(menu.count, (menu.scrollPosition + maxItems)); i++ )
225  {
226  this->drawMenuItem(d, i);
227  }
228  menu.oldSelection = menu.selection;
229  if ( menu.count > maxItems )
230  {
231  this->drawScrollIndicators(d, maxItems);
232  }
233 }
234 
239 #endif
lcdint_t left
left offset
Definition: canvas_types.h:167
NanoRect structure describes rectangle area.
Definition: rect.h:42
#define lcd_gfx_min(x, y)
Custom min function.
Definition: menu.h:38
Point class.
int8_t lcdint_t
internal int type, used by the library.
Definition: canvas_types.h:77
LcdGfxMenu(const char **items, uint8_t count, const NanoRect &rect={})
Creates menu object with the provided list of menu items.
lcduint_t width
width of menu
Definition: canvas_types.h:169
void up()
Moves selection pointer up by 1 item.
Rectangle class.
lcduint_t height
height of menu
Definition: canvas_types.h:171
void updateSize(D &d)
Updates size of the object, if it was not set previously.
Definition: menu.h:113
void show(D &d)
Shows menu items on the display.
Definition: menu.h:218
uint8_t size()
Returns total count of menu items in menu.
Basic structures of nano gfx library.
uint8_t selection()
Returns currently selected menu item.
uint8_t selection
currently selected item. Internally updated.
Definition: canvas_types.h:159
uint8_t scrollPosition
position of menu scrolling. Internally updated
Definition: canvas_types.h:163
#define lcd_gfx_max(x, y)
Custom max function.
Definition: menu.h:43
uint8_t count
count of menu items in the menu
Definition: canvas_types.h:157
void down()
Moves selection pointer down by 1 item.
Class implements menu objects for lcdgfx library.
Definition: menu.h:54
void setRect(const NanoRect &rect={})
Sets rect area for the menu.
Describes menu object.
Definition: canvas_types.h:152
lcdint_t top
top offset
Definition: canvas_types.h:165
Font class.
uint8_t oldSelection
selected item, when last redraw operation was performed. Internally updated.
Definition: canvas_types.h:161
const char ** items
list of menu items of the menu
Definition: canvas_types.h:155