Made scrollbars more accurate.

- Used unicode characters to have fractional lengthed bars.
- Don't allow specifing a scrollbar character anymore. You
  can give the bar's color and background color.
This commit is contained in:
Andrew Hamilton 2018-07-17 08:58:29 +10:00
parent 3a62a2a0d7
commit 07ffb403f5
2 changed files with 67 additions and 27 deletions

View file

@ -7,6 +7,7 @@
import unittest
import vigil.fill3 as fill3
import vigil.termstr as termstr
class WidgetTests(unittest.TestCase):
@ -70,30 +71,43 @@ class WidgetTests(unittest.TestCase):
placeholder.widget = self.TEXT_B
self.assert_string(placeholder.appearance_min(), "B")
def assert_string2(self, appearance, expected_string):
self.assertEqual(
("\n".join(line.data for line in appearance),
"".join("i" if style.fg_color==termstr.Color.black else " "
for line in appearance for style in line.style)),
expected_string)
def test_scroll_bar(self):
scroll_bar = fill3.ScrollBar(is_horizontal=True, bar_char="#")
scroll_bar = fill3.ScrollBar(is_horizontal=True)
self.assertEqual(scroll_bar.interval, (0, 0))
self.assert_string(scroll_bar.appearance((1, 1)), "#")
self.assert_string2(scroll_bar.appearance((1, 1)), (" ", "i"))
scroll_bar.interval = (0, 0.5)
self.assert_string(scroll_bar.appearance((2, 1)), "# ")
self.assert_string2(scroll_bar.appearance((2, 1)), (" ", "i "))
scroll_bar.interval = (0, 0.1)
self.assert_string(scroll_bar.appearance((2, 1)), "# ")
self.assert_string2(scroll_bar.appearance((2, 1)), (" ", "i "))
scroll_bar.interval = (0.25, 0.75)
self.assert_string(scroll_bar.appearance((4, 1)), " ## ")
scroll_bar = fill3.ScrollBar(is_horizontal=False, bar_char="#")
self.assert_string2(scroll_bar.appearance((4, 1)), ("", " i "))
scroll_bar.interval = (0, 0.75)
self.assert_string2(scroll_bar.appearance((2, 1)), ("", "i "))
scroll_bar = fill3.ScrollBar(is_horizontal=False)
self.assertEqual(scroll_bar.interval, (0, 0))
self.assert_string(scroll_bar.appearance((1, 1)), "#")
self.assert_string2(scroll_bar.appearance((1, 1)), ("", " "))
scroll_bar.interval = (0, 0.5)
self.assert_string(scroll_bar.appearance((1, 2)), "#\n"
" ")
self.assert_string2(scroll_bar.appearance((1, 2)), ("\n"
"", " i"))
scroll_bar.interval = (0, 0.1)
self.assert_string(scroll_bar.appearance((1, 2)), "#\n"
" ")
self.assert_string2(scroll_bar.appearance((1, 2)), ("\n"
"", " i"))
scroll_bar.interval = (0.25, 0.75)
self.assert_string(scroll_bar.appearance((1, 4)), " \n"
"#\n"
"#\n"
" ")
self.assert_string2(scroll_bar.appearance((1, 4)), (" \n"
"\n"
"\n"
"", " i"))
scroll_bar.interval = (0, 0.75)
self.assert_string2(scroll_bar.appearance((1, 2)), ("\n"
"", " i"))
def test_table_widget(self):
table = fill3.Table([])

View file

@ -179,15 +179,30 @@ class Filler:
class ScrollBar:
_GREY_BACKGROUND_STYLE = termstr.CharStyle(bg_color=termstr.Color.grey_100)
_GREY_BLOCK = termstr.TermStr(" ", _GREY_BACKGROUND_STYLE)
_HORIZONTAL_CHARS = [" ", "", "", "", "", "", "", ""]
_VERTICAL_CHARS = ["", "", "", "", "", "", "", ""]
def __init__(self, is_horizontal, interval=(0, 0), bar_char=_GREY_BLOCK,
background_char=" "):
def __init__(self, is_horizontal, interval=(0, 0),
bar_color=termstr.Color.grey_100,
background_color=termstr.Color.black):
self._is_horizontal = is_horizontal
self.interval = interval
self.bar_char = bar_char
self.background_char = background_char
self.bar_color = bar_color
self.background_color = background_color
self.bar_char = termstr.TermStr("").fg_color(bar_color)
self.background_char = termstr.TermStr(" ").bg_color(background_color)
self.start_h_chars = [termstr.TermStr(char).fg_color(
self.background_color).bg_color(self.bar_color)
for char in self._HORIZONTAL_CHARS]
self.end_h_chars = [termstr.TermStr(char).fg_color(
self.bar_color).bg_color(self.background_color)
for char in self._HORIZONTAL_CHARS]
self.start_v_chars = [termstr.TermStr(char).fg_color(
self.bar_color).bg_color(self.background_color)
for char in self._VERTICAL_CHARS]
self.end_v_chars = [termstr.TermStr(char).fg_color(
self.background_color).bg_color(self.bar_color)
for char in self._VERTICAL_CHARS]
def appearance(self, dimensions):
width, height = dimensions
@ -195,13 +210,24 @@ class ScrollBar:
length = width if self._is_horizontal else height
assert all(0 <= fraction <= 1 for fraction in self.interval), \
self.interval
start_index, end_index = [int(fraction * length)
for fraction in self.interval]
if start_index == end_index and end_index < length:
end_index += 1
(start_index, start_remainder), (end_index, end_remainder) = \
[divmod(fraction * length * 8, 8) for fraction in self.interval]
start_index, end_index = int(start_index), int(end_index)
start_remainder, end_remainder = \
int(start_remainder), int(end_remainder)
if start_index == end_index:
end_index, end_remainder = start_index + 1, start_remainder
elif end_index == start_index + 1:
end_remainder = max(start_remainder, end_remainder)
start_chars, end_chars = ((self.start_h_chars, self.end_h_chars)
if self._is_horizontal
else (self.start_v_chars, self.end_v_chars))
bar = (self.background_char * start_index +
self.bar_char * (end_index - start_index) +
self.background_char * (length - end_index))
start_chars[start_remainder] +
self.bar_char * (end_index - start_index - 1) +
end_chars[end_remainder] +
self.background_char * (length - end_index - 1))
bar = bar[:length]
return [bar] if self._is_horizontal else [char for char in bar]