CheeseBoard
A library for use with the CheeseBoard Cheddar platform
GfxStringListBox.cpp
1 #include <MutilaDebug.h>
2 #include "GfxStringListBox.h"
3 #include "GfxTextBox.h"
4 #include "CheeseboardConfig.h"
5 
6 GfxStringListBox::GfxStringListBox(uint16_t width) :
7  _width(width),
8  _lineHeight(CBOLED_MESSAGE_FONT_HEIGHT + (2*CBOLED_MESSAGE_FONT_VSEP)),
9  _selected(-1)
10 {
11  for(uint8_t i=0; i<MaxItems; i++) {
12  _items[i] = NULL;
13  }
14 
15  // TODO: calculate screen lines based on line height and screen size
16  // as ooposed to this hard-coded value
17  _screenLines = 4;
18  _screenStart = 0;
19 }
20 
21 GfxStringListBox::~GfxStringListBox()
22 {
23  for(uint8_t i=0; i<MaxItems; i++) {
24  if (_items[i] != NULL) {
25  delete _items[i];
26  _items[i] = NULL;
27  }
28  }
29 }
30 
31 int16_t GfxStringListBox::add(const String s)
32 {
33  int16_t i = findGap();
34  if (i >= 0) {
35  _items[i] = new String(s);
36  return true;
37  } else {
38  return false;
39  }
40 }
41 
42 bool GfxStringListBox::remove(const uint8_t idx, bool compactAfter)
43 {
44  if (idx >= 0 && idx <MaxItems && _items[idx] != NULL) {
45  delete _items[idx];
46  _items[idx] = NULL;
47 
48  // remove selection
49  if (_selected == idx) {
50  _selected = -1;
51  }
52 
53  // compact if requested
54  if (compactAfter) {
55  compact();
56  }
57  return true;
58  } else {
59  return false;
60  }
61 }
62 
63 void GfxStringListBox::draw(uint16_t xOffset, uint16_t yOffset)
64 {
65  DBLN(F("GfxStringListBox::draw"));
66  uint8_t drawn = 0;
67  for(uint8_t i=0; i<MaxItems && drawn<_screenLines; i++) {
68  if (_items[i] != NULL) {
69  if (isOnScreen(i)) {
70  GfxTextBox tb(_width, *_items[i], selected() == i);
71  tb.draw(xOffset, yOffset+(tb.height()*drawn));
72  drawn++;
73  }
74  }
75  }
76 }
77 
79 {
80  return _width;
81 }
82 
84 {
85  return _lineHeight * _screenLines;
86 }
87 
88 int16_t GfxStringListBox::findGap(uint8_t startAt)
89 {
90  uint8_t i;
91  for(i=startAt; i<MaxItems && _items[i] != NULL; i++) {;}
92  if (i<MaxItems) {
93  return i;
94  } else {
95  return -1;
96  }
97 }
98 
99 int16_t GfxStringListBox::findNext(uint8_t from)
100 {
101  for(uint8_t i=from+1; i<MaxItems; i++) {
102  if (_items[i] != NULL) {
103  return i;
104  }
105  }
106  return -1;
107 }
108 
109 int16_t GfxStringListBox::findPreceding(uint8_t from)
110 {
111  if (from == 0 || from >= MaxItems) {
112  return -1;
113  }
114 
115  for(uint8_t i=from-1; i>=0; i--) {
116  if (_items[i] != NULL) {
117  return i;
118  }
119  }
120  return -1;
121 }
122 
123 int16_t GfxStringListBox::find(const String s, uint8_t n)
124 {
125  uint8_t i;
126  for(i=0; i<MaxItems; i++) {
127  if (*_items[i] == s) {
128  if (n-- == 1) {
129  return i;
130  }
131  }
132  }
133  return -1;
134 }
135 
137 // TODO: void GfxStringListBox::sort();
138 
140 {
141  int16_t gap = findGap();
142  if (gap >= 0) {
143  for (uint8_t i=gap+1; i<MaxItems; i++) {
144  if (_items[i] != NULL) {
145  return false;
146  }
147  }
148  }
149  return true;
150 }
151 
154 {
155  while (!isCompacted()) {
156  int16_t gap = findGap();
157  if (gap >= 0) {
158  for(uint8_t i=gap; i<MaxItems-1; i++) {
159  _items[i] = _items[i+1];
160  if (i+1 == _selected) {
161  _selected = i;
162  }
163  }
164  _items[MaxItems-1] = NULL;
165  }
166  }
167 }
168 
169 bool GfxStringListBox::select(int16_t idx)
170 {
171  if (idx >= MaxItems || !(idx == -1 || _items[idx] != NULL)) {
172  return false;
173  } else {
174  _selected = idx;
175  return true;
176  return false;
177  }
178 }
179 
182 {
183  return _selected;
184 }
185 
187 {
188  uint8_t lines = _screenLines;
189  for (uint8_t i=_screenStart; i<MaxItems && lines>0; i++) {
190  if (i == idx) {
191  return true;
192  }
193  if (_items[i] != NULL) {
194  lines--;
195  }
196  }
197  return false;
198 }
199 
200 uint8_t GfxStringListBox::rowsFrom(uint8_t idx)
201 {
202  uint8_t count = 0;
203  for (uint8_t i=idx; i<MaxItems; i++) {
204  if (_items[i] != NULL) {
205  count++;
206  }
207  }
208  return count;
209 }
210 
211 uint8_t GfxStringListBox::scrollDown(uint8_t rows)
212 {
213  uint8_t scrolled = 0;
214  while(rows > 0) {
215  int16_t nextItem = findNext(_screenStart);
216  if (nextItem == -1) {
217  return scrolled;
218  }
219  if (rowsFrom(nextItem) < _screenLines) {
220  return scrolled;
221  } else {
222  _screenStart = nextItem;
223  scrolled++;
224  }
225  rows--;
226  }
227  return scrolled;
228 }
229 
230 uint8_t GfxStringListBox::scrollUp(uint8_t rows)
231 {
232  uint8_t scrolled = 0;
233  while(rows > 0) {
234  int16_t preItem = findPreceding(_screenStart);
235  if (preItem == -1) {
236  return scrolled;
237  }
238  _screenStart = preItem;
239  scrolled++;
240  rows--;
241  }
242  return scrolled;
243 }
244 
245 bool GfxStringListBox::scrollTo(uint8_t idx)
246 {
247  if (_items[idx] == NULL || idx > MaxItems) {
248  return false;
249  }
250 
251  if (idx < _screenStart) {
252  // Ohhhh... I feel like I'm tempting an infinite loop here
253  while(!isOnScreen(idx)) {
254  scrollUp(1);
255  }
256  } else {
257  while(!isOnScreen(idx)) {
258  // Ohhhh... I feel like I'm tempting an infinite loop here
259  scrollDown(1);
260  }
261  }
262 }
263 
264 
265 
void compact()
Make used items contiguous (remove gaps)
uint8_t rowsFrom(uint8_t idx)
bool isOnScreen(uint8_t idx)
void compact()
Make used items contiguous (remove gaps)
int16_t findPreceding(uint8_t from=MaxItems)
uint8_t scrollUp(uint8_t rows)
int16_t add(const String s)
uint8_t scrollDown(uint8_t rows)
bool remove(const uint8_t idx, bool compactAfter=true)
int16_t findGap(uint8_t startAt=0)
int16_t findGap(uint8_t startAt=0)
int16_t findNext(uint8_t from=0)
void draw(uint16_t xOffset=0, uint16_t yOffset=0)
bool isCompacted()
Sort the items contained in the list box using quicksort.
bool select(int16_t idx)
int16_t find(const String s, uint8_t n=1)
uint8_t scrollUp(uint8_t rows)
uint8_t rowsFrom(uint8_t idx)
uint16_t height()
Definition: GfxTextBox.cpp:38
uint8_t scrollDown(uint8_t rows)
int16_t findNext(uint8_t from=0)
bool isOnScreen(uint8_t idx)
bool scrollTo(uint8_t idx)
bool isCompacted()
Sort the items contained in the list box using quicksort.
int16_t findPreceding(uint8_t from=MaxItems)
void draw(uint16_t xOffset=0, uint16_t yOffset=0)
Definition: GfxTextBox.cpp:12