2010-08-05

DialogClass::ActivateEvent

While I labor over my post for my 3rd law of EnScript, here's an interesting problem. A former colleague of mine, Jeff, emailed me with a sample script. He wanted his user interface to be a wizard, and wanted a subsequent tab to update what it displayed based upon what the user put into the previous tab.

If the only update that needs to occur is to redisplay data from some variable, then this will happen automatically. When the user clicks "Next" on a tab, the widgets on that dialog will write their data to their corresponding variables. When the next tab is displayed, that dialog will automatically re-read its variables. If variables are being shared between widgets on the different dialogs, then everything will appear to be in sync.

However, if you need to do something more complex (a simple example being to update the text in a StaticTextClass, which doesn't have a linked variable), then you need to override DialogClass::ActivateEvent(). ActivateEvent() is called whenever a DialogClass object is displayed, i.e., has become active. There's also WindowClass::Setup(), which is called when a dialog, or a parent dialog, is first displayed because of Execute() or Wizard().

Meanwhile, CanClose() corresponds to the user clicking "Ok" or one of "Next" or "Previous". Returning false from CanClose() will cause the user to remain looking at the current dialog; the idea is that you could perform some validation in CanClose() and if it failed, call ErrorMessage() and return false.

With DialogClass/WindowClass virtual functions, it is generally necessary to call the parent function. If you don't, bad things will happen. The exception to this is CheckControls().

Below is a modified version of Jeff's test script that demonstrates how this works. Try modifying one of the ActivateEvent() functions to return false.


class MainClass {
  String test, test2;

  int  myint;

  void Main() {
    myint = 7;
    test = "text";
    test2 = "text2";
    SystemClass::ClearConsole();
    MasterDialogClass dlg(this);
    dlg.Wizard();
  }
}


class PageDialogClass1: DialogClass {
  StaticTextClass Message;

    PageDialogClass1(DialogClass parent, MainClass &m):
    DialogClass(parent, "First Page"),
    Message(this, m.test, START, START, DEFAULT, DEFAULT, READONLY)
  {
  }
}



class PageDialogClass2: DialogClass {
  StringEditClass Str_Text;
  IntEditClass    Int;

  PageDialogClass2(DialogClass parent, MainClass &m):
    DialogClass(parent, "Second Page"),
    Str_Text (this, "Text", START, START, 80, DEFAULT, 0, m.test2, 80, WindowClass::REQUIRED),
    Int(this, "Int", SAME, NEXT, 100, DEFAULT, 0, m.myint, 0, 30, 0)
  {
  }

  virtual void Setup() {
    Console.WriteLine("Page2 Setup");
    DialogClass::Setup();
  }

  virtual bool ActivateEvent() {
    Console.WriteLine("Page2 ActivateEvent");
    return DialogClass::ActivateEvent();
  }

  virtual bool CanClose() {
    Console.WriteLine("Page2 CanClose");
    return DialogClass::CanClose();
  }
}


class PageDialogClass3: DialogClass {
  MainClass       Main;
  StaticTextClass Message;
  IntEditClass    Int;


  PageDialogClass3(DialogClass parent, MainClass &m):
    DialogClass(parent, "Third Page"),
    Main = m,
    Message(this, m.test2, START, START, 80, 12, READONLY), //I want this to show the text entered on Page2   
    Int(this, "Int", SAME, NEXT, 100, DEFAULT, 0, m.myint, 0, 30, 0)
  {
  }

  virtual void Setup() {
    Console.WriteLine("Page3 Setup");
    DialogClass::Setup();
  }

  virtual bool ActivateEvent() {
    Console.WriteLine("Page3 ActivateEvent");
    Message.SetText(Main.test2);
    return DialogClass::ActivateEvent();
  }

  virtual bool CanClose() {
    Console.WriteLine("Page3 CanClose");
    return DialogClass::CanClose();
  }
}


class MasterDialogClass: DialogClass {

  PageDialogClass1          Page1;
  PageDialogClass2          Page2;
  PageDialogClass3          Page3;

  MasterDialogClass(MainClass m):
 
    DialogClass(null, ""),
    Page1(this, m),
    Page2(this, m),
    Page3(this, m)
  {}

  virtual void Setup() {
    Console.WriteLine("Master Setup");
    DialogClass::Setup();
  }

  virtual bool ActivateEvent() {
    Console.WriteLine("Master ActivateEvent");
    return DialogClass::ActivateEvent();
  }

  virtual bool CanClose() {
    Console.WriteLine("Master CanClose");
    return DialogClass::CanClose();
  }
}

1 comment:

  1. Thanks so much Jon!

    Funny how something so simple can become so not simple!

    ReplyDelete