Preview transformed glyph with vanilla

Just getting started with Glyphs scripting and I can’t figure out the way GlyphView works.

When I want to preview the original layer it works, but not with the copied layer.

from vanilla import *
from GlyphsApp.UI import *

class GlyphPreviewDemo(object):

	def __init__(self):

		self.title = "Glyph Preview"
		self.w = FloatingWindow((200, 200), self.title)

		layerCopy = Glyphs.font.selectedLayers[0].copy()
		layerCopy.applyTransform([1, 0.0, 0.0, .8, 0, 0])

		self.w.Preview = GlyphPreview((0, 0, 0, 0), layer=layerCopy)
		self.w.open()


GlyphPreviewDemo()

Thanks!

You need to also set same parent as your initial layer :

from vanilla import *
from GlyphsApp.UI import *

class GlyphPreviewDemo(object):

	def __init__(self):

		self.title = "Glyph Preview"
		self.w = FloatingWindow((200, 200), self.title)

		layerCopy = Glyphs.font.selectedLayers[0].copy()
		layerCopy.parent = Glyphs.font.selectedLayers[0].parent 
		layerCopy.applyTransform([1, 0.0, 0.0, .8, 0, 0])

		self.w.Preview = GlyphPreview((0, 0, 0, 0), layer=layerCopy)
		self.w.open()


GlyphPreviewDemo()

Thanks that works perfectly :slight_smile:

Other related question: can I update the view afterwards?

What I tried >>>

self.w.Preview = GlyphPreview((200, 0, 0, 0), layer=self.layerCopy)
# Other stuff happens
self.layerCopy.applyTransform([1, 0.0, 0.0, .5, 0, 0])
self.w.Preview._nsObject.updateLayer()

You can just set the layer again.

self.w.Preview.layer = newLayer

.updateLayer() means to update some internal stuff, not the GSLayer. So that is not helping.

I would try to apply the transformation to the view, instead scaling the layer. You would need to copy the “GlyphPreview” class and add the a transformation in the drawRect_() function.
I added this for the next version. But if you rename the classes, you can use this code:

# -*- coding: utf-8 -*-

__all__ = ["GlyphPreview"]

import traceback
from GlyphsApp import GSLayer
from AppKit import NSView, NSColor, NSAffineTransform, NSGraphicsContext, NSRectFill
from vanilla.vanillaBase import VanillaBaseObject


class GSGlyphPreviewView(NSView):

	_transformation = None

	def setGlyph_(self, glyph):
		self._glyph = glyph

	def setDelegate_(self, delegate):
		self._delegate = delegate

	def drawRect_(self, rect):
		frame = self.bounds()
		NSColor.whiteColor().set()
		NSRectFill(frame)
		try:
			if self._transformation:
				NSGraphicsContext.saveGraphicsState()
				self._transformation.concat()
			if self._glyph is not None:
				if isinstance(self._glyph, GSLayer):
					layer = self._glyph
				elif isinstance(self._glyph, RGlyph):
					layer = self._glyph._layer
				if layer:
					layer.drawInFrame_(frame)
		except:
			print(traceback.format_exc())
		finally:
			if self._transformation:
				NSGraphicsContext.restoreGraphicsState()

	def mouseDown_(self, event):
		try:
			if event.clickCount() == 2:
				if self._delegate.mouseDoubleDownCallBack:
					self._delegate.mouseDoubleDownCallBack(self)
				return
			if self._delegate.mouseDownCallBack:
				self._delegate.mouseDownCallBack(self)
		except:
			print(traceback.format_exc())

	def mouseUp_(self, event):
		try:
			if self._delegate.mouseUpCallBack:
				self._delegate.mouseUpCallBack(self)
		except:
			print(traceback.format_exc())


class GlyphPreview(VanillaBaseObject):
	"""
	A control that allows for showing a glyph

	GlyphPreview objects handle GSLayer

		from vanilla import FloatingWindow
		from GlyphsApp.UI import GlyphPreview
		class GlyphPreviewDemo(object):
			def __init__(self):
				self.title = "Glyph Preview"
				self.w = FloatingWindow((200, 200), self.title)
				layer = Glyphs.font.selectedLayers[0]
				self.w.Preview = GlyphPreview((0, 0, 0, 0), layer=layer)
				self.w.Preview.mouseDoubleDownCallBack = self.mouseDoubleDown
				self.w.open()
			def mouseDoubleDown(self, sender):
				print "Mouse Double Down"

		GlyphPreviewDemo()

	**posSize** Tuple of form *(left, top, width, height)* representing the position and size of the color well.

	**layer** A *GSLayer*. If *None* is given, the view will be empty.
	"""

	nsGlyphPreviewClass = GSGlyphPreviewView

	def __init__(self, posSize, layer=None):
		self.mouseDownCallBack = None
		self.mouseDoubleDownCallBack = None
		self.mouseUpCallBack = None
		self._setupView(self.nsGlyphPreviewClass, posSize)
		self._nsObject.setDelegate_(self)
		self._nsObject.setGlyph_(layer)

	@property
	def layer(self):
		return self._nsObject._layer

	@layer.setter
	def layer(self, value):
		self._nsObject._layer = value
		self._nsObject.setNeedsDisplay_(True)

	@property
	def transformation(self):
		return self._nsObject._transformation

	@transformation.setter
	def transformation(self, value):
		assert isinstance(value, NSAffineTransform)
		self._nsObject._transformation = value
		self._nsObject.setNeedsDisplay_(True)

Thank you for the reply! Transformation is working now.

Is the logic the same for switching to different glyphs? I tried this but it seems I’m still missing something.

self.w.Preview = GlyphPreview((200, 0, 0, 0), layer=self.layerCopy)

# Other stuff happens
self.layerCopy = Glyphs.font.glyphs['B'].layers[0].copy()
self.layerCopy.parent = Glyphs.font.glyphs['B'].layers[0].parent
self.w.Preview.layer = self.layerCopy

(and is there somewhere where I can find documentation on this?)

Just do:

self.w.Preview.layer = Glyphs.font.glyphs['B'].layers[0]

This also doesn’t update the glyphView.

I tried using a copy of the layer because I want to preview changes to the glyph (more complicated than just transformation).

Does the fact that it’s in a callback change anything?

	def xPosSliderCallback(self, sender):
		self.w.Preview.layer = Glyphs.font.glyphs['C'].layers[0]

That should work. Maybe add a print() to make sure the callback is actually working.

Oh adding a „print()“ is a rather nasty hack. I think I remember Tim having had such a print statement in one of his scripts too, with the comment that it is just for forcing an update.

I think Georg suggested the print just as a way to debug whether the callback is invoked as expected, not to force an update.

Hm what am I missing? The callback comes through, and for just transforming the glyph it does work. But changing to another glyph doesn’t do anything.

from vanilla import *
from GlyphsApp.UI import *

class GlyphPreviewDemo(object):

	def __init__(self):
		self.w = FloatingWindow((500, 200), "Glyph Preview")

		self.layerCopy = Glyphs.font.glyphs['A'].layers[0].copy()
		self.layerCopy.parent = Glyphs.font.glyphs['A'].layers[0].parent

		self.w.Preview = GlyphPreview((300, 0, 0, 0), layer=self.layerCopy)
		self.w.transformButton = Button((10, -60, 280, 20), "Transform",
							callback=self.transformCallback)
		self.w.button = Button((10, -30, 280, 20), "Change",
							callback=self.buttonCallback)

		self.w.open()

	def transformCallback(self, sender):
		print("Transform Callback check")
		self.layerCopy.applyTransform((.9, 0, 0, .9, 0, 0))
		self.w.Preview.layer = self.layerCopy

	def buttonCallback(self, sender):
		print("Change Callback check")
		self.layerCopy = Glyphs.font.glyphs['B'].layers[0]
		self.w.Preview.layer = self.layerCopy

GlyphPreviewDemo()