Init
This commit is contained in:
parent
1b51fbd552
commit
6bd3102593
121
Desktop_Test/Desktop_Test.ino
Normal file
121
Desktop_Test/Desktop_Test.ino
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include "window_manager.h"
|
||||||
|
#include "desktop_hander.h"
|
||||||
|
#include "input_manager.h"
|
||||||
|
#include "tft_handler.h"
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
|
||||||
|
WindowManager* wm; // Globals
|
||||||
|
Desktop_Hander* dh;
|
||||||
|
InputManager* im;
|
||||||
|
TFT_Handler* th;
|
||||||
|
|
||||||
|
DISPLAY_STATE* _display_state;
|
||||||
|
CLICK_EVENT* _click_event;
|
||||||
|
|
||||||
|
uint32_t totalHeap = ESP.getHeapSize();
|
||||||
|
uint32_t freeHeap = ESP.getFreeHeap();
|
||||||
|
uint32_t usedHeap = totalHeap - freeHeap;
|
||||||
|
float percentUsed = (float)usedHeap * 100.0 / totalHeap;
|
||||||
|
|
||||||
|
TaskHandle_t Task1;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Initializing...");
|
||||||
|
|
||||||
|
_display_state = new DISPLAY_STATE();
|
||||||
|
_display_state->update_display.store(false);
|
||||||
|
|
||||||
|
_click_event = new CLICK_EVENT();
|
||||||
|
_click_event->event = CLICK_EVENTS::NONE;
|
||||||
|
|
||||||
|
wm = new WindowManager();
|
||||||
|
dh = new Desktop_Hander();
|
||||||
|
im = new InputManager();
|
||||||
|
th = new TFT_Handler();
|
||||||
|
|
||||||
|
th->init(_display_state);
|
||||||
|
im->init(_display_state, th, _click_event);
|
||||||
|
dh->init(th);
|
||||||
|
wm->init(th);
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
// Create InputManager thread
|
||||||
|
xTaskCreatePinnedToCore(
|
||||||
|
task1, /* Task function. */
|
||||||
|
"task1", /* name of task. */
|
||||||
|
10000, /* Stack size of task */
|
||||||
|
NULL, /* parameter of the task */
|
||||||
|
1, /* priority of the task */
|
||||||
|
&Task1, /* Task handle to keep track of created task */
|
||||||
|
0); /* pin task to core 0 */
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Window win1 = {
|
||||||
|
.id = 0,
|
||||||
|
.x = 10,
|
||||||
|
.y = 30,
|
||||||
|
.width = 350,
|
||||||
|
.height = 250,
|
||||||
|
.background_color = 0xbdf7, // Blue
|
||||||
|
.foreground_color = COL_DARK_BLUE, // White
|
||||||
|
.focused = false,
|
||||||
|
.title = "Hello Worl!",
|
||||||
|
.window_actions = {},
|
||||||
|
};
|
||||||
|
|
||||||
|
wm->create_window(win1);
|
||||||
|
|
||||||
|
Window win2 = {
|
||||||
|
.id = 1,
|
||||||
|
.x = 30,
|
||||||
|
.y = 50,
|
||||||
|
.width = 350,
|
||||||
|
.height = 250,
|
||||||
|
.background_color = 0xbdf7, // Blue
|
||||||
|
.foreground_color = COL_DARK_BLUE, // White
|
||||||
|
.focused = true,
|
||||||
|
.title = "lmao",
|
||||||
|
.window_actions = {},
|
||||||
|
};
|
||||||
|
|
||||||
|
wm->create_window(win2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
totalHeap = ESP.getHeapSize();
|
||||||
|
freeHeap = ESP.getFreeHeap();
|
||||||
|
usedHeap = totalHeap - freeHeap;
|
||||||
|
percentUsed = (float)usedHeap * 100.0 / totalHeap;
|
||||||
|
|
||||||
|
int start = millis();
|
||||||
|
|
||||||
|
int id = wm->click_event(*_click_event);
|
||||||
|
if (id >= 0)
|
||||||
|
_display_state->update_display.store(true);
|
||||||
|
|
||||||
|
_click_event->event = CLICK_EVENTS::NONE;
|
||||||
|
|
||||||
|
if (_display_state->update_display.load()) {
|
||||||
|
dh->re_draw_desktop();
|
||||||
|
wm->draw_all();
|
||||||
|
im->draw_button();
|
||||||
|
_display_state->update_display.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stop = millis();
|
||||||
|
|
||||||
|
//Serial.print("Total mem: "); Serial.println(ESP.getHeapSize());
|
||||||
|
//Serial.print("Mem left: "); Serial.println(ESP.getFreeHeap());
|
||||||
|
//Serial.print("Mem % used: "); Serial.println(percentUsed);
|
||||||
|
//Serial.println(stop - start);
|
||||||
|
|
||||||
|
delay(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
void task1(void * pvParameters) {
|
||||||
|
for(;;) {
|
||||||
|
im->update();
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Desktop_Test/GLOBALS.h
Normal file
18
Desktop_Test/GLOBALS.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
enum CLICK_EVENTS {
|
||||||
|
NONE = 0,
|
||||||
|
LEFT_CLICK = 1,
|
||||||
|
RIGHT_CLICK = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CLICK_EVENT {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
CLICK_EVENTS event;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DISPLAY_STATE {
|
||||||
|
std::atomic<bool> update_display;
|
||||||
|
};
|
||||||
10
Desktop_Test/desktop.h
Normal file
10
Desktop_Test/desktop.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "WString.h"
|
||||||
|
|
||||||
|
struct Desktop_Item {
|
||||||
|
int id;
|
||||||
|
int place_x;
|
||||||
|
int place_y;
|
||||||
|
int icon_size_x;
|
||||||
|
int icon_size_y;
|
||||||
|
};
|
||||||
59
Desktop_Test/desktop_hander.cpp
Normal file
59
Desktop_Test/desktop_hander.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include "desktop_hander.h"
|
||||||
|
#include "tft_handler.h"
|
||||||
|
|
||||||
|
void Desktop_Hander::init(TFT_Handler* th) {
|
||||||
|
tft = th;
|
||||||
|
|
||||||
|
for (int i; 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
re_draw_desktop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Desktop_Hander::re_draw_desktop() {
|
||||||
|
draw_background(0x0410);
|
||||||
|
draw_task_bar(0xbdf7);
|
||||||
|
|
||||||
|
for (const auto& item : items) {
|
||||||
|
draw_desktop_Item(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Desktop_Hander::draw_background(int color) {
|
||||||
|
tft->fill_screen(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Desktop_Hander::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Desktop_Hander::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Desktop_Hander::click_event(CLICK_EVENT event) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
19
Desktop_Test/desktop_hander.h
Normal file
19
Desktop_Test/desktop_hander.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "desktop.h"
|
||||||
|
#include "tft_handler.h"
|
||||||
|
#include <vector>
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
|
||||||
|
class Desktop_Hander {
|
||||||
|
private:
|
||||||
|
TFT_Handler* tft;
|
||||||
|
std::vector<Desktop_Item> items;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init(TFT_Handler* th);
|
||||||
|
void re_draw_desktop();
|
||||||
|
void draw_background(int color);
|
||||||
|
void draw_task_bar(int color);
|
||||||
|
void draw_desktop_Item(Desktop_Item desktop_item);
|
||||||
|
int click_event(CLICK_EVENT event);
|
||||||
|
};
|
||||||
9
Desktop_Test/icons.h
Normal file
9
Desktop_Test/icons.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Mouse_Icon {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int size_x;
|
||||||
|
int size_y;
|
||||||
|
int color;
|
||||||
|
};
|
||||||
95
Desktop_Test/input_manager.cpp
Normal file
95
Desktop_Test/input_manager.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include "GLOBALS.h"
|
||||||
|
#include "tft_handler.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
#include "input_manager.h"
|
||||||
|
|
||||||
|
void InputManager::init(DISPLAY_STATE* display_state, TFT_Handler* tf, CLICK_EVENT* event) {
|
||||||
|
_display_state = display_state;
|
||||||
|
_event = event;
|
||||||
|
_tf = tf;
|
||||||
|
|
||||||
|
mi = {
|
||||||
|
.x = 5,
|
||||||
|
.y = 5,
|
||||||
|
.size_x = 4,
|
||||||
|
.size_y = 4,
|
||||||
|
.color = 0x0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
pinMode(BUTTON_PINS[i], INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputManager::update() {
|
||||||
|
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
int reading = digitalRead(BUTTON_PINS[i]);
|
||||||
|
|
||||||
|
// Check if button state changed
|
||||||
|
if (reading != lastButtonState[i]) {
|
||||||
|
lastDebounceTime[i] = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only register change after debounce delay
|
||||||
|
if ((millis() - lastDebounceTime[i]) > DEBOUNCE_DELAY) {
|
||||||
|
if (reading != buttonState[i]) {
|
||||||
|
buttonState[i] = reading;
|
||||||
|
|
||||||
|
// Button was pressed (went from HIGH to LOW)
|
||||||
|
if (buttonState[i] == LOW) {
|
||||||
|
// Add your button handling code here
|
||||||
|
handle_button_press(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastButtonState[i] = reading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputManager::handle_button_press(int buttonIndex) {
|
||||||
|
// Add your custom logic here for each button
|
||||||
|
switch(buttonIndex) {
|
||||||
|
case 0:
|
||||||
|
if (mi.x > 480)
|
||||||
|
mi.x = 479;
|
||||||
|
else
|
||||||
|
mi.x += 5;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (mi.y > 320)
|
||||||
|
mi.y = 319;
|
||||||
|
else
|
||||||
|
mi.y += 5;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (mi.y < 0)
|
||||||
|
mi.y = 1;
|
||||||
|
else
|
||||||
|
mi.y -= 5;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (mi.x < 0)
|
||||||
|
mi.x = 1;
|
||||||
|
else
|
||||||
|
mi.x -= 5;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_event->event = CLICK_EVENTS::LEFT_CLICK;
|
||||||
|
_event->x = mi.x;
|
||||||
|
_event->y = mi.y;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_display_state->update_display.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputManager::draw_button() {
|
||||||
|
_tf->draw_box(mi.x, mi.y, mi.size_x, mi.size_y, mi.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputManager::are_buttons_pressed(int btn1, int btn2) {
|
||||||
|
return (buttonState[btn1] == LOW && buttonState[btn2] == LOW);
|
||||||
|
}
|
||||||
28
Desktop_Test/input_manager.h
Normal file
28
Desktop_Test/input_manager.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "tft_handler.h"
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
#include "icons.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
class InputManager {
|
||||||
|
private:
|
||||||
|
int BUTTON_PINS[6] = {4, 5, 6, 7, 17, 16};
|
||||||
|
static constexpr int NUM_BUTTONS = 6;
|
||||||
|
const unsigned long DEBOUNCE_DELAY = 25; // milliseconds
|
||||||
|
unsigned long lastDebounceTime[NUM_BUTTONS] = {0};
|
||||||
|
int lastButtonState[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
|
||||||
|
int buttonState[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
|
||||||
|
|
||||||
|
DISPLAY_STATE* _display_state;
|
||||||
|
CLICK_EVENT* _event;
|
||||||
|
TFT_Handler* _tf;
|
||||||
|
Mouse_Icon mi;
|
||||||
|
|
||||||
|
void handle_button_press(int buttonIndex);
|
||||||
|
bool are_buttons_pressed(int btn1, int btn2);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init(DISPLAY_STATE* display_state, TFT_Handler* tf, CLICK_EVENT* event);
|
||||||
|
void update();
|
||||||
|
void draw_button();
|
||||||
|
};
|
||||||
49
Desktop_Test/tft_handler.cpp
Normal file
49
Desktop_Test/tft_handler.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include "tft_handler.h"
|
||||||
|
|
||||||
|
void TFT_Handler::init(DISPLAY_STATE* display_state) {
|
||||||
|
_display_state = display_state;
|
||||||
|
|
||||||
|
tft.setColorDepth(16);
|
||||||
|
tft.init();
|
||||||
|
tft.fillScreen(0x0000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFT_Handler::draw_box(int x, int y, int size_x, int size_y, int color) {
|
||||||
|
tft.startWrite();
|
||||||
|
|
||||||
|
tft.setRotation(3);
|
||||||
|
tft.fillRect(x, y, size_x, size_y, color);
|
||||||
|
|
||||||
|
tft.endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFT_Handler::draw_rect(int x, int y, int size_x, int size_y, int thickness, int color) {
|
||||||
|
tft.startWrite();
|
||||||
|
|
||||||
|
tft.setRotation(3);
|
||||||
|
tft.drawRect(x, y, size_x, size_y, color);
|
||||||
|
|
||||||
|
tft.endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFT_Handler::draw_line(int x1, int y1, int x2, int y2, int color) {
|
||||||
|
tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFT_Handler::draw_text(int x, int y, std::string str) {
|
||||||
|
tft.startWrite();
|
||||||
|
|
||||||
|
tft.setTextColor(TFT_WHITE);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.drawString(str.c_str(), x, y);
|
||||||
|
|
||||||
|
tft.endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFT_Handler::fill_screen(int color) {
|
||||||
|
tft.startWrite();
|
||||||
|
|
||||||
|
tft.fillScreen(color);
|
||||||
|
|
||||||
|
tft.endWrite();
|
||||||
|
}
|
||||||
63
Desktop_Test/tft_handler.h
Normal file
63
Desktop_Test/tft_handler.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <LovyanGFX.hpp>
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define MAX_X 480
|
||||||
|
#define MAX_Y 320
|
||||||
|
|
||||||
|
// https://github.com/lovyan03/LovyanGFX/issues/714#issuecomment-2968349655
|
||||||
|
// https://github.com/lovyan03/LovyanGFX/issues/734
|
||||||
|
class LGFX : public lgfx::LGFX_Device {
|
||||||
|
public:
|
||||||
|
lgfx::Panel_ILI9488 panel;
|
||||||
|
lgfx::Bus_SPI spi;
|
||||||
|
|
||||||
|
LGFX() {
|
||||||
|
|
||||||
|
// ---- SPI BUS CONFIG ----
|
||||||
|
{
|
||||||
|
auto cfg = spi.config(); // *** GET STRUCT ***
|
||||||
|
cfg.spi_host = SPI2_HOST;
|
||||||
|
cfg.pin_sclk = 12;
|
||||||
|
cfg.pin_mosi = 11;
|
||||||
|
cfg.pin_dc = 21;
|
||||||
|
cfg.pin_miso = -1;
|
||||||
|
cfg.freq_write = 40000000;
|
||||||
|
cfg.freq_read = 16000000;
|
||||||
|
spi.config(cfg); // *** APPLY CONFIG ***
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- PANEL CONFIG ----
|
||||||
|
{
|
||||||
|
auto cfg = panel.config(); // *** GET STRUCT ***
|
||||||
|
cfg.pin_cs = 10;
|
||||||
|
cfg.pin_rst = 15;
|
||||||
|
|
||||||
|
cfg.memory_width = 320;
|
||||||
|
cfg.memory_height = 480;
|
||||||
|
cfg.panel_width = 320;
|
||||||
|
cfg.panel_height = 480;
|
||||||
|
cfg.offset_x = 0;
|
||||||
|
cfg.offset_y = 0;
|
||||||
|
|
||||||
|
panel.config(cfg); // *** APPLY CONFIG ***
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.setBus(&spi);
|
||||||
|
setPanel(&panel);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TFT_Handler {
|
||||||
|
public:
|
||||||
|
LGFX tft;
|
||||||
|
DISPLAY_STATE* _display_state;
|
||||||
|
|
||||||
|
void init(DISPLAY_STATE* display_state);
|
||||||
|
void draw_box(int x, int y, int size_x, int size_y, int color);
|
||||||
|
void draw_rect(int x, int y, int size_x, int size_y, int thickness, int color);
|
||||||
|
void draw_line(int x1, int y1, int x2, int y2, int color);
|
||||||
|
void draw_text(int x, int y, std::string str);
|
||||||
|
void fill_screen(int color);
|
||||||
|
};
|
||||||
22
Desktop_Test/window.h
Normal file
22
Desktop_Test/window.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum class WindowAction {
|
||||||
|
EXIT = 1,
|
||||||
|
FILE = 2,
|
||||||
|
HELP = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Window {
|
||||||
|
int id;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int background_color;
|
||||||
|
int foreground_color;
|
||||||
|
bool focused;
|
||||||
|
std::string title;
|
||||||
|
std::vector<WindowAction> window_actions;
|
||||||
|
};
|
||||||
99
Desktop_Test/window_manager.cpp
Normal file
99
Desktop_Test/window_manager.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "HardwareSerial.h"
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
#include "window_manager.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
void WindowManager::init(TFT_Handler* th) {
|
||||||
|
tft = th;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::create_window(Window window) {
|
||||||
|
windows.push_back(window);
|
||||||
|
draw_window(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::close_window(int window_id) {
|
||||||
|
for (auto it = windows.begin(); it != windows.end(); ++it) {
|
||||||
|
if (it->id == window_id) {
|
||||||
|
windows.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::draw_all() {
|
||||||
|
for (const auto& win : windows) {
|
||||||
|
draw_window(win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::draw_window(Window window) {
|
||||||
|
// Outer shadow
|
||||||
|
//tft->draw_box(window.x, window.y, window.width + 2, window.height + 2, 0x0000);
|
||||||
|
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 + 30 + 5, window.width - 6, window.height - 7 - 30, COL_WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WindowManager::click_event(CLICK_EVENT event) {
|
||||||
|
int id = -1;
|
||||||
|
|
||||||
|
if (event.event == CLICK_EVENTS::NONE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate BACKWARDS - last window is on top
|
||||||
|
for (int i = windows.size() - 1; i >= 0; i--) {
|
||||||
|
Window& window = windows[i];
|
||||||
|
|
||||||
|
if (event.event != CLICK_EVENTS::LEFT_CLICK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (event.x >= window.x && event.x <= (window.x + window.width)) {
|
||||||
|
|
||||||
|
if (event.y >= window.y && event.y <= (window.y + window.height)) {
|
||||||
|
|
||||||
|
if (window.focused)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unfocus all windows
|
||||||
|
for (size_t j = 0; j < windows.size(); j++) {
|
||||||
|
windows[j].focused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus this window
|
||||||
|
window.focused = true;
|
||||||
|
id = window.id;
|
||||||
|
|
||||||
|
// Move window to end (top of z-order)
|
||||||
|
auto it = windows.begin() + i;
|
||||||
|
std::rotate(it, it + 1, windows.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
27
Desktop_Test/window_manager.h
Normal file
27
Desktop_Test/window_manager.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
#include "tft_handler.h"
|
||||||
|
#include <vector>
|
||||||
|
#include "GLOBALS.h"
|
||||||
|
|
||||||
|
#define COL_WHITE 0xffff
|
||||||
|
#define COL_BLACK 0x0000
|
||||||
|
#define COL_GREY 0xbdf7
|
||||||
|
#define COL_LIGHT_GREY 0x8410
|
||||||
|
#define COL_DARK_BLUE 0x0014
|
||||||
|
#define COL_RED 0xf800
|
||||||
|
|
||||||
|
class WindowManager {
|
||||||
|
private:
|
||||||
|
TFT_Handler* tft; // Pointer to shared TFT handler
|
||||||
|
std::vector<Window> windows; // Track all windows
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init(TFT_Handler* th);
|
||||||
|
void create_window(Window window);
|
||||||
|
void close_window(int window_id);
|
||||||
|
void draw_all(); // Redraw all windows
|
||||||
|
void draw_window(Window window);
|
||||||
|
int click_event(CLICK_EVENT event);
|
||||||
|
};
|
||||||
10
PocketPutrMessageService/.idea/.idea.PocketPutrMessageService/.idea/.gitignore
vendored
Normal file
10
PocketPutrMessageService/.idea/.idea.PocketPutrMessageService/.idea/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/.idea.PocketPutrMessageService.iml
|
||||||
|
/modules.xml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/contentModel.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
16
PocketPutrMessageService/PocketPutrMessageService.sln
Normal file
16
PocketPutrMessageService/PocketPutrMessageService.sln
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PocketPutrMessageService", "PocketPutrMessageService\PocketPutrMessageService.csproj", "{265B3E5A-541D-4B84-97B7-18A0F3D49272}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{265B3E5A-541D-4B84-97B7-18A0F3D49272}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{265B3E5A-541D-4B84-97B7-18A0F3D49272}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{265B3E5A-541D-4B84-97B7-18A0F3D49272}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{265B3E5A-541D-4B84-97B7-18A0F3D49272}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace PocketPutrMessageService;
|
||||||
|
|
||||||
|
public class ClientService
|
||||||
|
{
|
||||||
|
public static void Run()
|
||||||
|
{
|
||||||
|
using HttpListener listener = new();
|
||||||
|
listener.Prefixes.Add("http://localhost:8001/");
|
||||||
|
|
||||||
|
listener.Start();
|
||||||
|
|
||||||
|
Console.WriteLine("Listening on port 8001...");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
HttpListenerContext context = listener.GetContext();
|
||||||
|
HttpListenerRequest req = context.Request;
|
||||||
|
|
||||||
|
Console.WriteLine($"Received request for {req.Url}");
|
||||||
|
|
||||||
|
using HttpListenerResponse resp = context.Response;
|
||||||
|
resp.Headers.Set("Content-Type", "text/plain");
|
||||||
|
|
||||||
|
const string data = "Hello there!";
|
||||||
|
byte[] buffer = Encoding.UTF8.GetBytes(data);
|
||||||
|
resp.ContentLength64 = buffer.Length;
|
||||||
|
|
||||||
|
using Stream ros = resp.OutputStream;
|
||||||
|
ros.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
namespace PocketPutrMessageService;
|
||||||
|
|
||||||
|
public class DatabaseService
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<PublishAot>false</PublishAot>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
|
|
||||||
|
<ServerGarbageCollection>false</ServerGarbageCollection>
|
||||||
|
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
|
||||||
|
<RetainVMGarbageCollection>false</RetainVMGarbageCollection>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.Data.SQLite" Version="2.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
// See https://aka.ms/new-console-template for more information
|
||||||
|
|
||||||
|
using PocketPutrMessageService;
|
||||||
|
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
|
||||||
|
ClientService clientService = new ClientService();
|
||||||
|
ClientService.Run();
|
||||||
7
PocketPutrMessageService/global.json
Normal file
7
PocketPutrMessageService/global.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"rollForward": "latestMinor",
|
||||||
|
"allowPrerelease": false
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user