From c3dcdb06869d14a8f06fab7a4b3a5e88d8be44aa Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sun, 27 Mar 2016 21:48:19 -0400 Subject: [PATCH 1/5] Entity = characters, damage profiles... anything with the generic drop down list of entities along with new/rename/etc buttons. This commit starts refactoring how we handle this, hopefully simplifying the process to a series of dialogs rather than trying to manage multiple control in the window. --- gui/builtinViews/entityEditor.py | 151 ++++++++++++++++++ gui/patternEditor.py | 252 +++++++++---------------------- service/damagePattern.py | 5 +- 3 files changed, 225 insertions(+), 183 deletions(-) create mode 100644 gui/builtinViews/entityEditor.py diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py new file mode 100644 index 000000000..7eb439fb1 --- /dev/null +++ b/gui/builtinViews/entityEditor.py @@ -0,0 +1,151 @@ +import wx +from gui.bitmapLoader import BitmapLoader +import service + +class BaseValidator(wx.PyValidator): + def __init__(self): + wx.PyValidator.__init__(self) + + def Validate(self, win): + raise NotImplementedError() + + def TransferToWindow(self): + return True + + def TransferFromWindow(self): + return True + +class TextEntryValidatedDialog(wx.TextEntryDialog): + def __init__(self, parent, validator=None, *args, **kargs): + wx.TextEntryDialog.__init__(self, parent, *args, **kargs) + self.txtctrl = self.FindWindowById(3000) + if validator: + self.txtctrl.SetValidator(validator()) + +class EntityEditor (wx.Panel): + """ + Entity Editor is a panel that takes some sort of list as a source and populates a drop down with options to add/ + rename/clone/delete an entity. Comes with dialogs that take user input. Classes that derive this class must override + functions that get the list from the source, what to do when user does an action, and how to validate the input. + """ + + def __init__(self, parent, entityName): + wx.Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL) + self.entityName = entityName + self.validator = None + self.navSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.choices = self.getEntitiesFromContext() + self.choices.sort(key=lambda p: p.name) + self.entityChoices = wx.Choice(self, choices=map(lambda p: p.name, self.choices)) + self.navSizer.Add(self.entityChoices, 1, wx.ALL, 5) + + buttons = (("new", wx.ART_NEW, self.OnNew), + ("rename", BitmapLoader.getBitmap("rename", "gui"), self.OnRename), + ("copy", wx.ART_COPY, self.OnCopy), + ("delete", wx.ART_DELETE, self.OnDelete)) + + size = None + for name, art, func in buttons: + bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art + btn = wx.BitmapButton(self, wx.ID_ANY, bitmap) + if size is None: + size = btn.GetSize() + + btn.SetMinSize(size) + btn.SetMaxSize(size) + + btn.SetToolTipString("{} {}".format(name.capitalize(), self.entityName)) + btn.Bind(wx.EVT_BUTTON, func) + setattr(self, "btn%s" % name.capitalize(), btn) + self.navSizer.Add(btn, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2) + + self.entityChoices.SetSelection(0) + self.SetSizer(self.navSizer) + self.Layout() + + def SetEditorValidator(self, validator=None): + """ Sets validator class (not an instance of the class) """ + self.validator = validator + + def getEntitiesFromContext(self): + """ Gets list of entities from current context """ + raise NotImplementedError() + + def DoNew(self, name): + """Override method to do new entity logic. Must return the new entity""" + raise NotImplementedError() + + def DoCopy(self, name): + """Override method to copy entity. Must return the copy""" + raise NotImplementedError() + + def DoRename(self, name): + """Override method to rename an entity""" + raise NotImplementedError() + + def DoDelete(self, name): + """Override method to delete entity""" + raise NotImplementedError() + + def OnNew(self, event): + dlg = TextEntryValidatedDialog(self, self.validator, + "Enter a name for your new {}:".format(self.entityName), + "New {}".format(self.entityName)) + + if dlg.ShowModal() == wx.ID_OK: + new = self.DoNew(dlg.GetValue().strip()) + self.refreshEntityList(new) + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + + def OnCopy(self, event): + dlg = TextEntryValidatedDialog(self, self.validator, + "Enter a name for your {} copy:".format(self.entityName), + "Copy {}".format(self.entityName)) + active = self.getActiveEntity() + dlg.SetValue("{} Copy".format(active.name)) + dlg.txtctrl.SetInsertionPointEnd() + + if dlg.ShowModal() == wx.ID_OK: + copy = self.DoCopy(active, dlg.GetValue().strip()) + self.refreshEntityList(copy) + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + + def OnRename(self, event): + dlg = TextEntryValidatedDialog(self, self.validator, + "Enter a new name for your {}:".format(self.entityName), + "Rename {}".format(self.entityName)) + active = self.getActiveEntity() + dlg.SetValue(active.name) + dlg.txtctrl.SetInsertionPointEnd() + + if dlg.ShowModal() == wx.ID_OK: + self.DoRename(active, dlg.GetValue().strip()) + self.refreshEntityList(active) + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + + def OnDelete(self, event): + dlg = wx.MessageDialog(self, + "Do you really want to delete the {} {}?".format(self.getActiveEntity().name, self.entityName), + "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION) + + if dlg.ShowModal() == wx.ID_YES: + self.DoDelete(self.getActiveEntity()) + self.refreshEntityList() + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + + def refreshEntityList(self, selected=None): + self.choices = self.getEntitiesFromContext() + self.entityChoices.Clear() + self.entityChoices.AppendItems(map(lambda p: p.name, self.choices)) + if selected: + idx = self.choices.index(selected) + self.entityChoices.SetSelection(idx) + else: + self.entityChoices.SetSelection(0) + + def getActiveEntity(self): + if len(self.choices) == 0: + return None + + return self.choices[self.entityChoices.GetSelection()] \ No newline at end of file diff --git a/gui/patternEditor.py b/gui/patternEditor.py index 40b8e45aa..88f24c17c 100644 --- a/gui/patternEditor.py +++ b/gui/patternEditor.py @@ -23,11 +23,65 @@ import service from wx.lib.intctrl import IntCtrl from gui.utils.clipboard import toClipboard, fromClipboard from service.damagePattern import ImportError - +from gui.builtinViews.entityEditor import EntityEditor, BaseValidator ########################################################################### ## Class DmgPatternEditorDlg ########################################################################### +class DmgPatternTextValidor(BaseValidator): + def __init__(self): + BaseValidator.__init__(self) + + def Clone(self): + return DmgPatternTextValidor() + + def Validate(self, win): + profileEditor = win.Parent + textCtrl = self.GetWindow() + text = textCtrl.GetValue().strip() + + try: + if len(text) == 0: + raise ValueError("You must supply a name for your Damage Profile!") + elif text in [x.name for x in profileEditor.choices]: + raise ValueError("Damage Profile name already in use, please choose another.") + + return True + except ValueError, e: + wx.MessageBox(u"{}".format(e), "Error") + textCtrl.SetFocus() + return False + + +class DmgPatternEntityEditor(EntityEditor): + def __init__(self, parent): + EntityEditor.__init__(self, parent, "Damage Profile") + self.SetEditorValidator(DmgPatternTextValidor) + + def getEntitiesFromContext(self): + """ Gets list of entities from current context """ + sDP = service.DamagePattern.getInstance() + choices = sorted(sDP.getDamagePatternList(), key=lambda p: p.name) + return [c for c in choices if c.name != "Selected Ammo"] + + def DoNew(self, name): + sDP = service.DamagePattern.getInstance() + return sDP.newPattern(name) + + def DoRename(self, entity, name): + sDP = service.DamagePattern.getInstance() + sDP.renamePattern(entity, name) + + def DoCopy(self, entity, name): + sDP = service.DamagePattern.getInstance() + copy = sDP.copyPattern(entity) + sDP.renamePattern(copy, name) + return copy + + def DoDelete(self, entity): + sDP = service.DamagePattern.getInstance() + sDP.deletePattern(entity) + class DmgPatternEditorDlg(wx.Dialog): DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive") @@ -39,52 +93,12 @@ class DmgPatternEditorDlg(wx.Dialog): mainSizer = wx.BoxSizer(wx.VERTICAL) - self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL) - sDP = service.DamagePattern.getInstance() self.choices = sDP.getDamagePatternList() - # Remove "Selected Ammo" Damage Pattern - for dp in self.choices: - if dp.name == "Selected Ammo": - self.choices.remove(dp) - # Sort the remaining list and continue on - self.choices.sort(key=lambda p: p.name) - self.ccDmgPattern = wx.Choice(self, choices=map(lambda p: p.name, self.choices)) - self.ccDmgPattern.Bind(wx.EVT_CHOICE, self.patternChanged) - self.ccDmgPattern.SetSelection(0) - self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) - self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename) - self.namePicker.Hide() - - size = None - headerSizer.Add(self.ccDmgPattern, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT|wx.LEFT, 3) - buttons = (("new", wx.ART_NEW), - ("rename", BitmapLoader.getBitmap("rename", "gui")), - ("copy", wx.ART_COPY), - ("delete", wx.ART_DELETE)) - for name, art in buttons: - bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art - btn = wx.BitmapButton(self, wx.ID_ANY, bitmap) - if size is None: - size = btn.GetSize() - - btn.SetMinSize(size) - btn.SetMaxSize(size) - - btn.Layout() - setattr(self, name, btn) - btn.Enable(True) - btn.SetToolTipString("%s pattern" % name.capitalize()) - headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL) - - self.btnSave = wx.Button(self, wx.ID_SAVE) - self.btnSave.Hide() - self.btnSave.Bind(wx.EVT_BUTTON, self.processRename) - self.headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER) - - mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2) + self.entityEditor = DmgPatternEntityEditor(self) + mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2) self.sl = wx.StaticLine(self) mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) @@ -108,7 +122,7 @@ class DmgPatternEditorDlg(wx.Dialog): bmp = wx.StaticBitmap(self, wx.ID_ANY, BitmapLoader.getBitmap("%s_big"%type, "gui")) if i%2: style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT - border = 10 + border = 20 else: style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT border = 5 @@ -155,6 +169,7 @@ class DmgPatternEditorDlg(wx.Dialog): importExport = (("Import", wx.ART_FILE_OPEN, "from"), ("Export", wx.ART_FILE_SAVE_AS, "to")) + for name, art, direction in importExport: bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) btn = wx.BitmapButton(self, wx.ID_ANY, bitmap) @@ -170,14 +185,9 @@ class DmgPatternEditorDlg(wx.Dialog): self.Layout() bsize = self.GetBestSize() - self.SetSize((-1,bsize.height)) + self.SetSize((-1, bsize.height)) - self.new.Bind(wx.EVT_BUTTON, self.newPattern) - self.rename.Bind(wx.EVT_BUTTON, self.renamePattern) - self.copy.Bind(wx.EVT_BUTTON, self.copyPattern) - self.delete.Bind(wx.EVT_BUTTON, self.deletePattern) - self.Import.Bind(wx.EVT_BUTTON, self.importPatterns) - self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns) + self.Bind(wx.EVT_CHOICE, self.patternChanged) self.patternChanged() @@ -188,7 +198,7 @@ class DmgPatternEditorDlg(wx.Dialog): if self.block: return - p = self.getActivePattern() + p = self.entityEditor.getActiveEntity() total = sum(map(lambda attr: getattr(self, "%sEdit"%attr).GetValue(), self.DAMAGE_TYPES)) for type in self.DAMAGE_TYPES: editObj = getattr(self, "%sEdit"%type) @@ -207,24 +217,18 @@ class DmgPatternEditorDlg(wx.Dialog): for type in self.DAMAGE_TYPES: editObj = getattr(self, "%sEdit"%type) editObj.Enable(False) - self.rename.Enable(False) - self.delete.Enable(False) + self.entityEditor.btnRename.Enable(False) + self.entityEditor.btnDelete.Enable(False) def unrestrict(self): for type in self.DAMAGE_TYPES: editObj = getattr(self, "%sEdit"%type) editObj.Enable() - self.rename.Enable() - self.delete.Enable() - - def getActivePattern(self): - if len(self.choices) == 0: - return None - - return self.choices[self.ccDmgPattern.GetSelection()] + self.entityEditor.btnRename.Enable() + self.entityEditor.btnDelete.Enable() def patternChanged(self, event=None): - p = self.getActivePattern() + p = self.entityEditor.getActiveEntity() if p is None: return @@ -244,126 +248,9 @@ class DmgPatternEditorDlg(wx.Dialog): self.block = False self.ValuesUpdated() - def newPattern(self, event): - self.restrict() - - self.block = True - # reset values - for type in self.DAMAGE_TYPES: - editObj = getattr(self, "%sEdit"%type) - editObj.SetValue(0) - - self.block = False - - self.btnSave.SetLabel("Create") - self.Refresh() - self.renamePattern() - - def renamePattern(self, event=None): - if event is not None: - self.btnSave.SetLabel("Rename") - - self.ccDmgPattern.Hide() - self.namePicker.Show() - self.headerSizer.Replace(self.ccDmgPattern, self.namePicker) - self.namePicker.SetFocus() - - if event is not None: # Rename mode - self.btnSave.SetLabel("Rename") - self.namePicker.SetValue(self.getActivePattern().name) - else: # Create mode - self.namePicker.SetValue("") - - for btn in (self.new, self.rename, self.delete, self.copy): - btn.Hide() - - self.btnSave.Show() - self.headerSizer.Layout() - if event is not None: - event.Skip() - - def processRename(self, event): - newName = self.namePicker.GetLineText(0) - self.stNotice.SetLabel("") - - if newName == "": - self.stNotice.SetLabel("Invalid name.") - return - - sDP = service.DamagePattern.getInstance() - if self.btnSave.Label == "Create": - p = sDP.newPattern() - else: - # we are renaming, so get the current selection - p = self.getActivePattern() - - for pattern in self.choices: - if pattern.name == newName and p != pattern: - self.stNotice.SetLabel("Name already used, please choose another") - return - - sDP.renamePattern(p, newName) - - self.updateChoices(newName) - self.headerSizer.Replace(self.namePicker, self.ccDmgPattern) - self.ccDmgPattern.Show() - self.namePicker.Hide() - self.btnSave.Hide() - for btn in (self.new, self.rename, self.delete, self.copy): - btn.Show() - - sel = self.ccDmgPattern.GetSelection() - self.ccDmgPattern.Delete(sel) - self.ccDmgPattern.Insert(newName, sel) - self.ccDmgPattern.SetSelection(sel) - self.ValuesUpdated() - self.unrestrict() - - def copyPattern(self,event): - sDP = service.DamagePattern.getInstance() - p = sDP.copyPattern(self.getActivePattern()) - self.choices.append(p) - id = self.ccDmgPattern.Append(p.name) - self.ccDmgPattern.SetSelection(id) - self.btnSave.SetLabel("Copy") - self.renamePattern() - self.patternChanged() - - def deletePattern(self,event): - sDP = service.DamagePattern.getInstance() - sel = self.ccDmgPattern.GetSelection() - sDP.deletePattern(self.getActivePattern()) - self.ccDmgPattern.Delete(sel) - self.ccDmgPattern.SetSelection(max(0, sel - 1)) - del self.choices[sel] - self.patternChanged() - - def __del__( self ): + def __del__(self): pass - def updateChoices(self, select=None): - "Gathers list of patterns and updates choice selections" - sDP = service.DamagePattern.getInstance() - self.choices = sDP.getDamagePatternList() - - for dp in self.choices: - if dp.name == "Selected Ammo": # don't include this special butterfly - self.choices.remove(dp) - - # Sort the remaining list and continue on - self.choices.sort(key=lambda p: p.name) - self.ccDmgPattern.Clear() - - for i, choice in enumerate(map(lambda p: p.name, self.choices)): - self.ccDmgPattern.Append(choice) - - if select is not None and choice == select: - self.ccDmgPattern.SetSelection(i) - - if select is None: - self.ccDmgPattern.SetSelection(0) - self.patternChanged() - def importPatterns(self, event): text = fromClipboard() if text: @@ -384,3 +271,6 @@ class DmgPatternEditorDlg(wx.Dialog): sDP = service.DamagePattern.getInstance() toClipboard( sDP.exportPatterns() ) self.stNotice.SetLabel("Patterns exported to clipboard") + + def contextChanged(self, event): + print "lol" \ No newline at end of file diff --git a/service/damagePattern.py b/service/damagePattern.py index 374940e0c..b67b10956 100644 --- a/service/damagePattern.py +++ b/service/damagePattern.py @@ -46,9 +46,10 @@ class DamagePattern(): def getDamagePattern(self, name): return eos.db.getDamagePattern(name) - def newPattern(self): + def newPattern(self, name): p = eos.types.DamagePattern(0, 0, 0, 0) - p.name = "" + p.name = name + eos.db.save(p) return p def renamePattern(self, p, newName): From 3315d27d45404915b6996a8c8d5d34a3bcffe981 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sun, 27 Mar 2016 22:12:59 -0400 Subject: [PATCH 2/5] Applied entity editor to resist editor. Fixed issue with checking for same name in validator. Center dialogs on parents to make it look nicer --- gui/builtinViews/entityEditor.py | 4 + gui/patternEditor.py | 8 +- gui/resistsEditor.py | 272 +++++++------------------------ service/targetResists.py | 5 +- 4 files changed, 71 insertions(+), 218 deletions(-) diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py index 7eb439fb1..e7eb11771 100644 --- a/gui/builtinViews/entityEditor.py +++ b/gui/builtinViews/entityEditor.py @@ -92,6 +92,7 @@ class EntityEditor (wx.Panel): dlg = TextEntryValidatedDialog(self, self.validator, "Enter a name for your new {}:".format(self.entityName), "New {}".format(self.entityName)) + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: new = self.DoNew(dlg.GetValue().strip()) @@ -105,6 +106,7 @@ class EntityEditor (wx.Panel): active = self.getActiveEntity() dlg.SetValue("{} Copy".format(active.name)) dlg.txtctrl.SetInsertionPointEnd() + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: copy = self.DoCopy(active, dlg.GetValue().strip()) @@ -118,6 +120,7 @@ class EntityEditor (wx.Panel): active = self.getActiveEntity() dlg.SetValue(active.name) dlg.txtctrl.SetInsertionPointEnd() + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: self.DoRename(active, dlg.GetValue().strip()) @@ -128,6 +131,7 @@ class EntityEditor (wx.Panel): dlg = wx.MessageDialog(self, "Do you really want to delete the {} {}?".format(self.getActiveEntity().name, self.entityName), "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION) + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_YES: self.DoDelete(self.getActiveEntity()) diff --git a/gui/patternEditor.py b/gui/patternEditor.py index 88f24c17c..92454d750 100644 --- a/gui/patternEditor.py +++ b/gui/patternEditor.py @@ -43,7 +43,7 @@ class DmgPatternTextValidor(BaseValidator): try: if len(text) == 0: raise ValueError("You must supply a name for your Damage Profile!") - elif text in [x.name for x in profileEditor.choices]: + elif text in [x.name for x in profileEditor.entityEditor.choices]: raise ValueError("Damage Profile name already in use, please choose another.") return True @@ -59,7 +59,6 @@ class DmgPatternEntityEditor(EntityEditor): self.SetEditorValidator(DmgPatternTextValidor) def getEntitiesFromContext(self): - """ Gets list of entities from current context """ sDP = service.DamagePattern.getInstance() choices = sorted(sDP.getDamagePatternList(), key=lambda p: p.name) return [c for c in choices if c.name != "Selected Ammo"] @@ -93,10 +92,6 @@ class DmgPatternEditorDlg(wx.Dialog): mainSizer = wx.BoxSizer(wx.VERTICAL) - sDP = service.DamagePattern.getInstance() - - self.choices = sDP.getDamagePatternList() - self.entityEditor = DmgPatternEntityEditor(self) mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2) @@ -186,6 +181,7 @@ class DmgPatternEditorDlg(wx.Dialog): self.Layout() bsize = self.GetBestSize() self.SetSize((-1, bsize.height)) + self.CenterOnParent() self.Bind(wx.EVT_CHOICE, self.patternChanged) diff --git a/gui/resistsEditor.py b/gui/resistsEditor.py index 3d8ac6ef2..57b438dc5 100644 --- a/gui/resistsEditor.py +++ b/gui/resistsEditor.py @@ -22,6 +22,61 @@ from gui.bitmapLoader import BitmapLoader import service from gui.utils.clipboard import toClipboard, fromClipboard from service.targetResists import ImportError +from gui.builtinViews.entityEditor import EntityEditor, BaseValidator + + +class TargetResistsTextValidor(BaseValidator): + def __init__(self): + BaseValidator.__init__(self) + + def Clone(self): + return TargetResistsTextValidor() + + def Validate(self, win): + profileEditor = win.Parent + textCtrl = self.GetWindow() + text = textCtrl.GetValue().strip() + + try: + if len(text) == 0: + raise ValueError("You must supply a name for your Target Resist Profile!") + elif text in [x.name for x in profileEditor.entityEditor.choices]: + raise ValueError("Target Resist Profile name already in use, please choose another.") + + return True + except ValueError, e: + wx.MessageBox(u"{}".format(e), "Error") + textCtrl.SetFocus() + return False + + +class TargetResistsEntityEditor(EntityEditor): + def __init__(self, parent): + EntityEditor.__init__(self, parent, "Target Resist Profile") + self.SetEditorValidator(TargetResistsTextValidor) + + def getEntitiesFromContext(self): + sTR = service.TargetResists.getInstance() + choices = sorted(sTR.getTargetResistsList(), key=lambda p: p.name) + return choices + + def DoNew(self, name): + sTR = service.TargetResists.getInstance() + return sTR.newPattern(name) + + def DoRename(self, entity, name): + sTR = service.TargetResists.getInstance() + sTR.renamePattern(entity, name) + + def DoCopy(self, entity, name): + sTR = service.TargetResists.getInstance() + copy = sTR.copyPattern(entity) + sTR.renamePattern(copy, name) + return copy + + def DoDelete(self, entity): + sTR = service.TargetResists.getInstance() + sTR.deletePattern(entity) class ResistsEditorDlg(wx.Dialog): @@ -35,51 +90,8 @@ class ResistsEditorDlg(wx.Dialog): mainSizer = wx.BoxSizer(wx.VERTICAL) - self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL) - - sTR = service.TargetResists.getInstance() - - self.choices = sTR.getTargetResistsList() - - # Sort the remaining list and continue on - self.choices.sort(key=lambda p: p.name) - self.ccResists = wx.Choice(self, choices=map(lambda p: p.name, self.choices)) - self.ccResists.Bind(wx.EVT_CHOICE, self.patternChanged) - self.ccResists.SetSelection(0) - - self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) - self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename) - self.namePicker.Hide() - - size = None - headerSizer.Add(self.ccResists, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3) - - buttons = (("new", wx.ART_NEW), - ("rename", BitmapLoader.getBitmap("rename", "gui")), - ("copy", wx.ART_COPY), - ("delete", wx.ART_DELETE)) - for name, art in buttons: - bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art - btn = wx.BitmapButton(self, wx.ID_ANY, bitmap) - if size is None: - size = btn.GetSize() - - btn.SetMinSize(size) - btn.SetMaxSize(size) - - btn.Layout() - setattr(self, name, btn) - btn.Enable(True) - btn.SetToolTipString("%s resist profile" % name.capitalize()) - headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL) - - - self.btnSave = wx.Button(self, wx.ID_SAVE) - self.btnSave.Hide() - self.btnSave.Bind(wx.EVT_BUTTON, self.processRename) - headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER) - - mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2) + self.entityEditor = TargetResistsEntityEditor(self) + mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2) self.sl = wx.StaticLine(self) mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) @@ -159,14 +171,10 @@ class ResistsEditorDlg(wx.Dialog): self.Layout() bsize = self.GetBestSize() - self.SetSize((-1,bsize.height)) + self.SetSize((-1, bsize.height)) + self.CenterOnParent() - self.new.Bind(wx.EVT_BUTTON, self.newPattern) - self.rename.Bind(wx.EVT_BUTTON, self.renamePattern) - self.copy.Bind(wx.EVT_BUTTON, self.copyPattern) - self.delete.Bind(wx.EVT_BUTTON, self.deletePattern) - self.Import.Bind(wx.EVT_BUTTON, self.importPatterns) - self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns) + self.Bind(wx.EVT_CHOICE, self.patternChanged) self.patternChanged() @@ -184,7 +192,7 @@ class ResistsEditorDlg(wx.Dialog): return try: - p = self.getActivePattern() + p = self.entityEditor.getActiveEntity() for type in self.DAMAGE_TYPES: editObj = getattr(self, "%sEdit"%type) @@ -220,33 +228,10 @@ class ResistsEditorDlg(wx.Dialog): finally: # Refresh for color changes to take effect immediately self.Refresh() - def restrict(self): - for type in self.DAMAGE_TYPES: - editObj = getattr(self, "%sEdit"%type) - editObj.Enable(False) - self.rename.Enable(False) - self.delete.Enable(False) - - def unrestrict(self): - for type in self.DAMAGE_TYPES: - editObj = getattr(self, "%sEdit"%type) - editObj.Enable() - self.rename.Enable() - self.delete.Enable() - - def getActivePattern(self): - if len(self.choices) == 0: - return None - - return self.choices[self.ccResists.GetSelection()] - def patternChanged(self, event=None): "Event fired when user selects pattern. Can also be called from script" - p = self.getActivePattern() + p = self.entityEditor.getActiveEntity() if p is None: - # This happens when there are no patterns in the DB. As such, force - # user to create one first or exit dlg. - self.newPattern(None) return self.block = True @@ -259,142 +244,9 @@ class ResistsEditorDlg(wx.Dialog): self.block = False self.ValuesUpdated() - def newPattern(self, event): - ''' - Simply does new-pattern specifics: replaces label on button, restricts, - and resets values to default. Hands off to the rename function for - further handling. - ''' - self.btnSave.SetLabel("Create") - self.restrict() - # reset values - for type in self.DAMAGE_TYPES: - editObj = getattr(self, "%sEdit"%type) - editObj.ChangeValue("0.0") - editObj.SetForegroundColour(self.colorReset) - - self.Refresh() - self.renamePattern() - - def renamePattern(self, event=None): - "Changes layout to facilitate naming a pattern" - - self.showInput(True) - - if event is not None: # Rename mode - self.btnSave.SetLabel("Rename") - self.namePicker.SetValue(self.getActivePattern().name) - else: # Create mode - self.namePicker.SetValue("") - - if event is not None: - event.Skip() - - def processRename(self, event): - ''' - Processes rename event (which can be new or old patterns). If new - pattern, creates it; if old, selects it. if checks are valid, rename - saves pattern to DB. - - Also resets to default layout and unrestricts. - ''' - newName = self.namePicker.GetLineText(0) - self.stNotice.SetLabel("") - - if newName == "": - self.stNotice.SetLabel("Invalid name") - return - - sTR = service.TargetResists.getInstance() - if self.btnSave.Label == "Create": - p = sTR.newPattern() - else: - # we are renaming, so get the current selection - p = self.getActivePattern() - - # test for patterns of the same name - for pattern in self.choices: - if pattern.name == newName and p != pattern: - self.stNotice.SetLabel("Name already used, please choose another") - return - - # rename regardless of new or rename - sTR.renamePattern(p, newName) - - self.updateChoices(newName) - self.showInput(False) - sel = self.ccResists.GetSelection() - self.ValuesUpdated() - self.unrestrict() - - def copyPattern(self,event): - sTR = service.TargetResists.getInstance() - p = sTR.copyPattern(self.getActivePattern()) - self.choices.append(p) - id = self.ccResists.Append(p.name) - self.ccResists.SetSelection(id) - self.btnSave.SetLabel("Copy") - self.renamePattern() - self.patternChanged() - - def deletePattern(self,event): - sTR = service.TargetResists.getInstance() - sel = self.ccResists.GetSelection() - sTR.deletePattern(self.getActivePattern()) - self.ccResists.Delete(sel) - self.ccResists.SetSelection(max(0, sel - 1)) - del self.choices[sel] - self.patternChanged() - - def showInput(self, bool): - if bool and not self.namePicker.IsShown(): - self.ccResists.Hide() - self.namePicker.Show() - self.headerSizer.Replace(self.ccResists, self.namePicker) - self.namePicker.SetFocus() - for btn in (self.new, self.rename, self.delete, self.copy): - btn.Hide() - self.btnSave.Show() - self.restrict() - self.headerSizer.Layout() - elif not bool and self.namePicker.IsShown(): - self.headerSizer.Replace(self.namePicker, self.ccResists) - self.ccResists.Show() - self.namePicker.Hide() - self.btnSave.Hide() - for btn in (self.new, self.rename, self.delete, self.copy): - btn.Show() - self.unrestrict() - self.headerSizer.Layout() - - def __del__( self ): pass - def updateChoices(self, select=None): - "Gathers list of patterns and updates choice selections" - sTR = service.TargetResists.getInstance() - self.choices = sTR.getTargetResistsList() - - if len(self.choices) == 0: - #self.newPattern(None) - return - - # Sort the remaining list and continue on - self.choices.sort(key=lambda p: p.name) - self.ccResists.Clear() - - for i, choice in enumerate(map(lambda p: p.name, self.choices)): - self.ccResists.Append(choice) - - if select is not None and choice == select: - self.ccResists.SetSelection(i) - - if select is None: - self.ccResists.SetSelection(0) - - self.patternChanged() - def importPatterns(self, event): "Event fired when import from clipboard button is clicked" diff --git a/service/targetResists.py b/service/targetResists.py index a8f61b9f9..2640551f4 100644 --- a/service/targetResists.py +++ b/service/targetResists.py @@ -39,9 +39,10 @@ class TargetResists(): def getTargetResists(self, name): return eos.db.getTargetResists(name) - def newPattern(self): + def newPattern(self, name): p = eos.types.TargetResists(0.0, 0.0, 0.0, 0.0) - p.name = "" + p.name = name + eos.db.save(p) return p def renamePattern(self, p, newName): From a3d9d5cca8e30d389be6498599e96fefffa5df83 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 28 Mar 2016 21:23:27 -0400 Subject: [PATCH 3/5] Migrate character editor to use new entity editor. --- eos/db/saveddata/character.py | 1 + eos/db/saveddata/queries.py | 2 +- eos/saveddata/character.py | 10 +- gui/builtinViews/entityEditor.py | 5 +- gui/builtinViews/implantEditor.py | 4 +- gui/characterEditor.py | 354 +++++++++++++----------------- gui/characterSelection.py | 6 +- gui/gangView.py | 5 +- service/character.py | 38 ++-- 9 files changed, 194 insertions(+), 231 deletions(-) diff --git a/eos/db/saveddata/character.py b/eos/db/saveddata/character.py index f3d4d1e13..e6be52535 100644 --- a/eos/db/saveddata/character.py +++ b/eos/db/saveddata/character.py @@ -37,6 +37,7 @@ characters_table = Table("characters", saveddata_meta, mapper(Character, characters_table, properties = { + "savedName": characters_table.c.name, "_Character__owner": relation( User, backref = "characters"), diff --git a/eos/db/saveddata/queries.py b/eos/db/saveddata/queries.py index de813ee1c..5a6dd1bfc 100644 --- a/eos/db/saveddata/queries.py +++ b/eos/db/saveddata/queries.py @@ -154,7 +154,7 @@ def getCharacter(lookfor, eager=None): elif isinstance(lookfor, basestring): eager = processEager(eager) with sd_lock: - character = saveddata_session.query(Character).options(*eager).filter(Character.name == lookfor).first() + character = saveddata_session.query(Character).options(*eager).filter(Character.savedName == lookfor).first() else: raise TypeError("Need integer or string as argument") return character diff --git a/eos/saveddata/character.py b/eos/saveddata/character.py index 902e17da8..24fa08694 100644 --- a/eos/saveddata/character.py +++ b/eos/saveddata/character.py @@ -90,7 +90,7 @@ class Character(object): return all0 def __init__(self, name, defaultLevel=None, initSkills=True): - self.name = name + self.savedName = name self.__owner = None self.defaultLevel = defaultLevel self.__skills = [] @@ -129,6 +129,14 @@ class Character(object): def owner(self, owner): self.__owner = owner + @property + def name(self): + return self.savedName if not self.isDirty else "{} *".format(self.savedName) + + @name.setter + def name(self, name): + self.savedName = name + @property def skills(self): return self.__skills diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py index e7eb11771..acba2b28b 100644 --- a/gui/builtinViews/entityEditor.py +++ b/gui/builtinViews/entityEditor.py @@ -152,4 +152,7 @@ class EntityEditor (wx.Panel): if len(self.choices) == 0: return None - return self.choices[self.entityChoices.GetSelection()] \ No newline at end of file + return self.choices[self.entityChoices.GetSelection()] + + def setActiveEntity(self, entity): + self.entityChoices.SetSelection(self.choices.index(entity)) \ No newline at end of file diff --git a/gui/builtinViews/implantEditor.py b/gui/builtinViews/implantEditor.py index f12b5fcc1..bcdb96c7b 100644 --- a/gui/builtinViews/implantEditor.py +++ b/gui/builtinViews/implantEditor.py @@ -110,7 +110,7 @@ class BaseImplantEditorView (wx.Panel): """ Adds implant to the current context""" raise NotImplementedError() - def removeImplantFromContext(self, pos): + def removeImplantFromContext(self, implant): """ Removes implant from the current context""" raise NotImplementedError() @@ -191,7 +191,7 @@ class BaseImplantEditorView (wx.Panel): def removeItem(self, event): pos = self.pluggedImplantsTree.GetFirstSelected() if pos != -1: - self.removeImplantFromContext(pos) + self.removeImplantFromContext(self.implants[pos]) self.update() class AvailableImplantsView(d.Display): diff --git a/gui/characterEditor.py b/gui/characterEditor.py index 4be9fc5ee..72fc0a333 100644 --- a/gui/characterEditor.py +++ b/gui/characterEditor.py @@ -26,6 +26,73 @@ import service from gui.contextMenu import ContextMenu import gui.globalEvents as GE from gui.builtinViews.implantEditor import BaseImplantEditorView +from gui.builtinViews.entityEditor import EntityEditor, BaseValidator + + +class CharacterTextValidor(BaseValidator): + def __init__(self): + BaseValidator.__init__(self) + + def Clone(self): + return CharacterTextValidor() + + def Validate(self, win): + profileEditor = win.Parent + textCtrl = self.GetWindow() + text = textCtrl.GetValue().strip() + + try: + if len(text) == 0: + raise ValueError("You must supply a name for the Character!") + elif text in [x.name for x in profileEditor.entityEditor.choices]: + raise ValueError("Character name already in use, please choose another.") + + return True + except ValueError, e: + wx.MessageBox(u"{}".format(e), "Error") + textCtrl.SetFocus() + return False + + +class CharacterEntityEditor(EntityEditor): + def __init__(self, parent): + EntityEditor.__init__(self, parent, "Character") + self.SetEditorValidator(CharacterTextValidor) + + def getEntitiesFromContext(self): + sChar = service.Character.getInstance() + charList = sorted(sChar.getCharacterList(), key=lambda c: c.name) + + # Do some processing to ensure that we have All 0 and All 5 at the top + all5 = sChar.all5() + all0 = sChar.all0() + + charList.remove(all5) + charList.remove(all0) + + charList.insert(0, all5) + charList.insert(0, all0) + + return charList + + def DoNew(self, name): + sChar = service.Character.getInstance() + return sChar.new(name) + + def DoRename(self, entity, name): + sChar = service.Character.getInstance() + sChar.rename(entity, name) + + def DoCopy(self, entity, name): + sChar = service.Character.getInstance() + copy = sChar.copy(entity) + sChar.rename(copy, name) + return copy + + def DoDelete(self, entity): + sChar = service.Character.getInstance() + sChar.delete(entity) + class CharacterEditor(wx.Frame): def __init__(self, parent): @@ -37,57 +104,16 @@ class CharacterEditor(wx.Frame): self.mainFrame = parent #self.disableWin = wx.WindowDisabler(self) + sFit = service.Fit.getInstance() - self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) ) + self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) mainSizer = wx.BoxSizer(wx.VERTICAL) - self.navSizer = wx.BoxSizer(wx.HORIZONTAL) - sChar = service.Character.getInstance() - - self.btnSave = wx.Button(self, wx.ID_SAVE) - self.btnSave.Hide() - self.btnSave.Bind(wx.EVT_BUTTON, self.processRename) - - self.characterRename = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER) - self.characterRename.Hide() - self.characterRename.Bind(wx.EVT_TEXT_ENTER, self.processRename) - - self.charChoice = wx.Choice(self, wx.ID_ANY, style=0) - self.navSizer.Add(self.charChoice, 1, wx.ALL | wx.EXPAND, 5) - - charList = sChar.getCharacterList() - - for id, name, active in charList: - i = self.charChoice.Append(name, id) - if active: - self.charChoice.SetSelection(i) - - self.navSizer.Add(self.btnSave, 0, wx.ALL , 5) - - - buttons = (("new", wx.ART_NEW), - ("rename", BitmapLoader.getBitmap("rename", "gui")), - ("copy", wx.ART_COPY), - ("delete", wx.ART_DELETE)) - - size = None - for name, art in buttons: - bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art - btn = wx.BitmapButton(self, wx.ID_ANY, bitmap) - if size is None: - size = btn.GetSize() - - btn.SetMinSize(size) - btn.SetMaxSize(size) - - btn.SetToolTipString("%s character" % name.capitalize()) - btn.Bind(wx.EVT_BUTTON, getattr(self, name)) - setattr(self, "btn%s" % name.capitalize(), btn) - self.navSizer.Add(btn, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2) - - - mainSizer.Add(self.navSizer, 0, wx.ALL | wx.EXPAND, 5) + self.entityEditor = CharacterEntityEditor(self) + mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2) + # Default drop down to current fit's character + self.entityEditor.setActiveEntity(sFit.character) self.viewsNBContainer = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0) @@ -114,7 +140,6 @@ class CharacterEditor(wx.Frame): bSizerButtons.AddStretchSpacer() bSizerButtons.Add(self.btnOK, 0, wx.ALL, 5) - self.btnSaveChar.Bind(wx.EVT_BUTTON, self.saveChar) self.btnSaveAs.Bind(wx.EVT_BUTTON, self.saveCharAs) self.btnRevert.Bind(wx.EVT_BUTTON, self.revertChar) @@ -129,16 +154,12 @@ class CharacterEditor(wx.Frame): self.Centre(wx.BOTH) - charID = self.getActiveCharacter() - if sChar.getCharName(charID) in ("All 0", "All 5"): - self.restrict() - - self.registerEvents() + self.Bind(wx.EVT_CLOSE, self.closeEvent) + self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList) + self.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged) def btnRestrict(self): - sChar = service.Character.getInstance() - charID = self.getActiveCharacter() - char = sChar.getCharacter(charID) + char = self.entityEditor.getActiveEntity() # enable/disable character saving stuff self.btnSaveChar.Enable(not char.ro and char.isDirty) @@ -146,46 +167,34 @@ class CharacterEditor(wx.Frame): self.btnRevert.Enable(char.isDirty) def refreshCharacterList(self, event=None): - sChar = service.Character.getInstance() - charList = sChar.getCharacterList() - active = self.getActiveCharacter() - self.charChoice.Clear() - - for id, name, _ in charList: - i = self.charChoice.Append(name, id) - if active == id: - self.charChoice.SetSelection(i) - + """This is only called when we save a modified character""" + active = self.entityEditor.getActiveEntity() + self.entityEditor.refreshEntityList(active) self.btnRestrict() + if event: + event.Skip() + def editingFinished(self, event): #del self.disableWin wx.PostEvent(self.mainFrame, GE.CharListUpdated()) self.Destroy() - def registerEvents(self): - self.Bind(wx.EVT_CLOSE, self.closeEvent) - self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList) - self.charChoice.Bind(wx.EVT_CHOICE, self.charChanged) - def saveChar(self, event): sChr = service.Character.getInstance() - charID = self.getActiveCharacter() - sChr.saveCharacter(charID) - self.sview.populateSkillTree() + char = self.entityEditor.getActiveEntity() + sChr.saveCharacter(char.ID) wx.PostEvent(self, GE.CharListUpdated()) def saveCharAs(self, event): - charID = self.getActiveCharacter() - dlg = SaveCharacterAs(self, charID) + char = self.entityEditor.getActiveEntity() + dlg = SaveCharacterAs(self, char.ID) dlg.ShowModal() - self.sview.populateSkillTree() def revertChar(self, event): sChr = service.Character.getInstance() - charID = self.getActiveCharacter() - sChr.revertCharacter(charID) - self.sview.populateSkillTree() + char = self.entityEditor.getActiveEntity() + sChr.revertCharacter(char.ID) wx.PostEvent(self, GE.CharListUpdated()) def closeEvent(self, event): @@ -194,109 +203,25 @@ class CharacterEditor(wx.Frame): self.Destroy() def restrict(self): - self.btnRename.Enable(False) - self.btnDelete.Enable(False) - self.iview.Enable(False) - self.aview.Enable(False) + self.entityEditor.btnRename.Enable(False) + self.entityEditor.btnDelete.Enable(False) def unrestrict(self): - self.btnRename.Enable(True) - self.btnDelete.Enable(True) - self.iview.Enable(True) - self.aview.Enable(True) + self.entityEditor.btnRename.Enable() + self.entityEditor.btnDelete.Enable() def charChanged(self, event): - self.sview.populateSkillTree() - sChar = service.Character.getInstance() - charID = self.getActiveCharacter() - if sChar.getCharName(charID) in ("All 0", "All 5"): + char = self.entityEditor.getActiveEntity() + if char.name in ("All 0", "All 5"): self.restrict() else: self.unrestrict() - wx.PostEvent(self, GE.CharChanged()) + self.btnRestrict() + if event is not None: event.Skip() - def getActiveCharacter(self): - selection = self.charChoice.GetCurrentSelection() - return self.charChoice.GetClientData(selection) if selection is not None else None - - def new(self, event): - sChar = service.Character.getInstance() - charID = sChar.new() - id = self.charChoice.Append(sChar.getCharName(charID), charID) - self.charChoice.SetSelection(id) - self.unrestrict() - self.btnSave.SetLabel("Create") - self.rename(None) - self.charChanged(None) - - def rename(self, event): - if event is not None: - self.btnSave.SetLabel("Rename") - self.charChoice.Hide() - self.characterRename.Show() - self.navSizer.Replace(self.charChoice, self.characterRename) - self.characterRename.SetFocus() - for btn in (self.btnNew, self.btnCopy, self.btnRename, self.btnDelete): - btn.Hide() - - self.btnSave.Show() - self.navSizer.Layout() - - sChar = service.Character.getInstance() - currName = sChar.getCharName(self.getActiveCharacter()) - self.characterRename.SetValue(currName) - self.characterRename.SetSelection(0, len(currName)) - - def processRename(self, event): - sChar = service.Character.getInstance() - newName = self.characterRename.GetLineText(0) - - if newName == "All 0" or newName == "All 5": - newName = newName + " bases are belong to us" - - charID = self.getActiveCharacter() - sChar.rename(charID, newName) - - self.charChoice.Show() - self.characterRename.Hide() - self.navSizer.Replace(self.characterRename, self.charChoice) - for btn in (self.btnNew, self.btnCopy, self.btnRename, self.btnDelete): - btn.Show() - - self.btnSave.Hide() - self.navSizer.Layout() - self.refreshCharacterList() - - def copy(self, event): - sChar = service.Character.getInstance() - charID = sChar.copy(self.getActiveCharacter()) - id = self.charChoice.Append(sChar.getCharName(charID), charID) - self.charChoice.SetSelection(id) - self.unrestrict() - self.btnSave.SetLabel("Copy") - self.rename(None) - wx.PostEvent(self, GE.CharChanged()) - - def delete(self, event): - dlg = wx.MessageDialog(self, - "Do you really want to delete this character?", - "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION) - - if dlg.ShowModal() == wx.ID_YES: - sChar = service.Character.getInstance() - sChar.delete(self.getActiveCharacter()) - sel = self.charChoice.GetSelection() - self.charChoice.Delete(sel) - self.charChoice.SetSelection(sel - 1) - newSelection = self.getActiveCharacter() - if sChar.getCharName(newSelection) in ("All 0", "All 5"): - self.restrict() - - wx.PostEvent(self, GE.CharChanged()) - def Destroy(self): sFit = service.Fit.getInstance() fitID = self.mainFrame.getActiveFit() @@ -308,7 +233,8 @@ class CharacterEditor(wx.Frame): class SkillTreeView (wx.Panel): def __init__(self, parent): - wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL) + wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL) + self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) pmainSizer = wx.BoxSizer(wx.VERTICAL) @@ -335,6 +261,10 @@ class SkillTreeView (wx.Panel): tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup) tree.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.scheduleMenu) + # bind the Character selection event + self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.populateSkillTree) + self.charEditor.Bind(GE.CHAR_LIST_UPDATED, self.populateSkillTree) + srcContext = "skillItem" itemContext = "Skill" context = (srcContext, itemContext) @@ -365,11 +295,10 @@ class SkillTreeView (wx.Panel): self.Layout() - def populateSkillTree(self): + def populateSkillTree(self, event=None): sChar = service.Character.getInstance() - charID = self.Parent.Parent.getActiveCharacter() - dirtySkills = sChar.getDirtySkills(charID) - dirtyGroups = set([skill.item.group.ID for skill in dirtySkills]) + char = self.charEditor.entityEditor.getActiveEntity() + dirtyGroups = set([skill.item.group.ID for skill in char.dirtySkills]) groups = sChar.getSkillGroups() imageId = self.skillBookImageId @@ -386,6 +315,9 @@ class SkillTreeView (wx.Panel): tree.SortChildren(root) + if event: + event.Skip() + def expandLookup(self, event): root = event.Item tree = self.skillTreeListCtrl @@ -395,11 +327,11 @@ class SkillTreeView (wx.Panel): #Get the real intrestin' stuff sChar = service.Character.getInstance() - char = self.Parent.Parent.getActiveCharacter() + char = self.charEditor.entityEditor.getActiveEntity() for id, name in sChar.getSkills(tree.GetPyData(root)): iconId = self.skillBookImageId childId = tree.AppendItem(root, name, iconId, data=wx.TreeItemData(id)) - level, dirty = sChar.getSkillLevel(char, id) + level, dirty = sChar.getSkillLevel(char.ID, id) tree.SetItemText(childId, "Level %d" % level if isinstance(level, int) else level, 1) if dirty: tree.SetItemTextColour(childId, wx.BLUE) @@ -415,10 +347,9 @@ class SkillTreeView (wx.Panel): if self.skillTreeListCtrl.GetChildrenCount(item) > 0: return - sChar = service.Character.getInstance() - charID = self.Parent.Parent.getActiveCharacter() + char = self.charEditor.entityEditor.getActiveEntity() sMkt = service.Market.getInstance() - if sChar.getCharName(charID) not in ("All 0", "All 5"): + if char.name not in ("All 0", "All 5"): self.levelChangeMenu.selection = sMkt.getItem(self.skillTreeListCtrl.GetPyData(item)) self.PopupMenu(self.levelChangeMenu) else: @@ -429,21 +360,21 @@ class SkillTreeView (wx.Panel): level = self.levelIds.get(event.Id) sChar = service.Character.getInstance() - charID = self.Parent.Parent.getActiveCharacter() + char = self.charEditor.entityEditor.getActiveEntity() selection = self.skillTreeListCtrl.GetSelection() skillID = self.skillTreeListCtrl.GetPyData(selection) if level is not None: self.skillTreeListCtrl.SetItemText(selection, "Level %d" % level if isinstance(level, int) else level, 1) - sChar.changeLevel(charID, skillID, level, persist=True) + sChar.changeLevel(char.ID, skillID, level, persist=True) elif event.Id == self.revertID: - sChar.revertLevel(charID, skillID) + sChar.revertLevel(char.ID, skillID) elif event.Id == self.saveID: - sChar.saveSkill(charID, skillID) + sChar.saveSkill(char.ID, skillID) self.skillTreeListCtrl.SetItemTextColour(selection, None) - dirtySkills = sChar.getDirtySkills(charID) + dirtySkills = sChar.getDirtySkills(char.ID) dirtyGroups = set([skill.item.group.ID for skill in dirtySkills]) parentID = self.skillTreeListCtrl.GetItemParent(selection) @@ -452,7 +383,6 @@ class SkillTreeView (wx.Panel): if groupID not in dirtyGroups: self.skillTreeListCtrl.SetItemTextColour(parentID, None) - wx.PostEvent(self.Parent.Parent, GE.CharListUpdated()) event.Skip() @@ -460,31 +390,37 @@ class ImplantEditorView(BaseImplantEditorView): def __init__(self, parent): BaseImplantEditorView.__init__ (self, parent) - if "__WXGTK__" in wx.PlatformInfo: + self.determineEnabled() + + if "__WXGTK__" in wx.PlatformInfo: self.pluggedImplantsTree.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu) else: self.pluggedImplantsTree.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu) def bindContext(self): - self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.contextChanged) + self.Parent.Parent.entityEditor.Bind(wx.EVT_CHOICE, self.contextChanged) + + def contextChanged(self, event): + BaseImplantEditorView.contextChanged(self, event) + self.determineEnabled() def getImplantsFromContext(self): sChar = service.Character.getInstance() - charID = self.Parent.Parent.getActiveCharacter() + char = self.Parent.Parent.entityEditor.getActiveEntity() - return sChar.getImplants(charID) + return sChar.getImplants(char.ID) def addImplantToContext(self, item): sChar = service.Character.getInstance() - charID = self.Parent.Parent.getActiveCharacter() + char = self.Parent.Parent.entityEditor.getActiveEntity() - sChar.addImplant(charID, item.ID) + sChar.addImplant(char.ID, item.ID) - def removeImplantFromContext(self, pos): + def removeImplantFromContext(self, implant): sChar = service.Character.getInstance() - charID = self.Parent.Parent.getActiveCharacter() + char = self.Parent.Parent.entityEditor.getActiveEntity() - sChar.removeImplant(charID, self.implants[pos]) + sChar.removeImplant(char.ID, implant) def scheduleMenu(self, event): event.Skip() @@ -497,11 +433,19 @@ class ImplantEditorView(BaseImplantEditorView): menu = ContextMenu.getMenu((self.Parent.Parent,), *context) self.PopupMenu(menu) + def determineEnabled(self): + char = self.Parent.Parent.entityEditor.getActiveEntity() + + if char.name in ("All 0", "All 5"): + self.Enable(False) + else: + self.Enable() + class APIView (wx.Panel): def __init__(self, parent): wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL) - self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.charChanged) + self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) self.apiUrlCreatePredefined = u"https://community.eveonline.com/support/api-key/CreatePredefined?accessMask=8" @@ -585,13 +529,17 @@ class APIView (wx.Panel): self.hlEveAPI2 = wx.HyperlinkCtrl( self, wx.ID_ANY, self.apiUrlKeyList, self.apiUrlKeyList, wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE ) pmainSizer.Add( self.hlEveAPI2, 0, wx.ALL, 2 ) + self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged) + self.SetSizer(pmainSizer) self.Layout() self.charChanged(None) def charChanged(self, event): sChar = service.Character.getInstance() - ID, key, char, chars = sChar.getApiDetails(self.Parent.Parent.getActiveCharacter()) + activeChar = self.charEditor.entityEditor.getActiveEntity() + + ID, key, char, chars = sChar.getApiDetails(activeChar.ID) self.inputID.SetValue(str(ID)) self.inputKey.SetValue(key) @@ -609,6 +557,14 @@ class APIView (wx.Panel): self.charChoice.Enable(False) self.btnFetchSkills.Enable(False) + if activeChar.name in ("All 0", "All 5"): + self.Enable(False) + self.stDisabledTip.Show() + self.Layout() + else: + self.Enable() + self.stDisabledTip.Hide() + self.Layout() if event is not None: event.Skip() diff --git a/gui/characterSelection.py b/gui/characterSelection.py index 990dc8bf5..47df7e018 100644 --- a/gui/characterSelection.py +++ b/gui/characterSelection.py @@ -83,9 +83,9 @@ class CharacterSelection(wx.Panel): charList = sChar.getCharacterList() picked = False - for id, name, active in charList: - currId = choice.Append(name, id) - if id == activeChar: + for char in charList: + currId = choice.Append(char.name, char.ID) + if char.ID == activeChar: choice.SetSelection(currId) self.charChanged(None) picked = True diff --git a/gui/gangView.py b/gui/gangView.py index 2e6d7b1da..25a457301 100644 --- a/gui/gangView.py +++ b/gui/gangView.py @@ -346,9 +346,8 @@ class GangView ( ScrolledPanel ): choice.Clear() currSelFound = False for char in charList: - id,name,_ = char - choice.Append(name, id) - if chCurrData == id: + choice.Append(char.name, char.ID) + if chCurrData == char.ID: currSelFound = True if chCurrSelection == -1: diff --git a/service/character.py b/service/character.py index 6078ccd8a..a4d68c98a 100644 --- a/service/character.py +++ b/service/character.py @@ -50,9 +50,8 @@ class CharacterImportThread(threading.Thread): # we try to parse api XML data first with open(path, mode='r') as charFile: sheet = service.ParseXML(charFile) - charID = sCharacter.new() - sCharacter.rename(charID, sheet.name+" (imported)") - sCharacter.apiUpdateCharSheet(charID, sheet.skills) + char = sCharacter.new(sheet.name+" (imported)") + sCharacter.apiUpdateCharSheet(char.ID, sheet.skills) except: # if it's not api XML data, try this # this is a horrible logic flow, but whatever @@ -69,9 +68,8 @@ class CharacterImportThread(threading.Thread): "typeID": int(skill.getAttribute("typeID")), "level": int(skill.getAttribute("level")), }) - charID = sCharacter.new() - sCharacter.rename(charID, name+" (EVEMon)") - sCharacter.apiUpdateCharSheet(charID, skills) + char = sCharacter.new(name+" (EVEMon)") + sCharacter.apiUpdateCharSheet(char.ID, skills) except: continue @@ -116,6 +114,11 @@ class Character(object): return cls.instance + def __init__(self): + # Simply initializes default characters in case they aren't in the database yet + self.all0() + self.all5() + def exportText(self): data = "Pyfa exported plan for \""+self.skillReqsDict['charname']+"\"\n" data += "=" * 79 + "\n" @@ -185,10 +188,7 @@ class Character(object): return self.all5().ID def getCharacterList(self): - baseChars = [eos.types.Character.getAll0(), eos.types.Character.getAll5()] - sFit = service.Fit.getInstance() - - return map(lambda c: (c.ID, c.name if not c.isDirty else "{} *".format(c.name), c == sFit.character), eos.db.getCharacterList()) + return eos.db.getCharacterList() def getCharacter(self, charID): char = eos.db.getCharacter(charID) @@ -248,25 +248,21 @@ class Character(object): def getCharName(self, charID): return eos.db.getCharacter(charID).name - def new(self): - char = eos.types.Character("New Character") + def new(self, name="New Character"): + char = eos.types.Character(name) eos.db.save(char) - return char.ID + return char - def rename(self, charID, newName): - char = eos.db.getCharacter(charID) + def rename(self, char, newName): char.name = newName eos.db.commit() - def copy(self, charID): - char = eos.db.getCharacter(charID) + def copy(self, char): newChar = copy.deepcopy(char) eos.db.save(newChar) - return newChar.ID + return newChar - def delete(self, charID): - char = eos.db.getCharacter(charID) - eos.db.commit() + def delete(self, char): eos.db.remove(char) def getApiDetails(self, charID): From 11610370921daf08225e8487cc1fe9ae4b634c91 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Tue, 29 Mar 2016 21:51:39 -0400 Subject: [PATCH 4/5] Migrate implant set editor to new entity editor --- gui/builtinViews/entityEditor.py | 6 +- gui/setEditor.py | 277 +++++++------------------------ service/implantSet.py | 9 +- 3 files changed, 70 insertions(+), 222 deletions(-) diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py index acba2b28b..faaf1e3bb 100644 --- a/gui/builtinViews/entityEditor.py +++ b/gui/builtinViews/entityEditor.py @@ -76,15 +76,15 @@ class EntityEditor (wx.Panel): """Override method to do new entity logic. Must return the new entity""" raise NotImplementedError() - def DoCopy(self, name): + def DoCopy(self, entity, name): """Override method to copy entity. Must return the copy""" raise NotImplementedError() - def DoRename(self, name): + def DoRename(self, entity, name): """Override method to rename an entity""" raise NotImplementedError() - def DoDelete(self, name): + def DoDelete(self, entity): """Override method to delete entity""" raise NotImplementedError() diff --git a/gui/setEditor.py b/gui/setEditor.py index 293ff5c76..3b283d601 100644 --- a/gui/setEditor.py +++ b/gui/setEditor.py @@ -24,9 +24,63 @@ import service from gui.utils.clipboard import toClipboard, fromClipboard from service.implantSet import ImportError import logging +from gui.builtinViews.entityEditor import EntityEditor, BaseValidator logger = logging.getLogger(__name__) +class ImplantTextValidor(BaseValidator): + def __init__(self): + BaseValidator.__init__(self) + + def Clone(self): + return ImplantTextValidor() + + def Validate(self, win): + profileEditor = win.Parent + textCtrl = self.GetWindow() + text = textCtrl.GetValue().strip() + + try: + if len(text) == 0: + raise ValueError("You must supply a name for the Implant Set!") + elif text in [x.name for x in profileEditor.entityEditor.choices]: + raise ValueError("Imlplant Set name already in use, please choose another.") + + return True + except ValueError, e: + wx.MessageBox(u"{}".format(e), "Error") + textCtrl.SetFocus() + return False + + +class ImplantSetEntityEditor(EntityEditor): + def __init__(self, parent): + EntityEditor.__init__(self, parent, "Implant Set") + self.SetEditorValidator(ImplantTextValidor) + + def getEntitiesFromContext(self): + sIS = service.ImplantSets.getInstance() + return sorted(sIS.getImplantSetList(), key=lambda c: c.name) + + def DoNew(self, name): + sIS = service.ImplantSets.getInstance() + return sIS.newSet(name) + + def DoRename(self, entity, name): + sIS = service.ImplantSets.getInstance() + sIS.renameSet(entity, name) + + def DoCopy(self, entity, name): + sIS = service.ImplantSets.getInstance() + copy = sIS.copySet(entity) + sIS.renameSet(copy, name) + return copy + + def DoDelete(self, entity): + sIS = service.ImplantSets.getInstance() + sIS.deleteSet(entity) + + class ImplantSetEditor(BaseImplantEditorView): def __init__(self, parent): BaseImplantEditorView.__init__(self, parent) @@ -34,27 +88,26 @@ class ImplantSetEditor(BaseImplantEditorView): self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) def bindContext(self): - self.Parent.ccSets.Bind(wx.EVT_CHOICE, self.contextChanged) + self.Parent.entityEditor.Bind(wx.EVT_CHOICE, self.contextChanged) def getImplantsFromContext(self): sIS = service.ImplantSets.getInstance() - set = self.Parent.getActiveSet() + set = self.Parent.entityEditor.getActiveEntity() if set: return sIS.getImplants(set.ID) return [] def addImplantToContext(self, item): sIS = service.ImplantSets.getInstance() - set = self.Parent.getActiveSet() + set = self.Parent.entityEditor.getActiveEntity() sIS.addImplant(set.ID, item.ID) - def removeImplantFromContext(self, pos): + def removeImplantFromContext(self, implant): sIS = service.ImplantSets.getInstance() - set = self.Parent.getActiveSet() - - sIS.removeImplant(set.ID, self.implants[pos]) + set = self.Parent.entityEditor.getActiveEntity() + sIS.removeImplant(set.ID, implant) class ImplantSetEditorDlg(wx.Dialog): @@ -66,55 +119,8 @@ class ImplantSetEditorDlg(wx.Dialog): mainSizer = wx.BoxSizer(wx.VERTICAL) - self.headerSizer = headerSizer = wx.BoxSizer(wx.HORIZONTAL) - - sIS = service.ImplantSets.getInstance() - - self.choices = sIS.getImplantSetList() - - # Sort the remaining list and continue on - self.choices.sort(key=lambda s: s.name) - self.ccSets = wx.Choice(self, wx.ID_ANY, style=0) - - for set in self.choices: - i = self.ccSets.Append(set.name, set.ID) - - self.ccSets.Bind(wx.EVT_CHOICE, self.setChanged) - self.ccSets.SetSelection(0) - - self.namePicker = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER) - self.namePicker.Bind(wx.EVT_TEXT_ENTER, self.processRename) - self.namePicker.Hide() - - size = None - headerSizer.Add(self.ccSets, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3) - - buttons = (("new", wx.ART_NEW), - ("rename", BitmapLoader.getBitmap("rename", "gui")), - ("copy", wx.ART_COPY), - ("delete", wx.ART_DELETE)) - - for name, art in buttons: - bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON) if name != "rename" else art - btn = wx.BitmapButton(self, wx.ID_ANY, bitmap) - if size is None: - size = btn.GetSize() - - btn.SetMinSize(size) - btn.SetMaxSize(size) - - btn.Layout() - setattr(self, name, btn) - btn.Enable(True) - btn.SetToolTipString("%s implant set" % name.capitalize()) - headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL) - - self.btnSave = wx.Button(self, wx.ID_SAVE) - self.btnSave.Hide() - self.btnSave.Bind(wx.EVT_BUTTON, self.processRename) - headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER) - - mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2) + self.entityEditor = ImplantSetEntityEditor(self) + mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2) self.sl = wx.StaticLine(self) mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) @@ -157,174 +163,15 @@ class ImplantSetEditorDlg(wx.Dialog): self.SetSizer(mainSizer) self.Layout() - self.new.Bind(wx.EVT_BUTTON, self.newSet) - self.rename.Bind(wx.EVT_BUTTON, self.renameSet) - self.copy.Bind(wx.EVT_BUTTON, self.copySet) - self.delete.Bind(wx.EVT_BUTTON, self.deleteSet) self.Import.Bind(wx.EVT_BUTTON, self.importPatterns) self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns) def closeEvent(self, event): self.Destroy() - def getActiveSet(self): - selection = self.ccSets.GetCurrentSelection() - return self.ccSets.GetClientData(selection) if selection is not None else None - - def restrict(self): - self.rename.Enable(False) - self.delete.Enable(False) - - def unrestrict(self): - self.rename.Enable() - self.delete.Enable() - - def getActiveSet(self): - if len(self.choices) == 0: - return None - - return self.choices[self.ccSets.GetSelection()] - - def setChanged(self, event=None): - "Event fired when user selects pattern. Can also be called from script" - p = self.getActiveSet() - self.iview.update() - if p is None: - # This happens when there are no patterns in the DB. As such, force - # user to create one first or exit dlg. - self.newSet(None) - return - - def newSet(self, event): - ''' - Simply does new-set specifics: replaces label on button, restricts, - and resets values to default. Hands off to the rename function for - further handling. - ''' - self.btnSave.SetLabel("Create") - self.restrict() - - self.Refresh() - self.renameSet() - - def renameSet(self, event=None): - "Changes layout to facilitate naming a pattern" - - self.showInput(True) - - if event is not None: # Rename mode - self.btnSave.SetLabel("Rename") - self.namePicker.SetValue(self.getActiveSet().name) - else: # Create mode - self.namePicker.SetValue("") - - if event is not None: - event.Skip() - - def processRename(self, event): - ''' - Processes rename event (which can be new or old patterns). If new - pattern, creates it; if old, selects it. if checks are valid, rename - saves pattern to DB. - - Also resets to default layout and unrestricts. - ''' - newName = self.namePicker.GetLineText(0) - self.stNotice.SetLabel("") - - if newName == "": - self.stNotice.SetLabel("Invalid name") - return - - sIS = service.ImplantSets.getInstance() - if self.btnSave.Label == "Create": - s = sIS.newSet() - else: - # we are renaming, so get the current selection - s = self.getActiveSet() - - # test for patterns of the same name - for set in self.choices: - if set.name == newName and s != set: - self.stNotice.SetLabel("Name already used, please choose another") - return - - # rename regardless of new or rename - sIS.renameSet(s, newName) - - self.updateChoices(newName) - self.showInput(False) - sel = self.ccSets.GetSelection() - self.unrestrict() - - def copySet(self,event): - sIS = service.ImplantSets.getInstance() - p = sIS.copySet(self.getActiveSet()) - self.choices.append(p) - id = self.ccSets.Append(p.name) - self.ccSets.SetSelection(id) - self.btnSave.SetLabel("Copy") - self.renameSet() - self.setChanged() - - def deleteSet(self,event): - sIS = service.ImplantSets.getInstance() - sel = self.ccSets.GetSelection() - sIS.deleteSet(self.getActiveSet()) - self.ccSets.Delete(sel) - self.ccSets.SetSelection(max(0, sel - 1)) - del self.choices[sel] - self.setChanged() - - def showInput(self, bool): - if bool and not self.namePicker.IsShown(): - self.ccSets.Hide() - self.namePicker.Show() - self.headerSizer.Replace(self.ccSets, self.namePicker) - self.namePicker.SetFocus() - for btn in (self.new, self.rename, self.delete, self.copy): - btn.Hide() - self.btnSave.Show() - self.restrict() - self.headerSizer.Layout() - elif not bool and self.namePicker.IsShown(): - self.headerSizer.Replace(self.namePicker, self.ccSets) - self.ccSets.Show() - self.namePicker.Hide() - self.btnSave.Hide() - for btn in (self.new, self.rename, self.delete, self.copy): - btn.Show() - self.unrestrict() - self.headerSizer.Layout() - - def __del__( self ): pass - def updateChoices(self, select=None): - "Gathers list of patterns and updates choice selections" - sIS = service.ImplantSets.getInstance() - self.choices = sIS.getImplantSetList() - - if len(self.choices) == 0: - #self.newPattern(None) - return - - # Sort the remaining list and continue on - self.choices.sort(key=lambda p: p.name) - self.ccSets.Clear() - - for i, choice in enumerate(map(lambda p: p.name, self.choices)): - self.ccSets.Append(choice) - - if select is not None and choice == select: - self.ccSets.SetSelection(i) - - if select is None: - self.ccSets.SetSelection(0) - - self.setChanged() - def importPatterns(self, event): "Event fired when import from clipboard button is clicked" diff --git a/service/implantSet.py b/service/implantSet.py index 4a517f0ca..0d0df5808 100644 --- a/service/implantSet.py +++ b/service/implantSet.py @@ -55,10 +55,11 @@ class ImplantSets(): set.implants.remove(implant) eos.db.commit() - def newSet(self): - p = eos.types.ImplantSet() - p.name = "" - return p + def newSet(self, name): + s = eos.types.ImplantSet() + s.name = name + eos.db.save(s) + return s def renameSet(self, s, newName): s.name = newName From 39b2f87194ed724528fd94f5384b51326d9be2c2 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Wed, 30 Mar 2016 00:03:48 -0400 Subject: [PATCH 5/5] Add in logic that required an entity for implant sets and target resists (not needed for character or damage profiles as we have read-only defaults) --- gui/builtinViews/entityEditor.py | 21 ++++++++++++++++++--- gui/mainFrame.py | 8 ++------ gui/resistsEditor.py | 13 ++++++++++++- gui/setEditor.py | 16 +++++++++++++++- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py index faaf1e3bb..112c1c63e 100644 --- a/gui/builtinViews/entityEditor.py +++ b/gui/builtinViews/entityEditor.py @@ -18,6 +18,8 @@ class BaseValidator(wx.PyValidator): class TextEntryValidatedDialog(wx.TextEntryDialog): def __init__(self, parent, validator=None, *args, **kargs): wx.TextEntryDialog.__init__(self, parent, *args, **kargs) + self.parent = parent + self.txtctrl = self.FindWindowById(3000) if validator: self.txtctrl.SetValidator(validator()) @@ -35,7 +37,7 @@ class EntityEditor (wx.Panel): self.validator = None self.navSizer = wx.BoxSizer(wx.HORIZONTAL) - self.choices = self.getEntitiesFromContext() + self.choices = [] self.choices.sort(key=lambda p: p.name) self.entityChoices = wx.Choice(self, choices=map(lambda p: p.name, self.choices)) self.navSizer.Add(self.entityChoices, 1, wx.ALL, 5) @@ -60,10 +62,11 @@ class EntityEditor (wx.Panel): setattr(self, "btn%s" % name.capitalize(), btn) self.navSizer.Add(btn, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2) - self.entityChoices.SetSelection(0) self.SetSizer(self.navSizer) self.Layout() + self.refreshEntityList() + def SetEditorValidator(self, validator=None): """ Sets validator class (not an instance of the class) """ self.validator = validator @@ -98,6 +101,8 @@ class EntityEditor (wx.Panel): new = self.DoNew(dlg.GetValue().strip()) self.refreshEntityList(new) wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + else: + return False def OnCopy(self, event): dlg = TextEntryValidatedDialog(self, self.validator, @@ -141,6 +146,7 @@ class EntityEditor (wx.Panel): def refreshEntityList(self, selected=None): self.choices = self.getEntitiesFromContext() self.entityChoices.Clear() + self.entityChoices.AppendItems(map(lambda p: p.name, self.choices)) if selected: idx = self.choices.index(selected) @@ -155,4 +161,13 @@ class EntityEditor (wx.Panel): return self.choices[self.entityChoices.GetSelection()] def setActiveEntity(self, entity): - self.entityChoices.SetSelection(self.choices.index(entity)) \ No newline at end of file + self.entityChoices.SetSelection(self.choices.index(entity)) + + def checkEntitiesExist(self): + if len(self.choices) == 0: + self.Parent.Hide() + if self.OnNew(None) is False: + return False + self.Parent.Show() + + return True \ No newline at end of file diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 3b76a13c9..7557813db 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -359,9 +359,7 @@ class MainFrame(wx.Frame): dlg.Show() def showTargetResistsEditor(self, event): - dlg=ResistsEditorDlg(self) - dlg.ShowModal() - dlg.Destroy() + ResistsEditorDlg(self) def showDamagePatternEditor(self, event): dlg=DmgPatternEditorDlg(self) @@ -369,9 +367,7 @@ class MainFrame(wx.Frame): dlg.Destroy() def showImplantSetEditor(self, event): - dlg=ImplantSetEditorDlg(self) - dlg.ShowModal() - dlg.Destroy() + ImplantSetEditorDlg(self) def showExportDialog(self, event): """ Export active fit """ diff --git a/gui/resistsEditor.py b/gui/resistsEditor.py index 57b438dc5..374f9c1fc 100644 --- a/gui/resistsEditor.py +++ b/gui/resistsEditor.py @@ -33,7 +33,7 @@ class TargetResistsTextValidor(BaseValidator): return TargetResistsTextValidor() def Validate(self, win): - profileEditor = win.Parent + profileEditor = win.parent.Parent textCtrl = self.GetWindow() text = textCtrl.GetValue().strip() @@ -169,6 +169,10 @@ class ResistsEditorDlg(wx.Dialog): btn.SetToolTipString("%s patterns %s clipboard" % (name, direction) ) footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT) + if not self.entityEditor.checkEntitiesExist(): + self.Destroy() + return + self.Layout() bsize = self.GetBestSize() self.SetSize((-1, bsize.height)) @@ -178,6 +182,8 @@ class ResistsEditorDlg(wx.Dialog): self.patternChanged() + self.ShowModal() + def closeEvent(self, event): self.Destroy() @@ -230,6 +236,11 @@ class ResistsEditorDlg(wx.Dialog): def patternChanged(self, event=None): "Event fired when user selects pattern. Can also be called from script" + + if not self.entityEditor.checkEntitiesExist(): + self.Destroy() + return + p = self.entityEditor.getActiveEntity() if p is None: return diff --git a/gui/setEditor.py b/gui/setEditor.py index 3b283d601..4e8baa9ed 100644 --- a/gui/setEditor.py +++ b/gui/setEditor.py @@ -36,7 +36,7 @@ class ImplantTextValidor(BaseValidator): return ImplantTextValidor() def Validate(self, win): - profileEditor = win.Parent + profileEditor = win.parent.Parent textCtrl = self.GetWindow() text = textCtrl.GetValue().strip() @@ -163,9 +163,23 @@ class ImplantSetEditorDlg(wx.Dialog): self.SetSizer(mainSizer) self.Layout() + if not self.entityEditor.checkEntitiesExist(): + self.Destroy() + return + + self.Bind(wx.EVT_CHOICE, self.entityChanged) + self.Import.Bind(wx.EVT_BUTTON, self.importPatterns) self.Export.Bind(wx.EVT_BUTTON, self.exportPatterns) + self.CenterOnParent() + self.ShowModal() + + def entityChanged(self, event): + if not self.entityEditor.checkEntitiesExist(): + self.Destroy() + return + def closeEvent(self, event): self.Destroy()