class JumpToLineWindow(BaseWindowController): lineNumber = None def __init__(self, callback): super(JumpToLineWindow, self).__init__() self.callback = callback # init the window self.w = FloatingWindow((WINDOW_WIDTH, 0), 'Jump to line') # edit text caption jumpingY = MARGIN_TOP self.w.caption = TextBox((MARGIN_LFT, jumpingY + 3, NET_WIDTH * .6, vanillaControlsSize['TextBoxRegularHeight']), 'Jump to line:') self.w.lineEdit = EditText( (MARGIN_LFT + NET_WIDTH * .6, jumpingY, -MARGIN_RGT, vanillaControlsSize['EditTextRegularHeight']), continuous=False) jumpingY += vanillaControlsSize['EditTextRegularHeight'] + MARGIN_INT self.w.cancelButton = Button( (-(BUTTON_WIDTH * 2 + MARGIN_INT + MARGIN_RGT), jumpingY, BUTTON_WIDTH, vanillaControlsSize['ButtonRegularHeight']), 'Cancel', callback=self.cancelButtonCallback) self.w.okButton = Button( (-(BUTTON_WIDTH + MARGIN_RGT), jumpingY, BUTTON_WIDTH, vanillaControlsSize['ButtonRegularHeight']), 'Ok', callback=self.okButtonCallback) jumpingY += vanillaControlsSize['ButtonRegularHeight'] + MARGIN_BTM self.setUpBaseWindowBehavior() self.w.resize(WINDOW_WIDTH, jumpingY) def get(self): try: self.lineNumber = int(self.w.lineEdit.get()) except ValueError: self.w.lineEdit.set('') self.lineNumber = None return self.lineNumber def enable(self, value): if value is True: self.w.center() self.w.show() else: self.w.hide() def cancelButtonCallback(self, sender): self.w.show(False) def okButtonCallback(self, sender): self.callback(self)
class ChooseExceptionWindow(BaseWindowController): lastEvent = None def __init__(self, options, callback): super(ChooseExceptionWindow, self).__init__() self.options = options self.callback = callback self.whichException = options[0] self.w = FloatingWindow((300, 120), 'Choose exception') self.w.optionsRadio = RadioGroup( (MARGIN, MARGIN, -MARGIN, len(options) * 20), options, callback=self.optionsCallback) self.w.optionsRadio.set(0) self.w.cancel = Button( (-(90 * 2 + MARGIN * 2), -(vanillaControlsSize['ButtonRegularHeight'] + MARGIN), 90, vanillaControlsSize['ButtonRegularHeight']), 'Cancel', callback=self.cancelCallback) self.w.submit = Button( (-(90 + MARGIN), -(vanillaControlsSize['ButtonRegularHeight'] + MARGIN), 90, vanillaControlsSize['ButtonRegularHeight']), 'Submit', callback=self.submitCallback) self.setUpBaseWindowBehavior() def set(self, exception): self.whichException = exception self.lastEvent = 'submit' def trigger(self): self.callback(self) def get(self): return self.whichException def enable(self, value): if value is True: self.w.center() self.w.show() else: self.w.hide() def close(self): self.whichException = None self.w.close() def setOptions(self, options): self.options = options optionsRepresentation = [] for lft, rgt in self.options: row = [] for eachSide in [lft, rgt]: if eachSide.startswith('@') is True: groupRepr = encloseClassTitleInBrackets(eachSide) row.append(groupRepr) else: row.append(eachSide) optionsRepresentation.append(', '.join(row)) if hasattr(self.w, 'optionsRadio') is True: delattr(self.w, 'optionsRadio') self.w.optionsRadio = RadioGroup( (MARGIN, MARGIN, -MARGIN, len(options) * 20), optionsRepresentation, callback=self.optionsCallback) def optionsCallback(self, sender): self.whichException = self.options[sender.get()] def cancelCallback(self, sender): self.lastEvent = 'cancel' self.whichException = None self.callback(self) self.w.hide() def submitCallback(self, sender): self.lastEvent = 'submit' self.callback(self) self.w.hide()
class VariableController(object): def __init__(self, attributes, callback, document=None): self._callback = callback self._attributes = None self.w = FloatingWindow((250, 50)) self.buildUI(attributes) self.w.open() if document: self.w.assignToDocument(document) self.w.setTitle("Variables") def buildUI(self, attributes): if self._attributes == attributes: return self._attributes = attributes if hasattr(self.w, "ui"): del self.w.ui self.w.ui = ui = vanilla.Group((0, 0, -0, -0)) y = 10 labelSize = 100 gutter = 5 for attribute in self._attributes: uiElement = attribute["ui"] name = attribute["name"] args = dict(attribute.get("args", {})) height = 19 # adjust the height if a radioGroup is vertical if uiElement == "RadioGroup": if args.get("isVertical", True): height = height * len(args.get("titles", [""])) # create a label for every ui element except a checkbox if uiElement not in ("CheckBox", "Button"): # create the label view label = vanilla.TextBox((0, y + 2, labelSize - gutter, height), "%s:" % name, alignment="right", sizeStyle="small") # set the label view setattr(ui, "%sLabel" % name, label) else: args["title"] = name # check the provided args and add required keys if uiElement == "ColorWell": # a color well needs a color to be set # no size style if "color" not in args: args["color"] = AppKit.NSColor.blackColor() elif uiElement == "TextEditor": # different control height # no size style height = attribute.get("height", 75) else: # all other get a size style args["sizeStyle"] = "small" # create the control view attr = getattr(vanilla, uiElement)((labelSize, y, -10, height), callback=self.changed, **args) # set the control view setattr(ui, name, attr) y += height + 6 # resize the window according the provided ui elements self.w.resize(250, y) def changed(self, sender): self.documentWindowToFront() if self._callback: self._callback() def get(self): data = {} for attribute in self._attributes: if attribute["ui"] in ("Button", ): continue name = attribute["name"] data[name] = getattr(self.w.ui, name).get() return data def show(self): self.w.show() def documentWindowToFront(self, sender=None): self.w.makeKey()
class UnicodePicker(AppKit.NSWindowController): def __new__(cls): return cls.alloc().init() def __init__(self): self.searchResults = [] self.selectedChars = "" self.w = FloatingWindow((300, 400), "Unicode Picker", minSize=(250, 300), autosaveName="UnicodePicker") y = 15 self.w.searchField = EditText((20, y, -20, 25), placeholder="Search Unicode name or value", callback=self.searchTextChanged_) y += 40 columnDescriptions = [ dict(title="char", width=40, cell=makeTextCell(align="center", font=AppKit.NSFont.systemFontOfSize_(14))), dict(title="unicode", width=60, cell=makeTextCell(align="right")), dict(title="name"), ] self.w.unicodeList = List((0, y, 0, -100), [], columnDescriptions=columnDescriptions, rowHeight=18, selectionCallback=self.listSelectionChanged_, doubleClickCallback=self.listDoubleClickCallback_) y = -95 self.w.unicodeText = TextBox((20, y, -10, 55), "") self.w.unicodeText._nsObject.cell().setFont_(AppKit.NSFont.systemFontOfSize_(36)) self.w.unicodeText._nsObject.cell().setLineBreakMode_(AppKit.NSLineBreakByTruncatingMiddle) y += 55 self.w.copyButton = Button((20, y, 120, 25), "Copy", callback=self.copy_) self.w.copyButton.enable(False) self.w.open() self.w._window.setWindowController_(self) self.w._window.setBecomesKeyOnlyIfNeeded_(False) self.w._window.makeKeyWindow() def show(self): if self.w._window is None: # we have been closed, let's reconstruct self.__init__() else: self.w.show() def searchTextChanged_(self, sender): results = [] terms = sender.get().upper().split() if len(terms) == 1: m = _unicodePat.match(terms[0]) if m is not None: uni = int(m.group(4), 16) if uni < 0x110000: results = [uni] if terms: uniSets = [set(findPrefix(t)) for t in terms] foundSet = uniSets[0] for s in uniSets[1:]: foundSet &= s results += sorted(foundSet) self.searchResults = results self.w.unicodeList.set([]) self.appendResults_(500) def appendResults_(self, maxResults): start = len(self.w.unicodeList) unicodeItems = [dict(char=chr(uni), unicode=f"U+{uni:04X}", name=unicodedata.name(chr(uni), "")) for uni in self.searchResults[start:start+maxResults]] if len(self.searchResults) > start + maxResults: unicodeItems.append(dict(name="...more...")) self.w.unicodeList.extend(unicodeItems) def listSelectionChanged_(self, sender): sel = sender.getSelection() if sel and sender[max(sel)]["name"] == "...more...": del sender[len(sender) - 1] self.appendResults_(500) sender.setSelection(sel) chars = "".join(chr(self.searchResults[i]) for i in sel) self.w.copyButton.enable(bool(chars)) self.selectedChars = chars self.w.unicodeText.set(chars) def listDoubleClickCallback_(self, sender): app = AppKit.NSApp() w = app.mainWindow() fr = w.firstResponder() if fr is None or not isinstance(fr, AppKit.NSTextView): return fr.insertText_replacementRange_(self.selectedChars, fr.selectedRange()) def copy_(self, sender): p = AppKit.NSPasteboard.generalPasteboard() p.clearContents() p.declareTypes_owner_([AppKit.NSPasteboardTypeString], None) p.setString_forType_(self.selectedChars, AppKit.NSPasteboardTypeString)