#=============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of pyfa. # # pyfa is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # pyfa is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with pyfa. If not, see . #=============================================================================== import wx import bitmapLoader import service from wx.lib.intctrl import IntCtrl from gui.utils.clipboard import toClipboard, fromClipboard from service.damagePattern import ImportError ########################################################################### ## Class DmgPatternEditorDlg ########################################################################### class DmgPatternEditorDlg (wx.Dialog): DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive") def __init__(self, parent): wx.Dialog.__init__ (self, parent, id = wx.ID_ANY, title = u"Damage Pattern Editor", size = wx.Size( 400,240 )) self.block = False self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize) 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() self.btnSave = wx.Button(self, wx.ID_SAVE) self.btnSave.Hide() self.btnSave.Bind(wx.EVT_BUTTON, self.processRename) 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", "icons")), ("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) mainSizer.Add(headerSizer, 0, wx.EXPAND | wx.ALL, 2) self.sl = wx.StaticLine(self) mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) contentSizer = wx.BoxSizer(wx.VERTICAL) self.embitmap = bitmapLoader.getBitmap("em_big", "icons") self.thermbitmap = bitmapLoader.getBitmap("thermal_big", "icons") self.kinbitmap = bitmapLoader.getBitmap("kinetic_big", "icons") self.expbitmap = bitmapLoader.getBitmap("explosive_big", "icons") dmgeditSizer = wx.FlexGridSizer(2, 6, 0, 2) dmgeditSizer.AddGrowableCol(0) dmgeditSizer.AddGrowableCol(5) dmgeditSizer.SetFlexibleDirection(wx.BOTH) dmgeditSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED) width = -1 defSize = wx.Size(width,-1) for i, type in enumerate(self.DAMAGE_TYPES): bmp = wx.StaticBitmap(self, wx.ID_ANY, bitmapLoader.getBitmap("%s_big"%type, "icons")) if i%2: style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT border = 10 else: style = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT border = 5 # set text edit setattr(self, "%sEdit"%type, IntCtrl(self, wx.ID_ANY, 0, wx.DefaultPosition, defSize)) setattr(self, "%sPerc"%type, wx.StaticText(self, wx.ID_ANY, u"0%")) editObj = getattr(self, "%sEdit"%type) dmgeditSizer.Add(bmp, 0, style, border) dmgeditSizer.Add(editObj, 0, wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5) dmgeditSizer.Add(getattr(self, "%sPerc"%type), 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5) editObj.Bind(wx.EVT_TEXT, self.ValuesUpdated) editObj.SetLimited(True) editObj.SetMin(0) editObj.SetMax(99999) contentSizer.Add(dmgeditSizer, 1, wx.EXPAND | wx.ALL, 5) self.slfooter = wx.StaticLine(self) contentSizer.Add(self.slfooter, 0, wx.EXPAND | wx.TOP, 5) footerSizer = wx.BoxSizer(wx.HORIZONTAL) perSizer = wx.BoxSizer(wx.VERTICAL) self.stNotice = wx.StaticText(self, wx.ID_ANY, u"") self.stNotice.Wrap(-1) perSizer.Add(self.stNotice, 0, wx.BOTTOM | wx.TOP | wx.LEFT, 5) footerSizer.Add(perSizer, 1, wx.ALIGN_CENTER_VERTICAL, 5) self.totSizer = wx.BoxSizer(wx.VERTICAL) contentSizer.Add(footerSizer, 0, wx.EXPAND, 5) mainSizer.Add(contentSizer, 1, wx.EXPAND, 0) if "wxGTK" in wx.PlatformInfo: self.closeBtn = wx.Button( self, wx.ID_ANY, u"Close", wx.DefaultPosition, wx.DefaultSize, 0 ) mainSizer.Add( self.closeBtn, 0, wx.ALL|wx.ALIGN_RIGHT, 5 ) self.closeBtn.Bind(wx.EVT_BUTTON, self.closeEvent) self.SetSizer(mainSizer) 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) btn.SetMinSize( btn.GetSize() ) btn.SetMaxSize( btn.GetSize() ) btn.Layout() setattr(self, name, btn) btn.Enable(True) btn.SetToolTipString("%s patterns %s clipboard" % (name, direction) ) footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT) self.Layout() bsize = self.GetBestSize() 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.patternChanged() def closeEvent(self, event): self.Destroy() def ValuesUpdated(self, event=None): if self.block: return p = self.getActivePattern() total = sum(map(lambda attr: getattr(self, "%sEdit"%attr).GetValue(), self.DAMAGE_TYPES)) for type in self.DAMAGE_TYPES: editObj = getattr(self, "%sEdit"%type) percObj = getattr(self, "%sPerc"%type) setattr(p, "%sAmount"%type, editObj.GetValue()) percObj.SetLabel("%.1f%%"%(float(editObj.GetValue())*100/total if total > 0 else 0)) self.totSizer.Layout() if event is not None: event.Skip() service.DamagePattern.getInstance().saveChanges(p) 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.ccDmgPattern.GetSelection()] def patternChanged(self, event=None): p = self.getActivePattern() if p is None: return if p.name == "Uniform" or p.name == "Selected Ammo": self.restrict() else: self.unrestrict() self.block = True for field in self.DAMAGE_TYPES: edit = getattr(self, "%sEdit" % field) amount = getattr(p, "%sAmount" % field) edit.SetValue(amount) self.block = False self.ValuesUpdated() def newPattern(self,event): sDP = service.DamagePattern.getInstance() p = sDP.newPattern() self.choices.append(p) id = self.ccDmgPattern.Append(p.name) self.ccDmgPattern.SetSelection(id) self.restrict() # reset values for type in self.DAMAGE_TYPES: editObj = getattr(self, "%sEdit"%type) editObj.SetValue(0) self.btnSave.SetLabel("Create") 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() self.namePicker.SetValue(self.getActivePattern().name) for btn in (self.new, self.rename, self.delete, self.copy): btn.Hide() self.headerSizer.Remove(btn) self.headerSizer.Add(self.btnSave, 0, wx.ALIGN_CENTER) 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("") 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 if newName == "": self.stNotice.SetLabel("Invalid name.") return sDP = service.DamagePattern.getInstance() sDP.renamePattern(p, newName) self.headerSizer.Replace(self.namePicker, self.ccDmgPattern) self.ccDmgPattern.Show() self.namePicker.Hide() self.btnSave.Hide() self.headerSizer.Remove(self.btnSave) for btn in (self.new, self.rename, self.delete, self.copy): self.headerSizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL) 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 ): pass def updateChoices(self): "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 choice in map(lambda p: p.name, self.choices): self.ccDmgPattern.Append(choice) self.ccDmgPattern.SetSelection(0) self.patternChanged() def importPatterns(self, event): text = fromClipboard() if text: sDP = service.DamagePattern.getInstance() try: sDP.importPatterns(text) self.stNotice.SetLabel("Patterns successfully imported from clipboard") except service.damagePattern.ImportError, e: self.stNotice.SetLabel(str(e)) except Exception, e: self.stNotice.SetLabel("Could not import from clipboard: unknown errors") finally: self.updateChoices() else: self.stNotice.SetLabel("Could not import from clipboard") def exportPatterns(self, event): sDP = service.DamagePattern.getInstance() toClipboard( sDP.exportPatterns() ) self.stNotice.SetLabel("Patterns exported to clipboard")