Author Topic: JSR : Opening a second dialog window from 'within' another  (Read 5961 times)

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Hi all,

I wonder whether anyone can help here.

I an reasonably happy about opening a single dialog window within JSR - there are plenty examples here on the Forum and in the sample scripts supplied with PI v1.4.

However, what I want to do is to have a PushButton on one dialog window provide access to a second window - to allow configuration for example, without cluttering up the first window by trying to put ALL the controls on one pane.

I can see how to do this (maybe) using 'dialogue.done()' in some way [ however, at the same time I cannot understand the difference between dialog.ok() and dialog.execute(), so maybe I will have no chance using dialog.done()  :'( ]

Has anyone got any ideas?

The basic code I am playing with (until I can sort out the error, and therefore re-incorporate the idea into my main deBayering Script) is as follows :-

Quote

#include <pjsr/Sizer.jsh>
#include <pjsr/StdButton.jsh>

console.writeln("Global : Defining prototypes");
mainDialog.prototype = new Dialog;
secondaryDialog.prototype = new Dialog;

console.writeln("Global : Entering main loop");
void main();
console.writeln("Global : End of Script");

function mainDialog()
{
   this.__base__ = Dialog;
   this.__base__();

   var setupDialog = new secondaryDialog();
   console.writeln("mainDialog() : Setup dialog instantiated");

   var lvTest = 123;
   console.writeln("mainDialog() : Local Variable defined as ",lvTest);

   this.Setup_Button = new PushButton( this );
   this.Setup_Button.text = " Set Options ";

   this.Setup_Button.onClick = function()
   {
      console.writeln("mainDialog() : 'Set Options' button pressed");
      // THE FOLLOWING LINE DOESN'T WORK AS IT SEEMS UNABLE TO ACCESS THE CONTENTS OF THE VARIABLE
      //console.writeln("mainDialog() : Local variable is = ", lvTest);

/*
      THIS ENTIRE SECTION OF CODE DOESN'T SEEM TO WORK AT ALL
      WHICH MAKES ME THINK THAT I   C A N N O T   HAVE THIS TYPE OF CODE WITHIN A DIALOG() FUNCTION
      HOWEVER, THIS LEAVES ME THINKING THAT I HAVE TO BE ABLE TO DETECT THE BUTTON PUSH FROM THE
      'CALLING' FUNCTION - IN THIS CASE, main(). IF SO, THEN HOW DO I PASS BACK TO 'main()' THE FACT
      THAT A BUTTON OTHER THAN 'OK' OR 'CANCEL' WAS PRESSED ?
     
      for ( ; ; )
      {
         if ( setupDialog.execute() )
         {
            console.writeln ("Secondary Dialog 'OK' pressed");
            break;
         }
         break;
      }
      console.writeln ("Secondary Dialog closed");
*/

   }

   this.ok_Button = new PushButton( this );
   this.ok_Button.text = " OK ";
   this.ok_Button.onClick = function()
   {
      this.dialog.ok();
   }

   this.cancel_Button = new PushButton( this );
   this.cancel_Button.text = " Cancel ";
   this.cancel_Button.onClick = function()
   {
      this.dialog.cancel();
   }

   this.buttons_Sizer = new HorizontalSizer;
   this.buttons_Sizer.spacing = 8;
   this.buttons_Sizer.add( this.Setup_Button );
   this.buttons_Sizer.addStretch();
   this.buttons_Sizer.add( this.ok_Button );
   this.buttons_Sizer.add( this.cancel_Button );
   this.sizer = new VerticalSizer;
   this.sizer.margin = 8;
   this.sizer.spacing = 6;
   this.sizer.add( this.buttons_Sizer );
   this.windowTitle = "Main";
   this.adjustToContents();
}

function secondaryDialog()
{
   this.__base__ = Dialog;
   this.__base__();

   this.ok_Button = new PushButton( this );
   this.ok_Button.text = " OK ";
   this.ok_Button.onClick = function()
   {
      this.dialog.ok();
   }

   this.cancel_Button = new PushButton( this );
   this.cancel_Button.text = " Cancel ";
   this.cancel_Button.onClick = function()
   {
      this.dialog.cancel();
   }

   this.buttons_Sizer = new HorizontalSizer;
   this.buttons_Sizer.spacing = 8;
   this.buttons_Sizer.addStretch();
   this.buttons_Sizer.add( this.ok_Button );
   this.buttons_Sizer.add( this.cancel_Button );
   this.sizer = new VerticalSizer;
   this.sizer.margin = 8;
   this.sizer.spacing = 6;
   this.sizer.add( this.buttons_Sizer );
   this.windowTitle = "Setup";
   this.adjustToContents();
}

function main()
{
   console.show
   console.abortEnabled = true;

   console.writeln("main() : Instantiating First dialog");
   var firstDialog = new mainDialog ();
   console.writeln("main() : First dialog instantiated");

   for ( ; ; )
   {
      if ( firstDialog.execute() )
      {
         console.writeln ("main() : Main Dialog 'OK' pressed");
         continue;
      }
      console.writeln ("main() : Main Dialog closed");
      break;
   }
   console.writeln ("main() : Script completed");
}


Help would certainly be appreciated.

Cheers,

Niall
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
Re: JSR : Opening a second dialog window from 'within' another
« Reply #1 on: 2009 May 03 13:12:56 »
Sorry, can't help you. I downloaded and twisted your code a bit to no avail.

What I have thought for a future script of mine that needed many parameters, was using a TabBox. Have you considered that? It seems friendlier than a series of nested dialogs to me (ever went throught that "click OK three times" mantra? ;)).
--
 David Serrano

Offline Niall Saunders

  • PTeam Member
  • PixInsight Jedi Knight
  • *****
  • Posts: 1456
  • We have cookies? Where ?
Re: JSR : Opening a second dialog window from 'within' another
« Reply #2 on: 2009 May 03 13:36:39 »
Hi David,

Thanks for 'having a look'

Yes, whilst I was waiting for an answer, I had a look at ALL of the processes available on the JSR 'sidebar' - and I did, briefly, consider the 'TABS' option. However, I haven't seen any examples of the use of TABS in the sample modules, so I will probably have to re-invent that wheel as well  :sad:

In the meantime, I think I will just create the dialog layout anyway - I feel sure that the fundamental constructs will be just as applicable in a TAB environment, so I might as well sort all that code out anyway.

Hopefully Juan will catch up soon, and hopefully I won't have gone down any 'dead ends' code-wise.

Cheers,
Cheers,
Niall Saunders
Clinterty Observatories
Aberdeen, UK

Altair Astro GSO 10" f/8 Ritchey Chrétien CF OTA on EQ8 mount with homebrew 3D Balance and Pier
Moonfish ED80 APO & Celestron Omni XLT 120
QHY10 CCD & QHY5L-II Colour
9mm TS-OAG and Meade DSI-IIC

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Re: JSR : Opening a second dialog window from 'within' another
« Reply #3 on: 2009 May 05 00:39:27 »
Hi Niall,

Here we go. Watch the comments tagged with the "###" sequence.

Code: [Select]
#include <pjsr/Sizer.jsh>
#include <pjsr/StdButton.jsh>

console.writeln("Global : Defining prototypes");
mainDialog.prototype = new Dialog;
secondaryDialog.prototype = new Dialog;

console.writeln("Global : Entering main loop");
void main();
console.writeln("Global : End of Script");

function mainDialog()
{
   this.__base__ = Dialog;
   this.__base__();

/*
   ### The following code doesn't work as intended; see replacement below.
   
   var setupDialog = new secondaryDialog();
*/
   this.setupDialog = new secondaryDialog( this ); // ### setupDialog is now a property of mainDialog
   console.writeln("mainDialog() : Setup dialog instantiated");

   var lvTest = 123;
   console.writeln("mainDialog() : Local Variable defined as ",lvTest);

   this.Setup_Button = new PushButton( this );
   this.Setup_Button.text = " Set Options ";

   this.Setup_Button.onClick = function()
   {
      console.writeln("mainDialog() : 'Set Options' button pressed");
      // THE FOLLOWING LINE DOESN'T WORK AS IT SEEMS UNABLE TO ACCESS THE CONTENTS OF THE VARIABLE

/*
   ### Of course, lvTest is not available here because this function is an
       event handler. This function will be called only when the Setup_Button
       is clicked, and when that happens, lvTest doesn't exist since it is
       local to mainDialog()'s constructor. We could say that lvTest is a
       "private member" of mainDialog.

       Either declare lvTest as a global variable, or make it available as a
       property of mainDialog.
*/
      //console.writeln("mainDialog() : Local variable is = ", lvTest);

/*
      THIS ENTIRE SECTION OF CODE DOESN'T SEEM TO WORK AT ALL
      WHICH MAKES ME THINK THAT I   C A N N O T   HAVE THIS TYPE OF CODE WITHIN A DIALOG() FUNCTION
      HOWEVER, THIS LEAVES ME THINKING THAT I HAVE TO BE ABLE TO DETECT THE BUTTON PUSH FROM THE
      'CALLING' FUNCTION - IN THIS CASE, main(). IF SO, THEN HOW DO I PASS BACK TO 'main()' THE FACT
      THAT A BUTTON OTHER THAN 'OK' OR 'CANCEL' WAS PRESSED ?
*/

/*
   ### That happened for the same reason as above: setupDialog was declared as a
       private variable of mainDialog's constructor. I replaced it above by a
       declaration as a property of mainDialog, so it works fine now.

       Note that since setupDialog is a property of Setup_Button's *parent*
       control, we must access it through its window or dialog properties. Both
       properties provide access to a control's top-level parent control.
*/
     
      for ( ;; )
      {
         if ( this.dialog.setupDialog.execute() )
         {
            console.writeln ("Secondary Dialog 'OK' pressed");
            break;
         }
         break;
      }
      console.writeln ("Secondary Dialog closed");

   }

   this.ok_Button = new PushButton( this );
   this.ok_Button.text = " OK ";
   this.ok_Button.onClick = function()
   {
      this.dialog.ok();
   }

   this.cancel_Button = new PushButton( this );
   this.cancel_Button.text = " Cancel ";
   this.cancel_Button.onClick = function()
   {
      this.dialog.cancel();
   }

   this.buttons_Sizer = new HorizontalSizer;
   this.buttons_Sizer.spacing = 8;
   this.buttons_Sizer.add( this.Setup_Button );
   this.buttons_Sizer.addStretch();
   this.buttons_Sizer.add( this.ok_Button );
   this.buttons_Sizer.add( this.cancel_Button );
   this.sizer = new VerticalSizer;
   this.sizer.margin = 8;
   this.sizer.spacing = 6;
   this.sizer.add( this.buttons_Sizer );
   this.windowTitle = "Main";
   this.adjustToContents();
}

function secondaryDialog( w )
{
   this.__base__ = Dialog;
   this.__base__();

/*
   ### Anchor this dialog 32 pixels from the top-left corner of the parent
       dialog. This improves visual identification of dialog hierarchy.
*/
   this.parentWindow = w;

   this.onShow = function()
   {
      var p = new Point( this.parentWindow.position );
      p.moveBy( 32 );
      // ### Unfortunately, the PJSR in PI 1.4 has a bug that prevents correct
      //     assignment of the Control.position property. This has been fixed
      //     in PI 1.5. The workaround is to use the Control.move() function.
      //this.position = p;
      this.move( p );
   }

   this.ok_Button = new PushButton( this );
   this.ok_Button.text = " OK ";
   this.ok_Button.onClick = function()
   {
      this.dialog.ok();
   }

   this.cancel_Button = new PushButton( this );
   this.cancel_Button.text = " Cancel ";
   this.cancel_Button.onClick = function()
   {
      this.dialog.cancel();
   }

   this.buttons_Sizer = new HorizontalSizer;
   this.buttons_Sizer.spacing = 8;
   this.buttons_Sizer.addStretch();
   this.buttons_Sizer.add( this.ok_Button );
   this.buttons_Sizer.add( this.cancel_Button );
   this.sizer = new VerticalSizer;
   this.sizer.margin = 8;
   this.sizer.spacing = 6;
   this.sizer.add( this.buttons_Sizer );
   this.windowTitle = "Setup";
   this.adjustToContents();
}

function main()
{
   console.show
   console.abortEnabled = true;

   console.writeln("main() : Instantiating First dialog");
   var firstDialog = new mainDialog ();
   console.writeln("main() : First dialog instantiated");

   for ( ; ; )
   {
      if ( firstDialog.execute() )
      {
         console.writeln ("main() : Main Dialog 'OK' pressed");
         continue;
      }
      console.writeln ("main() : Main Dialog closed");
      break;
   }
   console.writeln ("main() : Script completed");
}

Now it works fine. A series of dialogs is a good option, IMO. It helps to have them visually positioned forming a "cascade". I've added an onShow() function to your secondaryDialog to accomplish this feature.

As David has said, a TabBox control is also an interesting alternative. It's quite easy to use. Just define your tab pages as Control objects, and add them to a TabBox using this function:

Code: [Select]
void TabBox.addPage( Control page, String label[, Bitmap icon] )
Hope this helps.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/