#1383 js: fwt dialogs are not truely modal

ilya Wed 12 Jan 2011

And one more strange thing in js. If we try to make some fwt dialogs conditional behaviour like

if (Dialog.openQuestion(e.window, "0", Dialog.yesNo) == null)
{
  Dialog.openInfo(e.window, "1")
  Dialog.openInfo(e.window, "2")
  Dialog.openQuestion(e.window, "3", Dialog.yesNo)    
  Dialog.openQuestion(e.window, "4", Dialog.yesNo)    
}

we'll get all the dialog boxes at once, because the execution will not stop when a dialog shows up and will continue with the null result of the openQuestion function. So we will see all five dialogs in stack.

Still, the more dialogs are stacked, the more dark colored background is...

App was launched by FireFox Namoroka 3.6.3 64-bit

andy Wed 12 Jan 2011

Yeah that is a side-effect of browser's (non-threaded) event-driven design JsVMs. We can't actually block - since that would lock up the browser. So code will continue to execute after Dialog.open. This is the convention I use:

Dialog(window)
{
  ...
  onClose.add |e|
  {
    // run code after dialog closes
  }
}.open

// anything here will run right after dlg opens

ilya Thu 13 Jan 2011

Thanks, @andy, now I see the reason.

Still I hadn't got a clue how to read the dialog result in onClose event, is it possible to?

I had to do a subclass to handle that conditional behaviour

@Js
class DialogWithAfterClose : Dialog
{
  new make(Window? parent) : super(parent) { }

  |Obj?->Void|? afterClose := null

  override Void close(Obj? result := null)
  {
    super.close(result)
    if (afterClose != null) afterClose(result)
  }
}

and

@Js
class JsDialog
{
//////////////////////////////////////////////////////////////////////////
// Message Boxes Alternatives for Js
//////////////////////////////////////////////////////////////////////////

  **
  ** Open an information message box.  See `openMsgBox`.
  **
  static Obj? openInfo(Window? parent, Str msg, Obj? details := null,
                      Command[] commands := [Dialog.ok], |Obj?->Void|? afterClose := null)
  {
    return openMsgBox(Dialog#.pod, "info", parent, msg, details, commands, afterClose)
  }

  ... skip similar obvious details


  static Obj? openMsgBox(Pod pod, Str keyBase, Window? parent, Obj body,
                         Obj? details := null, Command[] commands := [Dialog.ok], |Obj?->Void|? afterClose := null)
  {
    // get localized props
    title := pod.locale("${keyBase}.name")
    locImage := pod.locale("${keyBase}.image")
    Image? image
    try { image = Image(locImage.toUri) } catch {}

    // swizzle details if passed commands
    if (details is Command[]) { commands = details; details = null }

    // swizzle details if passed Func
    if (details is Func) { afterClose = details; details = null }

    dialog := DialogWithAfterClose(parent)
    {
      it.title    = title
      it.image    = image
      it.body     = body
      it.details  = details
      it.commands = commands
      it.afterClose = afterClose
    }
    return dialog.open
  }
}

And after that the following code works fine

JsDialog.openQuestion(e.window, "0", null, Dialog.yesNo) 
|Obj? res|
{
  if (res == Dialog.yes) 
  {
    JsDialog.openInfo(e.window, res?.toStr ?: "null") 
    |Obj? res1|
    {
      JsDialog.openInfo(e.window, "2") 
      |Obj? res2|
      {
        JsDialog.openQuestion(e.window, "3", null, Dialog.yesNo) 
        |Obj? res3|
        {
          JsDialog.openInfo(e.window, res3?.toStr ?: "null")
        }
      }
    }
  }
}

andy Thu 13 Jan 2011

Still I hadn't got a clue how to read the dialog result in onClose event, is it possible to?

The command that was invoked to close the dialog is passed in Event.data:

Dialog(window)
{
  ...
  commands = Dialog.okCancel
  onClose.add |e|
  {
    if (e.data != Dialog.ok) return
    ...
  }
}

The Dialog.openXXX shortcuts don't work well with this model at the moment. So if you want to poll for their result, you would need to roll your own.

ilya Thu 13 Jan 2011

Thanks, @andy, seems now I'll just add |Event->Void|? onClose := null params to my JSDialog util wrap class and add

if (onClose != null) it.onClose.add(onClose)

to Dialog creation in JSDialog.openMsgBox, and it will handle the work I need...

I would appreciate if such functionality is added to the mentioned Dialog.openXXX shortcuts, seems it wouldn't break any existing code and it will provide a Dialog shortcuts closure style invocation with the same behaviour on all platforms.

brian Thu 13 Jan 2011

I personally find the lack of modal dialogs a real stumbling block. As a hardcore FWT programmer on the desktop, but casual FWT programmer for browser coder, I screw up every time.

The end game here for everything is going to have to be:

  1. Make everything work
  2. or Make the compiler report an error if something isn't available

We are starting to have our own customers use FWT in browser too, so we'll definitely need to improve the "on-ramp" experience.

ilya Thu 13 Jan 2011

Working with dialog results inside "onClose" closures looks fine for me now, the code will look rather easy to comprehend

Dialog.openQuestion(e.window, "0", null, Dialog.yesNo) 
|res|
{
  if (res.data == Dialog.yes) 
  {
    Dialog.openInfo(e.window, res.data?.toStr ?: "null") 
    |res1|
    {
      Dialog.openInfo(e.window, "2") 
      |res2|
      {
        Dialog.openQuestion(e.window, "3", null, Dialog.yesNo) 
        |res3|
        {
          Dialog.openInfo(e.window, res3.data?.toStr ?: "null")
        }
      }
    }
  }
}

And if it becomes the only way to get a result from a Dialog - we'll get the same behavior on all platforms... but by the cost of rewriting tons of old code.

So, yes, it would be very nice if CompilerJs will somehow mark getting result from a Dialog in usual way (without "onClose" closure) like an error.

Login or Signup to reply.