Module Dftable.pkg
1//************************************************************************
2//
3// Confidential Trade Secret.
4// Copyright 1987-1997 Data Access Corporation, Miami FL, USA
5// All Rights reserved
6// DataFlex is a registered trademark of Data Access Corporation.
7//
8//************************************************************************
9//
10// $File name : DFTable.pkg
11// $File title : Table (dbGrid) support for VDF
12// Notice :
13// $Author(s) : John Tuohy
14//
15// $Rev History
16//
17// 11/6/98 JJT - Fixed but in Assign_DD_Label
18// 8/13/97 JJT - Set up support for Prompt_button_State
19// 07/30/97 JJT - Added set current_item check for batch_state
20// 6/24/97 JJT - Added Auto-label DD support: Auto_label_State. Assign_DD_Label
21// 01/31/97 JJT - default highlight_row_state to T
22// 07/23/96 JJT - New Class names
23// 06/05/96 JJT - Fixed new_item and current_item to check if current_item
24// really exists before calling update_focus_field
25// 06/03/96 JJT - Fixed new_item and current_item to check for extended dso
26// before proceeding.
27// 05/28/96 JJT - Added code list exported description support.
28// 04/26/96 JJT - Augmented Set Current_item/Item to refresh DD Buffer
29// (we need a better way).
30// 05/01/95 JJT - Modified to support Cell and row highlighting
31// 03/28/95 JJT - Removed 0 Layer class
32// Changed name to dftable.pkg
33// 08/19/94 JJT - Blended Classes from CB and DAF
34//************************************************************************
35
36
37// not defined in windows, the aspect for a multi row FORM
38#REPLACE BASPECT_MULTIFORM |CI135
39
40Use Windows.pkg
41Use Table_ds.pkg
42Use DFData.pkg
43Use dfConfrm.pkg
44Use PrmpBtMx.pkg // need the defines for prompt button modes
45Use DfDeoFt.pkg
46
47{ ClassType=Abstract }
48{ HelpTopic=dbGrid_ }
49// batch_state should never be used in dbGrids, only dbLists.
50{ OverrideProperty=Batch_State DesignTime=False Visibility=Private }
51Class dbGrid_ is a DataList
52 Import_Class_Protocol Table_ds_mixin
53End_Class
54
55//
56// dfGrid
57//
58{ ClassType=Abstract }
59{ HelpTopic=dbGridDS }
60{ OverrideProperty=Floating_Menu_Object InitialValue=Default_dbFloating_Menu_ID }
61{ OverrideProperty=Highlight_Row_State InitialValue=True }
62Class dbGridDS is a dbGrid_
63
64 Procedure Construct_Object
65 Forward Send Construct_Object No_Image
66
67 Set Floating_Menu_Object to Default_dbFloating_Menu_ID
68
69 // set default verify messages for table. The most sensible is to
70 // use no save verify, a line delete verify and parent's data-loss
71 // Note: these messsages are defined in dfconfrm.pkg
72 Set Verify_Delete_msg to (RefFunc(Line_Delete_Confirmation))
73 Set Verify_Save_msg to (RefFunc(No_Confirmation))
74
75 on_key key_F11 send add_or_remove_row PRIVATE // same as F5
76
77 { Category=Appearance }
78 Property String Prompt_Button_Value '>>'
79 { Category=Appearance }
80 { EnumList="PB_PromptAuto, PB_PromptOn, PB_PromptOff" }
81 Property Integer Prompt_Button_Mode PB_PromptAuto
82 Set HighLight_Row_State to True
83 End_Procedure // Construct_Object
84
85 // These two messages are maintained for backwards compatibility. Avoid
86 // using these. Use Prompt_Button_Mode instead
87 { MethodType=Property Visibility=Private Obsolete=True }
88 Procedure Set Auto_Create_Prompt_Button integer bState
89 Set Prompt_Button_Mode to (if(bstate,PB_PromptAuto,PB_PromptOff))
90 End_Procedure
91
92 { MethodType=Property Visibility=Private Obsolete=True }
93 Function Auto_Create_Prompt_Button Returns integer
94 Function_Return (Prompt_Button_Mode(self)=PB_PromptAuto)
95 End_Function
96
97 // If any items are checkboxes we also need to set their aspect.
98 // We can't set these for the protoobject
99 // because they won't get copied in to the real rows. However, setting
100 // aspect for the actual table items (even if there are none) works.
101 // Also, you must set this for every item because setting zero sets all other items.
102 //
103 Procedure End_Construct_Object
104 integer ele i ic
105 Forward Send END_CONSTRUCT_OBJECT // as you were.
106 Get prototype_object to ele // get prototype row object
107 get item_count of ele to ic // number of items in this object
108 decrement ic //
109 For i from 0 to ic
110 if (checkbox_item_state(ele,i)) Begin // if item is check
111 Set Button_aspect item i TO BASPECT_CHECKLIST // set check look
112 Set Form_Datatype item i to ASCII_WINDOW
113 end
114 else Set Button_aspect item i TO BASPECT_MULTIFORM // set form look
115 Loop
116 Send Create_Prompt_Button (Prompt_Button_Mode(self)) // add prompt symbol to headers is needed
117 //Send Set_up_rows
118 End_Procedure // END_CONSTRUCT_OBJECT
119
120 { MethodType=Event }
121 Procedure Header_Mouse_Click Integer Item#
122 Integer iRVal
123 Boolean bUsePrompt
124 // if prompt not used, do normal header stuff which supports reversing indexes.
125 If (prompt_button_mode(self)=PB_PromptOff) ;
126 Forward Send Header_mouse_Click Item#
127 else Begin
128 Get Msg_Activate_Column item# to iRval
129 // with VDF8 if prompt_button_mode (for headers) is OFF we will not send prompt.
130 If (not(iRval)) Send Prompt
131 end
132 End_Procedure
133
134 { MethodType=Property NoDoc=True }
135 Procedure Set Current_Item integer item#
136 Integer i
137 Integer iOldItem iNewItem
138 If (item# eq Current_item(Self) or batch_state(Self)) ;
139 Forward Set Current_Item to item#
140 Else Begin
141 get dynamic_update_State to i
142 Set dynamic_update_State to 0
143
144 Get Current_Item to iOldItem
145 Forward Set Current_Item to item#
146 Get Current_Item to iNewItem
147 If (iOldItem<>iNewItem) Begin
148 // Bug fix that makes sure we did not land in a skipfound field
149 Send SkipFoundAdjust // see comments in SkipFoundAdjust about this fix
150 End
151
152 If i eq 1 ;
153 set dynamic_update_State to 2
154 Else ;
155 if i eq 0 Set dynamic_update_State to 0
156 End
157 end_procedure
158
159 // find the prompt object for the passed prototype obj and item
160 // this augmented in DD to be a bit more fancy
161 { Visibility=Private }
162 Function Ele_Prompt_Object integer ele integer item# returns integer
163 Function_Return (Prompt_Object(ele,item#))
164 End_Function
165
166 // Create a prompt Buttons. This was created so the process of creating
167 // a prompt button object can be augmented.
168 // Although a param is passed, it is ignored here (used in forms). This
169 // checks all labels if auto-prompt is true, is a trailer prompt marker
170 // exists (...) and if the column a prompt. If so, it sets the trailer
171 // prompt marker (if it is not already there).
172 // To disable this entire process set Prompt_Button_Mode to PB_PromptOff
173 Procedure Create_Prompt_Button Integer CreateMode // 0=auto, 1=make, 2=remove
174 integer ele i ic
175 String sPrVal sLbl
176 integer PrValLen
177 Get Prompt_Button_Value to sPrVal
178// If (Auto_Create_Prompt_Button(self)=0 OR sPrVal='') ;
179// Procedure_Return
180 If (CreateMode=PB_PromptOff OR sPrVal='') ;
181 Procedure_Return
182 Length sPrVal to PrValLen
183 Get prototype_object to ele // get prototype row object
184 get item_count of ele to ic // number of items in this object
185 decrement ic
186 For i from 0 to ic
187 If (CreateMode=PB_PromptOn OR ;
188 (Ele_Prompt_Object(self,ele,i) AND ;
189 Shadow_State(ele,i)=0 ) ) Begin
190 Get Header_Label Item i to sLbl
191 If (sLbl<>'' AND right(sLbl,PrValLen)<>sPrVal) ;
192 Set Header_Label item i to (sLbl * sPrVal)
193 End
194 Loop
195 End_Procedure // Create_Prompt_Button
196
197 // used to create automatic embedded prompt buttons. Called by end_construct_object
198 { Visibility=Private }
199 Procedure CreateEmbeddedPrompts
200 handle hEle
201 integer i ic
202 Get prototype_object to hEle // get prototype row object
203 get item_count of hEle to ic // number of items in this object
204 decrement ic
205 For i from 0 to ic
206 // only create automatic buttons if there is no button predefined already and the
207 // column has a prompt object associated with it.
208 If ( (Form_Button(self,i)=FORM_BUTTON_NONE) AND Ele_Prompt_Object(self,hEle,i) ) Begin
209 Set Form_Button_Value i To (psEmbeddedButtonValue(self))
210 Set Form_Button i To FORM_BUTTON_PROMPT
211 End
212 Loop
213 End_Procedure
214
215 // changes to improve autofind logic.
216 { Visibility=Private }
217 procedure DoAutoFind
218 Integer bChanged bOn iCur
219 Get Current_item to iCur
220 // both changed_state and item_changed_state must be set for an autofind. If a default
221 // value is set item_changed_state will be true and changed_state will be false. We want to
222 // ignore these conditions
223 get item_changed_State item iCur to bChanged
224 if (bChanged and changed_state(self)) begin
225 get item_option item iCur AUTOFIND_BIT to bOn
226 if bOn begin
227 get item_option item iCur AUTOFIND_GE_BIT to bOn
228 Send entry_autofind (if(bOn,GE,EQ)) iCur
229 end
230 end
231 end_procedure
232
233 // changes to improve autofind logic. Before save do an autofind check for all items in row
234 { Visibility=Private }
235 function Row_save returns integer
236 Integer iFrom iTo iCrnt iOld iErr
237 Integer iOldDyn
238 Boolean bInRowSave
239
240 Get pbInRowSave to bInRowSave
241 If bInRowSave Begin
242 Function_Return 1
243 End
244
245 Get Current_item to iOld
246 Get base_item to iFrom
247 Get Item_limit to iTo
248 Move (iFrom+iTo-1) to iTo
249 Get Dynamic_Update_state to iOldDyn
250 Set Dynamic_Update_state to 0 // let's not show item changing
251 For iCrnt from iFrom to iTo
252 Set New_Item to iCrnt
253 Send DoAutoFind
254 loop
255 Set New_item to iOld
256 If iOldDyn ;
257 Set Dynamic_Update_state to 2 // 2=only paint what's dirty
258 forward get row_save to iErr
259 Function_Return iErr
260 end_function
261
262 // changes to improve autofind logic. Do autofind before changing
263 { MethodType=Event NoDoc=True }
264 Procedure Item_Change Integer iFromItem Integer iToItem returns integer
265 integer iNewTo
266 integer iOldCur iNewCur
267 if (Changing_State(self)) procedure_Return iToItem
268 // it is possible though unlikely that autofind will change the current item. If this
269 // happens we might need to recalculate where we should change from and to. This will
270 // only happen if autofind is on the main file which represents a pretty odd way to use
271 // tables.
272 Get Current_item to iOldCur
273 send DoAutoFind // if autofind is on main file, the entire table can be refreshed and current_item changed!
274 Get Current_item to iNewCur
275 If (iOldCur<>iNewCur) Begin // current_item changed. We will adjust iToItem and iFromItem to make the best of this
276 // if iFromItem was not the old current_item this is a very strange event - Just return
277 If (iOldCur<>iFromItem) procedure_return iNewCur
278 Move iNewCur to iFromItem // adjust iFromItem to be the newly changed current_item
279 // Adjust iToItem relative to change the in iFromItem. If the new iToItem is out of bounds, do nothing
280 Move (iToItem - iOldCur + iNewCur) to iToItem
281 If (iToItem<0 or iToItem>=item_count(self)) procedure_return iNewCur
282 end
283 forward get msg_item_change iFromItem iToItem to iNewTo
284 procedure_return iNewTo
285 end_Procedure
286
287
288 { Visibility=Private }
289 // this was added as a bug fix in 12.1. It is possible to navigate into a skipfound item if you
290 // are navigating from a blank grid row to an existing row. This happens because the runtime skipfound
291 // logic checks the file buffer's status and this happens before the row navigation. Changing this in runtime
292 // would be a deep change which could create side-effects. The safer fix here does a check after the item
293 // change has occurred. It checks to see if the item has landed in an improper skipfound field. If it has it
294 // tried to get out the field. This should workaround this issue with a minimum of side effects. You will only
295 // see a change with skipfound fields.
296 Procedure SkipFoundAdjust
297 Boolean bSkipFound
298 Integer iNewItem iFile iStat
299 Get Current_Item to iNewItem
300 Get item_option iNewItem SkipFound to bSkipFound
301 If bSkipFound Begin
302 Get data_file iNewItem to iFile
303 If (iFile) Begin
304 Get_Attribute DF_FILE_STATUS of iFile to iStat
305 If (iStat<>DF_FILE_INACTIVE) Begin
306 // if we landed on an active skipfound field, we need to move somewhere else
307 Send next // move to valid forward next item
308 If (Current_Item(Self)=iNewItem) Begin
309 // in rare case that forward navigate failed, go backwards
310 Send Previous
311 End
312 End
313 End
314 End
315 End_Procedure
316
317
318End_Class // DfTable
319
320
321Use DD_Deomx.pkg // mixin support for dd classes
322use DD_CdDeo.pkg // mixin support for exported descriptions
323
324{ ClassType=Abstract }
325{ HelpTopic=dbGridDD }
326Class dbGridDD is a dbGridDS
327 Import_Class_Protocol Extended_DEO_Mixin
328 Import_Class_Protocol Extended_DEO_Status_Help_Mixin
329 Import_Class_Protocol Code_Description_Mixin
330 // we are implementing Scan_servers directly in this class to get the embedded buttonF
331 //Import_Class_Protocol Extended_DEO_Prompt_Mixin
332
333 Procedure Construct_Object
334 Forward Send Construct_Object
335 Send Define_Code_Description_Mixin
336 End_Procedure // Construct_Object
337
338 { MethodType=Property NoDoc=True }
339 Procedure Set Current_Item Integer Itm
340 // we must if there are no items. In which case do nothing
341 If ( Focus(Desktop)=self AND ;
342 (Current_Item(self)<Item_Count(self)) AND ;
343 Item_Count(self) AND ;
344 Extended_deo_State(self) ) ;
345 Send Update_Focus_Field
346 Forward Set Current_Item to Itm
347 End_Procedure // Set Current_Item
348
349 { Visibility=Private }
350 Procedure Set New_Item Integer Itm
351 // we must if there are no items. In which case do nothing
352 If ( Focus(Desktop)=self AND ;
353 Item_Count(self) AND ;
354 Extended_deo_State(self) ) ;
355 Send Update_Focus_Field
356 Forward Set New_Item to Itm
357 End_Procedure // Set Current_Item
358
359 { Visibility=Private }
360 Function Ele_Prompt_Object integer ele integer item# returns integer
361 Integer iObj
362 Integer iDSO
363 Integer iFile
364 Integer iField
365 Forward Get Ele_Prompt_Object ele Item# to iObj
366 If (iObj=0 AND Extended_DEO_State(self)) Begin
367 // only check if not combo column (combos don't use prompt lists)
368 If not (Column_Combo_state(self,Item#) ) begin
369 Get Server to iDSO
370 If iDSO Begin
371 Get Data_File of ele item Item# to iFile
372 If iFile Begin
373 Get Data_Field of ele item Item# to iField
374 Get File_Field_Prompt_Object of iDSO iFile iField to iObj
375 // if checkbox don't show prompts for simple validation tables
376 If (iObj=DD_Global_Validation_Prompt_Object and checkbox_item_state(self,Item#)) ;
377 move 0 to iObj
378 End
379 End
380 End
381 End
382 Function_Return iObj
383 End_Function
384
385
386
387 //************************************************************************//
388 // Assign_DD_Label //
389 // This assigns the DEO's from the DD. This uses short labels and //
390 // sets column headers. //
391 //************************************************************************//
392 { Visibility=Private }
393 Procedure Assign_DD_Label Integer iDSO Integer iFile Integer iField ;
394 Integer iDEO Integer iItem
395 String sName
396 Get File_Field_Label of iDSO iFile iField DD_LABEL_SHORT to sName
397 Set Header_Label item iItem to sName
398 End_Procedure
399
400 // this fixes grid bug where insert_row loses the current changed value.
401 // this only happens when you've changed an item in the top row and you press
402 // the up arrow.
403 { NoDoc=True }
404 procedure Up_Row
405 Integer iCur
406 get current_item to iCur
407 // if row 0 and the current item is changed..just set the value to
408 // itself. Local value bypasses all the DD stuff (which will happen later)
409 if (current_row(self)=0 AND item_changed_state(self,iCur)) ;
410 set local_value item iCur to (value(self,iCur))
411 forward send up_row
412 End_Procedure
413
414 // Hook to set prompt buttons for header and embedded
415 { Visibility=Private }
416 Procedure Scan_Servers
417 Integer iMode
418 Forward Send Scan_Servers
419
420 If Not (Extended_DEO_State(self)) ;
421 Procedure_Return
422
423 Get Prompt_Button_Mode to iMode
424 If iMode eq PB_PromptAuto ;
425 Send Create_Prompt_Button iMode
426 If (pbEmbeddedPrompts(self)) send CreateEmbeddedPrompts
427 End_Procedure
428
429 // notification that an item option has been changed by the DD. This
430 // change already made to prototype object and must now be made items
431 // for that column. Note that only the options that matter trigger this
432 // notification
433 { Visibility=Private }
434 Procedure Item_Options_Changed integer iItem
435 integer i iRows iCols
436 integer iCur iOptions
437 get Row_Count to iRows
438 Get Item_Limit to iCols
439 Get Item_Options of (ProtoType_object(self)) iItem to iOptions
440 For i from 0 to (iRows-1)
441 Move (i * iCols + iItem) to iCur
442 Set Item_Options iCur to iOptions
443 Set Form_Options iCur to iOptions
444 Loop
445 end_procedure
446
447 // notification that an item mask value has been changed by the DD. This
448 // change already made to the first form must be made to all other items
449 // in the same column
450 { Visibility=Private }
451 Procedure Item_Mask_Changed integer iItem
452 integer i iRows iCols
453 string sMask
454 get Row_Count to iRows
455 Get Item_Limit to iCols
456 Get Form_Mask iItem to sMask
457 For i from 1 to (iRows-1)
458 Set Form_Mask (i * iCols + iItem) to sMask
459 Loop
460 set dynamic_update_state to 1 // required to paint changes
461 end_procedure
462End_Class
463
464Struct tGridComboHelper
465 boolean bDataOnly // internal. Data only no description
466 integer eCodeDisplay // can be accessed via get/set Column_Combo_Code_Display_Mode
467 string[] sDataValues // internal. array of data values
468End_Struct
469
470
471
472{ HelpTopic=dbGrid }
473Class dbGrid Is A dbGridDD
474
475 Procedure Construct_Object
476 forward send Construct_object
477
478 { Visibility=Private }
479 property integer piActiveColumn 0 // use by comboFillItem callback to figure out column
480
481 // Array of of helpers. One is set for each active combo column
482 { Visibility=Private }
483 Property tGridComboHelper[] pGridComboHelpers
484
485 end_procedure
486
487 { MethodType=Property Visibility=Private }
488 Function pGridComboHelper integer iColumn returns tGridComboHelper
489 tGridComboHelper GridComboHelper
490 tGridComboHelper[] GridComboHelpers
491 Get pGridComboHelpers to GridComboHelpers
492 // If this is accessed before the column helper is created, create it,
493 If (SizeOfArray(GridComboHelpers)<=iColumn) Begin
494 // if turning on a column combo, intialize the helper struct
495 Move CB_CODE_DISPLAY_DESCRIPTION to GridComboHelper.eCodeDisplay // default value
496 Set pGridComboHelper iColumn to GridComboHelper // initializes the struct
497 End
498 Else Begin
499 Move GridComboHelpers[iColumn] to GridComboHelper
500 End
501 Function_Return GridComboHelper
502 end_function
503
504 { MethodType=Property Visibility=Private }
505 Procedure Set pGridComboHelper integer iColumn tGridComboHelper GridComboHelper
506 tGridComboHelper[] GridComboHelpers
507 Get pGridComboHelpers to GridComboHelpers
508 Move GridComboHelper to GridComboHelpers[iColumn]
509 Set pGridComboHelpers to GridComboHelpers
510 End_Procedure
511
512 // aumgent to clear the datavalues in the helper object
513 { NoDoc=True }
514 Procedure Column_Combo_Delete_Data integer iColumn
515 tGridComboHelper GridComboHelper
516 forward send Column_Combo_delete_Data iColumn
517 Get pGridComboHelper iColumn to GridComboHelper
518 Move (ResizeArray(GridComboHelper.sDataValues,0)) to GridComboHelper.sDataValues
519 Set pGridComboHelper iColumn to GridComboHelper
520 End_Procedure
521
522// 12.1: helper is added as needed in pGridComboHelper, not here.
523// // augment to create and remove a helper object as needed.
524// { MethodType=Property NoDoc=True }
525// Procedure Set Column_Combo_State integer iColumn boolean bState
526// boolean bOldState
527// tGridComboHelper GridComboHelper
528// Get Column_Combo_State iColumn to bOldState
529// If ( not(bOldState) and bState) begin
530// // if turning on a column combo, intialize the helper struct
531// Move CB_CODE_DISPLAY_DESCRIPTION to GridComboHelper.eCodeDisplay // default value
532// set pGridComboHelper iColumn to GridComboHelper // initializes the struct
533// end
534// Forward Set Column_Combo_state iColumn to bState
535// End_Procedure
536
537 { MethodType=Property }
538 Function Column_Combo_Code_Display_Mode integer iColumn Returns integer
539 tGridComboHelper GridComboHelper
540 Get pGridComboHelper iColumn to GridComboHelper
541 Function_return GridComboHelper.eCodeDisplay
542 End_Function
543
544 { MethodType=Property }
545 { ColumnBased=True }
546 { Category=Appearance }
547 { EnumList="CB_Code_Display_Description, CB_Code_Display_Code, CB_Code_Display_Both" }
548 { InitialValue=CB_Code_Display_Description }
549 Procedure Set Column_Combo_Code_Display_Mode integer iColumn integer eVal
550 tGridComboHelper GridComboHelper
551 Get pGridComboHelper iColumn to GridComboHelper
552 Move eVal to GridComboHelper.eCodeDisplay
553 Set pGridComboHelper iColumn to GridComboHelper
554 End_Function
555
556 // For a column, pass data and return the description
557 { Visibility=Private }
558 Function Column_Combo_Data_To_Description integer iColumn String sValue returns String
559 tGridComboHelper GridComboHelper
560 integer i iItems
561
562 Get pGridComboHelper iColumn to GridComboHelper
563
564 If (GridComboHelper.bDataOnly or GridComboHelper.eCodeDisplay=CB_CODE_DISPLAY_CODE) begin
565 Function_Return sValue
566 end
567
568 // search for the data in our list of data values for this column
569 Move (SizeOfArray(GridComboHelper.sDataValues)) to iItems
570 For i From 0 to (iItems-1)
571 If (GridComboHelper.sDataValues[i]=sValue) Begin
572 Get Column_Combo_Value iColumn I to sValue
573 Function_Return sValue
574 end
575 end
576
577 // else if no match we will use the data as the description
578 Function_Return sValue
579 End_function
580
581 // for a column, pass description and find the data
582 { Visibility=Private }
583 Function Column_Combo_Description_to_Data integer iColumn String sValue returns String
584 integer iItem
585 tGridComboHelper GridComboHelper
586
587 Get pGridComboHelper iColumn to GridComboHelper
588
589 // if data only, just return the data
590 If (GridComboHelper.bDataOnly or GridComboHelper.eCodeDisplay=CB_CODE_DISPLAY_CODE) begin
591 Function_Return sValue
592 end
593
594 // some kind of translation is needed. See if we have a match in our combo-list and then find the data value
595 Get Column_Combo_Find iColumn 0 sValue to iItem
596 If (iItem >= 0) begin // if value is found
597 Move GridComboHelper.sDataValues[iItem] to sValue
598 end
599 // else if not found, Just return the data (validation can be handled by the dd).
600
601 Function_Return sValue
602 End_Function
603
604 // Public augmentation point. Pass current datavalue and all info
605 // in record buffer. Should return what you want to see on the screen.
606 // Augment to support various description/data Display formats.
607 //
608 { MethodType=Event }
609 Function Column_Combo_Description_Value integer iColumn integer eMode String sDescVal String sDataVal returns string
610 If (eMode=CB_CODE_DISPLAY_CODE) begin
611 Move sDataVal to sDescVal
612 end
613 Else If (eMode=CB_CODE_DISPLAY_BOTH) begin
614 Move (sDataVal * "-" * sDescVal) to sDescVal
615 end
616 // else if deisplay description, juyst return the description as is
617 Function_Return sDescVal
618 End_Function // Column_Combo_Description_Value
619
620
621
622 // Message to add Items to a list. Similar to Add_Item except
623 // it handles an optional second parameter. If no 2nd param the first
624 // is used in its place. This will normally be used inside of Fill_List.
625 //
626 // Send Column_Combo_Add_Item iColumn Descr_Value {Data_Value}
627 //
628 Procedure Column_Combo_Add_Item integer iColumn String sDescription String sDat
629 String sData
630 Integer iItem
631 tGridComboHelper GridComboHelper
632
633 // If sDat not passed, use sDescription for both display and database values
634 Move (If(num_arguments<3, sDescription, sDat)) to sData
635
636 Get Column_Combo_item_count iColumn to iItem // get this before we add the item.
637
638 Get pGridComboHelper iColumn to GridComboHelper
639
640 // If no items we have a new list. We want to know if it is data only
641 // or data descr. By default, assume that it is data-only
642 If (iItem=0) begin
643 Move True to GridComboHelper.bDataOnly
644 end
645
646 // this lets us convert the description. By default it returns the
647 // value passed. This allows you to pass a data param that gets
648 // changed for display purposes.
649 Get Column_Combo_Description_Value iColumn GridComboHelper.eCodeDisplay sDescription sData to sDescription
650
651 Forward send Column_Combo_Add_Item iColumn sDescription // used by the display list
652
653 Move sData to GridComboHelper.sDataValues[iItem] // the actual data value
654
655 // If description does not match the data we set this flag false
656 If (sDescription<>sData AND GridComboHelper.bDataOnly ) begin
657 Move false to GridComboHelper.bDataOnly
658 end
659 set pGridComboHelper iColumn to GridComboHelper
660 End_Procedure
661
662
663 // this is the one the callback calls. We must figure out the column and pass it on
664 { Visibility=Private }
665 Procedure ComboFillItem integer iItem string sData string sDescription ;
666 integer iFile RowId riId
667 integer iCol
668 Get piActiveColumn to iCol
669 Send ColumnComboFillItem iCol iItem sData sDescription iFile riId
670 End_Procedure
671
672 { Visibility=Private }
673 Procedure ColumnComboFillItem integer iCol integer iItem string sData string sDescription ;
674 integer iFile RowId riId
675 If (sDescription='') Move sData to sDescription
676 Send Column_Combo_Add_Item iCol sDescription sData
677 End_Procedure
678
679 { Visibility=Private }
680 Procedure Column_Combo_Add_Blank_Item integer iCol String Blank_Desc
681 integer iItems
682 Get Column_combo_Item_count iCol to iItems
683 Send ColumnComboFillItem iCol iItems '' Blank_Desc 0 (NullRowId())
684 End_Procedure
685
686 // Fills the list by loading the entire defined data-file
687 //
688 { MethodType=Event }
689 Procedure Column_Combo_Fill_List integer iCol
690 integer iFile iField eDisplayMode
691 handle hoSrvr hoEle hoTable
692
693 Send Column_Combo_Delete_Data iCol
694 Set piActiveColumn to iCol
695 Get Server to hoSrvr
696 Get Prototype_object to hoEle
697 Get Data_File of hoEle iCol to iFile
698 Get Data_Field of hoEle iCol to iField
699 If (hoSrvr AND iFile) Begin
700 Get Item_Field_Property GET_File_Field_Table_Object iCol to hoTable
701 // this does a callback of ComboFillItem for each item in the list
702 Send File_Field_Fill_List of hoSrvr iFile iField Self msg_ComboFillItem
703 If (hoTable AND not(Column_Combo_Entry_State(self,iCol)) AND Allow_Blank_State(hoTable)) begin
704 //Column_Combo_Allow_Undefined_state(Self,iCol)) begin
705 Send Column_Combo_Add_Blank_Item iCol DD_BLANK_CODE_DESCRIPTION
706 end
707 End
708 End_Procedure
709
710 // augment to update the DD each time this changes
711 { MethodType=Event Nodoc=True }
712 Procedure Combo_Item_Changed integer iItem
713 Forward Send combo_item_Changed iItem
714 Set Item_Field_Current_Value iItem to (Value(Self,iItem)) // this updates the DD
715 end_Procedure
716
717 // If a combo column, convert from description to data and forward
718 { MethodType=Property Visibility=Private }
719 Procedure Set Item_Field_Current_Value Integer iItem String sValue
720 integer iCol
721 Boolean bCombo
722 Get Column iItem to iCol
723 Get Column_Combo_State iCol to bCombo
724 If bCombo begin
725 Get Column_Combo_Description_to_data iCol sValue to sValue
726 end
727 Forward Set Item_Field_Current_Value iItem to sValue
728 End_Procedure // Set Item_Field_Current_Value
729
730 // If a combo column, convert from data to description and forward
731 { Visibility=Private }
732 Procedure Item_Value_Changed Integer iItem String sValue
733 Boolean bCombo
734 integer iCol
735 Get Column iItem to iCol
736 Get Column_Combo_State iCol to bCombo
737 If bCombo begin
738 Get Column_Combo_Data_to_Description iCol sValue to sValue
739 end
740 Forward Send Item_Value_Changed iItem sValue
741 End_Procedure
742
743
744 // augment to refresh all dynamic code tables
745 { Nodoc=True }
746 Procedure Activate returns integer
747 integer iRVal iCol iColumns
748 Handle hoTable
749 String sValue
750 boolean bCol
751
752 Forward Get MSG_Activate to iRVal
753
754 if not iRVal Begin
755 Get Item_limit to iColumns
756 For iCol From 0 to (iColumns-1)
757 Get Column_Combo_State iCol to bCol
758 If bCol begin
759 Get Item_Field_Property GET_File_Field_Table_Object iCol to hoTable
760 If (hoTable AND (Static_State(hoTable)=0 OR Table_Loaded_State(hoTable)=0)) Begin
761 Send Column_Combo_Fill_List iCol
762 End
763 End
764 Loop
765 End
766 Procedure_Return iRVal
767 End_Procedure // Activate
768
769 // augment to refill a combo validation table if needed (if the val table is not static)
770 Function Item_Entry Integer iMsg Integer iItem Returns Integer
771 Integer iResult iCol
772 Boolean bCol
773 Handle hoTable
774 Forward Get Item_Entry iMsg iItem to iResult
775 If (iResult=0) Begin
776 Get Column iItem to iCol
777 Get Column_Combo_State iCol to bCol
778 If bCol Begin
779 Get Item_Field_Property GET_File_Field_Table_Object iCol to hoTable
780 If (hoTable and (not(Static_State(hoTable)) or not(Table_Loaded_State(hoTable))) ) Begin
781 // if a combo column that has a DD validation table that is not statuc or not loaded, fill it now
782 Send Column_Combo_Fill_List iCol
783 End
784 End
785 End
786 Function_Return iResult
787 End_Function
788
789
790 // This Replaces DD message with one that understands
791 // description and data difference. //
792 { MethodType=Property Visibility=Private }
793 Function Data_Value integer iItem Returns String
794 string sValue
795 integer iCol
796 Boolean bCombo
797
798 Get Column iItem to iCol
799 Get Column_Combo_State iCol to bCombo
800 If bCombo begin
801 Get Value iItem to sValue
802 Get Column_Combo_Description_to_Data iCol sValue to sValue
803 end
804 else begin
805 Forward Get Data_Value iItem to sValue
806 end
807 Function_Return sValue
808 End_Function
809
810 // Augmented to handle entry_state=F combos. These type of combos must
811 // have a default value (since something always appears in the form). So
812 // we must check for cases where we have a value in the combo that is
813 // not reflected in the DD buffer. In such a case, update the buffer with
814 // a default value. Called by entry_defaults
815 //
816 { MethodType=Event Visibility=Private }
817 Procedure ColumnComboEntryDefaults integer iItem handle hoDSO integer iFile integer iField
818 integer iCol
819 boolean bColCombo bEntry
820
821 Get Column iItem to iCol
822 Get Column_combo_state iCol to bColCombo
823 If bColCombo begin
824 get Column_Combo_Entry_State iCol to bEntry
825 If not bEntry begin
826 // set default value in DD to the data value of current combo
827 Set File_Field_Default_Value of hoDSO iFile iField to (Data_Value(Self,iItem))
828 end
829 end
830 End_Procedure
831
832
833 // change so that list is initialized first. Also, set extended_deo_state before
834 // attempting to fill list (it needs that information).
835 { Visibility=Private }
836 Procedure Attach_Deo_To_Server
837 Handle hoSrvr hoEle
838 integer iCols iCol iItems
839 boolean bColCombo bExtended
840
841 Get Server to hoSrvr
842 If hoSrvr begin
843 Get Extended_DSO_State of hoSrvr to bExtended
844 Set Extended_DEO_State to bExtended
845 end
846 Get ProtoType_object to hoEle
847 Get Item_Count of hoEle to iCols
848 For iCol From 0 to (iCols-1)
849 Get Column_Combo_state iCol to bColCombo
850 If bColCombo begin
851 If not bExtended begin
852 Error DFERR_PROGRAM "Column Combos in DEO Grids must be attached to a DDO"
853 Move iCols to iCol // force exit from for loop
854 end
855 Else Begin
856 // if the list is empty fill it. This way static lists are only loaded one time
857 Get Column_Combo_Item_count iCol to iItems
858 If (iItems=0) Send Column_Combo_fill_list iCol
859 end
860 end
861 Loop
862 Forward Send Attach_deo_to_Server
863 End_Procedure
864
865 // augment to unset capslock if the display mode is not Code. If not code display the data that is displayed is
866 // not the data being sent to the DD and it should not be capslocked by the DD. Also set a bigger form_margin.
867 // You'd only need a big form_margin if entry_state is true which would be unlikely with a description combo (but it is supported).
868 { Visibility=Private }
869 Procedure Copy_Item_Options Integer iDSO Integer iFile Integer iField Integer iDEO Integer iItem
870 Integer eDisplayMode
871 Boolean bCombo bDataOnly
872 tGridComboHelper GridComboHelper
873 Forward Send Copy_Item_Options iDSO iFile iField iDEO iItem
874 If Not (Extended_deo_State(self)) Procedure_Return
875 Get Column_combo_state iItem to bCombo
876 If bCombo begin
877 Get pGridComboHelper iItem to GridComboHelper
878 Get Column_Combo_Code_Display_mode iItem to eDisplayMode
879 If (eDisplayMode<>CB_CODE_DISPLAY_CODE and not(GridComboHelper.bDataOnly)) Begin
880 Set Column_Capslock_State iItem to False // this might be been set true by the forward send of this message
881 set Form_Margin iItem to 255 // allow 255 characters which should be enough for any combo
882 set Form_DataType iItem to ASCII_WINDOW // If display description-- make it a string
883 end
884 end
885 End_Procedure
886
887
888 { Visibility=Private }
889 Procedure Set Local_Value integer iItem string sVal
890 integer iCol
891 Boolean bCombo
892 Get Column iItem to iCol
893 Get Column_Combo_State iCol to bCombo
894 If bCombo begin
895 get Column_Combo_Data_To_Description iCol sVal to sVal
896 end
897 Forward Set Local_Value iItem to sVal
898 End_Procedure // Set Local_Value
899
900 { NoDoc=True }
901 procedure Prompt
902 integer iCol
903 get Current_Col to iCol
904 If not (Column_Combo_State(self,iCol)) Begin
905 Forward send Prompt
906 end
907 end_procedure
908
909 { NoDoc=True }
910 // 12.1 Fix: We must augment Entry_update to handle column combos where the description is different than the
911 // data. In such a case, we do not want the internal entry_update ot move data from the column. Instead,
912 // we will do this manually. If the item should not be updated, we will stop it by setting its state temporarily
913 // to NoPut/NoEnter. This change is purposefully made to be as targeted as possible. It only
914 // changes entry_update for the one column. If you don't use combos, this has no impact at all.
915 // It might have made more sense to completely rewrite the entry_update but it seems safer to just make as
916 // small a change as spossible.
917 Procedure Entry_Update Integer iFile Integer iDoAll
918 Integer iBase iLimit iItem iDataFile iDataField iCols iNoPut iNoEnter
919 String sVal
920 Integer[] iDescCol iDescNoEnter iDescNoPut
921
922 // only do this with normal Finds and autofinds.. DD saves never calls this method. Finds always pass
923 // iDoAll as 1 (saves are 3). This check is done to keep the change as limited as possible
924 If (iDoAll=1) Begin
925 Get Item_Limit to iLimit // number of cols in row
926 Get Base_Item to iBase // first item in row
927 For iItem from 0 to (iLimit-1)
928 // We only care about column_combo_state=T, Column_Combo_display_modes that use descriptions
929 // and columns that are bound to the DD and columns that are not displayonly
930 If (Column_Combo_State(Self,iItem) and ;
931 Column_Combo_Code_Display_Mode(Self,iItem)<>CB_Code_Display_Code and ;
932 Data_File(Self,iItem)>0) Begin
933
934 Get Column_Option iItem noPut to iNoPut
935 Get Column_Option iItem noEnter to iNoEnter
936 // if it is noput and noenter it is displayonly and there is nothing to do
937 // Entry_update will update items unless both noput and noenter are set. You'd think
938 // that NoPut would stop it, but for finds it does not.
939 If not (iNoPut and iNoEnter) Begin
940 Move (iBase+iItem) to iDescCol[iCols] // keep track of the item to change
941 Move iNoEnter to iDescNoEnter[iCols] // the item's NoEnter
942 Move iNoPut to iDescNoPut[iCols] // the item's NoPut
943 // Changing this will stop the runtime from moving data from the item to the buffer
944 Set Item_Option iDescCol[iCols] noPut to True
945 Set Item_Option iDescCol[iCols] noEnter to True
946 Increment iCols
947
948 End
949 End
950 Loop
951 End
952
953 // the normal entry_update
954 Forward Send Entry_Update iFile iDoAll
955
956 // For any items we changed, we must manually do the Entry_update and restore the item state
957 For iItem from 0 to (iCols-1)
958 Get Data_Field iDescCol[iItem] to iDataField
959 Get Data_File iDescCol[iItem] to iDataFile
960 Get Data_Value iDescCol[iItem] to sVal // converts from description to data
961 Set_Field_Value iDataFile iDataField to sVal // upadate the buffer
962 // restore items
963 Set Item_Option iDescCol[iItem] noPut to iDescNoput[iItem]
964 Set Item_Option iDescCol[iItem] noEnter to iDescNoEnter[iItem]
965 Loop
966
967 End_Procedure
968
969
970End_Class
971
972