peterbrittain / asciimatics

A cross platform package to do curses-like operations, plus higher level APIs and widgets to create text UIs and ASCII art animations

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

スクリーンショット 2023-07-06 12 49 32

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