Difference between revisions of "Dialog/Form Validation"

From wiki.visual-prolog.com

(Move from WEB)
 
(source files)
 
(9 intermediate revisions by 2 users not shown)
Line 3: Line 3:
In this tutorial, we will show you how to validate controls in a dialog or in a form. First we will describe the validation concept. We will show how integerControl and realControl use the validation concept. Then we consider the validation in a container control. And finally we will add the validation for several usual controls: editControl, listBox and a newly created custom control.
In this tutorial, we will show you how to validate controls in a dialog or in a form. First we will describe the validation concept. We will show how integerControl and realControl use the validation concept. Then we consider the validation in a container control. And finally we will add the validation for several usual controls: editControl, listBox and a newly created custom control.


'''Download: ''Source files''''' of the example project used in this tutorial.
Source files corresponding to this tutorial is available in the examples '''Help -> Install Examples...'''


==Validation Concept==
==Validation Concept==
Line 19: Line 19:
==Validation in integerControl and realControl==
==Validation in integerControl and realControl==


Let us create a form and add two '''custom controls''' in it with the classes integerControl and realControl. You can see the result in the supplied example project in the form integerControlAndRealControl.
Let us create a form and add two '''custom controls''' in it with the classes integerControl and realControl. You can see the result in the supplied example project in the form <vp>integerControlAndRealControl</vp>.


The generated code will look like:
The generated code will look like:
Line 30: Line 30:
realControl_ctl:setSize(60,12),</vip>
realControl_ctl:setSize(60,12),</vip>


Also we need to add invocation of integerControlAndRealControl'''' form:
Also we need to add invocation of <vp>integerControlAndRealControl</vp> form:


<vip>predicates
<vip>predicates
Line 41: Line 41:
When we run the project and input non-integral values, we will see a dialog box with an explanation about the mistake.
When we run the project and input non-integral values, we will see a dialog box with an explanation about the mistake.


We can add also ''onOK'' responder to retrieve values of the validated controls:
We can add also <vp>onOK</vp> responder to retrieve values of the validated controls:


<vip>predicates
<vip>predicates
Line 52: Line 52:
         stdIO::write("Real value = ",Real, "\n").</vip>
         stdIO::write("Real value = ",Real, "\n").</vip>


It is important to notice ''onOK'' responder is '''not''' invoked if the dialog validation is not successful. And of course, ''onOK'' responder is invoked '''after''' all validation predicates.
It is important to notice <vp>onOK</vp> responder is '''not''' invoked if the dialog validation is not successful. And of course, <vp>onOK</vp> responder is invoked '''after''' all validation predicates.


Let us look in file \pfc\gui\controls\integerControl.pro to inspect how the validation is implemented. We can see:
Let us look in file '''\pfc\gui\controls\integerControl.pro''' to inspect how the validation is implemented. We can see:


<vip>clauses
<vip>clauses
Line 69: Line 69:
     onIntValidate(_) = contentsOk.</vip>
     onIntValidate(_) = contentsOk.</vip>


I.e. if the local predicate checkContent considers the text as an integer, then the validation is successful.
I.e. if the local predicate checkContent considers the text as an <vp>integer</vp>, then the validation is successful.


As it is mentioned above we can also force validation programmatically. We will add button TryValidation and code:
As it is mentioned above we can also force validation programmatically. We will add button TryValidation and code:
Line 84: Line 84:
==Validation in Container Controls==
==Validation in Container Controls==


For considering the validation in a container control, we should create such control first. Let us create a new control ''fromTo'' in our project and add two controls integerControl in it.
For considering the validation in a container control, we should create such control first. Let us create a new control <vp>fromTo</vp> in our project and add two controls integerControl in it.


We will consider that ''fromTo'' control is valid if From value is less than To value, therefore we will add the validation responder to fromTo''''  control:
We will consider that <vp>fromTo</vp> control is valid if <vp>From</vp> value is less than <vp>To</vp> value, therefore we will add a validation responder to <vp>fromTo</vp> control:


<vip>predicates
<vip>predicates
     validateFromTo : control::validateResponder.
     validateFromTo : control::validateResponder.
clauses
clauses
     onIntValidate(Source) = control::contentsInvalid(Source,from_ctl,
     validateFromTo (Source) = control::contentsInvalid(Source,from_ctl,
       "From value must be less than To value") :-
       "From value must be less than To value") :-
         from_ctl:getInteger() >= to_ctl:getInteger(),
         from_ctl:getInteger() >= to_ctl:getInteger(),
         !.
         !.
     onIntValidate(_) = control::contentsOk.</vip>
     validateFromTo (_) = control::contentsOk.</vip>


Please notice that control from_ctl'''' will receive the focus if the validation is not successful.
Please notice that control <vp>from_ctl</vp> will receive the focus if the validation is not successful.


==Validation in Usual Controls==
==Validation in Usual Controls==


Let us create a new control myControl'''' in our project, and then create a form and add three controls in it:
Let us create a new control <vp>myControl</vp> in our project, and then create a form and add three controls in it:


*edit control;
*edit control;
Line 107: Line 107:
*listbox control;
*listbox control;


*custom control of myControl'''' class.
*custom control of <vp>myControl</vp> class.


You can see the result in the supplied example project in the form ''usualControls''.
You can see the result in the supplied example project in the form ''usualControls''.
Line 157: Line 157:
That is, you can see that it is possible to validate a control in really different ways.
That is, you can see that it is possible to validate a control in really different ways.


==References==
[[Category:GUI]]
 
[[Category:Tutorials]]

Latest revision as of 10:55, 4 March 2016

When a user presses OK in a dialog, it means that something should happen. But this can only happen if the data in the dialog are valid. The dialog/form must be validated. This tutorial describes the validation mechanism supported by PFC GUI. It also shows how to use the validating controls integerControl and realControl, and how to validate other controls in a dialog/form.

In this tutorial, we will show you how to validate controls in a dialog or in a form. First we will describe the validation concept. We will show how integerControl and realControl use the validation concept. Then we consider the validation in a container control. And finally we will add the validation for several usual controls: editControl, listBox and a newly created custom control.

Source files corresponding to this tutorial is available in the examples Help -> Install Examples...

Validation Concept

The validation concept is based on the idea: "control values should be valid". The validation check happens on pressing OK button in a dialog or a form, but the validation check can be forced programmatically also.

It is the responsibility of a control to state that its contents is valid, therefore a validation responder can be set to a control.

When a dialog or a form makes the validation check, the controls are tested sequentially, but if one of the tests results in

contentsInvalid(Source, FocusControl, ErrorMessage)

then the validation check is terminated.

Validation in integerControl and realControl

Let us create a form and add two custom controls in it with the classes integerControl and realControl. You can see the result in the supplied example project in the form integerControlAndRealControl.

The generated code will look like:

integerControl_ctl := integercontrol::new(This),
integerControl_ctl:setPosition(92, 4),
integerControl_ctl:setSize(60,12),
realControl_ctl := realcontrol::new(This),
realControl_ctl:setPosition(92, 20),
realControl_ctl:setSize(60,12),

Also we need to add invocation of integerControlAndRealControl form:

predicates
    onFileIntegercontrolRealcontrol : window::menuItemListener.
clauses
    onFileIntegercontrolRealcontrol(Source, _MenuTag) :-
        Form = integerControlAndRealControl::new(Source),
        Form:show().

When we run the project and input non-integral values, we will see a dialog box with an explanation about the mistake.

We can add also onOK responder to retrieve values of the validated controls:

predicates
    onOk : button::clickResponder.
clauses
    onOk(_) = button::defaultAction() :-
        Integer = integerControl_ctl:getInteger(),
        Real = realControl_ctl:getReal(),
        stdIO::write("Integer value = ",Integer, "\n"),
        stdIO::write("Real value = ",Real, "\n").

It is important to notice onOK responder is not invoked if the dialog validation is not successful. And of course, onOK responder is invoked after all validation predicates.

Let us look in file \pfc\gui\controls\integerControl.pro to inspect how the validation is implemented. We can see:

clauses
    new() :-
        editControl::new(),
        addValidateResponder(onIntValidate).
 
predicates
    onIntValidate : validateResponder.
clauses
    onIntValidate(_) = contentsInvalid(This,This, ErrorMessage) :-
        string(ErrorMessage) = checkContent(getText()),
        !.
    onIntValidate(_) = contentsOk.

I.e. if the local predicate checkContent considers the text as an integer, then the validation is successful.

As it is mentioned above we can also force validation programmatically. We will add button TryValidation and code:

predicates
    onTryValidation : button::clickResponder.
clauses
    onTryValidation(_Source) = button::defaultAction() :-
        tryValidateWithErrorDialog(),
        !,
        stdIO::write("All controls are valid\n").
    onTryValidation(_Source) = button::defaultAction().

Validation in Container Controls

For considering the validation in a container control, we should create such control first. Let us create a new control fromTo in our project and add two controls integerControl in it.

We will consider that fromTo control is valid if From value is less than To value, therefore we will add a validation responder to fromTo control:

predicates
    validateFromTo : control::validateResponder.
clauses
    validateFromTo (Source) = control::contentsInvalid(Source,from_ctl,
      "From value must be less than To value") :-
        from_ctl:getInteger() >= to_ctl:getInteger(),
        !.
    validateFromTo (_) = control::contentsOk.

Please notice that control from_ctl will receive the focus if the validation is not successful.

Validation in Usual Controls

Let us create a new control myControl in our project, and then create a form and add three controls in it:

  • edit control;
  • listbox control;
  • custom control of myControl class.

You can see the result in the supplied example project in the form usualControls.

Initialization code will contain the setting of responders and initialization for these three controls:

clauses
    new(Parent) :-
        formWindow::new(Parent),
        generatedInitialize(),
        edit_ctl:addValidateResponder(validateEditCtl),
        listbox_ctl:addList(["First","Second","Third"]),
        listbox_ctl:addValidateResponder(validateListBox).

And validation responders will look like:

predicates
    validateEditCtl : control::validateResponder.
clauses
    validateEditCtl(_) = control::contentsOk :-
        "OK" = edit_ctl:getText(),
        !.
    validateEditCtl(Source) = control::contentsInvalid(
          Source, Source,
          "Edit control expects to have the text 'OK'").
 
predicates
    validateListBox : control::validateResponder.
clauses
    validateListBox(Source) = control::contentsInvalid(
          Source,Source,
          "Selection of the first row is not allowed") :-
        0 = listbox_ctl:tryGetSelectedIndex(),
        !.
    validateListBox(_) = control::contentsOk().
 
predicates
    validateMyControl : control::validateResponder.
clauses
    validateMyControl(Source) = control::contentsInvalid(
          Source,Source,
          string::concat("A marker in the ",Missed,
            " part is mandatory")) :-
        Missed = toString(isMandatoryMarkNotActive(
          mandatoryMark, activatedMark)),
        !.
    validateMyControl(_) = control::contentsOk().

That is, you can see that it is possible to validate a control in really different ways.