1 /*---------------------------------------------------------------------------*
2
3 Copyright (C) Nintendo. All rights reserved.
4
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10
11 *---------------------------------------------------------------------------*/
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <math.h>
17 #include <vector>
18 #include <list>
19 #include <hash_map>
20
21 #include <cafe/os.h>
22
23 #include <cafe/gx2.h>
24
25 #include <cafe/demo/demowin.h>
26
27 namespace DEMOWin
28 {
29
30 #include "demowin/demowin_tabbing.cpp"
31 #include "demowin/demowin_helpers.cpp"
32
33 #include "demowin/demowin_manager.cpp"
34
35 #include "demowin/demowin_tab_window.cpp"
36
37 #include "demowin/demowin_button.cpp"
38 #include "demowin/demowin_held_button.cpp"
39
40 #include "demowin/demowin_scroll_bar.cpp"
41 #include "demowin/demowin_slider_bar.cpp"
42 #include "demowin/demowin_slider_bar_float.cpp"
43
44 #include "demowin/demowin_combo_box.cpp"
45 #include "demowin/demowin_double_combo_box.cpp"
46
47 #include "demowin/demowin_text.cpp"
48 #include "demowin/demowin_text_center.cpp"
49 #include "demowin/demowin_text_right.cpp"
50 #include "demowin/demowin_text_multi.cpp"
51
52 // A very special flag to ignore window bounds for input (i.e. for combo boxes)
53 bool gIgnoreBounds = false;
54
ComboCustom(WindowManager * manager,const char * name,const AutoList<int> & start,const AutoList<const char * > & names,const AutoList<AutoList<const char * >> & option)55 ComboCustom::ComboCustom(WindowManager* manager, const char* name, const AutoList<int>& start, const AutoList<const char*>& names, const AutoList<AutoList<const char*> >& option)
56 : Window(manager, name, CVec2(0, 0), CVec2(1.4, 0.1 + start.count * 0.1))
57 {
58 ASSERT(start.count == names.count && names.count == option.count);
59
60 int count = start.count;
61
62 // Set up the counts array
63 std::vector<int> counts;
64 counts.resize(count);
65
66 for (int i = 0; i < counts.size(); ++i)
67 counts[i] = option.args[i].count;
68
69 // Set up the option array
70 std::vector<const char* const*> optionArray;
71 optionArray.resize(count);
72
73 for (int i = 0; i < optionArray.size(); ++i)
74 optionArray[i] = option.args[i].args;
75
76 Init(count, &counts[0], start.args, names.args, &optionArray[0]);
77 }
78
ComboCustom(WindowManager * manager,const char * name,const AutoList<int> & start,const AutoList<const char * > & names,const AutoList<std::vector<const char * >> & option)79 ComboCustom::ComboCustom(WindowManager* manager, const char* name, const AutoList<int>& start, const AutoList<const char*>& names, const AutoList<std::vector<const char*> >& option)
80 : Window(manager, name, CVec2(0, 0), CVec2(1.4, 0.1 + start.count * 0.1))
81 {
82 ASSERT(start.count == names.count && names.count == option.count);
83
84 int count = start.count;
85
86 // Set up the counts array
87 std::vector<int> counts;
88 counts.resize(count);
89
90 for (int i = 0; i < counts.size(); ++i)
91 counts[i] = option.args[i].size();
92
93 // Set up the option array
94 std::vector<const char* const*> optionArray;
95 optionArray.resize(count);
96
97 for (int i = 0; i < optionArray.size(); ++i)
98 optionArray[i] = &option.args[i][0];
99
100 Init(count, &counts[0], start.args, names.args, &optionArray[0]);
101 }
102
ComboCustom(WindowManager * manager,const char * name,const std::vector<int> & start,const std::vector<const char * > & names,const std::vector<std::vector<const char * >> & option)103 ComboCustom::ComboCustom(WindowManager* manager, const char* name, const std::vector<int>& start, const std::vector<const char*>& names, const std::vector<std::vector<const char*> >& option)
104 : Window(manager, name, CVec2(0, 0), CVec2(1.4, 0.1 + option.size() * 0.1))
105 {
106 ASSERT(start.size() == names.size());
107 ASSERT(names.size() == option.size());
108 ASSERT(option.size() <= 10);
109
110 int count = start.size();
111
112 // Set up the counts array
113 std::vector<int> counts;
114 counts.resize(count);
115
116 for (int i = 0; i < counts.size(); ++i)
117 counts[i] = option[i].size();
118
119 // Set up the option array
120 std::vector<const char* const*> optionArray;
121 optionArray.resize(count);
122
123 for (int i = 0; i < optionArray.size(); ++i)
124 optionArray[i] = &option[i][0];
125
126 Init(count, &counts[0], &start[0], &names[0], &optionArray[0]);
127 }
128
Init(int num,const int * counts,const int * start,const char * const * names,const char * const * const * option)129 void ComboCustom::Init(int num, const int* counts, const int* start, const char* const* names, const char* const* const* option)
130 {
131 MenuText text(this, CVec3(0, 0, 0.1), CVec2(1.0, 0.07), "", CVec4(1.0, 1.0, 1.0));
132 ComboBox box(this, CVec3(0.4, 0, 0.1), CVec2(0.4, 0.09), NULL, 0, NULL);
133
134 for (int j = 0; j < num; ++j)
135 {
136 choice[j] = start[j];
137
138 int count = counts[j];
139
140 options[j].resize(count);
141 optionsList[j].resize(count);
142
143 // Figure out how many options we actually have (no limit)
144 for (int i = 0; i < count; ++i)
145 {
146 options[j][i] = option[j][i];
147 optionsList[j][i] = &options[j][i];
148 }
149
150 text.text = names[j];
151 text.y = -0.1 - j * 0.1;
152 MenuText::Add(text);
153
154 box.data = &optionsList[j][0];
155 box.count = count;
156 box.target = &choice[j];
157 box.y = -0.1 - j * 0.1;
158 ComboBox::Add(box);
159 }
160 }
161
162 // Constructs the window
Window(WindowManager * manager,const char * _name,CVec2 _position,CVec2 _size,CVec2 _maxSize,bool _canKill)163 Window::Window(WindowManager* manager, const char* _name, CVec2 _position, CVec2 _size, CVec2 _maxSize, bool _canKill)
164 : name(_name), position(_position), size(_size), maxSize(_maxSize), x(position.x), y(position.y), width(size.x), height(size.y), maxWidth(maxSize.x), maxHeight(maxSize.y), canKill(_canKill), deleteFlag(false), offY(0), visible(false), enabled(true), master(NULL), child(NULL), dummyTab(this), manager(NULL)
165 {
166 if (maxHeight <= 0)
167 maxHeight = height;
168
169 ASSERT(width >= 0);
170 ASSERT(height >= 0);
171 ASSERT(maxHeight >= height);
172
173 manager->AddToWindowList(this);
174
175 scrollBar = new ScrollBar(this, CVec3(width / 2 - SCROLLBAR_WIDTH / 2, -height / 2, 0.9), CVec2(SCROLLBAR_WIDTH, height), maxHeight, height);
176 menu = new MenuItem(this);
177 }
178
179 // Not that this would ever be called, but...
~Window()180 Window::~Window()
181 {
182 for (std::list<MenuItem*>::iterator iter = this->menuItems.begin(); iter != this->menuItems.end(); ++iter)
183 delete (*iter);
184
185 this->menuItems.clear();
186 this->tabItems.clear();
187
188 delete scrollBar;
189 delete menu;
190
191 this->manager->RemoveFromWindowList(this);
192 }
193
194 // Returns the top
GetOffY()195 float& Window::GetOffY()
196 {
197 // Master knows best!
198 if (this->master)
199 return this->master->GetOffY();
200
201 return this->offY;
202 }
203
204 // Returns the top
GetTop()205 float Window::GetTop()
206 {
207 // Master knows best!
208 if (this->master)
209 return this->master->GetTop();
210
211 return this->y;
212 }
213
214 // Returns the width
GetWidth()215 float Window::GetWidth()
216 {
217 // Master knows best!
218 if (this->master)
219 return this->master->GetWidth();
220
221 float ret = this->width;
222
223 Window* custom = this->child;
224 while (custom)
225 {
226 if (custom->width > ret)
227 ret = custom->width;
228
229 custom = custom->child;
230 }
231
232 return ret;
233 }
234
235 // Returns the height
GetHeight()236 float Window::GetHeight()
237 {
238 // Master knows best!
239 if (this->master)
240 return this->master->GetHeight();
241
242 float ret = this->height;
243
244 Window* custom = this->child;
245 while (custom)
246 {
247 ret += custom->height;
248 custom = custom->child;
249 }
250
251 return ret;
252 }
253
254 // Returns the maximum height
GetMaxHeight()255 float Window::GetMaxHeight()
256 {
257 // Master knows best!
258 if (this->master)
259 return this->master->GetMaxHeight();
260
261 float ret = this->maxHeight;
262
263 Window* custom = this->child;
264 while (custom)
265 {
266 ret += custom->maxHeight;
267 custom = custom->child;
268 }
269
270 return ret;
271 }
272
273 // Returns the ultimate master of this window
GetMaster()274 Window* Window::GetMaster()
275 {
276 // We're the ultimate master!
277 if (!this->master)
278 return this;
279
280 return this->master->GetMaster();
281 }
282
283 // Determines if the cursor is over this window
CursorOver()284 bool Window::CursorOver()
285 {
286 if (manager->peripheral->CursorColliding(this->GetX(), this->GetTop() - this->GetHeight() / 2, this->GetWidth(), this->GetHeight()))
287 return true;
288
289 for (std::list<MenuItem*>::iterator iter = this->menuItems.begin(); iter != this->menuItems.end(); ++iter)
290 {
291 if ((*iter)->CursorOver())
292 return true;
293 }
294
295 // Don't forget the child's menu items!
296 if (this->child)
297 return this->child->CursorOver();
298
299 return false;
300 }
301
302 // Resets the items in the window
Reset()303 void Window::Reset()
304 {
305 for (std::list<MenuItem*>::iterator iter = this->menuItems.begin(); iter != this->menuItems.end(); ++iter)
306 (*iter)->Reset();
307
308 scrollBar->Reset();
309 }
310
311 // Causes a window to become hidden
Hide()312 void Window::Hide()
313 {
314 this->visible = false;
315
316 // Cut all our ties!
317 DetachWindow();
318 if (this->master)
319 this->master->DetachWindow();
320 }
321
322 // Causes a window to become visible
Show()323 void Window::Show()
324 {
325 this->visible = true;
326 }
327
328 // Determines if this window is in front
InFront()329 bool Window::InFront()
330 {
331 return (this == manager->GetWindowList()[manager->GetWindowOrder()[0]]);
332 }
333
334 // Determines if this window is enabled
Enabled()335 bool Window::Enabled()
336 {
337 return this->GetMaster()->enabled;
338 }
339
340 // Determines if this window is visible
Visible()341 bool Window::Visible()
342 {
343 return this->GetMaster()->visible;
344 }
345
346 // Brings a window to the front
BringToFront()347 void Window::BringToFront()
348 {
349 if (this->InFront())
350 return;
351
352 this->manager->BringWindowToFront(this);
353
354 menu->TabIndex() = NULL;
355 menu->TabSubIndex() = -1;
356 }
357
358 // Brings a window to the front
ClearItems()359 void Window::ClearItems()
360 {
361 for (std::list<MenuItem*>::iterator iter = menuItems.begin(); iter != menuItems.end(); ++iter)
362 delete *iter;
363
364 menuItems.clear();
365 tabItems.clear();
366 sortedItems.clear();
367 sortedDrawItems.clear();
368 }
369
370 // Anything special the window updates beforehand
PreUpdate(bool canUpdate)371 bool Window::PreUpdate(bool canUpdate)
372 {
373 this->offY = 0;
374
375 if (canUpdate)
376 {
377 float height = this->GetHeight();
378 scrollBar->count = this->GetMaxHeight();
379 scrollBar->max = height;
380 scrollBar->x = (this->GetWidth() - SCROLLBAR_WIDTH) / 2;
381 scrollBar->y = -height / 2;
382 scrollBar->height = height;
383 canUpdate = scrollBar->Update();
384 }
385 else
386 scrollBar->Reset();
387
388 this->offY = scrollBar->pos;
389
390 return canUpdate;
391 }
392
393 // Anything special the window draws beforehand
PreDraw()394 void Window::PreDraw()
395 {
396 float temp = this->offY;
397 this->offY = 0;
398
399 float height = this->GetHeight();
400 scrollBar->count = this->GetMaxHeight();
401 scrollBar->max = height;
402 scrollBar->x = (this->GetWidth() - SCROLLBAR_WIDTH) / 2;
403 scrollBar->y = -height / 2;
404 scrollBar->height = height;
405 scrollBar->Draw();
406
407 this->offY = temp;
408 }
409
410 // Attaches a window (replaces the old one)
AttachWindow(Window * window)411 void Window::AttachWindow(Window* window)
412 {
413 DetachWindow();
414
415 // Could be NULL!
416 if (!window)
417 return;
418
419 // Make sure the old master of this child isn't the master anymore!
420 if (window->master)
421 window->master->DetachWindow();
422
423 this->child = window;
424 window->master = this;
425 window->visible = true;
426 }
427
428 // Detaches the current child window
DetachWindow()429 void Window::DetachWindow()
430 {
431 if (!this->child)
432 return;
433
434 this->child->master = NULL;
435 this->child->Hide();
436 this->child = NULL;
437
438 // Reset the master's offset!
439 Window* master = this;
440 while (master->master)
441 master = master->master;
442 master->offY = 0;
443 }
444
445 // Detaches the current child window
AddTabbing(MenuItem * item)446 void Window::AddTabbing(MenuItem* item)
447 {
448 tabItems.push_back(TabObject());
449 TabObject& tab = tabItems.back();
450 tab.Add(this, item, true);
451 }
452
453 }
454