From 170853f0f452f54a82775539800318602eb48037 Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Tue, 6 Aug 2019 23:51:09 +0300 Subject: [PATCH] Add line style support --- graphs/gui/frame.py | 24 +++++++---- graphs/gui/lists.py | 12 ++++-- graphs/gui/stylePickers.py | 10 ++++- graphs/style.py | 25 ++++++++++- graphs/wrapper.py | 23 ++-------- gui/builtinViewColumns/graphLineStyle.py | 55 ++++++++++++++++++++++++ gui/viewColumn.py | 1 + service/const.py | 8 ++++ 8 files changed, 125 insertions(+), 33 deletions(-) create mode 100644 gui/builtinViewColumns/graphLineStyle.py diff --git a/graphs/gui/frame.py b/graphs/gui/frame.py index e9272b4be..d8db2d7b6 100644 --- a/graphs/gui/frame.py +++ b/graphs/gui/frame.py @@ -31,7 +31,7 @@ import gui.globalEvents as GE import gui.mainFrame from graphs.data.base import FitGraph from graphs.events import RESIST_MODE_CHANGED -from graphs.style import BASE_COLORS, LIGHTNESSES, hsl_to_hsv +from graphs.style import BASE_COLORS, LIGHTNESSES, STYLES, hsl_to_hsv from gui.bitmap_loader import BitmapLoader from service.const import GraphCacheCleanupReason from service.settings import GraphSettings @@ -269,13 +269,14 @@ class GraphFrame(wx.Frame): else: iterList = tuple((f, None) for f in sources) for source, target in iterList: - # Get color data + # Get line style data try: colorData = BASE_COLORS[source.colorID] except KeyError: pyfalog.warning('Invalid color "{}" for "{}"'.format(source.colorID, source.name)) continue color = colorData.hsl + lineStyle = 'solid' if target is not None: try: lightnessData = LIGHTNESSES[target.lightnessID] @@ -283,7 +284,14 @@ class GraphFrame(wx.Frame): pyfalog.warning('Invalid lightness "{}" for "{}"'.format(target.lightnessID, target.name)) continue color = lightnessData.func(color) + try: + lineStyleData = STYLES[target.lineStyleID] + except KeyError: + pyfalog.warning('Invalid line style "{}" for "{}"'.format(target.lightnessID, target.name)) + continue + lineStyle = lineStyleData.mplSpec color = hsv_to_rgb(hsl_to_hsv(color)) + # Get point data try: xs, ys = view.getPlotPoints( @@ -307,14 +315,14 @@ class GraphFrame(wx.Frame): max_y = max(max_y, max_y_this) if len(xs) == 1 and len(ys) == 1: - self.subplot.plot(xs, ys, color=color, marker='.') + self.subplot.plot(xs, ys, color=color, linestyle=lineStyle, marker='.') else: - self.subplot.plot(xs, ys, color=color) + self.subplot.plot(xs, ys, color=color, linestyle=lineStyle) if target is None: - legend.append((color, source.shortName)) + legend.append((color, lineStyle, source.shortName)) else: - legend.append((color, '{} vs {}'.format(source.shortName, target.shortName))) + legend.append((color, lineStyle, '{} vs {}'.format(source.shortName, target.shortName))) except Exception as ex: pyfalog.warning('Invalid values in "{0}"', source.name) self.canvas.draw() @@ -340,8 +348,8 @@ class GraphFrame(wx.Frame): legend2 = [] for i, iData in enumerate(legend): - color, label = iData - legend2.append(Patch(color=color, label=label), ) + color, lineStyle, label = iData + legend2.append(Patch(color=color, linestyle=lineStyle, label=label), ) if len(legend2) > 0 and self.ctrlPanel.showLegend: leg = self.subplot.legend(handles=legend2) diff --git a/graphs/gui/lists.py b/graphs/gui/lists.py index 7e575d25f..a7b4b7f02 100644 --- a/graphs/gui/lists.py +++ b/graphs/gui/lists.py @@ -27,10 +27,11 @@ 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.builtinViewColumns.graphLineStyle import GraphLineStyle from gui.contextMenu import ContextMenu from service.const import GraphCacheCleanupReason from service.fit import Fit -from .stylePickers import ColorPickerPopup, LightnessPickerPopup +from .stylePickers import ColorPickerPopup, LightnessPickerPopup, LineStylePickerPopup class BaseWrapperList(gui.display.Display): @@ -122,7 +123,9 @@ class BaseWrapperList(gui.display.Display): if row != -1: pickers = { self.getColIndex(GraphColor): ColorPickerPopup, - self.getColIndex(GraphLightness): LightnessPickerPopup} + self.getColIndex(GraphLightness): LightnessPickerPopup, + self.getColIndex(GraphLineStyle): LineStylePickerPopup} + # In case we had no index for some column, remove None pickers.pop(None, None) col = self.getColumn(event.Position) if col in pickers: @@ -286,7 +289,7 @@ class SourceWrapperList(BaseWrapperList): for colorID in BASE_COLORS: if leastUses == colorUseMap.get(colorID, 0): break - self._wrappers.append(SourceWrapper(item, colorID)) + self._wrappers.append(SourceWrapper(item=item, colorID=colorID)) def spawnMenu(self, event): selection = self.getSelectedWrappers() @@ -307,6 +310,7 @@ class TargetWrapperList(BaseWrapperList): DEFAULT_COLS = ( 'Graph Lightness', + 'Graph Line Style', 'Base Icon', 'Base Name') @@ -330,7 +334,7 @@ class TargetWrapperList(BaseWrapperList): for lightnessID in LIGHTNESSES: if leastUses == lightnessUseMap.get(lightnessID, 0): break - self._wrappers.append(TargetWrapper(item=item, lightnessID=lightnessID)) + self._wrappers.append(TargetWrapper(item=item, lightnessID=lightnessID, lineStyleID=None)) def spawnMenu(self, event): selection = self.getSelectedWrappers() diff --git a/graphs/gui/stylePickers.py b/graphs/gui/stylePickers.py index 9e3bfa8a1..233ff4302 100644 --- a/graphs/gui/stylePickers.py +++ b/graphs/gui/stylePickers.py @@ -21,7 +21,7 @@ # noinspection PyPackageRequirements import wx -from graphs.style import BASE_COLORS, LIGHTNESSES +from graphs.style import BASE_COLORS, LIGHTNESSES, STYLES from gui.bitmap_loader import BitmapLoader from service.const import GraphLightness @@ -96,3 +96,11 @@ class LightnessPickerPopup(StylePickerPopup): wrapperAttr = 'lightnessID' ncols = 3 nrows = 1 + + +class LineStylePickerPopup(StylePickerPopup): + + styleContainer = STYLES + wrapperAttr = 'lineStyleID' + ncols = 4 + nrows = 1 diff --git a/graphs/style.py b/graphs/style.py index 33a12121c..84f15d520 100644 --- a/graphs/style.py +++ b/graphs/style.py @@ -20,13 +20,29 @@ from collections import OrderedDict, namedtuple -from service.const import GraphColor, GraphLightness +# noinspection PyPackageRequirements +import wx + +from service.const import GraphColor, GraphLightness, GraphLineStyle ColorData = namedtuple('ColorData', ('hsl', 'name', 'iconName')) LightnessData = namedtuple('LightnessData', ('name', 'iconName', 'func')) +class LineStyleData: + + def __init__(self, name, iconNamePrefix, mplSpec): + self.name = name + self._iconNamePrefix = iconNamePrefix + self.mplSpec = mplSpec + + @property + def iconName(self): + # TODO: add code to use white icon if background is dark + return '{}_black'.format(self._iconNamePrefix) + + # In HSL format BASE_COLORS = OrderedDict([ (GraphColor.red, ColorData((0 / 360.0, 1.0, 0.5), 'Red', 'color_red')), @@ -60,3 +76,10 @@ 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))]) + + +STYLES = OrderedDict([ + (GraphLineStyle.solid, LineStyleData('Solid', 'style_solid', 'solid')), + (GraphLineStyle.dashed, LineStyleData('Dashed', 'style_dashed', (0, (5, 1)))), + (GraphLineStyle.dotted, LineStyleData('Dotted', 'style_dotted', (0, (1, 1)))), + (GraphLineStyle.dashdotted, LineStyleData('Dash-dotted', 'style_dashdot', (0, (3, 1, 1, 1))))]) diff --git a/graphs/wrapper.py b/graphs/wrapper.py index adc5b9cd8..48b7b9e6a 100644 --- a/graphs/wrapper.py +++ b/graphs/wrapper.py @@ -110,26 +110,11 @@ class SourceWrapper(BaseWrapper): class TargetWrapper(BaseWrapper): - def __init__(self, item, lightnessID): + def __init__(self, item, lightnessID, lineStyleID): super().__init__(item=item) - self._lightnessID = lightnessID - self.__resistMode = TargetResistMode.auto - - @property - def lightnessID(self): - return self._lightnessID - - @lightnessID.setter - def lightnessID(self, value): - self._lightnessID = value - - @property - def resistMode(self): - return self.__resistMode - - @resistMode.setter - def resistMode(self, value): - self.__resistMode = value + self.lightnessID = lightnessID + self.lineStyleID = lineStyleID + self.resistMode = TargetResistMode.auto def getResists(self, includeLayer=False): em = therm = kin = explo = 0 diff --git a/gui/builtinViewColumns/graphLineStyle.py b/gui/builtinViewColumns/graphLineStyle.py new file mode 100644 index 000000000..3338e03ca --- /dev/null +++ b/gui/builtinViewColumns/graphLineStyle.py @@ -0,0 +1,55 @@ +# ============================================================================= +# Copyright (C) 2010 Diego Duclos +# +# This file is part of pyfa. +# +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +# ============================================================================= + +# noinspection PyPackageRequirements +import wx + +from graphs.style import STYLES +from graphs.wrapper import TargetWrapper +from gui.viewColumn import ViewColumn + + +class GraphLineStyle(ViewColumn): + + name = 'Graph Line Style' + + def __init__(self, fittingView, params): + ViewColumn.__init__(self, fittingView) + self.resizable = False + self.size = 20 + self.maxsize = self.size + self.mask = wx.LIST_MASK_TEXT + + def getImageId(self, stuff): + if isinstance(stuff, TargetWrapper): + try: + styleData = STYLES[stuff.lineStyleID] + except KeyError: + return -1 + img = self.fittingView.imageList.GetImageIndex(styleData.iconName, 'gui') + return img + return -1 + + def getToolTip(self, stuff): + if isinstance(stuff, TargetWrapper): + return 'Change line style' + return '' + + +GraphLineStyle.register() diff --git a/gui/viewColumn.py b/gui/viewColumn.py index e7f3109fa..ec58ef4d8 100644 --- a/gui/viewColumn.py +++ b/gui/viewColumn.py @@ -78,6 +78,7 @@ from gui.builtinViewColumns import ( # noqa: E402, F401 capacitorUse, graphColor, graphLightness, + graphLineStyle, maxRange, misc, price, diff --git a/service/const.py b/service/const.py index c88ea6e4c..105c08e2a 100644 --- a/service/const.py +++ b/service/const.py @@ -157,3 +157,11 @@ class GraphLightness(IntEnum): normal = autoId() dark = autoId() bright = autoId() + + +@unique +class GraphLineStyle(IntEnum): + solid = autoId() + dashed = autoId() + dotted = autoId() + dashdotted = autoId()