Various event binding fixes for context menus. It's still a mess, but it's not as bad of a mess.

This commit is contained in:
blitzmann
2014-11-30 01:14:47 -05:00
parent 7100e8997b
commit 081e32da6f
18 changed files with 222 additions and 204 deletions

View File

@@ -70,7 +70,7 @@ class Ship(ItemAttrShortcut, HandledItem):
"""
Checks if provided item is a valid mode.
If ship has modes, and current mode is not valid, return forced mode
If ship has modes, and current item is not valid, return forced mode
else if mode is valid, return Mode
else if ship does not have modes, return None

View File

@@ -14,6 +14,7 @@ __all__ = [
"whProjector",
"cargo",
"shipJump",
#"changeAffectingSkills",
"tacticalMode",
"targetResists",
"priceClear"

View File

@@ -8,7 +8,6 @@ class AmmoPattern(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if srcContext not in ("marketItemGroup", "marketItemMisc") or self.mainFrame.getActiveFit() is None:
return False
@@ -33,5 +32,4 @@ class AmmoPattern(ContextMenu):
def getBitmap(self, context, selection):
return None
AmmoPattern.register()

View File

@@ -10,17 +10,17 @@ import gui.globalEvents as GE
class ChangeAffectingSkills(ContextMenu):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.sChar = service.Character.getInstance()
self.sFit = service.Fit.getInstance()
fit = self.sFit.getFit(self.mainFrame.getActiveFit())
self.charID = fit.character.ID
def display(self, srcContext, selection):
if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "fittingShip"):
return False
self.sChar = service.Character.getInstance()
self.sFit = service.Fit.getInstance()
fit = self.sFit.getFit(self.mainFrame.getActiveFit())
self.charID = fit.character.ID
if self.sChar.getCharName(self.charID) in ("All 0", "All 5"):
return False
@@ -52,9 +52,6 @@ class ChangeAffectingSkills(ContextMenu):
def getText(self, itmContext, selection):
return "Change %s Skills" % itmContext
def activate(self, fullContext, selection, i):
pass
def addSkill(self, rootMenu, skill, i):
if i < 0:
label = "Not Learned"
@@ -63,32 +60,30 @@ class ChangeAffectingSkills(ContextMenu):
id = wx.NewId()
self.skillIds[id] = (skill, i)
menuItem = wx.MenuItem(rootMenu, id, label, kind=wx.ITEM_CHECK)
menuItem = wx.MenuItem(rootMenu, id, label, kind=wx.ITEM_RADIO)
rootMenu.Bind(wx.EVT_MENU, self.handleSkillChange, menuItem)
return menuItem
def getSubMenu(self, context, selection, menu, i, pitem):
self.context = context
def getSubMenu(self, context, selection, rootMenu, i, pitem):
self.skillIds = {}
m = wx.Menu()
sub = wx.Menu()
for skill in self.skills:
skillItem = wx.MenuItem(m, wx.NewId(), skill.item.name)
sub = wx.Menu()
skillItem.SetSubMenu(sub)
skillItem = wx.MenuItem(sub, wx.NewId(), skill.item.name)
grandSub = wx.Menu()
skillItem.SetSubMenu(grandSub)
if skill.learned:
bitmap = bitmapLoader.getBitmap("lvl%s" % skill.level, "icons")
if bitmap is not None:
skillItem.SetBitmap(bitmap)
for i in xrange(-1, 6):
levelItem = self.addSkill(menu, skill, i)
sub.AppendItem(levelItem)
levelItem = self.addSkill(rootMenu, skill, i)
grandSub.AppendItem(levelItem)
#@ todo: add check to current level. Need to fix #109 first
m.AppendItem(skillItem)
sub.AppendItem(skillItem)
return m
return sub
def handleSkillChange(self, event):
skill, level = self.skillIds[event.Id]

View File

@@ -15,7 +15,7 @@ class DamagePattern(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("resistancesViewFull",) and self.mainFrame.getActiveFit() is not None
return srcContext == "resistancesViewFull" and self.mainFrame.getActiveFit() is not None
def getText(self, itmContext, selection):
sDP = service.DamagePattern.getInstance()
@@ -24,12 +24,11 @@ class DamagePattern(ContextMenu):
self.fit = sFit.getFit(fitID)
self.patterns = sDP.getDamagePatternList()
self.patterns.sort( key=lambda p: (p.name not in ["Uniform",
"Selected Ammo"], p.name) )
self.patterns.sort(key=lambda p: (p.name not in ["Uniform","Selected Ammo"], p.name))
self.patternIds = {}
self.subMenus = OrderedDict()
self.singles = []
self.singles = []
# iterate and separate damage patterns based on "[Parent] Child"
for pattern in self.patterns:
@@ -48,6 +47,50 @@ class DamagePattern(ContextMenu):
self.m = map(lambda p: p.name, self.singles) + self.subMenus.keys()
return self.m
def addPattern(self, rootMenu, pattern):
id = wx.NewId()
name = getattr(pattern, "_name", pattern.name) if pattern is not None else "No Profile"
self.patternIds[id] = pattern
menuItem = wx.MenuItem(rootMenu, id, name)
rootMenu.Bind(wx.EVT_MENU, self.handlePatternSwitch, menuItem)
# set pattern attr to menu item
menuItem.pattern = pattern
# determine active pattern
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
f = sFit.getFit(fitID)
dp = f.damagePattern
if dp == pattern:
bitmap = bitmapLoader.getBitmap("state_active_small", "icons")
menuItem.SetBitmap(bitmap)
return menuItem
def getSubMenu(self, context, selection, rootMenu, i, pitem):
rootMenu.Bind(wx.EVT_MENU, self.handlePatternSwitch) # this bit is required for some reason
if self.m[i] not in self.subMenus:
# if we're trying to get submenu to something that shouldn't have one,
# redirect event of the item to handlePatternSwitch and put pattern in
# our patternIds mapping, then return None for no submenu
id = pitem.GetId()
self.patternIds[id] = self.singles[i]
if self.patternIds[id] == self.fit.damagePattern:
bitmap = bitmapLoader.getBitmap("state_active_small", "icons")
pitem.SetBitmap(bitmap)
return None
sub = wx.Menu()
# Items that have a parent
for pattern in self.subMenus[self.m[i]]:
sub.AppendItem(self.addPattern(rootMenu, pattern))
return sub
def handlePatternSwitch(self, event):
pattern = self.patternIds.get(event.Id, False)
if pattern is False:
@@ -60,50 +103,4 @@ class DamagePattern(ContextMenu):
setattr(self.mainFrame,"_activeDmgPattern", pattern)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def addPattern(self, menu, pattern):
id = wx.NewId()
name = getattr(pattern, "_name", pattern.name) if pattern is not None else "No Profile"
self.patternIds[id] = pattern
item = wx.MenuItem(menu, id, name)
menu.Bind(wx.EVT_MENU, self.handlePatternSwitch, item)
# set pattern attr to menu item
item.pattern = pattern
# determine active pattern
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
f = sFit.getFit(fitID)
dp = f.damagePattern
if dp == pattern:
bitmap = bitmapLoader.getBitmap("state_active_small", "icons")
item.SetBitmap(bitmap)
return item
def getSubMenu(self, context, selection, menu, i, pitem):
menu.Bind(wx.EVT_MENU, self.handlePatternSwitch) # this bit is required for some reason
if self.m[i] not in self.subMenus:
# if we're trying to get submenu to something that shouldn't have one,
# redirect event of the item to handlePatternSwitch and put pattern in
# our patternIds mapping, then return None for no submenu
id = pitem.GetId()
self.patternIds[id] = self.singles[i]
menu.Bind(wx.EVT_MENU, self.handlePatternSwitch, pitem)
if self.patternIds[id] == self.fit.damagePattern:
bitmap = bitmapLoader.getBitmap("state_active_small", "icons")
pitem.SetBitmap(bitmap)
return None
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handlePatternSwitch)
# Items that have a parent
for pattern in self.subMenus[self.m[i]]:
sub.AppendItem(self.addPattern(sub, pattern))
return sub
DamagePattern.register()

View File

@@ -15,7 +15,6 @@ class ItemRemove(ContextMenu):
return "Remove {0} Stack".format(itmContext)
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)

View File

@@ -10,7 +10,7 @@ class FactorReload(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("firepowerViewFull",) and self.mainFrame.getActiveFit() is not None
return srcContext == "firepowerViewFull" and self.mainFrame.getActiveFit() is not None
def getText(self, itmContext, selection):
return "Factor in Reload Time"

View File

@@ -9,8 +9,13 @@ class ItemStats(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return srcContext in ("marketItemGroup", "marketItemMisc", "fittingModule", "fittingCharge", "fittingShip", "baseShip", "cargoItem",
"droneItem", "implantItem", "boosterItem", "skillItem", "projectedModule", "projectedDrone", "projectedCharge")
return srcContext in ("marketItemGroup", "marketItemMisc",
"fittingModule", "fittingCharge",
"fittingShip", "baseShip",
"cargoItem", "droneItem",
"implantItem", "boosterItem",
"skillItem", "projectedModule",
"projectedDrone", "projectedCharge")
def getText(self, itmContext, selection):
return "{0} Stats".format(itmContext if itmContext is not None else "Item")
@@ -33,7 +38,7 @@ class ItemStats(ContextMenu):
if mstate.CmdDown():
reuse = True
if self.mainFrame.GetActiveStatsWindow() == None and reuse:
if self.mainFrame.GetActiveStatsWindow() is None and reuse:
ItemStatsDialog(stuff, fullContext)
elif reuse:

View File

@@ -8,19 +8,24 @@ class MarketJump(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
validContexts = ("marketItemMisc", "fittingModule", "fittingCharge", "droneItem", "implantItem",
"boosterItem", "projectedModule", "projectedDrone", "projectedCharge", "cargoItem")
if not srcContext in validContexts:
validContexts = ("marketItemMisc", "fittingModule",
"fittingCharge", "droneItem",
"implantItem", "boosterItem",
"projectedModule", "projectedDrone",
"projectedCharge", "cargoItem")
if not srcContext in validContexts or selection is None or len(selection) < 1:
return False
sMkt = service.Market.getInstance()
if selection is None or len(selection) < 1:
return False
item = getattr(selection[0], "item", selection[0])
mktGrp = sMkt.getMarketGroupByItem(item)
# 1663 is Special Edition Festival Assets, we don't have root group for it
if mktGrp is None or mktGrp.ID == 1663:
return False
doit = not selection[0].isEmpty if srcContext == "fittingModule" else True
doit = not selection[0].isEmpty if srcContext == "fittingModule" else True
return doit
def getText(self, itmContext, selection):
@@ -28,7 +33,9 @@ class MarketJump(ContextMenu):
def activate(self, fullContext, selection, i):
srcContext = fullContext[0]
if srcContext in ("fittingModule", "droneItem", "implantItem", "boosterItem", "projectedModule", "projectedDrone", "cargoItem"):
if srcContext in ("fittingModule", "droneItem", "implantItem",
"boosterItem", "projectedModule", "projectedDrone",
"cargoItem"):
item = selection[0].item
elif srcContext in ("fittingCharge", "projectedCharge"):
item = selection[0].charge

View File

@@ -8,6 +8,9 @@ from eos.types import Hardpoint
import gui.globalEvents as GE
class ModuleAmmoPicker(ContextMenu):
DAMAGE_TYPES = ("em", "explosive", "kinetic", "thermal")
MISSILE_ORDER = ("em", "thermal", "kinetic", "explosive", "mixed")
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
@@ -19,7 +22,9 @@ class ModuleAmmoPicker(ContextMenu):
validCharges = None
checkedTypes = set()
for mod in modules:
# loop through modules and gather list of valid charges
if mod.item.ID in checkedTypes:
continue
checkedTypes.add(mod.item.ID)
@@ -41,10 +46,6 @@ class ModuleAmmoPicker(ContextMenu):
def getText(self, itmContext, selection):
return "Charge"
def activate(self, fullContext, selection, i):
pass
DAMAGE_TYPES = ("em", "explosive", "kinetic", "thermal")
def turretSorter(self, charge):
damage = 0
range = (self.module.getModifiedItemAttr("maxRange") or 0) * (charge.getAttribute("weaponRangeMultiplier") or 1)
@@ -57,15 +58,14 @@ class ModuleAmmoPicker(ContextMenu):
# Take optimal and half falloff as range factor
rangeFactor = range + falloff / 2
return (- rangeFactor, charge.name.rsplit()[-2:], damage, charge.name)
return - rangeFactor, charge.name.rsplit()[-2:], damage, charge.name
MISSILE_ORDER = ("em", "thermal", "kinetic", "explosive", "mixed")
def missileSorter(self, charge):
# Get charge damage type and total damage
chargeDamageType, totalDamage = self.damageInfo(charge)
# Find its position in sort list
position = self.MISSILE_ORDER.index(chargeDamageType)
return (position, totalDamage, charge.name)
return position, totalDamage, charge.name
def damageInfo(self, charge):
# Set up data storage for missile damage stuff
@@ -90,7 +90,6 @@ class ModuleAmmoPicker(ContextMenu):
return chargeDamageType, totalDamage
def numericConverter(self, string):
return int(string) if string.isdigit() else string
@@ -98,11 +97,12 @@ class ModuleAmmoPicker(ContextMenu):
parts = charge.name.split(" ")
return map(self.numericConverter, parts)
def addCharge(self, menu, charge):
def addCharge(self, rootMenu, charge):
id = wx.NewId()
name = charge.name if charge is not None else "Empty"
self.chargeIds[id] = charge
item = wx.MenuItem(menu, id, name)
item = wx.MenuItem(rootMenu, id, name)
rootMenu.Bind(wx.EVT_MENU, self.handleAmmoSwitch, item)
item.charge = charge
if charge is not None and charge.icon is not None:
bitmap = bitmapLoader.getBitmap(charge.icon.iconFile, "pack")
@@ -116,11 +116,8 @@ class ModuleAmmoPicker(ContextMenu):
m.Append(id, u'%s' % text)
m.Enable(id, False)
def getSubMenu(self, context, selection, menu, i, pitem):
self.context = context
menu.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
def getSubMenu(self, context, selection, rootMenu, i, pitem):
m = wx.Menu()
m.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.chargeIds = {}
hardpoint = self.module.hardpoint
moduleName = self.module.item.name
@@ -150,7 +147,7 @@ class ModuleAmmoPicker(ContextMenu):
base = charge
nameBase = currBase
range = currRange
item = self.addCharge(m, charge)
item = self.addCharge(rootMenu, charge)
items.append(item)
else:
if sub is None:
@@ -158,9 +155,9 @@ class ModuleAmmoPicker(ContextMenu):
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")
item.SetSubMenu(sub)
sub.AppendItem(self.addCharge(sub, base))
sub.AppendItem(self.addCharge(rootMenu, base))
sub.AppendItem(self.addCharge(sub, charge))
sub.AppendItem(self.addCharge(rootMenu, charge))
if sub is not None:
self.addSeperator(sub, "More Damage")
@@ -194,20 +191,20 @@ class ModuleAmmoPicker(ContextMenu):
m.AppendItem(item)
if charge.name not in ("Light Defender Missile I", "Heavy Defender Missile I"):
sub.AppendItem(self.addCharge(sub, charge))
sub.AppendItem(self.addCharge(rootMenu, charge))
else:
defender = charge
if defender is not None:
m.AppendItem(self.addCharge(sub, defender))
m.AppendItem(self.addCharge(rootMenu, defender))
if sub is not None:
self.addSeperator(sub, "More Damage")
else:
self.charges.sort(key=self.nameSorter)
for charge in self.charges:
m.AppendItem(self.addCharge(m, charge))
m.AppendItem(self.addCharge(rootMenu, charge))
m.AppendItem(self.addCharge(m, None))
m.AppendItem(self.addCharge(rootMenu, None))
return m
def handleAmmoSwitch(self, event):

View File

@@ -33,7 +33,7 @@ class ModuleGlobalAmmoPicker(ModuleAmmoPicker):
selectedModule = self.modules[0]
allModules = []
for mod in fit.modules:
if mod.itemID == None:
if mod.itemID is None:
continue
if mod.itemID == selectedModule.itemID:
allModules.append(mod)

View File

@@ -8,7 +8,7 @@ class OpenFit(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return "projectedFit" in srcContext
return srcContext == "projectedFit"
def getText(self, itmContext, selection):
return "Open Fit in New Tab"

View File

@@ -9,7 +9,7 @@ class PriceClear(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
return "priceViewFull" in srcContext
return srcContext == "priceViewFull"
def getText(self, itmContext, selection):
return "Reset Price Cache"

View File

@@ -9,10 +9,7 @@ class ShipJump(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
validContexts = ("fittingShip")
if not srcContext in validContexts:
return False
return True
return srcContext == "fittingShip"
def getText(self, itmContext, selection):
return "Open in Ship Browser"

View File

@@ -12,36 +12,36 @@ class TacticalMode(ContextMenu):
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
self.ship = sFit.getFit(fitID).ship
self.modes = self.ship.getValidModes()
self.modeItems = self.ship.getModeItems()
if not srcContext in ("fittingShip") or self.modes is None:
return False
return True
return srcContext == "fittingShip" and self.modeItems is not None
def getText(self, itmContext, selection):
return "Modes"
return "Tactical Modes"
def handleModeChange(self, event):
mode = self.modeIds[event.Id]
print mode
# @todo fit service change mode
def addMode(self, menu, mode):
label = mode.item.name.rsplit()[-2]
def addMode(self, rootMenu, item):
label = item.name.rsplit()[-2]
id = wx.NewId()
self.modeIds[id] = mode
menuItem = wx.MenuItem(menu, id, label, kind=wx.ITEM_CHECK)
menu.Bind(wx.EVT_MENU, self.handleModeChange, menuItem)
self.itemIds[id] = item
menuItem = wx.MenuItem(rootMenu, id, label, kind=wx.ITEM_RADIO)
rootMenu.Bind(wx.EVT_MENU, self.handleMode, menuItem)
return menuItem
def getSubMenu(self, context, selection, menu, i, pitem):
sub = wx.Menu()
self.modeIds = {}
# Items that have a parent
for mode in self.modes:
sub.AppendItem(self.addMode(sub, mode))
def getSubMenu(self, context, selection, rootMenu, i, pitem):
self.context = context
self.itemIds = {}
return sub
m = wx.Menu()
for item in self.modeItems:
menuItem = self.addMode(rootMenu, item)
m.AppendItem(menuItem)
return m
def handleMode(self, event):
item = self.itemIds[event.Id]
print item
# @todo fit service change mode
TacticalMode.register()

View File

@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
from gui.contextMenu import ContextMenu
import gui.mainFrame
import service
@@ -17,21 +15,18 @@ class TargetResists(ContextMenu):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, srcContext, selection):
if self.mainFrame.getActiveFit() is None or srcContext not in ("firepowerViewFull",):
if self.mainFrame.getActiveFit() is None or srcContext != "firepowerViewFull":
return False
sTR = service.TargetResists.getInstance()
self.patterns = sTR.getTargetResistsList()
self.patterns.sort( key=lambda p: (p.name in ["None"], p.name) )
self.patterns.sort(key=lambda p: (p.name in ["None"], p.name))
return len(self.patterns) > 0
def getText(self, itmContext, selection):
return "Target Resists"
def activate(self, fullContext, selection, i):
pass
def handleResistSwitch(self, event):
pattern = self.patternIds.get(event.Id, False)
if pattern is False:
@@ -43,12 +38,14 @@ class TargetResists(ContextMenu):
sFit.setTargetResists(fitID, pattern)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def addPattern(self, menu, pattern, currBase = None):
def addPattern(self, rootMenu, pattern):
id = wx.NewId()
name = getattr(pattern, "_name", pattern.name) if pattern is not None else "No Profile"
self.patternIds[id] = pattern
item = wx.MenuItem(menu, id, name)
item = wx.MenuItem(rootMenu, id, name)
rootMenu.Bind(wx.EVT_MENU, self.handleResistSwitch, item)
# set pattern attr to menu item
item.pattern = pattern
@@ -63,21 +60,12 @@ class TargetResists(ContextMenu):
item.SetBitmap(bitmap)
return item
def addSeperator(self, m, text):
id = wx.NewId()
m.Append(id, u'%s' % text)
m.Enable(id, False)
def getSubMenu(self, context, selection, menu, i, pitem):
self.context = context
menu.Bind(wx.EVT_MENU, self.handleResistSwitch)
m = wx.Menu()
m.Bind(wx.EVT_MENU, self.handleResistSwitch)
def getSubMenu(self, context, selection, rootMenu, i, pitem):
self.patternIds = {}
self.subMenus = OrderedDict()
self.singles = []
sub = wx.Menu()
for pattern in self.patterns:
start, end = pattern.name.find('['), pattern.name.find(']')
if start is not -1 and end is not -1:
@@ -90,30 +78,30 @@ class TargetResists(ContextMenu):
else:
self.singles.append(pattern)
m.AppendItem(self.addPattern(m, None)) # Add reset
m.AppendSeparator()
sub.AppendItem(self.addPattern(rootMenu, None)) # Add reset
sub.AppendSeparator()
# Single items, no parent
for pattern in self.singles:
m.AppendItem(self.addPattern(m, pattern))
sub.AppendItem(self.addPattern(rootMenu, pattern))
# Items that have a parent
for menuName, patterns in self.subMenus.items():
# Create parent item for root menu that is simply name of parent
item = wx.MenuItem(menu, wx.NewId(), menuName)
item = wx.MenuItem(rootMenu, wx.NewId(), menuName)
# Create menu for child items
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handleResistSwitch)
grandSub = wx.Menu()
#sub.Bind(wx.EVT_MENU, self.handleResistSwitch)
# Apply child menu to parent item
item.SetSubMenu(sub)
item.SetSubMenu(grandSub)
# Append child items to child menu
for pattern in patterns:
sub.AppendItem(self.addPattern(sub, pattern))
m.AppendItem(item) #finally, append parent item to root menu
grandSub.AppendItem(self.addPattern(rootMenu, pattern))
sub.AppendItem(item) #finally, append parent item to root menu
return m
return sub
TargetResists.register()

View File

@@ -14,29 +14,27 @@ class WhProjector(ContextMenu):
def getText(self, itmContext, selection):
return "Add System Effects"
def activate(self, fullContext, selection, i):
pass
def getSubMenu(self, context, selection, menu, i, pitem):
self.idmap = {}
menu.Bind(wx.EVT_MENU, self.handleSelection)
m = wx.Menu()
def getSubMenu(self, context, selection, rootMenu, i, pitem):
sMkt = service.Market.getInstance()
effdata = sMkt.getSystemWideEffects()
self.idmap = {}
sub = wx.Menu()
for swType in sorted(effdata):
item = wx.MenuItem(m, wx.ID_ANY, swType)
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handleSelection)
item.SetSubMenu(sub)
m.AppendItem(item)
subItem = wx.MenuItem(sub, wx.ID_ANY, swType)
grandSub = wx.Menu()
subItem.SetSubMenu(grandSub)
sub.AppendItem(subItem)
for swData in sorted(effdata[swType], key=lambda tpl: tpl[2]):
wxid = wx.NewId()
swObj, swName, swClass = swData
self.idmap[wxid] = (swObj, swName)
subitem = wx.MenuItem(sub, wxid, swClass)
sub.AppendItem(subitem)
return m
grandSubItem = wx.MenuItem(grandSub, wxid, swClass)
rootMenu.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem)
grandSub.AppendItem(grandSubItem)
return sub
def handleSelection(self, event):
#Skip events ids that aren't mapped

View File

@@ -21,29 +21,47 @@ import wx
class ContextMenu(object):
menus = []
@classmethod
def register(cls):
ContextMenu.menus.append(cls)
@classmethod
def getMenu(cls, selection, *fullContexts):
menu = wx.Menu()
menu.info = {}
menu.selection = selection
"""
getMenu returns a menu that is used with wx.PopupMenu.
selection: provides a list of what was selected. If only 1 item was
selected, it's is a 1-item list or tuple. Can also be None for
contexts without selection, such as statsPane or projected view
fullContexts: a number of tuples of the following tuple:
srcContext - context were menu was spawned, eg: projectedFit,
cargoItem, etc
itemContext - usually the name of the item's category
eg:
(('fittingModule', 'Module'), ('fittingShip', 'Ship'))
(('marketItemGroup', 'Implant'),)
(('fittingShip', 'Ship'),)
"""
rootMenu = wx.Menu()
rootMenu.info = {}
rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection
empty = True
menu.Bind(wx.EVT_MENU, cls.handler)
for i, fullContext in enumerate(fullContexts):
amount = 0
srcContext = fullContext[0]
try:
itmContext = fullContext[1]
itemContext = fullContext[1]
except IndexError:
itmContext = None
itemContext = None
for menuHandler in cls.menus:
# loop through registered menus
m = menuHandler()
if m.display(srcContext, selection):
amount += 1
texts = m.getText(itmContext, selection)
texts = m.getText(itemContext, selection)
if isinstance(texts, basestring):
texts = (texts,)
@@ -51,54 +69,72 @@ class ContextMenu(object):
multiple = not isinstance(bitmap, wx.Bitmap)
for it, text in enumerate(texts):
id = wx.NewId()
item = wx.MenuItem(menu, id, text)
menu.info[id] = (m, fullContext, it)
rootItem = wx.MenuItem(rootMenu, id, text)
rootMenu.info[id] = (m, fullContext, it)
sub = m.getSubMenu(srcContext, selection, menu, it, item)
if sub is not None:
item.SetSubMenu(sub)
sub = m.getSubMenu(srcContext, selection, rootMenu, it, rootItem)
if sub is None:
# if there is no sub menu, bind the handler to the rootItem
rootMenu.Bind(wx.EVT_MENU, cls.handler, rootItem)
else:
# If there is a submenu, it is expected that the sub
# logic take care of it's own binding. No binding is
# done here
#
# It is important to remember that when binding sub
# menu items, bind them to the rootMenu for proper
# event handling, eg:
# rootMenu.Bind(wx.EVE_MENU, self.handle, menuItem)
rootItem.SetSubMenu(sub)
if bitmap is not None:
if multiple:
bp = bitmap[it]
if bp:
item.SetBitmap(bp)
rootItem.SetBitmap(bp)
else:
item.SetBitmap(bitmap)
rootItem.SetBitmap(bitmap)
menu.AppendItem(item)
rootMenu.AppendItem(rootItem)
empty = False
if amount > 0 and i != len(fullContexts) - 1:
menu.AppendSeparator()
rootMenu.AppendSeparator()
return menu if empty is False else None
return rootMenu if empty is False else None
@classmethod
def handler(cls, event):
menu = event.EventObject
stuff = menu.info.get(event.Id)
if stuff is not None:
m, context, i = stuff
menuHandler, context, i = stuff
selection = menu.selection
if not hasattr(selection, "__iter__"):
selection = (selection,)
m.activate(context, selection, i)
menuHandler.activate(context, selection, i)
else:
event.Skip()
def display(self, context, selection):
raise NotImplementedError()
def activate(self, context, selection, i):
def activate(self, fullContext, selection, i):
return None
def getSubMenu(self, context, selection, menu, i, pitem):
def getSubMenu(self, context, selection, rootMenu, i, pitem):
return None
def getText(self, context, selection):
"""
getText should be implemented in child classes, and should return either
a string that will make up a menu item label or a list of strings which
will make numerous menu items.
These menu items will be added to the root menu
"""
raise NotImplementedError()
def getBitmap(self, context, selection):