[haiku-development] Re: Glass Elevator proposal: templated BControl

  • From: John Scipione <jscipione@xxxxxxxxx>
  • To: "haiku-development@xxxxxxxxxxxxx" <haiku-development@xxxxxxxxxxxxx>
  • Date: Wed, 11 Jul 2018 11:51:40 -0700

On Tue, Jul 10, 2018 at 3:04 PM, waddlesplash <waddlesplash@xxxxxxxxx> wrote:

The point of templated classes is to abstract functionality that does not
depend very strongly on type, but rather is some sort of structure that will
be reused across types, e.g. lists. In this case, however, unless I am
mistaken the only things in "common" are getter/setter functions, which here
take an int32.

Aren't templated classes used in a lot of different contexts?
Basically any time you want to make the type used by a class generic?
What you're describing sounds a lot like BObjectList which is kind of
along the same lines making a BList be able to use an abstract type as
BTypedControl would do to BControl.

So perhaps the better question to ask is "why should BControl know anything
about the type of data it's working with?" Then we would remove
SetValue/Value from the base class and move it just to subclasses. After
all, the vast majority (if not actually all?) users of BControl will be
calling the base class method anyway, and I don't know what value the
current system has in this abstraction.

See Pulkomandy's response and
https://www.haiku-os.org/legacy-docs/bebook/BControl_Overview.html
BControl having a value is one of its defining characteristics. Maybe
BControl is over-specified?

This is what Qt does at least, and I imagine most other toolkits behave
similarly. We are of course free to be different, but I think we should only
be so when it makes sense to; and I don't see that here.

I followed Qt's lead when making AbstractSpinner (See QAbstractButton)
and was told that that was not the right design paradigm. So maybe
following Qt's lead is not a good way to go. I also point out some of
the some flaws to this approach in my response to Stippi below.

On Tue, Jul 10, 2018, 11:44 PM Adrien Destugues <pulkomandy@xxxxxxxxx> wrote:
Having a value is the only thing that BControl brings over a standard BView. 
If your control does not fit this pattern, then don't make it a BControl.

Thank you for this, I looked for a good explanation of the BeBook but
couldn't find one. BControl has a Value as part of its definition.

A template would defeat the purpose of the class, which is that you know how 
to access the value, no matter what kind of control (even custom ones) you 
are dealing with. This is useful for example in making the value available to 
hey scripting.

You can have any type that you want, as long as it's int32.

If you really want a generic type, you would need something QVariant-like, 
most probably a BMessage with a "value" field which could be of any type. But 
this makes manipulating the value a lot more inconvenient.

Keep it focused on BColorControl. I want to send an rgb_color from its
Value() method, if you're looking at the value of a BColorControl then
the caller should be able to infer the type of the Value it is asking
for. If you are asking a BColorControl what its value is, the caller
you should expect an rgb_color not an int32. I'm not sure how this
could be handled in hey though... good food for thought.

Since we are talking about R2 changes and ABI breakage anyways, I think such 
small changes are not a good way to proceed, R2 is one rare occasion where we 
can review the API as a whole and change a lot of things, so we need to take 
a more high level view on how we want it to work. This means a careful review 
of why each class exists, what it was meant to provide, how it ended up being 
actually used, and only then, how could we make it either simpler or more 
flexible (or both, ideally ;))

One of many small changes will become a big change. I'd also like to
rework a lot of IK class constructors to have as few params as
possible. You should be able to make a new BButtton() and then fill in
the pieces afterwords without having to look in the documentation to
figure out what the constructor parameters are for BButton. We really
should nail down these details sooner or later or Haiku is gonna
suffer from some serious second syndrome effect.

On Wed, Jul 11, 2018 at 4:50 AM, Stephan Aßmus <superstippi@xxxxxx> wrote:
The design goal of the API should be to make it easy for developers to write
correctly behaving applications and to minimize the code necessary to wire
everything together. I think the Be API isn't perfect in this regard.
So whether or not we need BTypedControl... What common problem does it
? solve? Would there be a much better way to solve it? IMHO, the Interface Kit
tries to make it easy to process UI events in other threads, but they have to 
be
BLoopers if you want to minimize the necessary code. What I think is missing
is a notion to separate UI from data and to bind the two together, possibly 
in an
automated fashion. I don't yet see how BTypedControl helps much with that.

The problem BTypedControl trying to solve is to enable the app
developer to make a BControl subclass but that has a value type other
than int32. Some existing examples where this would be useful are
BColorControl and BDecimalSpinner, neither of which particularly wants
to take an int32 value. My choices are to inherit from BView and
BInvoker and the reimplement the parts of BControl that I need (e.g.
IsEnabled()), or to work around the problematic int32 value methods.
I've implemented the former while shaking my head and I've also
implemented the latter approach with mixed results.

It seems like what has been suggested to solve this problem is to add
another layer of abstraction outside the BControl class for storing
the value inside of a class member possibly using a BMessage as a way
to make the value type generic. I could see that but it seems less
straightforward than using a template class and you lose the ability
to define Value() and SetValue() methods in the BControl class without
having to reach into the subclass. You'd have to use const void*
pointers to pass back the data without knowing it's type and expect
the caller (the BTypedControl subclass I guess) to cast the pointer
back to the appropriate type. However, perhaps this could all be
worked around inside the class without having to expose too many of
the details to the subclass implementer.

Other related posts: