Large pep8 compliance to make work for Tox

This commit is contained in:
Ebag333
2016-12-13 21:23:01 -08:00
parent b2a5a20650
commit be53dedb18
50 changed files with 2216 additions and 2066 deletions

View File

@@ -22,7 +22,8 @@ import wx
class PFListPane(wx.ScrolledWindow):
def __init__(self, parent):
wx.ScrolledWindow.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(1, 1), style=wx.TAB_TRAVERSAL)
wx.ScrolledWindow.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(1, 1),
style=wx.TAB_TRAVERSAL)
self._wList = []
self._wCount = 0

View File

@@ -2,7 +2,6 @@ import wx
import gui.utils.colorUtils as colorUtils
import gui.utils.drawUtils as drawUtils
SearchButton, EVT_SEARCH_BTN = wx.lib.newevent.NewEvent()
CancelButton, EVT_CANCEL_BTN = wx.lib.newevent.NewEvent()
TextEnter, EVT_TEXT_ENTER = wx.lib.newevent.NewEvent()
@@ -40,7 +39,9 @@ class PFSearchBox(wx.Window):
self._hl = False
w, h = size
self.EditBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, (-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1), wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0))
self.EditBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition,
(-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1),
wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0))
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBk)

View File

@@ -19,7 +19,6 @@
import config
versionString = "{0} {1} - {2} {3}".format(config.version, config.tag, config.expansionName, config.expansionVersion)
licenses = (
"pyfa is released under GNU GPLv3 - see included LICENSE file",

View File

@@ -35,7 +35,6 @@ import gui.chromeTabs
class AdditionsPane(TogglePanel):
def __init__(self, parent):
TogglePanel.__init__(self, parent, forceLayout=1)

View File

@@ -30,7 +30,6 @@ except ImportError:
class BitmapLoader(object):
try:
archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r')
except IOError:

View File

@@ -27,21 +27,21 @@ from service.market import Market
class CargoViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.SetDataObject(self.dropData)
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
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():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
def OnData(self, x, y, t):
if self.GetData():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
# @todo: Was copied form another class and modified. Look through entire file, refine
# @todo: Was copied form another class and modified. Look through entire file, refine
class CargoView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",

View File

@@ -99,14 +99,14 @@ class CharacterEntityEditor(EntityEditor):
class CharacterEditor(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id=wx.ID_ANY, title=u"pyfa: Character Editor", pos=wx.DefaultPosition,
size=wx.Size(640, 600), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=u"pyfa: Character Editor", pos=wx.DefaultPosition,
size=wx.Size(640, 600), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
i = wx.IconFromBitmap(BitmapLoader.getBitmap("character_small", "gui"))
self.SetIcon(i)
self.mainFrame = parent
#self.disableWin = wx.WindowDisabler(self)
# self.disableWin = wx.WindowDisabler(self)
sFit = Fit.getInstance()
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
@@ -179,7 +179,7 @@ class CharacterEditor(wx.Frame):
event.Skip()
def editingFinished(self, event):
#del self.disableWin
# del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
@@ -201,7 +201,7 @@ class CharacterEditor(wx.Frame):
wx.PostEvent(self, GE.CharListUpdated())
def closeEvent(self, event):
#del self.disableWin
# del self.disableWin
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
self.Destroy()
@@ -234,18 +234,20 @@ class CharacterEditor(wx.Frame):
wx.Frame.Destroy(self)
class SkillTreeView (wx.Panel):
class SkillTreeView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TAB_TRAVERSAL)
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.TAB_TRAVERSAL)
self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
pmainSizer = wx.BoxSizer(wx.VERTICAL)
tree = self.skillTreeListCtrl = wx.gizmos.TreeListCtrl(self, wx.ID_ANY, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
tree = self.skillTreeListCtrl = wx.gizmos.TreeListCtrl(self, wx.ID_ANY,
style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
pmainSizer.Add(tree, 1, wx.EXPAND | wx.ALL, 5)
self.imageList = wx.ImageList(16, 16)
tree.SetImageList(self.imageList)
self.skillBookImageId = self.imageList.Add(BitmapLoader.getBitmap("skill_small", "gui"))
@@ -289,7 +291,6 @@ class SkillTreeView (wx.Panel):
self.revertID = wx.NewId()
self.levelChangeMenu.Append(self.revertID, "Revert")
self.saveID = wx.NewId()
self.levelChangeMenu.Append(self.saveID, "Save")
@@ -328,7 +329,7 @@ class SkillTreeView (wx.Panel):
if tree.GetItemText(child) == "dummy":
tree.Delete(child)
#Get the real intrestin' stuff
# Get the real intrestin' stuff
sChar = Character.getInstance()
char = self.charEditor.entityEditor.getActiveEntity()
for id, name in sChar.getSkills(tree.GetPyData(root)):
@@ -391,7 +392,7 @@ class SkillTreeView (wx.Panel):
class ImplantEditorView(BaseImplantEditorView):
def __init__(self, parent):
BaseImplantEditorView.__init__ (self, parent)
BaseImplantEditorView.__init__(self, parent)
self.determineEnabled()
@@ -445,9 +446,10 @@ class ImplantEditorView(BaseImplantEditorView):
self.Enable()
class APIView (wx.Panel):
class APIView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300), style=wx.TAB_TRAVERSAL)
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 300),
style=wx.TAB_TRAVERSAL)
self.charEditor = self.Parent.Parent # first parent is Notebook, second is Character Editor
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
@@ -456,17 +458,17 @@ class APIView (wx.Panel):
pmainSizer = wx.BoxSizer(wx.VERTICAL)
hintSizer = wx.BoxSizer( wx.HORIZONTAL )
hintSizer = wx.BoxSizer(wx.HORIZONTAL)
hintSizer.AddStretchSpacer()
self.stDisabledTip = wx.StaticText( self, wx.ID_ANY, u"You cannot add API Details for All 0 and All 5 characters.\n"
u"Please select another character or make a new one.", style=wx.ALIGN_CENTER )
self.stDisabledTip.Wrap( -1 )
hintSizer.Add( self.stDisabledTip, 0, wx.TOP | wx.BOTTOM, 10 )
self.stDisabledTip = wx.StaticText(self, wx.ID_ANY,
u"You cannot add API Details for All 0 and All 5 characters.\n"
u"Please select another character or make a new one.", style=wx.ALIGN_CENTER)
self.stDisabledTip.Wrap(-1)
hintSizer.Add(self.stDisabledTip, 0, wx.TOP | wx.BOTTOM, 10)
self.stDisabledTip.Hide()
hintSizer.AddStretchSpacer()
pmainSizer.Add(hintSizer, 0, wx.EXPAND, 5)
fgSizerInput = wx.FlexGridSizer(3, 2, 0, 0)
fgSizerInput.AddGrowableCol(1)
fgSizerInput.SetFlexibleDirection(wx.BOTH)
@@ -498,39 +500,44 @@ class APIView (wx.Panel):
pmainSizer.Add(fgSizerInput, 0, wx.EXPAND, 5)
btnSizer = wx.BoxSizer( wx.HORIZONTAL )
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnSizer.AddStretchSpacer()
self.btnFetchCharList = wx.Button(self, wx.ID_ANY, u"Get Characters")
btnSizer.Add(self.btnFetchCharList, 0, wx.ALL, 2)
self.btnFetchCharList.Bind(wx.EVT_BUTTON, self.fetchCharList)
self.btnFetchSkills = wx.Button(self, wx.ID_ANY, u"Fetch Skills")
btnSizer.Add(self.btnFetchSkills, 0, wx.ALL, 2)
self.btnFetchSkills = wx.Button(self, wx.ID_ANY, u"Fetch Skills")
btnSizer.Add(self.btnFetchSkills, 0, wx.ALL, 2)
self.btnFetchSkills.Bind(wx.EVT_BUTTON, self.fetchSkills)
self.btnFetchSkills.Enable(False)
btnSizer.AddStretchSpacer()
pmainSizer.Add(btnSizer, 0, wx.EXPAND, 5)
self.stStatus = wx.StaticText(self, wx.ID_ANY, wx.EmptyString)
self.stStatus = wx.StaticText(self, wx.ID_ANY, wx.EmptyString)
pmainSizer.Add(self.stStatus, 0, wx.ALL, 5)
pmainSizer.AddStretchSpacer()
self.stAPITip = wx.StaticText( self, wx.ID_ANY, u"You can create a pre-defined key here (only CharacterSheet is required):", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stAPITip.Wrap( -1 )
self.stAPITip = wx.StaticText(self, wx.ID_ANY,
u"You can create a pre-defined key here (only CharacterSheet is required):",
wx.DefaultPosition, wx.DefaultSize, 0)
self.stAPITip.Wrap(-1)
pmainSizer.Add( self.stAPITip, 0, wx.ALL, 2 )
pmainSizer.Add(self.stAPITip, 0, wx.ALL, 2)
self.hlEveAPI = wx.HyperlinkCtrl( self, wx.ID_ANY, self.apiUrlCreatePredefined, self.apiUrlCreatePredefined, wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE )
pmainSizer.Add( self.hlEveAPI, 0, wx.ALL, 2 )
self.hlEveAPI = wx.HyperlinkCtrl(self, wx.ID_ANY, self.apiUrlCreatePredefined, self.apiUrlCreatePredefined,
wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE)
pmainSizer.Add(self.hlEveAPI, 0, wx.ALL, 2)
self.stAPITip2 = wx.StaticText( self, wx.ID_ANY, u"Or, you can choose an existing key from:", wx.DefaultPosition, wx.DefaultSize, 0 )
self.stAPITip2.Wrap( -1 )
pmainSizer.Add( self.stAPITip2, 0, wx.ALL, 2 )
self.stAPITip2 = wx.StaticText(self, wx.ID_ANY, u"Or, you can choose an existing key from:", wx.DefaultPosition,
wx.DefaultSize, 0)
self.stAPITip2.Wrap(-1)
pmainSizer.Add(self.stAPITip2, 0, wx.ALL, 2)
self.hlEveAPI2 = wx.HyperlinkCtrl( self, wx.ID_ANY, self.apiUrlKeyList, self.apiUrlKeyList, wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE )
pmainSizer.Add( self.hlEveAPI2, 0, wx.ALL, 2 )
self.hlEveAPI2 = wx.HyperlinkCtrl(self, wx.ID_ANY, self.apiUrlKeyList, self.apiUrlKeyList, wx.DefaultPosition,
wx.DefaultSize, wx.HL_DEFAULT_STYLE)
pmainSizer.Add(self.hlEveAPI2, 0, wx.ALL, 2)
self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)
@@ -587,7 +594,7 @@ class APIView (wx.Panel):
except TimeoutError, e:
self.stStatus.SetLabel("Request timed out. Please check network connectivity and/or proxy settings.")
except Exception, e:
self.stStatus.SetLabel("Error:\n%s"%e.message)
self.stStatus.SetLabel("Error:\n%s" % e.message)
else:
self.charChoice.Clear()
for charName in list:
@@ -611,8 +618,8 @@ class APIView (wx.Panel):
except Exception, e:
self.stStatus.SetLabel("Unable to retrieve %s\'s skills. Error message:\n%s" % (charName, e))
class SaveCharacterAs(wx.Dialog):
class SaveCharacterAs(wx.Dialog):
def __init__(self, parent, charID):
wx.Dialog.__init__(self, parent, title="Save Character As...", size=wx.Size(300, 60))
self.charID = charID
@@ -640,4 +647,3 @@ class SaveCharacterAs(wx.Dialog):
event.Skip()
self.Close()

View File

@@ -26,7 +26,6 @@ from gui.bitmapLoader import BitmapLoader
from service.fit import Fit
_PageChanging, EVT_NOTEBOOK_PAGE_CHANGING = wx.lib.newevent.NewEvent()
_PageChanged, EVT_NOTEBOOK_PAGE_CHANGED = wx.lib.newevent.NewEvent()
_PageAdding, EVT_NOTEBOOK_PAGE_ADDING = wx.lib.newevent.NewEvent()
@@ -527,7 +526,10 @@ class PFTabRenderer:
"""
self.tabRegion = wx.RegionFromBitmap(self.tabBackBitmap)
self.closeBtnRegion = wx.RegionFromBitmap(self.ctabCloseBmp)
self.closeBtnRegion.Offset(self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2, (self.tabHeight - self.ctabCloseBmp.GetHeight()) / 2)
self.closeBtnRegion.Offset(
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2,
(self.tabHeight - self.ctabCloseBmp.GetHeight()) / 2
)
def InitColors(self):
"""Determines colors used for tab, based on system settings"""
@@ -1277,7 +1279,12 @@ class PFTabsContainer(wx.Panel):
selpos = pos
if selected is not skipTab:
selected.SetPosition((selpos, self.containerHeight - self.height))
self.addButton.SetPosition((round(tabsWidth) + self.inclination * 2, self.containerHeight - self.height / 2 - self.addButton.GetHeight() / 3))
self.addButton.SetPosition(
(
round(tabsWidth) + self.inclination * 2,
self.containerHeight - self.height / 2 - self.addButton.GetHeight() / 3
)
)
def OnLeaveWindow(self, event):
@@ -1302,7 +1309,12 @@ class PFTabsContainer(wx.Panel):
if not self.previewTab.GetSelected():
page = self.Parent.GetPage(self.GetTabIndex(self.previewTab))
if page.Snapshot():
self.previewWnd = PFNotebookPagePreview(self, (mposx + 3, mposy + 3), page.Snapshot(), self.previewTab.text)
self.previewWnd = PFNotebookPagePreview(
self,
(mposx + 3, mposy + 3),
page.Snapshot(),
self.previewTab.text
)
self.previewWnd.Show()
event.Skip()
@@ -1310,7 +1322,15 @@ class PFTabsContainer(wx.Panel):
class PFNotebookPagePreview(wx.Frame):
def __init__(self, parent, pos, bitmap, title):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=pos, size=wx.DefaultSize, style=wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP)
wx.Frame.__init__(
self,
parent,
id=wx.ID_ANY,
title=wx.EmptyString,
pos=pos,
size=wx.DefaultSize,
style=wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP
)
self.title = title
self.bitmap = bitmap

View File

@@ -1,180 +1,179 @@
# =============================================================================
# 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/>.
# =============================================================================
import wx
import logging
logger = logging.getLogger(__name__)
class ContextMenu(object):
menus = []
_ids = [] # [wx.NewId() for x in xrange(200)] # init with decent amount
_idxid = -1
@classmethod
def register(cls):
ContextMenu.menus.append(cls)
@classmethod
def getMenu(cls, selection, *fullContexts):
"""
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'),)
"""
cls._idxid = -1
debug_start = len(cls._ids)
rootMenu = wx.Menu()
rootMenu.info = {}
rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection
empty = True
for i, fullContext in enumerate(fullContexts):
amount = 0
srcContext = fullContext[0]
try:
itemContext = fullContext[1]
except IndexError:
itemContext = None
for menuHandler in cls.menus:
# loop through registered menus
m = menuHandler()
if m.display(srcContext, selection):
amount += 1
texts = m.getText(itemContext, selection)
if isinstance(texts, basestring):
texts = (texts,)
bitmap = m.getBitmap(srcContext, selection)
multiple = not isinstance(bitmap, wx.Bitmap)
for it, text in enumerate(texts):
id = cls.nextID()
rootItem = wx.MenuItem(rootMenu, id, text)
rootMenu.info[id] = (m, fullContext, it)
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)
elif sub:
# If sub exists and is not False, set submenu.
# Sub might return False when we have a mix of
# single menu items and submenus (see: damage profile
# context menu)
#
# If there is a submenu, it is expected that the sub
# logic take care of it's own bindings, including for
# any single root items. No binding is done here
#
# It is important to remember that when binding sub
# menu items, the menu to bind to depends on platform.
# Windows should bind to rootMenu, and all other
# platforms should bind to sub menu. See existing
# implementations for examples.
rootItem.SetSubMenu(sub)
if bitmap is not None:
if multiple:
bp = bitmap[it]
if bp:
rootItem.SetBitmap(bp)
else:
rootItem.SetBitmap(bitmap)
rootMenu.AppendItem(rootItem)
empty = False
if amount > 0 and i != len(fullContexts) - 1:
rootMenu.AppendSeparator()
debug_end = len(cls._ids)
if (debug_end - debug_start):
logger.debug("%d new IDs created for this menu" % (debug_end - debug_start))
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:
menuHandler, context, i = stuff
selection = menu.selection
if not hasattr(selection, "__iter__"):
selection = (selection,)
menuHandler.activate(context, selection, i)
else:
event.Skip()
def display(self, context, selection):
raise NotImplementedError()
def activate(self, fullContext, selection, i):
return None
def getSubMenu(self, context, selection, rootMenu, i, pitem):
return None
@classmethod
def nextID(cls):
"""
Fetches an ID from the pool of IDs allocated to Context Menu.
If we don't have enough ID's to fulfill request, create new
ID and add it to the pool.
See GH Issue #589
"""
cls._idxid += 1
if cls._idxid >= len(cls._ids): # We don't ahve an ID for this index, create one
cls._ids.append(wx.NewId())
return cls._ids[cls._idxid]
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):
return None
from gui.builtinContextMenus import * # noqa
# =============================================================================
# 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/>.
# =============================================================================
import wx
import logging
logger = logging.getLogger(__name__)
class ContextMenu(object):
menus = []
_ids = [] # [wx.NewId() for x in xrange(200)] # init with decent amount
_idxid = -1
@classmethod
def register(cls):
ContextMenu.menus.append(cls)
@classmethod
def getMenu(cls, selection, *fullContexts):
"""
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'),)
"""
cls._idxid = -1
debug_start = len(cls._ids)
rootMenu = wx.Menu()
rootMenu.info = {}
rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection
empty = True
for i, fullContext in enumerate(fullContexts):
amount = 0
srcContext = fullContext[0]
try:
itemContext = fullContext[1]
except IndexError:
itemContext = None
for menuHandler in cls.menus:
# loop through registered menus
m = menuHandler()
if m.display(srcContext, selection):
amount += 1
texts = m.getText(itemContext, selection)
if isinstance(texts, basestring):
texts = (texts,)
bitmap = m.getBitmap(srcContext, selection)
multiple = not isinstance(bitmap, wx.Bitmap)
for it, text in enumerate(texts):
id = cls.nextID()
rootItem = wx.MenuItem(rootMenu, id, text)
rootMenu.info[id] = (m, fullContext, it)
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)
elif sub:
# If sub exists and is not False, set submenu.
# Sub might return False when we have a mix of
# single menu items and submenus (see: damage profile
# context menu)
#
# If there is a submenu, it is expected that the sub
# logic take care of it's own bindings, including for
# any single root items. No binding is done here
#
# It is important to remember that when binding sub
# menu items, the menu to bind to depends on platform.
# Windows should bind to rootMenu, and all other
# platforms should bind to sub menu. See existing
# implementations for examples.
rootItem.SetSubMenu(sub)
if bitmap is not None:
if multiple:
bp = bitmap[it]
if bp:
rootItem.SetBitmap(bp)
else:
rootItem.SetBitmap(bitmap)
rootMenu.AppendItem(rootItem)
empty = False
if amount > 0 and i != len(fullContexts) - 1:
rootMenu.AppendSeparator()
debug_end = len(cls._ids)
if (debug_end - debug_start):
logger.debug("%d new IDs created for this menu" % (debug_end - debug_start))
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:
menuHandler, context, i = stuff
selection = menu.selection
if not hasattr(selection, "__iter__"):
selection = (selection,)
menuHandler.activate(context, selection, i)
else:
event.Skip()
def display(self, context, selection):
raise NotImplementedError()
def activate(self, fullContext, selection, i):
return None
def getSubMenu(self, context, selection, rootMenu, i, pitem):
return None
@classmethod
def nextID(cls):
"""
Fetches an ID from the pool of IDs allocated to Context Menu.
If we don't have enough ID's to fulfill request, create new
ID and add it to the pool.
See GH Issue #589
"""
cls._idxid += 1
if cls._idxid >= len(cls._ids): # We don't ahve an ID for this index, create one
cls._ids.append(wx.NewId())
return cls._ids[cls._idxid]
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):
return None
from gui.builtinContextMenus import * # noqa

View File

@@ -30,7 +30,8 @@ class CopySelectDialog(wx.Dialog):
copyFormatMultiBuy = 5
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=u"Select a format", size=(-1, -1), style=wx.DEFAULT_DIALOG_STYLE)
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title=u"Select a format", size=(-1, -1),
style=wx.DEFAULT_DIALOG_STYLE)
mainSizer = wx.BoxSizer(wx.VERTICAL)
copyFormats = [u"EFT", u"EFT (Implants)", u"XML", u"DNA", u"CREST", u"MultiBuy"]
@@ -40,7 +41,8 @@ class CopySelectDialog(wx.Dialog):
CopySelectDialog.copyFormatDna: u"A one-line text format",
CopySelectDialog.copyFormatCrest: u"A JSON format used for EVE CREST",
CopySelectDialog.copyFormatMultiBuy: u"MultiBuy text format"}
selector = wx.RadioBox(self, wx.ID_ANY, label=u"Copy to the clipboard using:", choices=copyFormats, style=wx.RA_SPECIFY_ROWS)
selector = wx.RadioBox(self, wx.ID_ANY, label=u"Copy to the clipboard using:", choices=copyFormats,
style=wx.RA_SPECIFY_ROWS)
selector.Bind(wx.EVT_RADIOBOX, self.Selected)
for format, tooltip in copyFormatTooltips.iteritems():
selector.SetItemToolTip(format, tooltip)

View File

@@ -16,9 +16,9 @@ import gui.globalEvents as GE
class CrestFittings(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Browse EVE Fittings", pos=wx.DefaultPosition, size=wx.Size( 550,450 ), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Browse EVE Fittings", pos=wx.DefaultPosition,
size=wx.Size(550, 450), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
@@ -26,42 +26,43 @@ class CrestFittings(wx.Frame):
mainSizer = wx.BoxSizer(wx.VERTICAL)
sCrest = Crest.getInstance()
characterSelectSizer = wx.BoxSizer( wx.HORIZONTAL )
characterSelectSizer = wx.BoxSizer(wx.HORIZONTAL)
if sCrest.settings.get('mode') == CrestModes.IMPLICIT:
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s"%sCrest.implicitCharacter.name, wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap( -1 )
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s" % sCrest.implicitCharacter.name,
wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap(-1)
characterSelectSizer.Add( self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
characterSelectSizer.Add(self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
else:
self.charChoice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [])
characterSelectSizer.Add( self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
characterSelectSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
self.updateCharList()
self.fetchBtn = wx.Button( self, wx.ID_ANY, u"Fetch Fits", wx.DefaultPosition, wx.DefaultSize, 5 )
characterSelectSizer.Add( self.fetchBtn, 0, wx.ALL, 5 )
mainSizer.Add( characterSelectSizer, 0, wx.EXPAND, 5 )
self.fetchBtn = wx.Button(self, wx.ID_ANY, u"Fetch Fits", wx.DefaultPosition, wx.DefaultSize, 5)
characterSelectSizer.Add(self.fetchBtn, 0, wx.ALL, 5)
mainSizer.Add(characterSelectSizer, 0, wx.EXPAND, 5)
self.sl = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
mainSizer.Add( self.sl, 0, wx.EXPAND |wx.ALL, 5 )
self.sl = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.sl, 0, wx.EXPAND | wx.ALL, 5)
contentSizer = wx.BoxSizer( wx.HORIZONTAL )
browserSizer = wx.BoxSizer( wx.VERTICAL )
contentSizer = wx.BoxSizer(wx.HORIZONTAL)
browserSizer = wx.BoxSizer(wx.VERTICAL)
self.fitTree = FittingsTreeView(self)
browserSizer.Add( self.fitTree, 1, wx.ALL|wx.EXPAND, 5 )
contentSizer.Add( browserSizer, 1, wx.EXPAND, 0 )
fitSizer = wx.BoxSizer( wx.VERTICAL )
browserSizer.Add(self.fitTree, 1, wx.ALL | wx.EXPAND, 5)
contentSizer.Add(browserSizer, 1, wx.EXPAND, 0)
fitSizer = wx.BoxSizer(wx.VERTICAL)
self.fitView = FitView(self)
fitSizer.Add( self.fitView, 1, wx.ALL|wx.EXPAND, 5 )
fitSizer.Add(self.fitView, 1, wx.ALL | wx.EXPAND, 5)
btnSizer = wx.BoxSizer( wx.HORIZONTAL )
self.importBtn = wx.Button( self, wx.ID_ANY, u"Import to pyfa", wx.DefaultPosition, wx.DefaultSize, 5 )
self.deleteBtn = wx.Button( self, wx.ID_ANY, u"Delete from EVE", wx.DefaultPosition, wx.DefaultSize, 5 )
btnSizer.Add( self.importBtn, 1, wx.ALL, 5 )
btnSizer.Add( self.deleteBtn, 1, wx.ALL, 5 )
fitSizer.Add( btnSizer, 0, wx.EXPAND )
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
self.importBtn = wx.Button(self, wx.ID_ANY, u"Import to pyfa", wx.DefaultPosition, wx.DefaultSize, 5)
self.deleteBtn = wx.Button(self, wx.ID_ANY, u"Delete from EVE", wx.DefaultPosition, wx.DefaultSize, 5)
btnSizer.Add(self.importBtn, 1, wx.ALL, 5)
btnSizer.Add(self.deleteBtn, 1, wx.ALL, 5)
fitSizer.Add(btnSizer, 0, wx.EXPAND)
contentSizer.Add(fitSizer, 1, wx.EXPAND, 0)
mainSizer.Add(contentSizer, 1, wx.EXPAND, 5)
@@ -104,12 +105,12 @@ class CrestFittings(wx.Frame):
self.charChoice.SetSelection(0)
def updateCacheStatus(self, event):
t = time.gmtime(self.cacheTime-time.time())
t = time.gmtime(self.cacheTime - time.time())
if t < 0:
self.cacheTimer.Stop()
else:
sTime = time.strftime("%H:%M:%S", t)
self.statusbar.SetStatusText("Cached for %s"%sTime, 0)
self.statusbar.SetStatusText("Cached for %s" % sTime, 0)
def ssoLogout(self, event):
if event.type == CrestModes.IMPLICIT:
@@ -163,8 +164,8 @@ class CrestFittings(wx.Frame):
data = json.loads(self.fitTree.fittingsTreeCtrl.GetPyData(selection))
dlg = wx.MessageDialog(self,
"Do you really want to delete %s (%s) from EVE?"%(data['name'], data['ship']['name']),
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
"Do you really want to delete %s (%s) from EVE?" % (data['name'], data['ship']['name']),
"Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION)
if dlg.ShowModal() == wx.ID_YES:
try:
@@ -174,9 +175,9 @@ class CrestFittings(wx.Frame):
class ExportToEve(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Export fit to EVE", pos=wx.DefaultPosition, size=(wx.Size(350,100)), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Export fit to EVE", pos=wx.DefaultPosition,
size=(wx.Size(350, 100)), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
self.mainFrame = parent
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
@@ -186,20 +187,21 @@ class ExportToEve(wx.Frame):
hSizer = wx.BoxSizer(wx.HORIZONTAL)
if sCrest.settings.get('mode') == CrestModes.IMPLICIT:
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s"%sCrest.implicitCharacter.name, wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap( -1 )
self.stLogged = wx.StaticText(self, wx.ID_ANY, "Currently logged in as %s" % sCrest.implicitCharacter.name,
wx.DefaultPosition, wx.DefaultSize)
self.stLogged.Wrap(-1)
hSizer.Add( self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
hSizer.Add(self.stLogged, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
else:
self.charChoice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [])
hSizer.Add( self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
hSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
self.updateCharList()
self.charChoice.SetSelection(0)
self.exportBtn = wx.Button( self, wx.ID_ANY, u"Export Fit", wx.DefaultPosition, wx.DefaultSize, 5 )
hSizer.Add( self.exportBtn, 0, wx.ALL, 5 )
self.exportBtn = wx.Button(self, wx.ID_ANY, u"Export Fit", wx.DefaultPosition, wx.DefaultSize, 5)
hSizer.Add(self.exportBtn, 0, wx.ALL, 5)
mainSizer.Add( hSizer, 0, wx.EXPAND, 5 )
mainSizer.Add(hSizer, 0, wx.EXPAND, 5)
self.exportBtn.Bind(wx.EVT_BUTTON, self.exportFitting)
@@ -271,7 +273,7 @@ class ExportToEve(wx.Frame):
data = sFit.exportCrest(fitID)
res = sCrest.postFitting(self.getActiveCharacter(), data)
self.statusbar.SetStatusText("%d: %s"%(res.status_code, res.reason), 0)
self.statusbar.SetStatusText("%d: %s" % (res.status_code, res.reason), 0)
try:
text = json.loads(res.text)
self.statusbar.SetStatusText(text['message'], 1)
@@ -282,40 +284,40 @@ class ExportToEve(wx.Frame):
class CrestMgmt(wx.Dialog):
def __init__( self, parent ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = "CREST Character Management", pos = wx.DefaultPosition, size = wx.Size( 550,250 ), style = wx.DEFAULT_DIALOG_STYLE )
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="CREST Character Management", pos=wx.DefaultPosition,
size=wx.Size(550, 250), style=wx.DEFAULT_DIALOG_STYLE)
self.mainFrame = parent
mainSizer = wx.BoxSizer( wx.HORIZONTAL )
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
self.lcCharacters = wx.ListCtrl( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT)
self.lcCharacters = wx.ListCtrl(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT)
self.lcCharacters.InsertColumn(0, heading='Character')
self.lcCharacters.InsertColumn(1, heading='Refresh Token')
self.popCharList()
mainSizer.Add( self.lcCharacters, 1, wx.ALL|wx.EXPAND, 5 )
mainSizer.Add(self.lcCharacters, 1, wx.ALL | wx.EXPAND, 5)
btnSizer = wx.BoxSizer( wx.VERTICAL )
btnSizer = wx.BoxSizer(wx.VERTICAL)
self.addBtn = wx.Button( self, wx.ID_ANY, u"Add Character", wx.DefaultPosition, wx.DefaultSize, 0 )
btnSizer.Add( self.addBtn, 0, wx.ALL | wx.EXPAND, 5 )
self.addBtn = wx.Button(self, wx.ID_ANY, u"Add Character", wx.DefaultPosition, wx.DefaultSize, 0)
btnSizer.Add(self.addBtn, 0, wx.ALL | wx.EXPAND, 5)
self.deleteBtn = wx.Button( self, wx.ID_ANY, u"Revoke Character", wx.DefaultPosition, wx.DefaultSize, 0 )
btnSizer.Add( self.deleteBtn, 0, wx.ALL | wx.EXPAND, 5 )
self.deleteBtn = wx.Button(self, wx.ID_ANY, u"Revoke Character", wx.DefaultPosition, wx.DefaultSize, 0)
btnSizer.Add(self.deleteBtn, 0, wx.ALL | wx.EXPAND, 5)
mainSizer.Add( btnSizer, 0, wx.EXPAND, 5 )
mainSizer.Add(btnSizer, 0, wx.EXPAND, 5)
self.addBtn.Bind(wx.EVT_BUTTON, self.addChar)
self.deleteBtn.Bind(wx.EVT_BUTTON, self.delChar)
self.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.ssoLogin)
self.SetSizer( mainSizer )
self.SetSizer(mainSizer)
self.Layout()
self.Centre( wx.BOTH )
self.Centre(wx.BOTH)
def ssoLogin(self, event):
self.popCharList()

View File

@@ -70,9 +70,8 @@ class Display(wx.ListCtrl):
self.imageListBase = self.imageList.ImageCount
# Override native HitTestSubItem (doesn't work as it should on GTK)
# Source: ObjectListView
# Override native HitTestSubItem (doesn't work as it should on GTK)
# Source: ObjectListView
def HitTestSubItem(self, pt):
"""
@@ -282,7 +281,7 @@ class Display(wx.ListCtrl):
self.SetColumnWidth(i, headerWidth)
else:
self.SetColumnWidth(i, col.size)
# self.Thaw()
# self.Thaw()
def update(self, stuff):
self.populate(stuff)

View File

@@ -28,24 +28,25 @@ from eos.types import Slot
from gui.contextMenu import ContextMenu
from service.fit import Fit
class FighterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
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():
data = self.dropData.GetText().split(':')
self.dropFn(x, y, data)
return t
class FighterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
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():
data = self.dropData.GetText().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 )
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"]
@@ -55,7 +56,7 @@ class FighterView(wx.Panel):
mainSizer.Add(self.fighterDisplay, 1, wx.EXPAND, 0)
textSizer = wx.BoxSizer(wx.HORIZONTAL)
textSizer.AddSpacer(( 0, 0), 1, wx.EXPAND, 5)
textSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
for x in self.labels:
lbl = wx.StaticText(self, wx.ID_ANY, x.capitalize())
@@ -74,10 +75,9 @@ class FighterView(wx.Panel):
mainSizer.Add(textSizer, 0, wx.EXPAND, 5)
self.SetSizer( mainSizer )
self.SetSizer(mainSizer)
self.SetAutoLayout(True)
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
def fitChanged(self, event):
@@ -90,7 +90,8 @@ class FighterView(wx.Panel):
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)
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)))
@@ -105,15 +106,15 @@ class FighterView(wx.Panel):
class FighterDisplay(d.Display):
DEFAULT_COLS = ["State",
#"Base Icon",
# "Base Icon",
"Base Name",
# "prop:droneDps,droneBandwidth",
#"Max Range",
#"Miscellanea",
# "Max Range",
# "Miscellanea",
"attr:maxVelocity",
"Fighter Abilities"
#"Price",
]
# "Price",
]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
@@ -131,12 +132,11 @@ class FighterDisplay(d.Display):
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
if "__WXGTK__" in wx.PlatformInfo:
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))
@@ -183,7 +183,7 @@ class FighterDisplay(d.Display):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
data.SetText("fighter:"+str(row))
data.SetText("fighter:" + str(row))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
@@ -229,7 +229,7 @@ class FighterDisplay(d.Display):
self.Parent.Parent.Parent.DisablePage(self.Parent, not fit)
#Clear list and get out if current fitId is None
# 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
@@ -257,7 +257,6 @@ class FighterDisplay(d.Display):
self.update(stuff)
event.Skip()
def addItem(self, event):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()

View File

@@ -1,448 +1,449 @@
import wx
from wx.lib.buttons import GenBitmapButton
import service.fleet
import gui.mainFrame
import gui.utils.colorUtils as colorUtils
import gui.sfBrowserItem as SFItem
from gui.bitmapLoader import BitmapLoader
from gui.PFListPane import PFListPane
from gui.utils.drawUtils import GetPartialText
FleetSelected, EVT_FLEET_SELECTED = wx.lib.newevent.NewEvent()
FleetRenamed, EVT_FLEET_RENAMED = wx.lib.newevent.NewEvent()
FleetRemoved, EVT_FLEET_REMOVED = wx.lib.newevent.NewEvent()
FleetItemSelect, EVT_FLEET_ITEM_SELECT = wx.lib.newevent.NewEvent()
FleetItemDelete, EVT_FLEET_ITEM_DELETE = wx.lib.newevent.NewEvent()
FleetItemNew, EVT_FLEET_ITEM_NEW = wx.lib.newevent.NewEvent()
FleetItemCopy, EVT_FLEET_ITEM_COPY = wx.lib.newevent.NewEvent()
FleetItemRename, EVT_FLEET_ITEM_RENAME = wx.lib.newevent.NewEvent()
class FleetBrowser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.sFleet = service.fleet.Fleet.getInstance()
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.hpane = FleetBrowserHeader(self)
mainSizer.Add(self.hpane, 0, wx.EXPAND)
self.m_sl2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_sl2, 0, wx.EXPAND, 0)
self.fleetItemContainer = PFFleetItemContainer(self)
mainSizer.Add(self.fleetItemContainer, 1, wx.EXPAND)
self.SetSizer(mainSizer)
self.Layout()
self.filter = ""
self.fleetIDMustEditName = -1
self.Bind(wx.EVT_SIZE, self.SizeRefreshList)
self.Bind(EVT_FLEET_ITEM_NEW, self.AddNewFleetItem)
self.Bind(EVT_FLEET_ITEM_SELECT, self.SelectFleetItem)
self.Bind(EVT_FLEET_ITEM_DELETE, self.DeleteFleetItem)
self.Bind(EVT_FLEET_ITEM_COPY, self.CopyFleetItem)
self.Bind(EVT_FLEET_ITEM_RENAME, self.RenameFleetItem)
self.PopulateFleetList()
def AddNewFleetItem(self, event):
fleetName = event.fleetName
newFleet = self.sFleet.addFleet()
self.sFleet.renameFleet(newFleet, fleetName)
self.fleetIDMustEditName = newFleet.ID
self.AddItem(newFleet.ID, newFleet.name, newFleet.count())
def SelectFleetItem(self, event):
fleetID = event.fleetID
self.fleetItemContainer.SelectWidgetByFleetID(fleetID)
wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleetID))
def CopyFleetItem(self, event):
fleetID = event.fleetID
fleet = self.sFleet.copyFleetByID(fleetID)
fleetName = fleet.name + " Copy"
self.sFleet.renameFleet(fleet, fleetName)
self.fleetIDMustEditName = fleet.ID
self.AddItem(fleet.ID, fleet.name, fleet.count())
self.fleetItemContainer.SelectWidgetByFleetID(fleet.ID)
wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleet.ID))
def RenameFleetItem(self, event):
fleetID = event.fleetID
fleet = self.sFleet.getFleetByID(fleetID)
newFleetName = event.fleetName
self.sFleet.renameFleet(fleet, newFleetName)
wx.PostEvent(self.mainFrame, FleetRenamed(fleetID=fleet.ID))
def DeleteFleetItem(self, event):
self.sFleet.deleteFleetByID(event.fleetID)
self.PopulateFleetList()
wx.PostEvent(self.mainFrame, FleetRemoved(fleetID=event.fleetID))
def AddItem(self, ID, name, count):
self.fleetItemContainer.AddWidget(FleetItem(self, ID, name, count))
widget = self.fleetItemContainer.GetWidgetByFleetID(ID)
self.fleetItemContainer.RefreshList(True)
self.fleetItemContainer.ScrollChildIntoView(widget)
wx.PostEvent(self, FleetItemSelect(fleetID=ID))
def PopulateFleetList(self):
self.Freeze()
filter_ = self.filter
self.fleetItemContainer.RemoveAllChildren()
fleetList = self.sFleet.getFleetList()
for fleetID, fleetName, fleetCount in fleetList:
if fleetName.lower().find(filter_.lower()) != -1:
self.fleetItemContainer.AddWidget(FleetItem(self, fleetID, fleetName, fleetCount))
self.fleetItemContainer.RefreshList()
self.Thaw()
def SetFilter(self, filter):
self.filter = filter
def SizeRefreshList(self, event):
ewidth, eheight = event.GetSize()
self.Layout()
self.fleetItemContainer.Layout()
self.fleetItemContainer.RefreshList(True)
event.Skip()
class FleetBrowserHeader(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 24), style=wx.TAB_TRAVERSAL)
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
self.newBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
bmpSize = (16, 16)
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
if 'wxMac' in wx.PlatformInfo:
bgcolour = wx.Colour(0, 0, 0, 0)
else:
bgcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
self.fbNewFleet = PFGenBitmapButton(self, wx.ID_ANY, self.newBmp, wx.DefaultPosition, bmpSize, wx.BORDER_NONE)
mainSizer.Add(self.fbNewFleet, 0, wx.LEFT | wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 5)
self.fbNewFleet.SetBackgroundColour(bgcolour)
self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_VERTICAL)
mainSizer.Add(self.sl1, 0, wx.EXPAND | wx.LEFT, 5)
self.tcFilter = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.tcFilter, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
self.stStatus = wx.StaticText(self, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0)
self.stStatus.Wrap(-1)
mainSizer.Add(self.stStatus, 1, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
self.SetSizer(mainSizer)
self.Layout()
self.fbNewFleet.Bind(wx.EVT_ENTER_WINDOW, self.fbNewEnterWindow)
self.fbNewFleet.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
self.fbNewFleet.Bind(wx.EVT_BUTTON, self.OnNewFleetItem)
self.tcFilter.Bind(wx.EVT_TEXT, self.OnFilterText)
self.tcFilter.Bind(wx.EVT_ENTER_WINDOW, self.fbFilterEnterWindow)
self.tcFilter.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
def OnFilterText(self, event):
filter = self.tcFilter.GetValue()
self.Parent.SetFilter(filter)
self.Parent.PopulateFleetList()
event.Skip()
def OnNewFleetItem(self, event):
wx.PostEvent(self.Parent, FleetItemNew(fleetName="New Fleet"))
def fbNewEnterWindow(self, event):
self.stStatus.SetLabel("New fleet")
self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
event.Skip()
def fbHItemLeaveWindow(self, event):
self.stStatus.SetLabel("")
self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
event.Skip()
def fbFilterEnterWindow(self, event):
self.stStatus.SetLabel("Filter list")
event.Skip()
class PFFleetItemContainer(PFListPane):
def __init__(self, parent):
PFListPane.__init__(self, parent)
self.selectedWidget = -1
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def IsWidgetSelectedByContext(self, widget):
if self.GetWidgetList()[widget].IsSelected():
return True
return False
def GetWidgetIndex(self, widgetWnd):
return self.GetWidgetList().index(widgetWnd)
def GetWidgetByFleetID(self, fleetID):
for widget in self.GetWidgetList():
if widget.fleetID == fleetID:
return widget
return None
def SelectWidget(self, widgetWnd):
wlist = self.GetWidgetList()
if self.selectedWidget != -1:
wlist[self.selectedWidget].SetSelected(False)
wlist[self.selectedWidget].Refresh()
windex = self.GetWidgetIndex(widgetWnd)
wlist[windex].SetSelected(True)
wlist[windex].Refresh()
self.selectedWidget = windex
def SelectWidgetByFleetID(self, fleetID):
widgetWnd = self.GetWidgetByFleetID(fleetID)
if widgetWnd:
self.SelectWidget(widgetWnd)
def RemoveWidget(self, child):
child.Destroy()
self.selectedWidget = -1
self._wList.remove(child)
def RemoveAllChildren(self):
for widget in self._wList:
widget.Destroy()
self.selectedWidget = -1
self._wList = []
def OnLeftUp(self, event):
event.Skip()
class FleetItem(SFItem.SFBrowserItem):
def __init__(self, parent, fleetID, fleetName, fleetCount,
id=wx.ID_ANY, pos=wx.DefaultPosition,
size=(0, 40), style=0):
SFItem.SFBrowserItem.__init__(self, parent, size=size)
self.fleetBrowser = self.Parent
self.fleetID = fleetID
self.fleetName = fleetName
self.fleetCount = fleetCount
self.padding = 4
self.fontBig = wx.FontFromPixelSize((0, 15), wx.SWISS, wx.NORMAL, wx.BOLD, False)
self.fontNormal = wx.FontFromPixelSize((0, 14), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.fontSmall = wx.FontFromPixelSize((0, 12), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.copyBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
self.renameBmp = BitmapLoader.getBitmap("fit_rename_small", "gui")
self.deleteBmp = BitmapLoader.getBitmap("fit_delete_small", "gui")
self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui")
self.fleetBmp = BitmapLoader.getBitmap("fleet_item_big", "gui")
fleetImg = self.fleetBmp.ConvertToImage()
fleetImg = fleetImg.Blur(2)
if not fleetImg.HasAlpha():
fleetImg.InitAlpha()
fleetImg = fleetImg.AdjustChannels(1, 1, 1, 0.5)
self.fleetEffBmp = wx.BitmapFromImage(fleetImg)
self.toolbar.AddButton(self.copyBmp, "Copy", self.CopyFleetCB)
self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.RenameFleetCB)
self.toolbar.AddButton(self.deleteBmp, "Delete", self.DeleteFleetCB)
self.editWidth = 150
self.tcFleetName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fleetName, wx.DefaultPosition, (self.editWidth, -1), wx.TE_PROCESS_ENTER)
if self.fleetBrowser.fleetIDMustEditName != self.fleetID:
self.tcFleetName.Show(False)
else:
self.tcFleetName.SetFocus()
self.tcFleetName.SelectAll()
self.fleetBrowser.fleetIDMustEditName = -1
self.renameBtn.SetBitmap(self.acceptBmp)
self.selected = True
self.tcFleetName.Bind(wx.EVT_KILL_FOCUS, self.OnEditLostFocus)
self.tcFleetName.Bind(wx.EVT_TEXT_ENTER, self.RenameFleet)
self.tcFleetName.Bind(wx.EVT_KEY_DOWN, self.EditCheckEsc)
self.animCount = 0
def MouseLeftUp(self, event):
if self.tcFleetName.IsShown():
self.RestoreEditButton()
else:
wx.PostEvent(self.fleetBrowser, FleetItemSelect(fleetID=self.fleetID))
def CopyFleetCB(self):
if self.tcFleetName.IsShown():
self.RestoreEditButton()
return
wx.PostEvent(self.fleetBrowser, FleetItemCopy(fleetID=self.fleetID))
def RenameFleetCB(self):
if self.tcFleetName.IsShown():
self.RenameFleet(None)
self.RestoreEditButton()
else:
self.tcFleetName.SetValue(self.fleetName)
self.tcFleetName.Show()
self.renameBtn.SetBitmap(self.acceptBmp)
self.Refresh()
self.tcFleetName.SetFocus()
self.tcFleetName.SelectAll()
self.Refresh()
def RenameFleet(self, event):
newFleetName = self.tcFleetName.GetValue()
self.fleetName = newFleetName
self.tcFleetName.Show(False)
wx.PostEvent(self.fleetBrowser, FleetItemRename(fleetID=self.fleetID, fleetName=self.fleetName))
self.Refresh()
def DeleteFleetCB(self):
if self.tcFleetName.IsShown():
self.RestoreEditButton()
return
wx.PostEvent(self.fleetBrowser, FleetItemDelete(fleetID=self.fleetID))
def RestoreEditButton(self):
self.tcFleetName.Show(False)
self.renameBtn.SetBitmap(self.renameBmp)
self.Refresh()
def OnEditLostFocus(self, event):
self.RestoreEditButton()
self.Refresh()
def EditCheckEsc(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE:
self.RestoreEditButton()
else:
event.Skip()
def IsSelected(self):
return self.selected
def UpdateElementsPos(self, mdc):
rect = self.GetRect()
self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding
self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2
self.toolbarx = self.toolbarx + self.animCount
self.fleetBmpx = self.padding + (rect.height - self.fleetBmp.GetWidth()) / 2
self.fleetBmpy = (rect.height - self.fleetBmp.GetHeight()) / 2
self.fleetBmpx -= self.animCount
self.textStartx = self.fleetBmpx + self.fleetBmp.GetWidth() + self.padding
self.fleetNamey = (rect.height - self.fleetBmp.GetHeight()) / 2
mdc.SetFont(self.fontBig)
wtext, htext = mdc.GetTextExtent(self.fleetName)
self.fleetCounty = self.fleetNamey + htext
mdc.SetFont(self.fontSmall)
wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel)
self.thoverx = self.toolbarx - self.padding - wlabel
self.thovery = (rect.height - hlabel) / 2
self.thoverw = wlabel
def DrawItem(self, mdc):
# rect = self.GetRect()
windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
textColor = colorUtils.GetSuitableColor(windowColor, 1)
mdc.SetTextForeground(textColor)
self.UpdateElementsPos(mdc)
self.toolbar.SetPosition((self.toolbarx, self.toolbary))
mdc.DrawBitmap(self.fleetEffBmp, self.fleetBmpx + 3, self.fleetBmpy + 2)
mdc.DrawBitmap(self.fleetBmp, self.fleetBmpx, self.fleetBmpy)
mdc.SetFont(self.fontNormal)
suffix = "%d ships" % self.fleetCount if self.fleetCount > 1 else "%d ship" % self.fleetCount if self.fleetCount == 1 else "No ships"
fleetCount = "Fleet size: %s" % suffix
fleetCount = GetPartialText(mdc, fleetCount, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(fleetCount, self.textStartx, self.fleetCounty)
mdc.SetFont(self.fontSmall)
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
mdc.SetFont(self.fontBig)
pfname = GetPartialText(mdc, self.fleetName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(pfname, self.textStartx, self.fleetNamey)
if self.tcFleetName.IsShown():
self.AdjustControlSizePos(self.tcFleetName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
def AdjustControlSizePos(self, editCtl, start, end):
fnEditSize = editCtl.GetSize()
wSize = self.GetSize()
fnEditPosX = end
fnEditPosY = (wSize.height - fnEditSize.height) / 2
if fnEditPosX < start:
editCtl.SetSize((self.editWidth + fnEditPosX - start, -1))
editCtl.SetPosition((start, fnEditPosY))
else:
editCtl.SetSize((self.editWidth, -1))
editCtl.SetPosition((fnEditPosX, fnEditPosY))
class PFGenBitmapButton(GenBitmapButton):
def __init__(self, parent, id, bitmap, pos, size, style):
GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style)
self.bgcolor = wx.Brush(wx.WHITE)
def SetBackgroundColour(self, color):
self.bgcolor = wx.Brush(color)
def GetBackgroundBrush(self, dc):
return self.bgcolor
import wx
from wx.lib.buttons import GenBitmapButton
import service.fleet
import gui.mainFrame
import gui.utils.colorUtils as colorUtils
import gui.sfBrowserItem as SFItem
from gui.bitmapLoader import BitmapLoader
from gui.PFListPane import PFListPane
from gui.utils.drawUtils import GetPartialText
FleetSelected, EVT_FLEET_SELECTED = wx.lib.newevent.NewEvent()
FleetRenamed, EVT_FLEET_RENAMED = wx.lib.newevent.NewEvent()
FleetRemoved, EVT_FLEET_REMOVED = wx.lib.newevent.NewEvent()
FleetItemSelect, EVT_FLEET_ITEM_SELECT = wx.lib.newevent.NewEvent()
FleetItemDelete, EVT_FLEET_ITEM_DELETE = wx.lib.newevent.NewEvent()
FleetItemNew, EVT_FLEET_ITEM_NEW = wx.lib.newevent.NewEvent()
FleetItemCopy, EVT_FLEET_ITEM_COPY = wx.lib.newevent.NewEvent()
FleetItemRename, EVT_FLEET_ITEM_RENAME = wx.lib.newevent.NewEvent()
class FleetBrowser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.sFleet = service.fleet.Fleet.getInstance()
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.hpane = FleetBrowserHeader(self)
mainSizer.Add(self.hpane, 0, wx.EXPAND)
self.m_sl2 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
mainSizer.Add(self.m_sl2, 0, wx.EXPAND, 0)
self.fleetItemContainer = PFFleetItemContainer(self)
mainSizer.Add(self.fleetItemContainer, 1, wx.EXPAND)
self.SetSizer(mainSizer)
self.Layout()
self.filter = ""
self.fleetIDMustEditName = -1
self.Bind(wx.EVT_SIZE, self.SizeRefreshList)
self.Bind(EVT_FLEET_ITEM_NEW, self.AddNewFleetItem)
self.Bind(EVT_FLEET_ITEM_SELECT, self.SelectFleetItem)
self.Bind(EVT_FLEET_ITEM_DELETE, self.DeleteFleetItem)
self.Bind(EVT_FLEET_ITEM_COPY, self.CopyFleetItem)
self.Bind(EVT_FLEET_ITEM_RENAME, self.RenameFleetItem)
self.PopulateFleetList()
def AddNewFleetItem(self, event):
fleetName = event.fleetName
newFleet = self.sFleet.addFleet()
self.sFleet.renameFleet(newFleet, fleetName)
self.fleetIDMustEditName = newFleet.ID
self.AddItem(newFleet.ID, newFleet.name, newFleet.count())
def SelectFleetItem(self, event):
fleetID = event.fleetID
self.fleetItemContainer.SelectWidgetByFleetID(fleetID)
wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleetID))
def CopyFleetItem(self, event):
fleetID = event.fleetID
fleet = self.sFleet.copyFleetByID(fleetID)
fleetName = fleet.name + " Copy"
self.sFleet.renameFleet(fleet, fleetName)
self.fleetIDMustEditName = fleet.ID
self.AddItem(fleet.ID, fleet.name, fleet.count())
self.fleetItemContainer.SelectWidgetByFleetID(fleet.ID)
wx.PostEvent(self.mainFrame, FleetSelected(fleetID=fleet.ID))
def RenameFleetItem(self, event):
fleetID = event.fleetID
fleet = self.sFleet.getFleetByID(fleetID)
newFleetName = event.fleetName
self.sFleet.renameFleet(fleet, newFleetName)
wx.PostEvent(self.mainFrame, FleetRenamed(fleetID=fleet.ID))
def DeleteFleetItem(self, event):
self.sFleet.deleteFleetByID(event.fleetID)
self.PopulateFleetList()
wx.PostEvent(self.mainFrame, FleetRemoved(fleetID=event.fleetID))
def AddItem(self, ID, name, count):
self.fleetItemContainer.AddWidget(FleetItem(self, ID, name, count))
widget = self.fleetItemContainer.GetWidgetByFleetID(ID)
self.fleetItemContainer.RefreshList(True)
self.fleetItemContainer.ScrollChildIntoView(widget)
wx.PostEvent(self, FleetItemSelect(fleetID=ID))
def PopulateFleetList(self):
self.Freeze()
filter_ = self.filter
self.fleetItemContainer.RemoveAllChildren()
fleetList = self.sFleet.getFleetList()
for fleetID, fleetName, fleetCount in fleetList:
if fleetName.lower().find(filter_.lower()) != -1:
self.fleetItemContainer.AddWidget(FleetItem(self, fleetID, fleetName, fleetCount))
self.fleetItemContainer.RefreshList()
self.Thaw()
def SetFilter(self, filter):
self.filter = filter
def SizeRefreshList(self, event):
ewidth, eheight = event.GetSize()
self.Layout()
self.fleetItemContainer.Layout()
self.fleetItemContainer.RefreshList(True)
event.Skip()
class FleetBrowserHeader(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(500, 24),
style=wx.TAB_TRAVERSAL)
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
self.newBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
bmpSize = (16, 16)
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
if 'wxMac' in wx.PlatformInfo:
bgcolour = wx.Colour(0, 0, 0, 0)
else:
bgcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)
self.fbNewFleet = PFGenBitmapButton(self, wx.ID_ANY, self.newBmp, wx.DefaultPosition, bmpSize, wx.BORDER_NONE)
mainSizer.Add(self.fbNewFleet, 0, wx.LEFT | wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, 5)
self.fbNewFleet.SetBackgroundColour(bgcolour)
self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_VERTICAL)
mainSizer.Add(self.sl1, 0, wx.EXPAND | wx.LEFT, 5)
self.tcFilter = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
mainSizer.Add(self.tcFilter, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
self.stStatus = wx.StaticText(self, wx.ID_ANY, u"", wx.DefaultPosition, wx.DefaultSize, 0)
self.stStatus.Wrap(-1)
mainSizer.Add(self.stStatus, 1, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
self.SetSizer(mainSizer)
self.Layout()
self.fbNewFleet.Bind(wx.EVT_ENTER_WINDOW, self.fbNewEnterWindow)
self.fbNewFleet.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
self.fbNewFleet.Bind(wx.EVT_BUTTON, self.OnNewFleetItem)
self.tcFilter.Bind(wx.EVT_TEXT, self.OnFilterText)
self.tcFilter.Bind(wx.EVT_ENTER_WINDOW, self.fbFilterEnterWindow)
self.tcFilter.Bind(wx.EVT_LEAVE_WINDOW, self.fbHItemLeaveWindow)
def OnFilterText(self, event):
filter = self.tcFilter.GetValue()
self.Parent.SetFilter(filter)
self.Parent.PopulateFleetList()
event.Skip()
def OnNewFleetItem(self, event):
wx.PostEvent(self.Parent, FleetItemNew(fleetName="New Fleet"))
def fbNewEnterWindow(self, event):
self.stStatus.SetLabel("New fleet")
self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
event.Skip()
def fbHItemLeaveWindow(self, event):
self.stStatus.SetLabel("")
self.Parent.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
event.Skip()
def fbFilterEnterWindow(self, event):
self.stStatus.SetLabel("Filter list")
event.Skip()
class PFFleetItemContainer(PFListPane):
def __init__(self, parent):
PFListPane.__init__(self, parent)
self.selectedWidget = -1
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def IsWidgetSelectedByContext(self, widget):
if self.GetWidgetList()[widget].IsSelected():
return True
return False
def GetWidgetIndex(self, widgetWnd):
return self.GetWidgetList().index(widgetWnd)
def GetWidgetByFleetID(self, fleetID):
for widget in self.GetWidgetList():
if widget.fleetID == fleetID:
return widget
return None
def SelectWidget(self, widgetWnd):
wlist = self.GetWidgetList()
if self.selectedWidget != -1:
wlist[self.selectedWidget].SetSelected(False)
wlist[self.selectedWidget].Refresh()
windex = self.GetWidgetIndex(widgetWnd)
wlist[windex].SetSelected(True)
wlist[windex].Refresh()
self.selectedWidget = windex
def SelectWidgetByFleetID(self, fleetID):
widgetWnd = self.GetWidgetByFleetID(fleetID)
if widgetWnd:
self.SelectWidget(widgetWnd)
def RemoveWidget(self, child):
child.Destroy()
self.selectedWidget = -1
self._wList.remove(child)
def RemoveAllChildren(self):
for widget in self._wList:
widget.Destroy()
self.selectedWidget = -1
self._wList = []
def OnLeftUp(self, event):
event.Skip()
class FleetItem(SFItem.SFBrowserItem):
def __init__(self, parent, fleetID, fleetName, fleetCount,
id=wx.ID_ANY, pos=wx.DefaultPosition,
size=(0, 40), style=0):
SFItem.SFBrowserItem.__init__(self, parent, size=size)
self.fleetBrowser = self.Parent
self.fleetID = fleetID
self.fleetName = fleetName
self.fleetCount = fleetCount
self.padding = 4
self.fontBig = wx.FontFromPixelSize((0, 15), wx.SWISS, wx.NORMAL, wx.BOLD, False)
self.fontNormal = wx.FontFromPixelSize((0, 14), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.fontSmall = wx.FontFromPixelSize((0, 12), wx.SWISS, wx.NORMAL, wx.NORMAL, False)
self.copyBmp = BitmapLoader.getBitmap("fit_add_small", "gui")
self.renameBmp = BitmapLoader.getBitmap("fit_rename_small", "gui")
self.deleteBmp = BitmapLoader.getBitmap("fit_delete_small", "gui")
self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui")
self.fleetBmp = BitmapLoader.getBitmap("fleet_item_big", "gui")
fleetImg = self.fleetBmp.ConvertToImage()
fleetImg = fleetImg.Blur(2)
if not fleetImg.HasAlpha():
fleetImg.InitAlpha()
fleetImg = fleetImg.AdjustChannels(1, 1, 1, 0.5)
self.fleetEffBmp = wx.BitmapFromImage(fleetImg)
self.toolbar.AddButton(self.copyBmp, "Copy", self.CopyFleetCB)
self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.RenameFleetCB)
self.toolbar.AddButton(self.deleteBmp, "Delete", self.DeleteFleetCB)
self.editWidth = 150
self.tcFleetName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fleetName, wx.DefaultPosition, (self.editWidth, -1),
wx.TE_PROCESS_ENTER)
if self.fleetBrowser.fleetIDMustEditName != self.fleetID:
self.tcFleetName.Show(False)
else:
self.tcFleetName.SetFocus()
self.tcFleetName.SelectAll()
self.fleetBrowser.fleetIDMustEditName = -1
self.renameBtn.SetBitmap(self.acceptBmp)
self.selected = True
self.tcFleetName.Bind(wx.EVT_KILL_FOCUS, self.OnEditLostFocus)
self.tcFleetName.Bind(wx.EVT_TEXT_ENTER, self.RenameFleet)
self.tcFleetName.Bind(wx.EVT_KEY_DOWN, self.EditCheckEsc)
self.animCount = 0
def MouseLeftUp(self, event):
if self.tcFleetName.IsShown():
self.RestoreEditButton()
else:
wx.PostEvent(self.fleetBrowser, FleetItemSelect(fleetID=self.fleetID))
def CopyFleetCB(self):
if self.tcFleetName.IsShown():
self.RestoreEditButton()
return
wx.PostEvent(self.fleetBrowser, FleetItemCopy(fleetID=self.fleetID))
def RenameFleetCB(self):
if self.tcFleetName.IsShown():
self.RenameFleet(None)
self.RestoreEditButton()
else:
self.tcFleetName.SetValue(self.fleetName)
self.tcFleetName.Show()
self.renameBtn.SetBitmap(self.acceptBmp)
self.Refresh()
self.tcFleetName.SetFocus()
self.tcFleetName.SelectAll()
self.Refresh()
def RenameFleet(self, event):
newFleetName = self.tcFleetName.GetValue()
self.fleetName = newFleetName
self.tcFleetName.Show(False)
wx.PostEvent(self.fleetBrowser, FleetItemRename(fleetID=self.fleetID, fleetName=self.fleetName))
self.Refresh()
def DeleteFleetCB(self):
if self.tcFleetName.IsShown():
self.RestoreEditButton()
return
wx.PostEvent(self.fleetBrowser, FleetItemDelete(fleetID=self.fleetID))
def RestoreEditButton(self):
self.tcFleetName.Show(False)
self.renameBtn.SetBitmap(self.renameBmp)
self.Refresh()
def OnEditLostFocus(self, event):
self.RestoreEditButton()
self.Refresh()
def EditCheckEsc(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE:
self.RestoreEditButton()
else:
event.Skip()
def IsSelected(self):
return self.selected
def UpdateElementsPos(self, mdc):
rect = self.GetRect()
self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding
self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2
self.toolbarx = self.toolbarx + self.animCount
self.fleetBmpx = self.padding + (rect.height - self.fleetBmp.GetWidth()) / 2
self.fleetBmpy = (rect.height - self.fleetBmp.GetHeight()) / 2
self.fleetBmpx -= self.animCount
self.textStartx = self.fleetBmpx + self.fleetBmp.GetWidth() + self.padding
self.fleetNamey = (rect.height - self.fleetBmp.GetHeight()) / 2
mdc.SetFont(self.fontBig)
wtext, htext = mdc.GetTextExtent(self.fleetName)
self.fleetCounty = self.fleetNamey + htext
mdc.SetFont(self.fontSmall)
wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel)
self.thoverx = self.toolbarx - self.padding - wlabel
self.thovery = (rect.height - hlabel) / 2
self.thoverw = wlabel
def DrawItem(self, mdc):
# rect = self.GetRect()
windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
textColor = colorUtils.GetSuitableColor(windowColor, 1)
mdc.SetTextForeground(textColor)
self.UpdateElementsPos(mdc)
self.toolbar.SetPosition((self.toolbarx, self.toolbary))
mdc.DrawBitmap(self.fleetEffBmp, self.fleetBmpx + 3, self.fleetBmpy + 2)
mdc.DrawBitmap(self.fleetBmp, self.fleetBmpx, self.fleetBmpy)
mdc.SetFont(self.fontNormal)
suffix = "%d ships" % self.fleetCount if self.fleetCount > 1 else "%d ship" % self.fleetCount if self.fleetCount == 1 else "No ships"
fleetCount = "Fleet size: %s" % suffix
fleetCount = GetPartialText(mdc, fleetCount, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(fleetCount, self.textStartx, self.fleetCounty)
mdc.SetFont(self.fontSmall)
mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery)
mdc.SetFont(self.fontBig)
pfname = GetPartialText(mdc, self.fleetName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(pfname, self.textStartx, self.fleetNamey)
if self.tcFleetName.IsShown():
self.AdjustControlSizePos(self.tcFleetName, self.textStartx, self.toolbarx - self.editWidth - self.padding)
def AdjustControlSizePos(self, editCtl, start, end):
fnEditSize = editCtl.GetSize()
wSize = self.GetSize()
fnEditPosX = end
fnEditPosY = (wSize.height - fnEditSize.height) / 2
if fnEditPosX < start:
editCtl.SetSize((self.editWidth + fnEditPosX - start, -1))
editCtl.SetPosition((start, fnEditPosY))
else:
editCtl.SetSize((self.editWidth, -1))
editCtl.SetPosition((fnEditPosX, fnEditPosY))
class PFGenBitmapButton(GenBitmapButton):
def __init__(self, parent, id, bitmap, pos, size, style):
GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style)
self.bgcolor = wx.Brush(wx.WHITE)
def SetBackgroundColour(self, color):
self.bgcolor = wx.Brush(color)
def GetBackgroundBrush(self, dc):
return self.bgcolor

View File

@@ -32,7 +32,8 @@ import gui.globalEvents as GE
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)
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))
@@ -49,10 +50,10 @@ class GangView(ScrolledPanel):
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_]['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, [])
@@ -94,7 +95,8 @@ class GangView(ScrolledPanel):
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_]['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
@@ -107,7 +109,8 @@ class GangView(ScrolledPanel):
# 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)
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)
@@ -271,7 +274,8 @@ class GangView(ScrolledPanel):
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'].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()

View File

@@ -1,6 +1,5 @@
import wx.lib.newevent
FitChanged, FIT_CHANGED = wx.lib.newevent.NewEvent()
CharListUpdated, CHAR_LIST_UPDATED = wx.lib.newevent.NewEvent()
CharChanged, CHAR_CHANGED = wx.lib.newevent.NewEvent()

View File

@@ -1,281 +1,282 @@
# =============================================================================
# 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/>.
# =============================================================================
import os
import wx
from service.fit import Fit
import gui.display
import gui.mainFrame
import gui.globalEvents as GE
from gui.graph import Graph
from gui.bitmapLoader import BitmapLoader
enabled = True
mplImported = False
class GraphFrame(wx.Frame):
def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):
global enabled
global mplImported
self.legendFix = False
if not enabled:
return
try:
import matplotlib as mpl
try:
cache_dir = mpl._get_cachedir()
except:
cache_dir = unicode(os.path.expanduser(os.path.join("~", ".matplotlib")))
cache_file = os.path.join(cache_dir, 'fontList.cache')
if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
# remove matplotlib font cache, see #234
os.remove(cache_file)
if not mplImported:
mpl.use('wxagg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
from matplotlib.figure import Figure
enabled = True
if mpl.__version__[0] != "1":
print("pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds")
print("pyfa: Recommended minimum matplotlib version is 1.0.0")
self.legendFix = True
except:
print("Problems importing matplotlib; continuing without graphs")
enabled = False
return
mplImported = True
wx.Frame.__init__(self, parent, title=u"pyfa: Graph Generator", style=style, size=(520, 390))
i = wx.IconFromBitmap(BitmapLoader.getBitmap("graphs_small", "gui"))
self.SetIcon(i)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.CreateStatusBar()
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
self.fits = [fit] if fit is not None else []
self.fitList = FitList(self)
self.fitList.SetMinSize((270, -1))
self.fitList.fitList.update(self.fits)
self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)
self.figure = Figure(figsize=(4, 3))
rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
clr = [c / 255. for c in rgbtuple]
self.figure.set_facecolor(clr)
self.figure.set_edgecolor(clr)
self.canvas = Canvas(self, -1, self.figure)
self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
self.subplot = self.figure.add_subplot(111)
self.subplot.grid(True)
self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND)
self.gridPanel = wx.Panel(self)
self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)
dummyBox = wx.BoxSizer(wx.VERTICAL)
self.gridPanel.SetSizer(dummyBox)
self.gridSizer = wx.FlexGridSizer(0, 4)
self.gridSizer.AddGrowableCol(1)
dummyBox.Add(self.gridSizer, 0, wx.EXPAND)
for view in Graph.views:
view = view()
self.graphSelection.Append(view.name, view)
self.graphSelection.SetSelection(0)
self.fields = {}
self.select(0)
self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
self.mainSizer.Add(self.sl1, 0, wx.EXPAND)
self.mainSizer.Add(self.fitList, 0, wx.EXPAND)
self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
self.Bind(wx.EVT_CLOSE, self.close)
self.Fit()
self.SetMinSize(self.GetSize())
def handleDrag(self, type, fitID):
if type == "fit":
self.AppendFitToList(fitID)
def close(self, event):
self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
event.Skip()
def getView(self):
return self.graphSelection.GetClientData(self.graphSelection.GetSelection())
def getValues(self):
values = {}
for fieldName, field in self.fields.iteritems():
values[fieldName] = field.GetValue()
return values
def select(self, index):
view = self.getView()
icons = view.getIcons()
labels = view.getLabels()
sizer = self.gridSizer
self.gridPanel.DestroyChildren()
self.fields.clear()
# Setup textboxes
for field, defaultVal in view.getFields().iteritems():
textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
self.fields[field] = textBox
textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
if defaultVal is not None:
if not isinstance(defaultVal, basestring):
defaultVal = ("%f" % defaultVal).rstrip("0")
if defaultVal[-1:] == ".":
defaultVal = defaultVal + "0"
textBox.ChangeValue(defaultVal)
imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
if icons:
icon = icons.get(field)
if icon is not None:
static = wx.StaticBitmap(self.gridPanel)
static.SetBitmap(icon)
imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
if labels:
label = labels.get(field)
label = label if label is not None else field
else:
label = field
imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
self.draw()
def draw(self, event=None):
values = self.getValues()
view = self.getView()
self.subplot.clear()
self.subplot.grid(True)
legend = []
for fit in self.fits:
try:
success, status = view.getPoints(fit, values)
if not success:
# TODO: Add a pwetty statys bar to report errors with
self.SetStatusText(status)
return
x, y = success, status
self.subplot.plot(x, y)
legend.append(fit.name)
except:
self.SetStatusText("Invalid values in '%s'" % fit.name)
self.canvas.draw()
return
if self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right", shadow=False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
elif not self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
self.canvas.draw()
self.SetStatusText("")
if event is not None:
event.Skip()
def onFieldChanged(self, event):
self.draw()
def AppendFitToList(self, fitID):
sFit = Fit.getInstance()
fit = sFit.getFit(fitID)
if fit not in self.fits:
self.fits.append(fit)
self.fitList.fitList.update(self.fits)
self.draw()
def removeItem(self, event):
row, _ = self.fitList.fitList.HitTest(event.Position)
if row != -1:
del self.fits[row]
self.fitList.fitList.update(self.fits)
self.draw()
class FitList(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
self.fitList = FitDisplay(self)
self.mainSizer.Add(self.fitList, 1, wx.EXPAND)
fitToolTip = wx.ToolTip("Drag a fit into this list to graph it")
self.fitList.SetToolTip(fitToolTip)
class FitDisplay(gui.display.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name"]
def __init__(self, parent):
gui.display.Display.__init__(self, parent)
# =============================================================================
# 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/>.
# =============================================================================
import os
import wx
from service.fit import Fit
import gui.display
import gui.mainFrame
import gui.globalEvents as GE
from gui.graph import Graph
from gui.bitmapLoader import BitmapLoader
enabled = True
mplImported = False
class GraphFrame(wx.Frame):
def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT):
global enabled
global mplImported
self.legendFix = False
if not enabled:
return
try:
import matplotlib as mpl
try:
cache_dir = mpl._get_cachedir()
except:
cache_dir = unicode(os.path.expanduser(os.path.join("~", ".matplotlib")))
cache_file = os.path.join(cache_dir, 'fontList.cache')
if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
# remove matplotlib font cache, see #234
os.remove(cache_file)
if not mplImported:
mpl.use('wxagg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
from matplotlib.figure import Figure
enabled = True
if mpl.__version__[0] != "1":
print("pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds")
print("pyfa: Recommended minimum matplotlib version is 1.0.0")
self.legendFix = True
except:
print("Problems importing matplotlib; continuing without graphs")
enabled = False
return
mplImported = True
wx.Frame.__init__(self, parent, title=u"pyfa: Graph Generator", style=style, size=(520, 390))
i = wx.IconFromBitmap(BitmapLoader.getBitmap("graphs_small", "gui"))
self.SetIcon(i)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.CreateStatusBar()
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
self.fits = [fit] if fit is not None else []
self.fitList = FitList(self)
self.fitList.SetMinSize((270, -1))
self.fitList.fitList.update(self.fits)
self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0)
self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND)
self.figure = Figure(figsize=(4, 3))
rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()
clr = [c / 255. for c in rgbtuple]
self.figure.set_facecolor(clr)
self.figure.set_edgecolor(clr)
self.canvas = Canvas(self, -1, self.figure)
self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))
self.subplot = self.figure.add_subplot(111)
self.subplot.grid(True)
self.mainSizer.Add(self.canvas, 1, wx.EXPAND)
self.mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND)
self.gridPanel = wx.Panel(self)
self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND)
dummyBox = wx.BoxSizer(wx.VERTICAL)
self.gridPanel.SetSizer(dummyBox)
self.gridSizer = wx.FlexGridSizer(0, 4)
self.gridSizer.AddGrowableCol(1)
dummyBox.Add(self.gridSizer, 0, wx.EXPAND)
for view in Graph.views:
view = view()
self.graphSelection.Append(view.name, view)
self.graphSelection.SetSelection(0)
self.fields = {}
self.select(0)
self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL)
self.mainSizer.Add(self.sl1, 0, wx.EXPAND)
self.mainSizer.Add(self.fitList, 0, wx.EXPAND)
self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.mainFrame.Bind(GE.FIT_CHANGED, self.draw)
self.Bind(wx.EVT_CLOSE, self.close)
self.Fit()
self.SetMinSize(self.GetSize())
def handleDrag(self, type, fitID):
if type == "fit":
self.AppendFitToList(fitID)
def close(self, event):
self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem)
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw)
event.Skip()
def getView(self):
return self.graphSelection.GetClientData(self.graphSelection.GetSelection())
def getValues(self):
values = {}
for fieldName, field in self.fields.iteritems():
values[fieldName] = field.GetValue()
return values
def select(self, index):
view = self.getView()
icons = view.getIcons()
labels = view.getLabels()
sizer = self.gridSizer
self.gridPanel.DestroyChildren()
self.fields.clear()
# Setup textboxes
for field, defaultVal in view.getFields().iteritems():
textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
self.fields[field] = textBox
textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
if defaultVal is not None:
if not isinstance(defaultVal, basestring):
defaultVal = ("%f" % defaultVal).rstrip("0")
if defaultVal[-1:] == ".":
defaultVal = defaultVal + "0"
textBox.ChangeValue(defaultVal)
imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL)
if icons:
icon = icons.get(field)
if icon is not None:
static = wx.StaticBitmap(self.gridPanel)
static.SetBitmap(icon)
imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1)
if labels:
label = labels.get(field)
label = label if label is not None else field
else:
label = field
imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0,
wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3)
sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL)
self.draw()
def draw(self, event=None):
values = self.getValues()
view = self.getView()
self.subplot.clear()
self.subplot.grid(True)
legend = []
for fit in self.fits:
try:
success, status = view.getPoints(fit, values)
if not success:
# TODO: Add a pwetty statys bar to report errors with
self.SetStatusText(status)
return
x, y = success, status
self.subplot.plot(x, y)
legend.append(fit.name)
except:
self.SetStatusText("Invalid values in '%s'" % fit.name)
self.canvas.draw()
return
if self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right", shadow=False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
elif not self.legendFix and len(legend) > 0:
leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False)
for t in leg.get_texts():
t.set_fontsize('small')
for l in leg.get_lines():
l.set_linewidth(1)
self.canvas.draw()
self.SetStatusText("")
if event is not None:
event.Skip()
def onFieldChanged(self, event):
self.draw()
def AppendFitToList(self, fitID):
sFit = Fit.getInstance()
fit = sFit.getFit(fitID)
if fit not in self.fits:
self.fits.append(fit)
self.fitList.fitList.update(self.fits)
self.draw()
def removeItem(self, event):
row, _ = self.fitList.fitList.HitTest(event.Position)
if row != -1:
del self.fits[row]
self.fitList.fitList.update(self.fits)
self.draw()
class FitList(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.mainSizer)
self.fitList = FitDisplay(self)
self.mainSizer.Add(self.fitList, 1, wx.EXPAND)
fitToolTip = wx.ToolTip("Drag a fit into this list to graph it")
self.fitList.SetToolTip(fitToolTip)
class FitDisplay(gui.display.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name"]
def __init__(self, parent):
gui.display.Display.__init__(self, parent)

View File

@@ -64,7 +64,8 @@ class ItemStatsDialog(wx.Dialog):
itmContext = fullContext[1]
except IndexError:
itmContext = None
item = getattr(victim, "item", None) if srcContext.lower() not in ("projectedcharge", "fittingcharge") else getattr(victim, "charge", None)
item = getattr(victim, "item", None) if srcContext.lower() not in (
"projectedcharge", "fittingcharge") else getattr(victim, "charge", None)
if item is None:
sMkt = Market.getInstance()
item = sMkt.getItem(victim.ID)
@@ -76,7 +77,8 @@ class ItemStatsDialog(wx.Dialog):
itemImg = BitmapLoader.getBitmap(iconFile, "icons")
if itemImg is not None:
self.SetIcon(wx.IconFromBitmap(itemImg))
self.SetTitle("%s: %s%s" % ("%s Stats" % itmContext if itmContext is not None else "Stats", item.name, " (%d)" % item.ID if config.debug else ""))
self.SetTitle("%s: %s%s" % ("%s Stats" % itmContext if itmContext is not None else "Stats", item.name,
" (%d)" % item.ID if config.debug else ""))
self.SetMinSize((300, 200))
if "wxGTK" in wx.PlatformInfo: # GTK has huge tab widgets, give it a bit more room
@@ -232,7 +234,8 @@ class ItemDescription(wx.Panel):
desc = re.sub("<( *)font( *)color( *)=(.*?)>(?P<inside>.*?)<( *)/( *)font( *)>", "\g<inside>", desc)
# Strip URLs
desc = re.sub("<( *)a(.*?)>(?P<inside>.*?)<( *)/( *)a( *)>", "\g<inside>", desc)
desc = "<body bgcolor='" + bgcolor.GetAsString(wx.C2S_HTML_SYNTAX) + "' text='" + fgcolor.GetAsString(wx.C2S_HTML_SYNTAX) + "' >" + desc + "</body>"
desc = "<body bgcolor='" + bgcolor.GetAsString(wx.C2S_HTML_SYNTAX) + "' text='" + fgcolor.GetAsString(
wx.C2S_HTML_SYNTAX) + "' >" + desc + "</body>"
self.description.SetPage(desc)
@@ -240,12 +243,13 @@ class ItemDescription(wx.Panel):
self.Layout()
class ItemParams (wx.Panel):
class ItemParams(wx.Panel):
def __init__(self, parent, stuff, item, context=None):
wx.Panel.__init__(self, parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.paramList = AutoListCtrl(self, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
self.paramList = AutoListCtrl(self, wx.ID_ANY,
style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
mainSizer.Add(self.paramList, 1, wx.ALL | wx.EXPAND, 0)
self.SetSizer(mainSizer)
@@ -263,10 +267,12 @@ class ItemParams (wx.Panel):
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, u" ", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.totalAttrsLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT)
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle view mode", wx.DefaultPosition, wx.DefaultSize, 0)
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle view mode", wx.DefaultPosition, wx.DefaultSize,
0)
bSizer.Add(self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.exportStatsBtn = wx.ToggleButton(self, wx.ID_ANY, u"Export Item Stats", wx.DefaultPosition, wx.DefaultSize, 0)
self.exportStatsBtn = wx.ToggleButton(self, wx.ID_ANY, u"Export Item Stats", wx.DefaultPosition, wx.DefaultSize,
0)
bSizer.Add(self.exportStatsBtn, 0, wx.ALIGN_CENTER_VERTICAL)
if stuff is not None:
@@ -470,7 +476,8 @@ class ItemParams (wx.Panel):
trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName),
"Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName),
"Modifier Percent": (lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
"Modifier Percent": (
lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
"Volume": (lambda: value, u"m\u00B3"),
"Sizeclass": (lambda: value, ""),
"Absolute Percent": (lambda: (value * 100), unitName),
@@ -508,7 +515,8 @@ class ItemCompare(wx.Panel):
self.currentSort = None
self.sortReverse = False
self.item = item
self.items = sorted(items, key=lambda x: x.attributes['metaLevel'].value if 'metaLevel' in x.attributes else None)
self.items = sorted(items,
key=lambda x: x.attributes['metaLevel'].value if 'metaLevel' in x.attributes else None)
self.attrs = {}
# get a dict of attrName: attrInfo of all unique attributes across all items
@@ -661,7 +669,7 @@ class ItemCompare(wx.Panel):
trans = {"Inverse Absolute Percent": (lambda: (1 - value) * 100, unitName),
"Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName),
"Modifier Percent": (
lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
"Volume": (lambda: value, u"m\u00B3"),
"Sizeclass": (lambda: value, ""),
"Absolute Percent": (lambda: (value * 100), unitName),
@@ -719,14 +727,15 @@ class ItemRequirements(wx.Panel):
self.skillIdHistory.append(skill.ID)
class ItemEffects (wx.Panel):
class ItemEffects(wx.Panel):
def __init__(self, parent, stuff, item):
wx.Panel.__init__(self, parent)
self.item = item
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.effectList = AutoListCtrl(self, wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
self.effectList = AutoListCtrl(self, wx.ID_ANY,
style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_VRULES | wx.NO_BORDER)
mainSizer.Add(self.effectList, 1, wx.ALL | wx.EXPAND, 0)
self.SetSizer(mainSizer)
@@ -1033,7 +1042,8 @@ class ItemAffectedBy(wx.Panel):
else:
item = afflictor.item
items[attrName].append((type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False)))
items[attrName].append(
(type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False)))
# Make sure projected fits are on top
rootOrder = container.keys()
@@ -1234,7 +1244,8 @@ class ItemAffectedBy(wx.Panel):
else:
penalized = ""
attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized, attrIcon))
attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier,
attrAmount, penalized, attrIcon))
attrSorted = sorted(attributes, key=lambda attribName: attribName[0])
for attr in attrSorted:
@@ -1242,9 +1253,11 @@ class ItemAffectedBy(wx.Panel):
if self.showRealNames:
display = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
saved = "%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
saved = "%s %s %.2f %s" % (
(displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
else:
display = "%s %s %.2f %s" % ((displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
display = "%s %s %.2f %s" % (
(displayName if displayName != "" else attrName), attrModifier, attrAmount, penalized)
saved = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
treeitem = self.affectedBy.AppendItem(child, display, attrIcon)

View File

@@ -81,6 +81,7 @@ if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION
try:
from gui.propertyEditor import AttributeEditor
disableOverrideEditor = False
except ImportError as e:
print("Error loading Attribute Editor: %s.\nAccess to Attribute Editor is disabled." % e.message)
@@ -240,7 +241,8 @@ class MainFrame(wx.Frame):
def LoadPreviousOpenFits(self):
sFit = Fit.getInstance()
self.prevOpenFits = SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits", {"enabled": False, "pyfaOpenFits": []})
self.prevOpenFits = SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits",
{"enabled": False, "pyfaOpenFits": []})
fits = self.prevOpenFits['pyfaOpenFits']
# Remove any fits that cause exception when fetching (non-existent fits)
@@ -259,8 +261,10 @@ class MainFrame(wx.Frame):
OpenFitsThread(fits, self.closeWaitDialog)
def LoadMainFrameAttribs(self):
mainFrameDefaultAttribs = {"wnd_width": 1000, "wnd_height": 700, "wnd_maximized": False, "browser_width": 300, "market_height": 0, "fitting_height": -200}
self.mainFrameAttribs = SettingsProvider.getInstance().getSettings("pyfaMainWindowAttribs", mainFrameDefaultAttribs)
mainFrameDefaultAttribs = {"wnd_width": 1000, "wnd_height": 700, "wnd_maximized": False, "browser_width": 300,
"market_height": 0, "fitting_height": -200}
self.mainFrameAttribs = SettingsProvider.getInstance().getSettings("pyfaMainWindowAttribs",
mainFrameDefaultAttribs)
if self.mainFrameAttribs["wnd_maximized"]:
width = mainFrameDefaultAttribs["wnd_width"]
@@ -623,7 +627,8 @@ class MainFrame(wx.Frame):
ModifiedAttributeDict.OVERRIDES = not ModifiedAttributeDict.OVERRIDES
wx.PostEvent(self, GE.FitChanged(fitID=self.getActiveFit()))
menu = self.GetMenuBar()
menu.SetLabel(menu.toggleOverridesId, "Turn Overrides Off" if ModifiedAttributeDict.OVERRIDES else "Turn Overrides On")
menu.SetLabel(menu.toggleOverridesId,
"Turn Overrides Off" if ModifiedAttributeDict.OVERRIDES else "Turn Overrides On")
def saveChar(self, event):
sChr = Character.getInstance()

View File

@@ -27,7 +27,6 @@ import gui.graphFrame
import gui.globalEvents as GE
from gui.bitmapLoader import BitmapLoader
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
from service.crest import CrestModes
@@ -158,7 +157,8 @@ class MainMenuBar(wx.MenuBar):
helpMenu.Append(wx.ID_ABOUT)
if config.debug:
helpMenu.Append(self.mainFrame.widgetInspectMenuID, "Open Widgets Inspect tool", "Open Widgets Inspect tool")
helpMenu.Append(self.mainFrame.widgetInspectMenuID, "Open Widgets Inspect tool",
"Open Widgets Inspect tool")
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)

View File

@@ -1,462 +1,461 @@
# =============================================================================
# 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/>.
# =============================================================================
import wx
from service.market import Market
from service.attribute import Attribute
import gui.display as d
import gui.PFSearchBox as SBox
from gui.cachingImageList import CachingImageList
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
RECENTLY_USED_MODULES = -2
MAX_RECENTLY_USED_MODULES = 20
class MarketBrowser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
vbox = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(vbox)
# Add a search box on top
self.search = SearchBox(self)
vbox.Add(self.search, 0, wx.EXPAND)
self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
vbox.Add(self.splitter, 1, wx.EXPAND)
# Grab market service instance and create child objects
self.sMkt = Market.getInstance()
self.searchMode = False
self.marketView = MarketTree(self.splitter, self)
self.itemView = ItemView(self.splitter, self)
self.splitter.SplitHorizontally(self.marketView, self.itemView)
self.splitter.SetMinimumPaneSize(250)
# Setup our buttons for metaGroup selection
# Same fix as for search box on macs,
# need some pixels of extra space or everything clips and is ugly
p = wx.Panel(self)
box = wx.BoxSizer(wx.HORIZONTAL)
p.SetSizer(box)
vbox.Add(p, 0, wx.EXPAND)
self.metaButtons = []
for name in self.sMkt.META_MAP.keys():
btn = wx.ToggleButton(p, wx.ID_ANY, name.capitalize(), style=wx.BU_EXACTFIT)
setattr(self, name, btn)
box.Add(btn, 1, wx.ALIGN_CENTER)
btn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleMetaButton)
btn.metaName = name
self.metaButtons.append(btn)
# Make itemview to set toggles according to list contents
self.itemView.setToggles()
p.SetMinSize((wx.SIZE_AUTO_WIDTH, btn.GetSize()[1] + 5))
def toggleMetaButton(self, event):
"""Process clicks on toggle buttons"""
ctrl = wx.GetMouseState().CmdDown()
ebtn = event.EventObject
if not ctrl:
for btn in self.metaButtons:
if btn.Enabled:
if btn == ebtn:
btn.SetValue(True)
else:
btn.SetValue(False)
else:
# Note: using the 'wrong' value for clicked button might seem weird,
# But the button is toggled by wx and we should deal with it
activeBtns = set()
for btn in self.metaButtons:
if (btn.GetValue() is True and btn != ebtn) or (btn.GetValue() is False and btn == ebtn):
activeBtns.add(btn)
# Do 'nothing' if we're trying to turn last active button off
if len(activeBtns) == 1 and activeBtns.pop() == ebtn:
# Keep button in the same state
ebtn.SetValue(True)
return
# Leave old unfiltered list contents, just re-filter them and show
self.itemView.filterItemStore()
def jump(self, item):
self.marketView.jump(item)
class SearchBox(SBox.PFSearchBox):
def __init__(self, parent, **kwargs):
SBox.PFSearchBox.__init__(self, parent, **kwargs)
cancelBitmap = BitmapLoader.getBitmap("fit_delete_small", "gui")
searchBitmap = BitmapLoader.getBitmap("fsearch_small", "gui")
self.SetSearchBitmap(searchBitmap)
self.SetCancelBitmap(cancelBitmap)
self.ShowSearchButton()
self.ShowCancelButton()
class MarketTree(wx.TreeCtrl):
def __init__(self, parent, marketBrowser):
wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
self.root = self.AddRoot("root")
self.imageList = CachingImageList(16, 16)
self.SetImageList(self.imageList)
self.sMkt = marketBrowser.sMkt
self.marketBrowser = marketBrowser
# Form market tree root
sMkt = self.sMkt
for mktGrp in sMkt.getMarketRoot():
iconId = self.addImage(sMkt.getIconByMarketGroup(mktGrp))
childId = self.AppendItem(self.root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
# All market groups which were never expanded are dummies, here we assume
# that all root market groups are expandable
self.AppendItem(childId, "dummy")
self.SortChildren(self.root)
# Add recently used modules node
rumIconId = self.addImage("market_small", "gui")
self.AppendItem(self.root, "Recently Used Modules", rumIconId, data=wx.TreeItemData(RECENTLY_USED_MODULES))
# Bind our lookup method to when the tree gets expanded
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
def addImage(self, iconFile, location="icons"):
if iconFile is None:
return -1
return self.imageList.GetImageIndex(iconFile, location)
def expandLookup(self, event):
"""Process market tree expands"""
root = event.Item
child = self.GetFirstChild(root)[0]
# If child of given market group is a dummy
if self.GetItemText(child) == "dummy":
# Delete it
self.Delete(child)
# And add real market group contents
sMkt = self.sMkt
currentMktGrp = sMkt.getMarketGroup(self.GetPyData(root), eager="children")
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
# If market should have items but it doesn't, do not show it
if sMkt.marketGroupValidityCheck(childMktGrp) is False:
continue
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
try:
childId = self.AppendItem(root, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
except:
continue
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
self.AppendItem(childId, "dummy")
self.SortChildren(root)
def jump(self, item):
"""Open market group and meta tab of given item"""
self.marketBrowser.searchMode = False
sMkt = self.sMkt
mg = sMkt.getMarketGroupByItem(item)
metaId = sMkt.getMetaGroupIdByItem(item)
jumpList = []
while mg is not None:
jumpList.append(mg.ID)
mg = mg.parent
for id in sMkt.ROOT_MARKET_GROUPS:
if id in jumpList:
jumpList = jumpList[:jumpList.index(id) + 1]
item = self.root
for i in range(len(jumpList) - 1, -1, -1):
target = jumpList[i]
child, cookie = self.GetFirstChild(item)
while self.GetItemPyData(child) != target:
child, cookie = self.GetNextChild(item, cookie)
item = child
self.Expand(item)
self.SelectItem(item)
self.marketBrowser.itemView.selectionMade(forcedMetaSelect=metaId)
class ItemView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"attr:power,,,True",
"attr:cpu,,,True"]
def __init__(self, parent, marketBrowser):
d.Display.__init__(self, parent)
marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade)
self.unfilteredStore = set()
self.filteredStore = set()
self.recentlyUsedModules = set()
self.sMkt = marketBrowser.sMkt
self.searchMode = marketBrowser.searchMode
self.marketBrowser = marketBrowser
self.marketView = marketBrowser.marketView
# Make sure our search actually does interesting stuff
self.marketBrowser.search.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
self.marketBrowser.search.Bind(SBox.EVT_TEXT, self.scheduleSearch)
# Make sure WE do interesting stuff too
self.Bind(wx.EVT_CONTEXT_MENU, self.contextMenu)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
# Make reverse map, used by sorter
self.metaMap = self.makeReverseMetaMap()
# Fill up recently used modules set
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
def startDrag(self, event):
row = self.GetFirstSelected()
if row != -1:
data = wx.PyTextDataObject()
data.SetText("market:" + str(self.active[row].ID))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
dropSource.DoDragDrop()
def itemActivated(self, event=None):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
if self.mainFrame.getActiveFit():
self.storeRecentlyUsedMarketItem(self.active[sel].ID)
self.recentlyUsedModules = set()
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
wx.PostEvent(self.mainFrame, ItemSelected(itemID=self.active[sel].ID))
def storeRecentlyUsedMarketItem(self, itemID):
if len(self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]) > MAX_RECENTLY_USED_MODULES:
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].pop(0)
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].append(itemID)
def selectionMade(self, event=None, forcedMetaSelect=None):
self.marketBrowser.searchMode = False
# Grab the threeview selection and check if it's fine
sel = self.marketView.GetSelection()
if sel.IsOk():
# Get data field of the selected item (which is a marketGroup ID if anything was selected)
seldata = self.marketView.GetPyData(sel)
if seldata is not None and seldata != RECENTLY_USED_MODULES:
# If market group treeview item doesn't have children (other market groups or dummies),
# then it should have items in it and we want to request them
if self.marketView.ItemHasChildren(sel) is False:
sMkt = self.sMkt
# Get current market group
mg = sMkt.getMarketGroup(seldata, eager=("items", "items.metaGroup"))
# Get all its items
items = sMkt.getItemsByMarketGroup(mg)
else:
items = set()
else:
# If method was called but selection wasn't actually made or we have a hit on recently used modules
if seldata == RECENTLY_USED_MODULES:
items = self.recentlyUsedModules
else:
items = set()
# Fill store
self.updateItemStore(items)
# Set toggle buttons / use search mode flag if recently used modules category is selected (in order to have all modules listed and not filtered)
if seldata is not RECENTLY_USED_MODULES:
self.setToggles(forcedMetaSelect=forcedMetaSelect)
else:
self.marketBrowser.searchMode = True
self.setToggles()
# Update filtered items
self.filterItemStore()
def updateItemStore(self, items):
self.unfilteredStore = items
def filterItemStore(self):
sMkt = self.sMkt
selectedMetas = set()
for btn in self.marketBrowser.metaButtons:
if btn.GetValue():
selectedMetas.update(sMkt.META_MAP[btn.metaName])
self.filteredStore = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas)
self.update(list(self.filteredStore))
def setToggles(self, forcedMetaSelect=None):
metaIDs = set()
sMkt = self.sMkt
for item in self.unfilteredStore:
metaIDs.add(sMkt.getMetaGroupIdByItem(item))
anySelection = False
for btn in self.marketBrowser.metaButtons:
btnMetas = sMkt.META_MAP[btn.metaName]
if len(metaIDs.intersection(btnMetas)) > 0:
btn.Enable(True)
# Select all available buttons if we're searching
if self.marketBrowser.searchMode is True:
btn.SetValue(True)
# Select explicitly requested button
if forcedMetaSelect is not None:
btn.SetValue(True if forcedMetaSelect in btnMetas else False)
else:
btn.Enable(False)
btn.SetValue(False)
if btn.GetValue():
anySelection = True
# If no buttons are pressed, press first active
if anySelection is False:
for btn in self.marketBrowser.metaButtons:
if btn.Enabled:
btn.SetValue(True)
break
def scheduleSearch(self, event=None):
search = self.marketBrowser.search.GetLineText(0)
# Make sure we do not count wildcard as search symbol
realsearch = search.replace("*", "")
# Re-select market group if search query has zero length
if len(realsearch) == 0:
self.selectionMade()
return
# Show nothing if query is too short
elif len(realsearch) < 3:
self.clearSearch()
return
self.marketBrowser.searchMode = True
self.sMkt.searchItems(search, self.populateSearch)
def clearSearch(self, event=None):
# Wipe item store and update everything to accomodate with it
# If clearSearch was generated by SearchCtrl's Cancel button, clear the content also
if event:
self.marketBrowser.search.Clear()
self.marketBrowser.searchMode = False
self.updateItemStore(set())
self.setToggles()
self.filterItemStore()
def populateSearch(self, items):
# If we're no longer searching, dump the results
if self.marketBrowser.searchMode is False:
return
self.updateItemStore(items)
self.setToggles()
self.filterItemStore()
def itemSort(self, item):
sMkt = self.sMkt
catname = sMkt.getCategoryByItem(item).name
try:
mktgrpid = sMkt.getMarketGroupByItem(item).ID
except AttributeError:
mktgrpid = None
print("unable to find market group for", item.name)
parentname = sMkt.getParentItemByItem(item).name
# Get position of market group
metagrpid = sMkt.getMetaGroupIdByItem(item)
metatab = self.metaMap.get(metagrpid)
metalvl = self.metalvls.get(item.ID, 0)
return (catname, mktgrpid, parentname, metatab, metalvl, item.name)
def contextMenu(self, event):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
item = self.active[sel]
sMkt = self.sMkt
sourceContext = "marketItemGroup" if self.marketBrowser.searchMode is False else "marketItemMisc"
itemContext = sMkt.getCategoryByItem(item).name
menu = ContextMenu.getMenu((item,), (sourceContext, itemContext))
self.PopupMenu(menu)
def populate(self, items):
if len(items) > 0:
# Get dictionary with meta level attribute
sAttr = Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Clear selection
self.deselectItems()
# Perform sorting, using item's meta levels besides other stuff
items.sort(key=self.itemSort)
# Mark current item list as active
self.active = items
# Show them
d.Display.populate(self, items)
def refresh(self, items):
if len(items) > 1:
# Get dictionary with meta level attribute
sAttr = Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Re-sort stuff
items.sort(key=self.itemSort)
for i, item in enumerate(items[:9]):
# set shortcut info for first 9 modules
item.marketShortcut = i + 1
d.Display.refresh(self, items)
def makeReverseMetaMap(self):
"""
Form map which tells in which tab items of given metagroup are located
"""
revmap = {}
i = 0
for mgids in self.sMkt.META_MAP.itervalues():
for mgid in mgids:
revmap[mgid] = i
i += 1
return revmap
# =============================================================================
# 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/>.
# =============================================================================
import wx
from service.market import Market
from service.attribute import Attribute
import gui.display as d
import gui.PFSearchBox as SBox
from gui.cachingImageList import CachingImageList
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
ItemSelected, ITEM_SELECTED = wx.lib.newevent.NewEvent()
RECENTLY_USED_MODULES = -2
MAX_RECENTLY_USED_MODULES = 20
class MarketBrowser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
vbox = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(vbox)
# Add a search box on top
self.search = SearchBox(self)
vbox.Add(self.search, 0, wx.EXPAND)
self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
vbox.Add(self.splitter, 1, wx.EXPAND)
# Grab market service instance and create child objects
self.sMkt = Market.getInstance()
self.searchMode = False
self.marketView = MarketTree(self.splitter, self)
self.itemView = ItemView(self.splitter, self)
self.splitter.SplitHorizontally(self.marketView, self.itemView)
self.splitter.SetMinimumPaneSize(250)
# Setup our buttons for metaGroup selection
# Same fix as for search box on macs,
# need some pixels of extra space or everything clips and is ugly
p = wx.Panel(self)
box = wx.BoxSizer(wx.HORIZONTAL)
p.SetSizer(box)
vbox.Add(p, 0, wx.EXPAND)
self.metaButtons = []
for name in self.sMkt.META_MAP.keys():
btn = wx.ToggleButton(p, wx.ID_ANY, name.capitalize(), style=wx.BU_EXACTFIT)
setattr(self, name, btn)
box.Add(btn, 1, wx.ALIGN_CENTER)
btn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleMetaButton)
btn.metaName = name
self.metaButtons.append(btn)
# Make itemview to set toggles according to list contents
self.itemView.setToggles()
p.SetMinSize((wx.SIZE_AUTO_WIDTH, btn.GetSize()[1] + 5))
def toggleMetaButton(self, event):
"""Process clicks on toggle buttons"""
ctrl = wx.GetMouseState().CmdDown()
ebtn = event.EventObject
if not ctrl:
for btn in self.metaButtons:
if btn.Enabled:
if btn == ebtn:
btn.SetValue(True)
else:
btn.SetValue(False)
else:
# Note: using the 'wrong' value for clicked button might seem weird,
# But the button is toggled by wx and we should deal with it
activeBtns = set()
for btn in self.metaButtons:
if (btn.GetValue() is True and btn != ebtn) or (btn.GetValue() is False and btn == ebtn):
activeBtns.add(btn)
# Do 'nothing' if we're trying to turn last active button off
if len(activeBtns) == 1 and activeBtns.pop() == ebtn:
# Keep button in the same state
ebtn.SetValue(True)
return
# Leave old unfiltered list contents, just re-filter them and show
self.itemView.filterItemStore()
def jump(self, item):
self.marketView.jump(item)
class SearchBox(SBox.PFSearchBox):
def __init__(self, parent, **kwargs):
SBox.PFSearchBox.__init__(self, parent, **kwargs)
cancelBitmap = BitmapLoader.getBitmap("fit_delete_small", "gui")
searchBitmap = BitmapLoader.getBitmap("fsearch_small", "gui")
self.SetSearchBitmap(searchBitmap)
self.SetCancelBitmap(cancelBitmap)
self.ShowSearchButton()
self.ShowCancelButton()
class MarketTree(wx.TreeCtrl):
def __init__(self, parent, marketBrowser):
wx.TreeCtrl.__init__(self, parent, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
self.root = self.AddRoot("root")
self.imageList = CachingImageList(16, 16)
self.SetImageList(self.imageList)
self.sMkt = marketBrowser.sMkt
self.marketBrowser = marketBrowser
# Form market tree root
sMkt = self.sMkt
for mktGrp in sMkt.getMarketRoot():
iconId = self.addImage(sMkt.getIconByMarketGroup(mktGrp))
childId = self.AppendItem(self.root, mktGrp.name, iconId, data=wx.TreeItemData(mktGrp.ID))
# All market groups which were never expanded are dummies, here we assume
# that all root market groups are expandable
self.AppendItem(childId, "dummy")
self.SortChildren(self.root)
# Add recently used modules node
rumIconId = self.addImage("market_small", "gui")
self.AppendItem(self.root, "Recently Used Modules", rumIconId, data=wx.TreeItemData(RECENTLY_USED_MODULES))
# Bind our lookup method to when the tree gets expanded
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.expandLookup)
def addImage(self, iconFile, location="icons"):
if iconFile is None:
return -1
return self.imageList.GetImageIndex(iconFile, location)
def expandLookup(self, event):
"""Process market tree expands"""
root = event.Item
child = self.GetFirstChild(root)[0]
# If child of given market group is a dummy
if self.GetItemText(child) == "dummy":
# Delete it
self.Delete(child)
# And add real market group contents
sMkt = self.sMkt
currentMktGrp = sMkt.getMarketGroup(self.GetPyData(root), eager="children")
for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp):
# If market should have items but it doesn't, do not show it
if sMkt.marketGroupValidityCheck(childMktGrp) is False:
continue
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
try:
childId = self.AppendItem(root, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID))
except:
continue
if sMkt.marketGroupHasTypesCheck(childMktGrp) is False:
self.AppendItem(childId, "dummy")
self.SortChildren(root)
def jump(self, item):
"""Open market group and meta tab of given item"""
self.marketBrowser.searchMode = False
sMkt = self.sMkt
mg = sMkt.getMarketGroupByItem(item)
metaId = sMkt.getMetaGroupIdByItem(item)
jumpList = []
while mg is not None:
jumpList.append(mg.ID)
mg = mg.parent
for id in sMkt.ROOT_MARKET_GROUPS:
if id in jumpList:
jumpList = jumpList[:jumpList.index(id) + 1]
item = self.root
for i in range(len(jumpList) - 1, -1, -1):
target = jumpList[i]
child, cookie = self.GetFirstChild(item)
while self.GetItemPyData(child) != target:
child, cookie = self.GetNextChild(item, cookie)
item = child
self.Expand(item)
self.SelectItem(item)
self.marketBrowser.itemView.selectionMade(forcedMetaSelect=metaId)
class ItemView(d.Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"attr:power,,,True",
"attr:cpu,,,True"]
def __init__(self, parent, marketBrowser):
d.Display.__init__(self, parent)
marketBrowser.Bind(wx.EVT_TREE_SEL_CHANGED, self.selectionMade)
self.unfilteredStore = set()
self.filteredStore = set()
self.recentlyUsedModules = set()
self.sMkt = marketBrowser.sMkt
self.searchMode = marketBrowser.searchMode
self.marketBrowser = marketBrowser
self.marketView = marketBrowser.marketView
# Make sure our search actually does interesting stuff
self.marketBrowser.search.Bind(SBox.EVT_TEXT_ENTER, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_SEARCH_BTN, self.scheduleSearch)
self.marketBrowser.search.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
self.marketBrowser.search.Bind(SBox.EVT_TEXT, self.scheduleSearch)
# Make sure WE do interesting stuff too
self.Bind(wx.EVT_CONTEXT_MENU, self.contextMenu)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
# Make reverse map, used by sorter
self.metaMap = self.makeReverseMetaMap()
# Fill up recently used modules set
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
def startDrag(self, event):
row = self.GetFirstSelected()
if row != -1:
data = wx.PyTextDataObject()
data.SetText("market:" + str(self.active[row].ID))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
dropSource.DoDragDrop()
def itemActivated(self, event=None):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
if self.mainFrame.getActiveFit():
self.storeRecentlyUsedMarketItem(self.active[sel].ID)
self.recentlyUsedModules = set()
for itemID in self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]:
self.recentlyUsedModules.add(self.sMkt.getItem(itemID))
wx.PostEvent(self.mainFrame, ItemSelected(itemID=self.active[sel].ID))
def storeRecentlyUsedMarketItem(self, itemID):
if len(self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"]) > MAX_RECENTLY_USED_MODULES:
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].pop(0)
self.sMkt.serviceMarketRecentlyUsedModules["pyfaMarketRecentlyUsedModules"].append(itemID)
def selectionMade(self, event=None, forcedMetaSelect=None):
self.marketBrowser.searchMode = False
# Grab the threeview selection and check if it's fine
sel = self.marketView.GetSelection()
if sel.IsOk():
# Get data field of the selected item (which is a marketGroup ID if anything was selected)
seldata = self.marketView.GetPyData(sel)
if seldata is not None and seldata != RECENTLY_USED_MODULES:
# If market group treeview item doesn't have children (other market groups or dummies),
# then it should have items in it and we want to request them
if self.marketView.ItemHasChildren(sel) is False:
sMkt = self.sMkt
# Get current market group
mg = sMkt.getMarketGroup(seldata, eager=("items", "items.metaGroup"))
# Get all its items
items = sMkt.getItemsByMarketGroup(mg)
else:
items = set()
else:
# If method was called but selection wasn't actually made or we have a hit on recently used modules
if seldata == RECENTLY_USED_MODULES:
items = self.recentlyUsedModules
else:
items = set()
# Fill store
self.updateItemStore(items)
# Set toggle buttons / use search mode flag if recently used modules category is selected (in order to have all modules listed and not filtered)
if seldata is not RECENTLY_USED_MODULES:
self.setToggles(forcedMetaSelect=forcedMetaSelect)
else:
self.marketBrowser.searchMode = True
self.setToggles()
# Update filtered items
self.filterItemStore()
def updateItemStore(self, items):
self.unfilteredStore = items
def filterItemStore(self):
sMkt = self.sMkt
selectedMetas = set()
for btn in self.marketBrowser.metaButtons:
if btn.GetValue():
selectedMetas.update(sMkt.META_MAP[btn.metaName])
self.filteredStore = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas)
self.update(list(self.filteredStore))
def setToggles(self, forcedMetaSelect=None):
metaIDs = set()
sMkt = self.sMkt
for item in self.unfilteredStore:
metaIDs.add(sMkt.getMetaGroupIdByItem(item))
anySelection = False
for btn in self.marketBrowser.metaButtons:
btnMetas = sMkt.META_MAP[btn.metaName]
if len(metaIDs.intersection(btnMetas)) > 0:
btn.Enable(True)
# Select all available buttons if we're searching
if self.marketBrowser.searchMode is True:
btn.SetValue(True)
# Select explicitly requested button
if forcedMetaSelect is not None:
btn.SetValue(True if forcedMetaSelect in btnMetas else False)
else:
btn.Enable(False)
btn.SetValue(False)
if btn.GetValue():
anySelection = True
# If no buttons are pressed, press first active
if anySelection is False:
for btn in self.marketBrowser.metaButtons:
if btn.Enabled:
btn.SetValue(True)
break
def scheduleSearch(self, event=None):
search = self.marketBrowser.search.GetLineText(0)
# Make sure we do not count wildcard as search symbol
realsearch = search.replace("*", "")
# Re-select market group if search query has zero length
if len(realsearch) == 0:
self.selectionMade()
return
# Show nothing if query is too short
elif len(realsearch) < 3:
self.clearSearch()
return
self.marketBrowser.searchMode = True
self.sMkt.searchItems(search, self.populateSearch)
def clearSearch(self, event=None):
# Wipe item store and update everything to accomodate with it
# If clearSearch was generated by SearchCtrl's Cancel button, clear the content also
if event:
self.marketBrowser.search.Clear()
self.marketBrowser.searchMode = False
self.updateItemStore(set())
self.setToggles()
self.filterItemStore()
def populateSearch(self, items):
# If we're no longer searching, dump the results
if self.marketBrowser.searchMode is False:
return
self.updateItemStore(items)
self.setToggles()
self.filterItemStore()
def itemSort(self, item):
sMkt = self.sMkt
catname = sMkt.getCategoryByItem(item).name
try:
mktgrpid = sMkt.getMarketGroupByItem(item).ID
except AttributeError:
mktgrpid = None
print("unable to find market group for", item.name)
parentname = sMkt.getParentItemByItem(item).name
# Get position of market group
metagrpid = sMkt.getMetaGroupIdByItem(item)
metatab = self.metaMap.get(metagrpid)
metalvl = self.metalvls.get(item.ID, 0)
return (catname, mktgrpid, parentname, metatab, metalvl, item.name)
def contextMenu(self, event):
# Check if something is selected, if so, spawn the menu for it
sel = self.GetFirstSelected()
if sel == -1:
return
item = self.active[sel]
sMkt = self.sMkt
sourceContext = "marketItemGroup" if self.marketBrowser.searchMode is False else "marketItemMisc"
itemContext = sMkt.getCategoryByItem(item).name
menu = ContextMenu.getMenu((item,), (sourceContext, itemContext))
self.PopupMenu(menu)
def populate(self, items):
if len(items) > 0:
# Get dictionary with meta level attribute
sAttr = Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Clear selection
self.deselectItems()
# Perform sorting, using item's meta levels besides other stuff
items.sort(key=self.itemSort)
# Mark current item list as active
self.active = items
# Show them
d.Display.populate(self, items)
def refresh(self, items):
if len(items) > 1:
# Get dictionary with meta level attribute
sAttr = Attribute.getInstance()
attrs = sAttr.getAttributeInfo("metaLevel")
sMkt = self.sMkt
self.metalvls = sMkt.directAttrRequest(items, attrs)
# Re-sort stuff
items.sort(key=self.itemSort)
for i, item in enumerate(items[:9]):
# set shortcut info for first 9 modules
item.marketShortcut = i + 1
d.Display.refresh(self, items)
def makeReverseMetaMap(self):
"""
Form map which tells in which tab items of given metagroup are located
"""
revmap = {}
i = 0
for mgids in self.sMkt.META_MAP.itervalues():
for mgid in mgids:
revmap[mgid] = i
i += 1
return revmap

View File

@@ -164,18 +164,18 @@ class DmgPatternEditorDlg(wx.Dialog):
("Export", wx.ART_FILE_SAVE_AS, "to"))
for name, art, direction in importExport:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
btn.SetMinSize(btn.GetSize())
btn.SetMaxSize(btn.GetSize())
btn.SetMinSize(btn.GetSize())
btn.SetMaxSize(btn.GetSize())
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction))
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
btn.Bind(wx.EVT_BUTTON, getattr(self, "{}Patterns".format(name.lower())))
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s patterns %s clipboard" % (name, direction))
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
btn.Bind(wx.EVT_BUTTON, getattr(self, "{}Patterns".format(name.lower())))
self.Layout()
bsize = self.GetBestSize()
@@ -196,10 +196,10 @@ class DmgPatternEditorDlg(wx.Dialog):
p = self.entityEditor.getActiveEntity()
total = sum(map(lambda attr: getattr(self, "%sEdit" % attr).GetValue(), self.DAMAGE_TYPES))
for type_ in self.DAMAGE_TYPES:
editObj = getattr(self, "%sEdit" % type_)
percObj = getattr(self, "%sPerc" % type_)
setattr(p, "%sAmount" % type_, editObj.GetValue())
percObj.SetLabel("%.1f%%" % (float(editObj.GetValue()) * 100 / total if total > 0 else 0))
editObj = getattr(self, "%sEdit" % type_)
percObj = getattr(self, "%sPerc" % type_)
setattr(p, "%sAmount" % type_, editObj.GetValue())
percObj.SetLabel("%.1f%%" % (float(editObj.GetValue()) * 100 / total if total > 0 else 0))
self.totSizer.Layout()

View File

@@ -25,7 +25,8 @@ logger = logging.getLogger(__name__)
class AttributeEditor(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, title="Attribute Editor", pos=wx.DefaultPosition,
size=wx.Size(650, 600), style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT | wx.TAB_TRAVERSAL)
size=wx.Size(650, 600),
style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT | wx.TAB_TRAVERSAL)
i = wx.IconFromBitmap(BitmapLoader.getBitmap("fit_rename_small", "gui"))
self.SetIcon(i)
@@ -54,7 +55,8 @@ class AttributeEditor(wx.Frame):
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
leftSizer = wx.BoxSizer(wx.VERTICAL)
leftPanel = wx.Panel(panel, wx.ID_ANY, style=wx.DOUBLE_BORDER if 'wxMSW' in wx.PlatformInfo else wx.SIMPLE_BORDER)
leftPanel = wx.Panel(panel, wx.ID_ANY,
style=wx.DOUBLE_BORDER if 'wxMSW' in wx.PlatformInfo else wx.SIMPLE_BORDER)
self.searchBox = SearchBox(leftPanel)
self.itemView = ItemView(leftPanel)
@@ -66,7 +68,8 @@ class AttributeEditor(wx.Frame):
mainSizer.Add(leftPanel, 1, wx.ALL | wx.EXPAND, 5)
rightSizer = wx.BoxSizer(wx.VERTICAL)
self.btnRemoveOverrides = wx.Button(panel, wx.ID_ANY, u"Remove Overides for Item", wx.DefaultPosition, wx.DefaultSize, 0)
self.btnRemoveOverrides = wx.Button(panel, wx.ID_ANY, u"Remove Overides for Item", wx.DefaultPosition,
wx.DefaultSize, 0)
self.pg = AttributeGrid(panel)
rightSizer.Add(self.pg, 1, wx.ALL | wx.EXPAND, 5)
rightSizer.Add(self.btnRemoveOverrides, 0, wx.ALL | wx.EXPAND, 5)
@@ -202,7 +205,8 @@ class ItemView(d.Display):
class AttributeGrid(wxpg.PropertyGrid):
def __init__(self, parent):
wxpg.PropertyGrid.__init__(self, parent, style=wxpg.PG_HIDE_MARGIN | wxpg.PG_HIDE_CATEGORIES | wxpg.PG_BOLD_MODIFIED | wxpg.PG_TOOLTIPS)
wxpg.PropertyGrid.__init__(self, parent,
style=wxpg.PG_HIDE_MARGIN | wxpg.PG_HIDE_CATEGORIES | wxpg.PG_BOLD_MODIFIED | wxpg.PG_TOOLTIPS)
self.SetExtraStyle(wxpg.PG_EX_HELP_AS_TOOLTIPS)
self.item = None

View File

@@ -27,7 +27,8 @@ from gui.bitmapLoader import BitmapLoader
class TogglePanel(wx.Panel):
def __init__(self, parent, forceLayout=-1):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL)
wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(-1, -1),
style=wx.TAB_TRAVERSAL)
self._toggle = 1
self.parent = parent

View File

@@ -79,7 +79,6 @@ class TargetResistsEntityEditor(EntityEditor):
class ResistsEditorDlg(wx.Dialog):
DAMAGE_TYPES = ("em", "thermal", "kinetic", "explosive")
def __init__(self, parent):
@@ -120,7 +119,8 @@ class ResistsEditorDlg(wx.Dialog):
setattr(self, "%sEdit" % type_, wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, defSize))
editObj = getattr(self, "%sEdit" % type_)
resistEditSizer.Add(editObj, 0, wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5)
resistEditSizer.Add(wx.StaticText(self, wx.ID_ANY, u"%", wx.DefaultPosition, wx.DefaultSize, 0), 0, wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5)
resistEditSizer.Add(wx.StaticText(self, wx.ID_ANY, u"%", wx.DefaultPosition, wx.DefaultSize, 0), 0,
wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER_VERTICAL, 5)
editObj.Bind(wx.EVT_TEXT, self.ValuesUpdated)
# Color we use to reset invalid value color

View File

@@ -146,17 +146,17 @@ class ImplantSetEditorDlg(wx.Dialog):
("Export", wx.ART_FILE_SAVE_AS, "to"))
for name, art, direction in importExport:
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
bitmap = wx.ArtProvider.GetBitmap(art, wx.ART_BUTTON)
btn = wx.BitmapButton(self, wx.ID_ANY, bitmap)
btn.SetMinSize(btn.GetSize())
btn.SetMaxSize(btn.GetSize())
btn.SetMinSize(btn.GetSize())
btn.SetMaxSize(btn.GetSize())
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s implant sets %s clipboard" % (name, direction))
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
btn.Layout()
setattr(self, name, btn)
btn.Enable(True)
btn.SetToolTipString("%s implant sets %s clipboard" % (name, direction))
footerSizer.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_RIGHT)
mainSizer.Add(footerSizer, 0, wx.ALL | wx.EXPAND, 5)

View File

@@ -13,7 +13,8 @@ BTN_DISABLED = 8
class PFBaseButton(object):
def __init__(self, normalBitmap=wx.NullBitmap, label="", callback=None, hoverBitmap=None, disabledBitmap=None, show=True):
def __init__(self, normalBitmap=wx.NullBitmap, label="", callback=None, hoverBitmap=None, disabledBitmap=None,
show=True):
self.normalBmp = normalBitmap
self.dropShadowOpacity = 0.2

View File

@@ -20,7 +20,6 @@ from gui.PFListPane import PFListPane
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
FitRenamed, EVT_FIT_RENAMED = wx.lib.newevent.NewEvent()
FitSelected, EVT_FIT_SELECTED = wx.lib.newevent.NewEvent()
FitRemoved, EVT_FIT_REMOVED = wx.lib.newevent.NewEvent()
@@ -67,7 +66,8 @@ class PFWidgetsContainer(PFListPane):
class RaceSelector(wx.Window):
def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, layout=wx.VERTICAL, animate=False):
def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0,
layout=wx.VERTICAL, animate=False):
wx.Window.__init__(self, parent, id, pos=pos, size=size, style=style)
self.animTimerID = wx.NewId()
@@ -344,11 +344,16 @@ class NavigationPanel(SFItem.SFBrowserItem):
self.switchBmp = self.AdjustChannels(self.switchBmpH)
self.newBmp = self.AdjustChannels(self.newBmpH)
self.toolbar.AddButton(self.resetBmp, "Ship groups", clickCallback=self.OnHistoryReset, hoverBitmap=self.resetBmpH)
self.toolbar.AddButton(self.resetBmp, "Ship groups", clickCallback=self.OnHistoryReset,
hoverBitmap=self.resetBmpH)
self.toolbar.AddButton(self.rewBmp, "Back", clickCallback=self.OnHistoryBack, hoverBitmap=self.rewBmpH)
self.btnNew = self.toolbar.AddButton(self.newBmp, "New fitting", clickCallback=self.OnNewFitting, hoverBitmap=self.newBmpH, show=False)
self.btnSwitch = self.toolbar.AddButton(self.switchBmpD, "Hide empty ship groups", clickCallback=self.ToggleEmptyGroupsView, hoverBitmap=self.switchBmpH, show=False)
self.toolbar.AddButton(self.searchBmp, "Search fittings", clickCallback=self.ToggleSearchBox, hoverBitmap=self.searchBmpH)
self.btnNew = self.toolbar.AddButton(self.newBmp, "New fitting", clickCallback=self.OnNewFitting,
hoverBitmap=self.newBmpH, show=False)
self.btnSwitch = self.toolbar.AddButton(self.switchBmpD, "Hide empty ship groups",
clickCallback=self.ToggleEmptyGroupsView, hoverBitmap=self.switchBmpH,
show=False)
self.toolbar.AddButton(self.searchBmp, "Search fittings", clickCallback=self.ToggleSearchBox,
hoverBitmap=self.searchBmpH)
self.padding = 4
self.lastSearch = ""
@@ -357,7 +362,9 @@ class NavigationPanel(SFItem.SFBrowserItem):
self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL)
w, h = size
self.BrowserSearchBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, (-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1), wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0))
self.BrowserSearchBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition,
(-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1),
wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0))
self.BrowserSearchBox.Show(False)
self.BrowserSearchBox.Bind(wx.EVT_TEXT_ENTER, self.OnBrowserSearchBoxEnter)
@@ -882,7 +889,9 @@ class ShipBrowser(wx.Panel):
for ship in ships:
shipTrait = ship.traits.traitText if (ship.traits is not None) else "" # empty string if no traits
self.lpane.AddWidget(ShipItem(self.lpane, ship.ID, (ship.name, shipTrait, len(sFit.getFitsWithShip(ship.ID))), ship.race))
self.lpane.AddWidget(
ShipItem(self.lpane, ship.ID, (ship.name, shipTrait, len(sFit.getFitsWithShip(ship.ID))),
ship.race))
for ID, name, shipID, shipName, booster, timestamp in fitList:
ship = sMkt.getItem(shipID)
@@ -923,7 +932,8 @@ class ShipBrowser(wx.Panel):
if fits:
for fit in fits:
shipTrait = fit.ship.traits.traitText if (fit.ship.traits is not None) else "" # empty string if no traits
shipTrait = fit.ship.traits.traitText if (
fit.ship.traits is not None) else "" # empty string if no traits
self.lpane.AddWidget(FitItem(
self.lpane,
@@ -1067,6 +1077,7 @@ class CategoryItem(SFItem.SFBrowserItem):
mdc.DrawText(categoryName, self.catx, self.caty)
# =============================================================================
# Waiting for total #fits impl in eos/service
#
@@ -1140,7 +1151,8 @@ class ShipItem(SFItem.SFBrowserItem):
self.editWidth = 150
self.padding = 4
self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s fit" % self.shipName, wx.DefaultPosition, (120, -1), wx.TE_PROCESS_ENTER)
self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s fit" % self.shipName, wx.DefaultPosition, (120, -1),
wx.TE_PROCESS_ENTER)
self.tcFitName.Show(False)
self.newBtn = self.toolbar.AddButton(self.newBmp, "New", self.newBtnCB)
@@ -1331,7 +1343,8 @@ class ShipItem(SFItem.SFBrowserItem):
mdc.SetFont(self.fontBig)
psname = drawUtils.GetPartialText(mdc, shipName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
psname = drawUtils.GetPartialText(mdc, shipName,
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(psname, self.textStartx, self.shipNamey)
@@ -1353,7 +1366,8 @@ class ShipItem(SFItem.SFBrowserItem):
class PFBitmapFrame(wx.Frame):
def __init__(self, parent, pos, bitmap):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=pos, size=wx.DefaultSize, style=wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP)
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=pos, size=wx.DefaultSize,
style=wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP)
img = bitmap.ConvertToImage()
img = img.ConvertToGreyscale()
bitmap = wx.BitmapFromImage(img)
@@ -1409,7 +1423,8 @@ class PFBitmapFrame(wx.Frame):
class FitItem(SFItem.SFBrowserItem):
def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0), shipID=None, itemData=None,
def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0), shipID=None,
itemData=None,
id=wx.ID_ANY, pos=wx.DefaultPosition,
size=(0, 40), style=0):
@@ -1487,7 +1502,8 @@ class FitItem(SFItem.SFBrowserItem):
self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.renameBtnCB)
self.toolbar.AddButton(self.deleteBmp, "Delete", self.deleteBtnCB)
self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fitName, wx.DefaultPosition, (self.editWidth, -1), wx.TE_PROCESS_ENTER)
self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fitName, wx.DefaultPosition, (self.editWidth, -1),
wx.TE_PROCESS_ENTER)
if self.shipBrowser.fitIDMustEditName != self.fitID:
self.tcFitName.Show(False)
@@ -1852,7 +1868,8 @@ class FitItem(SFItem.SFBrowserItem):
fitDate = time.localtime(self.timestamp)
fitLocalDate = "%d/%02d/%02d %02d:%02d" % (fitDate[0], fitDate[1], fitDate[2], fitDate[3], fitDate[4])
pfdate = drawUtils.GetPartialText(mdc, fitLocalDate, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
pfdate = drawUtils.GetPartialText(mdc, fitLocalDate,
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(pfdate, self.textStartx, self.timestampy)
@@ -1861,7 +1878,8 @@ class FitItem(SFItem.SFBrowserItem):
mdc.SetFont(self.fontBig)
psname = drawUtils.GetPartialText(mdc, self.fitName, self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
psname = drawUtils.GetPartialText(mdc, self.fitName,
self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw)
mdc.DrawText(psname, self.textStartx, self.fitNamey)

View File

@@ -81,7 +81,8 @@ class StatsPane(wx.Panel):
mainSizer.Add(tp, 0, wx.EXPAND | wx.LEFT, 3)
if i < maxviews - 1:
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, style=wx.HORIZONTAL), 0, wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 2)
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, style=wx.HORIZONTAL), 0,
wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, 2)
i += 1
tp.OnStateChange(tp.GetBestSize())

View File

@@ -23,79 +23,89 @@ import config
import dateutil.parser
from service import settings
class UpdateDialog(wx.Dialog):
class UpdateDialog(wx.Dialog):
def __init__(self, parent, release):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = "Pyfa Update", pos = wx.DefaultPosition, size = wx.Size( 400,300 ), style = wx.DEFAULT_DIALOG_STYLE )
wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="Pyfa Update", pos=wx.DefaultPosition,
size=wx.Size(400, 300), style=wx.DEFAULT_DIALOG_STYLE)
self.UpdateSettings = settings.UpdateSettings.getInstance()
self.releaseInfo = release
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
mainSizer = wx.BoxSizer( wx.VERTICAL )
mainSizer = wx.BoxSizer(wx.VERTICAL)
headSizer = wx.BoxSizer( wx.HORIZONTAL )
headSizer = wx.BoxSizer(wx.HORIZONTAL)
self.headingText = wx.StaticText( self, wx.ID_ANY, "Pyfa Update Available!", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE )
self.headingText.Wrap( -1 )
self.headingText.SetFont( wx.Font( 14, 74, 90, 92, False) )
self.headingText = wx.StaticText(self, wx.ID_ANY, "Pyfa Update Available!", wx.DefaultPosition, wx.DefaultSize,
wx.ALIGN_CENTRE)
self.headingText.Wrap(-1)
self.headingText.SetFont(wx.Font(14, 74, 90, 92, False))
headSizer.Add( self.headingText, 1, wx.ALL, 5 )
mainSizer.Add( headSizer, 0, wx.EXPAND, 5 )
headSizer.Add(self.headingText, 1, wx.ALL, 5)
mainSizer.Add(headSizer, 0, wx.EXPAND, 5)
mainSizer.Add( wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0, wx.EXPAND |wx.ALL, 5 )
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND | wx.ALL, 5)
versionSizer = wx.BoxSizer( wx.HORIZONTAL )
versionSizer = wx.BoxSizer(wx.HORIZONTAL)
if(self.releaseInfo['prerelease']):
self.releaseText = wx.StaticText( self, wx.ID_ANY, "Pre-release", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
self.releaseText.SetFont( wx.Font( 12, 74, 90, 92, False) )
self.releaseText.SetForegroundColour( wx.Colour( 230, 0, 0 ) )
if (self.releaseInfo['prerelease']):
self.releaseText = wx.StaticText(self, wx.ID_ANY, "Pre-release", wx.DefaultPosition, wx.DefaultSize,
wx.ALIGN_RIGHT)
self.releaseText.SetFont(wx.Font(12, 74, 90, 92, False))
self.releaseText.SetForegroundColour(wx.Colour(230, 0, 0))
else:
self.releaseText = wx.StaticText( self, wx.ID_ANY, "Stable", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_RIGHT )
self.releaseText.SetFont( wx.Font( 12, 74, 90, 90, False) )
self.releaseText = wx.StaticText(self, wx.ID_ANY, "Stable", wx.DefaultPosition, wx.DefaultSize,
wx.ALIGN_RIGHT)
self.releaseText.SetFont(wx.Font(12, 74, 90, 90, False))
self.releaseText.Wrap( -1 )
self.releaseText.Wrap(-1)
versionSizer.Add( self.releaseText, 1, wx.ALL, 5 )
versionSizer.Add(self.releaseText, 1, wx.ALL, 5)
self.versionText = wx.StaticText( self, wx.ID_ANY, self.releaseInfo['tag_name'], wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_LEFT )
self.versionText.Wrap( -1 )
self.versionText.SetFont( wx.Font( 12, 74, 90, 90, False) )
self.versionText = wx.StaticText(self, wx.ID_ANY, self.releaseInfo['tag_name'], wx.DefaultPosition,
wx.DefaultSize, wx.ALIGN_LEFT)
self.versionText.Wrap(-1)
self.versionText.SetFont(wx.Font(12, 74, 90, 90, False))
versionSizer.Add( self.versionText, 1, wx.ALL, 5 )
versionSizer.AddSpacer( ( 15, 5), 0, wx.EXPAND, 5 )
versionSizer.Add(self.versionText, 1, wx.ALL, 5)
versionSizer.AddSpacer((15, 5), 0, wx.EXPAND, 5)
mainSizer.Add( versionSizer, 0, wx.EXPAND, 5 )
mainSizer.AddSpacer( ( 0, 5), 0, wx.EXPAND, 5 )
mainSizer.Add(versionSizer, 0, wx.EXPAND, 5)
mainSizer.AddSpacer((0, 5), 0, wx.EXPAND, 5)
releaseDate = dateutil.parser.parse(self.releaseInfo['published_at'])
notesSizer = wx.BoxSizer( wx.HORIZONTAL )
self.notesTextCtrl = wx.TextCtrl( self, wx.ID_ANY, str(releaseDate.date())+":\n\n"+self.releaseInfo['body'], wx.DefaultPosition, wx.DefaultSize, wx.TE_AUTO_URL|wx.TE_MULTILINE|wx.TE_READONLY|wx.DOUBLE_BORDER|wx.TRANSPARENT_WINDOW )
notesSizer = wx.BoxSizer(wx.HORIZONTAL)
self.notesTextCtrl = wx.TextCtrl(self, wx.ID_ANY, str(releaseDate.date()) + ":\n\n" + self.releaseInfo['body'],
wx.DefaultPosition, wx.DefaultSize,
wx.TE_AUTO_URL | wx.TE_MULTILINE | wx.TE_READONLY | wx.DOUBLE_BORDER | wx.TRANSPARENT_WINDOW)
notesSizer.Add( self.notesTextCtrl, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5 )
mainSizer.Add( notesSizer, 1, wx.EXPAND, 5 )
notesSizer.Add(self.notesTextCtrl, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
mainSizer.Add(notesSizer, 1, wx.EXPAND, 5)
self.supressCheckbox = wx.CheckBox( self, wx.ID_ANY, "Don't remind me again for this release", wx.DefaultPosition, wx.DefaultSize, 0 )
self.supressCheckbox = wx.CheckBox(self, wx.ID_ANY, "Don't remind me again for this release",
wx.DefaultPosition, wx.DefaultSize, 0)
self.supressCheckbox.Bind(wx.EVT_CHECKBOX, self.SuppressChange)
mainSizer.Add( self.supressCheckbox, 0, wx.ALL, 5 )
mainSizer.Add( wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ), 0, wx.EXPAND |wx.ALL, 5 )
mainSizer.Add(self.supressCheckbox, 0, wx.ALL, 5)
mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0,
wx.EXPAND | wx.ALL, 5)
actionSizer = wx.BoxSizer( wx.HORIZONTAL )
actionSizer = wx.BoxSizer(wx.HORIZONTAL)
goSizer = wx.BoxSizer( wx.VERTICAL )
self.downloadButton = wx.Button( self, wx.ID_ANY, "Download", wx.DefaultPosition, wx.DefaultSize, 0 )
goSizer = wx.BoxSizer(wx.VERTICAL)
self.downloadButton = wx.Button(self, wx.ID_ANY, "Download", wx.DefaultPosition, wx.DefaultSize, 0)
self.downloadButton.Bind(wx.EVT_BUTTON, self.OnDownload)
goSizer.Add( self.downloadButton, 0, wx.ALL, 5 )
actionSizer.Add( goSizer, 1, wx.EXPAND, 5 )
goSizer.Add(self.downloadButton, 0, wx.ALL, 5)
actionSizer.Add(goSizer, 1, wx.EXPAND, 5)
self.closeButton = wx.Button(self, wx.ID_CLOSE)
self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
actionSizer.Add( self.closeButton, 0, wx.ALL, 5 )
mainSizer.Add( actionSizer, 0, wx.EXPAND, 5 )
actionSizer.Add(self.closeButton, 0, wx.ALL, 5)
mainSizer.Add(actionSizer, 0, wx.EXPAND, 5)
self.SetSizer( mainSizer )
self.SetSizer(mainSizer)
self.Layout()
# Handle use-case of suppressing a release, then a new version becoming available.
@@ -104,7 +114,7 @@ class UpdateDialog(wx.Dialog):
# safely reset this setting
self.UpdateSettings.set('version', None)
self.Centre( wx.BOTH )
self.Centre(wx.BOTH)
def OnClose(self, e):
self.Close()
@@ -116,5 +126,5 @@ class UpdateDialog(wx.Dialog):
self.UpdateSettings.set('version', None)
def OnDownload(self, e):
wx.LaunchDefaultBrowser('https://github.com/pyfa-org/Pyfa/releases/tag/'+self.releaseInfo['tag_name'])
wx.LaunchDefaultBrowser('https://github.com/pyfa-org/Pyfa/releases/tag/' + self.releaseInfo['tag_name'])
self.OnClose(e)

View File

@@ -5,11 +5,9 @@ different wxPython versions
import wx
if 'wxMac' in wx.PlatformInfo:
sizes = (10, 11, 12)
else:
sizes = (7, 8, 9)
SMALL, NORMAL, BIG = sizes