]> Shamusworld >> Repos - apple2/blob - src/gui/config.cpp
2fba40d4473df1cd83b932ca125d35663d00925f
[apple2] / src / gui / config.cpp
1 //
2 // config.cpp
3 //
4 // Configuration GUI
5 // by James Hammons
6 // © 2019 Underground Software
7 //
8
9 #include "config.h"
10 #include <vector>
11 #include "elements.h"
12 #include "font10pt.h"
13 #include "gui.h"
14 #include "log.h"
15 #include "settings.h"
16 #include "video.h"
17
18
19 #define C_WIDTH         402
20 #define C_HEIGHT        322
21 #define C_XPOS          ((VIRTUAL_SCREEN_WIDTH - C_WIDTH) / 2)
22 #define C_YPOS          ((VIRTUAL_SCREEN_HEIGHT - C_HEIGHT) / 2)
23
24 static SDL_Texture * window = NULL;
25 //static uint32_t windowPixels[C_WIDTH * C_HEIGHT];
26 static SDL_Texture * cardTex[3] = { 0 };
27 static SDL_Texture * cardBay = NULL;
28 bool Config::showWindow = false;
29
30 std::vector<void *> objList;
31
32 static bool dragging = false;
33 static bool entered = false;
34 static bool refresh = false;
35 //static bool cb1Checked = false;
36 static bool cb2Checked = false;
37 //static bool cb3Checked = false;
38 static bool cb4Checked = false;
39 static bool cbnChecked = false;
40 static char le1[512] = { 0 };
41
42 static const char cb1Text[] = "Automatically save state on exit";
43 static const char cb2Text[] = "Enable hard drive";
44 static const char cb3Text[] = "Run Apple2 in full screen mode";
45 static const char cb4Text[] = "Automatically switch to Apple ][ mode for games that require it";
46 static const char cbnText[] = "Don't check this box";
47 static const char le1Text[] = "HD1 location:";
48
49 static const char cbChecked[(9 * 11) + 1] =
50         "       @@"
51         "       @@"
52         "      @@ "
53         "      @@ "
54         "     @@  "
55         "  @@ @@  "
56         "@@  @@   "
57         " @@ @@   "
58         "  @@@ @  "
59         " @ @@ @  "
60         " @@  @@  ";
61
62 static const char cbUnchecked[(9 * 11) + 1] =
63         "         "
64         "         "
65         "         "
66         "         "
67         "         "
68         " @@@@@@  "
69         " @    @  "
70         " @    @  "
71         " @    @  "
72         " @    @  "
73         " @@@@@@  ";
74
75 static const char slotNum[7][(5 * 5) + 1] =
76 {
77         "  @  "
78         "@@@  "
79         "  @  "
80         "  @  "
81         "@@@@@",
82
83         "@@@@ "
84         "    @"
85         " @@@ "
86         "@    "
87         "@@@@@",
88
89         "@@@@ "
90         "    @"
91         " @@@ "
92         "    @"
93         "@@@@ ",
94
95         "@  @ "
96         "@  @ "
97         "@@@@@"
98         "   @ "
99         "   @ ",
100
101         "@@@@@"
102         "@    "
103         "@@@@ "
104         "    @"
105         "@@@@",
106
107         " @@@@"
108         "@    "
109         "@@@@ "
110         "@   @"
111         " @@@ ",
112
113         "@@@@@"
114         "    @"
115         "   @ "
116         "  @  "
117         " @   "
118 };
119
120 //static uint8_t card1[(96 * 11) + 1] = { 0 };
121
122
123 void Config::Init(SDL_Renderer * renderer)
124 {
125         window = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888,
126                 SDL_TEXTUREACCESS_TARGET, C_WIDTH, C_HEIGHT);
127
128         if (!window)
129         {
130                 WriteLog("GUI (Config): Could not create window!\n");
131                 return;
132         }
133
134         if (SDL_SetTextureBlendMode(window, SDL_BLENDMODE_BLEND) == -1)
135                 WriteLog("GUI (Config): Could not set blend mode for window.\n");
136
137         for(int t=0; t<3; t++)
138         {
139                 cardTex[t] = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
140                         SDL_TEXTUREACCESS_TARGET, 96, 11);
141                 SDL_SetTextureBlendMode(cardTex[t], SDL_BLENDMODE_BLEND);
142
143                 SDL_SetRenderTarget(renderer, cardTex[t]);
144                 SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
145                 SDL_RenderClear(renderer);
146
147                 SDL_SetRenderDrawColor(renderer, 0x00, 0xAA, 0x00, 0xFF);
148
149                 for(int j=3; j<8; j++)
150                         for(int i=0; i<96; i++)
151                                 SDL_RenderDrawPoint(renderer, i, j);
152         }
153
154         SDL_SetRenderTarget(renderer, cardTex[0]);
155         GUI::DrawString(renderer, 4, 0, "Disk ][");
156         SDL_SetRenderTarget(renderer, cardTex[1]);
157         GUI::DrawString(renderer, 2, 0, "Mockingboard");
158         SDL_SetRenderTarget(renderer, cardTex[2]);
159         GUI::DrawString(renderer, 6, 0, "SCSI");
160
161         cardBay =  SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 123, 99);
162         SDL_SetTextureBlendMode(cardBay, SDL_BLENDMODE_BLEND);
163         SDL_SetRenderTarget(renderer, cardBay);
164         SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
165         SDL_RenderClear(renderer);
166
167         GUI::DrawBox(renderer, 5, 5, 118, 88, 0xFF, 0xFF, 0xFF);
168         GUI::DrawStringVert(renderer, 5, 33 + 21, " SLOTS ");
169
170         for(int t=0; t<7; t++)
171         {
172                 GUI::DrawBox(renderer, FONT_WIDTH * 2, (FONT_HEIGHT * (t + 1)) + 3, 96, 5, 0xFF, 0xFF, 0xFF);
173                 GUI::DrawCharArray(renderer, slotNum[t], 112, (FONT_HEIGHT * (t + 1)) + 3, 5, 5, 0xFF, 0xFF, 0xFF);
174         }
175
176         SDL_SetRenderTarget(renderer, NULL);
177
178         objList.push_back(new CheckBox(1, 1, &settings.autoStateSaving, cb1Text));
179         objList.push_back(new CheckBox(1, 2, &cb2Checked, cb2Text));
180         objList.push_back(new CheckBox(1, 3, &settings.fullscreen, cb3Text));
181         objList.push_back(new CheckBox(1, 4, &cb4Checked, cb4Text));
182
183         objList.push_back(new CheckBox(1, 27, &cbnChecked, cbnText));
184
185         objList.push_back(new LineEdit(1, 6, le1, 48, le1Text));
186         objList.push_back(new Draggable(1 * FONT_WIDTH, 8 * FONT_HEIGHT, 96, 11, cardTex[0]));
187         objList.push_back(new Draggable(1 * FONT_WIDTH, 9 * FONT_HEIGHT, 96, 11, cardTex[0]));
188         objList.push_back(new Draggable(1 * FONT_WIDTH, 10 * FONT_HEIGHT, 96, 11, cardTex[1]));
189         objList.push_back(new Draggable(1 * FONT_WIDTH, 11 * FONT_HEIGHT, 96, 11, cardTex[1]));
190         objList.push_back(new Draggable(1 * FONT_WIDTH, 12 * FONT_HEIGHT, 96, 11, cardTex[2]));
191 }
192
193
194 void Config::ShowWindow(void)
195 {
196         entered = false;
197         showWindow = true;
198         refresh = true;
199 }
200
201
202 void Config::HideWindow(void)
203 {
204         showWindow = false;
205         refresh = true;
206 }
207
208
209 void Config::MouseDown(int32_t x, int32_t y, uint32_t buttons)
210 {
211         if (!showWindow || !entered)
212                 return;
213
214         dragging = true;
215         std::vector<void *>::iterator i;
216
217         for(i=objList.begin(); i!=objList.end(); i++)
218         {
219                 Object * obj = (Object *)(*i);
220
221                 switch (obj->type)
222                 {
223                 case OTCheckBox:
224                 {
225                         CheckBox * cb = (CheckBox *)obj;
226
227                         if (cb->hovered)
228                         {
229                                 *(cb->state) = !(*(cb->state));
230                                 refresh = true;
231                         }
232
233                         break;
234                 }
235
236                 case OTDraggable:
237                 {
238                         Draggable * d = (Draggable *)obj;
239
240                         if (d->hovered)
241                         {
242                                 d->dragging = true;
243                                 refresh = true;
244                         }
245
246                         break;
247                 }
248
249                 default:
250                         break;
251                 }
252         }
253 }
254
255
256 void Config::MouseUp(int32_t x, int32_t y, uint32_t buttons)
257 {
258         if (!showWindow)
259                 return;
260
261         dragging = false;
262         std::vector<void *>::iterator i;
263
264         for(i=objList.begin(); i!=objList.end(); i++)
265         {
266                 Object * obj = (Object *)(*i);
267
268                 switch (obj->type)
269                 {
270                 case OTDraggable:
271                 {
272                         Draggable * d = (Draggable *)obj;
273
274                         if (d->dragging)
275                         {
276                                 d->dragging = false;
277
278                                 if ((d->r.x > 120) && (d->r.x < 220) && (d->r.y > (8 * FONT_HEIGHT)) && (d->r.y < (15 * FONT_HEIGHT)))
279                                 {
280                                         d->spot = ((d->r.y - (8 * FONT_HEIGHT)) / FONT_HEIGHT) + 1;
281                                         d->r.x = 120;
282                                         d->r.y = (7 + d->spot) * FONT_HEIGHT;
283                                 }
284                                 else
285                                 {
286                                         d->r.x = d->homex;
287                                         d->r.y = d->homey;
288                                         d->spot = 0;
289                                 }
290
291                                 refresh = true;
292                         }
293
294                         break;
295                 }
296                 }
297         }
298 }
299
300
301 static int32_t oldx, oldy;
302 void Config::MouseMove(int32_t x, int32_t y, uint32_t buttons)
303 {
304         if (!showWindow)
305                 return;
306
307         int32_t nx = x - C_XPOS, ny = y - C_YPOS;
308
309         // Check to see if C has been hovered yet, and, if so, set a flag to show
310         // that it has
311         if (!entered && ((nx >= 0) && (nx <= C_WIDTH) && (ny >= 0)
312                 && (ny <= C_HEIGHT)))
313                 entered = true;
314
315         // Check to see if the C, since being hovered, is now no longer being
316         // hovered
317 //N.B.: Should probably make like a 1/2 to 1 second timeout to allow for overshooting the edge of the thing, maybe have the window fade out gradually and let it come back if you enter before it leaves...
318         if (entered && ((nx < 0) || (nx > C_WIDTH) || (ny < 0) || (ny > C_HEIGHT)))
319         {
320                 showWindow = false;
321                 refresh = true;
322                 return;
323         }
324
325         // Bail out if the C hasn't been entered yet
326         if (!entered)
327                 return;
328
329         std::vector<void *>::iterator i;
330
331         for(i=objList.begin(); i!=objList.end(); i++)
332         {
333                 Object * obj = (Object *)(*i);
334
335                 switch (obj->type)
336                 {
337                 case OTCheckBox:
338                 {
339                         CheckBox * cb = (CheckBox *)obj;
340                         bool oldHover = cb->hovered;
341                         cb->hovered = (((nx >= ((cb->r.x * FONT_WIDTH) + 1))
342                                 && (nx <= ((cb->r.x * FONT_WIDTH) + 6))
343                                 && (ny >= ((cb->r.y * FONT_HEIGHT) + 3))
344                                 && (ny <= ((cb->r.y * FONT_HEIGHT) + 8))) ? true : false);
345
346                         if (oldHover != cb->hovered)
347                                 refresh = true;
348
349                         break;
350                 }
351
352                 case OTLineEdit:
353                 {
354                         LineEdit * le = (LineEdit *)obj;
355                         uint32_t labelLen = strlen(le->label);
356                         bool oldHover = le->hovered;
357                         le->hovered = (((nx >= ((le->r.x + labelLen + 1) * FONT_WIDTH))
358                                 && (nx <= ((le->r.x + labelLen + 1 + le->size) * FONT_WIDTH))
359                                 && (ny >= ((le->r.y * FONT_HEIGHT)))
360                                 && (ny <= ((le->r.y + 1) * FONT_HEIGHT))) ? true : false);
361
362                         if (oldHover != le->hovered)
363                                 refresh = true;
364
365                         break;
366                 }
367
368                 case OTDraggable:
369                 {
370                         Draggable * d = (Draggable *)obj;
371
372                         if (!d->dragging)
373                         {
374                                 bool oldHover = d->hovered;
375                                 d->hovered = (((nx >= d->r.x) && (nx < (d->r.x + d->r.w))
376                                         && (ny >= d->r.y) && (ny < (d->r.y + d->r.h)))
377                                         ? true : false);
378
379                                 if (oldHover != d->hovered)
380                                         refresh = true;
381                         }
382                         else
383                         {
384                                 d->r.x += (nx - oldx);
385                                 d->r.y += (ny - oldy);
386                                 refresh = true;
387                         }
388
389                         break;
390                 }
391
392                 default:
393                         break;
394                 }
395         }
396
397         oldx = nx;
398         oldy = ny;
399 }
400
401
402 bool Config::KeyDown(uint32_t key)
403 {
404         if (!showWindow)
405                 return false;
406
407 //      bool response = false;
408         std::vector<void *>::iterator i;
409
410         for(i=objList.begin(); i!=objList.end(); i++)
411         {
412                 Object * obj = (Object *)(*i);
413
414                 switch (obj->type)
415                 {
416                 case OTLineEdit:
417                 {
418                         LineEdit * le = (LineEdit *)obj;
419
420                         if (le->hovered)
421                         {
422                                 uint32_t textLen = strlen(le->text);
423                                 le->text[textLen] = key;
424                                 refresh = true;
425 WriteLog("Config: textLen=%u, key=%02X\n", textLen, key);
426                                 return true;
427                         }
428
429                         break;
430                 }
431
432                 default:
433                         break;
434                 }
435         }
436
437         return false;
438 }
439
440
441 void Config::DrawElements(SDL_Renderer * renderer)
442 {
443         SDL_SetRenderDrawColor(renderer, 0x7F, 0x3F, 0x00, 0xEF);
444         SDL_RenderClear(renderer);
445
446         SDL_Rect cbRect = { 108, FONT_HEIGHT * 7, 123, 99 };
447         SDL_RenderCopy(renderer, cardBay, NULL, &cbRect);
448
449         std::vector<void *>::iterator i;
450
451         for(i=objList.begin(); i!=objList.end(); i++)
452         {
453                 Object * obj = (Object *)(*i);
454
455                 switch (obj->type)
456                 {
457                 case OTCheckBox:
458                 {
459                         CheckBox * cb = (CheckBox *)obj;
460                         uint8_t r = 0x00, g = 0xAA, b = 0x00;
461
462                         if (cb->hovered)
463                                 r = 0x20, g = 0xFF, b = 0x20;
464
465                         GUI::DrawCharArray(renderer, (*(cb->state) ? cbChecked : cbUnchecked), cb->r.x * FONT_WIDTH, (cb->r.y * FONT_HEIGHT) - 2, 9, 11, r, g, b);
466                         GUI::DrawString(renderer, cb->r.x + 2, cb->r.y, cb->text);
467                         break;
468                 }
469
470                 case OTLineEdit:
471                 {
472                         LineEdit * le = (LineEdit *)obj;
473                         GUI::DrawString(renderer, le->r.x, le->r.y, le->label);
474                         uint32_t labelLen = strlen(le->label);
475                         uint8_t r = 0x00, g = 0xAA, b = 0x00;
476
477                         if (le->hovered)
478                                 r = 0x20, g = 0xFF, b = 0x20;
479
480                         GUI::DrawBox(renderer, FONT_WIDTH * (le->r.x + labelLen + 1), FONT_HEIGHT * le->r.y, FONT_WIDTH * le->size, FONT_HEIGHT, r, g, b);
481                         GUI::DrawString(renderer, le->r.x + labelLen + 1, le->r.y, le->text);
482                         break;
483                 }
484
485                 case OTDraggable:
486                 {
487                         Draggable * d = (Draggable *)obj;
488                         SDL_RenderCopy(renderer, d->img, NULL, &d->r);
489                         break;
490                 }
491
492                 default:
493                         break;
494                 }
495         }
496 }
497
498
499 void Config::Render(SDL_Renderer * renderer)
500 {
501         if (!(window && showWindow))
502                 return;
503
504         if (refresh)
505         {
506                 SDL_SetRenderTarget(renderer, window);
507                 DrawElements(renderer);
508                 refresh = false;
509         }
510
511         SDL_SetRenderTarget(renderer, NULL);
512
513         SDL_Rect dst = { C_XPOS, C_YPOS, C_WIDTH, C_HEIGHT };
514         SDL_RenderCopy(renderer, window, NULL, &dst);
515 }
516