Abstract the implant editor to work with different sources

This commit is contained in:
blitzmann
2016-03-20 02:59:09 -04:00
parent 36ad31ab25
commit c1653c5f2e
4 changed files with 281 additions and 244 deletions

View File

@@ -1 +1 @@
__all__ = ["fittingView", "fleetView"]
__all__ = ["fittingView", "fleetView", "implantEditor"]

View File

@@ -0,0 +1,254 @@
import wx
import service
import gui.display as d
from gui.bitmapLoader import BitmapLoader
import gui.PFSearchBox as SBox
from gui.marketBrowser import SearchBox
from wx.lib.buttons import GenBitmapButton
class BaseImplantEditorView (wx.Panel):
def addMarketViewImage(self, iconFile):
if iconFile is None:
return -1
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
if bitmap is None:
return -1
else:
return self.availableImplantsImageList.Add(bitmap)
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.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
pmainSizer = wx.BoxSizer(wx.HORIZONTAL)
availableSizer = wx.BoxSizer(wx.VERTICAL)
self.searchBox = SearchBox(self)
self.itemView = ItemView(self)
self.itemView.Hide()
availableSizer.Add(self.searchBox, 0, wx.EXPAND)
availableSizer.Add(self.itemView, 1, wx.EXPAND)
'''
self.availableImplantsSearch = wx.SearchCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
self.availableImplantsSearch.ShowCancelButton(True)
availableSizer.Add(self.availableImplantsSearch, 0, wx.BOTTOM | wx.EXPAND, 2)
'''
self.availableImplantsTree = wx.TreeCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
root = self.availableRoot = self.availableImplantsTree.AddRoot("Available")
self.availableImplantsImageList = wx.ImageList(16, 16)
self.availableImplantsTree.SetImageList(self.availableImplantsImageList)
availableSizer.Add(self.availableImplantsTree, 1, wx.EXPAND)
pmainSizer.Add(availableSizer, 1, wx.ALL | wx.EXPAND, 5)
buttonSizer = wx.BoxSizer(wx.VERTICAL)
buttonSizer.AddSpacer(( 0, 0), 1)
self.btnAdd = GenBitmapButton(self, wx.ID_ADD, BitmapLoader.getBitmap("fit_add_small", "gui"), style = wx.BORDER_NONE)
buttonSizer.Add(self.btnAdd, 0)
self.btnRemove = GenBitmapButton(self, wx.ID_REMOVE, BitmapLoader.getBitmap("fit_delete_small", "gui"), style = wx.BORDER_NONE)
buttonSizer.Add(self.btnRemove, 0)
buttonSizer.AddSpacer(( 0, 0), 1)
pmainSizer.Add(buttonSizer, 0, wx.EXPAND, 0)
characterImplantSizer = wx.BoxSizer(wx.VERTICAL)
self.pluggedImplantsTree = AvailableImplantsView(self)
characterImplantSizer.Add(self.pluggedImplantsTree, 1, wx.ALL|wx.EXPAND, 5)
pmainSizer.Add(characterImplantSizer, 1, wx.EXPAND, 5)
self.SetSizer(pmainSizer)
# Populate the market tree
sMkt = service.Market.getInstance()
for mktGrp in sMkt.getImplantTree():
iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(mktGrp))
childId = self.availableImplantsTree.AppendItem(root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
if sMkt.marketGroupHasTypesCheck(mktGrp) is False:
self.availableImplantsTree.AppendItem(childId, "dummy")
self.availableImplantsTree.SortChildren(self.availableRoot)
#Bind the event to replace dummies by real data
self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.itemSelected)
self.itemView.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemSelected)
#Bind add & remove buttons
self.btnAdd.Bind(wx.EVT_BUTTON, self.itemSelected)
self.btnRemove.Bind(wx.EVT_BUTTON, self.removeItem)
# We update with an empty list first to set the initial size for Layout(), then update later with actual
# implants for character. This helps with sizing issues.
self.pluggedImplantsTree.update([])
self.bindContext()
self.Layout()
self.update()
def bindContext(self):
# Binds self.contextChanged to whatever changes the context
raise NotImplementedError()
def getImplantsFromContext(self):
""" Gets list of implants from current context """
raise NotImplementedError()
def addImplantToContext(self, item):
""" Adds implant to the current context"""
raise NotImplementedError()
def removeImplantFromContext(self, pos):
""" Removes implant from the current context"""
raise NotImplementedError()
def update(self):
"""Updates implant list based off the current context"""
self.implants = self.getImplantsFromContext()
self.implants.sort(key=lambda i: int(i.getModifiedItemAttr("implantness")))
self.pluggedImplantsTree.update(self.implants)
def contextChanged(self, event):
self.update()
event.Skip()
def expandLookup(self, event):
tree = self.availableImplantsTree
sMkt = service.Market.getInstance()
parent = event.Item
child, _ = tree.GetFirstChild(parent)
text = tree.GetItemText(child)
if text == "dummy" or text == "itemdummy":
tree.Delete(child)
# if the dummy item is a market group, replace with actual market groups
if text == "dummy":
#Add 'real stoof!' instead
currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent), eager="children")
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(childMktGrp))
childId = tree.AppendItem(parent, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
tree.AppendItem(childId, "dummy")
else:
tree.AppendItem(childId, "itemdummy")
# replace dummy with actual items
if text == "itemdummy":
currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent))
items = sMkt.getItemsByMarketGroup(currentMktGrp)
for item in items:
iconId = self.addMarketViewImage(item.icon.iconFile)
tree.AppendItem(parent, item.name, iconId, data=wx.TreeItemData(item))
tree.SortChildren(parent)
def itemSelected(self, event):
if event.EventObject is self.btnAdd:
# janky fix that sets EventObject so that we don't have similar code elsewhere.
if self.itemView.IsShown():
event.EventObject = self.itemView
else:
event.EventObject = self.availableImplantsTree
if event.EventObject is self.itemView:
sel = event.EventObject.GetFirstSelected()
item = self.itemView.items[sel]
else:
root = self.availableImplantsTree.GetSelection()
if not root.IsOk():
return
nchilds = self.availableImplantsTree.GetChildrenCount(root)
if nchilds == 0:
item = self.availableImplantsTree.GetPyData(root)
else:
event.Skip()
return
if item:
self.addImplantToContext(item)
self.update()
def removeItem(self, event):
pos = self.pluggedImplantsTree.GetFirstSelected()
if pos != -1:
self.removeImplantFromContext(pos)
self.update()
class AvailableImplantsView(d.Display):
DEFAULT_COLS = ["attr:implantness",
"Base Icon",
"Base Name"]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
self.Bind(wx.EVT_LEFT_DCLICK, parent.removeItem)
class ItemView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"attr:power,,,True",
"attr:cpu,,,True"]
def __init__(self, parent):
d.Display.__init__(self, parent)
self.parent = parent
self.searchBox = parent.searchBox
self.items = []
# Bind search actions
self.searchBox.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
self.searchBox.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
self.searchBox.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
self.searchBox.Bind(SBox.EVT_TEXT, self.scheduleSearch)
def clearSearch(self, event=None):
if self.IsShown():
self.parent.availableImplantsTree.Show()
self.Hide()
self.parent.Layout()
if event:
self.searchBox.Clear()
self.items = []
self.update(self.items)
def scheduleSearch(self, event=None):
sMkt = service.Market.getInstance()
search = self.searchBox.GetLineText(0)
# Make sure we do not count wildcard as search symbol
realsearch = search.replace("*", "")
# Show nothing if query is too short
if len(realsearch) < 3:
self.clearSearch()
return
sMkt.searchItems(search, self.populateSearch, ["Implant"])
def populateSearch(self, items):
if not self.IsShown():
self.parent.availableImplantsTree.Hide()
self.Show()
self.parent.Layout()
self.items = sorted(list(items), key=lambda i: i.name)
self.update(self.items)

View File

@@ -19,18 +19,13 @@
import wx
import gui.mainFrame
import wx.lib.newevent
import wx.gizmos
from gui.bitmapLoader import BitmapLoader
import service
import gui.display as d
from gui.contextMenu import ContextMenu
from wx.lib.buttons import GenBitmapButton
import gui.globalEvents as GE
import gui.PFSearchBox as SBox
from gui.marketBrowser import SearchBox
from gui.builtinViews.implantEditor import BaseImplantEditorView
class CharacterEditor(wx.Frame):
def __init__(self, parent):
@@ -97,7 +92,7 @@ class CharacterEditor(wx.Frame):
self.viewsNBContainer = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
self.sview = SkillTreeView(self.viewsNBContainer)
self.iview = ImplantsTreeView(self.viewsNBContainer)
self.iview = ImplantEditorView(self.viewsNBContainer)
self.aview = APIView(self.viewsNBContainer)
self.viewsNBContainer.AddPage(self.sview, "Skills")
@@ -460,256 +455,31 @@ class SkillTreeView (wx.Panel):
wx.PostEvent(self.Parent.Parent, GE.CharListUpdated())
event.Skip()
class ImplantsTreeView (wx.Panel):
def addMarketViewImage(self, iconFile):
if iconFile is None:
return -1
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
if bitmap is None:
return -1
else:
return self.availableImplantsImageList.Add(bitmap)
class ImplantEditorView(BaseImplantEditorView):
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.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
BaseImplantEditorView.__init__ (self, parent)
pmainSizer = wx.BoxSizer(wx.HORIZONTAL)
availableSizer = wx.BoxSizer(wx.VERTICAL)
self.searchBox = SearchBox(self)
self.itemView = ItemView(self)
self.itemView.Hide()
availableSizer.Add(self.searchBox, 0, wx.EXPAND)
availableSizer.Add(self.itemView, 1, wx.EXPAND)
'''
self.availableImplantsSearch = wx.SearchCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
self.availableImplantsSearch.ShowCancelButton(True)
availableSizer.Add(self.availableImplantsSearch, 0, wx.BOTTOM | wx.EXPAND, 2)
'''
self.availableImplantsTree = wx.TreeCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
root = self.availableRoot = self.availableImplantsTree.AddRoot("Available")
self.availableImplantsImageList = wx.ImageList(16, 16)
self.availableImplantsTree.SetImageList(self.availableImplantsImageList)
availableSizer.Add(self.availableImplantsTree, 1, wx.EXPAND)
pmainSizer.Add(availableSizer, 1, wx.ALL | wx.EXPAND, 5)
buttonSizer = wx.BoxSizer(wx.VERTICAL)
buttonSizer.AddSpacer(( 0, 0), 1)
#pmainSizer.Add(buttonSizer, 0, wx.TOP, 5)
self.btnAdd = GenBitmapButton(self, wx.ID_ADD, BitmapLoader.getBitmap("fit_add_small", "gui"), style = wx.BORDER_NONE)
buttonSizer.Add(self.btnAdd, 0)
self.btnRemove = GenBitmapButton(self, wx.ID_REMOVE, BitmapLoader.getBitmap("fit_delete_small", "gui"), style = wx.BORDER_NONE)
buttonSizer.Add(self.btnRemove, 0)
buttonSizer.AddSpacer(( 0, 0), 1)
pmainSizer.Add(buttonSizer, 0, wx.EXPAND, 0)
characterImplantSizer = wx.BoxSizer(wx.VERTICAL)
self.pluggedImplantsTree = AvailableImplantsView(self)
characterImplantSizer.Add(self.pluggedImplantsTree, 1, wx.ALL|wx.EXPAND, 5)
pmainSizer.Add(characterImplantSizer, 1, wx.EXPAND, 5)
self.SetSizer(pmainSizer)
# Populate the market tree
sMkt = service.Market.getInstance()
for mktGrp in sMkt.getImplantTree():
iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(mktGrp))
childId = self.availableImplantsTree.AppendItem(root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
if sMkt.marketGroupHasTypesCheck(mktGrp) is False:
self.availableImplantsTree.AppendItem(childId, "dummy")
self.availableImplantsTree.SortChildren(self.availableRoot)
#Bind the event to replace dummies by real data
self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
self.availableImplantsTree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.addImplant)
self.itemView.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
#Bind add & remove buttons
self.btnAdd.Bind(wx.EVT_BUTTON, self.addImplant)
self.btnRemove.Bind(wx.EVT_BUTTON, self.removeImplant)
#Bind the change of a character*
self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.charChanged)
# We update with an empty list first to set the initial size for Layout(), then update later with actual
# implants for character. This helps with sizing issues.
self.update([])
self.Layout()
def bindContext(self):
self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.contextChanged)
def getImplantsFromContext(self):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
self.update(sChar.getImplants(charID))
def itemActivated(self, event):
sel = event.EventObject.GetFirstSelected()
item = self.itemView.items[sel]
return sChar.getImplants(charID)
if item:
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
sChar.addImplant(charID, item.ID)
self.update(sChar.getImplants(charID))
def update(self, implants):
self.implants = implants[:]
self.implants.sort(key=lambda i: int(i.getModifiedItemAttr("implantness")))
self.pluggedImplantsTree.update(self.implants)
def charChanged(self, event):
def addImplantToContext(self, item):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
name = sChar.getCharName(charID)
if name == "All 0" or name == "All 5":
self.Enable(False)
else:
self.Enable(True)
self.update(sChar.getImplants(charID))
event.Skip()
sChar.addImplant(charID, item.ID)
def expandLookup(self, event):
tree = self.availableImplantsTree
sMkt = service.Market.getInstance()
parent = event.Item
child, _ = tree.GetFirstChild(parent)
text = tree.GetItemText(child)
if text == "dummy" or text == "itemdummy":
tree.Delete(child)
# if the dummy item is a market group, replace with actual market groups
if text == "dummy":
#Add 'real stoof!' instead
currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent), eager="children")
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(childMktGrp))
childId = tree.AppendItem(parent, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
tree.AppendItem(childId, "dummy")
else:
tree.AppendItem(childId, "itemdummy")
# replace dummy with actual items
if text == "itemdummy":
currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent))
items = sMkt.getItemsByMarketGroup(currentMktGrp)
for item in items:
iconId = self.addMarketViewImage(item.icon.iconFile)
tree.AppendItem(parent, item.name, iconId, data=wx.TreeItemData(item.ID))
tree.SortChildren(parent)
def addImplant(self, event):
root = self.availableImplantsTree.GetSelection()
if not root.IsOk():
return
nchilds = self.availableImplantsTree.GetChildrenCount(root)
def removeImplantFromContext(self, pos):
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
if nchilds == 0:
itemID = self.availableImplantsTree.GetPyData(root)
sChar.addImplant(charID, itemID)
self.update(sChar.getImplants(charID))
else:
event.Skip()
def removeImplant(self, event):
pos = self.pluggedImplantsTree.GetFirstSelected()
if pos != -1:
sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter()
sChar.removeImplant(charID, self.implants[pos])
self.update(sChar.getImplants(charID))
class AvailableImplantsView(d.Display):
DEFAULT_COLS = ["attr:implantness",
"Base Icon",
"Base Name"]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
self.Bind(wx.EVT_LEFT_DCLICK, parent.removeImplant)
#if "__WXGTK__" in wx.PlatformInfo:
# self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
#else:
# self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
class ItemView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"attr:power,,,True",
"attr:cpu,,,True"]
def __init__(self, parent):
d.Display.__init__(self, parent)
self.parent = parent
self.searchBox = parent.searchBox
self.items = []
# Bind search actions
self.searchBox.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
self.searchBox.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
self.searchBox.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
self.searchBox.Bind(SBox.EVT_TEXT, self.scheduleSearch)
def clearSearch(self, event=None):
if self.IsShown():
self.parent.availableImplantsTree.Show()
self.Hide()
self.parent.Layout()
if event:
self.searchBox.Clear()
self.items = []
self.update(self.items)
def scheduleSearch(self, event=None):
sMkt = service.Market.getInstance()
search = self.searchBox.GetLineText(0)
# Make sure we do not count wildcard as search symbol
realsearch = search.replace("*", "")
# Show nothing if query is too short
if len(realsearch) < 3:
self.clearSearch()
return
sMkt.searchItems(search, self.populateSearch, ["Implant"])
def populateSearch(self, items):
if not self.IsShown():
self.parent.availableImplantsTree.Hide()
self.Show()
self.parent.Layout()
self.items = sorted(list(items), key=lambda i: i.name)
self.update(self.items)
sChar.removeImplant(charID, self.implants[pos])
class APIView (wx.Panel):

View File

@@ -19,14 +19,24 @@
import wx
from gui.bitmapLoader import BitmapLoader
from gui.builtinViews.implantEditor import BaseImplantEditorView
import service
from gui.utils.clipboard import toClipboard, fromClipboard
from service.targetResists import ImportError
class EditorView(BaseImplantEditorView):
def __init__(self, parent):
BaseImplantEditorView.__init__(self, parent)
self.parent = parent
def getImplants(self):
return []
class ImplantSetEditorDlg(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = u"Implant Set Editor", size = wx.Size( 350,240 ))
wx.Dialog.__init__(self, parent, id = wx.ID_ANY, title = u"Implant Set Editor", size = wx.Size(640, 600))
self.block = False
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
@@ -82,6 +92,9 @@ class ImplantSetEditorDlg(wx.Dialog):
self.sl = wx.StaticLine(self)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.iview = EditorView(self)
mainSizer.Add(self.iview, 0, wx.EXPAND)
contentSizer = wx.BoxSizer(wx.VERTICAL)
self.slfooter = wx.StaticLine(self)