]> Shamusworld >> Repos - apple2/blob - src/gui/textedit.cpp
Converted to SDL 2, added fullscreen toggle.
[apple2] / src / gui / textedit.cpp
1 //
2 // TEXTEDIT.CPP
3 //
4 // Graphical User Interface button class
5 // by James L. Hammons
6 //
7 // JLH = James L. Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  02/17/2006  Created this file
12 // JLH  03/01/2006  Added basic editing functionality
13 //
14
15 #include "textedit.h"
16 #include "guimisc.h"                                                            // Various support functions
17
18 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
19 #define MASK_R 0xFF000000
20 #define MASK_G 0x00FF0000
21 #define MASK_B 0x0000FF00
22 #define MASK_A 0x000000FF
23 #else
24 #define MASK_R 0x000000FF
25 #define MASK_G 0x0000FF00
26 #define MASK_B 0x00FF0000
27 #define MASK_A 0xFF000000
28 #endif
29
30 //
31 // Text edit class implementation
32 //
33
34 TextEdit::TextEdit(uint32_t x/*= 0*/, uint32_t y/*= 0*/, uint32_t w/*= 0*/, uint32_t h/*= 0*/,
35         std::string s/*= ""*/, Element * parent/*= NULL*/):
36         Element(x, y, w, h, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x40, 0x40, 0xFF, parent),
37         activated(false), clicked(false), inside(false),
38         img(NULL), text(s), caretPos(0), scrollPos(0),
39         activatedSave(false), clickedSave(false), insideSave(false),
40         caretPosSave(0), scrollPosSave(0)
41 {
42         if (extents.h == 0)
43                 extents.h = GetFontHeight();
44
45         // Setup hardwired colors...
46
47         uint8_t * c = (uint8_t *)&hiliteColor;
48         c[0] = 0xFF, c[1] = 0x80, c[2] = 0x00, c[3] = 0xFF;
49         c = (uint8_t *)&cursorColor;
50         c[0] = 0x40, c[1] = 0xFF, c[2] = 0x60, c[3] = 0xFF;
51
52         // Create the text edit surface here...
53
54         img = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
55                 MASK_R, MASK_G, MASK_B, MASK_A);
56
57         Draw(); // Can we do this in the constructor??? Mebbe.
58 }
59
60 TextEdit::~TextEdit()
61 {
62         if (img)
63                 SDL_FreeSurface(img);
64 }
65
66 //Set different filters depending on type passed in on construction, e.g., filename, amount, etc...?
67 void TextEdit::HandleKey(SDL_Scancode key)
68 {
69         if (!activated)
70                 return;
71
72 // Punting this for now on SDL 2...
73 #if 0
74         SaveStateVariables();
75         SDLMod keyMod = SDL_GetModState();
76
77         if ((key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_0 && key <= SDLK_9)
78                 || key == SDLK_PERIOD || key == SDLK_SLASH || key == SDLK_SPACE)
79         {
80                 uint8_t chr = (uint8_t)key;
81
82                 // Handle shift key as well...
83                 if (keyMod & KMOD_SHIFT)
84                 {
85                         if (key >= SDLK_a && key <= SDLK_z)
86                                 chr &= 0xDF;                                    // Set to upper case
87                 }
88
89                 text.insert(scrollPos + caretPos, 1, chr);
90
91                 // If we hit the edge, then scroll; else advance the caret
92                 if ((GetFontWidth() * caretPos) > (extents.w - GetFontWidth()))
93                         scrollPos++;
94                 else
95                         caretPos++;
96         }
97         else if (key == SDLK_BACKSPACE)
98         {
99                 // If there's something to delete, go ahead and delete it
100                 if ((scrollPos + caretPos) > 0)
101                 {
102                         text.erase(scrollPos + caretPos - 1, 1);
103
104                         // Scroll the cursor to the left if possible, otherwise move the scroll position
105                         if (caretPos > 0)
106                                 caretPos--;
107                         else
108                                 scrollPos--;
109                 }
110         }
111         else if (key == SDLK_DELETE)
112         {
113                 if ((scrollPos + caretPos) < text.length())
114                         text.erase(scrollPos + caretPos, 1);
115         }
116         else if (key == SDLK_LEFT)
117         {
118                 if (caretPos > 0)
119                         caretPos--;
120                 else if (scrollPos > 0)
121                         scrollPos--;
122         }
123         else if (key == SDLK_RIGHT)
124         {
125                 if ((scrollPos + caretPos) < text.length())
126                 {
127                         if ((GetFontWidth() * caretPos) > (extents.w - GetFontWidth()))
128                                 scrollPos++;
129                         else
130                                 caretPos++;
131                 }
132         }
133         else if (key == SDLK_RETURN)
134         {
135                 clicked = activated = false;
136         }
137
138         CheckStateAndRedrawIfNeeded();
139 #endif
140 }
141
142 void TextEdit::HandleMouseMove(uint32_t x, uint32_t y)
143 {
144         SaveStateVariables();
145         inside = Inside(x, y);
146         CheckStateAndRedrawIfNeeded();
147 }
148
149 void TextEdit::HandleMouseButton(uint32_t x, uint32_t y, bool mouseDown)
150 {
151         SaveStateVariables();
152
153 //Not sure that this is right way to handle this...
154 //Should set the cursor position based on where in the text box it was clicked...
155         if (inside)
156         {
157                 if (mouseDown)
158                         clicked = true;
159
160                 if (clicked && !mouseDown)
161                 {
162                         clicked = false, activated = true;
163
164                         // Send a message to our parent widget (if any) that we're activated
165                         if (parent)
166                                 parent->Notify(this);
167                 }
168         }
169         else
170                 clicked = activated = false;
171
172         CheckStateAndRedrawIfNeeded();
173 }
174
175 void TextEdit::Draw(void)
176 {
177         if (img == NULL)
178                 return;                                                                 // Bail out if no surface was created...
179
180         SDL_Rect rect = GetScreenCoords();
181
182         // Now, draw the appropriate text state!
183
184         if (!activated)
185         {
186                 if (inside)
187                 {
188                         SDL_Rect rect2;
189                         rect2.x = 1;
190                         rect2.y = 1;
191                         rect2.w = extents.w - 2;
192                         rect2.h = extents.h - 2;
193
194                         SDL_FillRect(img, NULL, hiliteColor);
195                         SDL_FillRect(img, &rect2, bgColor);
196                 }
197                 else
198                         SDL_FillRect(img, NULL, bgColor);
199         }
200         else
201                 SDL_FillRect(img, NULL, bgColor);//Make a different color here, so we're clear we're editing...
202
203 //Should also draw different text color depending on whether or not we're activated...
204         if (activated)
205                 DrawStringTrans(img, 0, 0, fgColor, text.c_str() + scrollPos);
206         else
207                 DrawStringTrans(img, 0, 0, fgColor, text.c_str());
208
209         // Draw the cursor, if any
210
211         if (activated)
212         {
213                 SDL_Rect rectCursor;
214                 rectCursor.x = caretPos * GetFontWidth();
215                 rectCursor.y = 0;
216                 rectCursor.w = 2;
217                 rectCursor.h = GetFontHeight();
218
219                 SDL_FillRect(img, &rectCursor, cursorColor);
220         }
221
222         SDL_BlitSurface(img, NULL, screen, &rect);      // This handles alpha blending too! :-D
223
224         needToRefreshScreen = true;
225 }
226
227 void TextEdit::Notify(Element *)
228 {
229 }
230
231 std::string TextEdit::GetText(void)
232 {
233         return text;
234 }
235
236 void TextEdit::SaveStateVariables(void)
237 {
238         activatedSave = activated;
239         clickedSave = clicked;
240         insideSave = inside;
241         caretPosSave = caretPos;
242         scrollPosSave = scrollPos;
243         lengthSave = text.length();
244 }
245
246 void TextEdit::CheckStateAndRedrawIfNeeded(void)
247 {
248         // Check to see if any of our state variables changed since we last saved them...
249         if (activated != activatedSave || clicked != clickedSave || inside != insideSave
250                 || caretPos != caretPosSave || scrollPos != scrollPosSave
251                 || text.length() != lengthSave)
252                 Draw();
253 }