Hello altogether, I've a problem with the createItem function parameter "int mappingFunction()". This function is used to control the state of the created menu entry (available or not, invisible, checked) and works well, if I've nothing special to do.
Example: // some DXL script in the lib/dxl/startupfiles folder int GetState() { return menuAvailableChecked_; } // some DXL script in the lib/dxl/config/formalPopupFiles folder createMenu(alwaysOn, "MyMenue", 'M', null) createItem(GetState, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); end menu
The context menu within a formal module gets a checked menu item "Test".
Example: // some DXL script in the lib/dxl/startupfiles folder string g_Str1 = ""; string g_Str2 = ""; void SetString1 (string s) { print "SetString1('" s "')\n"; g_Str1 = s; } void SetString2 (string s) { print "SetString2('" s "')\n"; g_Str2 = s; } int GetState() { print "GetState: <" g_Str1 ">, <" g_Str2 ">\n"; if (0 == cistrcmp(g_Str1, g_Str2)) return menuAvailable_; else return menuAvailableChecked_; } // some DXL script in the lib/dxl/config/formalPopupFiles folder createMenu(alwaysOn, "MyMenue", 'M', null) SetString1("Hallo") SetString2("Hello") createItem(GetState, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); SetString2("Hallo") createItem(GetState, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); end menu
SetString1('Hallo') SetString2('Hello') SetString2('Hallo')
GetState: <Hallo>, <Hallo>
Best regards,
Michael MichaelBrockhaus - Mon Apr 03 07:54:55 EDT 2017 |
Re: Dynamic control of menu creation Obviously you need to store the values, since as you already found out, the time when you call "createMenu" and the time, when getState is invoked are different. Since insertMenu does not return a value to you, that you could use to find out, which menu was invoked inside the getState call, you probably need to resolve to one function per Menu item ... int GetState(string g_Str1, g_Str2) { print "GetState: <" g_Str1 ">, <" g_Str2 ">\n"; if (0 == cistrcmp(g_Str1, g_Str2)) return menuAvailable_; else return menuAvailableChecked_; } int GetStateMenu1() { return getState("Hello", "Hallo"); } createItem(GetStateMenu1, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); int GetStateMenu2() { return getState("Hello", "Hello"); } createItem(GetStateMenu2, "Test2", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); This is probably the cleanest way do solve this. You can try eval_ but I got the feeling you will be in for some crashes. Hope this helps, Regards, Mathias |
Re: Dynamic control of menu creation Mathias Mamsch - Mon Apr 03 08:59:38 EDT 2017 Obviously you need to store the values, since as you already found out, the time when you call "createMenu" and the time, when getState is invoked are different. Since insertMenu does not return a value to you, that you could use to find out, which menu was invoked inside the getState call, you probably need to resolve to one function per Menu item ... int GetState(string g_Str1, g_Str2) { print "GetState: <" g_Str1 ">, <" g_Str2 ">\n"; if (0 == cistrcmp(g_Str1, g_Str2)) return menuAvailable_; else return menuAvailableChecked_; } int GetStateMenu1() { return getState("Hello", "Hallo"); } createItem(GetStateMenu1, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); int GetStateMenu2() { return getState("Hello", "Hello"); } createItem(GetStateMenu2, "Test2", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); This is probably the cleanest way do solve this. You can try eval_ but I got the feeling you will be in for some crashes. Hope this helps, Regards, Mathias Hi, thank you for your fast response. I'm a little bit confused, because the reference manual says: "Mapping functions have to be defined in a file inside $DOORSHOME\lib\dxl\startupfiles and cannot be in the same file as the perms that call them." and the functions GetStateMenu1() and GetStateMenu2() are defined the same file as the calling perms are defined!? Nevertheless, there happened one improvement: DOORS isn'r crashing anymore. But I'll receive two error messages, when using the demo files of your post: -R-E- DXL: <Line:0> incorrect return statement -R-E- DXL: <Line:0> incorrect return statement Do you know why? I'm now using these lines of code: int getState(string g_Str1, g_Str2) { print "GetState: <" g_Str1 ">, <" g_Str2 ">\n"; if (0 == cistrcmp(g_Str1, g_Str2)) return menuAvailable_; else return menuAvailableChecked_; } createMenu(alwaysOn, "MyMenueEntry", 'M', null) int GetStateMenu1() { return getState("Hello", "Hallo"); } createItem(GetStateMenu1, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); int GetStateMenu2() { return getState("Hello", "Hello"); } createItem(GetStateMenu2, "Test2", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); end menu Even the print command in the getState function will not be executed (respectively I don't get an "GetState:..." Output in the DXL interaction window) Best regards, Michael |
Re: Dynamic control of menu creation MichaelBrockhaus - Mon Apr 03 10:11:18 EDT 2017 Hi, thank you for your fast response. I'm a little bit confused, because the reference manual says: "Mapping functions have to be defined in a file inside $DOORSHOME\lib\dxl\startupfiles and cannot be in the same file as the perms that call them." and the functions GetStateMenu1() and GetStateMenu2() are defined the same file as the calling perms are defined!? Nevertheless, there happened one improvement: DOORS isn'r crashing anymore. But I'll receive two error messages, when using the demo files of your post: -R-E- DXL: <Line:0> incorrect return statement -R-E- DXL: <Line:0> incorrect return statement Do you know why? I'm now using these lines of code: int getState(string g_Str1, g_Str2) { print "GetState: <" g_Str1 ">, <" g_Str2 ">\n"; if (0 == cistrcmp(g_Str1, g_Str2)) return menuAvailable_; else return menuAvailableChecked_; } createMenu(alwaysOn, "MyMenueEntry", 'M', null) int GetStateMenu1() { return getState("Hello", "Hallo"); } createItem(GetStateMenu1, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); int GetStateMenu2() { return getState("Hello", "Hello"); } createItem(GetStateMenu2, "Test2", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); end menu Even the print command in the getState function will not be executed (respectively I don't get an "GetState:..." Output in the DXL interaction window) Best regards, Michael I was mainly trying to solve the problem of having parametric behaviour of the getState() function, without realizing that there was an restriction to the definition of the mapping functions. I am not so deep into the menu creation logic, but - when the manual states as you say, then to me it seems, that the mapping functions need to be defined inside the global DXL context, while the createItem functions are called from a local DXL context. - In this case you would probably have to move the creation logic to the global DXL context, by defining it inside some file in the startupfiles. So something like this needs to go to the startupFiles: // startupFiles/myMenues.dxl int getState(...) { ... } int getStateMenu1 () { ... } int getStateMenu2 () { ... } and the createMenu code somewhere else, e.g. inside dxl/config/formalFiles: createMenu(alwaysOn, "MyMenue", 'M', null) createItem(GetStateMenu1, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); createItem(getStateMenu2, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); end menu While this tear apart of functionality is unfortunate - other plugins seem to solve this, but placing "include" statements inside the files, that both reference some addins directory. Regards, Mathias |
Re: Dynamic control of menu creation Mathias Mamsch - Mon Apr 03 10:41:30 EDT 2017 I was mainly trying to solve the problem of having parametric behaviour of the getState() function, without realizing that there was an restriction to the definition of the mapping functions. I am not so deep into the menu creation logic, but - when the manual states as you say, then to me it seems, that the mapping functions need to be defined inside the global DXL context, while the createItem functions are called from a local DXL context. - In this case you would probably have to move the creation logic to the global DXL context, by defining it inside some file in the startupfiles. So something like this needs to go to the startupFiles: // startupFiles/myMenues.dxl int getState(...) { ... } int getStateMenu1 () { ... } int getStateMenu2 () { ... } and the createMenu code somewhere else, e.g. inside dxl/config/formalFiles: createMenu(alwaysOn, "MyMenue", 'M', null) createItem(GetStateMenu1, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); createItem(getStateMenu2, "Test", 'M', null, null, null, null, "Demo", null, "C:\\tmp\\TextMsgBox.dxl"); end menu While this tear apart of functionality is unfortunate - other plugins seem to solve this, but placing "include" statements inside the files, that both reference some addins directory. Regards, Mathias Hm... Okay... Under these circumstances I've my initial problem, again :-) The idea was, that I'll outsource common functions in the startupfiles script and then call them from the specific config scripts (formalfiles, formalPopupFiles, baseWindowMenuFiles,..) and the "common" scripts will check, which menu state has to be returned. This seems not to be possible. Obviously I can 'control' the behaviour of the menus (formalfiles,...) from the startupfiles, but not vice versa because the config scripts will run only once... Probably I have to rethink my plans... Nevertheless, many thanks for your ideas. Regards, Michael |
Re: Dynamic control of menu creation MichaelBrockhaus - Tue Apr 04 06:47:30 EDT 2017 Hm... Okay... Under these circumstances I've my initial problem, again :-) The idea was, that I'll outsource common functions in the startupfiles script and then call them from the specific config scripts (formalfiles, formalPopupFiles, baseWindowMenuFiles,..) and the "common" scripts will check, which menu state has to be returned. This seems not to be possible. Obviously I can 'control' the behaviour of the menus (formalfiles,...) from the startupfiles, but not vice versa because the config scripts will run only once... Probably I have to rethink my plans... Nevertheless, many thanks for your ideas. Regards, Michael I am not sure I understand why this behaviour is a problem for you. In the end it boils down to "where do I need to put my code to make this work". You CAN control the behaviour of the menu from the config scripts (e.g. simple example: if user is not admin then disable this menu), but in addition to the code inside the config scripts you need to place the mapping functions corresponding to the menu items also in the startupfiles. If your problem is about passing state (variables) to the scripts in your menu, there is a couple of options to have a shared state (i.e. pass information from the local DXL context to the global context) - use simple types (integers, chars, booleans) do not allocate memory and can be saved inside global variables even from a local DXL context. You need to be very careful what you store in global variables, do not try strings, Buffers, etc. - files (write some data there, read it from the files from the startupfiles) - config area (type: confTemp ) for storing temporary data - environment variables (getenv / setenv) --> Warning: setenv will persist the data inside the registry, so it will be available after client restart. Maybe this helps, regards, Mathias |