Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ComboList.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: nGenEx.lib
6  FILE: ComboList.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Drop-down list of Buttons class
13 */
14 
15 #include "MemDebug.h"
16 #include "ComboList.h"
17 #include "ComboBox.h"
18 #include "Button.h"
19 #include "Video.h"
20 #include "Bitmap.h"
21 #include "Font.h"
22 #include "Screen.h"
23 
24 // +--------------------------------------------------------------------+
25 
26 ComboList::ComboList(ComboBox* ctrl, ActiveWindow* p, int ax, int ay, int aw, int ah, int maxentries)
27 : ScrollWindow(p, ax, ay, aw, ah + (ah-2)*maxentries + 2, 0, 0, p), combo_box(ctrl)
28 {
29  button_state = 0;
30  button_height = ah;
31  captured = 0;
32  seln = -1;
33  max_entries = maxentries;
34  scroll = 0;
35  scrolling = false;
36  border = true;
37  animated = true;
38  bevel_width = 5;
39 
40  if (ctrl)
41  CopyStyle(*ctrl);
42 
43  rect.h = (ah-2)*maxentries + 2;
44 
45  int screen_height = Video::GetInstance()->Height();
46 
47  if (rect.h > screen_height) {
48  rect.y = 0;
49  rect.h = screen_height;
50  }
51 
52  else if (rect.y + rect.h > screen_height) {
53  rect.y = screen_height - rect.h;
54  }
55 }
56 
57 ComboList::ComboList(ComboBox* ctrl, Screen* s, int ax, int ay, int aw, int ah, int maxentries)
58 : ScrollWindow(s, ax, ay, aw, ah + (ah-2)*maxentries + 2, 0), combo_box(ctrl)
59 {
60  button_state = 0;
61  button_height = ah;
62  captured = 0;
63  seln = -1;
64  max_entries = maxentries;
65  scroll = 0;
66  scrolling = false;
67  border = true;
68  animated = true;
69  bevel_width = 5;
70 
71  if (ctrl)
72  CopyStyle(*ctrl);
73 
74  rect.h = (ah-2)*maxentries + 2;
75 
76  int screen_height = Video::GetInstance()->Height();
77 
78  if (rect.h > screen_height) {
79  rect.y = 0;
80  rect.h = screen_height;
81  }
82 
83  else if (rect.y + rect.h > screen_height) {
84  rect.y = screen_height - rect.h;
85  }
86 
87  screen->AddWindow(this); // just in case the base ctor couldn't do this
88 }
89 
90 // +--------------------------------------------------------------------+
91 
93 {
94  items.destroy();
95 }
96 
97 // +--------------------------------------------------------------------+
98 
99 void
101 {
102  active_color = ctrl.GetActiveColor();
103  border_color = ctrl.GetBorderColor();
104  fore_color = ctrl.GetForeColor();
105  back_color = ctrl.GetBackColor();
106 
107  animated = ctrl.GetAnimated();
108  bevel_width = ctrl.GetBevelWidth();
109  border = ctrl.GetBorder();
110 }
111 
112 // +--------------------------------------------------------------------+
113 
114 void
116 {
117  if (!scrolling) {
118  scrolling = 1;
119  scroll = 0;
120  }
121 
123 }
124 
125 void
127 {
128  scrolling = 0;
129  scroll = 0;
131 }
132 
133 // +--------------------------------------------------------------------+
134 
135 void
137 {
138  int x = 0;
139  int y = 0;
140  int w = rect.w;
141  int h = button_height;
142 
143  int index = 0;
144 
145  // opening:
146  if (scrolling > 0) {
147  int limit = min(items.size(), max_entries);
148 
149  if (scroll < limit) {
150  if (limit > 6)
151  scroll += 4;
152 
153  else if (limit > 4)
154  scroll += 2;
155 
156  else
157  scroll += 1;
158  }
159 
160  if (scroll >= limit) {
161  scroll = limit;
162  scrolling = 0;
163  }
164  }
165 
166  // closing:
167  else if (scrolling < 0) {
168  if (scroll > 0)
169  scroll--;
170  else
171  scrolling = 0;
172  }
173 
174  if (items.size() < 1) {
175  Rect btn_rect(x,y,w,h);
176  DrawItem(" ", btn_rect, 0);
177  }
178  else {
179  ListIter<Text> item = items;
180  while (++item && index < max_entries) {
181  Rect btn_rect(x,y,w,h);
182  int sub_state = (index == seln) ? button_state : 0;
183 
184  DrawItem(*item, btn_rect, sub_state);
185 
186  y += button_height-2;
187  index++;
188  }
189  }
190 
191  DrawRect(0,0,rect.w-1,rect.h-1,fore_color);
192 }
193 
194 // +--------------------------------------------------------------------+
195 
196 void
198 {
199  if (state && active_color != Color::Black)
200  FillRect(rect, active_color);
201  else
202  FillRect(rect, back_color);
203 }
204 
205 void
206 ComboList::DrawItem(Text label, Rect& btn_rect, int state)
207 {
208  int x = btn_rect.x;
209  int y = btn_rect.y;
210  int w = btn_rect.w;
211  int h = btn_rect.h;
212 
213  // draw the bevel:
214  DrawRectSimple(btn_rect, state);
215 
216  // draw text here:
217  if (font && label.length()) {
218  int border_size = 4;
219 
221  border_size = 8;
222 
223  Rect label_rect = CalcLabelRect(btn_rect);
224  int vert_space = label_rect.h;
225  int horz_space = label_rect.w;
226 
227  DrawText(label.data(), 0, label_rect, DT_CALCRECT | DT_WORDBREAK | text_align);
228  vert_space = (vert_space - label_rect.h)/2;
229 
230  label_rect.w = horz_space;
231 
232  if (vert_space > 0)
233  label_rect.y += vert_space;
234 
235  if (animated && state > 0) {
236  label_rect.x += state;
237  label_rect.y += state;
238  }
239 
241  DrawText(label.data(), 0, label_rect, DT_WORDBREAK | text_align);
242  }
243 }
244 
246 {
247  // fit the text in the bevel:
248  Rect label_rect = btn_rect;
249  label_rect.Deflate(bevel_width, bevel_width);
250 
251  return label_rect;
252 }
253 
254 int ComboList::CalcSeln(int x, int y)
255 {
256  y -= rect.y;
257 
258  if (button_height < 1)
259  return 0;
260 
261  return (int) (y / (button_height-2));
262 }
263 
264 // +--------------------------------------------------------------------+
265 
266 int ComboList::OnMouseMove(int x, int y)
267 {
268  if (captured)
269  {
270  ActiveWindow* test = GetCapture();
271 
272  if (test != this)
273  {
274  captured = false;
275  button_state = -1;
276  }
277  }
278 
279  int new_seln = CalcSeln(x,y);
280 
281  if (new_seln != seln) {
282  seln = new_seln;
284  }
285 
286  return ActiveWindow::OnMouseMove(x,y);
287 }
288 
289 int ComboList::OnLButtonDown(int x, int y)
290 {
291  if (!captured)
292  captured = SetCapture();
293 
294  seln = CalcSeln(x,y);
295  button_state = 1;
296 
297  return ActiveWindow::OnLButtonDown(x,y);
298 }
299 
300 int ComboList::OnLButtonUp(int x, int y)
301 {
302  if (captured) {
303  ReleaseCapture();
304  captured = 0;
305  }
306 
307  seln = CalcSeln(x,y);
308  button_state = -1;
309  return ActiveWindow::OnLButtonUp(x,y);
310 }
311 
313 {
314  return ActiveWindow::OnClick();
315 }
316 
317 int ComboList::OnMouseEnter(int mx, int my)
318 {
319  if (button_state == 0)
320  button_state = -1;
321 
322  return ActiveWindow::OnMouseEnter(mx, my);
323 }
324 
325 int ComboList::OnMouseExit(int mx, int my)
326 {
327  if (button_state == -1)
328  button_state = 0;
329 
330  return ActiveWindow::OnMouseExit(mx, my);
331 }
332 
334 {
335  if (combo_box)
336  combo_box->HideList();
337 }
338 
339 // +--------------------------------------------------------------------+
340 
342 {
343  items.destroy();
344 }
345 
346 // +--------------------------------------------------------------------+
347 
348 void ComboList::AddItem(const char* item)
349 {
350  items.append(new(__FILE__,__LINE__) Text(item));
351 }
352 
354 {
355  while (++item)
356  items.append(new(__FILE__,__LINE__) Text(*item));
357 }
358 
360 {
361  items.destroy();
362  while (++item)
363  items.append(new(__FILE__,__LINE__) Text(*item));
364 
365  // Resize window:
366 
367  int ah = button_height;
368  max_entries = items.size();
369  Rect r = rect;
370  r.y = combo_box->Y();
371  int length = max_entries;
372 
373  if (length < 1)
374  length = 1;
375 
376  r.h = (ah-2)*length + 2;
377 
378  int screen_height = Video::GetInstance()->Height();
379 
380  if (r.h > screen_height) {
381  r.y = 0;
382  r.h = screen_height;
383  }
384 
385  else if (r.y + r.h > screen_height) {
386  r.y = screen_height - r.h;
387  }
388 
389  MoveTo(r);
390 }
391 
392 const char* ComboList::GetItem(int index)
393 {
394  if (index >= 0 && index < items.size())
395  return items[index]->data();
396  else
397  return 0;
398 }
399 
400 void ComboList::SetItem(int index, const char* item)
401 {
402  if (index >= 0 && index < items.size())
403  *items[index] = item;
404  else
405  items.append(new(__FILE__,__LINE__) Text(item));
406 }
407 
409 {
410  return items.size();
411 }
412 
414 {
415  if (seln >= 0 && seln < items.size())
416  return items[seln]->data();
417  else
418  return 0;
419 }
420 
422 {
423  if (seln >= 0 && seln < items.size())
424  return seln;
425  else
426  return -1;
427 }
428 
429 void ComboList::SetSelection(int index)
430 {
431  if (index >= 0 && index < items.size())
432  seln = index;
433 }
434