diff --git a/graphs/gui/frame.py b/graphs/gui/frame.py index 32226c679..b078ebd18 100644 --- a/graphs/gui/frame.py +++ b/graphs/gui/frame.py @@ -67,14 +67,17 @@ except Exception: class GraphFrame(wx.Frame): - def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT): + def __init__(self, parent): global graphFrame_enabled if not graphFrame_enabled: pyfalog.warning('Matplotlib is not enabled. Skipping initialization.') return - wx.Frame.__init__(self, parent, title='pyfa: Graph Generator', style=style, size=(520, 390)) + wx.Frame.__init__( + self, parent, title='Graphs', + style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT, + size=(520, 390)) self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.SetIcon(wx.Icon(BitmapLoader.getBitmap('graphs_small', 'gui'))) @@ -122,7 +125,7 @@ class GraphFrame(wx.Frame): self.ctrlPanel.updateControls(layout=False) # Event bindings - local events - self.Bind(wx.EVT_CLOSE, self.closeEvent) + self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_CHAR_HOOK, self.kbEvent) # Event bindings - external events @@ -149,15 +152,11 @@ class GraphFrame(wx.Frame): self.SetSize(newSize) self.SetMinSize(newSize) - def closeEvent(self, event): - self.closeWindow() - event.Skip() - def kbEvent(self, event): keycode = event.GetKeyCode() mstate = wx.GetMouseState() if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE: - self.closeWindow() + self.Close() return event.Skip() @@ -224,7 +223,7 @@ class GraphFrame(wx.Frame): self.draw() event.Skip() - def closeWindow(self): + def OnClose(self, event): self.mainFrame.Unbind(GE.FIT_RENAMED, handler=self.OnFitRenamed) self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.OnFitChanged) self.mainFrame.Unbind(GE.FIT_REMOVED, handler=self.OnFitRemoved) @@ -233,7 +232,7 @@ class GraphFrame(wx.Frame): self.mainFrame.Unbind(GE.TARGET_PROFILE_REMOVED, handler=self.OnProfileRemoved) self.mainFrame.Unbind(RESIST_MODE_CHANGED, handler=self.OnResistModeChanged) self.mainFrame.Unbind(GE.GRAPH_OPTION_CHANGED, handler=self.OnGraphOptionChanged) - self.Destroy() + event.Skip() def getView(self): return self.graphSelection.GetClientData(self.graphSelection.GetSelection()) diff --git a/gui/builtinContextMenus/targetProfile/editor.py b/gui/builtinContextMenus/targetProfile/editor.py index c523115fd..be42dd264 100644 --- a/gui/builtinContextMenus/targetProfile/editor.py +++ b/gui/builtinContextMenus/targetProfile/editor.py @@ -2,7 +2,7 @@ import gui.mainFrame from eos.saveddata.targetProfile import TargetProfile from graphs.wrapper import TargetWrapper from gui.contextMenu import ContextMenuSingle -from gui.targetProfileEditor import TargetProfileEditorDlg +from gui.targetProfileEditor import TargetProfileEditor class TargetProfileEditor(ContextMenuSingle): @@ -25,8 +25,7 @@ class TargetProfileEditor(ContextMenuSingle): return 'Edit Target Profile' def activate(self, callingWindow, fullContext, mainItem, i): - with TargetProfileEditorDlg(parent=callingWindow, selected=mainItem.item) as dlg: - dlg.ShowModal() + self.mainFrame.ShowTargetProfileEditor(selected=mainItem.item) TargetProfileEditor.register() diff --git a/gui/builtinViews/entityEditor.py b/gui/builtinViews/entityEditor.py index 93b9be1dd..c941657a5 100644 --- a/gui/builtinViews/entityEditor.py +++ b/gui/builtinViews/entityEditor.py @@ -97,58 +97,60 @@ class EntityEditor(wx.Panel): raise NotImplementedError() def OnNew(self, event): - dlg = TextEntryValidatedDialog(self, self.validator, - "Enter a name for your new {}:".format(self.entityName), - "New {}".format(self.entityName)) - dlg.CenterOnParent() + with TextEntryValidatedDialog( + self, self.validator, "Enter a name for your new {}:".format(self.entityName), + "New {}".format(self.entityName) + ) as dlg: + dlg.CenterOnParent() - if dlg.ShowModal() == wx.ID_OK: - # using dlg.textctrl.GetValue instead of simply dlg.GetValue because the proper way does not work in wxPython 2.8 - new = self.DoNew(dlg.txtctrl.GetValue().strip()) - self.refreshEntityList(new) - wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) - else: - return False + if dlg.ShowModal() == wx.ID_OK: + # using dlg.textctrl.GetValue instead of simply dlg.GetValue because the proper way does not work in wxPython 2.8 + new = self.DoNew(dlg.txtctrl.GetValue().strip()) + self.refreshEntityList(new) + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + else: + return False def OnCopy(self, event): - dlg = TextEntryValidatedDialog(self, self.validator, - "Enter a name for your {} copy:".format(self.entityName), - "Copy {}".format(self.entityName)) - active = self.getActiveEntity() - dlg.SetValue("{} Copy".format(active.name)) - dlg.txtctrl.SetInsertionPointEnd() - dlg.CenterOnParent() + with TextEntryValidatedDialog( + self, self.validator, "Enter a name for your {} copy:".format(self.entityName), + "Copy {}".format(self.entityName) + ) as dlg: + active = self.getActiveEntity() + dlg.SetValue("{} Copy".format(active.name)) + dlg.txtctrl.SetInsertionPointEnd() + dlg.CenterOnParent() - if dlg.ShowModal() == wx.ID_OK: - copy = self.DoCopy(active, dlg.txtctrl.GetValue().strip()) - self.refreshEntityList(copy) - wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + if dlg.ShowModal() == wx.ID_OK: + copy = self.DoCopy(active, dlg.txtctrl.GetValue().strip()) + self.refreshEntityList(copy) + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) def OnRename(self, event): - dlg = TextEntryValidatedDialog(self, self.validator, - "Enter a new name for your {}:".format(self.entityName), - "Rename {}".format(self.entityName)) - active = self.getActiveEntity() - dlg.SetValue(active.name) - dlg.txtctrl.SetInsertionPointEnd() - dlg.CenterOnParent() + with TextEntryValidatedDialog( + self, self.validator, "Enter a new name for your {}:".format(self.entityName), + "Rename {}".format(self.entityName) + ) as dlg: + active = self.getActiveEntity() + dlg.SetValue(active.name) + dlg.txtctrl.SetInsertionPointEnd() + dlg.CenterOnParent() - if dlg.ShowModal() == wx.ID_OK: - self.DoRename(active, dlg.txtctrl.GetValue().strip()) - self.refreshEntityList(active) - wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + if dlg.ShowModal() == wx.ID_OK: + self.DoRename(active, dlg.txtctrl.GetValue().strip()) + self.refreshEntityList(active) + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) def OnDelete(self, event): - dlg = wx.MessageDialog(self, - "Do you really want to delete the {} {}?".format(self.getActiveEntity().name, - self.entityName), - "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION) - dlg.CenterOnParent() - - if dlg.ShowModal() == wx.ID_YES: - self.DoDelete(self.getActiveEntity()) - self.refreshEntityList() - wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) + with wx.MessageDialog( + self, "Do you really want to delete the {} {}?".format(self.getActiveEntity().name, self.entityName), + "Confirm Delete", wx.YES | wx.NO | wx.ICON_QUESTION + ) as dlg: + dlg.CenterOnParent() + if dlg.ShowModal() == wx.ID_YES: + self.DoDelete(self.getActiveEntity()) + self.refreshEntityList() + wx.PostEvent(self.entityChoices, wx.CommandEvent(wx.wxEVT_COMMAND_CHOICE_SELECTED)) def refreshEntityList(self, selected=None): self.choices = self.getEntitiesFromContext() @@ -168,7 +170,11 @@ class EntityEditor(wx.Panel): return self.choices[self.entityChoices.GetSelection()] def setActiveEntity(self, entity): - self.entityChoices.SetSelection(self.choices.index(entity)) + try: + idx = self.choices.index(entity) + except IndexError: + return + self.entityChoices.SetSelection(idx) def checkEntitiesExist(self): if len(self.choices) == 0: diff --git a/gui/characterSelection.py b/gui/characterSelection.py index ef99bc5b8..841e6c7e3 100644 --- a/gui/characterSelection.py +++ b/gui/characterSelection.py @@ -180,7 +180,7 @@ class CharacterSelection(wx.Panel): if charID == -1: # revert to previous character self.charChoice.SetSelection(self.charCache) - self.mainFrame.showCharacterEditor(event) + self.mainFrame.OnShowCharacterEditor(event) return self.toggleRefreshButton() diff --git a/gui/esiFittings.py b/gui/esiFittings.py index b987782b7..d58734a1a 100644 --- a/gui/esiFittings.py +++ b/gui/esiFittings.py @@ -24,7 +24,7 @@ class EveFittings(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(750, 450), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL) + size=wx.Size(750, 450), style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT) self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 4cc550354..aa018997c 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -60,7 +60,7 @@ from gui.preferenceDialog import PreferenceDialog from gui.setEditor import ImplantSetEditorDlg from gui.shipBrowser import ShipBrowser from gui.statsPane import StatsPane -from gui.targetProfileEditor import TargetProfileEditorDlg +from gui.targetProfileEditor import TargetProfileEditor from gui.updateDialog import UpdateDialog from gui.utils.clipboard import fromClipboard from service.character import Character @@ -213,6 +213,7 @@ class MainFrame(wx.Frame): # Internal vars to keep track of other windows (graphing/stats) self.graphFrame = None + self.tgtProfileEditor = None self.statsWnds = [] self.activeStatsWnd = None @@ -385,31 +386,39 @@ class MainFrame(wx.Frame): # info.WebSite = (forumUrl, "pyfa thread at EVE Online forum") wx.adv.AboutBox(info) - def showDevTools(self, event): + def OnShowDevTools(self, event): dlg = DevTools(self) dlg.Show() - def showCharacterEditor(self, event): + def OnShowCharacterEditor(self, event): dlg = CharacterEditor(self) dlg.Show() - def showAttrEditor(self, event): + def OnShowAttrEditor(self, event): dlg = AttributeEditor(self) dlg.Show() - def showTargetProfileEditor(self, event): - with TargetProfileEditorDlg(self) as dlg: - dlg.ShowModal() + def OnShowTargetProfileEditor(self, event): + self.ShowTargetProfileEditor() - def showDamagePatternEditor(self, event): + def ShowTargetProfileEditor(self, selected=None): + if not self.tgtProfileEditor: + self.tgtProfileEditor = TargetProfileEditor(self, selected=selected) + self.tgtProfileEditor.Show() + else: + if selected: + self.tgtProfileEditor.selectTargetProfile(selected) + self.tgtProfileEditor.SetFocus() + + def OnShowDamagePatternEditor(self, event): with DmgPatternEditorDlg(self) as dlg: dlg.ShowModal() - def showImplantSetEditor(self, event): + def OnShowImplantSetEditor(self, event): with ImplantSetEditorDlg(self) as dlg: dlg.ShowModal() - def showExportDialog(self, event): + def OnShowExportDialog(self, event): """ Export active fit """ sFit = Fit.getInstance() fit = sFit.getFit(self.getActiveFit()) @@ -444,7 +453,7 @@ class MainFrame(wx.Frame): except RuntimeError: pyfalog.error("Tried to destroy an object that doesn't exist in .") - def showPreferenceDialog(self, event): + def OnShowPreferenceDialog(self, event): with PreferenceDialog(self) as dlg: dlg.ShowModal() @@ -463,21 +472,21 @@ class MainFrame(wx.Frame): # Widgets Inspector if config.debug: self.Bind(wx.EVT_MENU, self.openWXInspectTool, id=self.widgetInspectMenuID) - self.Bind(wx.EVT_MENU, self.showDevTools, id=menuBar.devToolsId) + self.Bind(wx.EVT_MENU, self.OnShowDevTools, id=menuBar.devToolsId) # About self.Bind(wx.EVT_MENU, self.ShowAboutBox, id=wx.ID_ABOUT) # Char editor - self.Bind(wx.EVT_MENU, self.showCharacterEditor, id=menuBar.characterEditorId) + self.Bind(wx.EVT_MENU, self.OnShowCharacterEditor, id=menuBar.characterEditorId) # Damage pattern editor - self.Bind(wx.EVT_MENU, self.showDamagePatternEditor, id=menuBar.damagePatternEditorId) + self.Bind(wx.EVT_MENU, self.OnShowDamagePatternEditor, id=menuBar.damagePatternEditorId) # Target Profile editor - self.Bind(wx.EVT_MENU, self.showTargetProfileEditor, id=menuBar.targetProfileEditorId) + self.Bind(wx.EVT_MENU, self.OnShowTargetProfileEditor, id=menuBar.targetProfileEditorId) # Implant Set editor - self.Bind(wx.EVT_MENU, self.showImplantSetEditor, id=menuBar.implantSetEditorId) + self.Bind(wx.EVT_MENU, self.OnShowImplantSetEditor, id=menuBar.implantSetEditorId) # Import dialog self.Bind(wx.EVT_MENU, self.fileImportDialog, id=wx.ID_OPEN) # Export dialog - self.Bind(wx.EVT_MENU, self.showExportDialog, id=wx.ID_SAVEAS) + self.Bind(wx.EVT_MENU, self.OnShowExportDialog, id=wx.ID_SAVEAS) # Import from Clipboard self.Bind(wx.EVT_MENU, self.importFromClipboard, id=wx.ID_PASTE) # Backup fits @@ -489,7 +498,7 @@ class MainFrame(wx.Frame): # Export HTML self.Bind(wx.EVT_MENU, self.exportHtml, id=menuBar.exportHtmlId) # Preference dialog - self.Bind(wx.EVT_MENU, self.showPreferenceDialog, id=wx.ID_PREFERENCES) + self.Bind(wx.EVT_MENU, self.OnShowPreferenceDialog, id=wx.ID_PREFERENCES) # User guide self.Bind(wx.EVT_MENU, self.goWiki, id=menuBar.wikiId) @@ -515,7 +524,7 @@ class MainFrame(wx.Frame): self.Bind(wx.EVT_MENU, self.ssoHandler, id=menuBar.ssoLoginId) # Open attribute editor - self.Bind(wx.EVT_MENU, self.showAttrEditor, id=menuBar.attrEditorId) + self.Bind(wx.EVT_MENU, self.OnShowAttrEditor, id=menuBar.attrEditorId) # Toggle Overrides self.Bind(wx.EVT_MENU, self.toggleOverrides, id=menuBar.toggleOverridesId) @@ -526,7 +535,7 @@ class MainFrame(wx.Frame): self.Bind(wx.EVT_MENU, self.toggleIgnoreRestriction, id=menuBar.toggleIgnoreRestrictionID) # Graphs - self.Bind(wx.EVT_MENU, self.openGraphFrame, id=menuBar.graphFrameId) + self.Bind(wx.EVT_MENU, self.OnShowGraphFrame, id=menuBar.graphFrameId) toggleSearchBoxId = wx.NewId() toggleShipMarketId = wx.NewId() @@ -957,7 +966,7 @@ class MainFrame(wx.Frame): def closeWaitDialog(self): del self.waitDialog - def openGraphFrame(self, event): + def OnShowGraphFrame(self, event): if not self.graphFrame: self.graphFrame = GraphFrame(self) diff --git a/gui/targetProfileEditor.py b/gui/targetProfileEditor.py index a72d21098..57d82deef 100644 --- a/gui/targetProfileEditor.py +++ b/gui/targetProfileEditor.py @@ -111,7 +111,7 @@ class TargetProfileEntityEditor(EntityEditor): wx.PostEvent(self.mainFrame, GE.TargetProfileRemoved(profileID=entity.ID)) -class TargetProfileEditorDlg(wx.Dialog): +class TargetProfileEditor(wx.Frame): DAMAGE_TYPES = OrderedDict([ ("em", "EM resistance"), @@ -124,9 +124,9 @@ class TargetProfileEditorDlg(wx.Dialog): ('radius', ('Radius', 'm'))]) def __init__(self, parent, selected=None): - wx.Dialog.__init__( + wx.Frame.__init__( self, parent, id=wx.ID_ANY, - title="Target Profile Editor", + title="Target Profile Editor", style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT, # Dropdown list widget is scaled to its longest content line on GTK, adapt to that size=wx.Size(500, 240) if "wxGTK" in wx.PlatformInfo else wx.Size(350, 240)) @@ -235,7 +235,7 @@ class TargetProfileEditorDlg(wx.Dialog): btn.Bind(wx.EVT_BUTTON, getattr(self, "{}Patterns".format(name.lower()))) if not self.entityEditor.checkEntitiesExist(): - self.Destroy() + self.Close() return self.Layout() @@ -259,10 +259,15 @@ class TargetProfileEditorDlg(wx.Dialog): def OnInputTimer(self, event): event.Skip() - if self.block: return + if self.validateFields(): + p = self.entityEditor.getActiveEntity() + TargetProfile.getInstance().saveChanges(p) + wx.PostEvent(self.mainFrame, GE.TargetProfileChanged(profileID=p.ID)) + def validateFields(self): + valid = True try: p = self.entityEditor.getActiveEntity() @@ -289,22 +294,18 @@ class TargetProfileEditorDlg(wx.Dialog): self.stNotice.SetLabel("") self.totSizer.Layout() - if event is not None: - event.Skip() - - TargetProfile.getInstance().saveChanges(p) - wx.PostEvent(self.mainFrame, GE.TargetProfileChanged(profileID=p.ID)) - except ValueError as e: self.stNotice.SetLabel(e.args[0]) + valid = False finally: # Refresh for color changes to take effect immediately self.Refresh() + return valid def patternChanged(self, event=None): """Event fired when user selects pattern. Can also be called from script""" if not self.entityEditor.checkEntitiesExist(): - self.Destroy() + self.Close() return p = self.entityEditor.getActiveEntity() @@ -327,7 +328,7 @@ class TargetProfileEditorDlg(wx.Dialog): edit.ChangeValueFloat(amount) self.block = False - self.OnFieldChanged() + self.validateFields() def __del__(self): pass @@ -372,3 +373,7 @@ class TargetProfileEditorDlg(wx.Dialog): changedFitIDs = Fit.getInstance().processTargetProfileChange() if changedFitIDs: wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=changedFitIDs)) + + def selectTargetProfile(self, profile): + self.entityEditor.setActiveEntity(profile) + self.patternChanged()