|
|
@ -11,59 +11,246 @@ |
|
|
|
#include "IRunnable.h" |
|
|
|
#include "IDrawable.h" |
|
|
|
|
|
|
|
// The maximum number of windows that can be created within the UI system.
|
|
|
|
#define MODULE_UI_MAX_WINDOWS 32 |
|
|
|
#define MODULE_UI_MULTICORE_STACK_SIZE 10240 |
|
|
|
|
|
|
|
// The maximum number of fonts that can be registered with the UI system.
|
|
|
|
#define MODULE_UI_MAX_FONTS 32 |
|
|
|
|
|
|
|
#define MODULE_UI_LAYOUT_MODE_NONE 0 |
|
|
|
#define MODULE_UI_LAYOUT_MODE_SPLIT_VERTICAL 1 |
|
|
|
#define MODULE_UI_LAYOUT_MODE_SPLIT_HORIZONTAL 2 |
|
|
|
#define MODULE_UI_LAYOUT_MODE_ABSOLUTE 3 |
|
|
|
/// <summary>
|
|
|
|
/// How to lay out the children of a given window
|
|
|
|
/// </summary>
|
|
|
|
enum ui_layout_mode : byte { |
|
|
|
/// <summary>
|
|
|
|
/// Perform no layout, all children will overlap
|
|
|
|
/// </summary>
|
|
|
|
NONE = 0, |
|
|
|
/// <summary>
|
|
|
|
/// Split vertically, windows laid out left to right
|
|
|
|
/// </summary>
|
|
|
|
SPLIT_VERTICAL = 1, |
|
|
|
/// <summary>
|
|
|
|
/// Split horizontally, windows laid out top to bottom
|
|
|
|
/// </summary>
|
|
|
|
SPLIT_HORIZONTAL = 2, |
|
|
|
/// <summary>
|
|
|
|
/// Manually lay out windows, each child must have its position and size set
|
|
|
|
/// </summary>
|
|
|
|
ABSOLUTE = 3 |
|
|
|
}; |
|
|
|
|
|
|
|
struct UiWindow; |
|
|
|
struct UiFont; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Module to handle layout out and putting things on the screen
|
|
|
|
/// </summary>
|
|
|
|
class Module_UI : public Task, public IRunnable |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// Reference to the power module so we can disable sleep while draws are in progress; the display chip
|
|
|
|
/// doesn't like it when you kill power mid-draw
|
|
|
|
/// </summary>
|
|
|
|
Module_Power* module_power; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// All registered/created windows
|
|
|
|
/// </summary>
|
|
|
|
UiWindow* m_window[MODULE_UI_MAX_WINDOWS]; |
|
|
|
/// <summary>
|
|
|
|
/// All fonts registered with the UI system
|
|
|
|
/// </summary>
|
|
|
|
UiFont* m_font[MODULE_UI_MAX_FONTS]; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Whether we've initialized the graphics hardware
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// This has to be done after every power-on (reset or deep sleep), but we do it lazily since it's often
|
|
|
|
/// not necessary and is time consuming.
|
|
|
|
/// </remarks>
|
|
|
|
bool m_initialized = false; |
|
|
|
bool m_dirty = false, m_redraw = false; |
|
|
|
// temp, until we implement scenes
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Whether any windows have been marked as "dirty" (requiring a redraw) since the last draw
|
|
|
|
/// </summary>
|
|
|
|
bool m_dirty = false; |
|
|
|
/// <summary>
|
|
|
|
/// Whether we desire a full-screen redraw at the next available opportunity
|
|
|
|
/// </summary>
|
|
|
|
bool m_redraw = false; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Handle to the root window
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// We only dirty / draw windows that exist somewhere underneath the root window
|
|
|
|
/// </remarks>
|
|
|
|
kernel_handle_t m_root; |
|
|
|
int m_draw_x, m_draw_y, m_draw_w, m_draw_h; |
|
|
|
|
|
|
|
|
|
|
|
// We track these values so methods like print/fill/etc can be aware of context when called by
|
|
|
|
// tasks and automatically draw within their allocated space.
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The X offset of the window we're currently drawing
|
|
|
|
/// </summary>
|
|
|
|
int m_draw_x; |
|
|
|
/// <summary>
|
|
|
|
/// The Y offset of the window we're currently drawing
|
|
|
|
/// </summary>
|
|
|
|
int m_draw_y; |
|
|
|
/// <summary>
|
|
|
|
/// The width of the window we're currently drawing
|
|
|
|
/// </summary>
|
|
|
|
int m_draw_w; |
|
|
|
/// <summary>
|
|
|
|
/// The height of the window we're currently drawing
|
|
|
|
/// </summary>
|
|
|
|
int m_draw_h; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Draw a window to screen, including all of its children
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="window">window to draw</param>
|
|
|
|
/// <param name="x">x offset on screen to start at</param>
|
|
|
|
/// <param name="y">y offset on screen to start at</param>
|
|
|
|
/// <param name="width">width of the space to draw within</param>
|
|
|
|
/// <param name="height">height of the space to draw within</param>
|
|
|
|
void draw_window(UiWindow* window, int x, int y, int width, int height); |
|
|
|
void local_to_screen(int* x, int* y); |
|
|
|
void get_screen_coordinates(UiWindow* window, int* x, int* y); |
|
|
|
|
|
|
|
public: |
|
|
|
Module_UI(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create a new window
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="drawable">drawable object</param>
|
|
|
|
/// <param name="parent">handle of a window to create this window under, WATCHOS_HANDLE_NULL for a root window</param>
|
|
|
|
/// <returns>handle of the newly created window</returns>
|
|
|
|
kernel_handle_t createWindow(IDrawable* drawable, kernel_handle_t parent); |
|
|
|
/// <summary>
|
|
|
|
/// Create a new placeholder window -- one that can have children, but is not drawn itself
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="parent">handle of the window to create this window under, WATCHOS_HANDLE_NULL for a root window</param>
|
|
|
|
/// <returns>handle of the newly created window</returns>
|
|
|
|
kernel_handle_t createWindow(kernel_handle_t parent); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Get the handle of the current root window
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>handle of the current root window</returns>
|
|
|
|
kernel_handle_t getRoot(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Set the current root window
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// Triggers a full screen redraw
|
|
|
|
/// </remarks>
|
|
|
|
/// <param name="handle">handle of the window that should be the root window</param>
|
|
|
|
void setRoot(kernel_handle_t handle); |
|
|
|
|
|
|
|
void initialize(); |
|
|
|
void start(); |
|
|
|
void tick(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Trigger a draw
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// Will either perform the draw synchronously (if multicore is disabled) or spawns a task
|
|
|
|
/// on the other core to run the draw asynchronously.
|
|
|
|
/// </remarks>
|
|
|
|
void draw(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Internal draw call, either called by draw() or indirectly if spawned on another core
|
|
|
|
/// </summary>
|
|
|
|
void do_draw(); |
|
|
|
|
|
|
|
void setLayoutMode(kernel_handle_t window_handle, byte layout_mode); |
|
|
|
/// <summary>
|
|
|
|
/// Set the layout mode of a window
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="window_handle">handle of the window to set the layout mode of</param>
|
|
|
|
/// <param name="layout_mode">one of the layout mode enum</param>
|
|
|
|
void setLayoutMode(kernel_handle_t window_handle, ui_layout_mode layout_mode); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Set the absolute position of an absolutely positioned window relative to parent
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// This only has any effect if the parent window is set to absolute layout
|
|
|
|
/// </remarks>
|
|
|
|
/// <param name="window_handle">handle to set the location of</param>
|
|
|
|
/// <param name="x">x offset from parent</param>
|
|
|
|
/// <param name="y">y offset from parent</param>
|
|
|
|
/// <param name="w">width of window</param>
|
|
|
|
/// <param name="h">height of window</param>
|
|
|
|
void setAbsolutePosition(kernel_handle_t window_handle, byte x, byte y, byte w, byte h); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Mark the window as dirty, requiring a draw
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="window_handle">handle of window to mark dirty</param>
|
|
|
|
void setDirty(kernel_handle_t window_handle); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Get the width of the current window
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>width in pixels</returns>
|
|
|
|
int getWidth(); |
|
|
|
/// <summary>
|
|
|
|
/// Get the height of the current window
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>height in pixels</returns>
|
|
|
|
int getHeight(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Fill the current window with the given colour
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="colour">colour to fill with; either COLOUR_PRIMARY or COLOUR_SECONDARY</param>
|
|
|
|
void fill(uint16_t colour = COLOUR_SECONDARY); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Fill a portion of the current window with the given colour
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="x">x offset within window</param>
|
|
|
|
/// <param name="y">y offset within window</param>
|
|
|
|
/// <param name="width">width of area to fill</param>
|
|
|
|
/// <param name="height">height of area to fill</param>
|
|
|
|
/// <param name="colour">colour to fill with; either COLOUR_PRIMARY or COLOUR_SECONDARY</param>
|
|
|
|
void fill(int x, int y, int width, int height, uint16_t colour = COLOUR_SECONDARY); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Print text to the screen
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="x">x offset within window to place bottom left corner of text</param>
|
|
|
|
/// <param name="y">y offset within window to place bottom left corner of text</param>
|
|
|
|
/// <param name="str">text to write</param>
|
|
|
|
/// <param name="colour">colour to render text with; either COLOUR_PRIMARY or COLOUR_SECONDARY</param>
|
|
|
|
/// <param name="font">pointer to GFXfont to use for text</param>
|
|
|
|
void print(int x, int y, char* str, uint16_t colour, void* font); |
|
|
|
/// <summary>
|
|
|
|
/// Print text to the screen
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="x">x offset within window to place bottom left corner of text</param>
|
|
|
|
/// <param name="y">y offset within window to place bottom left corner of text</param>
|
|
|
|
/// <param name="str">text to write</param>
|
|
|
|
/// <param name="colour">colour to render text with; either COLOUR_PRIMARY or COLOUR_SECONDARY</param>
|
|
|
|
/// <param name="font_id">id of a registered font</param>
|
|
|
|
void print(int x, int y, char* str, uint16_t colour = COLOUR_PRIMARY, byte font_id = 0); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Register a font with an id
|
|
|
|
/// </summary>
|
|
|
|
/// <remarks>
|
|
|
|
/// This can be passed to print(), avoids having to pull in the entire GFX library in order to
|
|
|
|
/// print text.
|
|
|
|
/// </remarks>
|
|
|
|
/// <param name="id">id to register the font with</param>
|
|
|
|
/// <param name="font">a pointer to a GFXfont</param>
|
|
|
|
void registerFont(byte id, const void* font); |
|
|
|
}; |
|
|
|
|
|
|
|