#include "window.h" #include "GLOBALS.h" #include "window_manager.h" #include void WindowManager::init(TFT_Handler* th, DISPLAY_STATE* ds) { tft = th; display_state = ds; // Subscribe to click events EventManager::getInstance().subscribe(this); // Create desktop items for (int i = 0; i < 5; i++) { Desktop_Item di = { .id = i, .place_x = i * 50 + 1, .place_y = 10, .icon_size_x = 45, .icon_size_y = 50, }; items.push_back(di); } } void WindowManager::on_click_event(CLICK_EVENT event) { if (event.event != CLICK_EVENTS::LEFT_CLICK) return; int icon_id = handle_desktop_click(event); int window_id = handle_window_click(event); int tast_icon_id = handle_taskbar_click(event); bool ckicked_start_button = handle_start_button_click(event); if (window_id >= 0) display_state->update_display.store(true); } // ======= Window ======= 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); TaskBarItem item; item.id = window.id; item.focused = window.focused; item.name = window.title; item.width = 60; item.height = 18; item.offset_x = 65; item.place_y = 298; // Set place_x and place_y for ALL items if (task_bar_items.size() == 0) { item.place_x = 60; } else { // For subsequent items, use the previous item's position + offset const TaskBarItem& prev = task_bar_items.back(); item.place_x = prev.place_x + prev.offset_x; } task_bar_items.push_back(item); 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; } } for (auto it = task_bar_items.begin(); it != task_bar_items.end(); ++it) { if (it->id == window_id) { task_bar_items.erase(it); display_state->update_display.store(true); break; } } } void WindowManager::minimize_window(int window_id) { for (auto it = windows.begin(); it != windows.end(); ++it) { if (it->id == window_id) { it->minimized = true; display_state->update_display.store(true); break; } } } void WindowManager::draw_all() { tft->start_draw(); draw_background(0x0410); draw_task_bar(0xbdf7); for (const auto& item : items) { draw_desktop_Item(item); } for (const auto& win : windows) { draw_window(win); } tft->end_draw(); } void WindowManager::draw_window(Window window) { if (window.minimized) return; // 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); } // ======= Desktop ======= void WindowManager::draw_background(int color) { tft->fill_screen(color); } void WindowManager::draw_desktop_Item(Desktop_Item desktop_item) { tft->draw_box(desktop_item.place_x, desktop_item.place_y, desktop_item.icon_size_x, desktop_item.icon_size_y, 0x4648); } void WindowManager::draw_task_bar(int color) { // bar tft->draw_box(0, 293, 480, 40, color); tft->draw_line(0, 294, 480, 294, 0xffff); // Outer shadow tft->draw_box(5, 297, 53, 21, 0x0000); // Inner shadow tft->draw_box(6, 298, 51, 19, 0x8410); // Highlight tft->draw_box(5, 297, 51, 19, 0xffff); // Button tft->draw_box(6, 298, 50, 18, color); Serial.println(task_bar_items.size()); //int temp_x = 0; for (TaskBarItem item : task_bar_items) { //temp_x += item.offset_x; if (item.focused) { tft->draw_box(item.place_x, item.place_y, item.width, item.height, COL_BLACK); } else { tft->draw_box(item.place_x, item.place_y, item.width, item.height, COL_DARK_BLUE); } } } 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; 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 (event.x >= x && event.x <= (x + it->width) && event.y >= y && event.y <= (y + it->height) && it->action == WindowAction::MINIMIZE) { minimize_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; } int WindowManager::handle_desktop_click(CLICK_EVENT event) { // Check if click is on desktop (not on taskbar or windows) // This is where you'd check if an icon was clicked for (const auto& item : items) { if (event.x >= item.place_x && event.x <= (item.place_x + item.icon_size_x) && event.y >= item.place_y && event.y <= (item.place_y + item.icon_size_y)) { Serial.print("Desktop item clicked: "); Serial.println(item.id); // TODO: Handle icon click (open window, etc.) return item.id; } } return -1; } int WindowManager::handle_taskbar_click(CLICK_EVENT event) { return -1; } bool WindowManager::handle_start_button_click(CLICK_EVENT event) { if (event.x >= 6 && event.x <= (6 + 50) && event.y >= 298 && event.y <= (298 + 18)) { Serial.println("Taskbar button clicked"); // TODO: Handle icon click (open window, etc.) return true; } return false; }