On Tuesday, May 30, 2017 at 5:35:43 PM UTC-4, Mr Flibble wrote:
> On 30/05/2017 22:07, Rick C. Hodgin wrote:
> > On Tuesday, May 30, 2017 at 12:36:04 PM UTC-4, Mr Flibble wrote:
> >> Handling a button clicked event in my C++ GUI library "neoGFX" is:
> >> button1.clicked([](){ /* do stuff */}); // simplicity
> >
> > What about parameters passed to the clicked() event? I might want
> > to know if it was left-clicked, right-clicked, middle-clicked, or
> > left-and-right clicked, left-and-middle-clicked, double-clicked,
> > double-right-clicked, etc. And what about the condition of the
> > modification keys like shift, alt, ctrl? Do you have thread-
> > level callbacks which support real-time sampling of those values?
>
> Such information is available allowing such events to be easily created.
I would think it would be the norm. One API with the extraneous info
being ignored if not used, rather than two or more APIs, one for the
"simple stuff" and one for the "regular stuff."
I'm not being picky or purposefully mean to you, Leigh. I honestly
do not see the advantage.
> Left clicking a button is a common use-case whilst right clicking a
> button is a rare use-case. I provide ready baked events for common
> use-cases whilst allowing the flexibility to create events for rare
> use-cases.
That's not true. It is in many use cases, but in those use cases
where right-clicking is common / standard, it's not at all true.
You're creating a true graphical UI. You have to expect people
will be coding for right-clicks on most everything, so as to
access settings about things they're clicking on, rather than a
type of normal navigation or selection.
> > What if the code on my clicked() event has to access a remote
> > Internet connection and it takes 5 seconds to establish a
> > connection, will the values of shift, ctrl, alt still be held
> > for me to examine if I poll them at some later point in my
> > algorithm after many seconds have gone by?
>
> Then you are doing it wrong. A library doesn't have to support doing it
> wrong use cases.
Well, I don't generally code like that. Sometimes you have to
because you receive OS callbacks without that information, but I
mention it here because I didn't see any parameters being passed
to your simplicity version above, hence the need for such functions
in such a case.
I think if you want simplicity, you should just receive a struct
or class that has defined callback functions, and then use those
if they're not NULL. Something simple:
struct SEvents {
bool (*onLeftClick)(SObject* state);
bool (*onRightClick)(SObject* state);
// ... and other such stuff
};
I think neoGrx could prepare a snapshot data object, or pass several
parameters, and have everything setup for the instance handoff, which
may then be propagated through for a while before control returns
from the dispatcher. In fact, you could even setup a dispatcher
which launches each event in its own thread as a nice service that
would prevent the user from having to write that code.
> > And what about code grouping? Am I now having to sift through
> > my GUI init() code to find all of the algorithms which handle
> > the various events? I don't have them arranged in a header or
> > class structure which can use traditional IDE tools to goto
> > body / definition? Now I'm going to a single init() event and
> > manually searching page after page for code, or using only a
> > ctrl+f Find feature of my editor?
>
> You appear to have a beef with C++ lambdas which is foolish as they are
> a great improvement to the language. You are not forced to use a lambda
> as you can use use anything convertible to a std::function object.
I do have a beef with lambdas. I've created an alternative which
better documents what's taking place by giving it a name, and allowing
it to be moved away from the syntax of the instruction in use.
I call it an adhoc, which is arbitrary code created at any point, and
it is not normally entered through normal flow, but only when explicitly
called by name or by address:
Search for "adhoc" on this message:
https://groups.google.com/d/msg/caliveprogramminglanguage/pSV7rzGcIeE/Ix3pBmhsBgAJ
Its syntax is basically like a type of local function, but by
creating it as a adhoc, it is documented in code for its explicit
use case:
int main(int argc, char* argv[])
{
// Create a function to reference which is related to this
// code immediately nearby.
adhoc int my_adhoc(int a, int b) {
return(a + b + 9);
}
cout << "5,6 equals " << my_adhoc(5, 6);
return 0;
}
CAlive also allows alternate syntax to create the same thing,
which can appear to be more similar to lambdas, and can be
encoded where lambdas are.
> > It might be simple, but unless it provides some real utility in
> > function and the development environment, then such simplicity
> > is akin to useless.
>
> It is both simple and provides utility.
As Einstein once said: "Things should be as simple as possible,
but no simpler." I think you've tried to make things simple, but
you're missed out on the fact that more is required for normal
events processing than your simple model, meaning the model is
now doubly complex because you have simple things and normal
things. I think it will be more confusing to users.