Subdialog
-
On 18/11/2016 at 06:40, xxxxxxxx wrote:
Using ScottA's example I now see what is going wrong, but I cannot explain it.
The example is working correctly when using only 1 sub dialog.
It goes wrong when I open the sub dialog a second time.What I do:
In the main dialog:command I open a Modal sub dialog.
When it is closed, I do some code and open the same Modal sub dialog.
In the sub dialog command I get the input and Close() the sub dialog.This apparently this is not correct.
When I use Close(), the next sub dialog is empty.
When I remove the Close() and close the sub dialog by closing the sub dialog window, everything is correct!Also the manual states that Close() a Modal dialog is not needed.
However, I like to close the modal sub dialog after the users confirms his input with a button and not by closing the sub dialog window.Bool MyDialog::Command(Int32 id,const BaseContainer &msg) { switch (id) { case MY_BUTTON1: subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID); ... ... subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID); break; } return TRUE; } In the sub dialog: Bool SubDialog::Command(Int32 id, const BaseContainer& msg) { if (id == MY_BUTTONOSMOK) { //Close(); //here it goes wrong!!! return TRUE; } //# all other ID's return TRUE; } // end Command
-
On 18/11/2016 at 07:59, xxxxxxxx wrote:
It works fine for me in R13.
Try it like this: this->Close();The only problem I've had with Close() is that it didn't work on macs.
I don't know if Maxon ever fixed it.-ScottA
-
On 18/11/2016 at 08:45, xxxxxxxx wrote:
Hi ScottA,
Did you try it with 2 sub dialogs after each other?
So opening one, close it process it and then open the same one again.
For me that is the issue.I tried this->Close(), but that did not help.
-Pim
PS I am using R16
-
On 18/11/2016 at 09:13, xxxxxxxx wrote:
2 sub dialogs? Are you opening more than one sub dialog?
I'm using the code I posted to test it. Which has one main dialog and one sub dialog(another GeDialog).
I added a close button to the sub dialog.
When I close the sub dialog with it's close button. And re-open it again using the main dialog. The sub dialog is not empty. It's all still there and working as expected.-ScottA
-
On 18/11/2016 at 09:34, xxxxxxxx wrote:
I use the same sub dialog twice.
So, in the main dialog I open the sub dialog, do some processing and open the sub dialog once again. Both times in the command of the main dialog.Hope this explains.
Pim -
On 18/11/2016 at 10:02, xxxxxxxx wrote:
I don't understand why you are opening the same sub dialog when it's already open?
Or do you mean that you close the sub dialog, and then re-open it a second time?Either way.
If I open the sub dialog. And then try to open it again(even though it's already open). It still works as expected for me. The sub dialog never goes blank(shows no gizmos).Here is my plugin that you can test out.
No matter which buttons I use on either dialog. The sub dialog always works and never goes blank.
It should work in R16: http://www2.zippyshare.com/v/XVulPng9/file.html-ScottA
-
On 18/11/2016 at 11:24, xxxxxxxx wrote:
Yes, i close it and open it a second time.
(New input from the user).
Thanks for the plugin.Pim
-
On 19/11/2016 at 11:52, xxxxxxxx wrote:
Hi ScottA,
Here your original file with my additions to show the issue.
To make it working in R16:
- changed LONG to Int32
- changed gNew MyDialog_CMD to NewObjClear(MyDialog_CMD)
- added #include "c4d.h" in .h file- changed the sub dialog mode from DLG_TYPE_ASYNC to DLG_TYPE_MODAL
- add a second call to open the sub dialog for a second time:case MY_BUTTON1: subDlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID); subDlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID); break;
So far it is still working.
After closing the first (modal) sub dialog, the second one is displayed correctly.Now I want to close the Modal sub dialog, when the user entered his input.
So I add a Close() in the command of the sub dialogcase MY_CKBOX: GePrint("Enabled"); Close(); break;
Now, after the user entered his input, the first modal sub dialog is closed, but the second one opens up empty!
Here the full code.
The .h file #define ID_DIALOG 123456789 #include "c4d.h" class RenameDialogTest : public GeDialog { private: String name; public: virtual Bool CreateLayout(void); virtual Bool InitValues(void); virtual Bool Command(Int32 id, const BaseContainer& msg); Bool SetName(String name); String GetName(); }; class MainDialog : public GeDialog { private: RenameDialogTest dlgSub; public: virtual Bool CreateLayout(void); virtual Bool InitValues(void); virtual Bool CoreMessage(Int32 id, const BaseContainer& msg); virtual Bool Command(Int32 id, const BaseContainer& msg); }; class Dialog : public CommandData { private: MainDialog dlg; public: virtual Bool Execute(BaseDocument *doc); virtual Bool RestoreLayout(void *secret); }; The cpp file: //This plugin is an example of using a dialog with a SubDialog that can each be docked into the C4D UI //Then saved to a custom layout // be sure to use a unique ID obtained from www.plugincafe.com #define PLUGIN_ID 10000061 #define SUBDLG_ID 10000062 #include "c4d.h" #include "gui.h" //#include "c4d_symbols.h" <----Not used in this example. No .h files are used enum { MY_STATIC_TEXT = 10000, MY_CKBOX, INLINE_CKBOX, MY_BUTTON1, MY_BUTTON2 }; enum { MY_TEXT_GROUP = 20000, MY_BUTTON_GROUP }; //The sub dialog class MySubDialog : public GeDialog { public: MySubDialog(void); virtual Bool CreateLayout(void); virtual Bool InitValues(void); virtual Bool Command(Int32 id,const BaseContainer &msg); virtual Int32 Message(const BaseContainer &msg,BaseContainer &result); virtual Bool CoreMessage (Int32 id,const BaseContainer &msg); }; MySubDialog::MySubDialog(void) {} Bool MySubDialog::CreateLayout(void) { SetTitle("Sub Dialog"); GroupBegin(MY_TEXT_GROUP, BFH_SCALEFIT,2,0,"",0); { AddStaticText(MY_STATIC_TEXT,BFH_CENTER,200,15,"",0); AddCheckbox(MY_CKBOX, BFH_CENTER, 20, 20, "MyBox"); } GroupEnd(); GroupBeginInMenuLine(); //Adds the checkbox to the menu area of the dialog window AddCheckbox(INLINE_CKBOX,0,0,0, String("Reset")); GroupEnd(); return TRUE; } Bool MySubDialog::InitValues(void) { // first call the parent instance if (!GeDialog::InitValues()) return FALSE; SetString(MY_STATIC_TEXT, "Sub Dialog"); this->SetBool(MY_CKBOX, FALSE); this->SetBool(INLINE_CKBOX, FALSE); return TRUE; } Bool MySubDialog::Command(Int32 id,const BaseContainer &msg) { switch (id) { case INLINE_CKBOX: InitValues(); // Executes the InitValues() function to reset the values break; case MY_CKBOX: GePrint("Enabled"); Close(); //Added Pim break; } return TRUE; } Bool MySubDialog::CoreMessage(Int32 id,const BaseContainer &msg) { return GeDialog::CoreMessage(id,msg); } Int32 MySubDialog::Message(const BaseContainer &msg,BaseContainer &result) { return GeDialog::Message(msg,result); } //The master dialog that is used to open the MySubDialog dialog class MyDialog : public GeDialog { MySubDialog subDlg; INSTANCEOF(MyDialog, GeDialog); public: MyDialog(void); virtual Bool CreateLayout(void); virtual Bool InitValues(void); virtual Bool Command(Int32 id,const BaseContainer &msg); virtual Int32 Message(const BaseContainer &msg,BaseContainer &result); virtual Bool CoreMessage (Int32 id,const BaseContainer &msg); virtual Int32 MyDialog::RestoreLayout(Int32 pluginid, Int32 subid, void *secret); }; MyDialog::MyDialog(void) {} Bool MyDialog::CreateLayout(void) { SetTitle("Main Dialog"); GroupBegin(MY_TEXT_GROUP, BFH_SCALEFIT,2,0,"",0); { AddStaticText(MY_STATIC_TEXT,BFH_CENTER,80,15,"",0); } GroupEnd(); GroupBegin(MY_BUTTON_GROUP, BFH_SCALEFIT,2,0,"",0); { AddButton(MY_BUTTON1,BFH_LEFT,100,15,"Open SubDlg"); AddButton(MY_BUTTON2,BFH_LEFT,100,15,"Change SubDlg"); } GroupEnd(); return TRUE; } Bool MyDialog::InitValues(void) { // first call the parent instance if (!GeDialog::InitValues()) return FALSE; SetBool(1001,FALSE); SetString(MY_STATIC_TEXT, "Hello"); return TRUE; } Bool MyDialog::Command(Int32 id,const BaseContainer &msg) { switch (id) { case MY_BUTTON1: subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID); //change Pim subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID); // Added Pim break; case MY_BUTTON2: subDlg.SetBool(MY_CKBOX, TRUE); break; } return TRUE; } Bool MyDialog::CoreMessage(Int32 id,const BaseContainer &msg) { return GeDialog::CoreMessage(id,msg); } Int32 MyDialog::Message(const BaseContainer &msg,BaseContainer &result) { return GeDialog::Message(msg,result); } //Restore the subdialog and the main dialog in the layout Int32 MyDialog::RestoreLayout(Int32 pluginid, Int32 subid, void *secret) { Int32 newsubid = ((RestoreLayoutSecret* )secret)->subid; if( newsubid == SUBDLG_ID ) return subDlg.RestoreLayout(PLUGIN_ID, pluginid, secret); //return MyDialog::RestoreLayout(PLUGIN_ID, 0, secret); //Used if INSTANCEOF(MyDialog, GeDialog); is not delared in the class return SUPER::RestoreLayout(PLUGIN_ID, 0, secret); } class MyDialog_CMD : public CommandData //MyDialog_CMD is the class name that needs to be listed in the main.cpp to register it properly { private: MyDialog dlg; public: virtual Bool Execute(BaseDocument *doc); virtual Int32 GetState(BaseDocument *doc); virtual Bool RestoreLayout(void *secret); }; Int32 MyDialog_CMD::GetState(BaseDocument *doc) { return CMD_ENABLED; } Bool MyDialog_CMD::Execute(BaseDocument *doc) { return dlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID, -1, -1, 300, 150); } Bool MyDialog_CMD::RestoreLayout(void *secret) { return dlg.RestoreLayout(PLUGIN_ID, 0, secret); } Bool RegisterMyDialog_CMD(void) { String help = "Dockable Subdialog Example"; //The help text displayed at the bottom of the C4D UI return RegisterCommandPlugin(PLUGIN_ID, "Dockable Subdialog",0, nullptr, help, NewObjClear(MyDialog_CMD)); }
The above code example is a bit silly, but the idea is that the user should enter his data using the same sub dialog twice.
Hope you can help me.
If not, the user has to close the sub dialog by closing its window, before he can continue.
In Python it is working!-Pim
-
On 19/11/2016 at 11:55, xxxxxxxx wrote:
Originally posted by xxxxxxxx
It should work in R16: http://www2.zippyshare.com/v/XVulPng9/file.html
I could not download this file.
It kept asking me to download other files, before I was allowed to download your file.-Pim
-
On 19/11/2016 at 12:59, xxxxxxxx wrote:
You're opening two sub dialogs that have the same ID# using MY_BUTTON1. That's a big no, no.
If you want to open 2 sub dialogs. You will need to create a class for each one of them, and give each one a unique ID# to avoid any clashing errors.
I don't know why it works in Python. But it really shouldn't.Can you post your R16 plugin with the source code anywhere?
I think it will be simpler to debug things having your actual plugin in hand.-ScottA
-
On 19/11/2016 at 16:01, xxxxxxxx wrote:
I am opening the same sub dialog. The dialogs that are opened after each other, are the same.
Here a link to a zip file with the R16 .h and .cpp file.
It is the same code as posted earlier.Note: I develop in R16, so it is supported under R16, R17 and R18.
-Pim
-
On 19/11/2016 at 19:47, xxxxxxxx wrote:
OK. I think I get it.
What you are doing seems a bit strange to me. But you must have your reasons for wanting to do it.Your sub dialog is a class. And just like any class. The way you use them is to make instances of the class. Then use those instances throughout your code.
So if you want to open the same sub dialog twice. You need to create two instances of it in your master dialog.
Right now you only have one instance and you're trying to use it twice, which is illegal.In your master dialog's class define a new sub dialog class instance
class MyDialog : public GeDialog { MySubDialog subDlg; MySubDialog subDlg2; //<---Add this to your code INSTANCEOF(MyDialog, GeDialog); //...the rest of the class code
Then open your new sub dialog instance
Bool MyDialog::Command(LONG id, const BaseContainer &msg) { switch (id) { case MY_BUTTON1: subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID, -1, -1, 200, 100, SUBDLG_ID); subDlg2.Open(DLG_TYPE_MODAL, PLUGIN_ID, -1, -1, 200, 100, SUBDLG_ID);//<---Like this break; case MY_BUTTON2: subDlg.SetBool(MY_CKBOX, TRUE); break; } return TRUE; }
That should prevent the second dialog from becoming empty when the first one is closed.
*But be warned. I don't think this is a good idea. I don't think these dialogs are meant to be used this way. I don't think they were designed to be created with multiple instances. The support guys can guide you better on that. It just seems wrong to me.
IMO. The better way to do this is to create another sub dialog class with it's own ID#. Then open them both the same way in your button code.-ScottA
-
On 20/11/2016 at 01:00, xxxxxxxx wrote:
Ok, I like your solution and I agree that the issue might be as you state:
"Right now you only have one instance and you're trying to use it twice, which is illegal."Until the support guys come with another solution, I will do as you suggest. Thanks.
Note: your solution works!
To explain my approach.
I have a plugin in which the user has to input an address and based on that input another address.
So sometimes one address and sometimes two addresses.
For both addresses I am using the sub dialog (seems logical to me).- show sub dialog
- user enters address
- store address.city in firstAddress
- close sub dialog- if firstAddress.city = Amsterdam
- show sub dialog (again)
- user enters second address
- store address.city in secondtAddress
- close sub dialog