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 "Popup.h"
10#include "../../Constants/Colors.h"
11#include "../../Managers/WindowManager.h"
12#include "../Helpers/TextDrawer.h"
13#include <algorithm>
14
15namespace WinServer {
16
17Popup* s_WinServer_Popup_the = nullptr;
18
19Popup::Popup()
20{
21 s_WinServer_Popup_the = this;
22}
23
24void Popup::on_set_data()
25{
26 size_t max_width = 0;
27 size_t max_height = 0;
28 for (auto& item : m_data) {
29 max_width = std::max(max_width, Helpers::text_width(item.text, m_font));
30 max_height += m_font.glyph_height() + spacing();
31 }
32 max_width = std::max(max_width, min_width());
33 bounds().set_width(max_width + 2 * spacing());
34 bounds().set_height(max_height + spacing());
35}
36
37void Popup::draw(LG::Context& ctx)
38{
39 if (!visible()) {
40 return;
41 }
42
43 ctx.set_fill_color(LG::Color::LightSystemOpaque);
44 ctx.fill_rounded(bounds(), LG::CornerMask(LG::CornerMask::SystemRadius));
45
46 ctx.set_fill_color(Color::Shadow);
47 ctx.draw_box_shading(bounds(), LG::Shading(LG::Shading::Type::Box, 0, LG::Shading::SystemSpread), LG::CornerMask(LG::CornerMask::SystemRadius));
48
49 const size_t line_height = (m_font.glyph_height() + spacing());
50 int height = bounds().min_y() + spacing();
51
52 for (int i = 0; i < m_data.size(); i++) {
53 if (i == m_hovered_item) {
54 ctx.set_fill_color(LG::Color::White);
55 ctx.fill_rounded(LG::Rect(bounds().min_x() + 4, height - spacing() / 2, bounds().width() - 8, line_height), LG::CornerMask(2));
56 }
57 ctx.set_fill_color(LG::Color::DarkSystemText);
58 Helpers::draw_text(ctx, { bounds().min_x() + spacing(), height }, m_data[i].text, m_font);
59 height += line_height;
60 }
61}
62
63void Popup::set_preferred_origin(const LG::Point<int>& origin)
64{
65 auto& wm = WindowManager::the();
66 LG::Point<int> pos;
67 int x = origin.x();
68 int y = origin.y();
69
70 if (origin.y() + bounds().height() > wm.visible_area().max_y()) {
71 y = origin.y() - bounds().height();
72 }
73 if (origin.x() + bounds().width() > wm.visible_area().max_x()) {
74 x = origin.x() - bounds().width();
75 }
76 pos.set_x(x);
77 pos.set_y(y);
78 m_bounds.set_origin(std::move(pos));
79}
80
81} // namespace WinServer