aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libkogata/draw.c27
-rw-r--r--src/sysapp/login/main.lua7
-rw-r--r--src/syslua/lx/gui.lua16
-rw-r--r--src/syslua/lx/tk.lua201
4 files changed, 232 insertions, 19 deletions
diff --git a/src/lib/libkogata/draw.c b/src/lib/libkogata/draw.c
index 4e5dcf2..9ef4031 100644
--- a/src/lib/libkogata/draw.c
+++ b/src/lib/libkogata/draw.c
@@ -599,17 +599,29 @@ int g_text_height(font_t *font, const char* text, int size) {
}
void g_write(fb_t *fb, int x, int y, const char* text, font_t *font, int size, color_t c) {
+ fb_region_t r;
+ r.x = 0;
+ r.y = 0;
+ r.w = fb->geom.width;
+ r.h = fb->geom.height;
+
+ g_region_write(fb, &r, x, y, text, font, size, c);
+}
+
+void g_region_write(fb_t *fb, fb_region_t *reg, int x, int y, const char* text, font_t *font, int size, color_t c) {
if (font->type == FONT_ASCII_BITMAP) {
while (*text != 0) {
uint8_t id = (uint8_t)*text;
if (id < font->ascii_bitmap.nchars) {
uint8_t *d = font->ascii_bitmap.data + (id * font->ascii_bitmap.ch);
for (int r = 0; r < font->ascii_bitmap.ch; r++) {
- if (y + r >= fb->geom.height) continue;
+ int yy = y + reg->y + r;
+ if (y + r >= reg->h || yy >= fb->geom.height) continue;
for (int j = 0; j < 8; j++) {
- if (x + j >= fb->geom.width) continue;
+ int xx = x + reg->x + j;
+ if (x + j >= reg->w || xx >= fb->geom.width) continue;
if (d[r] & (0x80 >> j)) {
- g_plot(fb, x + j, y + r, c);
+ g_plot(fb, xx, yy, c);
}
}
}
@@ -654,12 +666,18 @@ void g_write(fb_t *fb, int x, int y, const char* text, font_t *font, int size, c
for (int i = 0; i < h; i++) {
int yy = y + size + y0 + i;
if (yy < 0) continue;
+ if (yy >= reg->h) continue;
+ yy += reg->y;
+ if (yy < 0) continue;
if (yy >= fb->geom.height) continue;
uint8_t *line = fb->data + yy * fb->geom.pitch;
for (int j = 0; j < w; j++) {
int xx = x + x0 + (int)xpos + j;
if (xx < 0) continue;
+ if (xx >= reg->w) continue;
+ xx += reg->x;
+ if (xx < 0) continue;
if (xx >= fb->geom.width) continue;
uint8_t a = tmp[i*w+j];
@@ -686,9 +704,6 @@ void g_write(fb_t *fb, int x, int y, const char* text, font_t *font, int size, c
}
}
-void g_region_write(fb_t *fb, fb_region_t *reg, int x, int y, const char* text, font_t *font, int size, color_t c) {
- // TODO
-}
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/sysapp/login/main.lua b/src/sysapp/login/main.lua
index 6be064d..a0297f8 100644
--- a/src/sysapp/login/main.lua
+++ b/src/sysapp/login/main.lua
@@ -20,8 +20,13 @@ for x = 0, 255, 16 do
end
local f = draw.load_image('root:/logo.png')
+local wm = tk.wm_widget()
+tk.init(gui, wm)
+
local img = tk.image_widget(f)
-tk.init(gui, img)
+wm:add(img, "Window 1", 100, 16)
+local img2 = tk.image_widget(f)
+wm:add(img2, "Window 2", 16, 100)
gui.show_cursor()
diff --git a/src/syslua/lx/gui.lua b/src/syslua/lx/gui.lua
index 35e73b8..6cfb545 100644
--- a/src/syslua/lx/gui.lua
+++ b/src/syslua/lx/gui.lua
@@ -60,6 +60,22 @@ function gui.open_io()
gui.pcmouse_mainloop_fd = mainloop.add_fd(gui.pcmouse_fd, function() error("pcmouse fd error") end)
local function pcmouse_handler(ev)
local dx, dy, dw, lb, rb, mb = string.unpack("hhbBBB", ev)
+ local change_but = false
+
+ while not change_but do
+ local bytes, n = sys.read(gui.pcmouse_fd, 1, 8)
+ if n == 8 then
+ local dx2, dy2, dw2, lb2, rb2, mb2 = string.unpack("hhbBBB", ev)
+ change_but = change_but or (lb2 ~= lb) or (rb2 ~= rb) or (mb2 ~= mb)
+ dx = dx + dx2
+ dy = dy + dy2
+ lb = lb2
+ rb = rb2
+ mb = mb2
+ else
+ break
+ end
+ end
gui.on_mouse(dx, dy, dw, lb, rb, mb)
gui.pcmouse_mainloop_fd:expect(8, pcmouse_handler)
diff --git a/src/syslua/lx/tk.lua b/src/syslua/lx/tk.lua
index 3771748..374e260 100644
--- a/src/syslua/lx/tk.lua
+++ b/src/syslua/lx/tk.lua
@@ -19,15 +19,15 @@ function tk.widget(width, height)
return nil
end
- function w:redraw(x0, y0, w, h)
+ function w:redraw(x0, y0, buf)
-- Replaced by widget code by a function that does the actual drawing
end
- function w:on_mouse_down(lb, rb, mb)
+ function w:on_mouse_down(x, y, lb, rb, mb)
-- Handler for mouse down event
end
- function w:on_mouse_up(lb, rb, mb)
+ function w:on_mouse_up(x, y, lb, rb, mb)
-- Handler for mouse up event
end
@@ -51,6 +51,12 @@ function tk.widget(width, height)
end
function tk.init(gui, root_widget)
+ if tk.root_widget ~= nil then return end
+ tk.root_widget = root_widget
+
+ if root_widget.parent ~= nil then return end
+ root_widget.parent = gui
+
tk.fonts = {
default = draw.load_ttf_font("sys:/fonts/vera.ttf")
}
@@ -61,28 +67,25 @@ function tk.init(gui, root_widget)
gui.on_key_up = function(key) root_widget:on_key_up(key) end
gui.on_text_input = function(key) root_widget:on_text_input(char) end
gui.on_mouse_move = function(ox, oy, nx, ny) root_widget:on_mouse_move(ox, oy, nx, ny) end
- gui.on_mouse_down = function(lb, rb, mb) root_widget:on_mouse_down(lb, rb, mb) end
- gui.on_mouse_up = function(lb, rb, mb) root_widget:on_mouse_up(lb, rb, mb) end
+ gui.on_mouse_down = function(lb, rb, mb) root_widget:on_mouse_down(gui.mouse_x, gui.mouse_y, lb, rb, mb) end
+ gui.on_mouse_up = function(lb, rb, mb) root_widget:on_mouse_up(gui.mouse_x, gui.mouse_y, lb, rb, mb) end
function root_widget:get_draw_buffer(x0, y0, w, h)
return gui.surface:sub(x0, y0, w, h)
end
- root_widget:redraw(0, 0, root_widget.width, root_widget.height)
+ root_widget:redraw(0, 0, gui.surface)
end
function tk.image_widget(img)
local image = tk.widget(img:width(), img:height())
image.img = img
- function image:redraw(x0, y0, w, h)
- local buf = self:get_draw_buffer(x0, y0, w, h)
- if buf == nil then return end
-
+ function image:redraw(x0, y0, buf)
local step = 20
local halfstep = 10
- for x = x0 - (x0 % step), x0 + w, step do
- for y = y0 - (y0 % step), y0 + h, step do
+ for x = x0 - (x0 % step), x0 + buf:width(), step do
+ for y = y0 - (y0 % step), y0 + buf:height(), step do
buf:fillrect(x - x0, y - y0, halfstep, halfstep, buf:rgb(150, 150, 150))
buf:fillrect(x - x0 + halfstep, y - y0 + halfstep, halfstep, halfstep, buf:rgb(150, 150, 150))
buf:fillrect(x - x0 + halfstep, y - y0, halfstep, halfstep, buf:rgb(170, 170, 170))
@@ -95,5 +98,179 @@ function tk.image_widget(img)
return image
end
+function tk.wm_widget()
+ local wm = tk.widget(100, 100)
+ wm.windows = {} -- Last = on top
+
+ function wm:add(content, title, x, y)
+ local win = tk.widget(content.width + 2, content.height + 22)
+ win.parent = self
+ win.x = x or 24
+ win.y = y or 24
+ win.title = title
+ win.visible = true
+ table.insert(self.windows, win)
+
+ win.content = content
+ content.parent = win
+ content.x = 1
+ content.y = 21
+
+ function content:get_draw_buffer(x0, y0, w, h)
+ if x0 + w > self.width then w = self.width - x0 end
+ if y0 + h > self.height then h = self.height - y0 end
+ return win:get_draw_buffer(x0 + 1, y0 + 21, w, h)
+ end
+
+ function win:get_draw_buffer(x0, y0, w, h)
+ -- TODO clipping etc
+ end
+
+ function win:redraw(x0, y0, buf)
+ local xx0 = math.max(x0, 1)
+ local yy0 = math.max(y0, 21)
+
+ local ww, hh = buf:width() - (xx0-x0), buf:height() - (yy0-y0)
+ if xx0-1 + ww > content.width then ww = content.width - xx0+1 end
+ if yy0-21 + ww > content.height then hh = content.height - yy0+21 end
+
+ self.content:redraw(xx0-1, yy0-21, buf:sub(xx0-x0, yy0-y0, ww, hh))
+
+ buf:rect(-x0, -y0, self.width, self.height, buf:rgb(255, 128, 0))
+ buf:fillrect(-x0+1, -y0+1, win.width-2, 20, buf:rgb(200, 200, 200))
+ if win.title then
+ buf:write(-x0+2, -y0+2, win.title, tk.fonts.default, 16, buf:rgb(0, 0, 0))
+ end
+ end
+
+ function win:on_mouse_down(x, y, lb, rb, mb)
+ if y < 22 and lb then
+ self.moving = true
+ else
+ self.content:on_mouse_down(x-1, y-21, lb, rb, mb)
+ end
+ end
+
+ function win:on_mouse_up(x, y, lb, rb, mb)
+ if self.moving then
+ self.moving = false
+ else
+ self.content:on_mouse_up(x-1, y-21, lb, rb, mb)
+ end
+ end
+
+ function win:on_mouse_move(px, py, nx, ny)
+ if self.moving then
+ self.visible = false
+ wm:redraw_win(self)
+ self.x = self.x + nx - px
+ self.y = self.y + ny - py
+ self.visible = true
+ wm:redraw_win(self)
+ else
+ self.content:on_mouse_move(px-1, py-21, px-1, py-21)
+ end
+ end
+
+ self:redraw_win(win)
+ end
+
+ function wm:remove(win)
+ if win.parent ~= self then return end
+ win.parent = nil
+ win.get_draw_buffer = function() return nil end
+
+ win.content.parent = nil
+ win.content.get_draw_buffer = function() return nil end
+
+ for i, w2 in pairs(self.windows) do
+ if w2 == win then
+ table.remove(self.windows, i)
+ return
+ end
+ end
+ end
+
+ function wm:redraw_win(win)
+ local x0, y0 = math.max(0, win.x), math.max(0, win.y)
+ local width = win.x + win.width - x0
+ local height = win.y + win.height - y0
+ self:redraw(x0, y0, self:get_draw_buffer(x0, y0, width, height))
+ end
+
+ function wm:redraw(x0, y0, buf)
+ -- Draw background
+
+ local step = 32
+ local halfstep = 16
+ for x = x0 - (x0 % step), x0 + buf:width(), step do
+ for y = y0 - (y0 % step), y0 + buf:height(), step do
+ buf:fillrect(x - x0, y - y0, halfstep, halfstep, buf:rgb(110, 110, 140))
+ buf:fillrect(x - x0 + halfstep, y - y0 + halfstep, halfstep, halfstep, buf:rgb(110, 110, 140))
+ buf:fillrect(x - x0 + halfstep, y - y0, halfstep, halfstep, buf:rgb(110, 140, 110))
+ buf:fillrect(x - x0, y - y0 + halfstep, halfstep, halfstep, buf:rgb(110, 140, 110))
+ end
+ end
+
+ -- TODO do this in inverse order and clip regions of hidden windows
+ -- so that less redrawing is done
+ for i = 1, #self.windows do
+ win = self.windows[i]
+ if win.visible then
+ local wx0, wy0 = math.max(x0, win.x), math.max(y0, win.y)
+ local ww, wh = win.x + win.width - wx0, win.y + win.height - wy0
+ if ww > 0 and wh > 0 then
+ win:redraw(wx0 - win.x, wy0 - win.y, buf:sub(wx0 - x0, wy0 - y0, ww, wh))
+ end
+ end
+ end
+ end
+
+ function wm:find_win(x, y)
+ for i = #self.windows, 1, -1 do
+ local win = self.windows[i]
+ if win.visible and x >= win.x and y >= win.y and x < win.x + win.width and y < win.y + win.height then
+ return win
+ end
+ end
+ return nil
+ end
+
+ function wm:on_mouse_down(x, y, lb, rb, mb)
+ local on_win = self:find_win(x, y)
+ if on_win then
+ sys.dbg_print(string.format("Mouse down on window %s\n", on_win.title))
+
+ if self.windows[#self.windows] ~= on_win then
+ for i, w in pairs(self.windows) do
+ if w == on_win then
+ table.remove(self.windows, i)
+ break
+ end
+ end
+ table.insert(self.windows, on_win)
+ self:redraw_win(on_win)
+ end
+ on_win:on_mouse_down(x - on_win.x, y - on_win.y, lb, rb, mb)
+ end
+ end
+
+ function wm:on_mouse_up(x, y, lb, rb, mb)
+ local on_win = self:find_win(x, y)
+ if on_win then
+ on_win:on_mouse_up(x - on_win.x, y - on_win.y, lb, rb, mb)
+ end
+ end
+
+ function wm:on_mouse_move(prev_x, prev_y, new_x, new_y)
+ local on_win = self:find_win(prev_x, prev_y)
+ if on_win then
+ on_win:on_mouse_move(prev_x - on_win.x, prev_y - on_win.y, new_x - on_win.x, new_y - on_win.y)
+ end
+ end
+
+ return wm
+end
+
return tk