Browse Source

UI: absolute positioning; partial updates

master
Adam Pippin 3 years ago
parent
commit
bcb3d9d717
  1. 106
      watchos2/Module_UI.cpp
  2. 2
      watchos2/Module_UI.h

106
watchos2/Module_UI.cpp

@ -12,6 +12,8 @@ struct UiWindow
byte layout_mode; byte layout_mode;
UiWindow* parent; UiWindow* parent;
bool dirty; bool dirty;
bool needs_draw;
byte x, y, w, h;
}; };
struct UiFont struct UiFont
@ -57,7 +59,6 @@ void Module_UI::start()
} }
m_root = createWindow(WATCHOS_HANDLE_NULL); m_root = createWindow(WATCHOS_HANDLE_NULL);
module_power = static_cast<Module_Power*>(watchos::module(WATCHOS_MODULE_POWER)); module_power = static_cast<Module_Power*>(watchos::module(WATCHOS_MODULE_POWER));
} }
@ -81,6 +82,7 @@ kernel_handle_t Module_UI::createWindow(IDrawable* drawable, kernel_handle_t par
m_window[i]->layout_mode = MODULE_UI_LAYOUT_MODE_NONE; m_window[i]->layout_mode = MODULE_UI_LAYOUT_MODE_NONE;
m_window[i]->parent = nullptr; m_window[i]->parent = nullptr;
m_window[i]->dirty = true; m_window[i]->dirty = true;
m_window[i]->needs_draw = false;
if (parent != WATCHOS_HANDLE_NULL) if (parent != WATCHOS_HANDLE_NULL)
{ {
@ -162,12 +164,47 @@ void Module_UI::do_draw()
} }
} }
// TODO: Redraw only parts of the screen if necessary, etc // Actually figure out what to draw
// Also confirm that anything was actually drawn. Could mitigate the risk of extraenous draw calls bool whole_screen = false;
// from multicore (see above comments in draw()) int x, y;
// false does a full invert/etc, true just updates in place and can leave ghosting/etc for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
// do false on a full-screen redraw, false otherwise? trigger a full-screen redraw every certain number of redraws? {
gfx.display(!m_redraw); if (m_window[i] != nullptr && m_window[i]->needs_draw)
{
get_screen_coordinates(m_window[i], &x, &y);
if (x == 0 && y == 0 && m_window[i]->w == DISPLAY_WIDTH && m_window[i]->h == DISPLAY_HEIGHT)
{
whole_screen = true;
break;
}
}
}
if (whole_screen)
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr)
{
m_window[i]->needs_draw = false;
}
}
gfx.display(!m_redraw);
}
else
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->needs_draw)
{
get_screen_coordinates(m_window[i], &x, &y);
gfx.displayWindow(x, y, m_window[i]->w, m_window[i]->h);
m_window[i]->needs_draw = false;
}
}
}
m_redraw = false; m_redraw = false;
module_power->enableDeepSleep(); module_power->enableDeepSleep();
@ -181,11 +218,27 @@ void Module_UI::draw_window(UiWindow* window, int x, int y, int width, int heigh
m_draw_w = width; m_draw_w = width;
m_draw_h = height; m_draw_h = height;
// Track the last calculated position for this window so we can actually figure out
// where to update the screen.
if (window->parent != nullptr)
{
window->x = x - window->parent->x;
window->y = y - window->parent->y;
}
else
{
window->x = x;
window->y = y;
}
window->w = width;
window->h = height;
// Draw window // Draw window
if (window->drawable != nullptr && (window->dirty || m_redraw)) if (window->drawable != nullptr && (window->dirty || m_redraw))
{ {
window->drawable->draw(window->handle); window->drawable->draw(window->handle);
window->dirty = false; window->dirty = false;
window->needs_draw = true;
} }
// Count children // Count children
@ -238,7 +291,13 @@ void Module_UI::draw_window(UiWindow* window, int x, int y, int width, int heigh
} }
break; break;
case MODULE_UI_LAYOUT_MODE_ABSOLUTE: case MODULE_UI_LAYOUT_MODE_ABSOLUTE:
// TODO: for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->parent == window)
{
draw_window(m_window[i], x + m_window[i]->x, y + m_window[i]->y, m_window[i]->w, m_window[i]->h);
}
}
break; break;
} }
} }
@ -256,6 +315,23 @@ void Module_UI::setLayoutMode(kernel_handle_t window_handle, byte layout_mode)
watchos::panic("Trying to set layout mode on non-existent handle: %#010x", window_handle); watchos::panic("Trying to set layout mode on non-existent handle: %#010x", window_handle);
} }
void Module_UI::setAbsolutePosition(kernel_handle_t window_handle, byte x, byte y, byte w, byte h)
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->handle == window_handle)
{
m_window[i]->x = x;
m_window[i]->y = y;
m_window[i]->w = w;
m_window[i]->h = h;
return;
}
}
watchos::panic("Trying to set position on non-existent handle: %#010x", window_handle);
}
void Module_UI::setDirty(kernel_handle_t window_handle) void Module_UI::setDirty(kernel_handle_t window_handle)
{ {
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++) for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
@ -283,7 +359,7 @@ int Module_UI::getHeight()
void Module_UI::fill(uint16_t colour) void Module_UI::fill(uint16_t colour)
{ {
fill(m_draw_x, m_draw_y, m_draw_w, m_draw_h, colour); fill(0, 0, m_draw_w, m_draw_h, colour);
} }
void Module_UI::fill(int x, int y, int width, int height, uint16_t colour) void Module_UI::fill(int x, int y, int width, int height, uint16_t colour)
@ -328,6 +404,18 @@ void Module_UI::local_to_screen(int* x, int* y)
*y = m_draw_y + *y; *y = m_draw_y + *y;
} }
void Module_UI::get_screen_coordinates(UiWindow* window, int* x, int* y)
{
*x = window->x;
*y = window->y;
while (window->parent != nullptr)
{
window = window->parent;
*x = *x + window->x;
*y = *y + window->y;
}
}
void Module_UI::registerFont(byte id, const void* font) void Module_UI::registerFont(byte id, const void* font)
{ {
for (int i = 0; i < MODULE_UI_MAX_FONTS; i++) for (int i = 0; i < MODULE_UI_MAX_FONTS; i++)

2
watchos2/Module_UI.h

@ -38,6 +38,7 @@ class Module_UI : public Task, public IRunnable
void draw_window(UiWindow* window, int x, int y, int width, int height); void draw_window(UiWindow* window, int x, int y, int width, int height);
void local_to_screen(int* x, int* y); void local_to_screen(int* x, int* y);
void get_screen_coordinates(UiWindow* window, int* x, int* y);
public: public:
Module_UI(); Module_UI();
@ -53,6 +54,7 @@ public:
void do_draw(); void do_draw();
void setLayoutMode(kernel_handle_t window_handle, byte layout_mode); void setLayoutMode(kernel_handle_t window_handle, byte layout_mode);
void setAbsolutePosition(kernel_handle_t window_handle, byte x, byte y, byte w, byte h);
void setDirty(kernel_handle_t window_handle); void setDirty(kernel_handle_t window_handle);
int getWidth(); int getWidth();

Loading…
Cancel
Save