opuntiaOS - an operating system targeting x86 and ARMv7
at master 3.3 kB view raw
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 <libg/Color.h> 11#include <libui/Context.h> 12#include <libui/Label.h> 13 14namespace UI { 15 16Label::Label(View* superview, const LG::Rect& frame) 17 : View(superview, frame) 18{ 19} 20 21Label::Label(View* superview, Window* window, const LG::Rect& frame) 22 : View(superview, window, frame) 23{ 24} 25 26void Label::display(const LG::Rect& rect) 27{ 28 LG::Context ctx = graphics_current_context(); 29 ctx.add_clip(rect); 30 31 auto& f = font(); 32 const size_t letter_spacing = f.glyph_spacing(); 33 34 size_t label_width = bounds().width() - content_edge_insets().left() - content_edge_insets().right(); 35 size_t txt_width = text_width(); 36 size_t dots_width = font().glyph_width('.') * 3 + letter_spacing * 2; 37 38 bool need_to_stop_rendering_text = (txt_width > label_width); 39 size_t width_when_stop_rendering_text = content_edge_insets().left() + label_width - dots_width; 40 41 size_t content_width = text_width(); 42 size_t content_height = text_height(); 43 LG::Point<int> text_start { content_edge_insets().left(), std::max(content_edge_insets().top(), int(bounds().height() - content_height) / 2) }; 44 if (alignment() == Text::Alignment::Center) { 45 int preffered_start = ((int)bounds().width() - (int)content_width) / 2; 46 text_start.set_x(std::max(content_edge_insets().left(), preffered_start)); 47 } else if (alignment() == Text::Alignment::Right) { 48 int preffered_start = (int)bounds().width() - (int)content_width; 49 text_start.set_x(std::max(content_edge_insets().left(), preffered_start)); 50 } 51 52 ctx.set_fill_color(text_color()); 53 for (int i = 0; i < m_text.size(); i++) { 54 size_t glyph_width = f.glyph_width(m_text[i]) + letter_spacing; 55 if (need_to_stop_rendering_text && text_start.x() + glyph_width > width_when_stop_rendering_text) { 56 for (int j = 0; j < 3; j++) { 57 ctx.draw(text_start, f.glyph_bitmap('.')); 58 text_start.offset_by(f.glyph_width('.') + letter_spacing, 0); 59 } 60 return; 61 } 62 ctx.draw(text_start, f.glyph_bitmap(m_text[i])); 63 text_start.offset_by(glyph_width, 0); 64 } 65} 66 67void Label::mouse_entered(const LG::Point<int>& location) 68{ 69 set_hovered(true); 70} 71 72void Label::mouse_exited() 73{ 74 set_hovered(false); 75} 76 77void Label::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 Label::text_width() const 86{ 87 if (!m_text.size()) { 88 return 0; 89 } 90 91 size_t width = 0; 92 auto& f = font(); 93 const size_t letter_spacing = f.glyph_spacing(); 94 95 for (int i = 0; i < m_text.size(); i++) { 96 width += f.glyph_width(m_text[i]) + letter_spacing; 97 } 98 return width - letter_spacing; 99} 100 101size_t Label::text_height() const 102{ 103 return font().glyph_height(); 104} 105 106} // namespace UI