Listening to when a guide changes position

Hi there, I want to be able to update my panel UI whenever a guide is moved. If my memory serves me correctly, I think previously in Extendscript I managed to do this by listening to an event.

I’ve attached the event notifier but it looks like no event gets called when I move a guide.
I’d rather avoid having to update my panel UI every so often if possible. Any ideas?
I’m running Photoshop v23.2.2

Edit: changed “ruler” to “guide” to be clearer

Dragging a guide doesn’t fire a move event unfortunately, the only option to listen to it would be the historyStateChanged event I think:

photoshop.action.addNotificationListener([{event: "historyStateChanged"}], (event, desc) => {
  if(desc.name === "Drag Guide") {
    // guide got moved
  }
});

However, I wouldn’t recommend this approach for a plugin you intend to distribute:
First of all it’s dependent on PS being in English, since other languages would have other history texts.
Also, historyStateChanged also fires when you do undo/redo for example.

Now that I think about it, you could also listen to a mosueup using the move tool via toolModalStateChanged, but that also wouldn’t be accurate in 100% of the events coming in. If you just need to check or update some state, it might be enough though.

It is possible to use batchPlay for this but it does not emit event.

BTW the language issue could be solved:
require("photoshop").core.translateUIString("$$$/Commands/DragGuide=Drag Guide")

5 Likes

Thank you for the help guys!
I went with the history state change approach.

Interesting topic. Out of curiosity, is there a way to listen for removal of the layer with certain name?

Ok, I’ve found a way to do it, for anyone interested:

require('photoshop').action.addNotificationListener([{event: "historyStateChanged"}], (event, desc) => {
 const cosiek = require("photoshop").core.translateUIString("$$$/Commands/DeleteLayer=Delete Layer");

   if(desc.name === cosiek) {

const layerExistsByName = (name) => {return Boolean(app.activeDocument?.layers?.some(layer => layer.name === name))}
const existsWB = layerExistsByName("LAYER NAME");

if (existsWB === false) {
 // do stuff
   }
else {
//do other stuff
}   
}
}

You don’t really need the historyState + translation workaround for that, as deleting a layer is captured in the delete event:
image

If you check for _target?.[0]?._ref === "layer" you know that a layer has been deleted. You can then call your layerExistsByName function.

1 Like

Looks like a good solution but I didn’t manage to implement it yet, should I replace event name with “delate” and desc with _target?.[0]?._ref === “layer” ?

Thanks!

Yes, the event name is delete.
In the event handler you can then do the check via

if(desc._target?.[0]?._ref === "layer") {
   // layer has been deleted
}
1 Like

It works perfectly, thank you!

That is misleading. There are another ways to kill a layer. E.g. when you ungroup folder. It does kill the layergroup but it is not delete event. Or when you convert layer into smart object you do loose your original ID and it is replaced by new layer. Also plugins/Scripts can remove layers too but no usefull events are emited.

You’re right, the delete event alone doesn’t cover 100% of the cases where the layer (ID) gets removed, but I think it just depends on what @Adam is trying to achieve. If he just wants to show some warning when the user actively deletes the layer he uses for his plugin, that should be fine in most cases. Also he selects it by name anyways, which doesn’t change upon smart object conversion. Of course the plugin should check if the layer type is still correct then :smiley:

I’m not sure about the performance impacts if a plugin just listens to all events to validate some state (e.g layer exists) - if every plugin does it that’s surely not the best :thinking:

There should be better non-low level events like in CEP when you change active document tab. Then it would be fine.