Module Table_ds.pkg
1//************************************************************************
2// File Name: table_DS.Pkg
3// Creation Date: Mon 02-17-1992
4// Author(s): John J. Tuohy
5//
6// Class: Table_DS <--- Data_List <---Wide_List
7//
8// Table_DS class
9//
10// Thu 02-06-1992 For now we are not supporting deferred states with tables
11// Thu 07-02-1992 Changed add row and clear row behavior F5 S+F10
12// Thu 01-14-1993 reset new-item after delete of row (search for date)
13// 1/30/93 - Rewritten and brought up to date for DAF style
14// 01/12/94 - Added No_Create_State (for old table compatability)
15// 03/18/94 - Modifed Add row and clear to return to column zero after
16// a blank row is created.
17// 07/21/94 - Added Save_row procedure to maintain interface compatability
18// with the old DAC tables.
19// 10/04/94 -JJT Row_Changing is changed to make add mode items insert new
20// rows instead of overwriting
21// 11/07/94 -JJT Row_Changing altered to refind the current_record when
22// a find above or below the end of list fails and a blank
23// row is not allowed.
24//05/31/96 - JJT Renamed package and class to table_DS. Table.pkg is now
25// used to intelligently apply DD Logic.
26//************************************************************************/
27
28//************************************************************************
29// Version: 1.0
30// 02-23-1993 : Created
31//
32// Author: John J. Tuohy
33//
34// 1. Adds Stop_UI_State Support
35// 2. Adds Should_Save Property (LS - deleted)
36// 3. Modifies Changed_State to check Should_save (fixes RT bug) (LS - deleted)
37// 4. Adds Child_Table_State Property. If TRUE then Child_Entering and
38// Child_exiting called during object entry and exit.
39// 5. Adds Child_Entering Function (null). Intended for augmentation
40// 6. Add Child_Exiting Function. Attempts to save table line before
41// exiting the object.
42// 7. Modifies request_clear behavior to be more intuitive (02-23-1993)
43// F5 = request_Clear = Undo any changes
44// Shift+F10 = add_or_remove_Row = add new row, remove current row
45// 8. Adds auto-prompt
46// 9. Adds Validate_all_items_state
47//10. Adds dependent_item support
48//11. Add checkbox item support to class
49//12. Adds movable support (ver 1.1)
50//13. Added Validate_mode (mixin). Table default to Validate_on_save_Next
51//14. Added entry_defaults (and better retains) through mixin
52//
53// 10-07-1993 Add include file with new exit_function procedure.
54// 03/11/94 Item 10 and 11 for 1.1
55// 03/17/94 Item 12 v.1.1
56// 03/22/94 (LS) send add_row during end_construct_object to prevent
57// invalid item number error with dependent_items.
58// 04/08/94 (LS) v1.1 Added DEO delegation.
59// 05/02/94 Added Validate_Mode to handle validation (and their errors)
60// in a more friendly fashion. Done with mixin class.
61// 07/18/94 Add Clear_mx mixin for better setting of default values
62//************************************************************************/
63//************************************************************************/
64// 12/22/94 JJT Merge Changes
65// Merged the 0 class into entry_form.
66// Added DEO delegate logic to request_???? messages.
67// Set Deo_delegate_mode to default to DELEGATE_NEVER
68//
69// 03/06/95 -JJT 1) Altered Clear, Add_or_remove_row, clear_a_Row and
70// request_delete to go to first enterable item (set Item)
71// and not column 0. Needed when col1 is displayonly.
72// 2) Altered Add_or_revmoe_row and Clear_a_row to not remove
73// a new unchanged row when it is the only row.
74// 3) Altered Remove_row so that when the last row is removed
75// that the item will attempt to remain in the same
76// column if the prior row.
77// 05/16/95 jjt Added refresh to set unsorted_state true after a save.
78//
79// 05/22/95 JJT Added object_validation to focus support in request_clear_all
80// (also see deodlgmx.pkg). Note not added to request_clear
81// since this is handled differently in table.
82// 09/04/95 JJT - Code Clean up (removed dead commented code)
83//************************************************************************/
84
85
86
87use Datalist.pkg // Super class Data_list
88use Verify.pkg // Verify Mixin
89Use FindEdit.pkg // Find Edit mixin
90Use Dep_item.pkg // v1.1 Auto-dependent-item support
91Use CkBox_Mx.pkg // v1.1 checkbox mixin support
92Use DEODlgMx.pkg // v1.1 DEO delegation support
93Use Val_MX.pkg // v1.1 test validate options
94Use Clear_mx.pkg // v1.1 new defaults upon clear
95
96Register_Function Row_Changed Returns Integer
97
98class Table_DS_mixin is a mixin
99// New Properties:
100//
101// Allow_Top_Add_State Dflt:False If true then you may cursor up
102// to the top of the list and an empty
103// space will open up
104//
105// Allow_Bottom_Add_State Dflt: TRUE If true then you may cursor down
106// to the end of the list and an empty
107// space will open up
108//
109// Allow_Insert_Add_State Dflt: TRUE If true then you may insert a new
110// row at the current position.
111//
112// No_Create_State Dflt: False If True you can not add any new row (it
113// overrides the above three states).
114
115// No_Delete_State Dflt: False If True deletes are disabled in table
116//
117// Read_Only_State Dflt: False If true no edits, adds, or deletes
118// are allowed.
119//
120// Auto_Refresh_State Dflt:True If true the the table updates itself
121// after a save with the exception of
122// being in add mode.. It will rebuild
123// after you exit add mode. If False it
124// will not rebuild until screen is
125// refreshed
126//
127// Needs_Refresh_State Dflt:False Maintained by system. If true than
128// a save might have changed the table
129// order.
130//
131 procedure Construct_Object integer img
132 forward send construct_object img
133 on_key kADD_MODE send add_or_remove_row PRIVATE // same as F5
134 { Visibility=Private }
135 { PropertyType=Boolean }
136 Property Integer Wrapping_State False
137 { Category=Behavior }
138 { PropertyType=Boolean }
139 Property Integer Allow_Bottom_Add_State True
140 { Category=Behavior }
141 { PropertyType=Boolean }
142 Property Integer Allow_Top_Add_State False
143 { Category=Behavior }
144 { PropertyType=Boolean }
145 Property Integer Allow_Insert_Add_State True
146 { Category=Data }
147 { PropertyType=Boolean }
148 Property Integer No_Create_State False
149 { Category=Data }
150 { PropertyType=Boolean }
151 Property Integer No_Delete_State False
152 { Category=Behavior }
153 { PropertyType=Boolean }
154 Property Integer Auto_Regenerate_State True
155 { Visibility=Private }
156 { PropertyType=Boolean }
157 Property Integer Unsorted_State False
158 { Category=Behavior }
159 { PropertyType=Boolean }
160 Property Integer Child_Table_State False
161
162 // used to stop recursive saves
163 { Visibility=Private }
164 Property Boolean pbInRowSave False
165
166 Send define_Verify //invoke verify support constructor
167 send define_find_edit //invoke find/edit support constructor
168 // for grids, begin/end of data do what they always did. Jump to top/botton of data in grid
169 // If developer wants a key to find first/last record of current file (which may be a parent)
170 // they should define the key and send find_first/find_last
171 on_key kBegin_of_Data SEND Beginning_of_Data PRIVATE
172 on_key kEnd_of_Data SEND End_of_Data PRIVATE
173 Send Define_Validate
174 Send Define_Clear_Defaults
175 Send Define_CheckBox_Support
176 Send Define_DEO_Delegate // v1.1
177
178 Set Auto_Save_State to True //tables change default for wrap-around save
179
180 // In Tables navigation item validation will only occur on NEXT events
181 // (tab or enter). Without this, you get all kinds of unwanted item
182 // validation errors when you navigate - this makes tables much happier
183 //
184 Set Validate_Mode to VALIDATE_ON_SAVE_NEXT
185
186 // It probably makes most sense to make table NOT delegate any
187 // of their request_ messages. Tables have a very different behavior
188 // then item based DEOs. Delegating to a client (most likely case)
189 // will not do us any good. In rare cases a table might want to
190 // delegate to another table (with the same server) and in this
191 // case you can change this property.
192 //
193 Set Deo_delegate_mode to DELEGATE_NEVER
194
195 end_procedure
196
197 IMPORT_CLASS_PROTOCOL VERIFY_Mixin //include Verification support module
198 IMPORT_CLASS_PROTOCOL FIND_EDIT_Mixin //include finding/editing support module
199 IMPORT_CLASS_PROTOCOL Validate_Mixin // ver 1.1
200 // Note: This augments: Next and Validate_Items
201 IMPORT_CLASS_PROTOCOL DEO_Delegate_Mixin // ver 1.1
202 IMPORT_CLASS_PROTOCOL DEO_Dependent_item_mixin //v1.1
203 IMPORT_CLASS_PROTOCOL Clear_Defaults_Mixin // ver 1.1
204
205 IMPORT_CLASS_PROTOCOL Entry_CheckBox_Mixin // v1.1
206 //
207 // Create the cbox object. This only gets created if required.
208 // We create this in the class and not the mixin because you seem to
209 // get odd results if objects are created in mixin procedures
210 //
211 { Visibility=Private }
212 Function Create_Cbox_Object returns Integer // returns ID of object
213 Integer Obj
214 Object CBox is a CBox_array // keep track of list of
215 Move self to Obj // items which are check_box items
216 End_Object
217 Function_return Obj
218 End_Function
219
220
221 //
222 // clear inserts a new line and goes to that line
223 // 03/06/95 JJT - adjust so a clear returns to the first enterable
224 // item and not the first column.
225 { Visibility=Private }
226 procedure Clear
227 integer oldDynUpdt base oldChg iRet
228 if (Line_Display_State(self)) send entry_clear 1
229 else if (CurrentRowHasRecord(self)) begin
230 // This has been changed to make sure that an exit and an entry message
231 // is always sent, even if thee actual item number does not change (which it will not)
232 if (item_count(self)) ;
233 get exec_exit (current_item(self)) to iRet
234 get Dynamic_Update_State to oldDynUpdt
235 set Dynamic_Update_State to false
236 get base_item to base //send insert blank row changed base_item...
237 send insert_blank_row (current_row(self))
238 get Changing_State to oldChg
239 set Changing_State to true
240 //set current_item to base // doesn't work if 1st is displayonly
241 set item to true // Go to first enterable column!
242 Send Trim_Page
243 Send entry_display 0 0 // redisplay active (parent) file
244 set Changing_State to oldChg
245 set Dynamic_Update_State to oldDynUpdt
246 get exec_entry (current_item(self)) to iRet
247 end
248 end_procedure
249
250 // public
251 procedure Request_Clear
252 Integer rval
253 If (Should_delegate_Clear(self)) ;
254 Delegate send request_clear
255 Else ;
256 Get Clear_a_row to rval
257 end_procedure
258
259 // internal
260 { Visibility=Private }
261 function validate_range integer from# integer to# returns integer
262 integer count retval oldcuritem
263 move 0 to retval
264 get current_item to oldcuritem
265 for count from from# to to#
266 set new_item to count
267 move (exec_Validate(self,count)) to retval
268 until retval ne 0
269 set new_item to oldcuritem
270 if retval ne 0 function_return count //return item# that failed
271 else function_return -1 //-1 means all ok
272 end_function
273
274 // Internal
275 // Function: Allow_row_Change - Rets 0 if ok to change
276 //
277 // We want to change row...See if it is allowed. it is allowed if:
278 // 1. There is no change - no problem
279 // 2. If changes and auto_save - attempt to make the save
280 // 3. If changes and not auto_save - verify_data Loss
281 //
282 { Visibility=Private }
283 Function Allow_Row_Change Returns Integer
284 Integer RetVal
285 If (Read_Only_State(self)) function_Return // Read only...who cares
286
287 if Not (Row_Changed(self)) Function_Return // nothing changed..aok
288
289 If (Auto_Save_State(self)) ; // autosave...attempt to save
290 Get Row_save to RetVal
291 Else Begin
292 Get Verify_Data_Loss to RetVal // not autosave..verify loss
293 If RetVal eq 0 send Find_RowId (CurrentRowId(self))
294 End
295 Function_Return RetVal
296 End_Function
297
298 // internal:
299 // Remove row. Add another line in the table to replace the missing
300 // row. Make sure the current record remains active
301 //
302 // 03/06/95 JJT - make sure we stay in the same column when we remove
303 // the last row in a table
304 { Visibility=Private }
305 Procedure Remove_Row Integer CurRow
306 Integer rowCount CurItem notAtEnd
307 RowId riRec
308 integer eRecordStatus
309 Get Current_item to CurItem // remember where we started..
310 send delete_row curRow // dump the row
311 //
312 // if no rows or the last row has a valid record than add a blank row.
313 // if their already is a blank row we leave it alone
314 get Row_Count to RowCount
315 Move (RowCount=0 OR RowHasRecord(self,rowCount-1) ) to NotAtEnd
316 if (notatend) begin
317 send add_row
318 increment rowCount
319 end
320 get fill_next_row (rowCount-1) to eRecordStatus // lets add to the table end
321 // if no record remove that row we added
322 //If (eRecordStatus<>rsNewAtBottom and notatend) send Delete_Row (rowCount-1)
323 If ( (eRecordStatus=rsCleared or eRecordStatus=rsNewAtTop or eRecordStatus=rsNewAtBottom) and notatend) send Delete_Row (rowCount-1)
324 //
325 // If we removed the last row - move curItem up 1 row.
326 If (CurItem >= Item_Count(self)) ;
327 Move (CurItem - Item_limit(self)) to CurItem
328 Set New_Item to CurItem // reset back to old item
329 set Row_base_item to (Current_row(self))
330 Get CurrentRowId to riRec // we will refind the current record
331 If not (isNullRowId(riRec)) Begin
332 send Find_RowId riRec
333 end
334 End_Procedure
335
336 // private. Figure out what the first enterable column is likely to be. We use
337 // this to figure out if an exit message will need to get sent
338 { Visibility=Private }
339 Function FirstEnterableColumn returns integer
340 integer hProto iCol bShadow
341 get prototype_object to hProto
342 for iCol from 0 to (item_count(hProto)-1)
343 get shadow_state of hProto iCol to bShadow
344 if not bShadow function_return iCol
345 loop
346 function_return -1
347 end_function
348
349
350 // internal
351 // Add_or_Remove_row: This is the table clearing handler. If:
352 // A. New row / Unchanged: Delete empty row if this is not the
353 // only row.
354 // B. old row / unchanged: If Allow_Insert_Add_State and not
355 // no_create_state, insert new row and enter.
356 // C. New row / changed: Verify_loss and create emtpy row. Goto 1st
357 // enterable column.
358 // D. old row / changed: Verify_loss and insert row.
359 // (was: restore to what was)
360 //
361 //
362 // 03/06/95 JJT Altered logic. Case A: If row is new and unchanged
363 // and there is only 1 row do nothing.
364 // Case C: Goto first enterable column (not col 0)
365 { Visibility=Private }
366 procedure add_or_Remove_row
367 integer dynUpdt Changed iCur iRet
368 RowId riCurRec
369 If (read_only_State(self) or no_create_state(self)) Procedure_return
370 Get Row_Changed to Changed
371 Get CurrentRowId to riCurRec
372 Get dynamic_update_State to dynUpdt
373 Set dynamic_update_State to false
374 If not Changed begin
375 If (isNullRowId(riCurRec)) Begin // A. new row-unchanged
376 // If we only have 1 blank, unchanged row, do not
377 // remove it (it already is blank).
378 If (row_Count(self)>1) Begin
379 Get Current_item to iCur
380 get exec_exit iCur to iRet // we always want an exit message.
381 send Remove_Row (Current_Row(self))
382 if (Unsorted_State(self)) send Display
383 // if item did not change (very possible) we still want an entry message
384 if (current_item(self)=iCur) get exec_entry iCur to iRet
385 end
386 end
387 Else ; // B. old row-unchanged
388 if (Allow_Insert_Add_State(self)) send Clear
389 End
390 Else Begin // changed...first do verify data loss
391 If not (Verify_Data_Loss(self)) Begin
392 If (isNullRowId(riCurRec)) Begin // C. new row-changed
393 // Check to see if we are likely to switch columns when we clear the row. If we are
394 // not we still want an exit message so we must provide it ourselves
395 Get Current_item to iCur
396 If (FirstEnterableColumn(self)=Column(self,iCur)) ; // if first enterable column is where we
397 get exec_exit iCur to iRet // are, we still an exit message.
398 Send Clear_Row (Current_Row(self))
399 Set Item to TRUE // move to first enterable column!
400 // if item did not change (very possible) we still want an entry message
401 if (current_item(self)=iCur) get exec_entry iCur to iRet
402 End
403 Else begin // D. old row-changed
404 send Find_RowId riCurRec // restore current record
405 //added 12/30/93 08:45 am
406 if (Allow_Insert_Add_State(self)) send Clear // and add new
407 End
408 End
409 End
410 set dynamic_update_State to dynUpdt
411 end_procedure
412
413 // internal
414 // Clear_a_row: This is the table clearing handler. If:
415 // A. New row / Unchanged: Delete empty row (should it be ignore?)_
416 // Only do this, if this is not the only row.
417 // B. old row / unchanged: ignore
418 // C. New row / changed: verify_loss and create emtpy row, goto 1st
419 // enterable column
420 // D. old row / changed: verify_loss and restore to what was
421 //
422 //
423 // 03/06/95 JJT Altered logic. Case A: If row is new and unchanged
424 // and there is only 1 row do nothing.
425 // Case C: Goto first enterable column (not col 0)
426 { Visibility=Private }
427 Function Clear_a_row Returns integer
428 integer dynUpdt Changed rVal iCur
429 RowId riCurRec
430 If (read_only_State(self)) Procedure_return
431 Get Row_Changed to Changed
432 Get CurrentRowId to riCurRec
433 Get dynamic_update_State to dynUpdt
434 Set dynamic_update_State to false
435 If not Changed begin
436 If (isNullRowId(riCurRec)) Begin // A. new row-unchanged
437 // If we only have 1 blank, unchanged row, do not
438 // remove it (it already is blank).
439 if (row_Count(self)>1) Begin
440 Get Current_item to iCur
441 get exec_exit iCur to rVal // we always want an exit message.
442 send Remove_Row (Current_Row(self))
443 if (Unsorted_State(self)) send Display
444 // if item did not change (very possible) we still want an entry message
445 if (current_item(self)=iCur) get exec_entry iCur to rVal
446 end
447 end
448 //Else ; // B. old row-unchanged
449 // if (Allow_Insert_Add_State(self)) send Clear
450 End
451 Else Begin // changed...first do verify data loss
452 Get Verify_Data_Loss to Rval
453 If Rval eq 0 begin
454 If (IsNullRowId(riCurRec)) begin // C. new row-changed
455 Get Current_item to iCur
456 // Check to see if we are likely to switch columns when we clear the row. If we are
457 // not we still want an exit message so we must provide it ourselves
458 If (FirstEnterableColumn(self)=Column(self,iCur)) ; // if first enterable column is where we
459 get exec_exit iCur to rVal // are, we still an exit message.
460 Send Clear_Row (Current_Row(self))
461 set item to TRUE // go to first enterable column
462 // if item did not change (very possible) we still want an entry message
463 if (current_item(self)=iCur) get exec_entry iCur to rVal
464 end
465 Else ; // D. old row-changed
466 send Find_RowId riCurRec
467 End
468 End
469 If (Row_count(self)=0) Send Append_Blank_row
470 set dynamic_update_State to dynUpdt
471 Procedure_Return rVal
472 end_procedure
473
474 // public message: Add_new_row
475 //
476 // Pass: loc as: -1=top, 0=current row, 1=bottom
477 //
478 //
479 procedure Add_New_Row Integer iLoc
480 integer iOpt iCur iCount
481 If (read_only_State(self)) Procedure_return
482 if (iLoc=0) Begin // if insert row at current position
483 // if a new rec with no changes we already have a cleared row..
484 // so we skip this step. If not add_or_remove_row will do it.
485 if not ( not(CurrentRowHasrecord(self)) AND ;
486 not(row_changed(self)) ) send Add_or_Remove_Row
487 End
488 Else Begin
489 If (Allow_Row_Change(self)=0) begin // check is change is legal
490 // we will attempt to move up or down in the same column. If the current col is noenter
491 // we will move to first enterable column. If this happens the most likely case is that
492 // it is item 0 and we've never attempted to find a valid column.
493 Get Current_item to iCur
494 Get Item_count to iCount
495 If (iCur<iCount) Begin // check in case we have an empty grid.
496 get item_option iCur NoEnter to iOpt
497 If iOpt begin // if noenter
498 set item to true // go to first enterable item
499 end
500 End
501
502 If (iLoc=-1) begin // add to top
503 forward send Beginning_of_Data
504 send up_row
505 end
506 else begin // add to bottom
507 forward send end_of_Data
508 send down_row
509 end
510 end
511 End
512 end_procedure
513
514 // Internal
515 // procedure Child_Wrapping integer direction
516 // integer base targetItem
517 // send activate
518 // get base_item to base
519 // if direction ne 0 begin
520 // Move (base + item_limit(self)) to targetItem
521 // if targetItem ge (item_count(self)) send add_row
522 // end
523 // else begin
524 // Move (base - 1) to targetItem
525 // if targetItem lt 0 move 0 to targetItem
526 // end
527 // set current_item to targetItem
528 // procedure_return 1
529 // end_procedure
530
531 { MethodType=Event Visibility=Private Obsolete=True }
532 procedure Child_Wrapping integer direction integer xorigID
533 integer targetItem origID
534
535 if NUM_ARGUMENTS gt 1 move xorigID to origID
536 else get focus of desktop to origID
537 if origID eq 0 move self to origID
538
539 send activate
540
541 if direction ne 0 begin //wrapping forward
542 Move (base_item(self) + item_limit(self)) ;
543 to targetItem
544 if targetItem GE (item_count(self)) send add_row
545
546 //
547 // save only when wrapping forward
548 //
549 if (auto_Save_State(origID)) send request_Save to origID
550 else if (auto_save_state(self)) send request_save
551
552 set Wrapping_State to true
553 set current_item to targetItem
554 end
555 else set Wrapping_State to true
556
557 set item to direction //sets current_item to first/last enterable item
558
559 set Wrapping_State to false
560 procedure_return 1
561 end_procedure
562
563 // public
564 // Sun 07-05-1992 Added send Append_Blank_Row to leave an blank line
565 // 03/06/95 - Move to first enterable item if a blank-row is added.
566 procedure Request_Delete
567 integer obj# dynUpdt
568 If (Should_delegate_delete(self)) ;
569 Delegate Send Request_Delete
570 else Begin
571 if (read_only_State(self)=0 and No_Delete_State(self)=0) Begin
572 Get Server to Obj#
573 if (can_Delete(Obj#) AND Verify_Delete(self)=0) Begin
574 set changed_state to false
575 Send Row_Delete
576 [not err] Begin
577 get dynamic_update_State to dynUpdt
578 set dynamic_update_State to false
579 Send Remove_Row (Current_Row(self))
580 If (Row_count(self)=0) Begin
581 Send Append_Blank_row
582 Set Item to True // go to first enterable item
583 End
584 Set dynamic_update_State to dynUpdt
585 End
586 end
587 end
588 end
589 end_procedure
590
591 // public
592 procedure Request_Save
593 integer curItem retval
594 If (should_delegate_save(self)) ;
595 delegate Send Request_Save
596 else begin
597 If (Read_Only_State(self)) Procedure_Return
598 get current_item to curItem
599 if (exec_validate(self,curItem) <> 0) procedure_return
600 if (exec_exit(self,curItem) <> 0) procedure_return
601 if (Row_changed(self)) begin
602 Get Row_save to Retval
603 If (Retval=0 AND Auto_regenerate_State(self)) send Display
604 end
605 end
606 end_procedure
607
608 // this allows us to save a record without it clearing regardless of
609 // the Auto_Clear_DEO_State value
610 //
611 Procedure Request_Save_No_Clear
612 integer oldclr
613 If (should_delegate_save(self)) ;
614 delegate Send Request_Save_no_Clear
615 else begin
616 Get Auto_Clear_DEO_State to OldClr // whatever it was
617 Set Auto_Clear_DEO_State to False // it is now NO!
618 send request_save // do your magic
619 Set Auto_Clear_DEO_State to OldClr // back to whatever it was
620 end
621 End_procedure
622
623 // internal
624 // Function: Row Changing
625 //
626 // New row / Unchanged: Delete empty row..then move
627 // old row / unchanged: Move
628 // Auto_Save -New row / changed: Save then move
629 // Auto_Save -old row / changed: Save then move
630 // ~Auto_Save -New row / changed: Verify data loss / empty / move
631 // ~Auto_Save -old row / changed: Verify data loss / restore /move
632 //
633 // 10/04/94 -JJT changed to make add mode items insert new rows
634 // instead of overwriting
635 { MethodType=Event Visibility=Private }
636 function Row_Changing integer from# integer to# returns integer
637 integer retval lim toRow fromRow rowcount
638 integer dynUpdt wasNew ROS NCS
639 integer bToMoved iOldCurrentItem iOldTo
640 Integer eRowStatus
641 Rowid riRec
642
643 get Current_item to iOldCurrentItem
644
645 get Item_Limit to lim
646 get row item from# to fromRow
647 Move (not(RowHasRecord(self,fromRow))) to wasNew
648
649 // check if change allowed....if not return from#
650 // this might save a new record..so we recheck the rec array
651 If ( Allow_Row_Change(self) ) Function_Return from#
652
653 If (not(RowHasRecord(self,fromRow))) begin
654 // if a new record..we have approval to remove this row..do so
655 get dynamic_update_State to dynUpdt
656 set dynamic_update_State to false
657 send Remove_row fromRow
658 set dynamic_update_State to dynUpdt
659 if to# ge from# Move (to#-lim) to to# // target has moved
660 // anytime we remove the row, we consider this a new item. We use this to
661 // determine if an item_entry must be forced. Sometimes the actual item number
662 // will not change (so entry will not be sent normally). In such a case, we will
663 // force it.
664 move 1 to bToMoved
665 end
666
667 get row item to# to toRow
668 set base_item to (toRow * lim)
669 set new_item to to#
670 // this handles auto add. Auto Add=T if Move 1 down and it was a new rec
671 if ( (toRow - fromRow = 1) AND (wasNew) ) Begin
672 // 10/04/94 - Changed to make new rows get inserted instead
673 // of replacing current item. At this point we are in insert mode
674 // and we've moved to the new row. If this new row has data
675 // (i.e., its eRowStatus is not -1,-2, or 0) then we need to insert a row,
676 // else we just need to clear the row. In either case, make sure the
677 // current_row number does not change (insert changes current row)
678 If (CurrentRowHasRecord(self)) ;
679 Send Insert_Blank_row (Current_Row(self)) // existing data
680 else ;
681 Send Clear_Row (Current_Row(self)) // row already blank
682 set base_item to (toRow * lim) // The current row might
683 set new_item to to# // change so we reset it here.
684 Move (NullRowId()) to riRec
685 End
686 Else Begin
687 Get Record_RowId Item toRow to riRec // the new rec number
688 // if eRowStatus -2 or -1 then we need to go to the database to fill
689 // in the next record.
690 If not (IsNullRowId(riRec)) Begin
691 Send ReadByRowId riRec // read the next record
692 Move 1 to eRowStatus // 1 means has a record
693 End
694 else Begin
695 get Fill_next_row toRow to eRowStatus
696 If (eRowStatus>1) move 1 to eRowStatus // in case fill_next_row still returns a record
697 end
698 //
699 If (eRowStatus=1) Begin
700 send Display_other_UI // fill out rest of UI
701 set base_item to (toRow * lim)
702 End
703 Else begin
704 // if top row couldn't add only allow an empty row on top if
705 // it is allowed
706 Get Row_Count to rowCount
707 // if row count is 1 then this is the only row we have and we
708 // will not delete it.
709 If (RowCount>1 and eRowStatus=rsNewAtTop AND ;
710 ( Allow_top_add_State(self)=0 OR ;
711 No_Create_State(self) OR ;
712 Read_Only_State(self) ) ) ;
713 Begin
714 Send Delete_Row toRow
715 Set New_item to to# // added 01-14-1993
716 // added 11/07/94 - make sure we've got the right record
717 // in the buffer
718 Send ReadByRowId (CurrentRowId(self))
719 End
720 else Begin
721 // if bottom row couldn't add only allow an empty row on bottom if
722 // it is allowed
723 If (RowCount>1 and eRowStatus=rsNewAtBottom AND ;
724 ( Allow_Bottom_add_State(self)=0 OR ;
725 No_Create_State(self) OR ;
726 Read_Only_State(self) ) ) ;
727 begin
728 Send Delete_Row toRow // (Current_Row(self))
729 // adjustment stuff since current row no longer exists..
730 // could probably be optimized
731 move from# to to#
732 If (top_item(self)<>0) Set Top_item to 0 // (top-1)
733 set new_item to to#
734 // added 11/07/94 - make sure we've got the right record
735 // in the buffer
736 Send ReadbyRowId (CurrentRowId(self))
737 end
738 else Send Clear_Row toRow
739 End
740 End
741 End
742
743 get current_item to iOldTo // keep track of current To item, it might change now
744 If (eRowStatus=1 and Auto_regenerate_State(self) and UnSorted_State(self)) begin
745 send Display
746 end
747 Else Begin
748 Send Trim_Page
749 end
750 get Current_Item to to#
751 // if trimming changed to#, we mark it (it is a move)
752 if (to#<>iOldTo) move 1 to bToMoved
753
754 // if we are not in column 0 we must validate up to this row
755 // for all to work properly.
756 if to# gt (toRow * lim) begin
757 move (validate_range(self,(toRow * lim),(to# - 1))) to retval
758 if retval ne -1 function_return retval //returns item# which failed
759 end
760
761 // This traps cases where moves occur but the final current item ends up
762 // being in the same position where it started. We still want to force an entry
763 // message. So if we know a move has occured but it does not look like the item
764 // actually changed, we will force the message
765 if (bToMoved and to#=iOldCurrentItem) ;
766 get exec_entry to# to retval
767
768 function_return to#
769 end_function
770
771 // public
772 procedure Beginning_of_Data
773 If (Allow_Row_Change(self)=0) ;
774 forward send beginning_of_data
775 end_procedure
776
777 // public
778 procedure End_of_Data
779 If (Allow_Row_Change(self)=0) ;
780 forward send end_of_data
781 end_procedure
782
783 // public
784 Procedure Scroll Integer eDirection Integer iNumLines
785 integer dynUpdt
786 get dynamic_update_State to dynUpdt
787 set dynamic_update_State to false
788 If (Allow_Row_Change(self)=0) begin
789 // if rec is new and we have more than 1 row..remove the record
790 If ( Not(CurrentRowHasRecord(self)) AND Row_Count(self)>1 ) begin
791 // if a new record..we have approval to remove this row..do so
792 send Remove_row (Current_Row(self))
793 end
794 forward send Scroll eDirection iNumLines
795 end
796 set dynamic_update_State to dynUpdt
797 end_procedure
798
799
800 //
801 // Augment to unset the UnSorted_State Flag
802 //
803 { Visibility=Private }
804 Function Load_Page Integer Row# Returns Integer
805 Integer Retval
806 Forward Get Load_Page Row# to Retval
807 Set UnSorted_State to False
808 Function_Return Retval
809 End_Function
810
811 // Private:
812 // Control Mouse down so that it will move into an empty
813 // row just like down arrow does. Also if pressed anyhwere at the
814 // bottom of an empty then move to the last valid row.
815 //
816 { MethodType=Event NoDoc=True }
817 Procedure Mouse_Down Integer iWindowNumber Integer iPosition
818 integer rCount Row#
819 If iWindowNumber Gt 0 Begin
820 Decrement iWindowNumber
821 Get Row Item iWindowNumber to Row# // zero based
822 Get Row_Count to rCount // one based
823 If Row# GE rCount Begin
824 If ( rCount=0 OR ;
825 ( RowHasRecord(self,rcount-1) AND ;
826 Allow_Bottom_Add_State(self) AND ;
827 No_Create_State(self)=0 ) ) ;
828 //Begin
829 // If (Allow_row_Change(self)) Procedure_Return
830 Send Add_row
831 //end
832 Else Decrement rCount
833 Move ( rCount*Item_limit(self)+;
834 Column(self,iWindowNumber)) to iWindowNumber
835 End
836 //
837 Increment iWindowNumber
838 End
839 Forward Send Mouse_down iWindowNumber iPosition
840 End_Procedure
841
842 //-------------------------------------------------------------------
843 // messages requiring server services
844 //------------------------------------------------------------------
845 //
846
847 // public
848 procedure Request_Clear_All
849 integer srvr# retval foc
850 If (Should_delegate_Clear(self)) ;
851 Delegate send request_clear_all
852 Else Begin
853 get Server to srvr#
854 if (Read_Only_State(self)=0 AND ;
855 Row_Changed(self)) begin
856 if (Verify_Data_Loss(self) <> 0) ;
857 procedure_return
858 end
859 Get Focus of desktop to Foc
860 get Object_Item_Validation of Foc to retval
861 set Object_Item_Validation of Foc to false
862 if Srvr# ne 0 send clear_all to Srvr#
863 else send entry_clear_all 0
864 if (Auto_Top_Panel_State(self)) send beginning_of_panel
865 set Object_Item_Validation of Foc to retval
866 end
867 end_procedure
868
869 // Support passing of optinal Item to autofind on. If not passed the
870 // runtine will figure it out. Always pass the autofind-item. The runtime
871 // also calls this not passing an item but it figure it out.
872 { Visibility=Private }
873 Procedure Entry_Autofind integer eFindMode integer iItem
874 integer srvr# file# datafile# field# oldDisp oldChg item#
875 If (Num_Arguments>=2) ;
876 Move iItem to Item# // if item passed, use it for autofind
877 else ;
878 Get autofind_item to item#
879 get data_file item item# to datafile#
880 If DataFile# le 0 Procedure_Return
881 get data_field item item# to field#
882 get Server to srvr#
883 get main_file to file#
884 get Changing_State to oldChg
885 set Changing_State to TRUE
886 if srvr# ne 0 Begin
887 get line_display_State to oldDisp
888 if datafile# ne file# set line_display_State to true
889 //----remove deferred_state support
890 //send Item_Find to srvr# mode datafile# field# TRUE FALSE ;
891 // (Deferred_State(self))
892 send Item_Find to srvr# eFindMode datafile# field# TRUE FALSE FALSE
893 set line_display_State to oldDisp
894 end
895 Else begin
896 forward send entry_autofind eFindMode
897 if datafile# eq file# send display
898 end
899 set Changing_State to oldChg
900 end_procedure
901
902 // public
903 // FindEdit support behavior
904 //
905 procedure Request_Find integer mode integer entUpdtFlag
906 integer dataFile ser# mainfile# dfrdState
907 If (Should_delegate_find(self)) ;
908 delegate Send Request_Find mode entUpdtFlag
909 else begin
910 get Data_File to dataFile
911 If (DataFile=0) Procedure_return // if no datafile, skip the find
912 get Server to ser#
913 get Main_file to mainfile#
914 if (Read_Only_State(self) AND mainfile#<>DataFile) ;
915 Procedure_return
916 if (ser# <> 0 AND dataFile > 0) begin
917 get Deferred_State to dfrdState
918 send Item_Find to ser# mode dataFile ;
919 (Data_Field(self,CURRENT)) entUpdtFlag TRUE dfrdState
920 //--Re-add deferred_state support
921 //send Item_Find to ser# mode dataFile ;
922 // (Data_Field(self,CURRENT)) entUpdtFlag TRUE FALSE
923 [found] if dfrdState begin
924 if dataFile eq mainfile# send display
925 else send entry_display 0 0
926 end
927 end
928 else begin
929 send entry_find mode
930 [found] Begin
931 if datafile eq mainfile# send display
932 else send entry_Display 0 0
933 end
934 end
935 end
936 end_procedure
937
938 // public
939 // FindEdit support behavior
940 //
941 procedure Request_Superfind integer mode
942 integer obj# file# mainfile#
943 If (Should_delegate_find(self)) ;
944 delegate Send Request_SuperFind mode
945 else begin
946 get Server to obj#
947 get data_file to file#
948 if file# gt 0 begin
949 get main_file to mainfile#
950 if obj# ne 0 begin
951 indicate err false
952 send Request_SuperFind to obj# mode file# ;
953 (data_field(self,CURRENT))
954 [not found] begin
955 if mode lt 2 error DFERR_FIND_PRIOR_BEG_OF_FILE
956 else error DFERR_FIND_PAST_END_OF_FILE
957 end
958 end
959 else begin
960 send entry_superfind mode mainfile#
961 [found] begin
962 if file# eq mainfile# send display
963 else send entry_Display 0 0
964 end
965 end
966 end
967 End
968 end_procedure
969
970 // internal
971 { Visibility=Private }
972 procedure Row_Delete
973 integer Srvr#
974 get Server to Srvr#
975 indicate err false
976 //----remove deferred_state support
977 //if (Deferred_State(self)) ;
978 // send Request_Assign to Srvr# 0 //0 means main_file of Server
979 send Request_Delete to Srvr#
980 // add this because the server does not 0 current_record
981 // didn't work...sent off refresh Sun 07-05-1992
982 //send Request_Assign to Srvr# 0 //0 means main_file of Server
983 end_procedure
984
985 // This isbeing marked public because it is the one message that is always sent when a row in a grid is saved
986 // All other DEOs can use request_save for both sending and augmentation to catch a save. Here we need to
987 // send request_save but augment row_save (which i scalled by request_save and others).
988 function Row_save returns integer
989 Handle hoServer
990 Integer iErr iRetVal iMainFile
991 Boolean bInRowSave
992
993 // 12.1: Added a recursion check for saving. A save validation error could trigger a navigation
994 // event which could trigger another save. If in a save and we encounter another save, we consider
995 // this to be a validation error
996 Get pbInRowSave to bInRowSave
997 If bInRowSave Begin
998 Function_Return 1
999 End
1000
1001 Set pbInRowSave to True
1002 Get Server to hoServer
1003 Get Request_Validate of hoServer to iRetVal
1004 If (iRetVal<>0) Begin
1005 Move 1 to iErr
1006 End
1007 Else Begin
1008 If (Verify_Save(Self) = 0) Begin
1009 Send Save_Row // we do this for backwards interface reasons
1010 Move (If((Err),3,0)) to iErr
1011 End
1012 Else Begin
1013 Move 2 to iErr
1014 End
1015 End
1016 Set pbInRowSave to False
1017 Function_Return iErr
1018 End_Function
1019
1020 // internal
1021 // This exists to maintain compatability with the DAC table
1022 // interface (people might have augmented this). Note: It is better
1023 // to augment the row_save function because it returns a status value
1024 { Visibility=Private }
1025 Procedure Save_row
1026 Handle hoDD
1027 integer iRec iMain
1028 RowId riNewRec
1029 get Server to hoDD // we just assume that a server exists
1030 indicate err false // this would not get called if it did
1031 send Request_Save of hoDD // not.
1032 [not err] begin
1033 Get Main_File to iMain
1034 // if recnum based table, we will store the recnum in the status array. This is
1035 // done for backwards compatibility. Developers should only use the status check
1036 If (IsRecnumTable(self, iMain)) begin
1037 Get FileRecord to iRec
1038 set CurrentRecordStatus to iRec
1039 end
1040 else begin
1041 set CurrentRecordStatus to 1 // >0 means has record
1042 end
1043
1044 get FileRowid to riNewRec
1045 set currentRowId to riNewRec
1046 Set UnSorted_State to True
1047 end
1048 end_Procedure
1049
1050 // internal
1051 { Visibility=Private }
1052 Function Row_Changed Returns Integer
1053 Integer Srvr# ch
1054 Get Server to Srvr#
1055 get changed_state to Ch
1056 Function_Return (Ch OR ;
1057 (Srvr#<>0 AND Should_Save_Row(Srvr#)) )
1058 End_Function
1059
1060 { MethodType=Property }
1061 Function Should_Save Returns Integer // added 07-24-1992 - could replace row_changed
1062 // 02-21-1993 should only check fo change if items exist.
1063 If (Item_Count(self)) ;
1064 Function_Return (Row_Changed(self))
1065 //**Function_Return (Row_Changed(self))
1066 End_function
1067
1068 // Child_Entering and Child_Exiting are only called when Child_Table_State is
1069 // true. When a table is nested inside another DEO (a header / table
1070 // condition) you have different needs.
1071
1072 // Function Child_Entering
1073 //
1074 // By default this does nothing. If you return a non-zero value the table
1075 // will not be entered. Very useful. You will often use this to make sure
1076 // that 1) it is valid to enter the table and 2) that the header is
1077 // saved before entering the table.
1078 //
1079 { MethodType=Event }
1080 Function Child_Entering Returns Integer
1081 End_function
1082
1083 // Function Child_Exiting
1084 //
1085 // You can stop the exiting by returning a non-zero value. By default this
1086 // save the current record. If the save fails the exiting is stopped. Note
1087 // that the object ID you are entering is passed. This can be useful to
1088 // know. If you are exiting to a form or editor that is part of the table
1089 // (often a child of the table object) you may not want to save the table
1090 // line. If the object you are entering is part of the header, you would
1091 // probably want to save the table. Note that the default errs on the side
1092 // of caution (it always saves the table).
1093 //
1094 { MethodType=Event }
1095 Function Child_Exiting Integer toObj# Returns Integer
1096 Integer ret_val
1097 Boolean bInRowSave
1098
1099 // 12.1: if we are in the middle of saving a row, we do nothing which will most likely
1100 // allow the exit. This could happen if you have a validation error that requires
1101 // you to change the focus to the object where the validation failed.
1102 Get pbInRowSave to bInRowSave
1103 If bInRowSave Begin
1104 Function_Return 0
1105 End
1106
1107 Get Should_Save to Ret_Val
1108 if Ret_Val Send Request_Save
1109 Get Should_Save to Ret_Val
1110 Function_Return Ret_Val
1111 end_Function
1112
1113 // Entering is augmented to call Child_Entering if Child_Table_State=T
1114 //
1115 { MethodType=Event }
1116 Procedure Entering
1117 Integer ret_val
1118 integer bChanged
1119 Boolean bHasRecord
1120
1121 // If we are entering a new table (new record, unchanged) then
1122 // we should clear the row so we trigger any needed defaults from the DD0
1123 // This fixes a problem where entering a an empty child table does not show
1124 // the DD defaults.
1125 Get Row_Changed to bChanged
1126 Get CurrentRowHasRecord to bHasRecord
1127 // we do this here so that this dflts are set before the item_exit message
1128 // is sent, which is sent in the forward of entering.
1129 If ( not(bChanged) and Not(bHasRecord) ) ;
1130 send clear_row (Current_Row(self))
1131
1132 if (Child_Table_State(self)) Get Child_Entering to Ret_val
1133 If ret_Val eq 0 Forward get MSG_Entering to Ret_Val
1134 Procedure_Return Ret_Val
1135 end_procedure
1136
1137 // Exiting is augmented to call Child_Exiting if Child_Table_State=T
1138 //
1139 { MethodType=Event NoDoc=True }
1140 Procedure Exiting Handle hoDestination Returns Integer
1141 Integer ret_val
1142 if (Child_Table_State(self)) Get Child_Exiting hoDestination to Ret_val
1143 If ret_Val eq 0 Forward get MSG_Exiting hoDestination to Ret_Val
1144 Procedure_Return Ret_Val
1145 end_procedure
1146
1147
1148 // fix for RT bug in dependent_items that causes invalid item number
1149 // error if items don't exist when update_dependent_items occurs.
1150 procedure End_Construct_Object
1151 forward send end_construct_object
1152 send add_row
1153 end_procedure
1154
1155 // 05/16/95 -Augment so that refreshes that are part of a save sets the sorted
1156 // state to false. This probably belongs in data_list but this would require
1157 // moving all of the unsorted_state logic into that class. Not for now.
1158 //
1159 { MethodType=Event NoDoc=True }
1160 procedure Refresh integer notifyMode
1161 if (Batch_State(self)) Procedure_return
1162 Forward Send refresh notifyMode
1163 // If save on main-file, we are no longer sorted properly
1164 if ( notifyMode=MODE_SAVE AND ;
1165 Main_File(self)=Main_file(Server(self)) ) ;
1166 Set Unsorted_State to TRUE
1167 end_procedure
1168
1169 // disallow if row cannot be changed or it the record is new
1170 Procedure Reorder_List Integer iNewCol
1171 RowId riId
1172 Get currentRowId to riId
1173 If ( not(IsNullRowId(riId)) And (Read_Only_State(self) or not(Row_Changed(self)))) begin
1174 if (NUM_ARGUMENTS<1) ;
1175 Forward send reorder_list
1176 else ;
1177 Forward send reorder_list iNewCol
1178 end
1179 End_procedure
1180
1181 // disallow if row cannot be changed or it the record is new
1182 // but still set the new ordering
1183 { Visibility=Private }
1184 Procedure DoSetOrderingDirection integer bReverse
1185 RowId riId
1186 Get currentRowId to riId
1187 If ( not(IsNullRowId(riId)) And (Read_Only_State(self) or not(Row_Changed(self)))) ;
1188 forward send DoSetOrderingDirection bReverse
1189 End_Procedure
1190
1191
1192end_class
1193