From c7486a2113171d4d3fe7891ddf898f9f00865cc9 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Thu, 4 May 2017 16:27:27 +0200 Subject: Window moving :) --- src/lib/libkogata/draw.c | 27 +++++-- src/sysapp/login/main.lua | 7 +- src/syslua/lx/gui.lua | 16 ++++ src/syslua/lx/tk.lua | 201 +++++++++++++++++++++++++++++++++++++++++++--- 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 -- cgit v1.2.3