Enhance: get and set state of push-down-buttons (button love part1) #5227
Conversation
…art 1)
Provide a means to get and set the state of push down buttons (the latter
without executing the associate command or script). It requires adding
members to the `TAction` class to keep track of the `EAction` or
`TFlipButton` instance that is the implimentation of the button on a
`TEasyButton` or `TToolBar` respectively. As it happens this showed that
the previous code to regenerate them was creating new buttons each time but
was not deleting the existing ones that were getting replaced.
Also:
* made some members of the `TAtion` class (the name, script and both
commands) private as otherwise there is no point in the setters and getters
also provided!
* simpliedied the existing `getButtonState()` {that only works within the
script for a button) to remove an unneeded intermediate local (`int`)
value.
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
The original comment was wrong as well - using a `Q_ASSERT_X` would have broken things for a floatable/dockable toolbar type button (what `TAction::mpFButton` will point at)...! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
|
Hey there! Thanks for helping Mudlet improve. 🌟 Test versionsYou can directly test the changes here:
No need to install anything - just unzip and run. |
|
clang-tidy review says "All clean, LGTM! 👍" |
Note that for the getter this is an intermediate stage as is should be possibble to combine it with the existing `getButtonState()` function that takes NO arguments but only works within the Lua script for a push-down button. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
This simpilifies the UI so that `getButtonState()` works the same as before but if an button's ID number or "name" is supplied as an argument the state of the corresponding button (as a boolean though, NOT the existing and, TBH, odd, integer value 1 or 2, that the original function produces) is returned. In the event that the matching item is NOT a push-down button, or that it does not match an existing button then a 'nil' + (run-time) error message is returned instead. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
keneanung
left a comment
There was a problem hiding this comment.
One suggestion for me, but otherwise I like this.
src/TLuaInterpreter.cpp
Outdated
| auto argType = lua_type(L, 1); | ||
| TAction* pItem = nullptr; | ||
| if (argType == LUA_TNUMBER) { | ||
| int id = lua_tonumber(L, 1); | ||
| if (id < 0) { | ||
| return warnArgumentValue(L, __func__, QStringLiteral("item Id (%1) invalid, it must be equal or greater than zero").arg(id).toUtf8().constData()); | ||
| } | ||
| pItem = host.getActionUnit()->getAction(id); | ||
| if (!pItem) { | ||
| return warnArgumentValue(L, __func__, QStringLiteral("no button item with Id %1 found").arg(id).toUtf8().constData()); | ||
| } | ||
| if (!pItem->isPushDownButton()) { | ||
| return warnArgumentValue(L, __func__, QStringLiteral("item Id with %1 is not a push-down button").arg(id).toUtf8().constData()); | ||
| } | ||
| } | ||
|
|
||
| if (argType == LUA_TSTRING) { | ||
| QString name = lua_tostring(L, 1); | ||
| if (name.isEmpty()) { | ||
| return warnArgumentValue(L, __func__, "item name must not be an empty string"); | ||
| } | ||
| pItem = host.getActionUnit()->findAction(name); | ||
| if (!pItem) { | ||
| return warnArgumentValue(L, __func__, QStringLiteral("no button item with name '%1' found").arg(name).toUtf8().constData()); | ||
| } | ||
| if (!pItem->isPushDownButton()) { | ||
| return warnArgumentValue(L, __func__, QStringLiteral("item with name '%1' is not a push-down button").arg(name).toUtf8().constData()); | ||
| } | ||
| } |
There was a problem hiding this comment.
This whole part seems to be pretty much the same as in the set function. I would suggest putting this into a function that's used by both.
There was a problem hiding this comment.
TBH if the code was to be used in more than these two cases I'd go along with that idea but the additional complexity of a further function call for just this pair means I think it is a borderline decision and I'd prefer not to do that currently...
There was a problem hiding this comment.
🤔
In the medium term I'd like to have a set of introspection (?) functions that can get, and for some set, the common elements of all the mudlet item types (alias, button/menu/toolbars, keybindings, scripts, timers, triggers) i.e. "name", "command", "ID", "active" {based on both it's own and its ancestors' state} and possibly some further details... as such it may then be useful to factor out item identification based on EITHER a numeric ID OR a string name basis. At that point this would be useful to revisit.
There was a problem hiding this comment.
To me, this is not a borderline decision. It has strings and quite a bit of logic that should stay the same. And the easiest way for that is adding a function.
There was a problem hiding this comment.
- setButtonState is missing in Area 51
set the state of push down buttons (without executing the associate command or script).
Is that really always desired? Maybe a toggle would make sense. Not sure if this should even be default. Then again, I hardly used buttons myself.
src/TLuaInterpreter.cpp
Outdated
| return warnArgumentValue(L, __func__, QStringLiteral("no button item with Id %1 found").arg(id).toUtf8().constData()); | ||
| } | ||
| if (!pItem->isPushDownButton()) { | ||
| return warnArgumentValue(L, __func__, QStringLiteral("item Id with %1 is not a push-down button").arg(id).toUtf8().constData()); |
There was a problem hiding this comment.
| return warnArgumentValue(L, __func__, QStringLiteral("item Id with %1 is not a push-down button").arg(id).toUtf8().constData()); | |
| return warnArgumentValue(L, __func__, QStringLiteral("item with Id %1 is not a push-down button").arg(id).toUtf8().constData()); |
we discussed earlier if we go for "id" or "Id" or "ID" and can't remember the consensus reached.. but I feel like "Id" is the worst of those
There was a problem hiding this comment.
Um, one reference might be: #2605 - and it has not been closed...
Tomayto, Tomaahtoe ....
There was a problem hiding this comment.
Ah, I'll revise it to ID and hope that'll silence the critics... 🤞
src/TLuaInterpreter.cpp
Outdated
|
|
||
| if (!pItem) { | ||
| // we'll get here if the (first) argument is NOT usable: | ||
| lua_pushfstring(L, "%s: bad argument #1 type (ID as number or name as string expected, got %s!)", |
There was a problem hiding this comment.
See there is an "ID", let's use that consistently, shall we?
There was a problem hiding this comment.
Okay, in the scheme of things I can't be arsedbothered to fight this...
When configuring a UI that uses buttons/menus/toolbars it is pretty much essential to be able to set the state of push-down buttons to a required initial or to reflect something that is happening in-game independently of whatever script/command is associated with that button. A bit of refactoring to make the Lua script a simple function call to a script defined elsewhere (in a script element I guess) would be enough to reproduce clicking the button whereas only providing a function to simulate toggling the button state AND executing the script / send the command is actually a much less flexible way of doing things - and would not give the same scope for usage that the setter function herein gives... |
As suggested by peer-review. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
…e(...) This was strongly requested by @keneanung though my preference was against it for just two instances - as developing an API that would work with the `warnArgumentValue(...)` function took a bit of thought and I had to work with handling a `TAction**` (pointer to a pointer to a `TAction`) as a function argument! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
keneanung
left a comment
There was a problem hiding this comment.
Thank you very much for the rework 😄 I have a niggle that I'd love to see a change for. But it won't break my heart if you're adamant here 😉
src/TLuaInterpreter.cpp
Outdated
| // it also resets the pItem to be a nullptr | ||
| // does NOT return (normally) if the index item on the stack is not a number or | ||
| // a string | ||
| int TLuaInterpreter::getTActionFromIdOrName(lua_State* L, TAction** pItem, const int index, const char* func) |
There was a problem hiding this comment.
I know this isn't atypical for C++, but I prefer using function arguments as input instead of output. This is also mentioned in Clean Code. Have you considered returning multiple values via https://www.geeksforgeeks.org/returning-multiple-values-from-a-function-using-tuple-and-pair-in-c/?
There was a problem hiding this comment.
Agree - and we have many examples of this, check for example:
std::pair<bool, QString> changeModuleSync(const QString& enableModuleName, const QLatin1String &value);
std::pair<bool, QString> getModuleSync(const QString& moduleName);Make it a std::pair with the original return value of `TLuaInterpreter::getTActionFromIdOrName(...)` instead of passing it as a non-const reference argument. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
vadi2
left a comment
There was a problem hiding this comment.
Thanks for adding this requested feature in!
|
📚 documentation done, see:
|
|
Looks good! But it should be in Area 51 as it's not available yet. People naturally get confused when we list releases in docs that aren't out yet |
|
Please honor Area 51 template, e.g. don't hide version info below example section |
Ah, I was thinking that it being in the PTB would be justification for it making it into the main documentation.
🤔 I was trying to avoid contaminating the auto-completion Anyhow I have now relocated them, in the meantime, to Area 51 and perhaps someone else could reshape the items so as to fit better... |
someone else did |
published again for upcoming release |
Brief overview of PR changes/additions
Provide a means to get and set the state of push down buttons (the latter without executing the associate command or script). It requires adding members to the
TActionclass to keep track of theEActionorTFlipButtoninstance that is the implementation of the button on aTEasyButtonorTToolBarrespectively. As it happens this showed that the previous code to regenerate them was creating new buttons each time but was not deleting the existing ones that were getting replaced.Also:
TAtionclass (the name, script and both commands) private as otherwise there is no point in the setters and getters also provided!getButtonState(){that only works within the script for a button) to remove an unneeded intermediate local (int) value.Signed-off-by: Stephen Lyons slysven@virginmedia.com
Motivation for adding to Mudlet
It is something has been requested in the past (I think recently on Discord).
Other info (issues closed, discussion etc)
Further improvements to buttons/menus/toolbars are desirable and I can foresee some of them.
Release post highlight
Allow Lua scripts to get the state of click-down (toggle-able) buttons outside of the script for said button and allow for them to also set that state.