#959 ok command not work in Dialog

Akcelisto Fri 5 Feb 2010

using fwt
using gfx

class TestDlg {
  static Void main(){
    Dialog(null) {
      ok := Dialog.ok      
      ok.onInvoke.add{
        echo("ok")
      }
      commands = [ok,Dialog.cancel]
    }.open
  }
}

Why is no output when I press OK?

DanielFath Fri 5 Feb 2010

Nvm. Stupid comment.

msl Fri 5 Feb 2010

If you use your own command instead of Dialog.ok you get the behavior you want... So there's something in Dialog.ok that's stopping your handlers from being invoked.

If you take a look at Dialog.fan (under FAN_HOME/src/fwt/fan) you'll see that Dialog.ok is an instance of DialogCommand (declared in the same file).

The invoked(Event? e) method in this DialogCommand does two things:

switch (id)
{
  case DialogCommandId.details:
    toggleDetails:
  default:
    window?.close(this)
}

neither of which is call super.invoked(Event? e) (which would give the behavior you want)

So, in short - you can't add custom handlers to any of the Dialog.* commands.

Akcelisto Fri 5 Feb 2010

>you can't add custom handlers to any of the Dialog.* commands

What purpose it did?

brian Fri 5 Feb 2010

The predefined commands ok, cancel are designed to do two things:

  • provide predefined localized buttons
  • use as the "result value" of open

What you really want to do is this:

r := dialog.open
if (r == Dialog.ok) { ... }

See fwt::Dialog.openMsgBox and fwt::Dialog.commands

Akcelisto Fri 5 Feb 2010

How custom dialog must intercept OK inter own definition?

I want to save data in class MyDialog for incapsulation of fields of MyDialog.

class MyDialog : Dialog{
  new make(Window? parent, Person p) : super(parent){
    nameText := Text{}
    ageText := Text{}
    body := GridPane{nameText,ageText}
    ok := Dialog.ok      
    ok.onInvoke.add{
      p.name = nameText.text
      p.age = ageText.text.toInt
    }
    commands = [ok,Dialog.cancel]
  }
}

// using
MyDialog(parent,selectedPerson).open

msl Fri 5 Feb 2010

The answer's already in this thread:

using fwt
using gfx

class MyDialog : Dialog {
  Text name := Text { text="Enter your name" }
  Text age : Text { text="Enter your age" }
  new make(Window? parent) : super(parent) {
    body = GridPane{name, age}
    comamnds = [Dialog.ok, Dialog.cancel]
  }
}

class Person {
  Str? name
  Str? age
  override Str toStr() { return "Person(age=\"${age}\", name=\"${name}\")")
}

class Main {
  Void main() {
    p := Person()
    md := MyDialog(null)
    if (md.open() == Dialog.ok) {
      p.age = md.age.text
      p.name = md.name.text
    }
    echo(p)
  }
}

ivan Fri 5 Feb 2010

I'd rather write something like this:

class PersonDialog : Dialog
{
  new make(Window? parent) : super(parent)
  {
    body = GridPane 
    {
      it.numCols = 2
      it.add(Label {text = "Name"}); it.add(name)
      it.add(Label {text = "Age"}); it.add(age)
    }
    commands = [Dialog.ok, Dialog.cancel]
  }

  Text name := Text()
  Text age := Text()
}    

And then use it like that:

dialog := PersonDialog(parent)
dialog.name.text = selectedPerson.name
dialog.age.text = selectedPerson.age.toStr
if(dialog.open == Dialog.ok)
{
  selectedPerson.age = dialog.age.text.toInt
  selectedPerson.name = dialog.name.text
}

ivan Fri 5 Feb 2010

Argh! I'm late)

msl Fri 5 Feb 2010

Argh! I'm late)

Sidewalk needs some AJAXy goodness like stack overflow where you get "someone else has posted a response" as you're replying?

Andy/Brian: get on that wouldya? (or release the code for sidewalk and we'll take a look :P)

Akcelisto Fri 5 Feb 2010

I want use

PersonDialog(parent,selectedPerson).open

insead of

dialog := PersonDialog(parent)
dialog.name.text = selectedPerson.name
dialog.age.text = selectedPerson.age.toStr
if(dialog.open == Dialog.ok){
  selectedPerson.age = dialog.age.text.toInt
  selectedPerson.name = dialog.name.text
}

You suggest me write this every place where I open PersonDialog?

ivan Fri 5 Feb 2010

If there are thousands of places where you need to write it, then you can do something like this:

static Void showPersonDialog(Window? parent, Person person)
{
  //...you got the idea...
}

msl Fri 5 Feb 2010

@ivan I wouldn't go for something quite that ugly (general aversion to static).

Let's consider where we're at:

  1. You want to pass the Person to the fwt::Dialog to keep it as a single unit
  2. You can't add invocation handlers to fwt::Dialog.ok
  3. Brian's commented that fwt::Dialog.ok is intended to be used as a return value
  4. You get access to the fwt::Dialog.ok object by calling fwt::Dialog.open

What could you sub-class and what methods could override and intercept to figure out whether fwt::Dialog.ok was clicked (returned)?

I have the working code in front of me, but I might leave it as an open thread for the time being to see if we can't teach a man to fish :)

Martin

ivan Fri 5 Feb 2010

Martin, agree, solution with static method is too ugly, your solution is much better. Another option instead of subclassing (which is done anyway) and overriding is to create and use some other object instead of predefined Dialog.ok.

brian Fri 5 Feb 2010

Don't get too hung up on the static definitions of ok, cancel, etc - they are just conveniences for the common case where you don't want a subclass Dialog and just want to open something, then find out what button got pressed.

If you are going to do a custom dialog, just create your own Commands:

class MyDialog : Dialog
{
  new make(Window? p) : super(p)
  {
    body = Label { text="hello" }
    commands = 
    [ 
      Command.makeLocale(Dialog#.pod, "ok") { echo("!ok"); close }    
    ]
  }
}

If you want your dialog to return a result, pass the result to close so you can do things like this:

person := MyDialog(parent).open
if (person != null) echo("cancelled!")

Dialog is a swiss army knife - it lets you build up fairly sophisticated dialogs in one line, but also gives you all the hooks you need sophisticated subclassing.

andy Fri 5 Feb 2010

Sidewalk needs some AJAXy goodness like stack overflow where you get "someone else has posted a response" as you're replying?

Yes that would be useful to have next time we do a Sidewalk update.

Login or Signup to reply.