diff --git a/gui/builtinAdditionPanes/droneView.py b/gui/builtinAdditionPanes/droneView.py index 12ddac1e4..9afa30190 100644 --- a/gui/builtinAdditionPanes/droneView.py +++ b/gui/builtinAdditionPanes/droneView.py @@ -65,7 +65,7 @@ class DroneView(Display): ] def __init__(self, parent): - Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE) + Display.__init__(self, parent, style=wx.BORDER_NONE) self.lastFitId = None @@ -120,20 +120,22 @@ class DroneView(Display): def kbEvent(self, event): keycode = event.GetKeyCode() + mstate = wx.GetMouseState() + if keycode == wx.WXK_ESCAPE and not mstate.cmdDown and not mstate.altDown and not mstate.shiftDown: + self.unselectAll() + if keycode == 65 and mstate.cmdDown and not mstate.altDown and not mstate.shiftDown: + self.selectAll() if keycode == wx.WXK_DELETE or keycode == wx.WXK_NUMPAD_DELETE: - row = self.GetFirstSelected() - if row != -1: - try: - drone = self.drones[self.GetItemData(row)] - except IndexError: - return - self.removeDroneStack(drone) - + drones = self.getSelectedDrones() + self.removeDroneStacks(drones) event.Skip() def startDrag(self, event): row = event.GetIndex() if row != -1: + self.unselectAll() + self.Select(row, True) + data = wx.TextDataObject() dataStr = "drone:" + str(row) data.SetText(dataStr) @@ -245,7 +247,7 @@ class DroneView(Display): except IndexError: return if mstate.cmdDown or mstate.altDown: - self.removeDroneStack(drone) + self.removeDroneStacks([drone]) else: self.removeDrone(drone) @@ -253,41 +255,72 @@ class DroneView(Display): fitID = self.mainFrame.getActiveFit() if drone in self.original: position = self.original.index(drone) - self.mainFrame.command.Submit(cmd.GuiRemoveLocalDroneCommand( - fitID=fitID, position=position, amount=1)) + self.mainFrame.command.Submit(cmd.GuiRemoveLocalDronesCommand( + fitID=fitID, positions=[position], amount=1)) - def removeDroneStack(self, drone): + def removeDroneStacks(self, drones): fitID = self.mainFrame.getActiveFit() - if drone in self.original: - position = self.original.index(drone) - self.mainFrame.command.Submit(cmd.GuiRemoveLocalDroneCommand( - fitID=fitID, position=position, amount=math.inf)) + positions = [] + for drone in drones: + if drone in self.original: + positions.append(self.original.index(drone)) + self.mainFrame.command.Submit(cmd.GuiRemoveLocalDronesCommand( + fitID=fitID, positions=positions, amount=math.inf)) def click(self, event): - event.Skip() - row, _ = self.HitTest(event.Position) - if row != -1: + mainRow, _ = self.HitTest(event.Position) + if mainRow != -1: col = self.getColumn(event.Position) if col == self.getColIndex(State): fitID = self.mainFrame.getActiveFit() try: - drone = self.drones[row] + mainDrone = self.drones[mainRow] except IndexError: return - if drone in self.original: - position = self.original.index(drone) - self.mainFrame.command.Submit(cmd.GuiToggleLocalDroneStateCommand( - fitID=fitID, position=position)) + if mainDrone in self.original: + mainPosition = self.original.index(mainDrone) + positions = [] + for row in self.getSelectedRows(): + try: + drone = self.drones[row] + except IndexError: + continue + if drone in self.original: + positions.append(self.original.index(drone)) + self.mainFrame.command.Submit(cmd.GuiToggleLocalDroneStatesCommand( + fitID=fitID, + mainPosition=mainPosition, + positions=positions)) + return + event.Skip() def spawnMenu(self, event): - sel = self.GetFirstSelected() - if sel != -1: + selection = self.getSelectedDrones() + clickedPos = self.getRow(event.Position) + mainDrone = None + if clickedPos != -1: try: - drone = self.drones[sel] + drone = self.drones[clickedPos] except IndexError: - return - sMkt = Market.getInstance() - sourceContext = "droneItem" - itemContext = sMkt.getCategoryByItem(drone.item).name - menu = ContextMenu.getMenu(drone, (drone,), (sourceContext, itemContext)) + pass + else: + if drone in self.original: + mainDrone = drone + # Fall back to first selected item only if position is -1 + elif len(selection) > 0: + mainDrone = selection[0] + sourceContext = "droneItem" + itemContext = Market.getInstance().getCategoryByItem(mainDrone.item).name if mainDrone is not None else mainDrone + menu = ContextMenu.getMenu(mainDrone, selection, (sourceContext, itemContext)) + if menu: self.PopupMenu(menu) + + def getSelectedDrones(self): + drones = [] + for row in self.getSelectedRows(): + try: + drone = self.drones[self.GetItemData(row)] + except IndexError: + continue + drones.append(drone) + return drones diff --git a/gui/builtinContextMenus/itemRemove.py b/gui/builtinContextMenus/itemRemove.py index 666b96294..3023fe7b4 100644 --- a/gui/builtinContextMenus/itemRemove.py +++ b/gui/builtinContextMenus/itemRemove.py @@ -48,16 +48,18 @@ class RemoveItem(ContextMenuCombined): positions = getSimilarModPositions(fit.modules, mainItem) else: positions = [] - for position, mod in enumerate(fit.modules): - if mod in selection: - positions.append(position) + for mod in selection: + if mod in fit.modules: + positions.append(fit.modules.index(mod)) self.mainFrame.command.Submit(cmd.GuiRemoveLocalModuleCommand( fitID=fitID, positions=positions)) elif srcContext == "droneItem": - if mainItem in fit.drones: - position = fit.drones.index(mainItem) - self.mainFrame.command.Submit(cmd.GuiRemoveLocalDroneCommand( - fitID=fitID, position=position, amount=math.inf)) + positions = [] + for drone in selection: + if drone in fit.drones: + positions.append(fit.drones.index(drone)) + self.mainFrame.command.Submit(cmd.GuiRemoveLocalDronesCommand( + fitID=fitID, positions=positions, amount=math.inf)) elif srcContext == "fighterItem": if mainItem in fit.fighters: position = fit.fighters.index(mainItem) diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 54b469b92..5ba353793 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -268,19 +268,15 @@ class FittingView(d.Display): dropSource.DoDragDrop() def getSelectedMods(self): - sel = [] - row = self.GetFirstSelected() - while row != -1: + mods = [] + for row in self.getSelectedRows(): try: mod = self.mods[self.GetItemData(row)] except IndexError: - row = self.GetNextSelected(row) continue if mod and not isinstance(mod, Rack): - sel.append(mod) - row = self.GetNextSelected(row) - - return sel + mods.append(mod) + return mods def kbEvent(self, event): keycode = event.GetKeyCode() diff --git a/gui/display.py b/gui/display.py index 5052e5b18..38668ea09 100644 --- a/gui/display.py +++ b/gui/display.py @@ -25,6 +25,7 @@ from gui.cachingImageList import CachingImageList class Display(wx.ListCtrl): + DEFAULT_COLS = None def __init__(self, parent, size=wx.DefaultSize, style=0): @@ -284,3 +285,11 @@ class Display(wx.ListCtrl): if fallback is not None: return fallback return row + + def getSelectedRows(self): + rows = [] + row = self.GetFirstSelected() + while row != -1: + rows.append(row) + row = self.GetNextSelected(row) + return rows diff --git a/gui/fitCommands/__init__.py b/gui/fitCommands/__init__.py index 7ffc4dc04..08e118097 100644 --- a/gui/fitCommands/__init__.py +++ b/gui/fitCommands/__init__.py @@ -21,10 +21,10 @@ from .gui.itemsRebase import GuiRebaseItemsCommand from .gui.localDrone.add import GuiAddLocalDroneCommand from .gui.localDrone.changeAmount import GuiChangeLocalDroneAmountCommand from .gui.localDrone.changeMeta import GuiChangeLocalDroneMetaCommand -from .gui.localDrone.remove import GuiRemoveLocalDroneCommand +from .gui.localDrone.remove import GuiRemoveLocalDronesCommand from .gui.localDrone.stackSplit import GuiSplitLocalDroneStackCommand from .gui.localDrone.stacksMerge import GuiMergeLocalDroneStacksCommand -from .gui.localDrone.toggleState import GuiToggleLocalDroneStateCommand +from .gui.localDrone.toggleStates import GuiToggleLocalDroneStatesCommand from .gui.localFighter.abilityToggleState import GuiToggleLocalFighterAbilityStateCommand from .gui.localFighter.add import GuiAddLocalFighterCommand from .gui.localFighter.changeAmount import GuiChangeLocalFighterAmountCommand diff --git a/gui/fitCommands/calc/drone/localAdd.py b/gui/fitCommands/calc/drone/localAdd.py index 7fe9019f4..88c96be2c 100644 --- a/gui/fitCommands/calc/drone/localAdd.py +++ b/gui/fitCommands/calc/drone/localAdd.py @@ -15,7 +15,7 @@ pyfalog = Logger(__name__) class CalcAddLocalDroneCommand(wx.Command): def __init__(self, fitID, droneInfo, forceNewStack=False, commit=True): - wx.Command.__init__(self, True, 'Add Drone') + wx.Command.__init__(self, True, 'Add Local Drone') self.fitID = fitID self.droneInfo = droneInfo self.forceNewStack = forceNewStack diff --git a/gui/fitCommands/calc/drone/localChangeAmount.py b/gui/fitCommands/calc/drone/localChangeAmount.py index 9f6b2fa07..f0836362a 100644 --- a/gui/fitCommands/calc/drone/localChangeAmount.py +++ b/gui/fitCommands/calc/drone/localChangeAmount.py @@ -12,7 +12,7 @@ pyfalog = Logger(__name__) class CalcChangeLocalDroneAmountCommand(wx.Command): def __init__(self, fitID, position, amount, commit=True): - wx.Command.__init__(self, True, 'Change Drone Amount') + wx.Command.__init__(self, True, 'Change Local Drone Amount') self.fitID = fitID self.position = position self.amount = amount diff --git a/gui/fitCommands/calc/drone/localRemove.py b/gui/fitCommands/calc/drone/localRemove.py index 80362f933..bebcb0c60 100644 --- a/gui/fitCommands/calc/drone/localRemove.py +++ b/gui/fitCommands/calc/drone/localRemove.py @@ -13,7 +13,7 @@ pyfalog = Logger(__name__) class CalcRemoveLocalDroneCommand(wx.Command): def __init__(self, fitID, position, amount, commit=True): - wx.Command.__init__(self, True, 'Remove Drone') + wx.Command.__init__(self, True, 'Remove Local Drone') self.fitID = fitID self.position = position self.amountToRemove = amount diff --git a/gui/fitCommands/calc/drone/localToggleState.py b/gui/fitCommands/calc/drone/localToggleState.py deleted file mode 100644 index 557a44ff9..000000000 --- a/gui/fitCommands/calc/drone/localToggleState.py +++ /dev/null @@ -1,37 +0,0 @@ -import wx -from logbook import Logger - -import eos.db -from service.fit import Fit - - -pyfalog = Logger(__name__) - - -class CalcToggleLocalDroneStateCommand(wx.Command): - - def __init__(self, fitID, position, forceAmountActive=None): - wx.Command.__init__(self, True, 'Toggle Drone State') - self.fitID = fitID - self.position = position - self.forceAmountActive = forceAmountActive - self.savedAmountActive = None - - def Do(self): - pyfalog.debug('Doing toggling of local drone state at position {} for fit {}'.format(self.position, self.fitID)) - fit = Fit.getInstance().getFit(self.fitID) - drone = fit.drones[self.position] - self.savedAmountActive = drone.amountActive - if self.forceAmountActive is not None: - drone.amountActive = self.forceAmountActive - elif drone.amountActive > 0: - drone.amountActive = 0 - else: - drone.amountActive = drone.amount - eos.db.commit() - return True - - def Undo(self): - pyfalog.debug('Undoing toggling of local drone state at position {} for fit {}'.format(self.position, self.fitID)) - cmd = CalcToggleLocalDroneStateCommand(fitID=self.fitID, position=self.position, forceAmountActive=self.savedAmountActive) - return cmd.Do() diff --git a/gui/fitCommands/calc/drone/localToggleStates.py b/gui/fitCommands/calc/drone/localToggleStates.py new file mode 100644 index 000000000..eccd98006 --- /dev/null +++ b/gui/fitCommands/calc/drone/localToggleStates.py @@ -0,0 +1,55 @@ +import wx +from logbook import Logger + +import eos.db +from service.fit import Fit + + +pyfalog = Logger(__name__) + + +class CalcToggleLocalDroneStatesCommand(wx.Command): + + def __init__(self, fitID, mainPosition, positions, forceActiveAmounts=None): + wx.Command.__init__(self, True, 'Toggle Local Drone States') + self.fitID = fitID + self.mainPosition = mainPosition + self.positions = positions + self.forceActiveAmounts = forceActiveAmounts + self.savedActiveAmounts = None + + def Do(self): + pyfalog.debug('Doing toggling of local drone state at position {}/{} for fit {}'.format(self.mainPosition, self.positions, self.fitID)) + fit = Fit.getInstance().getFit(self.fitID) + + positions = self.positions[:] + if self.mainPosition not in positions: + positions.append(self.mainPosition) + self.savedActiveAmounts = {p: fit.drones[p].amountActive for p in positions} + + if self.forceActiveAmounts is not None: + for position, amountActive in self.forceActiveAmounts.items(): + drone = fit.drones[position] + drone.amountActive = amountActive + elif fit.drones[self.mainPosition].amountActive > 0: + for position in positions: + drone = fit.drones[position] + if drone.amountActive > 0: + drone.amountActive = 0 + else: + for position in positions: + drone = fit.drones[position] + if drone.amountActive == 0: + drone.amountActive = drone.amount + + eos.db.commit() + return True + + def Undo(self): + pyfalog.debug('Undoing toggling of local drone state at position {}/{} for fit {}'.format(self.mainPosition, self.positions, self.fitID)) + cmd = CalcToggleLocalDroneStatesCommand( + fitID=self.fitID, + mainPosition=self.mainPosition, + positions=self.positions, + forceActiveAmounts=self.savedActiveAmounts) + return cmd.Do() diff --git a/gui/fitCommands/calc/module/localChangeStates.py b/gui/fitCommands/calc/module/localChangeStates.py index e86612a44..7722e08a7 100644 --- a/gui/fitCommands/calc/module/localChangeStates.py +++ b/gui/fitCommands/calc/module/localChangeStates.py @@ -29,6 +29,8 @@ class CalcChangeLocalModuleStatesCommand(wx.Command): if mainMod.isEmpty: return False positions = [pos for pos in self.positions if not fit.modules[pos].isEmpty] + if self.mainPosition not in positions: + positions.append(self.mainPosition) self.savedStates = {pos: fit.modules[pos].state for pos in positions} changed = False diff --git a/gui/fitCommands/calc/module/localRemove.py b/gui/fitCommands/calc/module/localRemove.py index c5a5baf34..6001bf9d0 100644 --- a/gui/fitCommands/calc/module/localRemove.py +++ b/gui/fitCommands/calc/module/localRemove.py @@ -15,8 +15,8 @@ class CalcRemoveLocalModulesCommand(wx.Command): wx.Command.__init__(self, True, 'Remove Module') self.fitID = fitID self.positions = positions - self.savedModInfos = {} self.commit = commit + self.savedModInfos = None self.savedStateCheckChanges = None def Do(self): @@ -24,6 +24,7 @@ class CalcRemoveLocalModulesCommand(wx.Command): sFit = Fit.getInstance() fit = sFit.getFit(self.fitID) + self.savedModInfos = {} for position in self.positions: mod = fit.modules[position] if not mod.isEmpty: diff --git a/gui/fitCommands/gui/localDrone/remove.py b/gui/fitCommands/gui/localDrone/remove.py index 72a99b21d..24dec98e8 100644 --- a/gui/fitCommands/gui/localDrone/remove.py +++ b/gui/fitCommands/gui/localDrone/remove.py @@ -1,5 +1,6 @@ import wx +import eos.db import gui.mainFrame from gui import globalEvents as GE from gui.fitCommands.calc.drone.localRemove import CalcRemoveLocalDroneCommand @@ -7,24 +8,33 @@ from gui.fitCommands.helpers import InternalCommandHistory from service.fit import Fit -class GuiRemoveLocalDroneCommand(wx.Command): +class GuiRemoveLocalDronesCommand(wx.Command): - def __init__(self, fitID, position, amount): - wx.Command.__init__(self, True, 'Remove Local Drone') + def __init__(self, fitID, positions, amount): + wx.Command.__init__(self, True, 'Remove Local Drones') self.internalHistory = InternalCommandHistory() self.fitID = fitID - self.position = position + self.positions = positions self.amount = amount def Do(self): - cmd = CalcRemoveLocalDroneCommand(fitID=self.fitID, position=self.position, amount=self.amount) - success = self.internalHistory.submit(cmd) + results = [] + for position in self.positions: + cmd = CalcRemoveLocalDroneCommand( + fitID=self.fitID, + position=position, + amount=self.amount, + commit=False) + results.append(self.internalHistory.submit(cmd)) + success = any(results) + eos.db.commit() Fit.getInstance().recalc(self.fitID) wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitID=self.fitID)) return success def Undo(self): success = self.internalHistory.undoAll() + eos.db.commit() Fit.getInstance().recalc(self.fitID) wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitID=self.fitID)) return success diff --git a/gui/fitCommands/gui/localDrone/toggleState.py b/gui/fitCommands/gui/localDrone/toggleStates.py similarity index 63% rename from gui/fitCommands/gui/localDrone/toggleState.py rename to gui/fitCommands/gui/localDrone/toggleStates.py index 003032c00..656e2a1a6 100644 --- a/gui/fitCommands/gui/localDrone/toggleState.py +++ b/gui/fitCommands/gui/localDrone/toggleStates.py @@ -2,21 +2,25 @@ import wx import gui.mainFrame from gui import globalEvents as GE -from gui.fitCommands.calc.drone.localToggleState import CalcToggleLocalDroneStateCommand +from gui.fitCommands.calc.drone.localToggleStates import CalcToggleLocalDroneStatesCommand from gui.fitCommands.helpers import InternalCommandHistory from service.fit import Fit -class GuiToggleLocalDroneStateCommand(wx.Command): +class GuiToggleLocalDroneStatesCommand(wx.Command): - def __init__(self, fitID, position): - wx.Command.__init__(self, True, 'Toggle Local Drone State') + def __init__(self, fitID, mainPosition, positions): + wx.Command.__init__(self, True, 'Toggle Local Drone States') self.internalHistory = InternalCommandHistory() self.fitID = fitID - self.position = position + self.mainPosition = mainPosition + self.positions = positions def Do(self): - cmd = CalcToggleLocalDroneStateCommand(fitID=self.fitID, position=self.position) + cmd = CalcToggleLocalDroneStatesCommand( + fitID=self.fitID, + mainPosition=self.mainPosition, + positions=self.positions) success = self.internalHistory.submit(cmd) Fit.getInstance().recalc(self.fitID) wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitID=self.fitID))