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 AnchorsCtrls(Group): anchorName = '' anchorHeight = None def __init__(self, posSize, callbackAttrs, placeCallback, deleteCallback): super(AnchorsCtrls, self).__init__(posSize) self.callbackAttrs = callbackAttrs self.placeCallback = placeCallback self.deleteCallback = deleteCallback x, y, width, height = posSize jumpinY = 0 self.heightCaption = TextBox( (32, jumpinY, width / 2., vanillaControlsSize['TextBoxRegularHeight']), 'Height:') self.heightEdit = EditText( (width / 2., jumpinY, width / 2., vanillaControlsSize['EditTextRegularHeight']), continuous=False, callback=self.heightEditCallback) jumpinY += self.heightEdit.getPosSize()[3] + MARGIN_ROW self.nameCaption = TextBox( (32, jumpinY, width / 2., vanillaControlsSize['TextBoxRegularHeight']), 'Anchor:') self.nameCombo = ComboBox( (width / 2., jumpinY, width / 2., vanillaControlsSize['ComboBoxRegularHeight']), ['top', '_top', 'bottom', '_bottom'], callback=self.nameComboCallback) jumpinY += self.nameCombo.getPosSize()[3] + MARGIN_ROW * 2 self.placeButton = Button((0, jumpinY, width * .45, vanillaControlsSize['ButtonRegularHeight']), 'Place', callback=self.placeButtonCallback) self.deleteButton = Button( (width * .55, jumpinY, width * .45, vanillaControlsSize['ButtonRegularHeight']), 'Delete', callback=self.deleteButtonCallback) # public attrs def getHeight(self): return self.anchorHeight def getName(self): return self.anchorName # callbacks def heightEditCallback(self, sender): try: self.anchorHeight = int(sender.get()) self.callbackAttrs(self) except ValueError: self.heightEdit.set('') def nameComboCallback(self, sender): self.anchorName = sender.get() self.callbackAttrs(self) def placeButtonCallback(self, sender): self.placeCallback(self) def deleteButtonCallback(self, sender): self.deleteCallback(self)
class SingleGridController(Group): """this controller takes care of canvas grid drawing""" def __init__(self, posSize, index, isVertical, isHorizontal, step, gridColor, callback): Group.__init__(self, posSize) # from arguments to attributes self.ctrlX, self.ctrlY, self.ctrlWidth, self.ctrlHeight = posSize self.index = index self.isVertical = isVertical self.isHorizontal = isHorizontal self.step = step self.gridColor = gridColor self.callback = callback # ctrls jumpin_X = 12 self.indexText = TextBox( (jumpin_X, 0, 16, vanillaControlsSize['TextBoxRegularHeight']), '{:d})'.format(index)) jumpin_X += self.indexText.getPosSize()[2] self.stepCtrl = EditText( (jumpin_X, 0, 38, vanillaControlsSize['EditTextRegularHeight']), callback=self.stepCtrlCallback) jumpin_X += self.stepCtrl.getPosSize()[2] + 16 self.isHorizontalCheck = CheckBox( (jumpin_X, 0, 32, vanillaControlsSize['CheckBoxRegularHeight']), "H", value=self.isHorizontal, callback=self.isHorizontalCheckCallback) jumpin_X += self.isHorizontalCheck.getPosSize()[2] + 2 self.isVerticalCheck = CheckBox( (jumpin_X, 0, 32, vanillaControlsSize['CheckBoxRegularHeight']), "V", value=self.isVertical, callback=self.isVerticalCheckCallback) jumpin_X += self.isVerticalCheck.getPosSize()[2] + 10 self.whichColorWell = ColorWell( (jumpin_X, 0, 46, self.ctrlHeight), color=NSColor.colorWithCalibratedRed_green_blue_alpha_(*gridColor), callback=self.whichColorWellCallback) def enable(self, onOff): self.indexText.enable(onOff) self.stepCtrl.enable(onOff) self.isHorizontalCheck.enable(onOff) self.isVerticalCheck.enable(onOff) self.whichColorWell.enable(onOff) def get(self): return self.index - 1, { 'horizontal': self.isHorizontal, 'vertical': self.isVertical, 'step': self.step, 'color': self.gridColor } def stepCtrlCallback(self, sender): try: self.step = int(sender.get()) self.callback(self) except ValueError as error: self.step = None self.stepCtrl.set('') def isHorizontalCheckCallback(self, sender): self.isHorizontal = bool(sender.get()) self.callback(self) def isVerticalCheckCallback(self, sender): self.isVertical = bool(sender.get()) self.callback(self) def whichColorWellCallback(self, sender): calibratedColor = sender.get() self.gridColor = (calibratedColor.redComponent(), calibratedColor.greenComponent(), calibratedColor.blueComponent(), calibratedColor.alphaComponent()) self.callback(self)