1/*
2 * Copyright (C) 2020-2022 The opuntiaOS Project Authors.
3 * + Contributed by Nikita Melekhin <nimelehin@gmail.com>
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include <libfoundation/EventLoop.h>
10#include <libui/Button.h>
11#include <libui/Context.h>
12
13namespace UI {
14
15Button::Button(View* superview, const LG::Rect& frame)
16 : Control(superview, frame)
17{
18 set_background_color(LG::Color::LightSystemButton);
19}
20
21void Button::display(const LG::Rect& rect)
22{
23 LG::Context& ctx = graphics_current_context();
24 ctx.add_clip(rect);
25
26 ctx.set_fill_color(background_color());
27 if (m_button_type == Type::System) {
28 if (is_hovered()) {
29 ctx.set_fill_color(background_color().darken(8));
30 }
31 }
32 ctx.fill_rounded(bounds(), LG::CornerMask(4));
33
34 size_t content_width = text_width();
35 size_t content_height = text_height();
36 LG::Point<int> text_start { content_edge_insets().left(), std::max(content_edge_insets().top(), int(bounds().height() - content_height) / 2) };
37 if (alignment() == Text::Alignment::Center) {
38 text_start.set_x((bounds().width() - content_width) / 2);
39 } else if (alignment() == Text::Alignment::Right) {
40 text_start.set_x(bounds().width() - content_width);
41 }
42
43 auto& f = font();
44 const size_t letter_spacing = f.glyph_spacing();
45
46 ctx.set_fill_color(title_color());
47 for (int i = 0; i < m_title.size(); i++) {
48 ctx.draw(text_start, f.glyph_bitmap(m_title[i]));
49 text_start.offset_by(f.glyph_width(m_title[i]) + letter_spacing, 0);
50 }
51}
52
53void Button::mouse_entered(const LG::Point<int>& location)
54{
55 send_actions(UI::Event::Type::MouseEnterEvent);
56 View::mouse_entered(location);
57}
58
59void Button::mouse_exited()
60{
61 send_actions(UI::Event::Type::MouseLeaveEvent);
62 View::mouse_exited();
63}
64
65void Button::mouse_down(const LG::Point<int>& location)
66{
67 send_actions(UI::Event::Type::MouseDownEvent);
68 View::mouse_down(location);
69}
70
71void Button::mouse_up()
72{
73 send_actions(UI::Event::Type::MouseUpEvent);
74 View::mouse_up();
75}
76
77void Button::recalc_bounds()
78{
79 size_t new_width = text_width() + content_edge_insets().left() + content_edge_insets().right();
80 size_t new_height = text_height() + content_edge_insets().top() + content_edge_insets().bottom();
81 set_width(new_width);
82 set_height(new_height);
83}
84
85size_t Button::text_width()
86{
87 size_t width = 0;
88 auto& f = font();
89 const size_t letter_spacing = f.glyph_spacing();
90
91 for (int i = 0; i < m_title.size(); i++) {
92 width += f.glyph_width(m_title[i]);
93 }
94 width += std::max(size_t(0), m_title.size() - 1) * letter_spacing;
95 return width;
96}
97
98size_t Button::text_height() const
99{
100 return font().glyph_height();
101}
102
103} // namespace UI