Implementing Widget's Custom Color Palettes
kyoto7250 opened this issue · comments
Is your feature request related to a problem? Please describe.
When I try to change the color of the header of the MultiColumnListBox, but this behavior also changes the color of the title
of the border.
Describe the solution you'd like
I want to be able to pass a color palette to the Widget itself, and have access to a default if the desired color palette doesn't exist in the Widget.
Describe alternatives you've considered
If I create a custom widget, the problem will be solved, but I think it's better to have it as a default feature.
related:
#208
Additional context
My current understanding is that by doing register_frame
on the Frame, the Widget is associated with the Frame, so I think it's difficult to change the custom color of only specific Widgets now.
minimal reproduction
from asciimatics.widgets import (
Frame,
Layout,
MultiColumnListBox,
Widget,
)
from asciimatics.scene import Scene
from asciimatics.screen import Screen
class DemoFrame(Frame):
def __init__(self, screen) -> None:
super(DemoFrame, self).__init__(
screen,
10,
80,
has_border=True,
can_scroll=False,
title="TITLE",
)
layout = Layout([50, 50], fill_frame=True)
mc_list = MultiColumnListBox(
Widget.FILL_FRAME,
[10, 10],
[(["1", "2"], 1)],
titles=["A", "B"],
)
self.add_layout(layout)
layout.add_widget(mc_list)
# changed the color
mc_list._frame.palette["title"] = (
Screen.COLOUR_BLACK,
Screen.A_NORMAL,
Screen.COLOUR_WHITE,
)
self.fix()
def demo(screen) -> None:
screen.play([Scene([DemoFrame(screen)], -1, name="title")])
Screen.wrapper(demo, catch_interrupt=False)
screenshot
execution environment (for the future)
- asciimatics: 1.14.0
- OS: macOS 13.4.1
Hi. The point of the colour palette was to ensure that there is a consistent colour scheme for each Frame to make it clear when things are selected/disabled/etc, so I'd rather not start extending that to be a per-widget concept if possible.
Overrides are available via the custom_colour
property or (for some widgets like MultiColumnListBox) via a parser. They're not quite right here because:
- the custom colour is for the whole widget
- the parser only applies to the contents.
But that does show a possible path forwards... Would it work for you if you could use the parser to set custom colours in the title?
This should allow you to test it out (but is missing error handling, so is not the final patch)...
diff --git a/asciimatics/widgets/baselistbox.py b/asciimatics/widgets/baselistbox.py
index 58b932f..2c681fe 100644
--- a/asciimatics/widgets/baselistbox.py
+++ b/asciimatics/widgets/baselistbox.py
@@ -10,6 +10,7 @@ from abc import ABCMeta, abstractmethod, abstractproperty
from future.utils import with_metaclass
from asciimatics.event import KeyboardEvent, MouseEvent
from asciimatics.screen import Screen
+from asciimatics.strings import ColouredText
from asciimatics.widgets.widget import Widget
from asciimatics.widgets.scrollbar import _ScrollBar
@@ -36,7 +37,7 @@ class _BaseListBox(with_metaclass(ABCMeta, Widget)):
:param validator: Optional function to validate selection for this widget.
"""
super(_BaseListBox, self).__init__(name)
- self._titles = titles
+ self._titles = [ColouredText(x, parser) for x in titles]
self._label = label
self._parser = parser
self._options = self._parse_options(options)
Sorry my late reply.
I'd rather not start extending that to be a per-widget concept if possible.
I got it.
Would it work for you if you could use the parser to set custom colours in the title?
I didn't know about a class called ColoredText. Thank you for teaching me.
I will check it 👍🏽
Should now work with 48025bc