Skip to content

Commit

Permalink
Add color-picker setting support
Browse files Browse the repository at this point in the history
  • Loading branch information
kk7ds committed Oct 5, 2023
1 parent 68f6a46 commit b50ac31
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
54 changes: 54 additions & 0 deletions chirp/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,60 @@ def get_step(self):
return self._step


class RadioSettingValueRGB(RadioSettingValue):
"""A color setting, stored as (r, g, b)"""
def __init__(self, current):
super().__init__()
self.set_value(current)

@staticmethod
def from_bits(value, rbits, gbits, bbits):
outvals = []
for bits in [rbits, gbits, bbits]:
outval = value & (2 ** bits - 1)
# Map into 8-bpc space
outvals.insert(0, round(outval / (2 ** bits - 1) * 255))
value >>= bits
return RadioSettingValueRGB(tuple(outvals))

@staticmethod
def from_rgb24(value):
"""Return a RadioSettingValueRGB initialized from an rgb24 value"""
return RadioSettingValueRGB.from_bits(value, 8, 8, 8)

@staticmethod
def from_rgb16(value):
"""Return a RadioSettingValueRGB initialized from an rgb16 value"""
return RadioSettingValueRGB.from_bits(value, 5, 6, 5)

def set_value(self, value):
self._r, self._g, self._b = value

def get_value(self):
"""Returns (r, g, b)"""
return self._r, self._g, self._b

def get_bits(self, rbits, gbits, bbits):
"""Return color as a bitpacked integer.
Pass the number of bits for the r, g, and b channels packed
sequentially into an integer to be returned.
"""
outval = 0
for bits, val in zip([rbits, gbits, bbits],
[self._r, self._g, self._b]):
outval = (outval << bits) | round((2 ** bits - 1) * val / 255)
return outval

def get_rgb24(self):
"""Return an integer value for 24-bit color"""
return self.get_bits(8, 8, 8)

def get_rgb16(self):
"""Return an integer value for 16-bit color"""
return self.get_bits(5, 6, 5)


class RadioSettingValueFloat(RadioSettingValue):

"""A floating-point setting"""
Expand Down
12 changes: 11 additions & 1 deletion chirp/wxui/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,8 @@ def __init__(self, settinggroup, *a, **k):
editor = self._get_editor_bool(element, value)
elif isinstance(value, settings.RadioSettingValueString):
editor = self._get_editor_str(element, value)
elif isinstance(value, settings.RadioSettingValueRGB):
editor = self._get_editor_rgb(element, value)
else:
LOG.warning('Unsupported setting type %r' % value)
editor = None
Expand Down Expand Up @@ -510,14 +512,22 @@ def ValidateValue(self, text, info):
setting.get_name(),
value=str(value))

def _get_editor_rgb(self, setting, value):
return wx.propgrid.ColourProperty(setting.get_shortname(),
setting.get_name(),
wx.Colour(*value.get_value()))

def get_setting_values(self):
"""Return a dict of {name: (RadioSetting, newvalue)}"""
values = {}
for prop in self.pg._Items():
if prop.IsCategory():
continue
basename = prop.GetName().split(INDEX_CHAR)[0]
if isinstance(prop, wx.propgrid.EnumProperty):
if isinstance(prop, wx.propgrid.ColourProperty):
c = prop.GetValue()
value = c.red, c.green, c.blue
elif isinstance(prop, wx.propgrid.EnumProperty):
value = self._choices[basename][prop.GetValue()]
else:
value = prop.GetValue()
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@ def test_radio_setting_value_string(self):
self._set_and_test(value, "a", "abc", "abdef")
self._set_and_catch(value, "", "abcdefg")

def test_radio_setting_value_rgb(self):
value = settings.RadioSettingValueRGB((0, 0, 0))
self.assertEqual((0, 0, 0), value.get_value())
self.assertEqual(0, value.get_rgb16())
self.assertEqual(0, value.get_rgb24())

# 0x9c9a2f == 0x9cc6
value.set_value((0x9C, 0x9A, 0x2F))
self.assertEqual(0x9C9A2F, value.get_rgb24())
self.assertEqual(0x9CC6, value.get_rgb16())

value = settings.RadioSettingValueRGB.from_rgb16(0x9CC6)
# Rounding error on the B value
self.assertEqual(0x9C9A31, value.get_rgb24())

def test_validate_callback(self):
class TestException(Exception):
pass
Expand Down

0 comments on commit b50ac31

Please sign in to comment.