PocketPutr/Desktop_Test/window_manager.cpp
2025-12-16 20:48:21 +01:00

126 lines
3.8 KiB
C++

#include "window.h"
#include "GLOBALS.h"
#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) {
int total_pos_x = window.x + window.width;
int total_pos_y = window.y + window.height;
// Clamp window within the screen size AND taskbar
if (total_pos_x > MAX_SCREEN_WIDTH) window.x = MAX_SCREEN_WIDTH - window.width;
if (total_pos_y > MAX_SCREEN_HEIGHT) window.y = MAX_SCREEN_HEIGHT - window.height - 29;
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(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);
for (auto it = window.window_decorations.begin(); it != window.window_decorations.end(); ++it) {
if (it->action == WindowAction::CLOSE) {
// Close button
tft->draw_box(window.x + it->x_offset, window.y + it->y_offset, it->height, it->width, COL_RED);
}
if (it->action == WindowAction::MINIMIZE) {
// Minimize button
tft->draw_box(window.x + it->x_offset, window.y + it->y_offset, it->height, it->width, 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(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(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)) {
for (auto it = window.window_decorations.begin(); it != window.window_decorations.end(); ++it) {
int x = window.x + it->x_offset;
int y = window.y + it->y_offset;
Serial.printf("x: %i y: %i\n", x, y);
if (event.x >= x && event.x <= (x + it->width) && event.y >= y && event.y <= (y + it->height) && it->action == WindowAction::CLOSE) {
close_window(window.id);
return window.id;
}
}
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;
}