]> Shamusworld >> Repos - apple2/blob - src/gui/textedit.cpp
Undoing changes (accidentally) committed from r31.
[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 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 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 * c = (uint8 *)&hiliteColor;
48         c[0] = 0xFF, c[1] = 0x80, c[2] = 0x00, c[3] = 0xFF;
49         c = (uint8 *)&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(SDLKey key)
68 {
69         if (!activated)
70                 return;
71
72         SaveStateVariables();
73         SDLMod keyMod = SDL_GetModState();
74
75         if ((key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_0 && key <= SDLK_9)
76                 || key == SDLK_PERIOD || key == SDLK_SLASH || key == SDLK_SPACE)
77         {
78                 uint8 chr = (uint8)key;
79
80                 // Handle shift key as well...
81                 if (keyMod & KMOD_SHIFT)
82                 {
83                         if (key >= SDLK_a && key <= SDLK_z)
84                                 chr &= 0xDF;                                    // Set to upper case
85                 }
86
87                 text.insert(scrollPos + caretPos, 1, chr);
88
89                 // If we hit the edge, then scroll; else advance the caret
90                 if ((GetFontWidth() * caretPos) > (extents.w - GetFontWidth()))
91                         scrollPos++;
92                 else
93                         caretPos++;
94         }
95         else if (key == SDLK_BACKSPACE)
96         {
97                 // If there's something to delete, go ahead and delete it
98                 if ((scrollPos + caretPos) > 0)
99                 {
100                         text.erase(scrollPos + caretPos - 1, 1);
101
102                         // Scroll the cursor to the left if possible, otherwise move the scroll position
103                         if (caretPos > 0)
104                                 caretPos--;
105                         else
106                                 scrollPos--;
107                 }
108         }
109         else if (key == SDLK_DELETE)
110         {
111                 if ((scrollPos + caretPos) < text.length())
112                         text.erase(scrollPos + caretPos, 1);
113         }
114         else if (key == SDLK_LEFT)
115         {
116                 if (caretPos > 0)
117                         caretPos--;
118                 else if (scrollPos > 0)
119                         scrollPos--;
120         }
121         else if (key == SDLK_RIGHT)
122         {
123                 if ((scrollPos + caretPos) < text.length())
124                 {
125                         if ((GetFontWidth() * caretPos) > (extents.w - GetFontWidth()))
126                                 scrollPos++;
127                         else
128                                 caretPos++;
129                 }
130         }
131         else if (key == SDLK_RETURN)
132         {
133                 clicked = activated = false;
134         }
135
136         CheckStateAndRedrawIfNeeded();
137 }
138
139 void TextEdit::HandleMouseMove(uint32 x, uint32 y)
140 {
141         SaveStateVariables();
142         inside = Inside(x, y);
143         CheckStateAndRedrawIfNeeded();
144 }
145
146 void TextEdit::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
147 {
148         SaveStateVariables();
149
150 //Not sure that this is right way to handle this...
151 //Should set the cursor position based on where in the text box it was clicked...
152         if (inside)
153         {
154                 if (mouseDown)
155                         clicked = true;
156
157                 if (clicked && !mouseDown)
158                 {
159                         clicked = false, activated = true;
160
161                         // Send a message to our parent widget (if any) that we're activated
162                         if (parent)
163                                 parent->Notify(this);
164                 }
165         }
166         else
167                 clicked = activated = false;
168
169         CheckStateAndRedrawIfNeeded();
170 }
171
172 void TextEdit::Draw(void)
173 {
174         if (img == NULL)
175                 return;                                                                 // Bail out if no surface was created...
176
177         SDL_Rect rect = GetScreenCoords();
178
179         // Now, draw the appropriate text state!
180
181         if (!activated)
182         {
183                 if (inside)
184                 {
185                         SDL_Rect rect2;
186                         rect2.x = 1;
187                         rect2.y = 1;
188                         rect2.w = extents.w - 2;
189                         rect2.h = extents.h - 2;
190
191                         SDL_FillRect(img, NULL, hiliteColor);
192                         SDL_FillRect(img, &rect2, bgColor);
193                 }
194                 else
195                         SDL_FillRect(img, NULL, bgColor);
196         }
197         else
198                 SDL_FillRect(img, NULL, bgColor);//Make a different color here, so we're clear we're editing...
199
200 //Should also draw different text color depending on whether or not we're activated...
201         if (activated)
202                 DrawStringTrans(img, 0, 0, fgColor, text.c_str() + scrollPos);
203         else
204                 DrawStringTrans(img, 0, 0, fgColor, text.c_str());
205
206         // Draw the cursor, if any
207
208         if (activated)
209         {
210                 SDL_Rect rectCursor;
211                 rectCursor.x = caretPos * GetFontWidth();
212                 rectCursor.y = 0;
213                 rectCursor.w = 2;
214                 rectCursor.h = GetFontHeight();
215
216                 SDL_FillRect(img, &rectCursor, cursorColor);
217         }
218
219         SDL_BlitSurface(img, NULL, screen, &rect);      // This handles alpha blending too! :-D
220
221         needToRefreshScreen = true;
222 }
223
224 void TextEdit::Notify(Element *)
225 {
226 }
227
228 std::string TextEdit::GetText(void)
229 {
230         return text;
231 }
232
233 void TextEdit::SaveStateVariables(void)
234 {
235         activatedSave = activated;
236         clickedSave = clicked;
237         insideSave = inside;
238         caretPosSave = caretPos;
239         scrollPosSave = scrollPos;
240         lengthSave = text.length();
241 }
242
243 void TextEdit::CheckStateAndRedrawIfNeeded(void)
244 {
245         // Check to see if any of our state variables changed since we last saved them...
246         if (activated != activatedSave || clicked != clickedSave || inside != insideSave
247                 || caretPos != caretPosSave || scrollPos != scrollPosSave
248                 || text.length() != lengthSave)
249                 Draw();
250 }