-
-
Save ryanbugden/a7b946f786dce9cfd92853cdc827aeb1 to your computer and use it in GitHub Desktop.
Hit Command+L and type a glyph to throw it into the background layer very quickly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# menuTitle : Throw Glyph in Background | |
# shortCut : command + l | |
from vanilla import Window, TextBox, ComboBox, Button, HorizontalLine | |
from mojo.UI import AskString, StatusInteractivePopUpWindow, CurrentGlyphWindow | |
from mojo.events import addObserver, removeObserver | |
from defconAppKit.windows.baseWindow import BaseWindowController | |
from AppKit import NSColor, NSObject | |
if __name__ == "__main__": | |
from lib.tools.debugTools import ClassNameIncrementer | |
else: | |
def ClassNameIncrementer(clsName, bases, dct): | |
return type(clsName, bases, dct) | |
f = CurrentFont() | |
g = CurrentGlyph() | |
throw_to_lname = 'background' | |
# def getGlyphEditorRectAndScreen(editorWindow): | |
# screen = editorWindow.w.getNSWindow().screen() | |
# nsWindow = editorWindow.w.getNSWindow() | |
# scrollView = editorWindow.getGlyphView().enclosingScrollView() | |
# rectInWindowCoords = scrollView.convertRect_toView_(scrollView.frame(), None) | |
# rectInScreenCoords = nsWindow.convertRectToScreen_(rectInWindowCoords) | |
# (screenX, screenY), (screenWidth, screenHeight) = screen.frame() | |
# (x, y), (w, h) = rectInScreenCoords | |
# y = -(y + h) | |
# return (x, y, w, h), screen | |
def sortedByLength(lst): | |
lst2 = sorted(lst, key=len) | |
return lst2 | |
class GlyphThrower(BaseWindowController): | |
def __init__(self): | |
f = CurrentFont() | |
margin = 8 | |
text_height = 20 | |
text_width = 120 | |
gutter = 2 | |
button_width = text_width | |
button_height = text_height | |
window_height = margin * 2 + text_height * 2 + gutter * 3 | |
window_width = margin * 2 + text_width | |
# editorWindow = CurrentGlyphWindow() | |
# (editorX, editorY, editorW, editorH), screen = getGlyphEditorRectAndScreen(editorWindow) | |
# x = editorX + ((editorW - window_width) / 2) | |
# y = editorY + ((editorH - window_height) / 2) | |
self.w = StatusInteractivePopUpWindow((window_width, window_height)) | |
self.w.center() | |
self.w.text_box = TextBox( | |
(margin, margin, text_width, text_height), | |
text='Throw Glyph', | |
alignment='center', | |
selectable=False, | |
sizeStyle='small' | |
) | |
self.w.line = HorizontalLine((margin, margin + text_height + gutter/2, text_width, 1)) | |
self.chosen_glyph = str(g.name) | |
self.w.glyph_input = ComboBox( | |
(margin, margin + text_height + gutter*3, text_width, text_height), | |
sortedByLength(f.glyphOrder), # redundant now? | |
completes=True, | |
# continuous=True, | |
callback=self.throwCallback, | |
) | |
g_i_NS = self.w.glyph_input.getNSComboBox() | |
g_i_NS.setAlignment_(0) | |
g_i_NS.setFocusRingType_(1) | |
# g_i_NS.setAutomaticTextCompletionEnabled_(True) | |
g_i_NS.becomeFirstResponder() | |
g_i_NS.setNumberOfVisibleItems_(10) | |
g_i_NS.setButtonBordered_(False) | |
# g_i_NS.setHasVerticalScroller_(False) | |
self._sourceGlyphNameComboBoxDataSource = comboBoxDataSource.alloc().init() | |
g_i_NS.setUsesDataSource_(True) | |
g_i_NS.setDataSource_(self._sourceGlyphNameComboBoxDataSource) | |
self._sourceGlyphNameComboBoxDataSource.setGlyphNames_(sortedByLength(f.glyphOrder)) | |
self.w.glyph_input.set(self.chosen_glyph) | |
# invisible "close button" | |
self.w.close_button = Button((window_width + 20, window_height + 20, 1, 1), "", callback=self.closeCallback) | |
self.w.close_button.bind(chr(27), []) # make "escape" work | |
self.w.open() | |
def throwCallback(self, sender): | |
self.chosen_glyph = str(sender.get()) | |
if not self.chosen_glyph in f: | |
for glyph_name in f.glyphOrder: | |
if self.chosen_glyph in glyph_name: | |
if glyph_name.split(self.chosen_glyph)[0] == '': | |
self.chosen_glyph = glyph_name | |
if g != None: | |
try: | |
cl = CurrentLayer() | |
fro = f.defaultLayer[self.chosen_glyph] | |
if self.chosen_glyph in cl.keys(): | |
if cl[self.chosen_glyph].contours or cl[self.chosen_glyph].components: | |
fro = cl[self.chosen_glyph] | |
else: | |
fro = f.defaultLayer[self.chosen_glyph] | |
back = g.getLayer(throw_to_lname) | |
with back.undo(f'Throw glyph {g.name} in {throw_to_lname}'): | |
back.clear() | |
get_g = fro.copy() | |
fro.decompose() | |
back.appendGlyph(fro) | |
back.width = fro.width | |
fro.clear() | |
fro.appendGlyph(get_g) | |
back.changed() | |
# f.removeLayer('temp') | |
f.changed() | |
self.w.close() | |
except ValueError: | |
self.w.close() | |
else: | |
self.w.close() | |
f.getLayer(throw_to_lname).setDisplayOption({'Fill': True}) | |
def closeCallback(self, sender): | |
self.w.close() | |
# code from Tal to improve auto-complete behavior | |
class comboBoxDataSource(NSObject, metaclass=ClassNameIncrementer): | |
def init(self): | |
self = super(comboBoxDataSource, self).init() | |
self._glyphNames = [] | |
return self | |
def setGlyphNames_(self, names): | |
self._glyphNames = names | |
def comboBox_completedString_(self, comboBox, text): | |
if text in self._glyphNames: | |
return text | |
for name in self._glyphNames: | |
if name.startswith(text): | |
return name | |
return text | |
def comboBox_indexOfItemWithStringValue_(self, comboBox, text): | |
if text not in self._glyphNames: | |
return -1 | |
return self._glyphNames.index(text) | |
def comboBox_objectValueForItemAtIndex_(self, comboBox, index): | |
return self._glyphNames[index] | |
def numberOfItemsInComboBox_(self, comboBox): | |
return len(self._glyphNames) | |
if __name__ == "__main__": | |
GlyphThrower() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment