class SliderGroup(Group): def __init__(self, posSize, minValue, maxValue, value, callback): Group.__init__(self, posSize) self.slider = Slider( (2, 3, -55, 17), minValue=minValue, maxValue=maxValue, value=value, sizeStyle="regular", callback=self.sliderChanged) self.edit = EditText( (-40, 0, -0, 22), text=str(value), placeholder=str(value), callback=self.editChanged) self.callback = callback def sliderChanged(self, sender): self.edit.set(str(int(self.slider.get()))) self.callback(sender) def editChanged(self, sender): try: value = int(float(self.edit.get())) except ValueError: value = int(self.edit.getPlaceholder()) self.edit.set(value) self.slider.set(value) self.callback(sender)
class Label(Group): def __init__(self, posSize, attachCallback, labelName=None): super(Label, self).__init__(posSize) self.labelName = labelName self.attachCallback = attachCallback self.edit = EditText((0, 0, NET_WIDTH * .7, vanillaControlsSize['EditTextRegularHeight']), text=self.labelName, continuous=True, callback=self.editCallback) self.button = SquareButton( (NET_WIDTH * .72, 0, NET_WIDTH * .28, vanillaControlsSize['EditTextRegularHeight']), 'attach!', callback=self.buttonCallback) def get(self): return self.labelName def setLabelName(self, labelName): self.labelName = labelName self.edit.set(self.labelName) def editCallback(self, sender): self.labelName = sender.get() def buttonCallback(self, sender): self.attachCallback(self)
class SliderGroup(Group): def __init__(self, posSize, text, minValue, maxValue, value, callback): Group.__init__(self, posSize) self.text = TextBox((0, 0, -0, 20), text) self.slider = Slider((2, 20, -60, 17), minValue=minValue, maxValue=maxValue, value=value, sizeStyle="small", callback=self.sliderChanged) self.edit = EditText((-40, 15, -0, 22), text=str(value), placeholder=str(value), callback=self.editChanged) self.callback = callback def sliderChanged(self, sender): self.edit.set(str(int(self.slider.get()))) self.callback(sender) def editChanged(self, sender): try: value = int(float(self.edit.get())) except ValueError: value = int(self.edit.getPlaceholder()) self.edit.set(value) self.slider.set(value) def enable(self): self.text.enable(True) self.slider.enable(True) self.edit.enable(True) def disable(self): self.text.enable(False) self.slider.enable(False) self.edit.enable(False)
class TextField(Group): indent = 90 def __init__(self, position, label, placeholder=""): super(TextField, self).__init__((position[0], position[1], position[2], 22)) self.label = TextBox((0, 3, self.indent - 10, 22), "{0}:".format(label), alignment="right") self.text = EditText((self.indent, 0, 500 - 40 - self.indent, 22), placeholder=placeholder) def set(self, *args): return self.text.set(*args) def get(self): return self.text.get()
class TextField(Group): indent = 90 def __init__(self, position, label, placeholder=""): super(TextField, self).__init__( (position[0], position[1], position[2], 22)) self.label = TextBox((0, 3, self.indent - 10, 22), "{0}:".format(label), alignment="right") self.text = EditText((self.indent, 0, 500 - 40 - self.indent, 22), placeholder=placeholder) def set(self, *args): return self.text.set(*args) def get(self): return self.text.get()
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 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 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)
class SliderPlus(Group): _callback = weakrefCallbackProperty() def __init__(self, posSize, label, minValue, value, maxValue, continuous=True, callback=None): super().__init__(posSize) self._callback = callback self.label = TextBox((0, 0, 0, 20), label) self.slider = Slider((0, 18, -60, 20), value=minValue, minValue=minValue, maxValue=maxValue, continuous=continuous, callback=self._sliderCallback) self.editField = EditText((-50, 16, 0, 24), "", continuous=False, callback=self._editFieldCallback) self.editField._nsObject.setAlignment_(AppKit.NSRightTextAlignment) self._setSliderFromValue(value) self._setEditFieldFromValue(value) def _breakCycles(self): self._callback = None super()._breakCycles() def _sliderCallback(self, sender): value = sender.get() self._setEditFieldFromValue(value) callCallback(self._callback, self) def _editFieldCallback(self, sender): value = sender.get() if not value: # self._setSliderFromValue(None) callCallback(self._callback, self) return value = value.replace(",", ".") try: f = float(value) except ValueError: pass else: self.slider.set(f) sliderValue = self.slider.get() if sliderValue != f: self._setEditFieldFromValue(sliderValue) callCallback(self._callback, self) def _setSliderFromValue(self, value): if isinstance(value, set): value = sum(value) / len(value) elif value is None: minValue = self.slider._nsObject.minValue() maxValue = self.slider._nsObject.maxValue() value = (minValue + maxValue) / 2 self.slider.set(value) def _setEditFieldFromValue(self, value): if isinstance(value, set): if len(value) == 1: value = next(iter(value)) else: value = None if value is None: s = "" else: if int(value) == value: s = str(int(value)) else: s = f"{value:.1f}" self.editField.set(s) def get(self): if not self.editField.get(): return None else: return self.slider.get() def set(self, value): self._setSliderFromValue(value) self._setEditFieldFromValue(value)
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 ParameterSliderTextInput(Group): ''' Custom Vanilla object consisting mainly of a Slider & and text input linked together (through a parameter object) ''' def __init__(self, parameter, posSize, title=None, callback=None): super(ParameterSliderTextInput, self).__init__(posSize) self.parameter = parameter self.callback = callback editTextPosSize = (-65, 0, 40, 22) if title is None: sliderPosSize = (5, 3, -80, 15) elif title is not None: title = title.capitalize() sliderPosSize = (70, 3, -80, 15) self.title = TextBox((0, 3, 65, 30), title, sizeStyle='small') if parameter.dissociable: editTextPosSize = (-65, 0, 40, 22) self.checkBox = CheckBox((-22, 5, 22, 25), u'∞', callback=self.setFree, value=True, sizeStyle='mini') self.slider = Slider(sliderPosSize, minValue=parameter.limits[0], maxValue=parameter.limits[1], value=parameter.value, callback=self.valueInput, sizeStyle='small') self.textInput = EditText(editTextPosSize, str(parameter.value), callback=self.valueInput, continuous=False, sizeStyle='small') self.parameter.bind(self) def get(self): return self.parameter.get() def enable(self, b): self.slider.enable(b) self.textInput.enable(b) if hasattr(self, checkBox): self.checkBox.enable(b) def valueInput(self, sender): value = sender.get() parameter = self.parameter if value == 'R': 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) def update(self, sender): value = self.parameter.get() self.textInput.set(str(value)) if (value != '*'): self.slider.set(value) if hasattr(self, 'checkBox'): free = self.parameter.hasMaster self.checkBox.set(free) def setFree(self, sender): value = not bool(sender.get()) self.parameter.setFree(value)
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 ParameterSliderTextInput(Group): ''' Custom Vanilla object consisting mainly of a Slider & and text input linked together (through a parameter object) ''' def __init__(self, parameter, posSize, title=None, callback=None): super(ParameterSliderTextInput, self).__init__(posSize) self.parameter = parameter self.callback = callback editTextPosSize = (-45, 0, 45, 22) if title is None: sliderPosSize = (5, 3, -80, 15) elif title is not None: if len(title) > 15: title = '{0}.'.format(title[:16]) title = title.capitalize() sliderPosSize = (120, 3, -55, 15) self.title = TextBox((0, 3, 115, 30), title, sizeStyle='small') if parameter.dissociable: editTextPosSize = (-65, 0, 40, 22) self.checkBox = CheckBox((-22, 5, 22, 25), u'∞', callback=self.setFree, value=True, sizeStyle='mini') self.slider = Slider(sliderPosSize, minValue=parameter.limits[0], maxValue=parameter.limits[1], value=parameter.value, callback=self.valueInput, sizeStyle='small') self.textInput = EditText(editTextPosSize, str(parameter.value), callback=self.valueInput, continuous=False, sizeStyle='small') self.parameter.bind(self) def get(self): return self.parameter.get() def enable(self, b): self.slider.enable(b) self.textInput.enable(b) if hasattr(self, checkBox): self.checkBox.enable(b) def valueInput(self, sender): value = sender.get() parameter = self.parameter if value == 'R': 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) def update(self, sender): value = self.parameter.get() self.textInput.set(str(value)) if (value != '*'): self.slider.set(value) if hasattr(self, 'checkBox'): free = self.parameter.hasMaster self.checkBox.set(free) def setFree(self, sender): value = not bool(sender.get()) self.parameter.setFree(value)
class ParameterSliderTextInput(Group): """ Custom Vanilla object consisting mainly of a Slider & and text input linked together (through a parameter object) """ def __init__(self, parameter, posSize, title=None, callback=None): super(ParameterSliderTextInput, self).__init__(posSize) self.parameter = parameter self.callback = callback editTextPosSize = (-65, 0, 40, 22) if title is None: sliderPosSize = (5, 3, -80, 15) elif title is not None: title = title.capitalize() sliderPosSize = (70, 3, -80, 15) self.title = TextBox((0, 3, 65, 30), title, sizeStyle="small") if parameter.dissociable: editTextPosSize = (-65, 0, 40, 22) self.checkBox = CheckBox((-22, 5, 22, 25), u"∞", callback=self.setFree, value=True, sizeStyle="mini") self.slider = Slider( sliderPosSize, minValue=parameter.limits[0], maxValue=parameter.limits[1], value=parameter.value, callback=self.valueInput, sizeStyle="small", ) self.textInput = EditText( editTextPosSize, str(parameter.value), callback=self.valueInput, continuous=False, sizeStyle="small" ) self.parameter.bind(self) def get(self): return self.parameter.get() def enable(self, b): self.slider.enable(b) self.textInput.enable(b) if hasattr(self, checkBox): self.checkBox.enable(b) def valueInput(self, sender): value = sender.get() parameter = self.parameter if value == "R": 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) def update(self, sender): value = self.parameter.get() self.textInput.set(str(value)) if value != "*": self.slider.set(value) if hasattr(self, "checkBox"): free = self.parameter.hasMaster self.checkBox.set(free) def setFree(self, sender): value = not bool(sender.get()) self.parameter.setFree(value)
class JoystickController(Group): lastEvent = None keyboardCorrection = 0 def __init__(self, posSize, fontObj, isSymmetricalEditingOn, isSwappedEditingOn, isVerticalAlignedEditingOn, autoSave, autoSaveSpan, activePair, callback): super(JoystickController, self).__init__(posSize) self.fontObj = fontObj self.activePair = activePair self.isSymmetricalEditingOn = isSymmetricalEditingOn self.isSwappedEditingOn = isSwappedEditingOn self.isVerticalAlignedEditingOn = isVerticalAlignedEditingOn self.autoSave = autoSave self.autoSaveSpan = autoSaveSpan self.callback = callback buttonSide = 36 self.ctrlWidth, self.ctrlHeight = posSize[2], posSize[3] self.jumping_X = buttonSide/2. self.jumping_Y = 0 self.minusMajorCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), "{:+d}".format(MAJOR_STEP), sizeStyle='small', callback=self.minusMajorCtrlCallback) self.minusMajorCtrl.bind(*MINUS_MAJOR_SHORTCUT) self.jumping_X += buttonSide self.minusMinorCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), "{:+d}".format(MINOR_STEP), sizeStyle='small', callback=self.minusMinorCtrlCallback) self.minusMinorCtrl.bind(*MINUS_MINOR_SHORTCUT) self.jumping_X += buttonSide self.plusMinorCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), "{:+d}".format(MINOR_STEP), sizeStyle='small', callback=self.plusMinorCtrlCallback) self.plusMinorCtrl.bind(*PLUS_MINOR_SHORTCUT) self.jumping_X += buttonSide self.plusMajorCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), "{:+d}".format(MAJOR_STEP), sizeStyle='small', callback=self.plusMajorCtrlCallback) self.plusMajorCtrl.bind(*PLUS_MAJOR_SHORTCUT) self.jumping_X = buttonSide/2. self.jumping_Y += buttonSide self.lftSwitchCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide*2, buttonSide*.75), "lft switch", sizeStyle='small', callback=self.lftSwitchCtrlCallback) self.lftSwitchCtrl.bind(*LEFT_BROWSING_SHORTCUT) self.jumping_X += buttonSide*2 self.rgtSwitchCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide*2, buttonSide*.75), "rgt switch", sizeStyle='small', callback=self.rgtSwitchCtrlCallback) self.rgtSwitchCtrl.bind(*RIGHT_BROWSING_SHORTCUT) self.jumping_X = buttonSide/2. self.jumping_Y += buttonSide self.exceptionTrigger = SquareButton((self.jumping_X, self.jumping_Y, buttonSide*2, buttonSide*.75), 'exception', sizeStyle='small', callback=self.exceptionTriggerCallback) self.exceptionTrigger.bind(*EXCEPTION_SHORTCUT) self.jumping_X += buttonSide*2 self.undoButton = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide*.75), 'undo', sizeStyle='small', callback=self.undoButtonCallback) self.undoButton.bind(*UNDO_SHORTCUT) self.jumping_X += buttonSide self.redoButton = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide*.75), 'redo', sizeStyle='small', callback=self.redoButtonCallback) self.redoButton.bind(*REDO_SHORTCUT) self.jumping_X = buttonSide/2. self.jumping_Y += buttonSide*.75 self.previewCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide*2, buttonSide*.75), "preview", sizeStyle='small', callback=self.previewCtrlCallback) self.previewCtrl.bind(*PREVIEW_SHORTCUT) self.jumping_X += buttonSide*2 self.solvedCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide*2, buttonSide*.75), "solved", sizeStyle='small', callback=self.solvedCtrlCallback) self.solvedCtrl.bind(*SOLVED_SHORTCUT) self.jumping_X = buttonSide/2. self.jumping_Y += buttonSide*.75+2 self.symmetricalModeCheck = CheckBox((self.jumping_X, self.jumping_Y, self.ctrlWidth, vanillaControlsSize['CheckBoxRegularHeight']), 'symmetrical editing', value=self.isSwappedEditingOn, callback=self.symmetricalModeCallback) self.jumping_Y += buttonSide*.6 self.swappedModeCheck = CheckBox((self.jumping_X, self.jumping_Y, self.ctrlWidth, vanillaControlsSize['CheckBoxRegularHeight']), 'swapped editing', value=self.isSwappedEditingOn, callback=self.swappedModeCallback) self.jumping_Y += buttonSide*.6 self.verticalAlignedModeCheck = CheckBox((self.jumping_X, self.jumping_Y, self.ctrlWidth, vanillaControlsSize['CheckBoxRegularHeight']), 'vertically aligned editing', value=self.isVerticalAlignedEditingOn, callback=self.verticalAlignedModeCheckCallback) self.verticalAlignedModeCheck.bind(*VERTICAL_MODE_SHORTCUT) self.hiddenSwappedEditingButton = Button((self.jumping_X, self.ctrlHeight+40, self.ctrlWidth, vanillaControlsSize['ButtonRegularHeight']), 'hiddenSymmetriyEditingButton', callback=self.hiddenSwappedEditingButtonCallback) self.hiddenSwappedEditingButton.bind(*FLIPPED_EDITING_SHORTCUT) self.hiddenJumpToLineButton = Button((self.jumping_X, self.ctrlHeight+40, self.ctrlWidth, vanillaControlsSize['ButtonRegularHeight']), 'hiddenJumpToLineButton', callback=self.hiddenJumpToLineButtonCallback) self.hiddenJumpToLineButton.bind(*JUMP_TO_LINE_SHORTCUT) self.jumping_X = buttonSide self.jumping_Y += buttonSide self.previousWordCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), u'↖', callback=self.previousWordCtrlCallback) self.previousWordCtrl.bind(*PREVIOUS_WORD_SHORTCUT) self.jumping_X += buttonSide self.cursorUpCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), u'↑', callback=self.cursorUpCtrlCallback) self.cursorUpCtrl.bind(*CURSOR_UP_SHORTCUT) self.jumping_X += buttonSide*1.5 self.activePairEditCorrection = EditText((self.jumping_X, self.jumping_Y, 50, vanillaControlsSize['EditTextRegularHeight']), text='{:d}'.format(0), # init value continuous=False, callback=self.activePairEditCorrectionCallback) self.jumping_X = buttonSide self.jumping_Y += buttonSide self.cursorLeftCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), u"←", callback=self.cursorLeftCtrlCallback) self.cursorLeftCtrl.bind(*CURSOR_LEFT_SHORTCUT) self.jumping_X += buttonSide*2 self.cursorRightCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), u'→', callback=self.cursorRightCtrlCallback) self.cursorRightCtrl.bind(*CURSOR_RIGHT_SHORTCUT) self.jumping_X = buttonSide self.jumping_Y += buttonSide self.delPairCtrl = SquareButton((self.jumping_X-6, self.jumping_Y+6, buttonSide, buttonSide), u'Del', callback=self.delPairCtrlCallback) self.delPairCtrl.bind(*DEL_PAIR_SHORTCUT) self.jumping_X += buttonSide self.cursorDownCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), u'↓', callback=self.cursorDownCtrlCallback) self.cursorDownCtrl.bind(*CURSOR_DOWN_SHORTCUT) self.jumping_X += buttonSide self.nextWordCtrl = SquareButton((self.jumping_X, self.jumping_Y, buttonSide, buttonSide), u'↘', callback=self.nextWordCtrlCallback) self.nextWordCtrl.bind(*NEXT_WORD_SHORTCUT) self.jumping_Y += buttonSide*1.3 self.jumping_X = buttonSide*.5 self.autoSaveCheck = CheckBox((self.jumping_X, self.jumping_Y, buttonSide*2.5, vanillaControlsSize['CheckBoxRegularHeight']), 'auto save', callback=self.autoSaveCheckCallback) self.jumping_X += buttonSide*2.5 self.autoSaveSpanPopUp = PopUpButton((self.jumping_X, self.jumping_Y, buttonSide*1.5, vanillaControlsSize['PopUpButtonRegularHeight']), AUTO_SAVE_SPAN_OPTIONS, callback=self.autoSaveSpanPopUpCallback) self.autoSaveSpanPopUp.set(AUTO_SAVE_SPAN_OPTIONS.index("{:d}'".format(self.autoSaveSpan))) # goes out def getLastEvent(self): return self.lastEvent def getKeyboardCorrection(self): return self.keyboardCorrection def getAutoSaveState(self): return self.autoSave, self.autoSaveSpan # comes in def setActivePair(self, activePair): self.activePair = activePair self.updateCorrectionValue() def setSwappedEditing(self, value): self.isSwappedEditingOn = value self.swappedModeCheck.set(self.isSwappedEditingOn) def setSymmetricalEditing(self, value): self.isSymmetricalEditingOn = value self.symmetricalModeCheck.set(self.isSymmetricalEditingOn) def setFontObj(self, value): self.fontObj = value self.updateCorrectionValue() def updateCorrectionValue(self): correction, kerningReference, pairKind = getCorrection(self.activePair, self.fontObj) try: self.activePairEditCorrection.set('{:d}'.format(correction)) except ValueError: self.activePairEditCorrection.set('') # callbacks def minusMajorCtrlCallback(self, sender): self.lastEvent = 'minusMajor' self.callback(self) def minusMinorCtrlCallback(self, sender): self.lastEvent = 'minusMinor' self.callback(self) def plusMinorCtrlCallback(self, sender): self.lastEvent = 'plusMinor' self.callback(self) def plusMajorCtrlCallback(self, sender): self.lastEvent = 'plusMajor' self.callback(self) def delPairCtrlCallback(self, sender): self.lastEvent = 'deletePair' self.callback(self) def exceptionTriggerCallback(self, sender): self.lastEvent = 'exceptionTrigger' self.callback(self) def undoButtonCallback(self, sender): self.lastEvent = 'undo' self.callback(self) def redoButtonCallback(self, sender): self.lastEvent = 'redo' self.callback(self) def previewCtrlCallback(self, sender): self.lastEvent = 'preview' self.callback(self) def solvedCtrlCallback(self, sender): self.lastEvent = 'solved' self.callback(self) def swappedModeCallback(self, sender): self.lastEvent = 'swappedEditing' self.isSwappedEditingOn = bool(sender.get()) self.callback(self) def symmetricalModeCallback(self, sender): self.lastEvent = 'symmetricalEditing' self.isSymmetricalEditingOn = bool(sender.get()) self.callback(self) def verticalAlignedModeCheckCallback(self, sender): self.lastEvent = 'verticalAlignedEditing' self.isVerticalAlignedEditingOn = bool(sender.get()) self.callback(self) def hiddenSwappedEditingButtonCallback(self, sender): self.lastEvent = 'swappedEditing' self.isSwappedEditingOn = not self.isSwappedEditingOn self.swappedModeCheck.set(self.isSwappedEditingOn) self.callback(self) def hiddenJumpToLineButtonCallback(self, sender): self.lastEvent = 'jumpToLineTrigger' self.callback(self) def previousWordCtrlCallback(self, sender): self.lastEvent = 'previousWord' self.callback(self) def cursorUpCtrlCallback(self, sender): self.lastEvent = 'cursorUp' self.callback(self) def cursorLeftCtrlCallback(self, sender): self.lastEvent = 'cursorLeft' self.callback(self) def cursorRightCtrlCallback(self, sender): self.lastEvent = 'cursorRight' self.callback(self) def cursorDownCtrlCallback(self, sender): self.lastEvent = 'cursorDown' self.callback(self) def nextWordCtrlCallback(self, sender): self.lastEvent = 'nextWord' self.callback(self) def lftSwitchCtrlCallback(self, sender): self.lastEvent = 'switchLftGlyph' self.callback(self) def rgtSwitchCtrlCallback(self, sender): self.lastEvent = 'switchRgtGlyph' self.callback(self) def activePairEditCorrectionCallback(self, sender): # removing the pair, if nothing is written if sender.get() == '': self.keyboardCorrection = None self.callback(self) return # if numbers are there... try: self.lastEvent = 'keyboardEdit' self.keyboardCorrection = int(sender.get()) self.callback(self) except ValueError: if sender.get() != '-': self.activePairEditCorrection.set('{}'.format(self.keyboardCorrection)) print traceback.format_exc() def autoSaveCheckCallback(self, sender): self.lastEvent = 'autoSave' self.autoSave = bool(sender.get()) self.callback(self) def autoSaveSpanPopUpCallback(self, sender): self.lastEvent = 'autoSave' self.autoSaveSpan = INT_2_SPAN[AUTO_SAVE_SPAN_OPTIONS[sender.get()]] self.callback(self)