Windows and taskbar handling now works as intended. Except minimizing windows when pressed the taskbar item.

This commit is contained in:
Rasmus Rasmussen 2026-01-11 20:43:18 +01:00
parent c90425cc6e
commit 59b8c3ce3c
16 changed files with 285 additions and 182 deletions

View File

@ -71,6 +71,8 @@ void setup() {
delay(100); delay(100);
Serial.println("Initialization complete"); Serial.println("Initialization complete");
_display_state->update_display.store(true);
} }
void loop() { void loop() {

View File

@ -13,28 +13,28 @@
#define COL_RED 0xf800 #define COL_RED 0xf800
#define COL_TEAL 0x0410 #define COL_TEAL 0x0410
enum CLICK_EVENTS { enum CLICK_EVENTS : uint8_t {
NONE = 0, NONE = 0,
LEFT_CLICK = 1, LEFT_CLICK = 1,
RIGHT_CLICK = 2, RIGHT_CLICK = 2,
}; };
struct CLICK_EVENT { struct CLICK_EVENT {
short int x; short x;
short int y; short y;
CLICK_EVENTS event; CLICK_EVENTS event;
}; };
enum class ApplicationEventState { enum class ApplicationEventState : uint8_t {
NONE = 0, NONE = 0,
CREATED = 1, CREATED = 1,
CLOSED = 2, CLOSED = 2,
}; };
struct APPLICATION_EVENT { struct APPLICATION_EVENT {
short int id;
ApplicationEventState state;
char title[64]; char title[64];
short id;
ApplicationEventState state;
}; };
struct DISPLAY_STATE { struct DISPLAY_STATE {

View File

@ -17,8 +17,8 @@ public:
class EventManager { class EventManager {
private: private:
QueueHandle_t _click_event_queue;
std::vector<IEventListener*> _listeners; std::vector<IEventListener*> _listeners;
QueueHandle_t _click_event_queue;
TaskHandle_t _dispatcher_task; TaskHandle_t _dispatcher_task;
EventManager() { EventManager() {

View File

@ -31,7 +31,7 @@ public:
if (!_window->minimized) { if (!_window->minimized) {
_window->title = "Counter: " + std::to_string(counter); _window->title = "Counter: " + std::to_string(counter);
for (int i = 0; i < _window->window_content_text.size(); i++) { for (short i = 0; i < _window->window_content_text.size(); i++) {
_window->window_content_text[i].text = std::to_string(counter); _window->window_content_text[i].text = std::to_string(counter);
} }
@ -39,12 +39,11 @@ public:
} }
} }
vTaskDelay(pdMS_TO_TICKS(1000)); vTaskDelay(pdMS_TO_TICKS(1));
} }
} }
}; };
// Example Program 2: Text editor
class TextEditorProgram : public Program { class TextEditorProgram : public Program {
public: public:
void run() override { void run() override {
@ -57,7 +56,18 @@ public:
} }
}; };
// Example Program 3: Calculator class InternetTester : public Program {
public:
void run() override {
Serial.println("Text editor started!");
// You have full access to the window and can draw to it
while (_running) {
vTaskDelay(pdMS_TO_TICKS(1));
}
}
};
class CalculatorProgram : public Program { class CalculatorProgram : public Program {
public: public:
void run() override { void run() override {
@ -70,58 +80,95 @@ public:
} }
}; };
// Example Program 4: Game class Chatty : public Program {
class GameProgram : public Program {
public: public:
void run() override { void run() override {
Serial.println("Game started!"); Serial.println("Chatty started!");
while (_running) { while (_running) {
// Game logic and rendering // Game logic and rendering
vTaskDelay(pdMS_TO_TICKS(1)); // 20 FPS vTaskDelay(pdMS_TO_TICKS(1));
} }
} }
}; };
// Example Program 5: Settings
class SettingsProgram : public Program { class SettingsProgram : public Program {
private: private:
uint32_t max_idle_iterations; uint32_t max_idle_iterations;
bool showing_buttons = false;
public: public:
void on_click_event(CLICK_EVENT event) override {
if (_window->minimized) return;
}
void run() override { void run() override {
_window->x += 150; _window->x += 150;
_window->width -= 50; _window->width -= 50;
Serial.println("Settings started!"); Serial.println("Settings started!");
WindowContentText ram_usage; WindowContentText main_ram_usage_label;
WindowContentText ram_usage_label; WindowContentText main_ram_usage;
WindowContentText cpu_usage;
WindowContentText cpu_usage_label; WindowContentText cpu_usage_label;
ram_usage_label.size = 2; WindowContentText cpu_usage;
ram_usage_label.text = "RAM usage";
ram_usage_label.x = _window->x + 10; WindowContentText psram_usage_label;
ram_usage_label.y = _window->y + 50; WindowContentText psram_usage;
ram_usage.size = 2;
ram_usage.x = _window->x + 10; main_ram_usage_label.size = 2;
ram_usage.y = _window->y + 70; main_ram_usage_label.text = "RAM usage:";
main_ram_usage_label.x = _window->x + 5;
main_ram_usage_label.y = _window->y + 60;
main_ram_usage.size = 2;
main_ram_usage.x = _window->x + 7;
main_ram_usage.y = _window->y + 80;
psram_usage_label.size = 2;
psram_usage_label.text = "PSRAM usage:";
psram_usage_label.x = _window->x + 5;
psram_usage_label.y = _window->y + 100;
psram_usage.size = 2;
psram_usage.x = _window->x + 7;
psram_usage.y = _window->y + 120;
cpu_usage_label.size = 2; cpu_usage_label.size = 2;
cpu_usage_label.text = "CPU usage:"; cpu_usage_label.text = "CPU usage:";
cpu_usage_label.x = _window->x + 10; cpu_usage_label.x = _window->x + 5;
cpu_usage_label.y = _window->y + 90; cpu_usage_label.y = _window->y + 140;
cpu_usage.size = 2; cpu_usage.size = 2;
cpu_usage.x = _window->x + 10; cpu_usage.x = _window->x + 7;
cpu_usage.y = _window->y + 110; cpu_usage.y = _window->y + 160;
_window->window_content_text.push_back(ram_usage_label);
_window->window_content_text.push_back(ram_usage); _window->window_content_text.push_back(main_ram_usage_label);
_window->window_content_text.push_back(main_ram_usage);
_window->window_content_text.push_back(cpu_usage_label); _window->window_content_text.push_back(cpu_usage_label);
_window->window_content_text.push_back(cpu_usage); _window->window_content_text.push_back(cpu_usage);
_window->window_content_text.push_back(psram_usage_label);
_window->window_content_text.push_back(psram_usage);
ContentButton show_resources;
show_resources.action = "show resources";
show_resources.x = _window->x + 7;
show_resources.y = _window->y + 40;
show_resources.width = 70;
show_resources.height = 10;
show_resources.pressed = true;
_window->content_buttons.push_back(show_resources);
// Variables for metrics // Variables for metrics
size_t total_ram; size_t total_ram;
size_t total_psram;
size_t free_ram; size_t free_ram;
size_t free_psram;
size_t used_ram; size_t used_ram;
float ram_percent; size_t used_psram;
float ram_percent = 0.0f;
float psram_percentage = 0.0f;
float cpu_percent = 0.0f; float cpu_percent = 0.0f;
// For CPU calculation // For CPU calculation
@ -139,10 +186,14 @@ public:
size_t internal_free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); size_t internal_free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
size_t psram_total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); size_t psram_total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
size_t psram_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); size_t psram_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
total_ram = internal_total + psram_total; total_ram = internal_total;// + psram_total;
free_ram = internal_free + psram_free; total_psram = psram_total;
free_ram = internal_free;// + psram_free;
free_psram = psram_free;
used_ram = total_ram - free_ram; used_ram = total_ram - free_ram;
used_psram = total_psram - free_psram;
ram_percent = (float)used_ram / (float)total_ram * 100.0f; ram_percent = (float)used_ram / (float)total_ram * 100.0f;
psram_percentage = (float)used_psram / (float)total_psram * 100.0f;
// CPU Usage - measure idle task iterations // CPU Usage - measure idle task iterations
idle_count_current = xTaskGetIdleRunTimeCounter(); idle_count_current = xTaskGetIdleRunTimeCounter();
@ -166,8 +217,9 @@ public:
idle_count_last = idle_count_current; idle_count_last = idle_count_current;
_window->window_content_text[1].text = std::to_string(ram_percent); _window->window_content_text[1].text = std::to_string(ram_percent) + "%";
_window->window_content_text[3].text = std::to_string((int)cpu_percent) + "%"; _window->window_content_text[3].text = std::to_string((int)cpu_percent) + "%";
_window->window_content_text[5].text = std::to_string((int)psram_percentage) + "%";
vTaskDelay(pdMS_TO_TICKS(1)); vTaskDelay(pdMS_TO_TICKS(1));
if (counter == 1000) { if (counter == 1000) {

View File

@ -1,7 +1,7 @@
#include "helpers.h" #include "helpers.h"
void Helpers::recalculate_taskbar(std::vector<TaskBarItem>& task_bar_items) { void Helpers::recalculate_taskbar(std::vector<TaskBarItem>& task_bar_items) {
for (size_t i = 0; i < task_bar_items.size(); ++i) { for (short i = 0; i < task_bar_items.size(); ++i) {
if (i == 0) { if (i == 0) {
task_bar_items[i].place_x = 60; task_bar_items[i].place_x = 60;
} else { } else {

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
struct Mouse_Icon { struct Mouse_Icon {
short int x; short x;
short int y; short y;
short int size_x; short size_x;
short int size_y; short size_y;
short int color; short color;
}; };

View File

@ -43,7 +43,7 @@ void InputManager::update() {
} }
} }
void InputManager::handle_button_press(short int buttonIndex) { void InputManager::handle_button_press(short buttonIndex) {
bool needs_redraw = false; bool needs_redraw = false;
switch(buttonIndex) { switch(buttonIndex) {
@ -94,6 +94,6 @@ void InputManager::draw_button() {
_tf->draw_box(mi.x, mi.y, mi.size_x, mi.size_y, mi.color); _tf->draw_box(mi.x, mi.y, mi.size_x, mi.size_y, mi.color);
} }
bool InputManager::are_buttons_pressed(short int btn1, short int btn2) { bool InputManager::are_buttons_pressed(short btn1, short btn2) {
return (buttonState[btn1] == LOW && buttonState[btn2] == LOW); return (buttonState[btn1] == LOW && buttonState[btn2] == LOW);
} }

View File

@ -7,19 +7,19 @@
class InputManager { class InputManager {
private: private:
short int BUTTON_PINS[6] = {4, 5, 6, 7, 17, 16}; short BUTTON_PINS[6] = {4, 5, 6, 7, 17, 16};
static constexpr short int NUM_BUTTONS = 6; static constexpr short NUM_BUTTONS = 6;
short lastButtonState[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
short buttonState[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
const unsigned long DEBOUNCE_DELAY = 25; // milliseconds const unsigned long DEBOUNCE_DELAY = 25; // milliseconds
unsigned long lastDebounceTime[NUM_BUTTONS] = {0}; unsigned long lastDebounceTime[NUM_BUTTONS] = {0};
short int lastButtonState[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
short int buttonState[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
DISPLAY_STATE* _display_state; DISPLAY_STATE* _display_state;
TFT_Handler* _tf; TFT_Handler* _tf;
Mouse_Icon mi; Mouse_Icon mi;
void handle_button_press(short int buttonIndex); void handle_button_press(short buttonIndex);
bool are_buttons_pressed(short int btn1, short int btn2); bool are_buttons_pressed(short btn1, short btn2);
public: public:
void init(DISPLAY_STATE* display_state, TFT_Handler* tf); void init(DISPLAY_STATE* display_state, TFT_Handler* tf);

View File

@ -12,7 +12,7 @@ Program::~Program() {
close(); close();
} }
void Program::init(short int id, const std::string& name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state, CALIBRATION_IDLE calibration_idle) { void Program::init(char id, const std::string& name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state, CALIBRATION_IDLE calibration_idle) {
_id = id; _id = id;
_name = name; _name = name;
_window = window; _window = window;

View File

@ -6,33 +6,34 @@
#include <vector> #include <vector>
#include <LovyanGFX.hpp> #include <LovyanGFX.hpp>
#include "tft_handler.h" #include "tft_handler.h"
#include "event_manager.h"
// Forward declarations // Forward declarations
class Shell; class Shell;
class TFT_Handler; class TFT_Handler;
struct TaskBarItem { struct TaskBarItem {
short int id;
short int place_x;
short int place_y;
short int width;
short int height;
short int offset_x;
bool focused;
std::string name; std::string name;
short place_x;
short place_y;
short width;
short height;
char id;
char offset_x;
bool focused;
}; };
struct DesktopItem { struct DesktopItem {
short int id;
short int place_x;
short int place_y;
short int icon_size_x;
short int icon_size_y;
std::string name;
std::string program_class; // Which program class to instantiate std::string program_class; // Which program class to instantiate
std::string name;
short place_x;
short place_y;
char id;
char icon_size_x;
char icon_size_y;
}; };
enum class WindowAction { enum class WindowAction : uint8_t {
EXIT = 1, EXIT = 1,
FILE = 2, FILE = 2,
HELP = 3, HELP = 3,
@ -41,47 +42,57 @@ enum class WindowAction {
}; };
struct WindowDecoration { struct WindowDecoration {
short int x_offset; short x_offset;
short int y_offset; short y_offset;
short int width; short width;
short int height; short height;
WindowAction action; WindowAction action;
}; };
struct WindowContentText { struct WindowContentText {
short int x;
short int y;
short int size;
std::string text; std::string text;
short x;
short y;
char size;
};
struct ContentButton {
std::string action;
short x;
short y;
short width;
short height;
bool pressed;
}; };
struct Window { struct Window {
short int id; std::string title;
short int x; std::vector<WindowContentText> window_content_text;
short int y; std::vector<WindowDecoration> window_decorations;
short int width; std::vector<ContentButton> content_buttons;
short int height; unsigned short x;
short int background_color; unsigned short y;
short int foreground_color; unsigned short width;
unsigned short height;
unsigned short background_color;
unsigned short foreground_color;
char id;
bool focused; bool focused;
bool minimized; bool minimized;
std::string title;
std::vector<WindowDecoration> window_decorations;
std::vector<WindowContentText> window_content_text;
}; };
// Base Program class - all programs inherit from this // Base Program class - all programs inherit from this
class Program { class Program : public IEventListener {
protected: protected:
std::string _name;
Window* _window; Window* _window;
CALIBRATION_IDLE _calibration_idle;
Shell* _shell; Shell* _shell;
TFT_Handler* _tft; TFT_Handler* _tft;
DISPLAY_STATE* _display_state; DISPLAY_STATE* _display_state;
TaskHandle_t _task_handle; TaskHandle_t _task_handle;
short int _id; char _id;
std::string _name;
bool _running; bool _running;
CALIBRATION_IDLE _calibration_idle;
static void task_wrapper(void* pvParameters); static void task_wrapper(void* pvParameters);
@ -90,16 +101,19 @@ public:
virtual ~Program(); virtual ~Program();
// Initialize the program with its window and shell reference // Initialize the program with its window and shell reference
void init(short int id, const std::string& name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state, CALIBRATION_IDLE calibration_idle); void init(char id, const std::string& name, Window* window, Shell* shell, TFT_Handler* tft, DISPLAY_STATE* display_state, CALIBRATION_IDLE calibration_idle);
// Override this in your specific programs // Override this in your specific programs
virtual void run() = 0; virtual void run() = 0;
// listen to click events
void on_click_event(CLICK_EVENT event) override {}
// Called when the program should stop // Called when the program should stop
virtual void close(); virtual void close();
// Getters // Getters
int get_id() const { return _id; } short get_id() const { return _id; }
std::string get_name() const { return _name; } std::string get_name() const { return _name; }
Window* get_window() const { return _window; } Window* get_window() const { return _window; }
}; };

View File

@ -16,61 +16,66 @@ void Shell::init(TFT_Handler* th, DISPLAY_STATE* ds, SystemManager* system_manag
draw_task_bar(COL_GREY); draw_task_bar(COL_GREY);
// Create desktop items with their associated program classes // Create desktop items with their associated program classes
DesktopItem di0 = { DesktopItem di0;
.id = 0, di0.id = 0;
.place_x = 0 * 50 + 1, di0.place_x = 0 * 50 + 1;
.place_y = 10, di0.place_y = 10;
.icon_size_x = 45, di0.icon_size_x = 45;
.icon_size_y = 50, di0.icon_size_y = 50;
.name = "Counter", di0.name = "Counter";
.program_class = "CounterProgram" di0.program_class = "CounterProgram";
};
items.push_back(di0); items.push_back(di0);
DesktopItem di1 = { DesktopItem di1;
.id = 1, di1.id = 4;
.place_x = 1 * 50 + 1, di1.place_x = 4 * 50 + 1;
.place_y = 10, di1.place_y = 10;
.icon_size_x = 45, di1.icon_size_x = 45;
.icon_size_y = 50, di1.icon_size_y = 50;
.name = "Text Editor", di1.name = "Text Editor";
.program_class = "TextEditorProgram" di1.program_class = "TextEditorProgram";
};
items.push_back(di1); items.push_back(di1);
DesktopItem di2 = { DesktopItem di2;
.id = 2, di2.id = 2;
.place_x = 2 * 50 + 1, di2.place_x = 2 * 50 + 1;
.place_y = 10, di2.place_y = 10;
.icon_size_x = 45, di2.icon_size_x = 45;
.icon_size_y = 50, di2.icon_size_y = 50;
.name = "Calculator", di2.name = "Calculator";
.program_class = "CalculatorProgram" di2.program_class = "CalculatorProgram";
};
items.push_back(di2); items.push_back(di2);
DesktopItem di3 = { DesktopItem di3;
.id = 3, di3.id = 3;
.place_x = 3 * 50 + 1, di3.place_x = 3 * 50 + 1;
.place_y = 10, di3.place_y = 10;
.icon_size_x = 45, di3.icon_size_x = 45;
.icon_size_y = 50, di3.icon_size_y = 50;
.name = "Game", di3.name = "Game";
.program_class = "GameProgram" di3.program_class = "Chatty";
};
items.push_back(di3); items.push_back(di3);
DesktopItem di4 = { DesktopItem di4;
.id = 4, di4.id = 1;
.place_x = 4 * 50 + 1, di4.place_x = 1 * 50 + 1;
.place_y = 10, di4.place_y = 10;
.icon_size_x = 45, di4.icon_size_x = 45;
.icon_size_y = 50, di4.icon_size_y = 50;
.name = "Settings", di4.name = "Settings";
.program_class = "SettingsProgram" di4.program_class = "SettingsProgram";
};
items.push_back(di4); items.push_back(di4);
DesktopItem di5;
di5.id = 5;
di5.place_x = 5 * 50 + 1;
di5.place_y = 10;
di5.icon_size_x = 45;
di5.icon_size_y = 50;
di5.name = "Internet Tester";
di5.program_class = "InternetTester";
items.push_back(di5);
for (const auto& item : items) { for (const auto& item : items) {
draw_desktop_Item(item); draw_desktop_Item(item);
} }
@ -80,19 +85,19 @@ void Shell::on_click_event(CLICK_EVENT event) {
if (event.event != CLICK_EVENTS::LEFT_CLICK) return; if (event.event != CLICK_EVENTS::LEFT_CLICK) return;
// Always check windows first // Always check windows first
int window_id = handle_window_click(event); short window_id = handle_window_click(event);
if (window_id >= 0) { if (window_id >= 0) {
display_state->update_display.store(true); display_state->update_display.store(true);
return; return;
} }
int icon_id = handle_desktop_click(event); short icon_id = handle_desktop_click(event);
if (icon_id != -1) { if (icon_id != -1) {
display_state->update_display.store(true); display_state->update_display.store(true);
return; return;
} }
int tast_icon_id = handle_taskbar_click(event); short tast_icon_id = handle_taskbar_click(event);
if (tast_icon_id != -1) { if (tast_icon_id != -1) {
display_state->update_display.store(true); display_state->update_display.store(true);
return; return;
@ -107,8 +112,8 @@ void Shell::on_click_event(CLICK_EVENT event) {
// ======= Window ======= // ======= Window =======
void Shell::create_window(Window* window) { void Shell::create_window(Window* window) {
int total_pos_x = window->x + window->width; short total_pos_x = window->x + window->width;
int total_pos_y = window->y + window->height; short total_pos_y = window->y + window->height;
// Clamp window within the screen size AND taskbar // 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_x > MAX_SCREEN_WIDTH) window->x = MAX_SCREEN_WIDTH - window->width;
@ -116,9 +121,13 @@ void Shell::create_window(Window* window) {
windows.push_back(window); windows.push_back(window);
for (short i = 0; i < task_bar_items.size(); ++i) {
task_bar_items[i].focused = false;
}
TaskBarItem item; TaskBarItem item;
item.id = window->id; item.id = window->id;
item.focused = window->focused; item.focused = true;
item.name = window->title; item.name = window->title;
item.width = 95; item.width = 95;
item.height = 18; item.height = 18;
@ -139,11 +148,13 @@ void Shell::create_window(Window* window) {
display_state->update_display.store(true); display_state->update_display.store(true);
} }
void Shell::close_window(short int window_id) { void Shell::close_window(short window_id) {
for (auto it = windows.begin(); it != windows.end(); ++it) { for (auto it = windows.begin(); it != windows.end(); ++it) {
if ((*it)->id == window_id) { if ((*it)->id == window_id) {
Window* window_to_delete = *it;
windows.erase(it); windows.erase(it);
_system_manager->close_program((*it)->id); _system_manager->close_program(window_to_delete->id);
delete window_to_delete;
display_state->update_display.store(true); display_state->update_display.store(true);
break; break;
} }
@ -160,9 +171,9 @@ void Shell::close_window(short int window_id) {
Helpers::recalculate_taskbar(task_bar_items); Helpers::recalculate_taskbar(task_bar_items);
} }
void Shell::minimize_window(short int window_id) { void Shell::minimize_window(short window_id) {
for (auto it = windows.begin(); it != windows.end(); ++it) { for (auto it = windows.begin(); it != windows.end(); ++it) {
for (int i = 0; i < task_bar_items.size(); ++i) { for (short i = 0; i < task_bar_items.size(); ++i) {
if ((*it)->id == window_id && (*it)->id == task_bar_items[i].id) { if ((*it)->id == window_id && (*it)->id == task_bar_items[i].id) {
(*it)->minimized = true; (*it)->minimized = true;
task_bar_items[i].focused = false; task_bar_items[i].focused = false;
@ -182,7 +193,9 @@ void Shell::draw_all() {
} }
for (const auto& win : windows) { for (const auto& win : windows) {
if (!win->minimized) draw_window(*win); if (win->minimized) continue;
draw_window(*win);
} }
} }
@ -225,10 +238,14 @@ void Shell::draw_window(const Window& window) {
for (WindowContentText text : window.window_content_text) { for (WindowContentText text : window.window_content_text) {
tft->draw_text(text.x, text.y, text.text, COL_BLACK, text.size); tft->draw_text(text.x, text.y, text.text, COL_BLACK, text.size);
} }
for (ContentButton button : window.content_buttons) {
tft->draw_button(button.x, button.y, button.width, button.height, COL_GREY, button.pressed, button.action);
}
} }
// ======= Desktop ======= // ======= Desktop =======
void Shell::draw_background(short int color) { void Shell::draw_background(short color) {
tft->fill_screen(color); tft->fill_screen(color);
} }
@ -236,7 +253,7 @@ void Shell::draw_desktop_Item(const 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); 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(short int color) { void Shell::draw_task_bar(short color) {
// bar // bar
tft->draw_box(0, 293, 480, 40, color); tft->draw_box(0, 293, 480, 40, color);
tft->draw_line(0, 294, 480, 294, 0xffff); tft->draw_line(0, 294, 480, 294, 0xffff);
@ -276,9 +293,9 @@ void Shell::draw_start_menu() {
} }
short int Shell::handle_window_click(CLICK_EVENT event) { short Shell::handle_window_click(CLICK_EVENT event) {
// Iterate BACKWARDS - last window is on top // Iterate BACKWARDS - last window is on top
for (int i = windows.size() - 1; i >= 0; i--) { for (short i = windows.size() - 1; i >= 0; i--) {
Window* window = windows[i]; Window* window = windows[i];
if (window->minimized) continue; if (window->minimized) continue;
@ -287,8 +304,8 @@ short int Shell::handle_window_click(CLICK_EVENT event) {
&& event.y >= window->y && event.y <= (window->y + window->height)) { && event.y >= window->y && event.y <= (window->y + window->height)) {
for (auto it = window->window_decorations.begin(); it != window->window_decorations.end(); ++it) { for (auto it = window->window_decorations.begin(); it != window->window_decorations.end(); ++it) {
int x = window->x + it->x_offset; short x = window->x + it->x_offset;
int y = window->y + it->y_offset; short y = window->y + it->y_offset;
// Check if click is within either of the buttons // Check if click is within either of the buttons
if (event.x >= x && event.x <= (x + it->width) && event.y >= y && event.y <= (y + it->height) && it->action == WindowAction::CLOSE && !window->minimized) { if (event.x >= x && event.x <= (x + it->width) && event.y >= y && event.y <= (y + it->height) && it->action == WindowAction::CLOSE && !window->minimized) {
@ -302,9 +319,6 @@ short int Shell::handle_window_click(CLICK_EVENT event) {
} }
} }
// If the window is already focused, return
if (window->focused) return -1;
// Unfocus all windows // Unfocus all windows
for (auto& win : windows) { for (auto& win : windows) {
win->focused = false; win->focused = false;
@ -324,7 +338,7 @@ short int Shell::handle_window_click(CLICK_EVENT event) {
return -1; return -1;
} }
short int Shell::handle_desktop_click(CLICK_EVENT event) { short Shell::handle_desktop_click(CLICK_EVENT event) {
for (const auto& item : items) { for (const auto& item : items) {
if (event.x >= item.place_x && event.x <= (item.place_x + item.icon_size_x) 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)) { && event.y >= item.place_y && event.y <= (item.place_y + item.icon_size_y)) {
@ -385,18 +399,22 @@ short int Shell::handle_desktop_click(CLICK_EVENT event) {
return -1; return -1;
} }
short int Shell::handle_taskbar_click(CLICK_EVENT event) { short Shell::handle_taskbar_click(CLICK_EVENT event) {
for (int i = 0; i < task_bar_items.size(); ++i) { for (short i = 0; i < task_bar_items.size(); ++i) {
if (event.x >= task_bar_items[i].place_x && event.x <= (task_bar_items[i].place_x + task_bar_items[i].width) && event.y >= task_bar_items[i].place_y && event.y <= (task_bar_items[i].place_y + task_bar_items[i].height)) { if (event.x >= task_bar_items[i].place_x && event.x <= (task_bar_items[i].place_x + task_bar_items[i].width) && event.y >= task_bar_items[i].place_y && event.y <= (task_bar_items[i].place_y + task_bar_items[i].height)) {
for (int j = 0; j < windows.size(); ++j) { for (short j = 0; j < windows.size(); ++j) {
if (windows[j]->id == task_bar_items[i].id) { if (windows[j]->id != task_bar_items[i].id) continue;
for (int k = 0; k < windows.size(); ++k) windows[k]->focused = false;
for (short k = 0; k < windows.size(); ++k) windows[k]->focused = false;
windows[j]->focused = true; windows[j]->focused = true;
windows[j]->minimized = false; windows[j]->minimized = false;
}
auto it = windows.begin() + j;
std::rotate(it, it + 1, windows.end());
} }
for (int l = 0; l < task_bar_items.size(); ++l) task_bar_items[l].focused = false; for (short l = 0; l < task_bar_items.size(); ++l) task_bar_items[l].focused = false;
task_bar_items[i].focused = true; task_bar_items[i].focused = true;
return task_bar_items[i].id; return task_bar_items[i].id;
} }

View File

@ -8,17 +8,16 @@
class Shell : public IEventListener { class Shell : public IEventListener {
private: private:
TFT_Handler* tft;
DISPLAY_STATE* display_state;
std::vector<Window*> windows;
std::vector<TaskBarItem> task_bar_items; std::vector<TaskBarItem> task_bar_items;
std::vector<DesktopItem> items; std::vector<DesktopItem> items;
std::vector<Window*> windows;
TFT_Handler* tft;
DISPLAY_STATE* display_state;
SystemManager* _system_manager; SystemManager* _system_manager;
short int handle_window_click(CLICK_EVENT event); short handle_window_click(CLICK_EVENT event);
short int handle_desktop_click(CLICK_EVENT event); short handle_desktop_click(CLICK_EVENT event);
short int handle_taskbar_click(CLICK_EVENT event); short handle_taskbar_click(CLICK_EVENT event);
bool handle_start_button_click(CLICK_EVENT event); bool handle_start_button_click(CLICK_EVENT event);
public: public:
@ -26,13 +25,13 @@ public:
// ======= Window ======= // ======= Window =======
void create_window(Window* window); void create_window(Window* window);
void close_window(short int window_id); void close_window(short window_id);
void minimize_window(short int window_id); void minimize_window(short window_id);
void draw_window(const Window& window); void draw_window(const Window& window);
// ======= Desktop ======= // ======= Desktop =======
void draw_background(short int color); void draw_background(short color);
void draw_task_bar(short int color); void draw_task_bar(short color);
void draw_start_menu(); void draw_start_menu();
void draw_desktop_Item(const DesktopItem& desktop_item); void draw_desktop_Item(const DesktopItem& desktop_item);

View File

@ -13,8 +13,9 @@ void SystemManager::init(DISPLAY_STATE* display_state, Shell* shell, TFT_Handler
// Register all available programs // Register all available programs
register_program<CounterProgram>("CounterProgram"); register_program<CounterProgram>("CounterProgram");
register_program<TextEditorProgram>("TextEditorProgram"); register_program<TextEditorProgram>("TextEditorProgram");
register_program<InternetTester>("InternetTester");
register_program<CalculatorProgram>("CalculatorProgram"); register_program<CalculatorProgram>("CalculatorProgram");
register_program<GameProgram>("GameProgram"); register_program<Chatty>("Chatty");
register_program<SettingsProgram>("SettingsProgram"); register_program<SettingsProgram>("SettingsProgram");
} }

View File

@ -15,8 +15,8 @@ private:
DISPLAY_STATE* _display_state; DISPLAY_STATE* _display_state;
Shell* _shell; Shell* _shell;
TFT_Handler* _tft; TFT_Handler* _tft;
short int _next_program_id = 1;
CALIBRATION_IDLE _calibration_idle; CALIBRATION_IDLE _calibration_idle;
short _next_program_id = 1;
// Factory function type: creates a new instance of a Program // Factory function type: creates a new instance of a Program
using ProgramFactory = std::function<Program*()>; using ProgramFactory = std::function<Program*()>;

View File

@ -7,11 +7,12 @@ void TFT_Handler::init(DISPLAY_STATE* display_state) {
tft.setColorDepth(16); tft.setColorDepth(16);
tft.init(); tft.init();
tft.setRotation(3); tft.setRotation(3);
tft.fillScreen(0x0000); //tft.fillScreen(0x0000);
sprite.setColorDepth(16); sprite.setColorDepth(16);
sprite.setPsram(true); sprite.setPsram(true);
sprite.createSprite(480, 320); sprite.createSprite(480, 320);
sprite.fillScreen(0x0000);
} }
void TFT_Handler::draw_box(short int x, short int y, short int size_x, short int size_y, int color) { void TFT_Handler::draw_box(short int x, short int y, short int size_x, short int size_y, int color) {
@ -32,6 +33,22 @@ void TFT_Handler::draw_text(short int x, short int y, const std::string& str, in
sprite.drawString(str.c_str(), x, y); sprite.drawString(str.c_str(), x, y);
} }
void TFT_Handler::draw_button(short x, short y, short size_x, short size_y, int color, bool pressed, std::string str) {
if (pressed) {
sprite.fillRect(x - 2, y - 2, size_x + 2, size_y + 2, COL_BLACK);
sprite.fillRect(x - 1, y - 1, size_x + 1, size_y + 1, COL_DARK_GREY);
sprite.fillRect(x + 2, y + 2, size_x + 2, size_y + 2, COL_WHITE);
sprite.fillRect(x, y, size_x, size_y, color);
sprite.setTextColor(COL_BLACK);
sprite.setTextSize(1);
sprite.drawString(str.c_str(), x, y);
} else {
sprite.fillRect(x, y, size_x, size_y, color);
sprite.fillRect(x, y, size_x, size_y, color);
sprite.fillRect(x, y, size_x, size_y, color);
}
}
void TFT_Handler::fill_screen(int color) { void TFT_Handler::fill_screen(int color) {
sprite.fillScreen(color); sprite.fillScreen(color);
} }

View File

@ -61,11 +61,11 @@ public:
void init(DISPLAY_STATE* display_state); void init(DISPLAY_STATE* display_state);
void draw_box(short int x, short int y, short int size_x, short int size_y, int color); void draw_box(short x, short y, short size_x, short size_y, int color);
void draw_rect(short int x, short int y, short int size_x, short int size_y, short int thickness, int color); void draw_rect(short x, short y, short size_x, short size_y, short int thickness, int color);
void draw_line(short int x1, short int y1, short int x2, short int y2, int color); void draw_line(short x1, short y1, short x2, short y2, int color);
void draw_text(short int x, short int y, const std::string& str, int color, short int size); void draw_text(short x, short y, const std::string& str, int color, short int size);
void draw_button(short x, short y, short size_x, short size_y, int color, bool pressed, std::string str);
void fill_screen(int color); void fill_screen(int color);
void push_sprite(); void push_sprite();
}; };