PDA

View Full Version : display_buffer_msg & Prompt_Callback



Russell McDougall
16-May-2010, 04:41 AM
Are there recommended replacments for these messages in cDbCJGridPromptList?

Regarding the first, may i suggest a hook in MoveValueOut or ClosePromptList such as onMovevalueOut which would be passed the invoking object. May i also suggest that the term display_buffer_msg not be used and replaced with a more meaningful name.


Perhaps the Prompt_Callback could be a hook in InitializePromptList

John Tuohy
17-May-2010, 11:54 AM
Are there recommended replacments for these messages in cDbCJGridPromptList?

Regarding the first, may i suggest a hook in MoveValueOut or ClosePromptList such as onMovevalueOut which would be passed the invoking object. May i also suggest that the term display_buffer_msg not be used and replaced with a more meaningful name.


Perhaps the Prompt_Callback could be a hook in InitializePromptList
Russell,

Good question. I just answered another question (http://support.dataaccess.com/Forums/showthread.php?p=208983#post208983) that is related to this issue. This relates to the issue of providing special "easy" interfaces that obscure more standard techniques, which tends lead developers down the wrong path.

Prompt-lists used in the normal manner are designed to do a specific task. They are invoked from a DEO that has a file.field that is represented in the prompt-list. Upon selection, the invoking DEO's DD is updated with the selected record and all DEO's in the view are updated as needed. This is the main purpose of the Prompt-list and when used this way everything just works.

When invoking object is not a DEO that is related to the prompt list it is not really clear what the prompt-list should do. Should it update just the DEO and, if so, how? With the dbLists we tried to automate this by making some guesses. However, these guesses were not enough so we needed to create a bunch of additional properties that determined what the prompt should do. The problem was you might need to set these properties differently for different invoking objects and setting these properties might leave the prompt list in a state where it would not work properly with some other DEO. So we created additional interfaces and callbacks that tried to make this work. It just kept getting more complicated.

This also created a situation where the mechanism for using the prompt lists as non-relational lists directed you down the wrong path. When creating any kind of custom modal panel you really want to use the technique outlined in the article Communicating between views and dialogs (http://support.dataaccess.com/Forums/blog.php?tag=modal&u=2770). What's a shame about this is if you wish to add some kind of completely custom prompt which will not use the cDbCJGridPromptList you will probably be less likely to use the recommended approach.

The approach we are taking in cDbCJGridPromptLists is to make no assumptions about non relational prompt-lists. If you want to use it for non-relational uses, which is perfectly valid, you should use this the way you would use any any custom popup. You will create a custom method in the Modal dialog and you call that custom method from your invoking object by augmenting the invoking object's Popup method. When the modal dialog is closed, your Popup augmentation can update your view any way it wants. While this involves a little bit more coding, the end result is much clearer making it easier to maintain and extend.

Take a look at the report view sample in the "Grid Examples" workspace. It uses exactly this technique with the customer prompt list. I expect that most developer's initial reaction will be that this is different and extra work. It also may turn out that this will require too many changes in existing code. We can certainly add the old interfaces to the cDbCJGridPromptList - it just adds more clutter and we all pay the price for that.

We will appreciate feedback on this issue.

-John

Russell McDougall
17-May-2010, 03:10 PM
John this is my 2 cents worth.

Personally I would not like to see display_buffer_msg & Prompt_Callback put back in the code as I found them mysterious and far from intuitive.

The more I read the blog reference the more I think the programmer should provide his own code because every situation is different.

There are two points of interface.

1. Data communicated from the invoking object to a prompt object. This would normally be prepared in the Prompt message of the invoking object and acted upon in the popup method of the prompt object. Within the popup method communication is easy using the invoking object handle, byref or a struct.

2. Data returned from the prompt object to the invoking object could be done via byref or a struct. Alternatively data may be manipulated direct within the prompt object. Both would normally be done in the MoveDataOut method, either direct in the prompt object or communicating direct with the invoking object.

I would suggest that when Popup and MoveDataOut need to be overriden they need complete replacement rather than augmenting because every situation is different. They should not contain onPopup and onMovedataOut type hooks.

John Tuohy
17-May-2010, 06:30 PM
John this is my 2 cents worth.

Personally I would not like to see display_buffer_msg & Prompt_Callback put back in the code as I found them mysterious and far from intuitive.

The more I read the blog reference the more I think the programmer should provide his own code because every situation is different.

There are two points of interface.

1. Data communicated from the invoking object to a prompt object. This would normally be prepared in the Prompt message of the invoking object and acted upon in the popup method of the prompt object. Within the popup method communication is easy using the invoking object handle, byref or a struct.

2. Data returned from the prompt object to the invoking object could be done via byref or a struct. Alternatively data may be manipulated direct within the prompt object. Both would normally be done in the MoveDataOut method, either direct in the prompt object or communicating direct with the invoking object.

I would suggest that when Popup and MoveDataOut need to be overriden they need complete replacement rather than augmenting because every situation is different. They should not contain onPopup and onMovedataOut type hooks.

This is pretty much the same conclusion we arrived at. I am not sure you will ever need to augment any kind moveValueOut procedure in the cDbCJGridPromptList object itself. Instead you can probably just customize a function in the dbModalPanel object. The cDbCJGridPromptList will do some of the work for you. When the cDbCJGridPromptList is operating in this manual mode, it sets three properties when the cDbCJGridPromptList is closed, pbCancelled, piSelectedRow and priSelectedRowid. You can use this information to return whatever you want to return to the invoking object and then the invoking object can handle it however it wants. The current sample we have, only needs to check the canceled flag but it could use the others as well:


Function GetCustomerNumber Returns Integer
Boolean bCancel
Send Popup
Get pbCancelled of oSelList to bCancel
If not bCancel Begin
Function_Return Customer.Customer_Number
End
Function_Return 0
End_Function
Perhaps we should create a more complicated example, that returns more information like:

Function GetCustomerNumber tCustPromptInfo ByRef CustPromptInfo Returns Boolean
Boolean bCancel
Send Popup
Get pbCancelled of oSelList to bCancel
If not bCancel Begin
Move Customer.Customer_Number to CustPromptInfo.iNumber
Move Customer.Customer_Name to CustPromptInfo.sName
End
Function_Return bCancel
End_Function
Or if the list was a small static list that supported multi-select you might return an array of selected customer numbers.

Function GetCustomerSelections Integer[] ByRef ArrayOfCustNums Returns Boolean
Boolean bCancel bOldMulti bOldEnableSelect
Handle hoDataSource
Integer i iRows
tDataSourceRow[] MyData
Integer[] Sels


Get pbEnableSelection of oSelList to bOldEnableSelect
Get pbMultipleSelection of oSelList to bOldMulti
Set pbEnableSelection of oSelList to True
Set pbMultipleSelection of oSelList to True

Send Popup

Get pbCancelled of oSelList to bCancel
If not bCancel Begin
Move (ResizeArray(ArrayOfCustNums,0)) to ArrayOfCustNums
Get GetIndexesForSelectedRows of oSelList to Sels
Get phoDataSource of oSelList to hoDataSource
Get DataSource of hoDataSource to MyData
Move (SizeOfArray(Sels)) to iRows
For i from 0 to (iRow-1)
Move MyData[Sels[i]].sValue[0] to ArrayOfCustNums[i]
Loop
End

Set pbEnableSelection of oSelList to bOldEnableSelect
Set pbMultipleSelection of oSelList to bOldMulti

Function_Return bCancel
End_Function
Keep in mind that these examples functions are inside of the dbModalPanel which contains your cDbCJGridPromptList. The invoking object calls these functions and this object knows how the function works but has no idea what is actually going in in the ModalPanel. In fact it doesn't even know or care that you are using a cDbCJGridPromptList object inside of the ModalPanel The column prompt handler might look like this:


Procedure Prompt
Handle hoPopup
Integer[] ArrayOfSelections
Boolean bCancel

Get Prompt_Object to hoPopup
Get GetCustomerSelections of hoPopup (&ArrayOfSelections)to bCancel
If (not(bCancel)) Begin
Send DoWhateverWithSelections ArrayOfSelections
End
End_Procedure
This is a somewhat complicated example but you can see how it easily extends from the simple suggested approach for handling this kind of thing.

(Also note that I just typed this code directly into the editor here - I am sure there are syntax errors.)

-John

Gregg Finney
20-Apr-2011, 04:36 PM
My 2 cent's worth, you are doing something wrong.

danwalsh46
21-Apr-2011, 08:39 AM
Russell,

I am finding that the new properties in the cDbCJGridPromptLists class make using prompt lists in non-standard modes much easier than with the old classes. Custom access methods using by-reference variables as shown in the examples are very powerful and easy to use tools.

My suggestion would be that you bring some example code to this forum, if you need help, and see if we can't help you find acceptable solutions using the new tools. If the development team can see specific situations where the new class is falling short, then that is time to look for extensions to the new class.