Is it possible to open a Properties window?

I want to open Properties window (if not open) from a plugin. Alchemist gives me this:

const batchPlay = require("photoshop").action.batchPlay;

const result = await batchPlay(
[
   {
      "_obj": "invokeCommand",
      "commandID": 6478,
      "kcanDispatchWhileModal": true,
      "_isCommand": false,
      "_options": {
         "dialogOptions": "dontDisplay"
      }
   }
],{
   "synchronousExecution": false,
   "modalBehavior": "fail"
});

But getting error:

The command “<unknown>” is not currently available.

I assume it’s the wrong command ID :thinking:

Also tried "kcanDispatchWhileModal": false, but no luck :slightly_frowning_face:
Any advice? Or is this not possible at all?

The command ID is correct, you can execute menu items via
photoshop.core.performMenuCommand({ commandID });

You can read out the visible and obscured state from the app property panelList.

Btw, if you need to find the command ID for a dynamically added menu item (like a plugin), you can access it via the app property menuBarInfo, by traversing the submenus and matching by the panel titel.

3 Likes

Awesome. Thank you so much. That’s much more info than I asked, but was wondering about the other day :slight_smile: Will try to implement after work.

I guess it also answers this question I asked a while ago :slight_smile:

You’re welcome :slight_smile:
Ah, indeed! When I read the other post the first time I thought you were trying to click a button or run a function of another panel, which is not possible. But calling a menu command should work fine the way I’ve described above :+1:

1 Like

Where exactly is this panelList? require('photoshop').app doesn’t have such property :thinking: Same question for menuBarInfo


Also require('photoshop').core.performMenuCommand(6478); does not do anything for me :frowning:
I’m getting:

Error: Argument 1 has an invalid type. Expected type: object actual type: number

What kind of object should I pass?
Nevermind, figured the {} in your example was what I needed and not just a template-like syntax :sweat_smile:


Bonus question :slight_smile:
Is there a way to hide/close Properties window? Alchemist gives the exact same code snippet I posted initially, and in console it seems I can’t make it work at all… :confused:
image


Is there some decent documentation on photoshop?

1 Like

Try

const psCore = require('photoshop').core;
psCore.performMenuCommand({ "commandID": 6478 });

It’s a toggle :wink:

Aha, that works now in console and it toggles, but I can’t make it work in Ps via a menu plugin command. The Properties window opens the first time, but then it won’t close, but always keeps opening. I guess it’s because it’s not in focus when I click the menu.

Also I figured how to get panelList with Alchemist inspector, but for Properties I always get visible/obscured false. I guess this explains why window does not toggle, but always opens.

{
    ID: "panelid.static.smartbrush"
    name: "Properties"
    obscured: false
    visible: false
    _obj: "panelList"
}

Any suggested workaround?


Here’s the action. No matter if “Properties” window is closed or open, the result is always the same :frowning:

require('photoshop').action.batchPlay([
            {
                "_obj": "get",
                "_target": [
                    {"_property": "panelList"},
                    {"_ref": "application", "_enum": "ordinal", "_value": "targetEnum"}
                ]
            }
        ], {
        synchronousExecution: true,
        modalBehavior: 'execute'
    })[0].panelList[44]

Not sure if index is always 44, but seems like it


Also tried to get the state directly from core:

core.getMenuCommandState({"commandID":menuItem.command});

But this always returns [true]


Tried to get directly from menuBarInfo and see if menu is checked, but the result is always:

{
    "name":"Properties",
    "visible":true,
    "enabled":true,
    "checked":false
}

Anyone any ideas on how to get the correct status of the panel/window so I could toggle only if needed? :roll_eyes:

Could you summarize again, which behavior you’d like to see?
I just tested said menuCommand from

  1. the console
  2. inside a panel
  3. a plugin menu command

and in all cases it worked fine, by showing the properties window when it’s hidden and hiding it when it is shown.

The main question is - how do I prevent panel from hiding if it’s visible (or vice versa - prevent showing if it’s hidden). Or even bring it to front if it’s behind other panel? So basically I didn’t find a proper way to check the state, so that I could prevent a toggle if not needed

Hm, for my plugin this worked fine at least.

Here’s the relevant part:

 const panelState = getAppProperty('panelList').find(p => p.name === panelName)
  if (!panelState.visible || panelState.obscured) {
    performMenuCommand(panel.command)
  }

And when I test it with Alchemist specifically for the Properties Panel, I also seem to get the correct result:
Not opened:
image

opened:
image

Maybe I’m not seeing the issue yet, or it’s just a problem on your side :thinking:

That’s weird :thinking: I will re-check again, but when I tried, I had:

panelid.static.smartbrush is not really the panel that you want, is it

But it’s the only in list I see named “Properties” :confused:

You can find that out easily if you hide/show the properties panel and add the Application/panelList descriptor in Alchemist each time. If you then compare both for the differences, you should see which one you toggled.

1 Like

In the past i’ve used something like this:

function get_panelList() {
  return batchPlay(
    [{
      "_obj": "get",
      "_target": [{
          "_property": "panelList"
        },
        {
          "_ref": "application",
          "_enum": "ordinal",
          "_value": "targetEnum"
        }
      ]
    }], {
      "synchronousExecution": true
    })[0].panelList;
}

function showPropertiesPanel() {
  const panelStatus = get_panelList().find(panel => panel.name === "Properties")
  if (!panelStatus.visible || panelStatus.obscured) {
    require('photoshop').core.performMenuCommand({
      "commandID": 6478
    });
  }
}
1 Like

That’s exactly what I’ve posted above :smiley:

OK… So what’s the deal?
If I do const panelState = getAppProperty('panelList') and add a breakpoint, in console I find manually the Properties panel and it’s:

{
    ID: "panelid.static.smartbrush"
    name: "Properties"
    obscured: false
    visible: false
    _obj: "panelList"
}

But after .find(panel => panel.name === "Properties") I get:

{
    ID: "panelid.static.properties"
    name: "Properties"
    obscured: false
    visible: false
    _obj: "panelList"
}

How come in console it’s the different panel with the same name when whole list is expanded?
And I guess it’s better to search by ID, than by name (noticed name is different in other languages)

That’s weird indeed. And yes, matching by ID is always the better option. I only used it for panels of my own plugin, so matching by name works fine, too, in this case.