Move addition pane views into their own directory

This commit is contained in:
Ryan Holmes
2017-06-12 01:17:00 -04:00
parent a79257271e
commit 9dee761f6d
11 changed files with 23 additions and 23 deletions

View File

View File

@@ -0,0 +1,180 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
import gui.globalEvents as GE
import gui.marketBrowser as marketBrowser
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from gui.utils.staticHelpers import DragDropHelper
from service.fit import Fit
class BoosterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(BoosterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
dragged_data = DragDropHelper.data
data = dragged_data.split(':')
self.dropFn(x, y, data)
return t
class BoosterView(d.Display):
DEFAULT_COLS = [
"State",
"attr:boosterness",
"Base Name",
"Price",
]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.SetDropTarget(BoosterViewDrop(self.handleListDrag))
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def handleListDrag(self, x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
"""
if data[0] == "market":
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
if row != -1:
self.removeBooster(self.boosters[self.GetItemData(row)])
event.Skip()
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
event.Skip()
return
self.origional = fit.boosters if fit is not None else None
self.boosters = stuff = fit.boosters[:] if fit is not None else None
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
if item != -1:
self.EnsureVisible(item)
self.deselectItems()
self.populate(stuff)
self.refresh(stuff)
event.Skip()
def addItem(self, event):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if not fit or fit.isStructure:
return
trigger = sFit.addBooster(fitID, event.itemID)
if trigger:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
self.mainFrame.additionsPane.select("Boosters")
event.Skip()
def removeItem(self, event):
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
self.removeBooster(self.boosters[self.GetItemData(row)])
def removeBooster(self, booster):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.removeBooster(fitID, self.origional.index(booster))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def click(self, event):
event.Skip()
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.toggleBooster(fitID, row)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
wx.CallAfter(self.spawnMenu)
def spawnMenu(self):
sel = self.GetFirstSelected()
if sel != -1:
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
item = fit.boosters[sel]
srcContext = "boosterItem"
itemContext = "Booster"
menu = ContextMenu.getMenu((item,), (srcContext, itemContext))
self.PopupMenu(menu)

View File

@@ -0,0 +1,194 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
import gui.globalEvents as GE
from gui.utils.staticHelpers import DragDropHelper
from service.fit import Fit
from service.market import Market
class CargoViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(CargoViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
dragged_data = DragDropHelper.data
data = dragged_data.split(':')
self.dropFn(x, y, data)
return t
# @todo: Was copied form another class and modified. Look through entire file, refine
class CargoView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"attr:volume",
"Price"]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.SetDropTarget(CargoViewDrop(self.handleListDrag))
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def handleListDrag(self, x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
"""
if data[0] == "fitting":
self.swapModule(x, y, int(data[1]))
elif data[0] == "market":
sFit = Fit.getInstance()
sFit.addCargo(self.mainFrame.getActiveFit(), int(data[1]), 1)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def startDrag(self, event):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
dataStr = "cargo:" + str(row)
data.SetText(dataStr)
dropSource = wx.DropSource(self)
dropSource.SetData(data)
DragDropHelper.data = dataStr
dropSource.DoDragDrop()
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
row = self.GetFirstSelected()
if row != -1:
sFit.removeCargo(fitID, self.GetItemData(row))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
event.Skip()
def swapModule(self, x, y, modIdx):
"""Swap a module from fitting window with cargo"""
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
dstRow, _ = self.HitTest((x, y))
mstate = wx.GetMouseState()
# Gather module information to get position
module = fit.modules[modIdx]
if dstRow != -1: # we're swapping with cargo
if mstate.CmdDown(): # if copying, append to cargo
sFit.addCargo(self.mainFrame.getActiveFit(), module.item.ID)
else: # else, move / swap
sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.position, dstRow)
else: # dragging to blank spot, append
sFit.addCargo(self.mainFrame.getActiveFit(), module.item.ID)
if not mstate.CmdDown(): # if not copying, remove module
sFit.removeModule(self.mainFrame.getActiveFit(), module.position)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit(), action="moddel", typeID=module.item.ID))
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
event.Skip()
return
self.original = fit.cargo if fit is not None else None
self.cargo = stuff = fit.cargo if fit is not None else None
if stuff is not None:
stuff.sort(key=lambda cargo: cargo.itemID)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
if item != -1:
self.EnsureVisible(item)
self.deselectItems()
self.populate(stuff)
self.refresh(stuff)
event.Skip()
def removeItem(self, event):
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
cargo = self.cargo[self.GetItemData(row)]
sFit.removeCargo(fitID, self.original.index(cargo))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
wx.CallAfter(self.spawnMenu)
def spawnMenu(self):
sel = self.GetFirstSelected()
if sel != -1:
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
cargo = fit.cargo[sel]
sMkt = Market.getInstance()
sourceContext = "cargoItem"
itemContext = sMkt.getCategoryByItem(cargo.item).name
menu = ContextMenu.getMenu((cargo,), (sourceContext, itemContext))
self.PopupMenu(menu)

View File

@@ -0,0 +1,224 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.builtinAdditionPanes.droneView
import gui.display as d
import gui.globalEvents as GE
from eos.saveddata.drone import Drone as es_Drone
from gui.builtinContextMenus.commandFits import CommandFits
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from gui.utils.staticHelpers import DragDropHelper
from service.fit import Fit
class DummyItem(object):
def __init__(self, txt):
self.name = txt
self.icon = None
class DummyEntry(object):
def __init__(self, txt):
self.item = DummyItem(txt)
class CommandViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(CommandViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
dragged_data = DragDropHelper.data
data = dragged_data.split(':')
self.dropFn(x, y, data)
return t
class CommandView(d.Display):
DEFAULT_COLS = ["State", "Base Name"]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, CommandFits.populateFits)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_RIGHT_DOWN, self.click)
self.Bind(wx.EVT_LEFT_DCLICK, self.remove)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.droneView = gui.builtinAdditionPanes.droneView.DroneView
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(CommandViewDrop(self.handleListDrag))
@staticmethod
def handleListDrag(x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
"""
pass
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
row = self.GetFirstSelected()
if row != -1:
sFit.removeCommand(fitID, self.get(row))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def handleDrag(self, type, fitID):
# Those are drags coming from pyfa sources, NOT builtin wx drags
if type == "fit":
activeFit = self.mainFrame.getActiveFit()
if activeFit:
sFit = Fit.getInstance()
draggedFit = sFit.getFit(fitID)
sFit.addCommandFit(activeFit, draggedFit)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit))
def startDrag(self, event):
row = event.GetIndex()
if row != -1 and isinstance(self.get(row), es_Drone):
data = wx.PyTextDataObject()
dataStr = "command:" + str(self.GetItemData(row))
data.SetText(dataStr)
dropSource = wx.DropSource(self)
dropSource.SetData(data)
DragDropHelper.data = dataStr
dropSource.DoDragDrop()
@staticmethod
def fitSort(fit):
return fit.name
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
event.Skip()
return
stuff = []
if fit is not None:
self.fits = fit.commandFits[:]
self.fits.sort(key=self.fitSort)
stuff.extend(self.fits)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
if item != -1:
self.EnsureVisible(item)
self.deselectItems()
# todo: verify
if not stuff:
stuff = [DummyEntry("Drag a fit to this area")]
self.update(stuff)
def get(self, row):
numFits = len(self.fits)
if numFits == 0:
return None
return self.fits[row]
def click(self, event):
event.Skip()
row, _ = self.HitTest(event.Position)
if row != -1:
item = self.get(row)
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.toggleCommandFit(fitID, item)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
wx.CallAfter(self.spawnMenu)
def spawnMenu(self):
sel = self.GetFirstSelected()
menu = None
if sel != -1:
item = self.get(sel)
if item is None:
return
fitSrcContext = "commandFit"
fitItemContext = item.name
context = ((fitSrcContext, fitItemContext),)
context += ("commandView",),
menu = ContextMenu.getMenu((item,), *context)
elif sel == -1:
fitID = self.mainFrame.getActiveFit()
if fitID is None:
return
context = (("commandView",),)
menu = ContextMenu.getMenu([], *context)
if menu is not None:
self.PopupMenu(menu)
def remove(self, event):
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
thing = self.get(row)
if thing: # thing doesn't exist if it's the dummy value
sFit.removeCommand(fitID, thing)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))

View File

@@ -0,0 +1,259 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from gui.marketBrowser import ITEM_SELECTED, ItemSelected
from gui.display import Display
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from gui.utils.staticHelpers import DragDropHelper
from service.fit import Fit
from service.market import Market
class DroneViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(DroneViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
dragged_data = DragDropHelper.data
data = dragged_data.split(':')
self.dropFn(x, y, data)
return t
class DroneView(Display):
DEFAULT_COLS = [
"State",
# "Base Icon",
"Base Name",
# "prop:droneDps,droneBandwidth",
"Max Range",
"Miscellanea",
"attr:maxVelocity",
"Price",
]
def __init__(self, parent):
Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
self.hoveredRow = None
self.hoveredColumn = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(DroneViewDrop(self.handleDragDrop))
def OnLeaveWindow(self, event):
self.SetToolTip(None)
self.hoveredRow = None
self.hoveredColumn = None
event.Skip()
def OnMouseMove(self, event):
row, _, col = self.HitTestSubItem(event.Position)
if row != self.hoveredRow or col != self.hoveredColumn:
if self.ToolTip is not None:
self.SetToolTip(None)
else:
self.hoveredRow = row
self.hoveredColumn = col
if row != -1 and col != -1 and col < len(self.DEFAULT_COLS):
mod = self.drones[self.GetItemData(row)]
if self.DEFAULT_COLS[col] == "Miscellanea":
tooltip = self.activeColumns[col].getToolTip(mod)
if tooltip is not None:
self.SetToolTipString(tooltip)
else:
self.SetToolTip(None)
else:
self.SetToolTip(None)
else:
self.SetToolTip(None)
event.Skip()
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
if row != -1:
drone = self.drones[self.GetItemData(row)]
self.removeDrone(drone)
event.Skip()
def startDrag(self, event):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
dataStr = "drone:" + str(row)
data.SetText(dataStr)
dropSource = wx.DropSource(self)
dropSource.SetData(data)
DragDropHelper.data = dataStr
dropSource.DoDragDrop()
def handleDragDrop(self, x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
"""
if data[0] == "drone": # we want to merge drones
srcRow = int(data[1])
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
elif data[0] == "market":
wx.PostEvent(self.mainFrame, ItemSelected(itemID=int(data[1])))
def _merge(self, src, dst):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
if sFit.mergeDrones(fitID, self.drones[src], self.drones[dst]):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
DRONE_ORDER = ('Light Scout Drones', 'Medium Scout Drones',
'Heavy Attack Drones', 'Sentry Drones', 'Fighters',
'Fighter Bombers', 'Combat Utility Drones',
'Electronic Warfare Drones', 'Logistic Drones', 'Mining Drones', 'Salvage Drones')
def droneKey(self, drone):
sMkt = Market.getInstance()
groupName = sMkt.getMarketGroupByItem(drone.item).name
return (self.DRONE_ORDER.index(groupName),
drone.item.name)
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
event.Skip()
return
self.original = fit.drones if fit is not None else None
self.drones = stuff = fit.drones[:] if fit is not None else None
if stuff is not None:
stuff.sort(key=self.droneKey)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
if item != -1:
self.EnsureVisible(item)
self.deselectItems()
self.update(stuff)
event.Skip()
def addItem(self, event):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if not fit or fit.isStructure:
return
trigger = sFit.addDrone(fitID, event.itemID)
if trigger:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
self.mainFrame.additionsPane.select("Drones")
event.Skip()
def removeItem(self, event):
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
drone = self.drones[self.GetItemData(row)]
self.removeDrone(drone)
def removeDrone(self, drone):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.removeDrone(fitID, self.original.index(drone))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def click(self, event):
event.Skip()
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
drone = self.drones[row]
sFit.toggleDrone(fitID, self.original.index(drone))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
wx.CallAfter(self.spawnMenu)
def spawnMenu(self):
sel = self.GetFirstSelected()
if sel != -1:
drone = self.drones[sel]
sMkt = Market.getInstance()
sourceContext = "droneItem"
itemContext = sMkt.getCategoryByItem(drone.item).name
menu = ContextMenu.getMenu((drone,), (sourceContext, itemContext))
self.PopupMenu(menu)

View File

@@ -0,0 +1,316 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import gui.marketBrowser as marketBrowser
import gui.mainFrame
import gui.display as d
from gui.builtinViewColumns.state import State
from eos.saveddata.module import Slot
from gui.contextMenu import ContextMenu
from gui.utils.staticHelpers import DragDropHelper
from service.fit import Fit
from service.market import Market
class FighterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(FighterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
dragged_data = DragDropHelper.data
data = dragged_data.split(':')
self.dropFn(x, y, data)
return t
class FighterView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.labels = ["Light", "Heavy", "Support"]
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.fighterDisplay = FighterDisplay(self)
mainSizer.Add(self.fighterDisplay, 1, wx.EXPAND, 0)
textSizer = wx.BoxSizer(wx.HORIZONTAL)
textSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
for x in self.labels:
lbl = wx.StaticText(self, wx.ID_ANY, x.capitalize())
textSizer.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
lbl = wx.StaticText(self, wx.ID_ANY, "0")
setattr(self, "label%sUsed" % (x.capitalize()), lbl)
textSizer.Add(lbl, 0, wx.ALIGN_CENTER | wx.LEFT, 5)
textSizer.Add(wx.StaticText(self, wx.ID_ANY, "/"), 0, wx.ALIGN_CENTER)
lbl = wx.StaticText(self, wx.ID_ANY, "0")
setattr(self, "label%sTotal" % (x.capitalize()), lbl)
textSizer.Add(lbl, 0, wx.ALIGN_CENTER)
textSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
mainSizer.Add(textSizer, 0, wx.EXPAND, 5)
self.SetSizer(mainSizer)
self.SetAutoLayout(True)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
def fitChanged(self, event):
sFit = Fit.getInstance()
activeFitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(activeFitID)
if fit:
for x in self.labels:
slot = getattr(Slot, "F_{}".format(x.upper()))
used = fit.getSlotsUsed(slot)
total = fit.getNumSlots(slot)
color = wx.Colour(204, 51, 51) if used > total else wx.SystemSettings_GetColour(
wx.SYS_COLOUR_WINDOWTEXT)
lbl = getattr(self, "label%sUsed" % x.capitalize())
lbl.SetLabel(str(int(used)))
lbl.SetForegroundColour(color)
lbl = getattr(self, "label%sTotal" % x.capitalize())
lbl.SetLabel(str(int(total)))
lbl.SetForegroundColour(color)
self.Refresh()
class FighterDisplay(d.Display):
DEFAULT_COLS = ["State",
# "Base Icon",
"Base Name",
# "prop:droneDps,droneBandwidth",
# "Max Range",
# "Miscellanea",
"attr:maxVelocity",
"Fighter Abilities"
# "Price",
]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
self.hoveredRow = None
self.hoveredColumn = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(FighterViewDrop(self.handleDragDrop))
def OnLeaveWindow(self, event):
self.SetToolTip(None)
self.hoveredRow = None
self.hoveredColumn = None
event.Skip()
def OnMouseMove(self, event):
row, _, col = self.HitTestSubItem(event.Position)
if row != self.hoveredRow or col != self.hoveredColumn:
if self.ToolTip is not None:
self.SetToolTip(None)
else:
self.hoveredRow = row
self.hoveredColumn = col
if row != -1 and col != -1 and col < len(self.DEFAULT_COLS):
mod = self.fighters[self.GetItemData(row)]
if self.DEFAULT_COLS[col] == "Miscellanea":
tooltip = self.activeColumns[col].getToolTip(mod)
if tooltip is not None:
self.SetToolTipString(tooltip)
else:
self.SetToolTip(None)
else:
self.SetToolTip(None)
else:
self.SetToolTip(None)
event.Skip()
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
if row != -1:
fighter = self.fighters[self.GetItemData(row)]
self.removeFighter(fighter)
event.Skip()
def startDrag(self, event):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
dataStr = "fighter:" + str(row)
data.SetText(dataStr)
dropSource = wx.DropSource(self)
dropSource.SetData(data)
DragDropHelper.data = dataStr
dropSource.DoDragDrop()
def handleDragDrop(self, x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
"""
if data[0] == "fighter": # we want to merge fighters
srcRow = int(data[1])
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
elif data[0] == "market":
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
@staticmethod
def _merge(src, dst):
return
'''
DRONE_ORDER = ('Light Scout Drones', 'Medium Scout Drones',
'Heavy Attack Drones', 'Sentry Drones', 'Fighters',
'Fighter Bombers', 'Combat Utility Drones',
'Electronic Warfare Drones', 'Logistic Drones', 'Mining Drones', 'Salvage Drones',
'Light Fighters', 'Heavy Fighters', 'Support Fighters')
def droneKey(self, drone):
sMkt = Market.getInstance()
groupName = sMkt.getMarketGroupByItem(drone.item).name
print groupName
return (self.DRONE_ORDER.index(groupName),
drone.item.name)
'''
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.Parent.DisablePage(self.Parent, not fit)
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
event.Skip()
return
self.original = fit.fighters if fit is not None else None
self.fighters = stuff = fit.fighters[:] if fit is not None else None
'''
if stuff is not None:
stuff.sort(key=self.droneKey)
'''
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
if item != -1:
self.EnsureVisible(item)
self.deselectItems()
self.update(stuff)
event.Skip()
def addItem(self, event):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
trigger = sFit.addFighter(fitID, event.itemID)
if trigger:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
self.mainFrame.additionsPane.select("Fighters")
event.Skip()
def removeItem(self, event):
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
fighter = self.fighters[self.GetItemData(row)]
self.removeFighter(fighter)
def removeFighter(self, fighter):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.removeFighter(fitID, self.original.index(fighter))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def click(self, event):
event.Skip()
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
fighter = self.fighters[row]
sFit.toggleFighter(fitID, self.original.index(fighter))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
wx.CallAfter(self.spawnMenu)
def spawnMenu(self):
sel = self.GetFirstSelected()
if sel != -1:
fighter = self.fighters[sel]
sMkt = Market.getInstance()
sourceContext = "fighterItem"
itemContext = sMkt.getCategoryByItem(fighter.item).name
menu = ContextMenu.getMenu((fighter,), (sourceContext, itemContext))
self.PopupMenu(menu)

View File

@@ -0,0 +1,226 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
import gui.marketBrowser as marketBrowser
import gui.mainFrame
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
import gui.globalEvents as GE
from eos.saveddata.fit import ImplantLocation
from service.fit import Fit
from service.market import Market
class ImplantView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, style=wx.TAB_TRAVERSAL)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.implantDisplay = ImplantDisplay(self)
mainSizer.Add(self.implantDisplay, 1, wx.EXPAND, 0)
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
radioSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
self.rbFit = wx.RadioButton(self, id=wx.ID_ANY, label="Use Fit-specific Implants", style=wx.RB_GROUP)
self.rbChar = wx.RadioButton(self, id=wx.ID_ANY, label="Use Character Implants")
radioSizer.Add(self.rbFit, 0, wx.ALL, 5)
radioSizer.Add(self.rbChar, 0, wx.ALL, 5)
radioSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
mainSizer.Add(radioSizer, 0, wx.EXPAND, 5)
self.SetSizer(mainSizer)
self.SetAutoLayout(True)
self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelect, self.rbFit)
self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelect, self.rbChar)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
def fitChanged(self, event):
sFit = Fit.getInstance()
activeFitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(activeFitID)
if fit:
self.source = fit.implantSource
if fit.implantSource == ImplantLocation.FIT:
self.rbFit.SetValue(True)
else:
self.rbChar.SetValue(True)
self.rbFit.Enable(fit is not None)
self.rbChar.Enable(fit is not None)
def OnRadioSelect(self, event):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.toggleImplantSource(fitID, ImplantLocation.FIT if self.rbFit.GetValue() else ImplantLocation.CHARACTER)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
class ImplantDisplay(d.Display):
DEFAULT_COLS = [
"State",
"attr:implantness",
"Base Icon",
"Base Name",
"Price",
]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
row = self.GetFirstSelected()
if row != -1:
self.removeImplant(self.implants[self.GetItemData(row)])
event.Skip()
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.Parent.Parent.Parent.DisablePage(self.Parent, not fit or fit.isStructure)
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
event.Skip()
return
self.original = fit.implants if fit is not None else None
self.implants = stuff = fit.appliedImplants if fit is not None else None
if stuff is not None:
stuff.sort(key=lambda implant: implant.slot)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
if item != -1:
self.EnsureVisible(item)
self.deselectItems()
self.update(stuff)
event.Skip()
def addItem(self, event):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if not fit or fit.isStructure:
return
trigger = sFit.addImplant(fitID, event.itemID)
if trigger:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
self.mainFrame.additionsPane.select("Implants")
event.Skip()
def removeItem(self, event):
# Character implants can't be changed here...
if self.Parent.source == ImplantLocation.CHARACTER:
return
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
self.removeImplant(self.implants[self.GetItemData(row)])
def removeImplant(self, implant):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.removeImplant(fitID, self.original.index(implant))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def click(self, event):
event.Skip()
# Character implants can't be changed here...
if self.Parent.source == ImplantLocation.CHARACTER:
return
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.toggleImplant(fitID, row)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
wx.CallAfter(self.spawnMenu)
def spawnMenu(self):
sel = self.GetFirstSelected()
menu = None
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
if not fit:
return
if sel != -1:
implant = fit.appliedImplants[sel]
sMkt = Market.getInstance()
sourceContext = "implantItem" if fit.implantSource == ImplantLocation.FIT else "implantItemChar"
itemContext = sMkt.getCategoryByItem(implant.item).name
menu = ContextMenu.getMenu((implant,), (sourceContext, itemContext))
elif sel == -1 and fit.implantSource == ImplantLocation.FIT:
fitID = self.mainFrame.getActiveFit()
if fitID is None:
return
context = (("implantView",),)
menu = ContextMenu.getMenu([], *context)
if menu is not None:
self.PopupMenu(menu)

View File

@@ -0,0 +1,50 @@
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
import gui.globalEvents as GE
import gui.mainFrame
class NotesView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.lastFitId = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.editNotes = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.BORDER_NONE, )
mainSizer.Add(self.editNotes, 1, wx.EXPAND)
self.SetSizer(mainSizer)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.Bind(wx.EVT_TEXT, self.onText)
self.saveTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.delayedSave, self.saveTimer)
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
self.saveTimer.Stop() # cancel any pending timers
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
# when switching fits, ensure that we save the notes for the previous fit
if self.lastFitId is not None:
sFit.editNotes(self.lastFitId, self.editNotes.GetValue())
if event.fitID is None and self.lastFitId is not None:
self.lastFitId = None
event.Skip()
return
elif event.fitID != self.lastFitId:
self.lastFitId = event.fitID
self.editNotes.SetValue(fit.notes or "")
def onText(self, event):
# delay the save so we're not writing to sqlite on every keystroke
self.saveTimer.Stop() # cancel the existing timer
self.saveTimer.Start(1000, True)
def delayedSave(self, event):
sFit = Fit.getInstance()
sFit.editNotes(self.lastFitId, self.editNotes.GetValue())

View File

@@ -0,0 +1,314 @@
# =============================================================================
# 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 <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from logbook import Logger
import gui.builtinAdditionPanes.droneView
import gui.display as d
import gui.globalEvents as GE
from eos.saveddata.drone import Drone as es_Drone
from eos.saveddata.fighter import Fighter as es_Fighter
from eos.saveddata.module import Module as es_Module
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from gui.utils.staticHelpers import DragDropHelper
from service.fit import Fit
from service.market import Market
pyfalog = Logger(__name__)
class DummyItem(object):
def __init__(self, txt):
self.name = txt
self.icon = None
class DummyEntry(object):
def __init__(self, txt):
self.item = DummyItem(txt)
class ProjectedViewDrop(wx.PyDropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(ProjectedViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
if self.GetData():
dragged_data = DragDropHelper.data
data = dragged_data.split(':')
self.dropFn(x, y, data)
return t
class ProjectedView(d.Display):
DEFAULT_COLS = ["State",
"Ammo Icon",
"Base Icon",
"Base Name",
"Ammo"]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_RIGHT_DOWN, self.click)
self.Bind(wx.EVT_LEFT_DCLICK, self.remove)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
self.droneView = gui.builtinAdditionPanes.droneView.DroneView
if "__WXGTK__" in wx.PlatformInfo:
self.Bind(wx.EVT_RIGHT_UP, self.scheduleMenu)
else:
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(ProjectedViewDrop(self.handleListDrag))
def handleListDrag(self, x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
"""
if data[0] == "projected":
# if source is coming from projected, we are trying to combine drones.
self.mergeDrones(x, y, int(data[1]))
elif data[0] == "market":
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
sFit.project(fitID, int(data[1]))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE:
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
row = self.GetFirstSelected()
if row != -1:
sFit.removeProjected(fitID, self.get(row))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def handleDrag(self, type, fitID):
# Those are drags coming from pyfa sources, NOT builtin wx drags
if type == "fit":
activeFit = self.mainFrame.getActiveFit()
if activeFit:
sFit = Fit.getInstance()
draggedFit = sFit.getFit(fitID)
sFit.project(activeFit, draggedFit)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit))
def startDrag(self, event):
row = event.GetIndex()
if row != -1 and isinstance(self.get(row), es_Drone):
data = wx.PyTextDataObject()
dataStr = "projected:" + str(self.GetItemData(row))
data.SetText(dataStr)
dropSource = wx.DropSource(self)
dropSource.SetData(data)
DragDropHelper.data = dataStr
dropSource.DoDragDrop()
def mergeDrones(self, x, y, itemID):
srcRow = self.FindItemData(-1, itemID)
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
def _merge(self, src, dst):
dstDrone = self.get(dst)
if isinstance(dstDrone, es_Drone):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
if sFit.mergeDrones(fitID, self.get(src), dstDrone, True):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
@staticmethod
def moduleSort(module):
return module.item.name
@staticmethod
def fighterSort(fighter):
return fighter.item.name
def droneSort(self, drone):
item = drone.item
if item.marketGroup is None:
item = item.metaGroup.parent
return (self.droneView.DRONE_ORDER.index(item.marketGroup.name),
drone.item.name)
@staticmethod
def fitSort(fit):
return fit.name
def fitChanged(self, event):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
pyfalog.debug("ProjectedView::fitChanged: {}", repr(fit))
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
# Clear list and get out if current fitId is None
if event.fitID is None and self.lastFitId is not None:
self.DeleteAllItems()
self.lastFitId = None
event.Skip()
return
stuff = []
if fit is not None:
pyfalog.debug(" Collecting list of stuff to display in ProjectedView")
self.modules = fit.projectedModules[:]
self.drones = fit.projectedDrones[:]
self.fighters = fit.projectedFighters[:]
self.fits = fit.projectedFits[:]
self.modules.sort(key=self.moduleSort)
self.drones.sort(key=self.droneSort)
self.fighters.sort(key=self.fighterSort)
self.fits.sort(key=self.fitSort)
stuff.extend(self.modules)
stuff.extend(self.drones)
stuff.extend(self.fighters)
stuff.extend(self.fits)
if event.fitID != self.lastFitId:
self.lastFitId = event.fitID
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
if item != -1:
self.EnsureVisible(item)
self.deselectItems()
if not stuff:
stuff = [DummyEntry("Drag an item or fit, or use right-click menu for system effects")]
self.update(stuff)
def get(self, row):
numMods = len(self.modules)
numDrones = len(self.drones)
numFighters = len(self.fighters)
numFits = len(self.fits)
if (numMods + numDrones + numFighters + numFits) == 0:
return None
if row < numMods:
stuff = self.modules[row]
elif row - numMods < numDrones:
stuff = self.drones[row - numMods]
elif row - numMods - numDrones < numFighters:
stuff = self.fighters[row - numMods - numDrones]
else:
stuff = self.fits[row - numMods - numDrones - numFighters]
return stuff
def click(self, event):
event.Skip()
row, _ = self.HitTest(event.Position)
if row != -1:
item = self.get(row)
col = self.getColumn(event.Position)
if col == self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
sFit.toggleProjected(fitID, item, "right" if event.Button == 3 else "left")
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
def scheduleMenu(self, event):
event.Skip()
if self.getColumn(event.Position) != self.getColIndex(State):
wx.CallAfter(self.spawnMenu)
def spawnMenu(self):
sel = self.GetFirstSelected()
menu = None
if sel != -1:
item = self.get(sel)
if item is None:
return
sMkt = Market.getInstance()
if isinstance(item, es_Drone):
srcContext = "projectedDrone"
itemContext = sMkt.getCategoryByItem(item.item).name
context = ((srcContext, itemContext),)
elif isinstance(item, es_Fighter):
srcContext = "projectedFighter"
itemContext = sMkt.getCategoryByItem(item.item).name
context = ((srcContext, itemContext),)
elif isinstance(item, es_Module):
modSrcContext = "projectedModule"
modItemContext = sMkt.getCategoryByItem(item.item).name
modFullContext = (modSrcContext, modItemContext)
if item.charge is not None:
chgSrcContext = "projectedCharge"
chgItemContext = sMkt.getCategoryByItem(item.charge).name
chgFullContext = (chgSrcContext, chgItemContext)
context = (modFullContext, chgFullContext)
else:
context = (modFullContext,)
else:
fitSrcContext = "projectedFit"
fitItemContext = item.name
context = ((fitSrcContext, fitItemContext),)
context += ("projected",),
menu = ContextMenu.getMenu((item,), *context)
elif sel == -1:
fitID = self.mainFrame.getActiveFit()
if fitID is None:
return
context = (("projected",),)
menu = ContextMenu.getMenu([], *context)
if menu is not None:
self.PopupMenu(menu)
def remove(self, event):
row, _ = self.HitTest(event.Position)
if row != -1:
col = self.getColumn(event.Position)
if col != self.getColIndex(State):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
thing = self.get(row)
if thing: # thing doesn't exist if it's the dummy value
sFit.removeProjected(fitID, thing)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))