Adam Pippin
4 years ago
3 changed files with 190 additions and 18 deletions
@ -1,22 +1,168 @@ |
|||
#include <M5StickC.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) |
|||
{ |
|||
if (signal & SIGNAL_START) |
|||
{ |
|||
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) |
|||
{ |
|||
return 255; |
|||
} |
|||
|
|||
if (signal & SIGNAL_REDRAW) |
|||
{ |
|||
M5.Lcd.fillScreen(TFT_DARKGREY); |
|||
M5.Lcd.setRotation(3); |
|||
M5.Lcd.setTextColor(TFT_WHITE, TFT_DARKGREY); |
|||
for (int i=0; i<MAX_WINDOWS; i++) |
|||
{ |
|||
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; |
|||
} |
|||
|
|||
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_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