From b74a9f0c4b73bc3b98ec6c4345d9aaf4b6279f7a Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Tue, 9 May 2017 20:43:00 +0200 Subject: Simili file manager --- src/sysapp/login/main.lua | 113 ++++++++++++++++++++++++++++++++++++++++----- src/syslua/lx/tk.lua | 115 ++++++++++++++++++++++++---------------------- 2 files changed, 163 insertions(+), 65 deletions(-) diff --git a/src/sysapp/login/main.lua b/src/sysapp/login/main.lua index 0303c4f..a246c87 100644 --- a/src/sysapp/login/main.lua +++ b/src/sysapp/login/main.lua @@ -25,7 +25,7 @@ local wm = tk.window_manager() tk.init(gui, wm) local img = tk.image(f) -wm:add(img, "Window 1", 100, 16) +wm:add({title = "Window 1", x = 100, y = 16}, img) local img2 = tk.box({ center_content = true, vscroll = true, @@ -33,27 +33,118 @@ local img2 = tk.box({ vresize = true, hresize = true, }, tk.image(f)) -wm:add(img2, "Window 2", 16, 100) +wm:add({title = "Window 2", x = 16, y = 100}, img2) local img3 = tk.box({ constrain_size = true, vresize = true, hresize = true, }, tk.image(f)) -wm:add(img3, "Window 3", 300, 150) +wm:add({title = "Window 3", x = 300, y = 150}, img3) local txt = tk.text({color = tk.rgb(0, 255, 0), width=200}, "Hello, world!\nThis is a long text") -wm:add(txt, "Text example", 32, 32) +wm:add({title = "Text example", x = 32, y = 32}, txt) + + +function alert(text, on_dismiss) + local win = {} + win.widget = + tk.grid({}, + { { tk.text({padding = 16}, text) }, + { tk.box({center_content = true, height = 40}, + tk.text({background = tk.rgb(0, 255, 0), + padding = 4, + on_click = function() win.close() end}, + "Ok")) + } }) + win.close = function() + sys.dbg_print("Hello!") + wm:remove(win.win) + if on_dismiss then on_dismiss() end + end + win.win = wm:add({title = "Alert", + x = math.random(0, gui.surface:width() - 100), + y = math.random(0, gui.surface:height() - 100), + }, win.widget) +end + +function loopy() + alert("Hello, world !!", loopy) + gui.hide_cursor() + gui.surface:fillrect(0, 0, gui.surface:width(), gui.surface:height(), gui.surface:rgb(0, 0, 0)) + gui.show_cursor() + wm:redraw(0, 0, gui.surface:width(), gui.surface:height()) +end +loopy() + +-- A small file manager test :) + +local function open_listing(path) + local function fileline(name, path, size) + return { + tk.text(name), + tk.text(tostring(size)), + tk.box({center_content = true, width = 32}, + tk.text({background = tk.rgb(128, 128, 255), + padding =2, + text_size = 12, + on_click = function() open_listing(path) end}, + "open")) + } + end + local griditems = { + { tk.box({hresize = true, width = 200, constrain_size = true, min_width = 16, control_size = 8}, tk.text("Name")), + tk.box({hresize = true, width = 75, constrain_size = true, min_width = 16, control_size = 8}, tk.text("Size")), + tk.box({constrain_size = true}, tk.text("Actions")) + } + } + local fd = sys.open(path, sysdef.FM_READDIR) + if not fd then + alert("Could not FM_READDIR " .. path) + return + end + + local i = 0 + while true do + x = sys.readdir(fd, i) + if not x then break end + table.insert(griditems, fileline(x.name .. (x.type & sysdef.FT_DIR ~= 0 and "/" or ""), + path .. x.name .. "/", + x.size)) + i = i + 1 + end + sys.close(fd) + + local grid = tk.grid({border_size = 1}, griditems) + wm:add({title = path, + x = math.random(0, gui.surface:width() - 100), + y = math.random(0, gui.surface:height() - 100)}, + tk.box({vresize = true, hresize = true, vscroll = true, hscroll = true}, grid)) +end + +local function fsline(fs) + return { + tk.text(fs .. ":/"), + tk.box({center_content = true, width = 32}, + tk.text({background = tk.rgb(128, 128, 255), + padding =2, + text_size = 12, + on_click = function() open_listing(fs .. ":/") end}, + "open")) + } +end local grid = tk.grid({border_size = 1}, { { tk.box({hresize = true, width = 200, constrain_size = true, min_width = 16, control_size = 8}, tk.text("Name")), - tk.box({hresize = true, width = 100, constrain_size = true, min_width = 16, control_size = 8}, tk.text("Size")) }, - { tk.text("File A"), tk.text("10k") }, - { tk.text("File B"), tk.text("20k") }, - { tk.text("File C"), tk.text("15k") }, + tk.box({constrain_size = true}, tk.text("Actions")) + }, + fsline("io"), + fsline("root"), + fsline("config"), + fsline("app"), + fsline("sys"), }) -wm:add(tk.box({vresize = true, hresize = true, vscroll = true, hscroll = true}, grid), - "Grid example", 300, 20) - +wm:add({title = "Filesystems", x = 300, y = 20}, + tk.box({vresize = true, hresize = true, vscroll = true, hscroll = true}, grid)) mainloop.run() diff --git a/src/syslua/lx/tk.lua b/src/syslua/lx/tk.lua index 473ae3f..628ab91 100644 --- a/src/syslua/lx/tk.lua +++ b/src/syslua/lx/tk.lua @@ -135,6 +135,7 @@ function tk.widget(width, height, opts) y = 0, width = width, height = height, + on_click = function(self) end, } if opts then for k, v in pairs(opts) do @@ -147,10 +148,18 @@ function tk.widget(width, height, opts) -- does all the required redrawing -- - redraw : redraws a portion of the widget - -- can resize : checks if dimensiosn are valid + -- best resize : find best dimensions for resizing -- widget can replace this if necessary - function w:can_resize(width, height) - return (not width or width > 0) and (not height or height > 0) + function w:best_resize(width, height) + width = width or self.width + width = math.max(self.min_width or 1, width) + if self.max_width then width = math.min(width, self.max_width) end + + height = height or self.height + height = math.max(self.min_height or 1, height) + if self.max_height then height = math.min(height, self.max_height) end + + return width, height end -- do resize : updates position and size values but does not redraw anything @@ -216,9 +225,6 @@ function tk.widget(width, height, opts) self.left_click_valid = false end - function w:on_click() - end - function w:on_text_input(char) -- Handler for text input end @@ -297,13 +303,12 @@ function tk.image(a, b) local img = b or a local opts = b and a or {} + opts.min_width = img:width() + opts.min_height = img:height() + local image = tk.widget(img:width(), img:height(), opts) image.img = img - function image:can_resize(width, height) - return width >= self.img:width() and height >= self.img:height() - end - function image:draw(x0, y0, buf) local step = 20 local halfstep = 10 @@ -330,14 +335,20 @@ function tk.text(a, b) -- Some defaults opts.text_size = opts.text_size or 16 opts.padding = opts.padding or 2 - opts.background = opts.background or tk.rgb(255, 255, 255) + opts.background = opts.background or tk.rgb(220, 220, 220) opts.color = opts.color or tk.rgb(0, 0, 0) opts.line_spacing = opts.line_spacing or 1 if opts.word_wrap == nil then opts.word_wrap = true end opts.font = opts.font or tk.fonts.default opts.dy = opts.dy or -(opts.text_size//8) - local txt = tk.widget(100, #string.split(text, "\n")*(opts.text_size + opts.line_spacing) - opts.line_spacing + 2*opts.padding, opts) + local lines = string.split(text, "\n") + local width = 0 + for i = 1, #lines do + width = math.max(width, opts.font:text_width(lines[i], opts.text_size)) + end + + local txt = tk.widget(width+2*opts.padding, #lines*(opts.text_size + opts.line_spacing) - opts.line_spacing + 2*opts.padding, opts) txt.text = text function txt:draw(x0, y0, buf) @@ -371,40 +382,29 @@ function tk.box(a, b) opts.min_width = opts.min_width or 8 opts.min_height = opts.min_height or 8 opts.center_content = opts.center_content or false - opts.constrain_size = opts.constrain_size or nil - opts.background_color = opts.background_color or tk.rgb(190, 190, 190) + opts.constrain_size = opts.constrain_size or false + opts.background_color = opts.background_color or tk.rgb(220, 220, 220) opts.control_size = opts.control_size or 12 local box = tk.widget(content.width, content.height, opts) box.content = content box.content.parent = box - if box.center_content then - if box.width > box.content.width then - box.content.x = (box.width - box.content.width) // 2 - else - box.content.x = 0 - end - if box.height > box.content.height then - box.content.y = (box.height - box.content.height) // 2 - else - box.content.y = 0 - end - else - box.content.x = 0 - box.content.y = 0 - end + box.content.x = 0 + box.content.y = 0 - function box:can_resize(width, height) + function box:best_resize(width, height) if self.constrain_size then - return self.content:can_resize(width, height) + return self.content:best_resize(width, height) else - if width then - if self.min_width and width < self.min_width then return false end - end - if height then - if self.min_height and height < self.min_height then return false end - end - return true + width = width or self.width + width = math.max(self.min_width or 1, width) + if self.max_width then width = math.min(width, self.max_width) end + + height = height or self.height + height = math.max(self.min_height or 1, height) + if self.max_height then height = math.min(height, self.max_height) end + + return width, height end end @@ -435,10 +435,13 @@ function tk.box(a, b) assert(c == self.content) if self.constrain_size then self:resize(w, h) - elseif self.content:can_resize(w, h) then - self.content:do_resize(w, h) - self:do_resize(self.width, self.height) - self:redraw(0, 0, self.width, self.height, self) + else + local w, h = self.content:best_resize(w, h) + if w ~= self.content.width or h ~= self.content.height then + self.content:do_resize(w, h) + self:do_resize(self.width, self.height) + self:redraw(0, 0, self.width, self.height, self) + end end end @@ -569,8 +572,8 @@ function tk.grid(a, b) local grid = tk.widget(nil, nil, opts) grid.contents = contents - function grid:can_resize(w, h) - return w == self.col_pos[#self.contents[1]+1] and h == self.line_pos[#self.contents+1] + function grid:best_resize(w, h) + return self.col_pos[#self.contents[1]+1], self.line_pos[#self.contents+1] end function grid:reposition_elements() @@ -605,8 +608,6 @@ function tk.grid(a, b) self.contents[l][c]:do_resize(self.col_width[c], self.line_height[l]) end end - -- Resize me - self:do_resize(self.col_pos[#self.contents[1]+1], self.line_pos[#self.contents+1]) end function grid:get_lc(x, y) @@ -644,7 +645,8 @@ function tk.grid(a, b) end function grid:resize_child(item, width, height) - if not item:can_resize(width, height) then return end + local width, height = item:best_resize(width, height) + if width == item.width and height == item.height then return end local l, c = item.grid_l, item.grid_c local recalc = false @@ -702,6 +704,7 @@ function tk.grid(a, b) end grid:reposition_elements() + grid.width, grid.height = grid:best_resize(0, 0) return grid end @@ -719,12 +722,13 @@ function tk.window_manager() wm.mouse_mb = false wm.mouse_win = nil - function wm:add(content, title, x, y) - local win = tk.widget(content.width + 2, content.height + 22) + function wm:add(opts, content) + opts.x = opts.x or 24 + opts.y = opts.y or 24 + opts.title = opts.title or "--" + + local win = tk.widget(content.width + 2, content.height + 22, opts) win.parent = self - win.x = x or 24 - win.y = y or 24 - win.title = title win.visible = true table.insert(self.windows, win) self.window_pos[win] = {x = win.x, y = win.y, h = win.height, w = win.width} @@ -737,7 +741,8 @@ function tk.window_manager() function win:resize_child(c, w, h) assert(c == self.content) - if c:can_resize(w, h) then + local w, h = c:best_resize(w, h) + if w ~= c.width or h ~= c.height then local reg1 = wm.window_pos[self] c:do_resize(w, h) @@ -758,7 +763,7 @@ function tk.window_manager() self:draw_sub(x0, y0, buf, self.content) 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)) + buf:fillrect(-x0+1, -y0+1, win.width-2, 20, buf:rgb(255, 255, 255)) if win.title then buf:write(-x0+2, -y0+2, win.title, tk.fonts.default, 16, buf:rgb(0, 0, 0)) end @@ -797,6 +802,8 @@ function tk.window_manager() end self:redraw_win(win) + + return win end function wm:remove(win) -- cgit v1.2.3