tboox / ltui

🍖 A cross-platform terminal ui library based on Lua
https://tboox.org
Apache License 2.0
808 stars 49 forks source link

Mouse support #14

Closed laelnasan closed 3 years ago

laelnasan commented 3 years ago

Hi, I've been looking for a good framework for working with ncurses in lua and by far this one is what works best for me. It would be nice, though if it would support the ncurses and pdcurses ability to use mouse events. Reading the lua code I noticed that it might be in the plans since there is a event related to it.

I've been working the last few days in the support for mouse events in ltui, and must say it was really easy to get it working compared to other solutions. If you would be so kind of reviewing my work, I would love to contribute to this great project.

Describe the solution you'd like

Mouse support for ltui

Describe alternatives you've considered

I've forked the code and made some small changes to it, and now it works! (at least with ncurses. couldn't get to run a windows machine, yet)

PS: I tried to stick to the coding style as much as possible.

https://github.com/tboox/ltui/pull/15

waruqi commented 3 years ago

Great, thank you very much for your contribution, I will review this patch.

waruqi commented 3 years ago

I have published v2.1 and upload it to luarocks.

laelnasan commented 3 years ago

So... reading through the src files of pdcurses I found out it was only missing a definition to support ncurses' mouse API. I've committed a single line that theoretically would solve it. I still don't have a windows machine set up, so if you would kindly do the testing it would be awesome. Sorry for the delay, I just didn't have the time till now.

waruqi commented 3 years ago

ok, I will test it.

laelnasan commented 3 years ago

Hi, me again After some work I finally got the mouse working with all view objects (AFAIK) and tests Since this is an optional feature I thought it would be fit to present it with a customization system. The ideia is to fool the Lua's loading system by placing a ltui.lua file in a higher priority directory as, for example, the directory where the tests are called. It may also be nice for newcomers (like me) to have an example on how to customize the package to attend individual needs.

https://gist.github.com/laelnasan/92129fecd1e231c6492cd3babd3a0f29

waruqi commented 3 years ago

Great! 👍

Can you help submit pr to directly modify these views of ltui instead of customizing the views.

We can add options.mouseable = true/false to the init() function of each view to selectively enable the mouse feature.

laelnasan commented 3 years ago

That would be a bit of a grind, because every call to an init() of a child of panel would have to be changed, specially the instantiation of the objects inside dialogs would have to be conditioned to the property. In the solution I presented, I change the behaviour of the classes at loading time so that all children inherit the changes automatically. Not saying it cant be done, but I can't see an easy way to do it

laelnasan commented 3 years ago

I think I may have found a workaround... I just don't know if it fits the coding style: to use a metatable to dynamically load the ltui/* modules and set a global ltui.options

Then one could write something like:

local ltui = require('ltui')
ltui.options = {mouseable = true}

local app   = ltui.application
local label = ltui.label
...
waruqi commented 3 years ago

ltui.options = {mouseable = true}

like this:

https://github.com/tboox/ltui/blob/987b002e0d28a6c3cf5aea63883a63f09d7ef0d5/src/ltui/textarea.lua#L37-L41

laelnasan commented 3 years ago

yes, but that is a option of the instantiated object, right? not the class per se. and how do we identify when the entire application is mouseable or not?

laelnasan commented 3 years ago

ow, I think I get it now

waruqi commented 3 years ago

yes, but that is a option of the instantiated object, right? not the class per se. and how do we identify when the entire application is mouseable or not?

Each view component should allow the user to control whether it can enable the mouse if this view support mouse.

laelnasan commented 3 years ago

but if the default behaviour doesn't take a global property then the user must modify every single object instantiated to get it working, is that it? I am not trying to convince you, just making sure I understand the idea.

waruqi commented 3 years ago

but if the default behaviour doesn't take a global property then the user must modify every single object instantiated to get it working, is that it? I am not trying to convince you, just making sure I understand the idea.

We can also use application:option_set() and view:application():option() to set/get global default option to all sub-views.