#include "LineInput.hxx" #include namespace { SDL_Rect const TEXTURE_RECTS[] = { {.x = 0, .y = 0, .w = 8, .h = 8}, // UPPER_LEFT {.x = 8, .y = 0, .w = 179, .h = 8}, // UPPER_EDGE {.x = 187, .y = 0, .w = 8, .h = 8}, // UPPER_RIGHT {.x = 0, .y = 8, .w = 8, .h = 34}, // LEFT_EDGE {.x = 8, .y = 8, .w = 179, .h = 34}, // CENTER {.x = 187, .y = 8, .w = 8, .h = 34}, // RIGHT_EDGE {.x = 0, .y = 42, .w = 8, .h = 7}, // LOWER_LEFT {.x = 8, .y = 42, .w = 179, .h = 7}, // LOWER_EDGE {.x = 187, .y = 42, .w = 8, .h = 7}, // LOWER_RIGHT }; SDL_Rect calculate_text_rect(SDL_Rect const& area, SDL_Texture* texture) { int text_w, text_h; SDL_QueryTexture(texture, nullptr, nullptr, &text_w, &text_h); // TODO: the height value is based on the default font height, therefor it should not be hard coded // this hack here is a solution for when the text is empty, // because in that case we cannot determine the height from the rendered texture text_h = 32; int const w = std::min(text_w, area.w-LineInput::MIN_WIDTH-8); int const h = std::min(text_h, area.h-LineInput::MIN_HEIGHT-8); return { .x = area.x+12, .y = area.y+(area.h-h)/2, .w = area.w>=(w+LineInput::MIN_WIDTH+8) ? w : 0, .h = area.h>=(h+LineInput::MIN_HEIGHT+8) ? h : 0, }; } } LineInput::LineInput(int const x, int const y, int const w, int const h, std::string value) :value_{std::move(value)}, x_{x}, y_{y}, w_{w}, h_{h}, focus_{false}, visible_{true}, texture_{"line_input.png"}, font_{"kenney_pixel.ttf"} { assert(w_>=MIN_WIDTH); assert(h_>=MIN_HEIGHT); } void LineInput::move(int const x, int const y) { x_ = x; y_ = y; } void LineInput::resize(int const w, int const h) { assert(w>=MIN_WIDTH); assert(h>=MIN_HEIGHT); w_ = w; h_ = h; } SDL_Rect LineInput::get_bounding_box() const { return {x_, y_, w_, h_}; } void LineInput::set_focus(bool const focus) { focus_ = focus; if (!focus_) SDL_StopTextInput(); } bool LineInput::has_focus() const { return focus_; } void LineInput::on_event(SDL_Event const& evt) { if (!focus_ || !visible_) return; if (evt.type==SDL_TEXTINPUT) { value_ += evt.text.text; auto it = value_.begin(); auto const end = value_.end(); int len = 0; // we assume valid UTF-8 here while (it!=end && len