4 // Graphical User Interface button class
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 02/17/2006 Created this file
12 // JLH 03/01/2006 Added basic editing functionality
16 #include "guimisc.h" // Various support functions
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
24 #define MASK_R 0x000000FF
25 #define MASK_G 0x0000FF00
26 #define MASK_B 0x00FF0000
27 #define MASK_A 0xFF000000
31 // Text edit class implementation
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)
43 extents.h = GetFontHeight();
45 // Setup hardwired colors...
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;
52 // Create the text edit surface here...
54 img = SDL_CreateRGBSurface(SDL_SWSURFACE, extents.w, extents.h, 32,
55 MASK_R, MASK_G, MASK_B, MASK_A);
57 Draw(); // Can we do this in the constructor??? Mebbe.
66 //Set different filters depending on type passed in on construction, e.g., filename, amount, etc...?
67 void TextEdit::HandleKey(SDL_Scancode key)
72 // Punting this for now on SDL 2...
75 SDLMod keyMod = SDL_GetModState();
77 if ((key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_0 && key <= SDLK_9)
78 || key == SDLK_PERIOD || key == SDLK_SLASH || key == SDLK_SPACE)
80 uint8_t chr = (uint8_t)key;
82 // Handle shift key as well...
83 if (keyMod & KMOD_SHIFT)
85 if (key >= SDLK_a && key <= SDLK_z)
86 chr &= 0xDF; // Set to upper case
89 text.insert(scrollPos + caretPos, 1, chr);
91 // If we hit the edge, then scroll; else advance the caret
92 if ((GetFontWidth() * caretPos) > (extents.w - GetFontWidth()))
97 else if (key == SDLK_BACKSPACE)
99 // If there's something to delete, go ahead and delete it
100 if ((scrollPos + caretPos) > 0)
102 text.erase(scrollPos + caretPos - 1, 1);
104 // Scroll the cursor to the left if possible, otherwise move the scroll position
111 else if (key == SDLK_DELETE)
113 if ((scrollPos + caretPos) < text.length())
114 text.erase(scrollPos + caretPos, 1);
116 else if (key == SDLK_LEFT)
120 else if (scrollPos > 0)
123 else if (key == SDLK_RIGHT)
125 if ((scrollPos + caretPos) < text.length())
127 if ((GetFontWidth() * caretPos) > (extents.w - GetFontWidth()))
133 else if (key == SDLK_RETURN)
135 clicked = activated = false;
138 CheckStateAndRedrawIfNeeded();
142 void TextEdit::HandleMouseMove(uint32_t x, uint32_t y)
144 SaveStateVariables();
145 inside = Inside(x, y);
146 CheckStateAndRedrawIfNeeded();
149 void TextEdit::HandleMouseButton(uint32_t x, uint32_t y, bool mouseDown)
151 SaveStateVariables();
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...
160 if (clicked && !mouseDown)
162 clicked = false, activated = true;
164 // Send a message to our parent widget (if any) that we're activated
166 parent->Notify(this);
170 clicked = activated = false;
172 CheckStateAndRedrawIfNeeded();
175 void TextEdit::Draw(void)
178 return; // Bail out if no surface was created...
180 SDL_Rect rect = GetScreenCoords();
182 // Now, draw the appropriate text state!
191 rect2.w = extents.w - 2;
192 rect2.h = extents.h - 2;
194 SDL_FillRect(img, NULL, hiliteColor);
195 SDL_FillRect(img, &rect2, bgColor);
198 SDL_FillRect(img, NULL, bgColor);
201 SDL_FillRect(img, NULL, bgColor);//Make a different color here, so we're clear we're editing...
203 //Should also draw different text color depending on whether or not we're activated...
205 DrawStringTrans(img, 0, 0, fgColor, text.c_str() + scrollPos);
207 DrawStringTrans(img, 0, 0, fgColor, text.c_str());
209 // Draw the cursor, if any
214 rectCursor.x = caretPos * GetFontWidth();
217 rectCursor.h = GetFontHeight();
219 SDL_FillRect(img, &rectCursor, cursorColor);
222 SDL_BlitSurface(img, NULL, screen, &rect); // This handles alpha blending too! :-D
224 needToRefreshScreen = true;
227 void TextEdit::Notify(Element *)
231 std::string TextEdit::GetText(void)
236 void TextEdit::SaveStateVariables(void)
238 activatedSave = activated;
239 clickedSave = clicked;
241 caretPosSave = caretPos;
242 scrollPosSave = scrollPos;
243 lengthSave = text.length();
246 void TextEdit::CheckStateAndRedrawIfNeeded(void)
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)