Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,7 @@ gitversion
eve.db

# vscode settings
.vscode
.vscode

# Local launcher (not for upstream)
run.ps1
28 changes: 26 additions & 2 deletions gui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys
from logbook import Logger
pyfalog = Logger(__name__)
from service.settings import LocaleSettings
from service.settings import LocaleSettings, ThemeSettings


class PyfaApp(wx.App):
Expand All @@ -16,6 +16,9 @@ def OnInit(self):
# Name for my application.
self.appName = "pyfa"

# Windows can only apply appearance before any windows exist.
self.ApplyAppearance()

#------------

# # Simplified init method.
Expand Down Expand Up @@ -74,4 +77,25 @@ def UpdateLanguage(self, lang=None):

else:
pyfalog.debug("Cannot find langauge: " + lang)
self.locale = wx.Locale(wx.Locale.FindLanguageInfo(LocaleSettings.defaults['locale']).Language)
self.locale = wx.Locale(wx.Locale.FindLanguageInfo(LocaleSettings.defaults['locale']).Language)

def ApplyAppearance(self):
try:
appearance_map = {
ThemeSettings.SYSTEM: wx.App.Appearance.System,
ThemeSettings.LIGHT: wx.App.Appearance.Light,
ThemeSettings.DARK: wx.App.Appearance.Dark,
}
except AttributeError:
pyfalog.debug("wx.App.Appearance is not available; skipping theme setup")
return

mode = ThemeSettings.getInstance().get('appearance')
target = appearance_map.get(mode, wx.App.Appearance.System)
try:
result = self.SetAppearance(target)
pyfalog.info("Set appearance to {0} (result {1})", mode, result)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.warning("Failed to set application appearance: {0}", e)
6 changes: 3 additions & 3 deletions gui/builtinPreferenceViews/pyfaDatabasePreferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def populatePanel(self, panel):
mainSizer.Add(self.stSetUserPath, 0, wx.ALL, 5)
self.inputUserPath = wx.TextCtrl(panel, wx.ID_ANY, config.savePath, wx.DefaultPosition, wx.DefaultSize, 0)
self.inputUserPath.SetEditable(False)
self.inputUserPath.SetBackgroundColour((200, 200, 200))
self.inputUserPath.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer.Add(self.inputUserPath, 0, wx.ALL | wx.EXPAND, 5)

# Save DB
Expand All @@ -50,7 +50,7 @@ def populatePanel(self, panel):

self.inputFitDB = wx.TextCtrl(panel, wx.ID_ANY, config.saveDB, wx.DefaultPosition, wx.DefaultSize, 0)
self.inputFitDB.SetEditable(False)
self.inputFitDB.SetBackgroundColour((200, 200, 200))
self.inputFitDB.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer.Add(self.inputFitDB, 0, wx.ALL | wx.EXPAND, 5)

# Game Data DB
Expand All @@ -60,7 +60,7 @@ def populatePanel(self, panel):

self.inputGameDB = wx.TextCtrl(panel, wx.ID_ANY, config.gameDB, wx.DefaultPosition, wx.DefaultSize, 0)
self.inputGameDB.SetEditable(False)
self.inputGameDB.SetBackgroundColour((200, 200, 200))
self.inputGameDB.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer.Add(self.inputGameDB, 0, wx.ALL | wx.EXPAND, 5)

self.cbsaveInRoot.SetValue(config.saveInRoot)
Expand Down
18 changes: 17 additions & 1 deletion gui/builtinPreferenceViews/pyfaGeneralPreferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from gui.bitmap_loader import BitmapLoader
from gui.preferenceView import PreferenceView
from service.fit import Fit
from service.settings import SettingsProvider, LocaleSettings
from service.settings import SettingsProvider, LocaleSettings, ThemeSettings
import eos.config
import wx.lib.agw.hyperlink as hl

Expand All @@ -23,6 +23,7 @@ def populatePanel(self, panel):
self.openFitsSettings = SettingsProvider.getInstance().getSettings("pyfaPrevOpenFits",
{"enabled": False, "pyfaOpenFits": []})
self.localeSettings = LocaleSettings.getInstance()
self.themeSettings = ThemeSettings.getInstance()
mainSizer = wx.BoxSizer(wx.VERTICAL)

self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title, wx.DefaultPosition, wx.DefaultSize, 0)
Expand Down Expand Up @@ -95,6 +96,17 @@ def langDisplay(langInfo):
wx.DefaultPosition,
wx.DefaultSize, 0), 0, wx.LEFT, 15)

self.appearanceChoices = [ThemeSettings.SYSTEM, ThemeSettings.LIGHT, ThemeSettings.DARK]
self.rbAppearance = wx.RadioBox(panel, -1, _t("Appearance (requires restart)"), wx.DefaultPosition, wx.DefaultSize,
[_t("System"), _t("Light"), _t("Dark")], 1, wx.RA_SPECIFY_COLS)
mainSizer.Add(self.rbAppearance, 0, wx.EXPAND | wx.TOP | wx.RIGHT | wx.BOTTOM, 10)
appearance = self.themeSettings.get('appearance')
try:
self.rbAppearance.SetSelection(self.appearanceChoices.index(appearance))
except ValueError:
self.rbAppearance.SetSelection(0)
self.rbAppearance.Bind(wx.EVT_RADIOBOX, self.OnAppearanceChange)

self.cbGlobalChar = wx.CheckBox(panel, wx.ID_ANY, _t("Use global character"), wx.DefaultPosition, wx.DefaultSize,
0)
mainSizer.Add(self.cbGlobalChar, 0, wx.ALL | wx.EXPAND, 5)
Expand Down Expand Up @@ -281,6 +293,10 @@ def onCBExpMutants(self, event):
fitID = self.mainFrame.getActiveFit()
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))

def OnAppearanceChange(self, event):
self.themeSettings.set('appearance', self.appearanceChoices[event.GetInt()])
event.Skip()

def OnAddLabelsChange(self, event):
self.sFit.serviceFittingOptions["additionsLabels"] = event.GetInt()
fitID = self.mainFrame.getActiveFit()
Expand Down
4 changes: 2 additions & 2 deletions gui/builtinPreferenceViews/pyfaLoggingPreferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def populatePanel(self, panel):
mainSizer.Add(self.stLogPath, 0, wx.ALL, 5)
self.inputLogPath = wx.TextCtrl(panel, wx.ID_ANY, config.logPath, wx.DefaultPosition, wx.DefaultSize, 0)
self.inputLogPath.SetEditable(False)
self.inputLogPath.SetBackgroundColour((200, 200, 200))
self.inputLogPath.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer.Add(self.inputLogPath, 0, wx.ALL | wx.EXPAND, 5)

import requests
Expand All @@ -49,7 +49,7 @@ def populatePanel(self, panel):
mainSizer.Add(self.certPath, 0, wx.ALL, 5)
self.certPathCtrl = wx.TextCtrl(panel, wx.ID_ANY, requests.certs.where(), wx.DefaultPosition, wx.DefaultSize, 0)
self.certPathCtrl.SetEditable(False)
self.certPathCtrl.SetBackgroundColour((200, 200, 200))
self.certPathCtrl.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
mainSizer.Add(self.certPathCtrl, 0, wx.ALL | wx.EXPAND, 5)

# Debug Logging
Expand Down
2 changes: 1 addition & 1 deletion gui/builtinShipBrowser/pfBitmapButton.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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)
self.bgcolor = wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))

def SetBackgroundColour(self, color):
self.bgcolor = wx.Brush(color)
Expand Down
2 changes: 0 additions & 2 deletions gui/utils/dark.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@


def isDark():
if 'wxMSW' in wx.PlatformInfo:
return False
try:
return wx.SystemSettings.GetAppearance().IsDark()
except (KeyboardInterrupt, SystemExit):
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
wxPython==4.2.1
wxPython==4.3.0
logbook==1.7.0.post0
numpy==1.26.2
matplotlib==3.8.2
Expand Down
33 changes: 33 additions & 0 deletions service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,36 @@ def set(self, key, value):
if key == 'locale' and value not in self.supported_languages():
self.settings[key] = self.DEFAULT
self.settings[key] = value


class ThemeSettings:
_instance = None

SYSTEM = "system"
LIGHT = "light"
DARK = "dark"
VALUES = (SYSTEM, LIGHT, DARK)

defaults = {
'appearance': SYSTEM,
}

def __init__(self):
self.settings = SettingsProvider.getInstance().getSettings('pyfaTheme', self.defaults)

@classmethod
def getInstance(cls):
if cls._instance is None:
cls._instance = ThemeSettings()
return cls._instance

def get(self, key):
value = self.settings[key]
if key == 'appearance' and value not in self.VALUES:
return self.defaults['appearance']
return value

def set(self, key, value):
if key == 'appearance' and value not in self.VALUES:
value = self.defaults['appearance']
self.settings[key] = value