UNSOLVED MultilineView getSelection returns None



  • Hi,

    I made a simple kerning window. If you run it and select a glyph from the view, getSelection method always returns None, you can see it in the output window. Am I doing something wrong or is it a bug? I need the selected glyph index to be able to tell which pair I'm selecting to create exceptions.

    Thanks

    import AppKit
    from mojo.UI import MultiLineView
    from vanilla import *
    import itertools
    import re
    
    DEF_OPTIONS = {'displayMode': 'Multi Line',
    'Show Kerning': True,
    'Multi Line': True,
    'xHeight Cut': False,
    'Water Fall': False,
    'Single Line': False,
    'Inverse': False,
    'Show Metrics': False,
    'Left to Right': False,
    'Right to Left': False,
    'Center': False,
    'Upside Down': False,
    'Stroke': False,
    'Fill': True,
    'Beam': False,
    'Guides': False,
    'Blues': False,
    'Family Blues': False,
    'Show Control glyphs': False,
    'Show Space Matrix': False,
    'Show Template Glyphs': False,
    'showLayers': []}
    
    RE_GROUP = re.compile(r'public.kern\d\.')
    
    
    class KeyEventMonitor(object):
    	MAIN_KEYS = 'wasd'
    	MODIFIER_TO_INCREMENT = {
    	131330: 50,  # shift
    	1179914: 100,  # cmd+shift
    	524576: 1,  # alt
    	}
    
    	def __init__(self, font):
    		self.font = font
    		self.keyMonitor = None
    		self.pairlist = []
    		self.currentGlyphSequence = []
    		self.spaceGlyph = self.font['space']
    		self.w = Window((600, 400), minSize=(300, 300))
    		self.w.lineView = MultiLineView((0, 0, -200, -0),
    										pointSize=50,
    										selectionCallback=self.lineViewSelectionCallback)
    		self.w.lineView.setFont(font)
    		self.w.pairListView = List((-200, -0, -0, -0), allowsMultipleSelection=False,
    							selectionCallback=self.selectPairInList, items=self.pairlist)
    		self.currentPairIndex = 0
    		self.w.lineView.setDisplayStates(DEF_OPTIONS)
    		self.w.lineView.setLineHeight(400)
    		self.w.bind("close", self.stop)
    		self.w.open()
    		self._startOverridingRFkeys()
    
    	def stop(self, sender):
    		self._stopOverridingRFkeys()
    
    	def start(self, sender):
    		self._startOverridingRFkeys()
    
    	def _startOverridingRFkeys(self):
    		self._stopOverridingRFkeys()
    		self.keyMonitor = AppKit.NSEvent.addLocalMonitorForEventsMatchingMask_handler_(
    			AppKit.NSKeyDownMask, self._keyDown)
    
    	def _stopOverridingRFkeys(self):
    		if self.keyMonitor is not None:
    			AppKit.NSEvent.removeMonitor_(self.keyMonitor)
    		self.keyMonitor = None
    
    	def _keyDown(self, event):
    		key = event.charactersIgnoringModifiers().lower()
    		if key in self.MAIN_KEYS and self.w.lineView.isFirstResponder():
    			self.kernWindowKeyDown(key, event.modifierFlags())
    		else:
    			self._stopOverridingRFkeys()
    			AppKit.NSApp().sendEvent_(event)
    			self._startOverridingRFkeys()
    
    	def selectPairInList(self, sender):
    		selection = sender.getSelection()
    		if selection != []:
    			self.currentPairIndex = selection[0]
    			self.redrawGlyphSequence()
    
    	def kernWindowKeyDown(self, key, modifier):
    		pair = self.pairlist[self.currentPairIndex]
    		kerningIncrement = self.MODIFIER_TO_INCREMENT.get(modifier, 10)
    		if key == 'w':
    			self.incrementPairIndex(-1)
    		elif key == 's':
    			self.incrementPairIndex(1)
    		elif key == 'a':
    			self.font.kerning[pair] += kerningIncrement
    		elif key == 'd':
    			self.font.kerning[pair] -= kerningIncrement
    		self.redrawGlyphSequence()
    
    	def incrementPairIndex(self, value):
    		self.currentPairIndex += value
    		if self.currentPairIndex == self.pairNumbers or self.currentPairIndex == -self.pairNumbers:
    			self.currentPairIndex = 0
    		self.w.pairListView.setSelection([self.currentPairIndex])
    		pair = self.pairlist[self.currentPairIndex]
    		self.processPairGlyphSequence(pair)
    
    	def redrawGlyphSequence(self):
    		self.w.lineView.set(self.currentGlyphSequence)
    
    	def processPairGlyphSequence(self, pair):
    		self.currentGlyphSequence = []
    		flattenPairs = self._getPairCombinations(pair)
    		for pair in flattenPairs:
    			self.currentGlyphSequence.extend([self.font[g] for g in pair])
    			self.currentGlyphSequence.append(self.spaceGlyph)
    
    	def lineViewSelectionCallback(self, sender):
    		print(sender.getSelection())
    
    	def _getPairCombinations(self, pair):
    		"""
    		Gives all the possible combinations a pair with kerning groups can create
    		"""
    		left, right = pair
    		leftGlyphs = self.font.groups.get(left, [left])
    		rightGlyphs = self.font.groups.get(right, [right])
    		return itertools.product(leftGlyphs, rightGlyphs)
    
    	def setPairList(self, pairlist):
    		"""
    		set the pair list to perform kerning on.
    		"""
    		self.pairlist = pairlist
    		self.w.pairListView.set(map(self.getPairStr, pairlist))
    		self.pairNumbers = len(pairlist)
    
    	def getPairStr(self, pair):
    		return ' | '.join(map(self.removeGroupTag, pair))
    
    	def removeGroupTag(self, pairEntry):
    		splitted = RE_GROUP.split(pairEntry)
    		if len(splitted) > 1:
    			return "@%s" % splitted[-1]
    		return splitted[-1]
    
    	def setPairListFromKerning(self):
    		self.setPairList(sorted(self.font.kerning.keys()))
    		self.w.pairListView.setSelection([0])
    		self.processPairGlyphSequence(self.pairlist[0])
    		self.redrawGlyphSequence()
    
    
    if __name__ == "__main__":
    	from mojo.UI import *
    	OutputWindow().clear()
    
    	f = CurrentFont()
    	k = KeyEventMonitor(CurrentFont())
    	k.setPairListFromKerning()
    


  • Looking forward to seeing this get fixed. Thank you @frederik.


  • admin

    I thought the index would be important for your script... and update is coming!



  • I wanted to use getSelection because in docs it says it should return the glyph index in the view. I also tried the glyphRecords but it doesn't have the index. With index I know which pair I'm adding the exception to. getSelectedGlyph returns the glyph which was not helpful in this case. But Thanks for the help ( ͡° ͜ʖ ͡°) and looking forward to the update.

    Cheeers!


  • admin

    Oh a bug, will be fixed in the next version

    but view.getSelectedGlyph() must work to get the selected glyph, be carefull as there could be multiple version of the same glyph in a line view

    from mojo.UI import MultiLineView
    
    import vanilla
    
    glyphNames = "abc"
    
    font = CurrentFont()
    
    
    def lineViewSelectionCallback(sender):
        print(sender.getSelectedGlyph())
    
    w = vanilla.Window((400, 400))
    w.s = MultiLineView((0, 0, 0, 0), selectionCallback=lineViewSelectionCallback)
    w.s.setFont(font)
    
    w.s.set([font[glyphName] for glyphName in glyphNames])
    
    w.open()
    

Log in to reply