aboutsummaryrefslogtreecommitdiff
path: root/src/Entry.cpp
blob: 28e303429a25097cfcffaa4f780bbdefa346ab87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "../include/Entry.hpp"
#include "../include/ResourceLoader.hpp"
#include "../include/Utils.hpp"
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Window/Event.hpp>
#include <cmath>

const float background_margin_horizontal = std::floor(5.0f * QuickMedia::get_ui_scale());
const float padding_vertical = std::floor(5.0f * QuickMedia::get_ui_scale());
const float background_margin_vertical = std::floor(0.0f * QuickMedia::get_ui_scale());

namespace QuickMedia {
    Entry::Entry(const std::string &placeholder_text, sf::Shader *rounded_rectangle_shader) :
        on_submit_callback(nullptr),
        draw_background(true),
        text("", false, std::floor(16 * get_ui_scale()), 0.0f),
        width(0.0f),
        background(sf::Vector2f(1.0f, 1.0f), 10.0f, sf::Color(60, 65, 73), rounded_rectangle_shader),
        placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16 * get_ui_scale())),
        mouse_left_inside(false)
    {
        text.setEditable(true);
        placeholder.setFillColor(sf::Color(255, 255, 255, 100));
    }

    void Entry::process_event(sf::Event &event) {
        if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
            sf::FloatRect box(background.get_position(), background.get_size());
            if(box.contains(event.mouseButton.x, event.mouseButton.y))
                mouse_left_inside = true;
            else
                mouse_left_inside = false;
        } else if(is_touch_enabled() && event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) {
            sf::FloatRect box(background.get_position(), background.get_size());
            if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y))
                show_virtual_keyboard();
            mouse_left_inside = false;
        }

        if(!text.isEditable())
            return;

        text.processEvent(event);

        if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Enter && !event.key.shift) {
            if(on_submit_callback) {
                auto u8 = text.getString().toUtf8();
                std::string *u8_str = (std::string*)&u8;
                bool clear_text = on_submit_callback(*u8_str);
                if(clear_text)
                    text.setString("");
            }
        }
    }

    // TODO: Set the max number of visible lines and use glScissor to cut off the lines outsides
    // (and also split text into lines to not draw them at all once they are not inside the scissor box)
    void Entry::draw(sf::RenderWindow &window) {
        background.set_size(sf::Vector2f(width, get_height()));
        if(draw_background)
            background.draw(window);

        if(text.getString().isEmpty() && !text.isEditable()) {
            window.draw(placeholder);
            //sf::Vector2f placeholder_pos = placeholder.getPosition();
            //const float caret_margin = 2.0f;
            //const float vspace = placeholder.getFont()->getLineSpacing(18);
            //sf::RectangleShape caret_rect(sf::Vector2f(2.0f, floor(vspace - caret_margin * 2.0f)));
            //caret_rect.setPosition(floor(placeholder_pos.x), floor(placeholder_pos.y + caret_margin));
            //window.draw(caret_rect);
        } else {
            text.draw(window);
        }
    }

    void Entry::set_single_line(bool single_line) {
        text.single_line_edit = single_line;
    }

    void Entry::set_editable(bool editable) {
        text.setEditable(editable);
    }

    void Entry::set_text(std::string new_text) {
        text.setString(sf::String::fromUtf8(new_text.data(), new_text.data() + new_text.size()));
    }

    void Entry::move_caret_to_end() {
        text.updateGeometry();
        text.moveCaretToEnd();
    }

    void Entry::append_text(std::string str) {
        text.appendText(std::move(str));
    }

    void Entry::replace(size_t start_index, size_t length, const sf::String &insert_str) {
        text.replace(start_index, length, insert_str);
    }

    int Entry::get_caret_index() const {
        return text.getCaretIndex();
    }

    void Entry::set_position(const sf::Vector2f &pos) {
        background.set_position(pos);
        text.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical));
        placeholder.setPosition(pos + sf::Vector2f(background_margin_horizontal, background_margin_vertical + std::floor(5.0f * get_ui_scale())));
    }

    void Entry::set_max_width(float width) {
        this->width = width;
        text.setMaxWidth(this->width - background_margin_horizontal * 2.0f);
    }

    bool Entry::is_editable() const {
        return text.isEditable();
    }

    float Entry::get_height() {
        text.updateGeometry();
        return std::floor(text.getHeight() + background_margin_vertical * 2.0f + padding_vertical * 2.0f);
    }

    const sf::String& Entry::get_text() const {
        return text.getString();
    }
}