This repository has been archived on 2025-10-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
inter-font/misc/pylib/robofab/interface/all/dialogs_mac_vanilla.py
Rasmus Andersson 8234b62ab7 Speeds up font compilation by around 200%
Cython is used to compile some hot paths into native Python extensions.
These hot paths were identified through running ufocompile with the hotshot
profiler and then converting file by file to Cython, starting with the "hottest"
paths and continuing until returns were deminishing. This means that only a few
Python files were converted to Cython.

Closes #23
Closes #20 (really this time)
2017-09-04 11:12:34 -04:00

267 lines
No EOL
8.5 KiB
Python

"""
Dialogs for environments that support cocao / vanilla.
"""
import vanilla.dialogs
from AppKit import NSApp, NSModalPanelWindowLevel, NSWindowCloseButton, NSWindowZoomButton, NSWindowMiniaturizeButton
__all__ = [
"AskString",
"AskYesNoCancel",
"FindGlyph",
"GetFile",
"GetFileOrFolder",
"GetFolder",
"Message",
"OneList",
"PutFile",
"SearchList",
"SelectFont",
"SelectGlyph",
# "TwoChecks",
# "TwoFields",
"ProgressBar",
]
class _ModalWindow(vanilla.Window):
nsWindowLevel = NSModalPanelWindowLevel
def __init__(self, *args, **kwargs):
super(_ModalWindow, self).__init__(*args, **kwargs)
self._window.standardWindowButton_(NSWindowCloseButton).setHidden_(True)
self._window.standardWindowButton_(NSWindowZoomButton).setHidden_(True)
self._window.standardWindowButton_(NSWindowMiniaturizeButton).setHidden_(True)
def open(self):
super(_ModalWindow, self).open()
self.center()
NSApp().runModalForWindow_(self._window)
def windowWillClose_(self, notification):
super(_ModalWindow, self).windowWillClose_(notification)
NSApp().stopModal()
class _baseWindowController(object):
def setUpBaseWindowBehavior(self):
self._getValue = None
self.w.okButton = vanilla.Button((-70, -30, -15, 20), "OK", callback=self.okCallback, sizeStyle="small")
self.w.setDefaultButton(self.w.okButton)
self.w.closeButton = vanilla.Button((-150, -30, -80, 20), "Cancel", callback=self.closeCallback, sizeStyle="small")
self.w.closeButton.bind(".", ["command"])
self.w.closeButton.bind(unichr(27), [])
self.cancelled = False
def okCallback(self, sender):
self.w.close()
def closeCallback(self, sender):
self.cancelled = True
self.w.close()
def get(self):
raise NotImplementedError
class _AskStringController(_baseWindowController):
def __init__(self, message, value, title):
self.w = _ModalWindow((370, 110), title)
self.w.infoText = vanilla.TextBox((15, 10, -15, 22), message)
self.w.input = vanilla.EditText((15, 40, -15, 22))
self.w.input.set(value)
self.setUpBaseWindowBehavior()
self.w.open()
def get(self):
if self.cancelled:
return None
return self.w.input.get()
class _listController(_baseWindowController):
def __init__(self, items, message, title, showSearch=False):
self.items = items
self.w = _ModalWindow((350, 300), title)
y = 10
self.w.infoText = vanilla.TextBox((15, y, -15, 22), message)
y += 25
if showSearch:
self.w.search = vanilla.SearchBox((15, y, -15, 22), callback=self.searchCallback)
y += 25
self.w.itemList = vanilla.List((15, y, -15, -40), self.items, allowsMultipleSelection=False)
self.setUpBaseWindowBehavior()
self.w.open()
def searchCallback(self, sender):
search = sender.get()
newItems = [item for item in self.items if repr(item).startswith(search)]
self.w.itemList.set(newItems)
if newItems:
self.w.itemList.setSelection([0])
def get(self):
index = self.w.itemList.getSelection()
if index:
index = index[0]
return self.w.itemList[index]
return None
def AskString(message, value='', title='RoboFab'):
"""
AskString Dialog
message the string
value a default value
title a title of the window (may not be supported everywhere)
"""
w = _AskStringController(message, value, title)
return w.get()
def AskYesNoCancel(message, title='RoboFab', default=0, informativeText=""):
"""
AskYesNoCancel Dialog
message the string
title* a title of the window
(may not be supported everywhere)
default* index number of which button should be default
(i.e. respond to return)
informativeText* A string with secundary information
* may not be supported everywhere
"""
return vanilla.dialogs.askYesNoCancel(messageText=message, informativeText=informativeText)
def FindGlyph(aFont, message="Search for a glyph:", title='RoboFab'):
items = aFont.keys()
items.sort()
w = _listController(items, message, title, showSearch=True)
glyphName = w.get()
if glyphName is not None:
return aFont[glyphName]
return None
def GetFile(message=None, title=None, directory=None, fileName=None, allowsMultipleSelection=False, fileTypes=None):
result = vanilla.dialogs.getFile(messageText=message, title=title, directory=directory, fileName=fileName, allowsMultipleSelection=allowsMultipleSelection, fileTypes=fileTypes)
if result is None:
return None
if not allowsMultipleSelection:
return str(list(result)[0])
else:
return [str(n) for n in list(result)]
def GetFolder(message=None, title=None, directory=None, allowsMultipleSelection=False):
result = vanilla.dialogs.getFolder(messageText=message, title=title, directory=directory, allowsMultipleSelection=allowsMultipleSelection)
if result is None:
return None
if not allowsMultipleSelection:
return str(list(result)[0])
else:
return [str(n) for n in list(result)]
def GetFileOrFolder(message=None, title=None, directory=None, fileName=None, allowsMultipleSelection=False, fileTypes=None):
result = vanilla.dialogs.getFileOrFolder(messageText=message, title=title, directory=directory, fileName=fileName, allowsMultipleSelection=allowsMultipleSelection, fileTypes=fileTypes)
if result is None:
return None
if not allowsMultipleSelection:
return str(list(result)[0])
else:
return [str(n) for n in list(result)]
def Message(message, title='RoboFab', informativeText=""):
vanilla.dialogs.message(messageText=message, informativeText=informativeText)
def OneList(items, message="Select an item:", title='RoboFab'):
w = _listController(items, message, title, showSearch=False)
return w.get()
def PutFile(message=None, fileName=None):
return vanilla.dialogs.putFile(messageText=message, fileName=fileName)
def SearchList(list, message="Select an item:", title='RoboFab'):
w = _listController(list, message, title, showSearch=True)
return w.get()
def SelectFont(message="Select a font:", title='RoboFab', allFonts=None):
if allFonts is None:
from robofab.world import AllFonts
fonts = AllFonts()
else:
fonts = allFonts
data = dict()
for font in fonts:
data["%s" %font] = font
items = data.keys()
items.sort()
w = _listController(items, message, title, showSearch=False)
value = w.get()
return data.get(value, None)
def SelectGlyph(aFont, message="Select a glyph:", title='RoboFab'):
items = aFont.keys()
items.sort()
w = _listController(items, message, title, showSearch=False)
glyphName = w.get()
if glyphName is not None:
return aFont[glyphName]
return None
def TwoChecks(title_1="One", title_2="Two", value1=1, value2=1, title='RoboFab'):
raise NotImplementedError
def TwoFields(title_1="One:", value_1="0", title_2="Two:", value_2="0", title='RoboFab'):
raise NotImplementedError
class ProgressBar(object):
def __init__(self, title="RoboFab...", ticks=None, label=""):
self.w = vanilla.Window((250, 60), title)
if ticks is None:
isIndeterminate = True
ticks = 0
else:
isIndeterminate = False
self.w.progress = vanilla.ProgressBar((15, 15, -15, 12), maxValue=ticks, isIndeterminate=isIndeterminate, sizeStyle="small")
self.w.text = vanilla.TextBox((15, 32, -15, 14), label, sizeStyle="small")
self.w.progress.start()
self.w.center()
self.w.open()
def close(self):
self.w.progress.stop()
self.w.close()
def getCurrentTick(self):
return self.w.progress.get()
def label(self, label):
self.w.text.set(label)
self.w.text._nsObject.display()
def tick(self, tickValue=None):
if tickValue is None:
self.w.progress.increment()
else:
self.w.progress.set(tickValue)
if __name__ == "__main__":
pass