diff --git a/src/ltui/action.lua b/src/ltui/action.lua index 20618a7..82a90b6 100644 --- a/src/ltui/action.lua +++ b/src/ltui/action.lua @@ -40,6 +40,7 @@ end action:register("ac_max", "ac_on_text_changed", "ac_on_selected", + "ac_on_clicked", "ac_on_resized", "ac_on_enter", "ac_on_load", diff --git a/src/ltui/boxdialog.lua b/src/ltui/boxdialog.lua index 1b1be6c..f27f0ac 100644 --- a/src/ltui/boxdialog.lua +++ b/src/ltui/boxdialog.lua @@ -64,6 +64,24 @@ function boxdialog:init(name, bounds, title) self:text():bounds().ey = self._TEXT_EY self:box():bounds_set(rect{0, self._TEXT_EY, v:width(), v:height() - 1}) end) + + -- on click for frame + self:frame():action_set(action.ac_on_clicked, function (v, x, y) + + -- get relative coordinates + x, y = x - v:bounds().sx, y - v:bounds().sy + local panel, box = v:parent():panel(), v:parent():box() + local px, py = x - panel:bounds().sx, y - panel:bounds().sy + + -- if coordinates don't match any view try box + if panel:option("mouseable") then + if panel:action_on(action.ac_on_clicked, x, y) then + return true + elseif box:option("mouseable") and not box:option("selectable") and box:bounds():contains(px, py) then + return box:action_on(action.ac_on_clicked, px, py) + end + end + end) end -- get box diff --git a/src/ltui/button.lua b/src/ltui/button.lua index 56ae916..aeaab56 100644 --- a/src/ltui/button.lua +++ b/src/ltui/button.lua @@ -41,8 +41,13 @@ function button:init(name, bounds, text, on_action) -- show cursor self:cursor_show(true) - -- init action + -- init actions + self:option_set("mouseable", true) self:action_set(action.ac_on_enter, on_action) + self:action_set(action.ac_on_clicked, function (v) + v:action_on(action.ac_on_enter) + return true + end) end -- draw button diff --git a/src/ltui/choicebox.lua b/src/ltui/choicebox.lua index e02626b..d0598a6 100644 --- a/src/ltui/choicebox.lua +++ b/src/ltui/choicebox.lua @@ -87,7 +87,12 @@ function choicebox:_do_insert(value, index, selected) local text = (selected and "(X) " or "( ) ") .. tostring(value) -- init a value item view - local item = button:new("choicebox.value." .. self:count(), rect:new(0, self:count(), self:width(), 1), text) + local item = button:new("choicebox.value." .. self:count(), + rect:new(0, self:count(), self:width(), 1), + text, + function (v, e) + self:_do_select() + end) -- attach this index item:extra_set("index", index) diff --git a/src/ltui/curses.lua b/src/ltui/curses.lua index 3ee6da1..6b55354 100644 --- a/src/ltui/curses.lua +++ b/src/ltui/curses.lua @@ -211,5 +211,10 @@ function curses.cursor_set(state) end end +-- has mouse? +function curses.has_mouse() + return curses.KEY_MOUSE and true or false +end + -- return module: curses return curses diff --git a/src/ltui/menuconf.lua b/src/ltui/menuconf.lua index 1f9983e..8709ae9 100644 --- a/src/ltui/menuconf.lua +++ b/src/ltui/menuconf.lua @@ -118,7 +118,12 @@ end function menuconf:_do_insert(config) -- init a config item view - local item = button:new("menuconf.config." .. self:count(), rect:new(0, self:count(), self:width(), 1), tostring(config)) + local item = button:new("menuconf.config." .. self:count(), + rect:new(0, self:count(), self:width(), 1), + tostring(config), + function (v, e) + self:_do_select() + end) -- attach this config item:extra_set("config", config) diff --git a/src/ltui/panel.lua b/src/ltui/panel.lua index e830702..1632f9e 100644 --- a/src/ltui/panel.lua +++ b/src/ltui/panel.lua @@ -26,6 +26,7 @@ local event = require("ltui/event") local point = require("ltui/point") local curses = require("ltui/curses") local dlist = require("ltui/base/dlist") +local action = require("ltui/action") -- define module local panel = panel or view() @@ -47,6 +48,32 @@ function panel:init(name, bounds) -- init views cache self._VIEWS_CACHE = {} + + -- on click action + self:option_set("mouseable", true) + self:action_set(action.ac_on_clicked, function (v, x, y) + + -- get relative coordinates + x, y = x - v:bounds().sx, y - v:bounds().sy + + -- try focused first + local current = v:current() + if current and current:option("mouseable") and current:bounds():contains(x, y) then + return current:action_on(action.ac_on_clicked, x, y) + end + + local p = v:last() + while p do + if p:option('selectable') and p:bounds():contains(x, y) then + if p:option("mouseable") then + v:select(p) + return p:action_on(action.ac_on_clicked, x, y) + end + return true + end + p = v:prev(p) + end + end) end -- get all child views diff --git a/src/ltui/program.lua b/src/ltui/program.lua index 7046274..b3d9692 100644 --- a/src/ltui/program.lua +++ b/src/ltui/program.lua @@ -25,6 +25,7 @@ local point = require("ltui/point") local panel = require("ltui/panel") local event = require("ltui/event") local curses = require("ltui/curses") +local action = require("ltui/action") -- define module local program = program or panel() @@ -46,6 +47,7 @@ function program:init(name, argv) -- init mouse support if curses.KEY_MOUSE then + -- curses.ALL_MOUSE_EVENTS may be set to mask unused events curses.mousemask(curses.ALL_MOUSE_EVENTS) end @@ -186,6 +188,11 @@ function program:on_event(e) elseif event.is_command(e, "cm_exit") then self:quit() return true + -- mouse events + elseif e.type == event.ev_mouse and curses.has_mouse() and self:option("mouseable") then + if e.btn_name == "BUTTON1_CLICKED" or e.btn_name == "BUTTON1_DOUBLE_CLICKED" then + self:action_on(action.ac_on_clicked, e.x, e.y) + end end end diff --git a/src/ltui/view.lua b/src/ltui/view.lua index d8e46b9..9800553 100644 --- a/src/ltui/view.lua +++ b/src/ltui/view.lua @@ -68,6 +68,7 @@ function view:init(name, bounds) -- init options local options = object() options.selectable = false -- true if window can be selected + options.mouseable = false -- false by default self._OPTIONS = options -- init attributes