Editable Customer List
-----------------------

This directory contains some trials to solve the following task:
A database table should be displayed and it should be possible to simultaneously edit the highlighted table record in a detail input.
It should be possible to edit/delete records , append new records and limit the displayed amount of data by calling a filter dialog.

This sounds like an easy game for multiple dialogs, but it turned out to be a bit harder than expected.
First lets inspect a sample implementing this task without multiple dialogs.

CustListDetail_old.4gl:
-----------------------
Browses the table in a DISPLAY ARRAY and shows simultaneously the details in another screen record, but to edit the record one has to double-click the highlighted line or to press the "Modify" button. To append a new record in the database, one has to press the "Append" button. The title of the window is set to assist the end user in which mode the program is. The code to do that is pretty short compared to the multiple dialogs samples.

Improved with multiple dialogs?
------------------------------
Now when starting CustListDetail or CustListDetail2 they both show nearly the same behavior:
It's possible to click directly into the record INPUT for the selected line in the DISPLAY ARRAY.
In the moment if we start to edit and change the current record we immediately run into a serious validation problem: some of our actions require the validation of the current record before we can continue with the intended action.

Example:
Change something in the current Record and pressing the 'Append' button:
In this moment you will be asked if you want to save your changes (CustListDetail) and after the confirmation the INPUT is cleared and you can enter new data.

The code to do that isn't that hard but you will have to perform the same steps which would have been done automatically for you if you would have left the dialog with ACCEPT DIALOG:

v1: Verify if the field constraints are met (by calling the new DIALOG.validate() method).

v2: Call the code which is called in the AFTER FIELD trigger of the field you are  currently inside.

v3: Call the code which is called in the AFTER INPUT.

Especially v2 is hard to solve if you have a lot of AFTER FIELD clauses, then you will either have to check with 
  IF INFIELD(a) THEN CALL after_field(a) END IF
or you check anyway all your AFTER FIELD constraints in each action which is type of ACCEPT DIALOG.
In the current sample it is sufficient to call the check code for AFTER FIELD address (done in CustListDetail.4gl in 'cust_validate_address' and in CustListDetail2 directly in AFTER FIELD address)

The validation steps have to be invoked for each action in the multiple dialog which require it: 'Append', 'Query' (we want to have saved correctly before we refill the list with data) and 'Save'.
The 'Save' button is optional, normally we don't need it because we ask in each possible step for confirmation, but it might help to assist end users which miss the 'Ok' button.

If we click into the DISPLAY ARRAY, MD helps us by automatically invoking the AFTER FIELD and AFTER INPUT of the INPUT sub dialog.

CustListDetail.4gl :
--------------------
The 'hard' way:
Solves the validation problems described above by calling a validation procedure ( cust_validate() ) which makes all the necessary checks. If an AFTER FIELD constraint is added later to a particular field, it must be called also in this validation procedure. The code to handle the actions 'append' and 'search' need to call the validation explicitly before performing the indended action code. The code for 'save' is similar: it must als check the validation before.

The sample shows also how to use the new 'dialogtouched' action, however this action is not limited to Multiple Dialogs, it is also possible to use it in traditional 4GL dialogs.
The wish to use 'dialogtouched' is driven to enable/disable the 'Save' action depending on changes in the current record: Because there is no clear Ok/Cancel dialog, it's adds more visibility to the current input state.
Note 'dialogtouched' in a traditional INPUT with Ok/Cancel could be used to enable the 'Ok' button only if something has been changed.

CustListdetail2.4gl
-------------------
The sub dialog action way:
Uses actions dedicated to the sub dialog  to surround the need for multiple validation checkings.
The 'append' and the 'search' actions are inside the DISPLAY ARRAY statement.
This means normally that this actions are only shown in the Action Panel if the focus is inside the DISPLAY ARRAY . If the focus is inside the DISPLAY ARRAY we went already thru the validation in the AFTER INPUT and hence have no need to check again: all validations for the INPUT sub dialog have been done already.
However there is the possility to make those actions always visible by fully qualifying them as BUTTON's inside the .per file, the end user does not see that this action is a sub dialog action:

BUTTON bnew:sr.append,TEXT="New",IMAGE="new";

the "sr.append" name means:display the append action for the sub dialog which handles the "sr" screen record (which is the DISPLAY ARRAY). This fully qualified action name instructs the run time to make the action always visible and do the following if one clicks on it:
If the focus is not inside the DISPLAY ARRAY,move the focus to the display array and perform the validation of the current sub dialog (the INPUT in this case).
Then the action code is performed.
This is exactly the case we need: our 'append'/'search' action code should be only performed if the INPUT is valid. By using this technique we achieve that.
If the focus is already inside the DISPLAY, the code for the action is immediately executed:no need to validate the INPUT, ist must have been validated earlier in the AFTER INPUT.

CustListDetail3.4gl
-------------------
The 3rd sample works like a traditional INPUT ARRAY, it has an OK/Cancel button and all the database work is assumed to take place after Ok has been clicked.
It also uses a single row INPUT ARRAY in place of the INPUT of sample1/sample2 showing that one can again save code if he uses the INPUT ARRAY.

Advantage:   
 -no confirmations inbetween the rows.
 -Database stuff in 1 transaction possible
Disadvantages:
 -some more logic at the end needed to delete/insert/update rows from the database
 -The sample also omit's the 'search' action because a search must be done then before calling this dialog.

Further caveeat
---------------
Both multiple dialogs using INPUT samples have another caveeat:
The DIALOG is not ready yet to toggle sub dialogs between the 2 modes WITHOUT DEFAULTS and without WITHOUT DEFAULTS dynamically.
Typically in the CustListDetail_old sample the INPUT is called with
INPUT ATTRIBUTES(WITHOUT DEFAULTS=NOT new) 
and in the new mode (WITHOUT DEFAULTS=FALSE) the DEFAULT values are load from the .per definition and the REQUIRED attribute is taken into account.
In the multiple dialog sample we can only use WITHOUT DEFAULTS=TRUE because we 'stay' in the INPUT if the record is changed and have yet no dynamic method available to put the INPUT into 'virgin' state if we press the 'Append' Button.
(Writing WITHOUT DEFAULTS=FALSE works but of cause only once for the first record displayed in the program and will be immediately overwritten by the first BEFORE ROW code of the DISPLAY ARRAY)
That's why the REQUIRED and DEFAULT attributes are not usable in this case, which raises again problems:
REQUIRED is used to force a user to visit a field in WITHOUT DEFAULTS=FALSE mode to ensure that an AFTER FIELD trigger is called. 
This mechanism is not usable with WITHOUT DEFAULTS=TRUE, instead one has to set the NOT NULL constraint together with a NULL value as default to force an end user to visit the field initially.
Note:
This only arises in the situation that we use the multiple dialog for inputting several records in one INPUT , as long as you use the multiple dialog as a typical Ok/Cancel dialog like shown in other samples (../Folder) the WITHOUT DEFAULTS mechanism works like expected.

Conclusion
----------
To make the wanted visual behavior happen you have a lot of possibilities

1. Calling all validations 'manually' for each action needing the validation for the current sub dialog(CustListDetail.4gl). This forces you to make extra functions for *each* AFTER FIELD check in your INPUT!
As already said, this is the 'hard' way and is also not looking intuitive, we cannot recommend it. Use one of the next techniques to make your life easier.

2. using sub dialog actions local to the DISPLAY ARRAY to let the DIALOG doing the validation for you . You need to get a bit experience how to fully qualify the sub dialog local action in the .per to let this action be active in each place of the DIALOG.
  (CustListDetail2.4gl)

3. Synchronizing an INPUT ARRAY with a DISPLAY ARRAY to save code lines and get 'append'/'delete' for free

In case 1.) case you will have to write a lot more code than in the original sample ,in case 2. and 3.) you must know about the possibilies in using sub dialog local actions for achieving the necessary validations.
