The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
textbox.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
3 by David White <dave@whitevine.net>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#define GETTEXT_DOMAIN "wesnoth-lib"
17
18#include "widgets/textbox.hpp"
19
20#include "cursor.hpp"
21#include "desktop/clipboard.hpp"
22#include "draw.hpp"
24#include "log.hpp"
25#include "sdl/rect.hpp"
27#include "sdl/input.hpp" // get_mouse_state
28#if defined(__ANDROID__) || defined(__IPHONEOS__)
29#include "video.hpp"
30#endif
31
32#include <SDL3/SDL_timer.h>
33
34static lg::log_domain log_display("display");
35#define WRN_DP LOG_STREAM(warn, log_display)
36#define DBG_G LOG_STREAM(debug, lg::general())
37
38namespace gui {
39
40textbox::textbox(int width, const std::string& text, bool editable, std::size_t max_size, int font_size, double alpha, double alpha_focus, const bool auto_join)
41 : scrollarea(auto_join), max_size_(max_size), font_size_(font_size), text_(unicode_cast<std::u32string>(text)),
42 cursor_(text_.size()), selstart_(-1), selend_(-1),
43 grabmouse_(false), text_pos_(0), editable_(editable),
44 show_cursor_(true), show_cursor_at_(0), text_image_(nullptr),
45 wrap_(false), line_height_(0), yscroll_(0), alpha_(alpha),
46 alpha_focus_(alpha_focus),
47 edit_target_(nullptr)
48 ,listening_(false)
49{
53}
54
56{
57 // Restore the cursor on destruction if we (probably) set it to IBEAM
58 if(cursor::get() == cursor::IBEAM) {
60 }
61}
62
69
70void textbox::set_inner_location(const rect& /*rect*/)
71{
72 if (!text_image_) return;
73 text_pos_ = 0;
74 update_text_cache(false);
75}
76
77const std::string textbox::text() const
78{
79 const std::string &ret = unicode_cast<std::string>(text_);
80 return ret;
81}
82
83// set_text does not respect max_size_
84void textbox::set_text(const std::string& text, const color_t& color)
85{
86 text_ = unicode_cast<std::u32string>(text);
87 cursor_ = text_.size();
88 text_pos_ = 0;
89 selstart_ = -1;
90 selend_ = -1;
92 update_text_cache(true, color);
94}
95
96void textbox::append_text(const std::string& text, bool auto_scroll, const color_t& color)
97{
98 if(!text_image_) {
99 set_text(text, color);
100 return;
101 }
102
103 //disallow adding multi-line text to a single-line text box
104 if(wrap_ == false && std::find_if(text.begin(),text.end(),utils::isnewline) != text.end()) {
105 return;
106 }
107
108 const std::u32string& wtext = unicode_cast<std::u32string>(text);
109 text_.insert(text_.end(), wtext.begin(), wtext.end());
110
112
113 queue_redraw();
114 update_text_cache(false);
115 const bool is_at_bottom = get_position() == get_max_position();
116 if(auto_scroll && is_at_bottom) scroll_to_bottom();
118}
119
121{
122 text_.clear();
123 cursor_ = 0;
124 cursor_pos_ = 0;
125 text_pos_ = 0;
126 selstart_ = -1;
127 selend_ = -1;
128 queue_redraw();
129 update_text_cache(true);
131}
132
133void textbox::set_selection(const int selstart, const int selend)
134{
135 if (!editable_) {
136 return;
137 }
138 if (selstart < 0 || selend < 0 || std::size_t(selstart) > text_.size() ||
139 std::size_t(selend) > text_.size()) {
140 WRN_DP << "out-of-boundary selection";
141 return;
142 }
143 selstart_= selstart;
144 selend_ = selend;
145 queue_redraw();
146}
147
148void textbox::set_cursor_pos(const int cursor_pos)
149{
150 if (!editable_) {
151 return;
152 }
153 if (cursor_pos < 0 || std::size_t(cursor_pos) > text_.size()) {
154 WRN_DP << "out-of-boundary selection";
155 return;
156 }
157
158 cursor_ = cursor_pos;
159 update_text_cache(false);
160 queue_redraw();
161}
162
163void textbox::draw_cursor(int pos) const
164{
165 if(show_cursor_ && editable_ && enabled()) {
166 rect rect {
167 location().x + pos
168 , location().y
169 , 1
170 , location().h
171 };
172
173 draw::fill(rect, 255, 255, 255, 255);
174 }
175}
176
178{
179 if(text_image_ == nullptr) {
180 update_text_cache(true);
181 }
182}
183
185{
186 const rect& loc = inner_location();
187
188 color_t c(0, 0, 0);
189
190 double& alpha = focus(nullptr) ? alpha_focus_ : alpha_;
191 c.a = 255 * alpha;
192
193 draw::fill(loc, c);
194
195 rect src;
196
197 if(text_image_ != nullptr) {
198 src.y = yscroll_;
199 src.w = std::min<std::size_t>(loc.w,text_image_.w());
200 src.h = std::min<std::size_t>(loc.h,text_image_.h());
201 src.x = text_pos_;
202 rect dest{loc.x, loc.y, src.w, src.h};
203
204 // Fills the selected area
205 if(enabled() && is_selection()) {
206 const int start = std::min<int>(selstart_,selend_);
207 const int end = std::max<int>(selstart_,selend_);
208 int startx = char_x_[start];
209 int starty = char_y_[start];
210 const int endx = char_x_[end];
211 const int endy = char_y_[end];
212
213 auto clipper = draw::reduce_clip(loc);
214
215 while(starty <= endy) {
216 const std::size_t right = starty == endy ? endx : text_image_.w();
217 if(right <= std::size_t(startx)) {
218 break;
219 }
220
221 rect r(loc.x + startx
222 , loc.y + starty - src.y
223 , right - startx
224 , line_height_);
225
226 draw::fill(r, 0, 0, 160, 140);
227
228 starty += int(line_height_);
229 startx = 0;
230 }
231 }
232
233 // Set the source region on the texture.
235
236 if(enabled()) {
237 draw::blit(text_image_, dest);
238 } else {
239 // HACK: using 30% opacity allows white text to look as though it is grayed out,
240 // while not changing any applicable non-grayscale AA. Actual colored text will
241 // not look as good, but this is not currently a concern since GUI1 textboxes
242 // are not used much nowadays, and they will eventually all go away.
244 draw::blit(text_image_, dest);
246 }
247
248 // This doesn't really need to be cleared, but why not.
250 }
251
252 draw_cursor(cursor_pos_ == 0 ? 0 : cursor_pos_ - 1);
253}
254
256{
258}
259
261{
262 return editable_;
263}
264
266{
267 return font_size_;
268}
269
271{
272 font_size_ = fs;
273}
274
279
280void textbox::set_wrap(bool val)
281{
282 if(wrap_ != val) {
283 wrap_ = val;
284 update_text_cache(true);
285 queue_redraw();
286 }
287}
288
289void textbox::scroll(unsigned int pos)
290{
291 yscroll_ = pos;
292 queue_redraw();
293}
294
295texture textbox::add_text_line(const std::u32string& text, const color_t& color)
296{
298
299 if(char_y_.empty()) {
300 char_y_.push_back(0);
301 } else {
302 char_y_.push_back(char_y_.back() + line_height_);
303 }
304
305 char_x_.push_back(0);
306
307 // Re-calculate the position of each glyph. We approximate this by asking the
308 // width of each substring, but this is a flawed assumption which won't work with
309 // some more complex scripts (that is, RTL languages). This part of the work should
310 // actually be done by the font-rendering system.
311 std::string visible_string;
312 std::u32string wrapped_text;
313
314 std::u32string::const_iterator backup_itor = text.end();
315
316 std::u32string::const_iterator itor = text.begin();
317 while(itor != text.end()) {
318 //If this is a space, save copies of the current state so we can roll back
319 if(char(*itor) == ' ') {
320 backup_itor = itor;
321 }
322 visible_string.append(unicode_cast<std::string>(*itor));
323
324 if(char(*itor) == '\n') {
325 backup_itor = text.end();
326 visible_string = "";
327 }
328
329 auto [w, _] = font::pango_line_size(visible_string, font_size_);
330
331 if(wrap_ && w >= inner_location().w) {
332 if(backup_itor != text.end()) {
333 int backup = itor - backup_itor;
334 itor = backup_itor + 1;
335 if(backup > 0) {
336 char_x_.erase(char_x_.end()-backup, char_x_.end());
337 char_y_.erase(char_y_.end()-backup, char_y_.end());
338 wrapped_text.erase(wrapped_text.end()-backup, wrapped_text.end());
339 }
340 } else {
341 if (visible_string == std::string("").append(unicode_cast<std::string>(*itor))) {
342 break; //breaks infinite loop where when running with a fake display, we word wrap a single character infinitely.
343 }
344 }
345 backup_itor = text.end();
346 wrapped_text.push_back(char32_t('\n'));
347 char_x_.push_back(0);
348 char_y_.push_back(char_y_.back() + line_height_);
349 visible_string = "";
350 } else {
351 wrapped_text.push_back(*itor);
352 char_x_.push_back(w);
353 char_y_.push_back(char_y_.back() + (char(*itor) == '\n' ? line_height_ : 0));
354 ++itor;
355 }
356 }
357
358 const std::string s = unicode_cast<std::string>(wrapped_text);
359 return font::pango_render_text(s, font_size_, color);
360}
361
362
363void textbox::update_text_cache(bool changed, const color_t& color)
364{
365 if(changed) {
366 char_x_.clear();
367 char_y_.clear();
368
370 }
371
372 int cursor_x = char_x_[cursor_];
373
374 if(cursor_x - text_pos_ > location().w) {
375 text_pos_ = cursor_x - location().w;
376 } else if(cursor_x - text_pos_ < 0) {
377 text_pos_ = cursor_x;
378 }
379 cursor_pos_ = cursor_x - text_pos_;
380
381 if (text_image_) {
384 }
385}
386
388{
389 return (selstart_ != -1) && (selend_ != -1) && (selstart_ != selend_);
390}
391
393{
394 if(!is_selection())
395 return;
396
397 std::u32string::iterator itor = text_.begin() + std::min(selstart_, selend_);
398 text_.erase(itor, itor + std::abs(selend_ - selstart_));
399 cursor_ = std::min(selstart_, selend_);
400 selstart_ = selend_ = -1;
401}
402
403namespace {
404 const unsigned int copypaste_modifier =
405#ifdef __APPLE__
406 SDL_KMOD_LGUI | SDL_KMOD_RGUI
407#else
408 SDL_KMOD_CTRL
409#endif
410 ;
411}
412
413bool textbox::requires_event_focus(const SDL_Event* event) const
414{
415 if(!focus_ || hidden() || !enabled()) {
416 return false;
417 }
418 if(event == nullptr) {
419 //when event is not specified, signal that focus may be desired later
420 return true;
421 }
422
423 if(event->type == SDL_EVENT_KEY_DOWN) {
424 SDL_Keycode key = event->key.key;
425 switch(key) {
426 case SDLK_UP:
427 case SDLK_DOWN:
428 case SDLK_PAGEUP:
429 case SDLK_PAGEDOWN:
430 //in the future we may need to check for input history or multi-line support
431 //for now, just return false since these events are not handled.
432 return false;
433 default:
434 return true;
435 }
436 }
437 //mouse events are processed regardless of focus
438 return false;
439}
440
441void textbox::handle_event(const SDL_Event& event)
442{
444 handle_event(event, false);
445}
446
447bool textbox::handle_text_input(const SDL_Event& event)
448{
449 bool changed = false;
450 std::string str = event.text.text;
451 std::u32string s = unicode_cast<std::u32string>(str);
452
453 DBG_G << "Char: " << str;
454
455 if (editable_) {
456 changed = true;
457 if (is_selection())
459
460 if (text_.size() + 1 <= max_size_) {
461
462 text_.insert(text_.begin() + cursor_, s.begin(), s.end());
463 cursor_ += s.size();
464 }
465 } else {
467 }
468 return changed;
469}
470
471bool textbox::handle_key_down(const SDL_Event &event)
472{
473 bool changed = false;
474
475 const SDL_Keymod modifiers = SDL_GetModState();
476
477 const int c = reinterpret_cast<const SDL_KeyboardEvent&>(event).key;
478 const int old_cursor = cursor_;
479
480 listening_ = true;
481
482 if(editable_) {
483 if(c == SDLK_LEFT && cursor_ > 0)
484 --cursor_;
485
486 if(c == SDLK_RIGHT && cursor_ < static_cast<int>(text_.size()))
487 ++cursor_;
488
489 // ctrl-a, ctrl-e and ctrl-u are readline style shortcuts, even on Macs
490 if(c == SDLK_END || (c == SDLK_E && (modifiers & SDL_KMOD_CTRL)))
491 cursor_ = text_.size();
492
493 if(c == SDLK_HOME || (c == SDLK_A && (modifiers & SDL_KMOD_CTRL)))
494 cursor_ = 0;
495
496 if((old_cursor != cursor_) && (modifiers & SDL_KMOD_SHIFT)) {
497 if(selstart_ == -1)
498 selstart_ = old_cursor;
500 }
501 } else if(c == SDLK_LEFT || c == SDLK_RIGHT || c == SDLK_END || c == SDLK_HOME) {
503 }
504
505 if(editable_) {
506 if(c == SDLK_BACKSPACE) {
507 changed = true;
508 if(is_selection()) {
510 } else if(cursor_ > 0) {
511 --cursor_;
512 text_.erase(text_.begin()+cursor_);
513 }
514 }
515
516 if(c == SDLK_U && (modifiers & SDL_KMOD_CTRL)) { // clear line
517 changed = true;
518 cursor_ = 0;
519 text_.resize(0);
520 }
521
522 if(c == SDLK_DELETE && !text_.empty()) {
523 changed = true;
524 if(is_selection()) {
526 } else {
527 if(cursor_ < static_cast<int>(text_.size())) {
528 text_.erase(text_.begin()+cursor_);
529 }
530 }
531 }
532 } else if(c == SDLK_BACKSPACE || c == SDLK_DELETE || (c == SDLK_U && (modifiers & SDL_KMOD_CTRL))) {
534 }
535
536
537 //movement characters may have a "Unicode" field on some platforms, so ignore it.
538 if(!(c == SDLK_UP || c == SDLK_DOWN || c == SDLK_LEFT || c == SDLK_RIGHT ||
539 c == SDLK_DELETE || c == SDLK_BACKSPACE || c == SDLK_END || c == SDLK_HOME ||
540 c == SDLK_PAGEUP || c == SDLK_PAGEDOWN)) {
541 if((event.key.mod & copypaste_modifier)
542 //on windows SDL fires for AltGr lctrl+ralt (needed to access @ etc on certain keyboards)
543#ifdef _WIN32
544 //&& !(event.key.keysym.mod & SDL_KMOD_ALT)
545#endif
546 ) {
547 switch(c) {
548 case SDLK_V: // paste
549 {
550 if(!editable()) {
552 break;
553 }
554
555 changed = true;
556 if(is_selection())
558
559 std::string str = desktop::clipboard::copy_from_clipboard();
560
561 //cut off anything after the first newline
562 str.erase(std::find_if(str.begin(),str.end(),utils::isnewline),str.end());
563
564 std::u32string s = unicode_cast<std::u32string>(str);
565
566 if(text_.size() < max_size_) {
567 if(s.size() + text_.size() > max_size_) {
568 s.resize(max_size_ - text_.size());
569 }
570 text_.insert(text_.begin()+cursor_, s.begin(), s.end());
571 cursor_ += s.size();
572 }
573
574 }
575
576 break;
577
578 case SDLK_C: // copy
579 {
580 if(is_selection())
581 {
582 const std::size_t beg = std::min<std::size_t>(std::size_t(selstart_),std::size_t(selend_));
583 const std::size_t end = std::max<std::size_t>(std::size_t(selstart_),std::size_t(selend_));
584
585 std::u32string ws(text_.begin() + beg, text_.begin() + end);
586 std::string s = unicode_cast<std::string>(ws);
588 }
589 }
590 break;
591
592 case SDLK_X: // cut
593 {
594 if(is_selection())
595 {
596 const std::size_t beg = std::min<std::size_t>(std::size_t(selstart_),std::size_t(selend_));
597 const std::size_t end = std::max<std::size_t>(std::size_t(selstart_),std::size_t(selend_));
598
599 std::u32string ws(text_.begin() + beg, text_.begin() + end);
600 std::string s = unicode_cast<std::string>(ws);
603 }
604 break;
605 }
606 case SDLK_A: // selectall
607 {
608 set_selection(0, text_.size());
609 break;
610 }
611 }//end switch
612 }
613 else {
615 }
616 }
617
618 return changed;
619}
620
621void textbox::handle_event(const SDL_Event& event, bool was_forwarded)
622{
623 if(!enabled())
624 return;
625
627 if(hidden())
628 return;
629
630 bool changed = false;
631
632 const int old_selstart = selstart_;
633 const int old_selend = selend_;
634
635 //Sanity check: verify that selection start and end are within text
636 //boundaries
637 if(is_selection() && !(std::size_t(selstart_) <= text_.size() && std::size_t(selend_) <= text_.size())) {
638 WRN_DP << "out-of-boundary selection";
639 selstart_ = selend_ = -1;
640 }
641
642 float mousex, mousey;
643 const uint8_t mousebuttons = sdl::get_mouse_state(&mousex,&mousey);
644 if(!(mousebuttons & SDL_BUTTON_MASK(1))) {
645 grabmouse_ = false;
646 }
647
648 const rect loc = inner_location();
649
650 const bool mouse_inside = loc.contains(mousex, mousey);
651
652#if defined(__ANDROID__) || defined(__IPHONEOS__)
653 if(mouse_inside) {
654 // Show onscreen keyboard
655 SDL_StartTextInput(video::get_window());
656 }
657#endif
658
659 // Someone else may set the mouse cursor for us to something unusual (e.g.
660 // the WAIT cursor) so we ought to mess with that only if it's set to
661 // NORMAL or IBEAM.
662
663 if(mouse_inside && cursor::get() == cursor::NORMAL) {
665 } else if(!mouse_inside && cursor::get() == cursor::IBEAM) {
667 }
668
669 bool clicked_inside = !mouse_locked() && (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN
670 && (mousebuttons & SDL_BUTTON_MASK(1))
671 && mouse_inside);
672 if(clicked_inside) {
673 set_focus(true);
674 }
675 if ((grabmouse_ && (!mouse_locked() && event.type == SDL_EVENT_MOUSE_MOTION)) || clicked_inside) {
676 const int x = mousex - loc.x + text_pos_;
677 const int y = mousey - loc.y;
678 int pos = 0;
679 int distance = x;
680
681 for(unsigned int i = 1; i < char_x_.size(); ++i) {
682 if(static_cast<int>(yscroll_) + y < char_y_[i]) {
683 break;
684 }
685
686 // Check individually each distance (if, one day, we support
687 // RTL languages, char_x_[c] may not be monotonous.)
688 if(std::abs(x - char_x_[i]) < distance && yscroll_ + y < char_y_[i] + line_height_) {
689 pos = i;
690 distance = std::abs(x - char_x_[i]);
691 }
692 }
693
694 cursor_ = pos;
695
696 if(grabmouse_)
698
699 update_text_cache(false);
700
701 if(!grabmouse_ && (mousebuttons & SDL_BUTTON_MASK(1))) {
702 grabmouse_ = true;
704 } else if (! (mousebuttons & SDL_BUTTON_MASK(1))) {
705 grabmouse_ = false;
706 }
707
708 queue_redraw();
709 }
710
711 //if we don't have the focus, then see if we gain the focus,
712 //otherwise return
713 if(!was_forwarded && focus(&event) == false) {
714 if (!mouse_locked() && event.type == SDL_EVENT_MOUSE_MOTION && loc.contains(mousex, mousey))
716
717 return;
718 }
719
720 const int old_cursor = cursor_;
721
722 if (event.type == SDL_EVENT_TEXT_INPUT && listening_) {
723 changed = handle_text_input(event);
724 } else if (event.type == SDL_EVENT_KEY_DOWN) {
725 changed = handle_key_down(event);
726 }
727
728 if(is_selection() && (selend_ != cursor_))
729 selstart_ = selend_ = -1;
730
731 //since there has been cursor activity, make the cursor appear for
732 //at least the next 500ms.
733 show_cursor_ = true;
734 show_cursor_at_ = SDL_GetTicks();
735
736 if(changed || old_cursor != cursor_ || old_selstart != selstart_ || old_selend != selend_) {
739 }
740
741 queue_redraw();
742}
743
744void textbox::pass_event_to_target(const SDL_Event& event)
745{
747 edit_target_->handle_event(event, true);
748 }
749}
750
752{
753 edit_target_ = target;
754}
755
756} //end namespace gui
map_location loc
Definition move.cpp:172
virtual void update_location(const rect &rect)
unsigned get_max_position() const
void set_shown_size(unsigned h)
unsigned get_position() const
void set_full_size(unsigned h)
void set_position(unsigned pos)
rect inner_location() const
virtual void handle_event(const SDL_Event &event)
void set_scroll_rate(unsigned r)
bool handle_text_input(const SDL_Event &event)
Definition textbox.cpp:447
double alpha_focus_
Definition textbox.hpp:96
textbox(int width, const std::string &text="", bool editable=true, std::size_t max_size=256, int font_size=font::SIZE_PLUS, double alpha=0.4, double alpha_focus=0.2, const bool auto_join=true)
Definition textbox.cpp:40
int show_cursor_at_
Definition textbox.hpp:88
virtual void set_inner_location(const rect &) override
Definition textbox.cpp:70
virtual void scroll(unsigned int pos) override
Definition textbox.cpp:289
void set_wrap(bool val)
Definition textbox.cpp:280
void scroll_to_bottom()
Definition textbox.cpp:275
const std::string text() const
Definition textbox.cpp:77
void erase_selection()
Definition textbox.cpp:392
void set_cursor_pos(const int cursor_pos)
Definition textbox.cpp:148
void set_selection(const int selstart, const int selend)
Definition textbox.cpp:133
std::size_t line_height_
Definition textbox.hpp:93
bool editable() const
Definition textbox.cpp:260
void pass_event_to_target(const SDL_Event &event)
Definition textbox.cpp:744
bool show_cursor_
Definition textbox.hpp:83
void set_text(const std::string &text, const color_t &color=font::NORMAL_COLOR)
Definition textbox.cpp:84
virtual void draw_contents() override
Definition textbox.cpp:184
virtual ~textbox()
Definition textbox.cpp:55
void draw_cursor(int pos) const
Definition textbox.cpp:163
void set_font_size(int fs)
Definition textbox.cpp:270
void set_editable(bool value)
Definition textbox.cpp:255
bool grabmouse_
Definition textbox.hpp:75
bool editable_
Definition textbox.hpp:81
textbox * edit_target_
Definition textbox.hpp:98
std::size_t yscroll_
Definition textbox.hpp:93
void clear()
Definition textbox.cpp:120
void handle_event(const SDL_Event &event, bool was_forwarded)
Definition textbox.cpp:621
bool is_selection()
Definition textbox.cpp:387
bool handle_key_down(const SDL_Event &event)
Definition textbox.cpp:471
std::vector< int > char_x_
Definition textbox.hpp:79
bool requires_event_focus(const SDL_Event *event=nullptr) const override
Definition textbox.cpp:413
bool listening_
Definition textbox.hpp:104
int font_size() const
Definition textbox.cpp:265
std::u32string text_
Definition textbox.hpp:69
double alpha_
Definition textbox.hpp:95
virtual void layout() override
Called by draw_manager to validate layout.
Definition textbox.cpp:177
void set_edit_target(textbox *target)
Definition textbox.cpp:751
texture text_image_
Definition textbox.hpp:89
int cursor_pos_
Definition textbox.hpp:78
void append_text(const std::string &text, bool auto_scroll=false, const color_t &color=font::NORMAL_COLOR)
Definition textbox.cpp:96
void update_text_cache(bool reset=false, const color_t &color=font::NORMAL_COLOR)
Definition textbox.cpp:363
std::vector< int > char_y_
Definition textbox.hpp:79
std::size_t max_size_
Definition textbox.hpp:65
virtual void update_location(const rect &rect) override
Definition textbox.cpp:63
texture add_text_line(const std::u32string &text, const color_t &color=font::NORMAL_COLOR)
Definition textbox.cpp:295
virtual void handle_text_changed(const std::u32string &)
Definition textbox.hpp:63
virtual void handle_event(const SDL_Event &) override
Definition widget.hpp:90
bool focus(const SDL_Event *event)
Definition widget.cpp:136
void set_measurements(int w, int h)
Definition widget.cpp:108
const rect & location() const
Definition widget.cpp:123
int width() const
Definition widget.cpp:113
void queue_redraw()
Indicate that the widget should be redrawn.
Definition widget.cpp:215
bool enabled() const
Definition widget.cpp:175
void set_focus(bool focus)
Definition widget.cpp:128
bool hidden() const
Definition widget.cpp:161
bool mouse_locked() const
Definition widget.cpp:64
bool focus_
Definition widget.hpp:91
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition texture.hpp:33
int w() const
The draw-space width of the texture, in pixels.
Definition texture.hpp:103
void reset()
Releases ownership of the managed texture and resets the ptr to null.
Definition texture.cpp:202
void set_src(const rect &r)
Set the source region of the texture used for drawing operations.
Definition texture.cpp:122
int h() const
The draw-space height of the texture, in pixels.
Definition texture.hpp:112
void set_alpha_mod(uint8_t alpha)
Alpha modifier.
Definition texture.cpp:146
void clear_src()
Clear the source region.
Definition texture.hpp:165
#define WRN_DP
Definition display.cpp:77
Drawing functions, for drawing things on the screen.
#define DBG_G
Definition gettext.cpp:36
static std::string _(const char *str)
Definition gettext.hpp:100
Contains functions for cleanly handling SDL input.
Standard logging facilities (interface).
CURSOR_TYPE get()
Definition cursor.cpp:185
@ NORMAL
Definition cursor.hpp:28
@ IBEAM
Definition cursor.hpp:28
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition cursor.cpp:151
void copy_to_clipboard(const std::string &text)
Copies text to the clipboard.
Definition clipboard.cpp:24
std::string copy_from_clipboard()
Copies text from the clipboard.
Definition clipboard.cpp:29
clip_setter reduce_clip(const ::rect &clip)
Set the clipping area to the intersection of the current clipping area and the given rectangle.
Definition draw.cpp:595
void fill()
Definition draw.cpp:115
void blit(const texture &tex, const ::rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition draw.cpp:409
void focus_handler(const sdl_handler *ptr)
Definition events.cpp:402
int get_max_height(unsigned size, font::family_class fclass, pango_text::FONT_STYLE style)
Returns the maximum glyph height of a font, in pixels.
Definition text.cpp:958
std::pair< int, int > pango_line_size(const std::string &line, int font_size, font::pango_text::FONT_STYLE font_style)
Determine the width and height of a line of text given a certain font size.
texture pango_render_text(const std::string &text, int size, const color_t &color, font::pango_text::FONT_STYLE style, bool use_markup, int max_width)
Returns a SDL texture containing the rendered text.
General purpose widgets.
uint32_t get_mouse_state(float *x, float *y)
A wrapper for SDL_GetMouseState that gives coordinates in draw space.
Definition input.cpp:28
STL namespace.
bool isnewline(const char c)
SDL_Window * get_window()
Definition video.cpp:712
int w
Definition pathfind.cpp:188
Contains the SDL_Rect helper code.
Transitional API for porting SDL_ttf-based code to Pango.
const std::size_t max_size
Definition sound.cpp:145
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
Definition sound.cpp:139
rect src
Non-transparent portion of the surface to compose.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49
static map_location::direction s
static lg::log_domain log_display("display")
ucs4_convert_impl::enableif< TD, typenameTS::value_type >::type unicode_cast(const TS &source)
#define i
#define h
#define c