Works, I guess
This commit is contained in:
parent
2eaa9563d2
commit
63991fd940
@ -1,13 +1,15 @@
|
|||||||
#include "window_manager.h"
|
#include "shell.h"
|
||||||
#include "input_manager.h"
|
#include "input_manager.h"
|
||||||
#include "tft_handler.h"
|
#include "tft_handler.h"
|
||||||
#include "event_manager.h"
|
#include "event_manager.h"
|
||||||
#include "GLOBALS.h"
|
#include "GLOBALS.h"
|
||||||
|
#include "system_manager.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
WindowManager* wm;
|
Shell* _shell;
|
||||||
InputManager* im;
|
InputManager* im;
|
||||||
TFT_Handler* th;
|
TFT_Handler* th;
|
||||||
|
SystemManager* sm;
|
||||||
|
|
||||||
DISPLAY_STATE* _display_state;
|
DISPLAY_STATE* _display_state;
|
||||||
|
|
||||||
@ -29,84 +31,34 @@ void setup() {
|
|||||||
_display_state->update_display.store(false);
|
_display_state->update_display.store(false);
|
||||||
|
|
||||||
// Create managers
|
// Create managers
|
||||||
wm = new WindowManager();
|
_shell = new Shell();
|
||||||
im = new InputManager();
|
im = new InputManager();
|
||||||
th = new TFT_Handler();
|
th = new TFT_Handler();
|
||||||
|
sm = new SystemManager();
|
||||||
|
|
||||||
// Initialize in order
|
// Initialize in order
|
||||||
th->init(_display_state);
|
th->init(_display_state);
|
||||||
|
sm->init(_display_state);
|
||||||
|
|
||||||
// Initialize event manager (creates dispatcher task)
|
// Initialize event manager (creates dispatcher task)
|
||||||
EventManager::getInstance().init();
|
EventManager::getInstance().init();
|
||||||
|
|
||||||
// Initialize components (they subscribe to events)
|
// Initialize components (they subscribe to events)
|
||||||
im->init(_display_state, th);
|
im->init(_display_state, th);
|
||||||
wm->init(th, _display_state);
|
_shell->init(th, _display_state, sm);
|
||||||
|
|
||||||
// Create input task on Core 0
|
// Create input task on Core 0
|
||||||
xTaskCreatePinnedToCore(input_task, "input_task", 4096, NULL, 1, &InputTask, 0);
|
xTaskCreatePinnedToCore(input_task, "input_task", 4096, NULL, 1, &InputTask, 0);
|
||||||
|
|
||||||
delay(100);
|
delay(100);
|
||||||
|
|
||||||
// Create test windows
|
|
||||||
|
|
||||||
WindowDecoration dec1 = {
|
|
||||||
.x_offset = 6,
|
|
||||||
.y_offset = 5,
|
|
||||||
.width = 25,
|
|
||||||
.height = 25,
|
|
||||||
.action = WindowAction::CLOSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
WindowDecoration dec2 = {
|
|
||||||
.x_offset = 36,
|
|
||||||
.y_offset = 5,
|
|
||||||
.width = 25,
|
|
||||||
.height = 25,
|
|
||||||
.action = WindowAction::MINIMIZE,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<WindowDecoration> wdec;
|
|
||||||
wdec.push_back(dec1);
|
|
||||||
wdec.push_back(dec2);
|
|
||||||
|
|
||||||
Window win1 = {
|
|
||||||
.id = 0,
|
|
||||||
.x = 10,
|
|
||||||
.y = 10,
|
|
||||||
.width = 350,
|
|
||||||
.height = 250,
|
|
||||||
.background_color = 0xbdf7,
|
|
||||||
.foreground_color = COL_DARK_BLUE,
|
|
||||||
.focused = false,
|
|
||||||
.minimized = false,
|
|
||||||
.title = "Hello World!",
|
|
||||||
.window_decorations = wdec,
|
|
||||||
};
|
|
||||||
wm->create_window(win1);
|
|
||||||
|
|
||||||
Window win2 = {
|
|
||||||
.id = 1,
|
|
||||||
.x = 70,
|
|
||||||
.y = 40,
|
|
||||||
.width = 350,
|
|
||||||
.height = 200,
|
|
||||||
.background_color = 0xbdf7,
|
|
||||||
.foreground_color = COL_DARK_BLUE,
|
|
||||||
.focused = true,
|
|
||||||
.minimized = false,
|
|
||||||
.title = "Second Window",
|
|
||||||
.window_decorations = wdec,
|
|
||||||
};
|
|
||||||
wm->create_window(win2);
|
|
||||||
|
|
||||||
Serial.println("Initialization complete");
|
Serial.println("Initialization complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// Only handle rendering in main loop
|
// Only handle rendering in main loop
|
||||||
if (_display_state->update_display.load()) {
|
if (_display_state->update_display.load()) {
|
||||||
wm->draw_all();
|
_shell->draw_all();
|
||||||
im->draw_button();
|
im->draw_button();
|
||||||
_display_state->update_display.store(false);
|
_display_state->update_display.store(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,10 +6,12 @@
|
|||||||
|
|
||||||
#define COL_WHITE 0xffff
|
#define COL_WHITE 0xffff
|
||||||
#define COL_BLACK 0x0000
|
#define COL_BLACK 0x0000
|
||||||
#define COL_GREY 0xbdf7
|
#define COL_GREY 0xbdf7 // Standard color
|
||||||
#define COL_LIGHT_GREY 0x8410
|
#define COL_LIGHT_GREY 0x8410
|
||||||
|
#define COL_DARK_GREY 0x9cf3
|
||||||
#define COL_DARK_BLUE 0x0014
|
#define COL_DARK_BLUE 0x0014
|
||||||
#define COL_RED 0xf800
|
#define COL_RED 0xf800
|
||||||
|
#define COL_TEAL 0x0410
|
||||||
|
|
||||||
enum CLICK_EVENTS {
|
enum CLICK_EVENTS {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
|
|||||||
14
Desktop_Test/helpers.cpp
Normal file
14
Desktop_Test/helpers.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
void Helpers::recalculate_taskbar(std::vector<TaskBarItem>* task_bar_items) {
|
||||||
|
for (size_t i = 0; i < task_bar_items->size(); ++i) {
|
||||||
|
auto& item = (*task_bar_items)[i];
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
item.place_x = 60;
|
||||||
|
} else {
|
||||||
|
const TaskBarItem& prev = (*task_bar_items)[i - 1];
|
||||||
|
item.place_x = prev.place_x + prev.offset_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Desktop_Test/helpers.h
Normal file
8
Desktop_Test/helpers.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
#include "program.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct Helpers {
|
||||||
|
static void recalculate_taskbar(std::vector<TaskBarItem>* task_bar_items);
|
||||||
|
};
|
||||||
30
Desktop_Test/program.cpp
Normal file
30
Desktop_Test/program.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "freertos/idf_additions.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "program.h"
|
||||||
|
|
||||||
|
Program::Program(DISPLAY_STATE* display_state) {
|
||||||
|
_display_state = display_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Program::init(int id, std::string name, Window* window) {
|
||||||
|
_id = id;
|
||||||
|
_task_name = name;
|
||||||
|
_window = window;
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(loop, _task_name.c_str(), 4096, this, 1, &_task_handle, 0);
|
||||||
|
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::close() {
|
||||||
|
vTaskDelete(_task_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Program::loop(void* pvParameters) {
|
||||||
|
Program* self = static_cast<Program*>(pvParameters);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
self->_display_state->update_display.store(true);
|
||||||
|
vTaskDelay(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
70
Desktop_Test/program.h
Normal file
70
Desktop_Test/program.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct TaskBarItem {
|
||||||
|
int id;
|
||||||
|
int place_x;
|
||||||
|
int place_y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int offset_x;
|
||||||
|
bool focused;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DesktopItem {
|
||||||
|
int id;
|
||||||
|
int place_x;
|
||||||
|
int place_y;
|
||||||
|
int icon_size_x;
|
||||||
|
int icon_size_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class WindowAction {
|
||||||
|
EXIT = 1,
|
||||||
|
FILE = 2,
|
||||||
|
HELP = 3,
|
||||||
|
MINIMIZE = 4,
|
||||||
|
CLOSE = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WindowDecoration {
|
||||||
|
int x_offset;
|
||||||
|
int y_offset;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
WindowAction action;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Window {
|
||||||
|
int id;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int background_color;
|
||||||
|
int foreground_color;
|
||||||
|
bool focused;
|
||||||
|
bool minimized;
|
||||||
|
std::string title;
|
||||||
|
std::vector<WindowDecoration> window_decorations;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Program {
|
||||||
|
private:
|
||||||
|
Window* _window;
|
||||||
|
DISPLAY_STATE* _display_state;
|
||||||
|
std::string _task_name = "";
|
||||||
|
TaskHandle_t _task_handle;
|
||||||
|
static void loop(void* pvParameters);
|
||||||
|
|
||||||
|
public:
|
||||||
|
int _id;
|
||||||
|
Program(DISPLAY_STATE* display_state);
|
||||||
|
int init(int id, std::string name, Window* window);
|
||||||
|
void close();
|
||||||
|
};
|
||||||
356
Desktop_Test/shell.cpp
Normal file
356
Desktop_Test/shell.cpp
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
#include "shell.h"
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include "system_manager.h"
|
||||||
|
|
||||||
|
void Shell::init(TFT_Handler* th, DISPLAY_STATE* ds, SystemManager* system_manager) {
|
||||||
|
tft = th;
|
||||||
|
display_state = ds;
|
||||||
|
_system_manager = system_manager;
|
||||||
|
|
||||||
|
// Subscribe to click events
|
||||||
|
EventManager::getInstance().subscribe(this);
|
||||||
|
|
||||||
|
draw_background(COL_TEAL);
|
||||||
|
draw_task_bar(COL_GREY);
|
||||||
|
|
||||||
|
// Create desktop items
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
DesktopItem di = {
|
||||||
|
.id = i,
|
||||||
|
.place_x = i * 50 + 1,
|
||||||
|
.place_y = 10,
|
||||||
|
.icon_size_x = 45,
|
||||||
|
.icon_size_y = 50,
|
||||||
|
};
|
||||||
|
items.push_back(di);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < items.size(); ++i) {
|
||||||
|
draw_desktop_Item(items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell::on_click_event(CLICK_EVENT event) {
|
||||||
|
if (event.event != CLICK_EVENTS::LEFT_CLICK) return;
|
||||||
|
|
||||||
|
int window_id = handle_window_click(event);
|
||||||
|
if (window_id >= 0) {
|
||||||
|
display_state->update_display.store(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icon_id = handle_desktop_click(event);
|
||||||
|
|
||||||
|
if (icon_id != -1) {
|
||||||
|
display_state->update_display.store(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tast_icon_id = handle_taskbar_click(event);
|
||||||
|
|
||||||
|
if (tast_icon_id != -1) {
|
||||||
|
display_state->update_display.store(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ckicked_start_button = handle_start_button_click(event);
|
||||||
|
|
||||||
|
if (ckicked_start_button) {
|
||||||
|
display_state->update_display.store(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======= Window =======
|
||||||
|
void Shell::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 = 95;
|
||||||
|
item.height = 18;
|
||||||
|
item.offset_x = 100;
|
||||||
|
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 Shell::close_window(int window_id) {
|
||||||
|
for (auto it = windows.begin(); it != windows.end(); ++it) {
|
||||||
|
if ((*it)->id == window_id) {
|
||||||
|
windows.erase(it);
|
||||||
|
_system_manager->close_program((*it)->id);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < task_bar_items.size(); ++i) {
|
||||||
|
TaskBarItem item = task_bar_items[i];
|
||||||
|
|
||||||
|
if (i == 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[i] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell::minimize_window(int window_id) {
|
||||||
|
for (auto it = windows.begin(); it != windows.end(); ++it) {
|
||||||
|
for (int i = 0; i < task_bar_items.size(); ++i) {
|
||||||
|
if ((*it)->id == window_id && (*it)->id == task_bar_items[i].id) {
|
||||||
|
(*it)->minimized = true;
|
||||||
|
task_bar_items[i].focused = false;
|
||||||
|
display_state->update_display.store(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell::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) {
|
||||||
|
if (!win->minimized) draw_window(*win);
|
||||||
|
}
|
||||||
|
tft->end_draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell::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 Shell::draw_background(int color) {
|
||||||
|
tft->fill_screen(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell::draw_desktop_Item(DesktopItem 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 Shell::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());
|
||||||
|
|
||||||
|
for (TaskBarItem item : task_bar_items) {
|
||||||
|
if (item.focused) {
|
||||||
|
tft->draw_box(item.place_x - 2, item.place_y - 2, item.width + 3, item.height + 3, COL_BLACK);
|
||||||
|
tft->draw_box(item.place_x - 1, item.place_y - 1, item.width + 2, item.height + 2, COL_DARK_GREY);
|
||||||
|
tft->draw_box(item.place_x, item.place_y, item.width + 2, item.height + 2, COL_WHITE);
|
||||||
|
tft->draw_box(item.place_x, item.place_y, item.width, item.height, COL_GREY);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tft->draw_box(item.place_x - 1, item.place_y - 1, item.width + 1, item.height + 1, COL_WHITE);
|
||||||
|
tft->draw_box(item.place_x, item.place_y, item.width + 2, item.height + 2, COL_BLACK);
|
||||||
|
tft->draw_rect(item.place_x, item.place_y, item.width + 1, item.height + 1, 1, COL_DARK_GREY);
|
||||||
|
tft->draw_box(item.place_x, item.place_y, item.width, item.height, COL_GREY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Shell::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 Shell::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);
|
||||||
|
|
||||||
|
WindowDecoration dec;
|
||||||
|
Window* win = new Window();
|
||||||
|
|
||||||
|
WindowDecoration dec1 = {
|
||||||
|
.x_offset = 6,
|
||||||
|
.y_offset = 5,
|
||||||
|
.width = 25,
|
||||||
|
.height = 25,
|
||||||
|
.action = WindowAction::CLOSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
WindowDecoration dec2 = {
|
||||||
|
.x_offset = 36,
|
||||||
|
.y_offset = 5,
|
||||||
|
.width = 25,
|
||||||
|
.height = 25,
|
||||||
|
.action = WindowAction::MINIMIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
win->window_decorations.push_back(dec1);
|
||||||
|
win->window_decorations.push_back(dec2);
|
||||||
|
|
||||||
|
win->id = 0;
|
||||||
|
win->x = 10;
|
||||||
|
win->y = 0;
|
||||||
|
win->width = 350;
|
||||||
|
win->height = 250;
|
||||||
|
win->background_color = 0xbdf7;
|
||||||
|
win->foreground_color = COL_DARK_BLUE;
|
||||||
|
win->focused = true;
|
||||||
|
win->minimized = false;
|
||||||
|
win->title = "Hello World!";
|
||||||
|
|
||||||
|
_system_manager->spawn_program(win);
|
||||||
|
create_window(win);
|
||||||
|
|
||||||
|
// TODO: Handle icon click (open window, etc.)
|
||||||
|
return item.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Shell::handle_taskbar_click(CLICK_EVENT event) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shell::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;
|
||||||
|
}
|
||||||
42
Desktop_Test/shell.h
Normal file
42
Desktop_Test/shell.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "tft_handler.h"
|
||||||
|
#include "event_manager.h"
|
||||||
|
#include "system_manager.h"
|
||||||
|
#include <vector>
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
#include "program.h"
|
||||||
|
|
||||||
|
class Shell : public IEventListener {
|
||||||
|
private:
|
||||||
|
TFT_Handler* tft;
|
||||||
|
DISPLAY_STATE* display_state;
|
||||||
|
std::vector<Window*> windows;
|
||||||
|
std::vector<TaskBarItem> task_bar_items;
|
||||||
|
std::vector<DesktopItem> items;
|
||||||
|
|
||||||
|
SystemManager* _system_manager;
|
||||||
|
|
||||||
|
int handle_window_click(CLICK_EVENT event);
|
||||||
|
int handle_desktop_click(CLICK_EVENT event);
|
||||||
|
int handle_taskbar_click(CLICK_EVENT event);
|
||||||
|
bool handle_start_button_click(CLICK_EVENT event);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init(TFT_Handler* th, DISPLAY_STATE* ds, SystemManager* system_manager);
|
||||||
|
|
||||||
|
// ======= Window =======
|
||||||
|
void create_window(Window* window);
|
||||||
|
void close_window(int window_id);
|
||||||
|
void minimize_window(int window_id);
|
||||||
|
void draw_window(Window window);
|
||||||
|
|
||||||
|
// ======= Desktop =======
|
||||||
|
void draw_background(int color);
|
||||||
|
void draw_task_bar(int color);
|
||||||
|
void draw_desktop_Item(DesktopItem desktop_item);
|
||||||
|
|
||||||
|
// ======= Shared =======
|
||||||
|
void draw_all();
|
||||||
|
// IEventListener interface
|
||||||
|
void on_click_event(CLICK_EVENT event) override;
|
||||||
|
};
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
#include "program.h"
|
||||||
|
#include "system_manager.h"
|
||||||
|
|
||||||
|
std::vector<Program*> SystemManager::init(DISPLAY_STATE* display_state) {
|
||||||
|
_display_state = display_state;
|
||||||
|
return _programs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemManager::spawn_program(Window* window) {
|
||||||
|
Program* program = new Program(_display_state);
|
||||||
|
|
||||||
|
window->id = _programs.size() + 1;
|
||||||
|
program->init(_programs.size() + 1, "lol", window);
|
||||||
|
_programs.push_back(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemManager::close_program(int id) {
|
||||||
|
for (size_t i = 0; i < _programs.size(); ++i) {
|
||||||
|
if (_programs[i]->_id == id) {
|
||||||
|
_programs[i]->close();
|
||||||
|
delete _programs[i]; // Free the memory
|
||||||
|
_programs.erase(_programs.begin() + i);
|
||||||
|
break; // Exit after erase
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "program.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class SystemManager {
|
class SystemManager {
|
||||||
private:
|
private:
|
||||||
|
DISPLAY_STATE* _display_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init();
|
std::vector<Program*> _programs;
|
||||||
|
std::vector<Program*> init(DISPLAY_STATE* display_state);
|
||||||
|
void spawn_program(Window* window);
|
||||||
|
void close_program(int id);
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue
Block a user