From c9f555a860ba36a7d9e63b7ec9e0add7ad66b875 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 4 Jun 2018 02:53:14 -0400 Subject: [PATCH] Move the slider to another file (makes it easier to test), and adjust the logic so that the base value is always considered in the center, no matter the skew of the ranges --- gui/builtinItemStatsViews/attributeSlider.py | 112 +++++++++++++++++++ gui/builtinItemStatsViews/itemMutator.py | 93 +-------------- 2 files changed, 113 insertions(+), 92 deletions(-) create mode 100644 gui/builtinItemStatsViews/attributeSlider.py diff --git a/gui/builtinItemStatsViews/attributeSlider.py b/gui/builtinItemStatsViews/attributeSlider.py new file mode 100644 index 000000000..569807764 --- /dev/null +++ b/gui/builtinItemStatsViews/attributeSlider.py @@ -0,0 +1,112 @@ +import wx + +class AttributeSlider(wx.Panel): + # Slider which abstracts users values from internal values (because the built in slider does not deal with floats + # and the like), based on http://wxpython-users.wxwidgets.narkive.com/ekgBzA7u/anyone-ever-thought-of-a-floating-point-slider + + def __init__(self, parent, baseValue, minMod, maxMod): + wx.Panel.__init__(self, parent) + + self.parent = parent + + self.base_value = baseValue + + self.UserMinValue = minMod + self.UserMaxValue = maxMod + + # The internal slider basically represents the percentage towards the end of the range. It has to be normalized + # in this way, otherwise when we start off with a base, if the range is skewed to one side, the base value won't + # be centered. We use a range of -100,100 so that we can depend on the SliderValue to contain the percentage + # toward one end + + self.SliderMinValue = -100 + self.SliderMaxValue = 100 + self.SliderValue = 0 + + self.statxt1 = wx.StaticText(self, wx.ID_ANY, 'left', + style=wx.ST_NO_AUTORESIZE | wx.ALIGN_LEFT) + self.statxt2 = wx.StaticText(self, wx.ID_ANY, 'middle', + style=wx.ST_NO_AUTORESIZE | wx.ALIGN_CENTRE) + self.statxt3 = wx.StaticText(self, wx.ID_ANY, 'right', + style=wx.ST_NO_AUTORESIZE | wx.ALIGN_RIGHT) + + self.statxt1.SetLabel("{0:.3f}".format(self.UserMinValue * self.base_value)) + self.statxt1.SetToolTip("{0:+f}%".format((1-self.UserMinValue)*-100)) + self.statxt2.SetLabel("{0:.3f}".format(self.base_value)) + self.statxt3.SetLabel("{0:.3f}".format(self.UserMaxValue * self.base_value)) + self.statxt3.SetToolTip("{0:+f}%".format((1-self.UserMaxValue)*-100)) + + self.slider = wx.Slider( + self, wx.ID_ANY, + self.SliderValue, + self.SliderMinValue, + self.SliderMaxValue, + style=wx.SL_HORIZONTAL) + + self.slider.SetTickFreq((self.SliderMaxValue - self.SliderMinValue) / 15) + + self.slider.Bind(wx.EVT_SCROLL, self.OnScroll) + + b = 20 + hsizer1 = wx.BoxSizer(wx.HORIZONTAL) + hsizer1.Add(self.statxt1, 1, wx.RIGHT, b) + hsizer1.Add(self.statxt2, 1, wx.LEFT | wx.RIGHT, b) + hsizer1.Add(self.statxt3, 1, wx.LEFT, b) + + b = 4 + vsizer1 = wx.BoxSizer(wx.VERTICAL) + vsizer1.Add(hsizer1, 0, wx.EXPAND | wx.ALL, b) + vsizer1.Add(self.slider, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.BOTTOM, b) + + self.SetSizerAndFit(vsizer1) + self.parent.SetClientSize((500, vsizer1.GetSize()[1])) + + def OnScroll(self, event): + self.SliderValue = self.slider.GetValue() + + # The slkider value tells us when mod we're going to use, depending on its sign + if self.SliderValue < 0: + mod = self.UserMinValue + elif self.SliderValue > 0: + mod = self.UserMaxValue + else: + mod = 1 + + # Get the slider value percentage as an absolute value + slider_mod = abs(self.SliderValue) / 100 + + # Gets our new mod by use the slider's percentage to determine where in the spectrum it is + new_mod = mod + ((1-mod)-((1-mod) * slider_mod)) + + # Modifies our base vale, to get out modified value + newValue = new_mod * self.base_value + + if mod == 1: + self.statxt2.SetLabel("{0:.3f}".format(newValue)) + else: + self.statxt2.SetLabel("{0:.3f} ({1:+.3f})".format(newValue, newValue-self.base_value,)) + self.statxt2.SetToolTip("{0:+f}%".format(newValue)) + + +class TestAttributeSlider(wx.Frame): + + def __init__(self, parent, id): + title = 'Slider...' + pos = wx.DefaultPosition + size = wx.DefaultSize + sty = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, parent, id, title, pos, size, sty) + + self.panel = AttributeSlider(self, 200, .80, 1.5) + + self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) + + def OnCloseWindow(self, event): + self.Destroy() + + +if __name__ == "__main__": + app = wx.App() + frame = TestAttributeSlider(None, wx.ID_ANY) + frame.Show() + app.MainLoop() diff --git a/gui/builtinItemStatsViews/itemMutator.py b/gui/builtinItemStatsViews/itemMutator.py index 82424c7a4..1ea56f318 100644 --- a/gui/builtinItemStatsViews/itemMutator.py +++ b/gui/builtinItemStatsViews/itemMutator.py @@ -11,6 +11,7 @@ from eos.saveddata.module import Module from eos.saveddata.ship import Ship from eos.saveddata.citadel import Citadel from eos.saveddata.fit import Fit +from .attributeSlider import AttributeSlider import gui.mainFrame from gui.contextMenu import ContextMenu @@ -42,95 +43,3 @@ class ItemMutator(wx.Panel): self.SetSizer(mainSizer) self.Layout() - -class AttributeSlider(wx.Panel): - # based on http://wxpython-users.wxwidgets.narkive.com/ekgBzA7u/anyone-ever-thought-of-a-floating-point-slider - - def __init__(self, parent, baseValue, minMod, maxMod): - wx.Panel.__init__(self, parent) - - self.parent = parent - - self.mod = 100 # modifier for the underlying Slider (ensure we don't hit floats, which it doesn't support) - self.base_value = baseValue - - - self.UserMinValue = minMod - self.UserMaxValue = maxMod - self.UserValue = 1 - - self.SliderMinValue = self.UserMinValue * self.mod - self.SliderMaxValue = self.UserMaxValue * self.mod - self.SliderValue = self.UserValue * self.mod - - self.statxt1 = wx.StaticText(self, wx.ID_ANY, 'left', - style=wx.ST_NO_AUTORESIZE | wx.ALIGN_LEFT) - self.statxt2 = wx.StaticText(self, wx.ID_ANY, 'middle', - style=wx.ST_NO_AUTORESIZE | wx.ALIGN_CENTRE) - self.statxt3 = wx.StaticText(self, wx.ID_ANY, 'right', - style=wx.ST_NO_AUTORESIZE | wx.ALIGN_RIGHT) - - self.statxt1.SetLabel("{0:.3f}".format(self.UserMinValue * self.base_value)) - self.statxt1.SetToolTip("{0:+f}%".format((1-self.UserMinValue)*-100)) - self.statxt2.SetLabel("{0:.3f}".format(self.UserValue * self.base_value)) - self.statxt3.SetLabel("{0:.3f}".format(self.UserMaxValue * self.base_value)) - self.statxt3.SetToolTip("{0:+f}%".format((1-self.UserMaxValue)*-100)) - - self.slider = wx.Slider( - self, wx.ID_ANY, - self.SliderValue, - self.SliderMinValue, - self.SliderMaxValue, - style=wx.SL_HORIZONTAL) - - self.slider.SetTickFreq((self.SliderMaxValue - self.SliderMinValue) / 15) - - self.slider.Bind(wx.EVT_SCROLL, self.OnScroll) - - b = 20 - hsizer1 = wx.BoxSizer(wx.HORIZONTAL) - hsizer1.Add(self.statxt1, 1, wx.RIGHT, b) - hsizer1.Add(self.statxt2, 1, wx.LEFT | wx.RIGHT, b) - hsizer1.Add(self.statxt3, 1, wx.LEFT, b) - - b = 4 - vsizer1 = wx.BoxSizer(wx.VERTICAL) - vsizer1.Add(hsizer1, 0, wx.EXPAND | wx.ALL, b) - vsizer1.Add(self.slider, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.BOTTOM, b) - - self.SetSizerAndFit(vsizer1) - self.parent.SetClientSize((500, vsizer1.GetSize()[1])) - - def OnScroll(self, event): - self.SliderValue = self.slider.GetValue() - self.UserValue = self.SliderValue / self.mod - newValue = self.UserValue * self.base_value - if self.UserValue == 1: - self.statxt2.SetLabel("{0:.3f}".format(newValue)) - else: - self.statxt2.SetLabel("{0:.3f} ({1:+.3f})".format(newValue, newValue-self.base_value,)) - self.statxt2.SetToolTip("{0:+f}%".format((1 - self.UserValue) * -100)) - - -class TestAttributeSlider(wx.Frame): - - def __init__(self, parent, id): - title = 'Slider...' - pos = wx.DefaultPosition - size = wx.DefaultSize - sty = wx.DEFAULT_FRAME_STYLE - wx.Frame.__init__(self, parent, id, title, pos, size, sty) - - self.panel = AttributeSlider(self, 200, 0.20, 1.3) - - self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) - - def OnCloseWindow(self, event): - self.Destroy() - - -if __name__ == "__main__": - app = wx.App() - frame = TestAttributeSlider(None, wx.ID_ANY) - frame.Show() - app.MainLoop()