]> Shamusworld >> Repos - apple2/blob - src/gui/config.cpp
a0203b2f4a06316b3dfe7e33f863a828b42adfeb
[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, &cb1Checked, cb1Text));
179         objList.push_back(new CheckBox(1, 1, &settings.autoStateSaving, cb1Text));
180         objList.push_back(new CheckBox(1, 2, &cb2Checked, cb2Text));
181         objList.push_back(new CheckBox(1, 3, &settings.fullscreen, cb3Text));
182         objList.push_back(new CheckBox(1, 4, &cb4Checked, cb4Text));
183
184         objList.push_back(new CheckBox(1, 27, &cbnChecked, cbnText));
185
186         objList.push_back(new LineEdit(1, 6, le1, 48, le1Text));
187         objList.push_back(new Draggable(1 * FONT_WIDTH, 8 * FONT_HEIGHT, 96, 11, cardTex[0]));
188         objList.push_back(new Draggable(1 * FONT_WIDTH, 9 * FONT_HEIGHT, 96, 11, cardTex[0]));
189         objList.push_back(new Draggable(1 * FONT_WIDTH, 10 * FONT_HEIGHT, 96, 11, cardTex[1]));
190         objList.push_back(new Draggable(1 * FONT_WIDTH, 11 * FONT_HEIGHT, 96, 11, cardTex[1]));
191         objList.push_back(new Draggable(1 * FONT_WIDTH, 12 * FONT_HEIGHT, 96, 11, cardTex[2]));
192 }
193
194
195 void Config::ShowWindow(void)
196 {
197         entered = false;
198         showWindow = true;
199         refresh = true;
200 }
201
202
203 void Config::HideWindow(void)
204 {
205         showWindow = false;
206         refresh = true;
207 }
208
209
210 void Config::MouseDown(int32_t x, int32_t y, uint32_t buttons)
211 {
212         if (!showWindow || !entered)
213                 return;
214
215         dragging = true;
216         std::vector<void *>::iterator i;
217
218         for(i=objList.begin(); i!=objList.end(); i++)
219         {
220                 Object * obj = (Object *)(*i);
221
222                 switch (obj->type)
223                 {
224                 case OTCheckBox:
225                 {
226                         CheckBox * cb = (CheckBox *)obj;
227
228                         if (cb->hovered)
229                         {
230                                 *(cb->state) = !(*(cb->state));
231                                 refresh = true;
232                         }
233
234                         break;
235                 }
236
237                 case OTDraggable:
238                 {
239                         Draggable * d = (Draggable *)obj;
240
241                         if (d->hovered)
242                         {
243                                 d->dragging = true;
244                                 refresh = true;
245                         }
246
247                         break;
248                 }
249
250                 default:
251                         break;
252                 }
253         }
254 }
255
256
257 void Config::MouseUp(int32_t x, int32_t y, uint32_t buttons)
258 {
259         if (!showWindow)
260                 return;
261
262         dragging = false;
263         std::vector<void *>::iterator i;
264
265         for(i=objList.begin(); i!=objList.end(); i++)
266         {
267                 Object * obj = (Object *)(*i);
268
269                 switch (obj->type)
270                 {
271                 case OTDraggable:
272                 {
273                         Draggable * d = (Draggable *)obj;
274
275                         if (d->dragging)
276                         {
277                                 d->dragging = false;
278
279                                 if ((d->r.x > 120) && (d->r.x < 220) && (d->r.y > (8 * FONT_HEIGHT)) && (d->r.y < (15 * FONT_HEIGHT)))
280                                 {
281                                         d->spot = ((d->r.y - (8 * FONT_HEIGHT)) / FONT_HEIGHT) + 1;
282                                         d->r.x = 120;
283                                         d->r.y = (7 + d->spot) * FONT_HEIGHT;
284                                 }
285                                 else
286                                 {
287                                         d->r.x = d->homex;
288                                         d->r.y = d->homey;
289                                         d->spot = 0;
290                                 }
291
292                                 refresh = true;
293                         }
294
295                         break;
296                 }
297                 }
298         }
299 }
300
301
302 static int32_t oldx, oldy;
303 void Config::MouseMove(int32_t x, int32_t y, uint32_t buttons)
304 {
305         if (!showWindow)
306                 return;
307
308         int32_t nx = x - C_XPOS, ny = y - C_YPOS;
309
310         // Check to see if C has been hovered yet, and, if so, set a flag to show
311         // that it has
312         if (!entered && ((nx >= 0) && (nx <= C_WIDTH) && (ny >= 0)
313                 && (ny <= C_HEIGHT)))
314                 entered = true;
315
316         // Check to see if the C, since being hovered, is now no longer being
317         // hovered
318 //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...
319         if (entered && ((nx < 0) || (nx > C_WIDTH) || (ny < 0) || (ny > C_HEIGHT)))
320         {
321                 showWindow = false;
322                 refresh = true;
323                 return;
324         }
325
326         // Bail out if the C hasn't been entered yet
327         if (!entered)
328                 return;
329
330         std::vector<void *>::iterator i;
331
332         for(i=objList.begin(); i!=objList.end(); i++)
333         {
334                 Object * obj = (Object *)(*i);
335
336                 switch (obj->type)
337                 {
338                 case OTCheckBox:
339                 {
340                         CheckBox * cb = (CheckBox *)obj;
341                         bool oldHover = cb->hovered;
342                         cb->hovered = (((nx >= ((cb->r.x * FONT_WIDTH) + 1))
343                                 && (nx <= ((cb->r.x * FONT_WIDTH) + 6))
344                                 && (ny >= ((cb->r.y * FONT_HEIGHT) + 3))
345                                 && (ny <= ((cb->r.y * FONT_HEIGHT) + 8))) ? true : false);
346
347                         if (oldHover != cb->hovered)
348                                 refresh = true;
349
350                         break;
351                 }
352
353                 case OTLineEdit:
354                 {
355                         LineEdit * le = (LineEdit *)obj;
356                         uint32_t labelLen = strlen(le->label);
357                         bool oldHover = le->hovered;
358                         le->hovered = (((nx >= ((le->r.x + labelLen + 1) * FONT_WIDTH))
359                                 && (nx <= ((le->r.x + labelLen + 1 + le->size) * FONT_WIDTH))
360                                 && (ny >= ((le->r.y * FONT_HEIGHT)))
361                                 && (ny <= ((le->r.y + 1) * FONT_HEIGHT))) ? true : false);
362
363                         if (oldHover != le->hovered)
364                                 refresh = true;
365
366                         break;
367                 }
368
369                 case OTDraggable:
370                 {
371                         Draggable * d = (Draggable *)obj;
372
373                         if (!d->dragging)
374                         {
375                                 bool oldHover = d->hovered;
376                                 d->hovered = (((nx >= d->r.x) && (nx < (d->r.x + d->r.w))
377                                         && (ny >= d->r.y) && (ny < (d->r.y + d->r.h)))
378                                         ? true : false);
379
380                                 if (oldHover != d->hovered)
381                                         refresh = true;
382                         }
383                         else
384                         {
385                                 d->r.x += (nx - oldx);
386                                 d->r.y += (ny - oldy);
387                                 refresh = true;
388                         }
389
390                         break;
391                 }
392
393                 default:
394                         break;
395                 }
396         }
397
398         oldx = nx;
399         oldy = ny;
400 }
401
402
403 bool Config::KeyDown(uint32_t key)
404 {
405         if (!showWindow)
406                 return false;
407
408 //      bool response = false;
409         std::vector<void *>::iterator i;
410
411         for(i=objList.begin(); i!=objList.end(); i++)
412         {
413                 Object * obj = (Object *)(*i);
414
415                 switch (obj->type)
416                 {
417                 case OTLineEdit:
418                 {
419                         LineEdit * le = (LineEdit *)obj;
420
421                         if (le->hovered)
422                         {
423                                 uint32_t textLen = strlen(le->text);
424                                 le->text[textLen] = key;
425                                 refresh = true;
426 WriteLog("Config: textLen=%u, key=%02X\n", textLen, key);
427                                 return true;
428                         }
429
430                         break;
431                 }
432
433                 default:
434                         break;
435                 }
436         }
437
438         return false;
439 }
440
441
442 void Config::DrawElements(SDL_Renderer * renderer)
443 {
444         SDL_SetRenderDrawColor(renderer, 0x7F, 0x3F, 0x00, 0xEF);
445         SDL_RenderClear(renderer);
446
447         SDL_Rect cbRect = { 108, FONT_HEIGHT * 7, 123, 99 };
448         SDL_RenderCopy(renderer, cardBay, NULL, &cbRect);
449
450         std::vector<void *>::iterator i;
451
452         for(i=objList.begin(); i!=objList.end(); i++)
453         {
454                 Object * obj = (Object *)(*i);
455
456                 switch (obj->type)
457                 {
458                 case OTCheckBox:
459                 {
460                         CheckBox * cb = (CheckBox *)obj;
461                         uint8_t r = 0x00, g = 0xAA, b = 0x00;
462
463                         if (cb->hovered)
464                                 r = 0x20, g = 0xFF, b = 0x20;
465
466                         GUI::DrawCharArray(renderer, (*(cb->state) ? cbChecked : cbUnchecked), cb->r.x * FONT_WIDTH, (cb->r.y * FONT_HEIGHT) - 2, 9, 11, r, g, b);
467                         GUI::DrawString(renderer, cb->r.x + 2, cb->r.y, cb->text);
468                         break;
469                 }
470
471                 case OTLineEdit:
472                 {
473                         LineEdit * le = (LineEdit *)obj;
474                         GUI::DrawString(renderer, le->r.x, le->r.y, le->label);
475                         uint32_t labelLen = strlen(le->label);
476                         uint8_t r = 0x00, g = 0xAA, b = 0x00;
477
478                         if (le->hovered)
479                                 r = 0x20, g = 0xFF, b = 0x20;
480
481                         GUI::DrawBox(renderer, FONT_WIDTH * (le->r.x + labelLen + 1), FONT_HEIGHT * le->r.y, FONT_WIDTH * le->size, FONT_HEIGHT, r, g, b);
482                         GUI::DrawString(renderer, le->r.x + labelLen + 1, le->r.y, le->text);
483                         break;
484                 }
485
486                 case OTDraggable:
487                 {
488                         Draggable * d = (Draggable *)obj;
489                         SDL_RenderCopy(renderer, d->img, NULL, &d->r);
490                         break;
491                 }
492
493                 default:
494                         break;
495                 }
496         }
497 }
498
499
500 void Config::Render(SDL_Renderer * renderer)
501 {
502         if (!(window && showWindow))
503                 return;
504
505         if (refresh)
506         {
507                 SDL_SetRenderTarget(renderer, window);
508                 DrawElements(renderer);
509                 refresh = false;
510         }
511
512         SDL_SetRenderTarget(renderer, NULL);
513
514         SDL_Rect dst = { C_XPOS, C_YPOS, C_WIDTH, C_HEIGHT };
515         SDL_RenderCopy(renderer, window, NULL, &dst);
516 }
517