Skip to content

Commit

Permalink
- Fixes #19
Browse files Browse the repository at this point in the history
  • Loading branch information
MyreMylar committed Nov 23, 2019
1 parent e1c541a commit 1e8b24c
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 35 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
include pygame_gui/data/licenses/*.txt
include pygame_gui/data/*.txt
include pygame_gui/data/*.ttf
include pygame_gui/data/*.json
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
sys.path.insert(0, os.path.abspath('../../pygame_gui/'))
sys.path.insert(0, os.path.abspath('../../pygame_gui/windows/'))
sys.path.insert(0, os.path.abspath('../../pygame_gui/elements/'))
sys.path.insert(0, os.path.abspath('../../pygame_gui/elements/text/'))
sys.path.insert(0, os.path.abspath('../../pygame_gui/core/'))


Expand Down
8 changes: 8 additions & 0 deletions pygame_gui/core/_string_data.py

Large diffs are not rendered by default.

71 changes: 51 additions & 20 deletions pygame_gui/core/ui_appearance_theme.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pygame
import json
import os
import io
import base64
import warnings
from contextlib import contextmanager

Expand All @@ -9,6 +11,13 @@
from pygame_gui.core.ui_font_dictionary import UIFontDictionary
from pygame_gui.core.ui_shadow import ShadowGenerator

# Only import the 'stringified' data if we can't find the actual default theme file
# This is need for working PyInstaller build
ROOT_PATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
THEME_PATH = os.path.normpath(os.path.join(ROOT_PATH, 'data/default_theme.json'))
if not os.path.exists(THEME_PATH):
from pygame_gui.core._string_data import default_theme

try:
from os import PathLike # for Python 3.6
except ImportError:
Expand Down Expand Up @@ -70,6 +79,8 @@ def __init__(self):
self.shape_cache = ShapeCache()

# the font to use if no other font is specified
# these hardcoded paths should be OK for PyInstaller right now because they will never actually used while
# fira_code is the default pre-loaded font. May need to re-vist this later.
module_root_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
self.base_font_info = {'name': 'fira_code',
'size': 14,
Expand Down Expand Up @@ -101,7 +112,15 @@ def __init__(self):

self._theme_file_last_modified = None
self._theme_file_path = None
self.load_theme(os.path.normpath(os.path.join(module_root_path, 'data/default_theme.json')))

# Only load the 'stringified' data if we can't find the actual default theme file
# This is need for PyInstaller build
default_theme_file_path = os.path.normpath(os.path.join(module_root_path, 'data/default_theme.json'))
if os.path.exists(default_theme_file_path):
self.load_theme(default_theme_file_path)
else:
default_theme_file = io.BytesIO(base64.standard_b64decode(default_theme))
self.load_theme(default_theme_file)

def get_font_dictionary(self):
"""
Expand All @@ -118,17 +137,18 @@ def check_need_to_reload(self):
:return bool: True if we need to reload elements because the theme data has changed.
"""
try:
stamp = os.stat(self._theme_file_path).st_mtime
except FileNotFoundError:
return False

if stamp != self._theme_file_last_modified:
self._theme_file_last_modified = stamp
self.reload_theming()
return True
else:
return False
if self._theme_file_path is not None:
try:
stamp = os.stat(self._theme_file_path).st_mtime
except FileNotFoundError:
return False

if stamp != self._theme_file_last_modified:
self._theme_file_last_modified = stamp
self.reload_theming()
return True
else:
return False

def update_shape_cache(self):
self.shape_cache.update()
Expand Down Expand Up @@ -487,17 +507,24 @@ def get_colour_or_gradient(self, object_ids, element_ids, colour_id):
@staticmethod
@contextmanager
def opened_w_error(filename, mode="r"):
try:
f = open(filename, mode)
except IOError as err:
yield None, err
if type(filename) != io.BytesIO:
try:
f = open(filename, mode)
except IOError as err:
yield None, err
else:
try:
yield f, None
finally:
f.close()
else:
f = filename
try:
yield f, None
finally:
f.close()

def load_theme(self, file_path: Union[str, PathLike]):
def load_theme(self, file_path: Union[str, PathLike, io.BytesIO]):
"""
Loads a theme file, and currently, all associated data like fonts and images required by the theme.
Expand All @@ -507,10 +534,14 @@ def load_theme(self, file_path: Union[str, PathLike]):
if file_path is None:
raise ValueError('Theme path cannot be None')

self._theme_file_path = file_path
self._theme_file_last_modified = os.stat(self._theme_file_path).st_mtime
if type(file_path) != io.BytesIO:
self._theme_file_path = file_path
self._theme_file_last_modified = os.stat(self._theme_file_path).st_mtime
used_file_path = os.path.abspath(file_path)
else:
used_file_path = file_path

with self.opened_w_error(os.path.abspath(file_path), 'r') as (theme_file, error):
with self.opened_w_error(used_file_path, 'r') as (theme_file, error):
if error:
warnings.warn("Failed to open theme file at path:" + str(file_path))
load_success = False
Expand Down
71 changes: 56 additions & 15 deletions pygame_gui/core/ui_font_dictionary.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import os
import io
import base64
import pygame
import warnings


# Only import the 'stringified' data if we can't find the actual default font file
# This is need for a working PyInstaller build
ROOT_PATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
FONT_PATH = os.path.normpath(os.path.join(ROOT_PATH, 'data/FiraCode-Regular.ttf'))
if not os.path.exists(FONT_PATH):
from pygame_gui.core._string_data import FiraCode_Regular, FiraCode_Bold
from pygame_gui.core._string_data import FiraMono_BoldItalic, FiraMono_RegularItalic


class UIFontDictionary:
"""
The font dictionary is used to store all the fonts that have been loaded into the UI system.
Expand Down Expand Up @@ -42,18 +53,31 @@ class UIFontDictionary:
def __init__(self):
self.default_font_size = 14

# Only use the 'stringified' data if we can't find the actual default font file
# This is need for a working PyInstaller build
module_root_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
self.loaded_fonts = {'fira_code_regular_14':
pygame.font.Font(os.path.join(module_root_path, 'data/FiraCode-Regular.ttf'),
self.default_font_size)}
self.known_font_paths = {'fira_code': [os.path.normpath(os.path.join(module_root_path,
'data/FiraCode-Regular.ttf')),
os.path.normpath(os.path.join(module_root_path,
'data/FiraCode-Bold.ttf')),
os.path.normpath(os.path.join(module_root_path,
'data/FiraMono-RegularItalic.ttf')),
os.path.normpath(os.path.join(module_root_path,
'data/FiraMono-BoldItalic.ttf'))]}
default_font_file_path = os.path.normpath(os.path.join(module_root_path, 'data/FiraCode-Regular.ttf'))
if os.path.exists(default_font_file_path):
self.loaded_fonts = {'fira_code_regular_14': pygame.font.Font(default_font_file_path,
self.default_font_size)}

self.known_font_paths = {'fira_code': [os.path.normpath(os.path.join(module_root_path,
'data/FiraCode-Regular.ttf')),
os.path.normpath(os.path.join(module_root_path,
'data/FiraCode-Bold.ttf')),
os.path.normpath(os.path.join(module_root_path,
'data/FiraMono-RegularItalic.ttf')),
os.path.normpath(os.path.join(module_root_path,
'data/FiraMono-BoldItalic.ttf'))]}
else:
fira_code_regular_file_object = io.BytesIO(base64.standard_b64decode(FiraCode_Regular))
self.loaded_fonts = {'fira_code_regular_14': pygame.font.Font(fira_code_regular_file_object,
self.default_font_size)}

self.known_font_paths = {'fira_code': [FiraCode_Regular,
FiraCode_Bold,
FiraMono_RegularItalic,
FiraMono_BoldItalic]}

self.used_font_ids = ['fira_code_regular_14']

Expand Down Expand Up @@ -140,7 +164,11 @@ def preload_font(self, font_size: int, font_name: str, bold: bool = False, itali
elif font_name in self.known_font_paths: # we know paths to this font, just haven't loaded current size/style
if bold and italic:
try:
new_font = pygame.font.Font(self.known_font_paths[font_name][3], font_size)
if type(self.known_font_paths[font_name][3]) == bytes:
file_loc = io.BytesIO(base64.standard_b64decode(self.known_font_paths[font_name][3]))
else:
file_loc = self.known_font_paths[font_name][3]
new_font = pygame.font.Font(file_loc, font_size)
new_font.set_bold(True)
new_font.set_italic(True)
self.loaded_fonts[font_id] = new_font
Expand All @@ -149,21 +177,34 @@ def preload_font(self, font_size: int, font_name: str, bold: bool = False, itali

elif bold and not italic:
try:
new_font = pygame.font.Font(self.known_font_paths[font_name][1], font_size)
if type(self.known_font_paths[font_name][1]) == bytes:
file_loc = io.BytesIO(base64.standard_b64decode(self.known_font_paths[font_name][1]))
else:
file_loc = self.known_font_paths[font_name][1]
new_font = pygame.font.Font(file_loc, font_size)
new_font.set_bold(True)
self.loaded_fonts[font_id] = new_font
except FileNotFoundError:
warnings.warn("Failed to load font at path: " + self.known_font_paths[font_name][1])
elif not bold and italic:
try:
new_font = pygame.font.Font(self.known_font_paths[font_name][2], font_size)
if type(self.known_font_paths[font_name][2]) == bytes:
file_loc = io.BytesIO(base64.standard_b64decode(self.known_font_paths[font_name][2]))
else:
file_loc = self.known_font_paths[font_name][2]
new_font = pygame.font.Font(file_loc, font_size)
new_font.set_italic(True)
self.loaded_fonts[font_id] = new_font
except FileNotFoundError:
warnings.warn("Failed to load font at path: " + self.known_font_paths[font_name][2])
else:
try:
self.loaded_fonts[font_id] = pygame.font.Font(self.known_font_paths[font_name][0], font_size)
if type(self.known_font_paths[font_name][0]) == bytes:
file_loc = io.BytesIO(base64.standard_b64decode(self.known_font_paths[font_name][0]))
else:
file_loc = self.known_font_paths[font_name][0]
new_font = pygame.font.Font(file_loc, font_size)
self.loaded_fonts[font_id] = new_font
except FileNotFoundError:
warnings.warn("Failed to load font at path: " + self.known_font_paths[font_name][0])
else:
Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
from setuptools import setup
from stringify import stringify_py

# will only run when calling: python setup.py install and not when running: pip install . -U
# that is actually the behaviour we want.
stringify_py(source_path='pygame_gui/data', destination_file='pygame_gui/core/_string_data.py')


setup(name='pygame_gui',
version='0.3.0',
Expand All @@ -15,6 +21,7 @@
'pygame_gui.elements.text', 'pygame_gui.windows'],
zip_safe=False,
python_requires='>=3.5',
setup_requires=['stringify'],
install_requires=['pygame>=1.9.3'],
include_package_data=True,
classifiers=[
Expand Down

0 comments on commit 1e8b24c

Please sign in to comment.