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.

This commit is contained in:
blitzmann
2016-03-27 21:48:19 -04:00
parent ca91f6bd92
commit c3dcdb0686
3 changed files with 225 additions and 183 deletions

View File

@@ -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()]

View File

@@ -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"

View File

@@ -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):