What's the difference for the two methods of UI initiator?
I’m building a UI with a sub-dialog and need it to appear only when a user clicks a button. However, I’m encountering different behaviors with two different approaches.
Method 1: Delayed Creation (Works as Expected)
In this method, I create and show the sub-dialog only when the button is clicked:
Class MySub:UIFrame
{
Object Init(Object self)
{
TagGroup DLGitems = DLGCreateDialog("Sub")
TagGroup RadioList=DLGCreateRadioList()
RadioList.DLGAddRadioItem("option 1",1)
RadioList.DLGAddRadioItem("option 2",2)
RadioList.DLGAddRadioItem("option 3",3)
DLGitems.DLGAddElement(RadioList)
Return self.super.Init(DLGitems)
}
}
Class MyMain:UIFrame
{
Object SubDialog
Void CallSubDialog(Object self)
{
Result("\nOpen sub-dialog.")
SubDialog.Pose() // call the local object
self.LookUpElement("Label").DLGTitle("option chosen")
}
Object Init(Object self, Object SDpass)
{
SubDialog = SDpass // Keep the object in a local variabl
TagGroup DLGitems = DLGCreateDialog("Main")
DLGitems.DLGAddElement(DLGCreateLabel("choose option").DLGIdentifier("Label"))
DLGitems.DLGAddElement(DLGCreatePushButton("Options","CallSubDialog"))
Return self.super.Init(DLGitems)
}
}
Object SubDialogOBJ = Alloc(MySub).Init() // Initialize the sub-dialog object in the main script
Object DialogOBJ = Alloc(MyMain).Init(SubDialogOBJ) // Pass on the object into the other
DialogOBJ.Display("Dialog")
Method 2: Immediate Creation in the Constructor (Unexpected Behavior)
Here, I initialize and show the sub-dialog in the constructor, which causes the sub-dialog to display as soon as the script runs:
Class MySub:UIFrame
{
TagGroup gen_MySubUI_dlg(Object self)
{
TagGroup DLGitems = DLGCreateDialog("Sub")
TagGroup RadioList=DLGCreateRadioList()
RadioList.DLGAddRadioItem("option 1",1)
RadioList.DLGAddRadioItem("option 2",2)
RadioList.DLGAddRadioItem("option 3",3)
DLGitems.DLGAddElement(RadioList)
Return DLGitems
}
MySub(Object self)
{
self.init(self.gen_MySubUI_dlg())
self.Display("MySubUI")
}
~MySub(Object self)
{
Result("Quit" + "\n")
}
}
Class MyMain:UIFrame
{
Object SubDialog
Void CallSubDialog(Object self)
{
Result("\nOpen sub-dialog.")
SubDialog.Pose() // call the local object
self.LookUpElement("Label").DLGTitle("option chosen")
}
Object Init(Object self, Object SDpass)
{
SubDialog = SDpass // Keep the object in a local variabl
TagGroup DLGitems = DLGCreateDialog("Main")
DLGitems.DLGAddElement(DLGCreateLabel("choose option").DLGIdentifier("Label"))
DLGitems.DLGAddElement(DLGCreatePushButton("Options","CallSubDialog"))
Return self.super.Init(DLGitems)
}
}
Object SubDialogOBJ = Alloc(MySub) // Initialize the sub-dialog object in the main script
Object DialogOBJ = Alloc(MyMain).Init(SubDialogOBJ) // Pass on the object into the other
DialogOBJ.Display("Dialog")
Questions:
Primary Question:
Additional Question:
Class MySub:UIFrame
{
TagGroup gen_MySubUI_dlg(Object self)
{
TagGroup DLGitems = DLGCreateDialog("Sub")
TagGroup RadioList=DLGCreateRadioList()
RadioList.DLGAddRadioItem("option 1",1)
RadioList.DLGAddRadioItem("option 2",2)
RadioList.DLGAddRadioItem("option 3",3)
DLGitems.DLGAddElement(RadioList)
Return DLGitems
}
MySub(Object self)
{
self.init(self.gen_MySubUI_dlg())
self.Display("MySubUI")
}
~MySub(Object self)
{
Result("Quit" + "\n")
}
}
Class MyMain:UIFrame
{
Object SubDialog
Void CallSubDialog(Object self)
{
Result("\nOpen sub-dialog.")
Alloc(MySub) // call the local object
}
Object Init(Object self)
{ // Keep the object in a local variabl
TagGroup DLGitems = DLGCreateDialog("Main")
DLGitems.DLGAddElement(DLGCreateLabel("choose option").DLGIdentifier("Label"))
DLGitems.DLGAddElement(DLGCreatePushButton("Options","CallSubDialog"))
Return self.super.Init(DLGitems)
}
}
Object DialogOBJ = Alloc(MyMain).Init() // Pass on the object into the other
DialogOBJ.Display("Dialog")
What I’ve Tried:
Any insights into the differences in these initialization methods and help identifying the error in the third example would be greatly appreciated.
I do not quite understand your question. In your 2nd code you call self.Display
in the constructor, so naturally the dialog gets immediately displayed?
Maybe you need to understand the concept of a constructor
method better?
This method is called (i.e. the code is run) the moment the object is created in memory, i.e. when you call Alloc(mySub)
you create the object of class 'mySub' in memory, which invokes its constructor method.
I'm adding an example of what you might want to do: Allocate the sub-dialog while the main script is still in scope, but do not display it. Instead, hold it as member variable of the the main dialog and display when the button is pressed (in the "OnButtonPressed" action method).
There are different ways that could be done:
// On the main script:
object sub = Alloc(sub)
object main = Alloc(main)
main.SetSubDlg(sub) // SetSubDlg is a custom method that stores into a member variable
main.LaunchDisplay() // LaunchDisplay is a custom method that shows the main dialog.
class CSubDialog : UIframe
{
number CreateAndPose(object self)
{
TagGroup dlg,dlgitems
dlg = DLGCreateDialog("SubDialog",dlgitems)
dlgItems.DLGAddElement(DLGCreateLabel("I'm the sub dialog."))
return self.init(dlg).pose()
}
}
class CMainDialog : UIframe
{
object subDlg
CMainDialog(object self)
{
// The constructor of CMainDialg is called as soon as the
// Alloc(CMainDialog) in the main program is called.
// At this time, the whole script code is still in scope
// so the subDLG can be allocated. Just hold it as member
// of this dialog.
subDlg = Alloc(CSubDialog)
}
void OnLaunchSub(object self)
{
// Safer coding: Check that the member variable is
// holding a valid object.
if ( !subDlg.ScriptObjectIsValid() ) throw( "No Sub dialog found." )
// Further safety, check if is of the correct class (All lower case!)
if ("csubdialog" != subDLG.ScriptObjectGetClassName()) throw( "Wrong object." )
subDLG.CreateAndPose()
}
object CreateAndDisplay(object self)
{
TagGroup dlg,dlgitems
dlg = DLGCreateDialog("Main Dialog",dlgitems)
dlgItems.DLGAddElement(DLGCreateLabel("I'm the main dialog."))
dlgItems.DLGAddElement(DLGCreatePushButton("Launch","OnLaunchSub"))
self.init(dlg).display("Main Dialog")
return self
}
}
Alloc(CMainDialog).CreateAndDisplay()