LevelBar not working correctly when set to discrete mode
When creating a discrete level bar, the expectation is that if I = [x-1, x] is an interval for an integer x, if the value of the level bar is in I, then either the x-th or (x-1)-th segment of the bar should be colored.
e.g. with 0 < x < 1 the first segment should be colored (or none on the second convention).
In the following photo there is are four level bars with max_value = 2
with values 0.1, 0.5, 1.1, 1.5
In this case the first segment appears colored in the range [0.5, 1.5). The expected should be one of
For an arbitrary max_value the behavior is the same as in the example, with segments being colored in intervals of the form (x+0.5, x+ 1.5] rather than (x, x+1].
The natural application for this is the use of css classes for different offsets, but as it is, the css class changes when the value is over offset
while the correct segment is colored while the value is over offset + 0.5
. This can be seen in the third picture, where same number of bars can have different css classes.
Bonus issue
From the docs
Use gtk_level_bar_set_value() to set the current value, and gtk_level_bar_add_offset_value() to set the value offsets at which the bar will be considered in a different state. GTK will add a few offsets by default on the level bar: GTK_LEVEL_BAR_OFFSET_LOW, GTK_LEVEL_BAR_OFFSET_HIGH and GTK_LEVEL_BAR_OFFSET_FULL, with values 0.25, 0.75 and 1.0 respectively.
When using discrete mode, these classes should not be automatically set as the range is not [0, 1] anymore and different classes, if any, should use integer offsets.
Reproducer
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk
def on_activate(app):
window = Gtk.ApplicationWindow(application=app)
box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 6)
for x in [0.1, 0.5 , 1.1, 1.5]:
level = Gtk.LevelBar()
level.props.mode = Gtk.LevelBarMode.DISCRETE
level.props.max_value = 2.0
level.props.value = x
box.append(level)
window.set_child(box)
window.show()
app = Gtk.Application()
app.connect("activate", on_activate)
app.run()