Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] live reload of .gggls project file after external change #283

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
26 changes: 25 additions & 1 deletion Lib/fontgoggles/mac/document.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import json
import pathlib
import objc
import AppKit

from ..project import Project
from .mainWindow import FGMainWindowController
from ..font import defaultSortSpec, sortedFontPathsAndNumbers
from .fileObserver import getFileObserver


class FGDocument(AppKit.NSDocument):
Expand Down Expand Up @@ -36,10 +39,24 @@ def dataOfType_error_(self, type, error):
return AppKit.NSData.dataWithData_(self.project.asJSON(rootPath)), error

def readFromData_ofType_error_(self, data, type, error):
rootPath = pathlib.Path(self.fileURL().path()).parent
documentPath = str(self.fileURL().path())
rootPath = pathlib.Path(documentPath).parent
self.project = Project.fromJSON(bytes(data), rootPath)
obs = getFileObserver()
obs.addObserver(documentPath, self._projectFileChangedOnDisk)
return True, None

@objc.python_method
def _projectFileChangedOnDisk(self, oldPath, newPath, wasModified):
if not wasModified:
return
rootPath = pathlib.Path(newPath).parent
with open(newPath, "rb") as f:
dataDict = json.load(f)
self.project.updateFromDict(dataDict, rootPath)
for controller in self.windowControllers():
controller.syncFromProject()

def revertToContentsOfURL_ofType_error_(self, url, type, error):
for controller in list(self.windowControllers()):
self.removeWindowController_(controller)
Expand All @@ -49,3 +66,10 @@ def revertToContentsOfURL_ofType_error_(self, url, type, error):
if success:
self.makeWindowControllers()
return True, error

def fileModificationDate(self):
# This is a workaround to avoid the "The file has been changed by another application"
# message, if we have reloaded the project after an external change.
fileManager = AppKit.NSFileManager.defaultManager()
attrs, error = fileManager.attributesOfItemAtPath_error_(self.fileURL().path(), None)
return attrs[AppKit.NSFileModificationDate]
41 changes: 41 additions & 0 deletions Lib/fontgoggles/mac/mainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,31 @@ def syncUISettingsWithProject(self):
uiSettings.feaVarTabSelection = feaVarTabValues[self.feaVarTabs.get()]
uiSettings.showHiddenAxes = self.variationsGroup.showHiddenAxes

@suppressAndLogException
def syncFromProject(self):
print("sync!")

textSettings = self.project.textSettings
uiSettings = self.project.uiSettings

self.w.mainSplitView.showPaneReally("characterList", uiSettings.characterListVisible)
self.w.mainSplitView.setPaneSize("characterList", uiSettings.characterListSize)

self.restoreWindowPosition(uiSettings.windowPosition)
self.textEntry.set(textSettings.text)

self.fontList.itemSize = uiSettings.fontListItemSize
self.fontList.relativeFontSize = textSettings.relativeFontSize
self.fontList.relativeHBaseline = textSettings.relativeHBaseline
self.fontList.relativeVBaseline = textSettings.relativeVBaseline
self.fontList.relativeMargin = textSettings.relativeMargin

self.fontList.purgeFontItems()
self.project.purgeFonts()
self._projectFontsChanged([])
self.growOrShrinkFontList()
self.textEntryChangedCallback(self.textEntry)

@objc.python_method
def restoreWindowPosition(self, windowPosition):
if not windowPosition:
Expand Down Expand Up @@ -1326,6 +1351,9 @@ class MySplitView(SplitView):
def isPaneReallyVisible(self, paneIdentifier):
return not self.isPaneVisible(paneIdentifier)

def showPaneReally(self, paneIdentifier, onOff):
self.showPane(paneIdentifier, not onOff)

def paneSize(self, paneIdentifier):
view = self._identifierToPane[paneIdentifier]["view"]
w, h = view._nsObject.frame().size
Expand All @@ -1334,6 +1362,19 @@ def paneSize(self, paneIdentifier):
else:
return h

def setPaneSize(self, paneIdentifier, size):
view = self._identifierToPane[paneIdentifier]["view"]
(x, y), (w, h) = view._nsObject.frame()
print((x, y), (w, h))
if self._nsObject.isVertical():
w = size
else:
h = size
# XXXX not working
# print((x, y), (w, h))
# view._nsObject.setFrame_(((x, y), (w, h)))
# self._nsObject.adjustSubviews()


_minimalSpaceBox = 12

Expand Down
7 changes: 6 additions & 1 deletion Lib/fontgoggles/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ def fromJSON(cls, data, rootPath):
@classmethod
def fromDict(cls, root, rootPath):
self = cls()
self.updateFromDict(root, rootPath)
return self

def updateFromDict(self, root, rootPath):
self.fonts = []
self.fontSelection = set() # not persistent
for fontItemInfoDict in root["fonts"]:
fontPath = pathlib.Path(os.path.normpath(os.path.join(rootPath, fontItemInfoDict["path"])))
self.addFont(fontPath, fontItemInfoDict.get("fontNumber", 0))
Expand All @@ -34,7 +40,6 @@ def fromDict(cls, root, rootPath):
# relative path -> absolute path
self.textSettings.textFilePath = os.path.normpath(os.path.join(rootPath, self.textSettings.textFilePath))
self.uiSettings.__dict__.update(root.get("uiSettings", {}))
return self

def asJSON(self, rootPath):
root = self.asDict(rootPath)
Expand Down