How to activate a layer via Python?

I tried to write a Python script that activates the master layer for the currently selected master (i.e. when a non-master layer is active). It should practically simulate clicking on the layers palette. How is it done?

This is what I have tried to far but the result is not perfect:

from GlyphsApp import *

font = Glyphs.font
thisGraphicView = font.currentTab.graphicView()

# Switch each glyph in the current tab to its master layer.
# This is exactly the desired behaviour but it does not last.
# After clicking on a different glyph, the layer is switched back to what it was before running this script.
for layer_index in range( len( font.currentTab.layers ) ):
    layer = font.currentTab.layers[layer_index]
    glyph = layer.parent
    master_layer = glyph.layers[ font.selectedFontMaster.id ]
    font.currentTab.layers[layer_index] = master_layer

# does not seem to have any effect
thisGraphicView.setActiveLayer_( font.glyphs['g'].layers[ font.selectedFontMaster.id ] )

# redraw
font.currentTab.redraw()

# Does not work. What is it supposed to do?
# font.currentTab.layersCursor = 0

# Another redraw
Glyphs.redraw()

After clicking on a different glyph, the layer is switched back to what it was before running this script.

Try to take the layer array, add the layers you like to see and the set the whole array

Layers = Font.currentTab.layers

# Add/remove stuff

Font.currentTab.layers = Layers

That might give strange results when you have some features active.

The activeLayer property is reset internally. It is not to be used like that.

The layerCursor is read only. It returned the cursor position in the .layers array. That can be diffeent than the text cursor with active ligatures.

1 Like

Oh, excellent! Now it works. And layerCursor is indeed very helpful, too.

Thanks for your help.

Just noticed that this method does not work if I try to switch to a non-master layer (or to retain non-master layers).

This code …

Layers = Font.currentTab.layers

# don’t touch anything

Font.currentTab.layers = Layers

… switches all glyphs in the tab that are on non-master layers to the respective master layer (which is not necessarily the font’s selected master).

I fixed it.

1 Like

Thanks!

Btw, this is the script I am using this code for:

I just realised that after using the script, I cannot switch all the glyphs in the tab to a different master using Cmd+1, Cmd+2 etc. any more. Any way to fix this?

Btw, I always found it very annoying if I have to manually switch a glyph to the respective master layer when Glyphs thinks I want to stay on the current layer. This happens a lot and causes lots of unnecessary clicks.

Can I ask that Cmd+1, Cmd+2 etc. always switches all glyphs in the tab to that master layer, without keeping some glyphs stuck. That would make me very, very happy.

The above script was partly an attempt to solve this problem (at least make it a little easier to switch to the master layer) but it seems it makes the situation worse.

I realise we had that discussion before:

Sorry, I still don’t see a realistic scenario in which the current behaviour is better, and I see a lot of uses in which it would be be better to always make Cmd+1 switch to the first master.

Georg, can you explain why you think the current behaviour is better?

Please have a look at the setter of tab.layers: https://github.com/schriftgestalt/GlyphsSDK/blob/master/ObjectWrapper/GlyphsApp/init.py#L7132

If you construct a string (NSMutableAttributedString) without attributes, the layers will follow the master selection.

Thanks for your help, Georg.

Finally got this to work:

Seems like after using this script, Cmd+1, Cmd+2 to activate masters does not work any more.
@GeorgSeifert any ideas how to fix that?

@GeorgSeifert Any Ideas how to fix this?

I find tht Toggle script immensely useful but it is annoying that it breaks the switching between masters.

1 Like

Agreed. Would it be possible to fix the switching, Georg?

The problem is that a user-selected layer must survive a master switch. Georg posted the solution above:

You can build this into the script. Every time you switch back to the master layer of a currently active master, you can reconstruct the tab string and the cursor position/selection.

1 Like

Sorry but this is all very cryptic. I tried for a while but could not make sense of your advice.

How do I construct a string (NSMutableAttributedString) without attributes?
What do I do with it after I have constructed it?

Okay, got this to work. Constructing a string without attibutes is not the solution, though. Will post the result later.

1 Like

The updated version is on Github now. It turned out that the best approach is not to interact with currentTab.layers directly but only to use the NSMutableAttributedString to control the active layers. The content of that NSMutableAttributedString needs to be partly with attributes and partly without.

1 Like