NG DialogPack Guide


Fluent Interface


NG-DialogPack fluent interface provides an easy and very convenient way for executing dialogs directly from code, without placing dialog component on the form. Fluent interface is organized as a static methods of TNGDialogs structure. Most of the methods are overloaded and provides different parameter sets for simplicity of use. Our goal was to provide a way to execute a variety of commonly used dialogs, starting from easy analogs of standard Delphi's ShowMessage, MessageDlg, InputBox or InpurQuery functions, and continuing with more complex, highly configurable task and input dialog (via dialog builders).

 

Simple methods

 

TNGDialogs structure provides huge amount of overloaded methods, which can be used to execute simple common dialogs. As an example of how to use these methods, look at the following code, which executes the analog of ShowMessage standard Delphi function:

 

TNGDialogs.Message('Hello World');

 

The code above will show the following dialog:

 

clip0015

 

In the next list all simple fluent interface methods are described:

 

Message - overloaded set of methods, which provide a way for executing message like dialogs; dialogs are analogous to standard Delphi's ShowMessage and MessageDlg functions.  The methods use the same parameter types as used in MessageDlg. Internally, Message methods are implemented using TNGMessageDialog, which provides look and feel, compatible with platform task dialogs.

Info, Error, Warning - methods, which allow to execute pre-configured dialog analogous to Message, which has single Ok button and the corresponding standard icon.

Confirm - overloaded set of methods, which are analogous to Ifno, Error or Warning methods, but show dialogs with question standard icon and Yes/No buttons (by default); the methods also allow to specify required buttons explicitly.

InputBox - overloaded set of methods, which provides a way for executing input dialogs, in a way analogous to standard Delphi' InputBox function. Internally the methods use TNGInputDialog, which provides task dialogs compatible look and feel. Just like standard Delphi function, InputBox methods take ADefault string (or TDateTime) parameter and return modified by the user value.

InputQuery - overloaded set of methods, which provides a way for executing input dialogs, in a way analogous to standard Delphi' InputQuery function. Internally the methods use TNGInputDialog, which provides task dialogs compatible look and feel. Just like standard Delphi function, InputQuery methods take AValue string (or TDateTime) var parameter and return Boolean value indicating whether the user clicked Ok button.

 

Dialog builders

 

TNGDialogs structure provides additionally two sets of overloading methods (for TNGTaskDialog and TNGInputDialog respectively), which returns corresponding builder structures, which allow to configure almost all aspects of the dialogs in a simple and accurate looking code. These two sets of methods are:

 

Task - overloaded set of methods, which returns TNGTaskDialog.TTaskBuilder structure, which allows to continue inline configuration of executing TNGTaskDialog.

Input - overloaded set of methods, which returns TNGTaskDialog.TInputBuilder structure, which allows to continue inline configuration of executing TNGInputDialog.

 

Despite the fact that these methods are overloaded, they allow to specify only basic dialog properties, like Caption, Title, Text and MainIcon as method parameters. All other dialog aspects can be configured inside the same code statement using returned builder structure methods. Following is the example of how to use such API:

 

  TNGDialogs.Task('My caption', 'My Title', 'My text')

            .Icon(Application.Icon)

            .Button('My Button', 100, True)

            .Buttons([tcbOk, tcbCancel])

            .Footer('My footer', tdiWarning)

            .Execute;

 

The code above will shows the following dialog:

 

clip0016

 

Another example shows how to use input dialog builder:

 

  TNGDialogs.Input('My caption', 'My title', 'My text')

            .Icon(tdiQuestion)

            .Button('My Button', 100, True)

            .Buttons([tcbOk, tcbCancel])

            .Value('Initial value')

            .Execute;

 

The code above will shows the following dialog:

 

clip0017

 

As can be seen, this complex dialog, which contains custom main icon, custom button (which is specified to be a default button) and a footer with configured icon, is executed using simple and clean code. Builder structures provides a huge sets of overloaded methods, which allows to specify:

 

All text dialog properties, such as Caption or Title;

Main icon;

Footer text and icon;

Expandable information;

Verification text;

Standard and custom buttons; including specification of custom buttons modal results, Enabled state and specification of the default button;

UseCommandLinks flag;

Radio-buttons;

Input type, input value and items for input dialog.

 

Note: Main and footer icon related methods allow to specify the corresponding icon in a form of standard icon, using TNGTaskDialogIcon enumeration, or a custom icon in a form of TIcon or TStream or resource name to load icon from.

 

Formally, almost all builder methods, such as Icon or Button return the builder itself, so the configuration can be continued just in the same code expression. The exception of this rule is Execute method and Dialog property:

 

Execute method

 

Execute builder method should be called as a last method after all configuration methods. It  executes pre-configured dialog and return TModalResult, just like the corresponding dialog's Execute method. Usually the returned value somehow used in if\then or case\off Delphi construct to know, which button has been clicked; in such cases whole dialog building expression can be placed directly inside mentioned constructs. For example:

 

  case TNGDialogs.Task('My caption', 'My Title', 'My text')

                 .Button('My Button', 100, True)

                 .Buttons([tcbOk, tcbCancel])

                 .Execute of

    mrOk:

      { Do something } ;

    mrCancel:

      { Do something } ;

    100:

      { Do something } ; // Custom 'My Button' clicked.

  end;

 

Sometimes, its required to have a reference to executed dialog, to get access to some its properties. For example, a reference to the dialog is needed to get known, which radio-button has been selected by the user. For such cases, Execute set of methods provides an overload, which has ADialog output parameter. Note, that ADialog parameter type is a template smart pointer type AutoFree<>, which allows to omit dialog instance destruction code and associated with it commonly used try\finally construct. Following is the example code, which shows how to use AutoFree<> correctly:

 

var

  dlg: AutoFree<TNGTaskDialog>;

begin

  case TNGDialogs.Task('Form state', 'Set new form state',

                       'Just for example')

                 .Buttons([tcbOk, tcbCancel], tcbOk)

                 .RadioButton('Maximize form')

                 .RadioButton('Minimize form')

                 .RadioButton('Close form')

                 .Execute(dlg) of

    mrOk:     case dlg.Selected.Index of

                0: Self.WindowState := wsMaximized;

                1: Self.WindowState := wsMinimized;

                2: Self.Close;

              end;

    mrCancel: ; // Do nothing.

  end;

end;

 

Dialog property

 

Dialog builder property can be called instead of Execute method to obtain an instance of configured dialog without it execution. Analogous to Execute method, it should be called as a last call after all configuration methods.  It also returns the instance of the dialog as an AutoFree<> value, which does not require writing explicit destruction code.

 

Despite the fact that our fluent interface provides a variety of methods to configure executing dialog, it does not cover all aspects. Some things, especially related to dialog events, are not included. Following is an example, which shows how Dialog property can be used to get executing dialog reference before execution and assign an event handler to OnButtonClick dialog event:

 

var

  dlg: AutoFree<TNGTaskDialog>;

begin

  dlg := TNGDialogs.Task('My caption', 'My title', 'My text')

                   .Buttons([tcbOk, tcbCancel], tcbOk)

                   .Dialog;

  dlg.OnButtonClick := MyButtonClick;

  dlg.Execute;

end;

 

There exist an even simpler way, which provides similar result, even without declaring dlg variable:

 

begin

  with TNGDialogs.Task('My caption', 'My title', 'My text')

                 .Buttons([tcbOk, tcbCancel], tcbOk)

                 .Dialog() do

  begin

    OnButtonClick := MyButtonClick;

    Execute;

  end;

end;