Message Board for Rorohiko Workflow Resources
https://www.rorohiko.com/cgi-bin/yabb2/YaBB.pl
General Category >> General Board >> Creating menus
https://www.rorohiko.com/cgi-bin/yabb2/YaBB.pl?num=1230397518

Message started by Kasyan on 12/28/08 at 05:05:18

Title: Creating menus
Post by Kasyan on 12/28/08 at 05:05:18
Hello Rorohiko forum,

First of all I want to say that I am in raptures over APID’s new features — especially adornments. This is terrific!

I have a few questions concerning creating menus:
Is it possible to add a new menu entry to an existing custom submenu (e.g. I’ve already created a submenu called “Scripts” during startup in targetengine "session")?
When I add a new entry into a standard InDesign menu, it works:
“Main:&Edit:Preferences:My Own Menu”
But when I try “Main:Scripts:My Own Menu” – doesn’t.

When I insert a new entry into a standard InDesign menu, can I control its position — like in ESTK2 — at the beginning/end or before/after some menu item?

In MyPlugIn.jsx file I found lines similar to this one – “app.registerMenuItem("menuItem4","Main:0x90B50kActivePageItemMenuKey:.Menutester:.Menu Bar Item 4",4.0);”
What for is the dot, following the colon, before “Menutester” and “Menu Bar Item 4”?
The cookbook says that ‘menu paths’ should be separated by colons.

It took quite an effort to figure out how to create menu item with check box. Here is what I came up with:
Event Filter: docLoaded, menuCountCharacters, enableMenus


Code (]if (theItem.eventCode == "enableMenus") {
     if (theItem.tempDataStore != 3) {
           theItem.tempDataStore = 1;
     }
}
else if (theItem.eventCode == "menuCountCharacters") {
     if (theItem.tempDataStore == 1) {
           theItem.tempDataStore = 3;
           Main();
     }
     else if (theItem.tempDataStore == 3) {
           theItem.tempDataStore = 1;
           ClearAdornments();
     }
}
else if (theItem.eventCode == "docLoaded") {
     app.registerMenuItem("menuCountCharacters", "Count Characters");
     ClearAdornments();
}[/code):

I read the comments in the file and found that setting ‘theItem.tempDataStore’ to some numeric value makes the menu item enabled/enabled, with/without checkbox, with/without dash.
0 or ‘false’ - disabled
1 or ‘true’ - enabled
2 - disabled with checkbox (2 + 0 = 2)
3 - enabled with checkbox ( 2 + 1 = 3)
4 - disabled with dash (4 + 0 = 4)
5 - enabled with dash (4 + 1 = 5)

According to comments, 15 combinations are possible in all.
I tried other combinations – from 6 to 15 – and they just seem to repeat the previous ones.
IOW are they usable?

One more question:
I want to create two menu items:
Event Filter: menuTest*, selected, enableMenus

[code]if (theItem.eventCode == "enableMenus")
{
 theItem.tempDataStore = 1;
}
else if (theItem.eventCode == "menuTest")
{
 alert("Menu was selected");
}
else if (theItem.eventCode == "selected")
{
 app.registerMenuItem ("menuTest1","Main:0x90B50kActivePageItemMenuKey:Menutest 1");
 app.registerMenuItem ("menuTest2","Main:0x90B50kActivePageItemMenuKey:Menutest 2");
 alert("Menu Items have been added");
}


Setting ‘theItem.tempDataStore’ to some value changes the state of both menu items at the same time. How to make, for example, one of them enabled and the other disabled?

And finally  the last question:
How to use Multi Selected (dash) menu item?
For example, I want to create ‘Fruits’ menu item containing three elements: ‘Apples’, ‘Pears’ and ‘Oranges’. And I want it to be checked/unchecked when all these three elements are checked/unchecked, but I want it to be dashed when some of them selected and some not.

Thank you in advance.

Kasyan

Title: Re: Creating menus
Post by Kris Coppieters on 12/29/08 at 07:48:18
Hi Kasyan,

I'll try to answer your various questions out of order - I'll take the simple ones first, and I'll keep the hard ones for last.

The dots in menu names mean 'don't translate'. Internally, InDesign has a fairly complex system that handles localization of strings - strings are represented by a (often readable) 'key' which has multiple translated strings associated to it.

I've written a fairly extensive article about this on Mark Niemann-Ross web site:

http://www.niemannross.com/developer/wiki/index.php?title=Secrets_of_the_menu_paths

It's written with a slight C++/SDK slant, but it should make clear why there are these dots in front of some menu items.

So, if you look at a menu path, you should realize that none of the strings (except the ones prefixed with dots) are 'display' strings - all of them are 'key' strings into some database that will be looked up and mapped before being displayed.

That's also why you often need to 'fish' for menu strings - trying to guess what they are in order to add a submenu or menu item.

Title: Re: Creating menus
Post by Kris Coppieters on 12/29/08 at 08:00:26
Next one: position of the menu items. You have some control over that via APID, but not a great deal. The floating-point value you see in the app.registerMenuItem() call affects the position - larger numbers are more towards the bottom, smaller numbers towards the top.

Also, turns out the value 333333.0 is 'magic' (I found this value through experimentation). If you use a floating point value larger than this, the menu item will end up behind any submenus you might add. Smaller than 333333.0 and it will sit before any submenus you might add via APID.

That gives you a little bit of control, but not nearly enough for most situations - for example, the submenus are all 'bunched together' in alphabetical order.

Keep in mind - app.registerMenuItem() is just a thin layer on top of the C++ API - and all APID does is simply 'pass through' most of the data it gets from the script - so the 'features' (like the 333333.0 magic value) I am describing here are not APID's - they are internal InDesign behavior that becomes exposed through APID.

If you want to have more control over the position of menu items, you need to use a 'hybrid' approach (Harbs figured this one out): first, create menus with with app.registerMenuItem(). Then create submenus with the standard ExtendScript submenus.add(), using LocationOptions. Then create the menus below the submenus with app.registerMenuItem().


Title: Re: Creating menus
Post by Kris Coppieters on 12/29/08 at 08:03:52
As to return values - there are 16 possible values (0-15), but only a few of these are really 'used' - i.e. 6 to 15 do not really serve any purpose, AFAIK. This is another case where you 'see' the C++ API 'shine through' APID - APID is the messenger, and it simply passes these values on to the underlying C++ API.

Title: Re: Creating menus
Post by Kris Coppieters on 12/29/08 at 08:06:59
As you've found out, to enable/disable/check/uncheck menu items, theItem.tempDataStore can be set to a single integer, which then affects all menu items at the same time.

To handle each menu item individually, you instead need to store an array of integers in theItem.tempDataStore instead - i.e. create an array, and add one integer value to the array for each menu item. Then store the array into theItem.tempDataStore.

That should allow you to control each menu item individually.

instead of

theItem.tempDataStore = 1;

you'd do

theItem.tempDataStore = [1,0];

Title: Re: Creating menus
Post by Kris Coppieters on 12/29/08 at 08:37:25
To get a multi-select menu item, you'd return a 4 instead of a 1 in the proper array position in theItem.tempDataStore.

For some additional info and sample code, there's an interesting sample to be found in the Examples folder that comes with the APID Developer Toolkit - it's called MenuDemo. Check it out...

Title: Re: Creating menus
Post by Kris Coppieters on 12/29/08 at 09:15:23
Finally, the first question - right now, I don't know the answer to that one - i.e. why you cannot add stuff to “Main:Scripts:My Own Menu” after creating it from a script in the session engine.

My guess is that you'd need to use a slightly different prefix than Main:Scripts... - but what the 'magic string' is I don't know, and I'd need to write a bit of C++ code to find out I think. Next time I am in that 'hood, I'll take a peek and see if I can come up with an answer...

Title: Re: Creating menus
Post by Kasyan on 12/29/08 at 20:06:48
Hi Kris,

Thank you for your detailed answers. But I still have the problem with setting two menus to different states. I tried to set theItem.tempDataStore to an array of integers before posting in the forum, but it didn’t work. I try to do it now and it doesn’t work either:
Event Filter: menuTest*, selected, enableMenus

Code (]if (theItem.eventCode == "enableMenus")
{
 theItem.tempDataStore = [1,0):

;
}
else if (theItem.eventCode == "menuTest1")
{
 alert("menuTest 1 was selected");
}
else if (theItem.eventCode == "menuTest2")
{
 alert("menuTest 2 was selected");
}
else if (theItem.eventCode == "selected")
{
 app.registerMenuItem ("menuTest1","Main:0x90B50kActivePageItemMenuKey:Menutest 1");
 app.registerMenuItem ("menuTest2","Main:0x90B50kActivePageItemMenuKey:Menutest 2");
 alert("Menu Items have been added");
}

Could you tell me where I am wrong?

Then I set ‘Use Debugger’ check box and run the script trough ESTK2 and found that when I invoke ‘enableMenus’ event, the code runs twice – each time for each menu item separately. So tried this approach as a workaround:
Event Filter: menuTest*, selected, enableMenus
[code]if (theItem.eventCode == "enableMenus")
{
 //alert("myCounter  = " + myCounter );
if (myCounter  == 0)
{
 theItem.tempDataStore = 0;
}
else if (myCounter  == 1)
{
theItem.tempDataStore = 1;
}
 myCounter ++;
if (myCounter > 1) myCounter = 0;
}
else if (theItem.eventCode == "menuTest1")
{
 alert("menuTest 1 was selected");
}
else if (theItem.eventCode == "menuTest2")
{
 alert("menuTest 2 was selected");
}
else if (theItem.eventCode == "selected")
{
 app.registerMenuItem ("menuTest1","Main:0x90B50kActivePageItemMenuKey:Menutest 1");
 app.registerMenuItem ("menuTest2","Main:0x90B50kActivePageItemMenuKey:Menutest 2");
 var myCounter = 0;
 alert("Menu Items have been added");
}[/code]

But it seems to be so clumsy.

Kasyan

Title: Re: Creating menus
Post by Harbs on 12/29/08 at 20:11:47
Hi Kasyan,

You need to enable group events.

Something like this...
theItem.setDataStore("$GROUP_EVENTS$",true);

Title: Re: Creating menus
Post by Kasyan on 12/29/08 at 20:30:07
Thank you, Harbs. Now it works.

Kasyan

Title: Re: Creating menus
Post by Kasyan on 01/05/09 at 21:50:11
Hi there,

I stumbled over a new problem: I am unable to change a value of ‘tempDataStore’ when it is set as an array. In the following code I create two menu items and want ‘menuTest1’ to change its state – checked/unchecked – each time I select it. This works for a single menu item when I set ‘tempDataStore’ to 1 (see my first snippet in this thread).
But when I set ‘tempDataStore’ to [1,3] and then try to change the value of the second element of the array – theItem.tempDataStore[1] = 1; – the value doesn’t change.
So, here is my code:

Event Filter: menuTest*, selected, enableMenus

Code (]if (theItem.eventCode == "enableMenus")
{
 theItem.tempDataStore = [1,3):

;
}
else if (theItem.eventCode == "menuTest1")
{
 if ( theItem.tempDataStore[1] == 3) {
  theItem.tempDataStore[1] = 1;
 }
else if ( theItem.tempDataStore[1] == 1) {
  theItem.tempDataStore[1] = 3;
}
  alert("menuTest 1 was selected\ntempDataStore[1] = " + theItem.tempDataStore[1]);
}
else if (theItem.eventCode == "menuTest2")
{
 alert("menuTest 2 was selected");
}
else if (theItem.eventCode == "selected")
{
 app.registerMenuItem ("menuTest1","Main:0x90B50kActivePageItemMenuKey:Menutest 1");
 app.registerMenuItem ("menuTest2","Main:0x90B50kActivePageItemMenuKey:Menutest 2");
 theItem.setDataStore("$GROUP_EVENTS$",true);
 alert("Menu Items have been added");
}


What am I missing here?

Kasyan

Title: Re: Creating menus
Post by Kris Coppieters on 01/05/09 at 22:39:31
Hi Kasyan,

Don't treat theItem.tempDataStore where theItem is the scripted plugin as a 'regular' property.

Try to keep the menu array in some other storage, and assign a copy of it to tempDataStore as a return value when needed.

For example, something like:

...
var menuState = [1 ,3];
theItem.setDataStore("com.kasyan.menustate",menuState,1);
...

... later ...
// .slice(0) below is probably not needed
// Fetch saved state and change it. Then re-save it.
var menuState = theItem.getDataStore("com.kasyan.menustate",1).slice(0);
menuState[1] = 1;
theItem.setDataStore("com.kasyan.menustate",menuState,1);
// Return data to caller
theItem.tempDataStore = menuState;

I've not tried any of the above code - give it a go and let me know if that works better.

Title: Re: Creating menus
Post by Kasyan on 01/07/09 at 05:49:40
Hi Kris,

I’ve got it! Now, when you told me this, I recollect that I read, in adobe forum, about the similar situation with ‘geometricBounds’ property: if a property is an array, then you must set it using an array. You can read the individual members of the array, but you can't write them.
I’m posting the working code in case somebody is interested to see it:

Event Filter: menuTest*, selected, enableMenus

Code (]if (theItem.eventCode == "enableMenus")
{
 if (theItem.tempDataStore == undefined) {
   alert("tempDataStore is undefined, going to set initial values");
   var menuState = [1,3):

;
   theItem.tempDataStore = menuState;
 }
}
else if (theItem.eventCode == "menuTest1")
{
 var menuState = theItem.tempDataStore;
 if (menuState[1] == 3) {
   menuState[1] = 1;
 }
 else if (menuState[1] == 1) {
   menuState[1] = 3;
 }
 theItem.tempDataStore = menuState;
 if (theItem.tempDataStore[1] == 1) {
   alert("menuTest 1 was unchecked");
 }
 else {
   alert("menuTest 1 was checked");
 }
}
else if (theItem.eventCode == "menuTest2")
{
 alert("menuTest 2 was selected");
}
else if (theItem.eventCode == "selected")
{
 app.registerMenuItem ("menuTest1","Main:0x90B50kActivePageItemMenuKey:Menutest 1");
 app.registerMenuItem ("menuTest2","Main:0x90B50kActivePageItemMenuKey:Menutest 2");
 theItem.setDataStore("$GROUP_EVENTS$",true);
 alert("Menu Items have been added");
}


Thank you, Kris. I would have never solved it without your help.

Kasyan

Message Board for Rorohiko Workflow Resources » Powered by YaBB 2.5.2!
YaBB Forum Software © 2000-2024. All Rights Reserved.