106 lines
2.7 KiB
C++
106 lines
2.7 KiB
C++
#include "window_manager.h"
|
|
#include <algorithm>
|
|
|
|
void WindowManager::init(TFT_Handler* th, DISPLAY_STATE* ds) {
|
|
tft = th;
|
|
display_state = ds;
|
|
|
|
// Subscribe to events
|
|
EventManager::getInstance().subscribe(this);
|
|
}
|
|
|
|
void WindowManager::create_window(Window window) {
|
|
windows.push_back(window);
|
|
display_state->update_display.store(true);
|
|
}
|
|
|
|
void WindowManager::close_window(int window_id) {
|
|
for (auto it = windows.begin(); it != windows.end(); ++it) {
|
|
if (it->id == window_id) {
|
|
windows.erase(it);
|
|
display_state->update_display.store(true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void WindowManager::draw_all() {
|
|
tft->start_draw();
|
|
for (const auto& win : windows) {
|
|
draw_window(win);
|
|
}
|
|
tft->end_draw();
|
|
}
|
|
|
|
void WindowManager::draw_window(const Window& window) {
|
|
// Outer shadow
|
|
tft->draw_rect(window.x, window.y, window.width + 2, window.height + 2, 1, 0x0000);
|
|
|
|
// Inner shadow
|
|
tft->draw_rect(window.x, window.y, window.width + 1, window.height + 1, 1, 0x8410);
|
|
|
|
// Highlight
|
|
tft->draw_rect(window.x - 1, window.y - 1, window.width + 1, window.height + 1, 1, 0xffff);
|
|
|
|
// Window
|
|
tft->draw_box(window.x, window.y, window.width, window.height, window.background_color);
|
|
|
|
// Decorations
|
|
tft->draw_box(window.x + 3, window.y + 3, window.width - 6, 30, window.foreground_color);
|
|
|
|
// Close button
|
|
tft->draw_box(window.x + 6, window.y + 5, 25, 25, COL_RED);
|
|
|
|
// Minimize button
|
|
tft->draw_box(window.x + 6 + 30, window.y + 5, 25, 25, COL_LIGHT_GREY);
|
|
|
|
// Window title
|
|
tft->draw_text(window.x + 6 + 65, window.y + 10, window.title.c_str());
|
|
|
|
// Window content
|
|
tft->draw_box(window.x + 3, window.y + 35, window.width - 6, window.height - 38, COL_WHITE);
|
|
}
|
|
|
|
void WindowManager::on_click_event(const CLICK_EVENT& event) {
|
|
if (event.event != CLICK_EVENTS::LEFT_CLICK) {
|
|
return;
|
|
}
|
|
|
|
int clicked_id = handle_window_click(event);
|
|
|
|
if (clicked_id >= 0) {
|
|
display_state->update_display.store(true);
|
|
}
|
|
}
|
|
|
|
int WindowManager::handle_window_click(const CLICK_EVENT& event) {
|
|
// Iterate BACKWARDS - last window is on top
|
|
for (int i = windows.size() - 1; i >= 0; i--) {
|
|
Window& window = windows[i];
|
|
|
|
// Check if click is within window bounds
|
|
if (event.x >= window.x && event.x <= (window.x + window.width) &&
|
|
event.y >= window.y && event.y <= (window.y + window.height)) {
|
|
|
|
if (window.focused) {
|
|
return -1;
|
|
}
|
|
|
|
// Unfocus all windows
|
|
for (auto& win : windows) {
|
|
win.focused = false;
|
|
}
|
|
|
|
// Focus this window
|
|
window.focused = true;
|
|
|
|
// Move window to end (top of z-order)
|
|
auto it = windows.begin() + i;
|
|
std::rotate(it, it + 1, windows.end());
|
|
|
|
return window.id;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
} |