Any GTK wizard out there who knows how to control a scrollbar?
PostedI have started a little project which requires a graphical interface, and I'm using GTK3 to do so.
One thing I need is to have a scrollbar. Nothing fancy here?, one would think.
And one would be right, after all there is a GtkScrollbar
widget that's just
what you'd think it is (if you thought it implemented a scrollbar that is...).
But because I'm picky or something, I wanted my scrollbar to have, say, values from 1 to 10, or 7 with a page size of 3. And, most importantly, I want possible values to only be integers. So 1, 2, 3, and so on up to 7. But no 1.2 or whatever.
Sounds simple?
Well, it should be, yes. There is a gtk_range_set_round_digits
() function
that's pretty much here for that: say you want 0 digits and it'll round up to a
full integer. Isn't life wonderful?
Debbie downer enters the room...
...so of course I'm gonna find a way to complain, I guess, because what would be the point of this post otherwise.
See, I know these days (in GTK) scrollbars don't really have steppers - aka those little arrow buttons you find on each end of a scrollbar - anymore, but a) I might like them, and b) I started working on an old GTK3 (circa 3.18) and they were still very much a thing. (On an unrelated topic, it probably might not be a bad idea if I updated a few things, like my GTK dev installation. But hey, that's for another day. Or Month. Or...)
Back on topic: I wanted those little things (to work), or a right-click on the scrollbar, which pretty much does the same thing I believe, and the thing is that, as per what I've described so far, it does not.
Steppers are a thing. That can work. That should work, no?
It doesn't work, because a click on a stepper will generate a bunch of value changes, but those are all very much not integers, so 1.0500 or similar. Of course they get nicely rounded up, but they all get rounded up the same thing, to 1, that is. Aka to the current value already, resulting in... nothing.
So the user clicks to scroll, and then... no scrolling happens. Which - call me crazy - seems a bit not what you'd expect. Sadly, I haven't seen a way to simply fix this.
Wizard wanted
Hence this quest for a GTK wizard that might give a, hopefully simple, answer to this little problem.
Because so far here's what I've come up with, and it is, say... not really satisfying. I mean, it kinda gives the wanted effect, I believe, but.
What I'm currently doing is this: forget about the whole
gtk_range_set_round_digits
(), connect to the change-value
signal and do it
yourself, with an added hack :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cstatic gboolean
sb_changed(GtkRange *range, GtkScrollType scroll, gdouble val, struct ctx *ctx)
{
gdouble oval, fval;
oval = gtk_range_get_value(range);
fval = floor(val + 0.5);
if ((ctx->last[0] && ctx->last[1] && ctx->last[0] == ctx->last[1] && val == ctx->last[0])
&& oval == fval) {
if (val > fval)
fval = oval + 1;
else
fval = oval - 1;
ctx->last[1] = fval;
} else {
ctx->last[0] = ctx->last[1];
ctx->last[1] = val;
}
gtk_range_set_value(range, fval);
return TRUE;
}
That's the usual rounding up, but also we keep track of the last 2 values that were set, and if they happen to be the same as the new one we just got, and if such value does round up to the same as the current value, we're assuming that's one stepper calling for a change, so we answer its prayers.
This looks like it works because usually a stepper click results in the same value being set a few times(*), whereas a drag of the scrollbar pretty much guarantees changing values each time.
(*) Those steppers might look like buttons, but they're not, really. It seems GTK notices the button press, starts emitting signals until the button release, or something to that effect. Point is, this doesn't register as a single event, but a few. The more you stay pressed the more signals are emitted, though all with the same value, since it doesn't change (due to the rounding up). So you could stay pressed forever and it still wouldn't move your scrollbar a bit.
Note of Type
For a moment there I thought, "hey, there's a GtkScrollType
argument, that
might be just the answer we're looking for!"
Because if there had been something like a GTK_SCROLL_STEP_DOWN
or similar, it
would've been an easy answer. But alas, they all come up as GTK_SCROLL_JUMP
and thus aren't helpful at all.
Unless, again, I'm missing something (obvious) here? If I am, and even if I'm not but you do have a better answer, please let me know.
And in case you want to play with this and try it for yourself, the full example code is available for online browsing or git cloning, depending how you feel today.