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 wx
import gui.mainFrame
import wx.lib.newevent import wx.lib.newevent
import wx.gizmos import wx.gizmos
from gui.bitmapLoader import BitmapLoader from gui.bitmapLoader import BitmapLoader
import service import service
import gui.display as d
from gui.contextMenu import ContextMenu from gui.contextMenu import ContextMenu
from wx.lib.buttons import GenBitmapButton
import gui.globalEvents as GE import gui.globalEvents as GE
from gui.builtinViews.implantEditor import BaseImplantEditorView
import gui.PFSearchBox as SBox
from gui.marketBrowser import SearchBox
class CharacterEditor(wx.Frame): class CharacterEditor(wx.Frame):
def __init__(self, parent): 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.viewsNBContainer = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
self.sview = SkillTreeView(self.viewsNBContainer) self.sview = SkillTreeView(self.viewsNBContainer)
self.iview = ImplantsTreeView(self.viewsNBContainer) self.iview = ImplantEditorView(self.viewsNBContainer)
self.aview = APIView(self.viewsNBContainer) self.aview = APIView(self.viewsNBContainer)
self.viewsNBContainer.AddPage(self.sview, "Skills") self.viewsNBContainer.AddPage(self.sview, "Skills")
@@ -460,256 +455,31 @@ class SkillTreeView (wx.Panel):
wx.PostEvent(self.Parent.Parent, GE.CharListUpdated()) wx.PostEvent(self.Parent.Parent, GE.CharListUpdated())
event.Skip() 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): 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) BaseImplantEditorView.__init__ (self, parent)
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
pmainSizer = wx.BoxSizer(wx.HORIZONTAL) def bindContext(self):
self.Parent.Parent.Bind(GE.CHAR_CHANGED, self.contextChanged)
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 getImplantsFromContext(self):
sChar = service.Character.getInstance() sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter() charID = self.Parent.Parent.getActiveCharacter()
self.update(sChar.getImplants(charID))
def itemActivated(self, event): return sChar.getImplants(charID)
sel = event.EventObject.GetFirstSelected()
item = self.itemView.items[sel]
if item: def addImplantToContext(self, 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):
sChar = service.Character.getInstance() sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter() 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)) sChar.addImplant(charID, item.ID)
event.Skip()
def expandLookup(self, event): def removeImplantFromContext(self, pos):
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)
sChar = service.Character.getInstance() sChar = service.Character.getInstance()
charID = self.Parent.Parent.getActiveCharacter() 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): sChar.removeImplant(charID, self.implants[pos])
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)
class APIView (wx.Panel): class APIView (wx.Panel):

View File

@@ -19,14 +19,24 @@
import wx import wx
from gui.bitmapLoader import BitmapLoader from gui.bitmapLoader import BitmapLoader
from gui.builtinViews.implantEditor import BaseImplantEditorView
import service import service
from gui.utils.clipboard import toClipboard, fromClipboard from gui.utils.clipboard import toClipboard, fromClipboard
from service.targetResists import ImportError 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): class ImplantSetEditorDlg(wx.Dialog):
def __init__(self, parent): 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.block = False
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize) self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
@@ -82,6 +92,9 @@ class ImplantSetEditorDlg(wx.Dialog):
self.sl = wx.StaticLine(self) self.sl = wx.StaticLine(self)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) 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) contentSizer = wx.BoxSizer(wx.VERTICAL)
self.slfooter = wx.StaticLine(self) self.slfooter = wx.StaticLine(self)