Adam Pippin
4 years ago
3 changed files with 190 additions and 18 deletions
@ -1,22 +1,168 @@ |
|||||
#include <M5StickC.h> |
#include <M5StickC.h> |
||||
#include "Kernel.h" |
#include "Kernel.h" |
||||
|
#include "UI.h" |
||||
|
|
||||
|
#define MAX_WINDOWS 8 |
||||
|
|
||||
|
struct Window *UI_get_window(int hwnd); |
||||
|
void base_window_callback(int hwnd, int x, int y, int width, int height); |
||||
|
void draw(int parent_hwnd, int x, int y, int width, int height); |
||||
|
|
||||
|
struct Window windows[MAX_WINDOWS]; |
||||
|
int next_hwnd = 1; |
||||
|
|
||||
int UI(int pid, unsigned int signal) |
int UI(int pid, unsigned int signal) |
||||
{ |
{ |
||||
if (signal & SIGNAL_START) |
if (signal & SIGNAL_START) |
||||
{ |
{ |
||||
Kernel_signal_mask(pid, SIGNAL_START | SIGNAL_STOP | SIGNAL_REDRAW); |
Kernel_signal_mask(pid, SIGNAL_START | SIGNAL_STOP | SIGNAL_REDRAW); |
||||
|
windows[0].hwnd = next_hwnd++; |
||||
|
windows[0].hwnd_parent = 0; |
||||
|
windows[0].layout_mode = LAYOUT_MODE_SPLIT_VERTICAL; |
||||
|
windows[0].callback = &base_window_callback; |
||||
} |
} |
||||
|
|
||||
if (signal & SIGNAL_STOP) |
if (signal & SIGNAL_STOP) |
||||
{ |
{ |
||||
return 255; |
return 255; |
||||
} |
} |
||||
|
|
||||
if (signal & SIGNAL_REDRAW) |
if (signal & SIGNAL_REDRAW) |
||||
{ |
{ |
||||
M5.Lcd.fillScreen(TFT_DARKGREY); |
for (int i=0; i<MAX_WINDOWS; i++) |
||||
M5.Lcd.setRotation(3); |
{ |
||||
M5.Lcd.setTextColor(TFT_WHITE, TFT_DARKGREY); |
if (windows[i].hwnd == 0 || windows[i].hwnd_parent != 0) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
M5.Lcd.setTextColor(TFT_WHITE, TFT_DARKGREY); |
||||
|
// TODO: Get actual screen bounds somehow
|
||||
|
draw(windows[i].hwnd, 0, 0, 160, 80); |
||||
|
} |
||||
} |
} |
||||
|
|
||||
return 0; |
return 0; |
||||
} |
} |
||||
|
|
||||
|
void draw(int parent_hwnd, int x, int y, int width, int height) |
||||
|
{ |
||||
|
Serial.printf("Drawing window %d\n", parent_hwnd); |
||||
|
// Trigger draw
|
||||
|
Window* parent_window = UI_get_window(parent_hwnd); |
||||
|
if (parent_window->hwnd == -1) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Call callback on parent if available
|
||||
|
if (parent_window->placeholder != true) |
||||
|
{ |
||||
|
(*parent_window->callback)(parent_hwnd, x, y, width, height); |
||||
|
} |
||||
|
|
||||
|
// Count the number of children
|
||||
|
int child_count = 0; |
||||
|
for (int i=0; i<MAX_WINDOWS; i++) |
||||
|
{ |
||||
|
if (windows[i].hwnd_parent == parent_hwnd) |
||||
|
{ |
||||
|
child_count++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Serial.printf("Found %d children\n", child_count); |
||||
|
|
||||
|
if (child_count == 0) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Grab all the children
|
||||
|
Window* children[child_count]; |
||||
|
int next_child = 0; |
||||
|
for (int i=0; i<MAX_WINDOWS; i++) |
||||
|
{ |
||||
|
if (windows[i].hwnd_parent == parent_hwnd) |
||||
|
{ |
||||
|
children[next_child++] = &windows[i]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
switch (parent_window->layout_mode) |
||||
|
{ |
||||
|
case LAYOUT_MODE_NONE: |
||||
|
{ |
||||
|
Serial.printf("Layout mode: none\n"); |
||||
|
for (int i=0; i<child_count; i++) |
||||
|
{ |
||||
|
draw(children[i]->hwnd, x, y, width, height); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
case LAYOUT_MODE_SPLIT_VERTICAL: |
||||
|
{ |
||||
|
Serial.printf("Layout mode: vertical\n"); |
||||
|
int child_width = width / child_count; |
||||
|
for (int i=0; i<child_count; i++) |
||||
|
{ |
||||
|
draw(children[i]->hwnd, x + (i * child_width), y, child_width, height); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
case LAYOUT_MODE_SPLIT_HORIZONTAL: |
||||
|
{ |
||||
|
Serial.printf("Layout mode: horizontal\n"); |
||||
|
int child_height = height / child_count; |
||||
|
for (int i=0; i<child_count; i++) |
||||
|
{ |
||||
|
draw(children[i]->hwnd, x, y + (i * child_height), width, child_height); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void base_window_callback(int hwnd, int x, int y, int width, int height) |
||||
|
{ |
||||
|
M5.Lcd.fillScreen(TFT_DARKGREY); |
||||
|
M5.Lcd.setRotation(3); |
||||
|
} |
||||
|
|
||||
|
int UI_create_window(void (*callback)(int, int, int, int, int), int parent /* = 0 */, int zorder /* = 0 */, bool placeholder /* = true */) |
||||
|
{ |
||||
|
Window* window = UI_get_window(0); |
||||
|
if (window->hwnd == -1) |
||||
|
{ |
||||
|
Kernel_panic("Cannot create window! Out of handles!"); |
||||
|
} |
||||
|
|
||||
|
window->hwnd = next_hwnd++; |
||||
|
window->hwnd_parent = parent; |
||||
|
window->placeholder = placeholder; |
||||
|
window->callback = callback; |
||||
|
return window->hwnd; |
||||
|
} |
||||
|
|
||||
|
void UI_set_layout_mode(int hwnd, int layout_mode) |
||||
|
{ |
||||
|
Window* window = UI_get_window(0); |
||||
|
if (window->hwnd == -1) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
window->layout_mode = layout_mode; |
||||
|
} |
||||
|
|
||||
|
struct Window *UI_get_window(int hwnd) |
||||
|
{ |
||||
|
for (int i=0; i<MAX_WINDOWS; i++) |
||||
|
{ |
||||
|
if (windows[i].hwnd == hwnd) |
||||
|
{ |
||||
|
return &windows[i]; |
||||
|
} |
||||
|
} |
||||
|
struct Window empty = Window(); |
||||
|
empty.hwnd = -1; |
||||
|
return ∅ |
||||
|
} |
||||
|
@ -1,2 +1,17 @@ |
|||||
|
|
||||
|
struct Window |
||||
|
{ |
||||
|
int hwnd = 0; |
||||
|
void (*callback)(int, int, int, int, int); |
||||
|
int hwnd_parent = 0; |
||||
|
int layout_mode = 0; |
||||
|
bool placeholder = false; |
||||
|
}; |
||||
|
|
||||
|
#define LAYOUT_MODE_NONE 0 |
||||
|
#define LAYOUT_MODE_SPLIT_VERTICAL 1 |
||||
|
#define LAYOUT_MODE_SPLIT_HORIZONTAL 2 |
||||
|
|
||||
int UI(int pid, unsigned int signal); |
int UI(int pid, unsigned int signal); |
||||
|
int UI_create_window(void (*callback)(int, int, int, int, int), int parent = 0, int zorder = 0, bool placeholder = false); |
||||
|
void UI_set_layout_mode(int hwnd, int layout_mode); |
||||
|
Loading…
Reference in new issue