From 2b4f1f553c6205cde391be68c510b744eda5b610 Mon Sep 17 00:00:00 2001 From: Spencer Brown Date: Mon, 12 Aug 2024 17:58:05 +1000 Subject: [PATCH] Create fake radio button for selectorwin menus --- src/ui_wx/__init__.py | 18 +++++++++++++++++- src/ui_wx/selector_win.py | 6 ++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/ui_wx/__init__.py b/src/ui_wx/__init__.py index aada9b1b..06689177 100644 --- a/src/ui_wx/__init__.py +++ b/src/ui_wx/__init__.py @@ -1,6 +1,6 @@ """This package contains UI code specific to WxWidgets.""" from __future__ import annotations -from typing import Literal +from typing import Final, Literal from collections.abc import Callable import logging @@ -118,3 +118,19 @@ def _join(self, children: list[str]) -> str: PEN_SLOT_BORDER = wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWFRAME), 3) PEN_SLOT_BORDER_SEL = wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT), 3) + + +def _make_radio_icon() -> wx.Bitmap: + """Generate a bitmap which makes check-style menus look like radio menus.""" + from PIL import Image, ImageDraw + fill = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUTEXT) + # Draw oversize then scale down to get some antialiasing. + img = Image.new('RGBA', (64, 64)) + draw = ImageDraw.Draw(img) + draw.ellipse([20, 20, 40, 40], (fill.red, fill.green, fill.blue, fill.alpha)) + return wx.Bitmap.FromBufferRGBA(16, 16, img.resize((16, 16)).tobytes()) + + +# TODO: Can't change the button design on other platforms, unfortunately. +# They only allow a single icon for both checked/unchecked. +RADIO_MENU_BITMAP: Final = _make_radio_icon() if utils.WIN else wx.NullBitmap diff --git a/src/ui_wx/selector_win.py b/src/ui_wx/selector_win.py index e0931e0e..74939e8c 100644 --- a/src/ui_wx/selector_win.py +++ b/src/ui_wx/selector_win.py @@ -21,7 +21,7 @@ from consts import SEL_ICON_SIZE from packages import AttrTypes from transtoken import CURRENT_LANG, TransToken -from ui_wx import MARKDOWN, wid_transtoken, PEN_SLOT_BORDER, PEN_SLOT_BORDER_SEL +from ui_wx import MARKDOWN, PEN_SLOT_BORDER, PEN_SLOT_BORDER_SEL, RADIO_MENU_BITMAP, wid_transtoken from ui_wx.img import WX_IMG, ImageSlot import utils @@ -670,14 +670,12 @@ def _ui_menu_add( label: TransToken, /, ) -> None: """Add the specified item to the group's menu.""" - # TODO: Ideally these should be radio buttons, not check buttons. - # But each menu gets a different group assigned. - # Maybe use custom bitmaps? self._menu_items[item] = menu_item = group.menu.AppendCheckItem( wx.ID_ANY, f':{item}', '', ) wid_transtoken.set_menu_text(menu_item, label) group.menu.Bind(wx.EVT_MENU, lambda evt: func(), menu_item) + menu_item.SetBitmap(RADIO_MENU_BITMAP, True) @override def _ui_menu_set_font(self, item_id: utils.SpecialID, /, suggested: bool) -> None: