diff --git a/graphs/gui/frame.py b/graphs/gui/frame.py index fbf05764c..e9272b4be 100644 --- a/graphs/gui/frame.py +++ b/graphs/gui/frame.py @@ -29,9 +29,9 @@ from logbook import Logger import gui.display import gui.globalEvents as GE import gui.mainFrame -from graphs.colors import BASE_COLORS, hsl_to_hsv from graphs.data.base import FitGraph from graphs.events import RESIST_MODE_CHANGED +from graphs.style import BASE_COLORS, LIGHTNESSES, hsl_to_hsv from gui.bitmap_loader import BitmapLoader from service.const import GraphCacheCleanupReason from service.settings import GraphSettings @@ -273,9 +273,17 @@ class GraphFrame(wx.Frame): try: colorData = BASE_COLORS[source.colorID] except KeyError: - pyfalog.warning('Invalid color for "{0}"', source.name) + pyfalog.warning('Invalid color "{}" for "{}"'.format(source.colorID, source.name)) continue - color = hsv_to_rgb(hsl_to_hsv(colorData.hsl)) + color = colorData.hsl + if target is not None: + try: + lightnessData = LIGHTNESSES[target.lightnessID] + except KeyError: + pyfalog.warning('Invalid lightness "{}" for "{}"'.format(target.lightnessID, target.name)) + continue + color = lightnessData.func(color) + color = hsv_to_rgb(hsl_to_hsv(color)) # Get point data try: xs, ys = view.getPlotPoints( diff --git a/graphs/gui/lists.py b/graphs/gui/lists.py index 370144ace..ceea79bf5 100644 --- a/graphs/gui/lists.py +++ b/graphs/gui/lists.py @@ -23,13 +23,14 @@ import wx import gui.display from eos.saveddata.targetProfile import TargetProfile -from graphs.colors import BASE_COLORS +from graphs.style import BASE_COLORS, LIGHTNESSES from graphs.wrapper import SourceWrapper, TargetWrapper from gui.builtinViewColumns.graphColor import GraphColor +from gui.builtinViewColumns.graphLightness import GraphLightness from gui.contextMenu import ContextMenu from service.const import GraphCacheCleanupReason from service.fit import Fit -from .stylePickers import ColorPickerPopup +from .stylePickers import ColorPickerPopup, LightnessPickerPopup class BaseWrapperList(gui.display.Display): @@ -123,14 +124,22 @@ class BaseWrapperList(gui.display.Display): if col == self.getColIndex(GraphColor): wrapper = self.getWrapper(row) if wrapper is not None: - win = ColorPickerPopup(parent=self, wrapper=wrapper, ncol=4, nrow=2) + win = ColorPickerPopup(parent=self, wrapper=wrapper) + pos = wx.GetMousePosition() + win.Position(pos, (0, 0)) + win.Popup() + return + if col == self.getColIndex(GraphLightness): + wrapper = self.getWrapper(row) + if wrapper is not None: + win = LightnessPickerPopup(parent=self, wrapper=wrapper) pos = wx.GetMousePosition() win.Position(pos, (0, 0)) win.Popup() return event.Skip() - def OnColorChange(self): + def OnLineStyleChange(self): self.updateView() self.graphFrame.draw() @@ -276,11 +285,11 @@ class SourceWrapperList(BaseWrapperList): continue colorUseMap[wrapper.colorID] += 1 leastUses = min(colorUseMap.values(), default=0) - color = None - for color in BASE_COLORS: - if leastUses == colorUseMap.get(color, 0): + colorID = None + for colorID in BASE_COLORS: + if leastUses == colorUseMap.get(colorID, 0): break - self._wrappers.append(SourceWrapper(item, color)) + self._wrappers.append(SourceWrapper(item, colorID)) def spawnMenu(self, event): selection = self.getSelectedWrappers() @@ -313,7 +322,18 @@ class TargetWrapperList(BaseWrapperList): self.updateView() def appendItem(self, item): - self._wrappers.append(TargetWrapper(item, None)) + # Find out least used lightness + lightnessUseMap = {l: 0 for l in LIGHTNESSES} + for wrapper in self._wrappers: + if wrapper.lightnessID not in lightnessUseMap: + continue + lightnessUseMap[wrapper.lightnessID] += 1 + leastUses = min(lightnessUseMap.values(), default=0) + lightnessID = None + for lightnessID in LIGHTNESSES: + if leastUses == lightnessUseMap.get(lightnessID, 0): + break + self._wrappers.append(TargetWrapper(item=item, lightnessID=lightnessID)) def spawnMenu(self, event): selection = self.getSelectedWrappers() diff --git a/graphs/gui/stylePickers.py b/graphs/gui/stylePickers.py index 92ae5a8f3..7e6346f6d 100644 --- a/graphs/gui/stylePickers.py +++ b/graphs/gui/stylePickers.py @@ -21,22 +21,21 @@ # noinspection PyPackageRequirements import wx -from graphs.colors import BASE_COLORS +from graphs.style import BASE_COLORS, LIGHTNESSES from gui.bitmap_loader import BitmapLoader +from service.const import GraphLightness class ColorPickerPopup(wx.PopupTransientWindow): - def __init__(self, parent, wrapper, ncol=0, nrow=0): + def __init__(self, parent, wrapper): super().__init__(parent, flags=wx.BORDER_SIMPLE) self.wrapper = wrapper - ncol = ncol or len(BASE_COLORS) - nrow = nrow or int(len(BASE_COLORS) / ncol) + (1 if (len(BASE_COLORS) % ncol) else 0) self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)) sizer = wx.BoxSizer(wx.VERTICAL) - grid = wx.GridSizer(nrow, ncol, 0, 0) + grid = wx.GridSizer(2, 4, 0, 0) self.patches = list() for colorID, colorData in BASE_COLORS.items(): icon = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap(colorData.iconName, 'gui')) @@ -54,7 +53,43 @@ class ColorPickerPopup(wx.PopupTransientWindow): colorID = getattr(event.GetEventObject(), 'colorID', None) if colorID is not None: self.wrapper.colorID = colorID - self.Parent.OnColorChange() + self.Parent.OnLineStyleChange() + self.Hide() + self.Destroy() + return + event.Skip() + + +class LightnessPickerPopup(wx.PopupTransientWindow): + + def __init__(self, parent, wrapper): + super().__init__(parent, flags=wx.BORDER_SIMPLE) + self.wrapper = wrapper + + self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)) + sizer = wx.BoxSizer(wx.VERTICAL) + + grid = wx.GridSizer(1, 3, 0, 0) + self.patches = list() + customOrder = (GraphLightness.dark, GraphLightness.normal, GraphLightness.bright) + for lightnessID in customOrder: + lightnessData = LIGHTNESSES[lightnessID] + icon = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap(lightnessData.iconName, 'gui')) + icon.lightnessID = lightnessID + icon.SetToolTip(lightnessData.name) + icon.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + grid.Add(icon, flag=wx.ALL, border=3) + sizer.Add(grid) + + self.SetSizer(sizer) + self.Fit() + self.Layout() + + def OnLeftDown(self, event): + lightnessID = getattr(event.GetEventObject(), 'lightnessID', None) + if lightnessID is not None: + self.wrapper.lightnessID = lightnessID + self.Parent.OnLineStyleChange() self.Hide() self.Destroy() return diff --git a/graphs/colors.py b/graphs/style.py similarity index 82% rename from graphs/colors.py rename to graphs/style.py index 1c83ffdf1..33a12121c 100644 --- a/graphs/colors.py +++ b/graphs/style.py @@ -20,10 +20,11 @@ from collections import OrderedDict, namedtuple -from service.const import GraphColor +from service.const import GraphColor, GraphLightness ColorData = namedtuple('ColorData', ('hsl', 'name', 'iconName')) +LightnessData = namedtuple('LightnessData', ('name', 'iconName', 'func')) # In HSL format @@ -53,3 +54,9 @@ def darken(hsl): def brighten(hsl): h, s, l = hsl return h, s * 0.7, l + (1 - l) * 0.4 + + +LIGHTNESSES = OrderedDict([ + (GraphLightness.normal, LightnessData('Normal', 'lightness_normal', lambda hsl: hsl)), + (GraphLightness.dark, LightnessData('Dark', 'lightness_dark', darken)), + (GraphLightness.bright, LightnessData('Bright', 'lightness_bright', brighten))]) diff --git a/graphs/wrapper.py b/graphs/wrapper.py index ec1f3da2c..adc5b9cd8 100644 --- a/graphs/wrapper.py +++ b/graphs/wrapper.py @@ -110,18 +110,18 @@ class SourceWrapper(BaseWrapper): class TargetWrapper(BaseWrapper): - def __init__(self, item, lightness): + def __init__(self, item, lightnessID): super().__init__(item=item) - self._lightness = lightness + self._lightnessID = lightnessID self.__resistMode = TargetResistMode.auto @property - def lightness(self): - return self._lightness + def lightnessID(self): + return self._lightnessID - @lightness.setter - def lightness(self, value): - self._lightness = value + @lightnessID.setter + def lightnessID(self, value): + self._lightnessID = value @property def resistMode(self): diff --git a/gui/builtinViewColumns/graphColor.py b/gui/builtinViewColumns/graphColor.py index 270f4624d..ba1d6ac69 100644 --- a/gui/builtinViewColumns/graphColor.py +++ b/gui/builtinViewColumns/graphColor.py @@ -20,7 +20,7 @@ # noinspection PyPackageRequirements import wx -from graphs.colors import BASE_COLORS +from graphs.style import BASE_COLORS from graphs.wrapper import SourceWrapper from gui.viewColumn import ViewColumn @@ -39,10 +39,10 @@ class GraphColor(ViewColumn): def getImageId(self, stuff): if isinstance(stuff, SourceWrapper): try: - color_data = BASE_COLORS[stuff.colorID] + colorData = BASE_COLORS[stuff.colorID] except KeyError: return -1 - img = self.fittingView.imageList.GetImageIndex(color_data.iconName, 'gui') + img = self.fittingView.imageList.GetImageIndex(colorData.iconName, 'gui') return img return -1 diff --git a/gui/builtinViewColumns/graphLightness.py b/gui/builtinViewColumns/graphLightness.py index c45e88de4..f36e30750 100644 --- a/gui/builtinViewColumns/graphLightness.py +++ b/gui/builtinViewColumns/graphLightness.py @@ -20,7 +20,7 @@ # noinspection PyPackageRequirements import wx -from graphs.colors import BASE_COLORS +from graphs.style import LIGHTNESSES from graphs.wrapper import TargetWrapper from gui.viewColumn import ViewColumn @@ -38,8 +38,12 @@ class GraphLightness(ViewColumn): def getImageId(self, stuff): if isinstance(stuff, TargetWrapper): - # img = self.fittingView.imageList.GetImageIndex(color_data.iconName, 'gui') - return -1 + try: + lightnessData = LIGHTNESSES[stuff.lightnessID] + except KeyError: + return -1 + img = self.fittingView.imageList.GetImageIndex(lightnessData.iconName, 'gui') + return img return -1 def getToolTip(self, stuff):