#=============================================================================== # 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 . #=============================================================================== import wx from wx.lib.scrolledpanel import ScrolledPanel import service import gui.mainFrame import gui.shipBrowser import gui.globalEvents as GE from gui import characterEditor as CharEditor class GangView ( ScrolledPanel ): def __init__( self, parent ): ScrolledPanel.__init__ ( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 100,20 ), style = wx.TAB_TRAVERSAL | wx.HSCROLL | wx.VSCROLL ) mainSizer = wx.BoxSizer( wx.VERTICAL ) self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.draggedFitID = None help = '''Set fit as booster to display in dropdown, or drag fitting from\nship browser to this window, or right click fit and select booster role.''' helpSizer = wx.BoxSizer( wx.HORIZONTAL ) self.helpText = wx.StaticText( self, wx.ID_ANY, help, wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE ) helpSizer.Add( self.helpText, 1, wx.ALL, 5 ) self.options = ["Fleet", "Wing", "Squad"] self.fleet = {} for id, option in enumerate(self.options): # set content for each commander self.fleet[id] = {} self.fleet[id]['stLabel'] = wx.StaticText( self, wx.ID_ANY, self.options[id]+':', wx.DefaultPosition, wx.DefaultSize, 0 ) self.fleet[id]['stText'] = wx.StaticText( self, wx.ID_ANY, 'None', wx.DefaultPosition, wx.DefaultSize, 0 ) self.fleet[id]['chFit'] = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [] ) self.fleet[id]['chChar'] = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [] ) self.fleet[id]['fitSizer'] = wx.BoxSizer( wx.VERTICAL ) self.FitDNDPopupMenu = self.buildBoostermenu() contentFGSizer = wx.FlexGridSizer( 5, 3, 0, 0 ) contentFGSizer.AddGrowableCol( 1 ) contentFGSizer.SetFlexibleDirection( wx.BOTH ) contentFGSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) ### Header self.stBooster = wx.StaticText( self, wx.ID_ANY, u"Booster", wx.DefaultPosition, wx.DefaultSize, 0 ) self.stBooster.Wrap( -1 ) self.stBooster.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) ) contentFGSizer.Add( self.stBooster, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5 ) self.stFits = wx.StaticText( self, wx.ID_ANY, u"Fits", wx.DefaultPosition, wx.DefaultSize, 0 ) self.stFits.Wrap( -1 ) self.stFits.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) ) contentFGSizer.Add( self.stFits, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL, 5 ) self.stCharacters = wx.StaticText( self, wx.ID_ANY, u"Characters", wx.DefaultPosition, wx.DefaultSize, 0 ) self.stCharacters.Wrap( -1 ) self.stCharacters.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) ) contentFGSizer.Add( self.stCharacters, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL, 5 ) self.m_staticline2 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) contentFGSizer.Add( self.m_staticline2, 0, wx.EXPAND, 5 ) self.m_staticline3 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) contentFGSizer.Add( self.m_staticline3, 0, wx.EXPAND, 5 ) self.m_staticline4 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) contentFGSizer.Add( self.m_staticline4, 0, wx.EXPAND, 5 ) ### Content for id in self.fleet: # set various properties self.fleet[id]['stLabel'].Wrap( -1 ) self.fleet[id]['stLabel'].SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) ) self.fleet[id]['stText'].Wrap( -1 ) # bind text and choice events self.fleet[id]['stText'].Bind(wx.EVT_LEFT_DCLICK, self.RemoveBooster) self.fleet[id]['stText'].Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow) self.fleet[id]['stText'].Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) self.fleet[id]['stText'].SetToolTip(wx.ToolTip("Double click to remove booster")) self.fleet[id]['chChar'].Bind(wx.EVT_CHOICE, self.CharChanged) self.fleet[id]['chFit'].Bind(wx.EVT_CHOICE, self.OnFitChoiceSelected) # add fit text and choice to the fit sizer self.fleet[id]['fitSizer'].Add( self.fleet[id]['stText'], 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) self.fleet[id]['fitSizer'].Add( self.fleet[id]['chFit'], 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND, 1 ) # add everything to the content sizer contentFGSizer.Add( self.fleet[id]['stLabel'], 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) contentFGSizer.Add( self.fleet[id]['fitSizer'], 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND, 5 ) contentFGSizer.Add( self.fleet[id]['chChar'], 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) mainSizer.Add( contentFGSizer, 1, wx.EXPAND, 0 ) mainSizer.Add( helpSizer, 0, wx.EXPAND, 0 ) self.SetSizer( mainSizer ) self.SetAutoLayout(True) self.SetupScrolling() self.mainFrame.Bind(GE.CHAR_LIST_UPDATED, self.RefreshCharacterList) self.mainFrame.Bind(GE.FIT_CHANGED, self.fitSelected) self.mainFrame.Bind(gui.shipBrowser.EVT_FIT_RENAMED, self.fitRenamed) self.mainFrame.Bind(gui.shipBrowser.BOOSTER_LIST_UPDATED, self.RefreshBoosterFits) self.RefreshBoosterFits() self.RefreshCharacterList() def buildBoostermenu(self): menu = wx.Menu() for id, option in enumerate(self.options): item = menu.Append(-1, option) # We bind it to the mainFrame because it may be called from either this class or from FitItem via shipBrowser self.mainFrame.Bind(wx.EVT_MENU, self.OnPopupItemSelected, item) return menu def OnEnterWindow(self, event): obj = event.GetEventObject() obj.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) event.Skip() def OnLeaveWindow(self, event): obj = event.GetEventObject() obj.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) event.Skip() def CharChanged(self, event): ''' Change booster character ''' chBooster = event.GetEventObject() type = -1 for id in self.fleet: if chBooster == self.fleet[id]['chChar']: type = id if type == -1: event.Skip() return sFit = service.Fit.getInstance() fleetSrv = service.Fleet.getInstance() activeFitID = self.mainFrame.getActiveFit() fit = sFit.getFit(activeFitID) sChar = service.Character.getInstance() charList = sChar.getCharacterList() if activeFitID: commanders = fleetSrv.loadLinearFleet(fit) if commanders is None: fleetCom, wingCom, squadCom = (None, None, None) else: fleetCom, wingCom, squadCom = commanders if type == 0: if fleetCom: charID = chBooster.GetClientData(chBooster.GetSelection()) sFit.changeChar(fleetCom.ID, charID) else: chBooster.SetSelection(0) if type == 1: if wingCom: charID = chBooster.GetClientData(chBooster.GetSelection()) sFit.changeChar(wingCom.ID, charID) else: chBooster.SetSelection(0) if type == 2: if squadCom: charID = chBooster.GetClientData(chBooster.GetSelection()) sFit.changeChar(squadCom.ID, charID) else: chBooster.SetSelection(0) sFit.recalc(fit, withBoosters=True) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFitID)) else: chBooster.SetSelection(0) def RemoveBooster(self, event): activeFitID = self.mainFrame.getActiveFit() if not activeFitID: return location = event.GetEventObject() for id in self.fleet: if location == self.fleet[id]['stText']: type = id sFit = service.Fit.getInstance() boostee = sFit.getFit(activeFitID) booster = None fleetSrv = service.Fleet.getInstance() if type == 0: fleetSrv.setLinearFleetCom(boostee, booster) if type == 1: fleetSrv.setLinearWingCom(boostee, booster) if type == 2: fleetSrv.setLinearSquadCom(boostee, booster) # Hide stText and, default fit selection, and enable it location.Hide() choice = self.fleet[type]['chFit'] choice.SetSelection(0) choice.Show() sFit.recalc(boostee, withBoosters=True) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFitID)) def fitRenamed(self, event): fleetSrv = service.Fleet.getInstance() activeFitID = self.mainFrame.getActiveFit() if activeFitID: ev = event ev.fitID = activeFitID self.fitSelected(ev) def fitSelected(self, event): ''' Fires when active fit is selected and when booster is saved to fit. Update the UI to reflect changes ''' fleetSrv = service.Fleet.getInstance() activeFitID = self.mainFrame.getActiveFit() sFit = service.Fit.getInstance() fit = sFit.getFit(event.fitID or activeFitID) commanders = (None, None, None) if activeFitID: commanders = fleetSrv.loadLinearFleet(fit) for id in self.fleet: # try...except here as we're trying 2 different criteria and want to fall back on the same code try: commander = commanders[id] if not activeFitID or commander is None: raise Exception() self.fleet[id]['stText'].SetLabel(commander.ship.item.name + ": " + commander.name) self.fleet[id]['chChar'].SetStringSelection(commander.character.name if commander.character is not None else "All 0") self.fleet[id]['chChar'].Enable() self.fleet[id]['chFit'].Hide() self.fleet[id]['stText'].Show() except: #set defaults, disable char selection, and enable fit selection self.fleet[id]['stText'].SetLabel("None") self.fleet[id]['chChar'].SetStringSelection("All 0") self.fleet[id]['chChar'].Disable() self.fleet[id]['chFit'].SetSelection(0) self.fleet[id]['chFit'].Show() self.fleet[id]['stText'].Hide() if activeFitID: self.Enable() else: self.Disable() self.Layout() self.SendSizeEvent() def AddCommander(self, fitID, type = None): ''' Adds booster to a fit, then recalculates active fit ''' if type is None: return activeFitID = self.mainFrame.getActiveFit() if activeFitID: sFit = service.Fit.getInstance() boostee = sFit.getFit(activeFitID) booster = sFit.getFit(fitID) fleetSrv = service.Fleet.getInstance() if type == 0: fleetSrv.setLinearFleetCom(boostee, booster) if type == 1: fleetSrv.setLinearWingCom(boostee, booster) if type == 2: fleetSrv.setLinearSquadCom(boostee, booster) sFit.recalc(boostee) wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFitID)) def RefreshBoosterFits(self, event = None): sFit = service.Fit.getInstance() sMkt = service.Market.getInstance() fitList = sFit.getBoosterFits() for id in self.fleet: choice = self.fleet[id]['chFit'] chCurrSelection = choice.GetSelection() chCurrData = -1 if chCurrSelection != -1: chCurrData = choice.GetClientData(chCurrSelection) chCurrSelString = choice.GetString(chCurrSelection) choice.Clear() currSelFound = False choice.Append("None", -1) for fit in fitList: id,name,type = fit ship = sMkt.getItem(type) choice.Append(ship.name+': '+name, id) if chCurrData == id: currSelFound = True if chCurrSelection == -1: choice.SetSelection(0) else: if currSelFound: choice.SetStringSelection(chCurrSelString) else: choice.SetSelection(0) def RefreshCharacterList(self, event = None): sChar = service.Character.getInstance() charList = sChar.getCharacterList() for id in self.fleet: choice = self.fleet[id]['chChar'] chCurrSelection = choice.GetSelection() chCurrData = -1 if chCurrSelection != -1: chCurrData = choice.GetClientData(chCurrSelection) chCurrSelString = choice.GetString(chCurrSelection) choice.Clear() currSelFound = False for char in charList: choice.Append(char.name, char.ID) if chCurrData == char.ID: currSelFound = True if chCurrSelection == -1: choice.SetSelection(1) else: if currSelFound: choice.SetStringSelection(chCurrSelString) else: choice.SetSelection(1) def handleDrag(self, type, fitID): ''' Handle dragging of fit to fleet interface ''' #Those are drags coming from pyfa sources, NOT builtin wx drags self.draggedFitID = None if type == "fit": activeFit = self.mainFrame.getActiveFit() if activeFit: self.draggedFitID = fitID pos = wx.GetMousePosition() pos = self.ScreenToClient(pos) self.PopupMenu(self.FitDNDPopupMenu, pos) def OnPopupItemSelected(self, event): ''' Fired when booster popup item is selected ''' # Get menu selection ID via self.options menuItem = event.EventObject.FindItemById(event.GetId()) type = self.options.index(menuItem.GetText()) if self.draggedFitID: sFit = service.Fit.getInstance() draggedFit = sFit.getFit(self.draggedFitID) self.AddCommander(draggedFit.ID, type) self.mainFrame.additionsPane.select("Fleet") def OnFitChoiceSelected(self, event): ''' Fired when booster choice is selected ''' sFit = service.Fit.getInstance() # set type via choice box used chFit = event.GetEventObject() fitID = chFit.GetClientData(chFit.GetSelection()) type = -1 for id in self.fleet: if chFit == self.fleet[id]['chFit']: type = id if type == -1 or fitID == -1: event.Skip() return fit = sFit.getFit(fitID) self.AddCommander(fit.ID, type) self.mainFrame.additionsPane.select("Fleet")