class FileUploadField(Group): def __init__(self, dimensions, storage=NullStorage()): self.storage = storage super(FileUploadField, self).__init__(dimensions) self.choose_file_button = Button((0, 3, 100, 17), "Choose File", sizeStyle="small", callback=self.choose_file) self.remove_file_button = Button((-60, 3, 60, 17), "Remove", sizeStyle="small", callback=self.remove_file) self.filepath_label = TextBox((18, 3, -70, 20), "") self.filepath_button = ImageButton((0, 3, -70, 20), "", callback=self.reveal_file) self.filepath_button.getNSButton().setTransparent_(True) self.filetype_image = ImageView((0, 4, 16, 16)) self.filepath = self.storage.retrieve() def choose_file(self, sender): filepath = getFile("Choose a .txt or .pdf document to use as a license", "Select License", fileTypes=("txt", "md", "pdf")) if filepath is not None: self.storage.store(filepath[0]) self.filepath = filepath[0] def remove_file(self, sender): self.storage.store(None) self.filepath = None def reveal_file(self, sender): workspace = NSWorkspace.sharedWorkspace() workspace.selectFile_inFileViewerRootedAtPath_(self.filepath, os.path.dirname(self.filepath)) @property def filename(self): if self.filepath is not None: return os.path.basename(self.filepath) else: return "" @property def filepath(self): return self._filepath @filepath.setter def filepath(self, value): self._filepath = value selected = value is not None and value is not '' icon = NSWorkspace.sharedWorkspace().iconForFile_(self._filepath) self.choose_file_button.show(not selected) self.remove_file_button.show(selected) self.filepath_label.show(selected) self.filepath_label.set(self.filename) self.filepath_button.show(selected) self.filetype_image.show(selected) self.filetype_image.setImage(imageObject=icon)
class FileUploadField(Group): def __init__(self, dimensions, storage=NullStorage()): self.storage = storage super(FileUploadField, self).__init__(dimensions) self.choose_file_button = Button((0, 3, 100, 17), "Choose File", sizeStyle="small", callback=self.choose_file) self.remove_file_button = Button((-60, 3, 60, 17), "Remove", sizeStyle="small", callback=self.remove_file) self.filepath_label = TextBox((18, 3, -70, 20), "") self.filepath_button = ImageButton((0, 3, -70, 20), "", callback=self.reveal_file) self.filepath_button.getNSButton().setTransparent_(True) self.filetype_image = ImageView((0, 4, 16, 16)) self.filepath = self.storage.retrieve() def choose_file(self, sender): filepath = getFile("Choose a .txt or .pdf document to use as a license", "Select License", fileTypes=("txt", "md", "pdf")) if filepath is not None: self.storage.store(filepath[0]) self.filepath = filepath[0] def remove_file(self, sender): self.storage.store(None) self.filepath = None def reveal_file(self, sender): workspace = NSWorkspace.sharedWorkspace() workspace.selectFile_inFileViewerRootedAtPath_(self.filepath, os.path.dirname(self.filepath)) @property def filename(self): if self.filepath is not None: return os.path.basename(self.filepath) else: return "" @property def filepath(self): return self._filepath @filepath.setter def filepath(self, value): self._filepath = value selected = value is not None and value is not '' icon = NSWorkspace.sharedWorkspace().iconForFile_(self._filepath) self.choose_file_button.show(not selected) self.remove_file_button.show(selected) self.filepath_label.show(selected) self.filepath_label.set(WhiteText(self.filename)) self.filepath_button.show(selected) self.filetype_image.show(selected) self.filetype_image.setImage(imageObject=icon)
class WordListController(Group): """this controller takes good care of word list flow""" def __init__(self, posSize, callback): super(WordListController, self).__init__(posSize) x, y, self.ctrlWidth, self.ctrlHeight = posSize self.callback = callback # handling kerning words self.kerningWordsDB = loadKerningTexts(STANDARD_KERNING_TEXT_FOLDER) self.kerningTextBaseNames = self.kerningWordsDB.keys() self.activeKerningTextBaseName = self.kerningTextBaseNames[0] # this is the list used for data manipulation self.wordsWorkingList = self.kerningWordsDB[self.activeKerningTextBaseName] # this list instead is used for data visualization in the ctrl self._makeWordsDisplayList(self.activeKerningTextBaseName) self.activeWord = self.wordsWorkingList[0]['word'] self.wordFilter = '' jumping_Y = 0 self.kerningVocabularyPopUp = PopUpButton((0, jumping_Y, self.ctrlWidth*.6, vanillaControlsSize['PopUpButtonRegularHeight']), self.kerningTextBaseNames, callback=self.kerningVocabularyPopUpCallback) self.openTextsFolderButton = SquareButton((self.ctrlWidth*.62, jumping_Y, self.ctrlWidth*.38, vanillaControlsSize['PopUpButtonRegularHeight']+1), 'Load texts...', sizeStyle='small', callback=self.openTextsFolderButtonCallback) wordsColumnDescriptors = [ {'title': '#', 'width': 30, 'editable': False}, {'title': 'word', 'width': self.ctrlWidth-80, 'editable': False}, {'title': 'done?', 'width': 35, 'cell': CheckBoxListCell(), 'editable': False}] jumping_Y += self.openTextsFolderButton.getPosSize()[3] + MARGIN_VER self.wordsListCtrl = List((0, jumping_Y, self.ctrlWidth, 170), self.wordsDisplayList, enableDelete=False, allowsMultipleSelection=False, columnDescriptions=wordsColumnDescriptors, selectionCallback=self.wordsListCtrlSelectionCallback, doubleClickCallback=self.wordsListCtrlDoubleClickCallback) jumping_Y += self.wordsListCtrl.getPosSize()[3] + MARGIN_VER self.wordsFilterCtrl = EditText((-70, jumping_Y-1, 70, vanillaControlsSize['EditTextRegularHeight']), placeholder='filter...', callback=self.wordsFilterCtrlCallback) self.wordsDone = len([row['done?'] for row in self.wordsWorkingList if row['done?'] != 0]) self.infoCaption = TextBox((0, jumping_Y+2, self.ctrlWidth-self.wordsFilterCtrl.getPosSize()[2], vanillaControlsSize['TextBoxRegularHeight']), 'done: {:d}/{:d}'.format(self.wordsDone, len(self.wordsWorkingList))) jumping_Y += self.wordsFilterCtrl.getPosSize()[3] + MARGIN_VER self.loadStatus = SquareButton((0, jumping_Y, 90, vanillaControlsSize['ButtonRegularHeight']+2), 'Load status', callback=self.loadStatusCallback) self.saveButton = SquareButton((-90, jumping_Y, 90, vanillaControlsSize['ButtonRegularHeight']+2), 'Save status', callback=self.saveButtonCallback) def _filterDisplayList(self): self.wordsDisplayList = [row for row in self.wordsWorkingList if self.wordFilter in row['word']] def _makeWordsDisplayList(self, textBaseName): self.wordsDisplayList = [] for eachRow in self.kerningWordsDB[self.activeKerningTextBaseName]: fixedWord = eachRow['word'].replace('//', '/') self.wordsDisplayList.append({'#': eachRow['#'], 'word': fixedWord, 'done?': eachRow['done?']}) def _updateInfoCaption(self): self.infoCaption.set('done: {:d}/{:d}'.format(self.wordsDone, len(self.wordsWorkingList))) def get(self): return self.activeWord def getActiveIndex(self): activeWordData = [wordData for wordData in self.wordsDisplayList if wordData['word'] == self.activeWord][0] activeWordIndex = self.wordsDisplayList.index(activeWordData) return activeWordIndex def nextWord(self): activeWordData = [wordData for wordData in self.wordsDisplayList if wordData['word'] == self.activeWord][0] activeWordIndex = self.wordsDisplayList.index(activeWordData) nextWordIndex = (activeWordIndex+1)%len(self.wordsDisplayList) self.activeWord = self.wordsDisplayList[nextWordIndex]['word'] self.wordsListCtrl.setSelection([nextWordIndex]) def previousWord(self): activeWordData = [wordData for wordData in self.wordsDisplayList if wordData['word'] == self.activeWord][0] activeWordIndex = self.wordsDisplayList.index(activeWordData) previousWordIndex = (activeWordIndex-1)%len(self.wordsDisplayList) self.activeWord = self.wordsDisplayList[previousWordIndex]['word'] self.wordsListCtrl.setSelection([previousWordIndex]) def jumpToLine(self, lineIndex): try: self.activeWord = self.wordsDisplayList[lineIndex]['word'] self.wordsListCtrl.setSelection([lineIndex]) except IndexError: pass def switchActiveWordSolvedAttribute(self): activeWordData = [wordData for wordData in self.wordsDisplayList if wordData['word'] == self.activeWord][0] activeWordIndex = self.wordsDisplayList.index(activeWordData) if activeWordData['done?'] == 0: self.wordsDisplayList[activeWordIndex]['done?'] = 1 else: self.wordsDisplayList[activeWordIndex]['done?'] = 0 self.wordsListCtrl.set(self.wordsDisplayList) self.wordsListCtrl.setSelection([activeWordIndex]) # ctrls callbacks def kerningVocabularyPopUpCallback(self, sender): self.activeKerningTextBaseName = self.kerningTextBaseNames[sender.get()] self.wordsWorkingList = self.kerningWordsDB[self.activeKerningTextBaseName] self.activeWord = self.wordsWorkingList[0]['word'] self._makeWordsDisplayList(self.activeKerningTextBaseName) self._filterDisplayList() self.wordsListCtrl.set(self.wordsDisplayList) self.callback(self) def openTextsFolderButtonCallback(self, sender): textFolder = u'{}'.format(getFolder('Choose a folder for texts files')[0]) # handling kerning words self.kerningWordsDB = loadKerningTexts(textFolder) self.kerningTextBaseNames = self.kerningWordsDB.keys() self.activeKerningTextBaseName = self.kerningTextBaseNames[0] # this is the list used for data manipulation self.wordsWorkingList = self.kerningWordsDB[self.activeKerningTextBaseName] # this list instead is used for data visualization in the ctrl self._makeWordsDisplayList(self.activeKerningTextBaseName) self.activeWord = self.wordsWorkingList[0]['word'] self.wordFilter = '' self._filterDisplayList() self._updateInfoCaption() # ctrls to be updated self.kerningVocabularyPopUp.setItems(self.kerningTextBaseNames) self.wordsListCtrl.set(self.wordsDisplayList) self.wordsFilterCtrl.set(self.wordFilter) self.callback(self) def wordsListCtrlSelectionCallback(self, sender): """this takes care of word count""" self.wordsDisplayList = [{'#': row['#'], 'word': row['word'], 'done?': row['done?']} for row in sender.get()] for eachDisplayedRow in self.wordsDisplayList: for indexWorkingRow, eachWorkingRow in enumerate(self.wordsWorkingList): if eachWorkingRow['word'] == eachDisplayedRow['word']: self.wordsWorkingList[indexWorkingRow] = eachDisplayedRow self.wordsDone = len([row['done?'] for row in self.wordsWorkingList if row['done?'] != 0]) self._updateInfoCaption() def wordsListCtrlDoubleClickCallback(self, sender): self.activeWord = self.wordsDisplayList[sender.getSelection()[0]]['word'] self.callback(self) def wordsFilterCtrlCallback(self, sender): self.wordFilter = sender.get() self._filterDisplayList() self.wordsListCtrl.set(self.wordsDisplayList) if len(self.wordsDisplayList) == 0: self.activeWord = None else: if self.activeWord not in [row['word'] for row in self.wordsDisplayList]: self.activeWord = self.wordsDisplayList[0]['word'] self.callback(self) def loadStatusCallback(self, sender): kerningStatusPath = getFile(title='Load Kerning Status JSON file', allowsMultipleSelection=False)[0] if os.path.splitext(os.path.basename(kerningStatusPath))[1] == '.json': jsonFile = open(kerningStatusPath, 'r') statusDictionary = json.load(jsonFile) jsonFile.close() # unwrap dictionaries self.kerningWordsDB = statusDictionary['kerningWordsDB'] self.kerningTextBaseNames = statusDictionary['kerningTextBaseNames'] self.activeKerningTextBaseName = statusDictionary['activeKerningTextBaseName'] self.wordsWorkingList = statusDictionary['wordsWorkingList'] self.wordsDisplayList = statusDictionary['wordsDisplayList'] self.activeWord = statusDictionary['activeWord'] self.wordFilter = statusDictionary['wordFilter'] # adjust controllers self.kerningVocabularyPopUp.setItems(self.kerningTextBaseNames) self.kerningVocabularyPopUp.set(self.kerningTextBaseNames.index(self.activeKerningTextBaseName)) self.wordsListCtrl.set(self.wordsDisplayList) for indexRow, eachRow in enumerate(self.wordsDisplayList): if eachRow['word'] == self.activeWord: self.wordsListCtrl.setSelection([indexRow]) break self._updateInfoCaption() self.callback(self) else: message('No JSON, no party!', 'Chosen file is not in the right format') def saveButtonCallback(self, sender): statusDict = { 'kerningWordsDB': self.kerningWordsDB, 'kerningTextBaseNames': self.kerningTextBaseNames, 'activeKerningTextBaseName': self.activeKerningTextBaseName, 'wordsWorkingList': self.wordsWorkingList, 'wordsDisplayList': self.wordsDisplayList, 'activeWord': self.activeWord, 'wordFilter': self.wordFilter} kerningStatusPath = putFile(title='Save Kerning Status JSON file', fileName='kerningStatus.json', canCreateDirectories=True) jsonFile = open(kerningStatusPath, 'w') json.dump(statusDict, jsonFile, indent=4) jsonFile.write('\n') jsonFile.close()
class ParameterTextInput(Group): def __init__(self, parameter, posSize, text='', callback=None, continuous=False, showRelativeValue=False): super(ParameterTextInput, self).__init__(posSize) self.parameter = parameter rel = self._relValue() self.callback = callback self.textInput = EditText((0, 0, -40, -0), text=text, callback=self._valueInput, continuous=continuous) self.relInfo = TextBox((-35, 5, -0, -0), rel, alignment='left', sizeStyle='small') self.showRelativeValue(showRelativeValue) self.vanillaInputs = [self.textInput] self.parameter.bind(self) def set(self, value): self.parameter.set(value) self.update(None) def get(self): return self.parameter.get() def enable(self, value): for item in self.vanillaInputs: item.enable(value) def _valueInput(self, sender): value = sender.get() parameter = self.parameter if value == 'R' and parameter.hasMaster: parameter.reset() parameter.update() if self.callback is not None: self.callback(self) return elif value != '*': parameter.setInput(value, sender=sender) parameter.update() if self.callback is not None: self.callback(self) rel = self._relValue() self.relInfo.set(rel) def showRelativeValue(self, b): self.relInfo.show(b) def setFree(self, sender): value = bool(sender.get()) self.parameter.setFree(value) def update(self, sender): value = self.parameter.get() self.textInput.set(str(value)) self._updateRelValue() def _updateRelValue(self): rel = self._relValue() self.relInfo.set(rel) def _relValue(self): parameter = self.parameter rel = '-' if parameter.hasMaster: if parameter.mode == 'ratio': rel = '%s' % (parameter.getRatio()) elif parameter.mode == 'offset': offsetValue = int(parameter.getOffset()) sign = '+' if offsetValue >= 0 else '' rel = '%s%s' % (sign, offsetValue) return rel
class ParameterTextInput(Group): def __init__(self, parameter, posSize, text='', callback=None, continuous=False, showRelativeValue=False): super(ParameterTextInput, self).__init__(posSize) self.parameter = parameter rel = self._relValue() self.callback = callback self.textInput = EditText((0, 0, -40, -0), text=text, callback=self._valueInput, continuous=continuous) self.relInfo = TextBox((-35, 5, -0, -0), rel, alignment='left', sizeStyle='small') self.showRelativeValue(showRelativeValue) self.vanillaInputs = [self.textInput] self.parameter.bind(self) def get(self): return self.parameter.get() def enable(self, value): for item in self.vanillaInputs: item.enable(value) def _valueInput(self, sender): value = sender.get() parameter = self.parameter if value == 'R' and parameter.hasMaster: parameter.reset() parameter.update() if self.callback is not None: self.callback(parameter) return elif value != '*': parameter.setInput(value, sender=sender) parameter.update() if self.callback is not None: self.callback(parameter) rel = self._relValue() self.relInfo.set(rel) def showRelativeValue(self, b): self.relInfo.show(b) def setFree(self, sender): value = bool(sender.get()) self.parameter.setFree(value) def update(self, sender): value = self.parameter.get() self.textInput.set(str(value)) self._updateRelValue() def _updateRelValue(self): rel = self._relValue() self.relInfo.set(rel) def _relValue(self): parameter = self.parameter rel = '-' if parameter.hasMaster: if parameter.mode == 'ratio': rel = '%s' % (parameter.getRatio()) elif parameter.mode == 'offset': offsetValue = int(parameter.getOffset()) sign = '+' if offsetValue >= 0 else '' rel = '%s%s' % (sign, offsetValue) return rel
class FontRow(Group): lastDirection = None isDisplayed = True def __init__(self, posSize, index, aFont, isTop, isBottom, directionCallback, displayedCallback): super(FontRow, self).__init__(posSize) self.directionCallback = directionCallback self.displayedCallback = displayedCallback self.index = index self.ctrlFont = aFont squareButtonSide = FONT_ROW_HEIGHT - 6 self.check = CheckBox( (0, 0, 16, vanillaControlsSize['CheckBoxRegularHeight']), '', value=self.isDisplayed, callback=self.checkCallback) self.caption = TextBox( (18, 2, 120, vanillaControlsSize['TextBoxRegularHeight']), '{}'.format(self.ctrlFont.info.styleName)) self.buttonUp = SquareButton((-(squareButtonSide * 2 + MARGIN_COL), 0, squareButtonSide, squareButtonSide), u'↑', callback=self.buttonUpCallback) if isTop is True: self.buttonUp.show(False) self.buttonDw = SquareButton( (-squareButtonSide, 0, squareButtonSide, squareButtonSide), u'↓', callback=self.buttonDwCallback) if isBottom is True: self.buttonDw.show(False) def setFont(self, aFont): self.ctrlFont = aFont self.caption.set('{}'.format(self.ctrlFont.info.styleName)) def getDirection(self): return self.lastDirection def setIsDisplayed(self, isDisplayed): self.isDisplayed = isDisplayed self.check.set(self.isDisplayed) def getIsDisplayed(self): return self.isDisplayed def getFont(self): return self.ctrlFont def checkCallback(self, sender): self.isDisplayed = bool(sender.get()) self.displayedCallback(self) def buttonUpCallback(self, sender): self.lastDirection = 'up' self.directionCallback(self) def buttonDwCallback(self, sender): self.lastDirection = 'down' self.directionCallback(self)