Module cDbCJGridDataSource.pkg
1Use ui
2Use cCJGridDataSource.pkg
3Use Datadict.pkg
4
5Enum_List
6 Define ufUpdateToDD
7 Define ufUpdateToBuffer
8End_Enum_List
9
10
11Class cCJGridCachedDataSource is a cCJGridDataSource
12
13 Procedure Construct_Object
14 Forward Send Construct_Object
15
16 { Visibility=Private }
17 Property Integer piRowCount 0 // Normalized Rows in cache
18 { Visibility=Private }
19 Property Integer piRowOffset 0 // Unnormalized off set to rows (if not zero)
20 { Visibility=Private }
21 Property Boolean pbAtTop False // has cache discovered first record
22 { Visibility=Private }
23 Property Boolean pbAtEnd False // has cache discovered last record
24 { Visibility=Private }
25 Property Integer piMinPageSize 50 // minimum number of records to page whenever a page is performed
26 { Visibility=Private }
27 Property Integer piMaxCacheSizeAllowed 150 // max size of cache, 0 - unlimited
28 { Visibility=Private }
29 Property Integer piMaxCacheRange -1 // internal - used to keep track of the largest range the grid has requested.
30 { Visibility=Private }
31 Property Boolean pbLoadAll False // if true, load all data with first page event
32 { Visibility=Private }
33 Property Boolean pbStaticData False // determines if datasource is static - once loaded it does not change
34 { Visibility=Private }
35 Property Handle Server // The DD server
36 { Visibility=Private }
37 Property Integer piGridOrdering -1 // Ordering from Grid. See Ordering for actual order which may differ
38 { Visibility=Private }
39 Property Boolean pbDDReadMode False // if true we never actually find the record in the dd - just read
40 { Visibility=Private }
41 Property Boolean pbReverseOrdering False // is data source reversed?
42 End_Procedure
43
44 { NoDoc=True }
45 Function DataIsStatic Returns Boolean
46 Boolean bStatic
47 Get pbStaticData to bStatic
48 Function_Return bStatic
49 End_Function
50
51 // ordering is calculated. If the server has a value, we use that. If not, use the grid's ordering
52 { Visibility=Private }
53 Function Ordering Returns Integer
54 Handle hoSever
55 Integer iOrdering
56 Get Server to hoSever
57 Get Ordering of hoSever to iOrdering
58 If (iOrdering=-1) Begin
59 Get piGridOrdering to iOrdering
60 End
61 Function_Return iOrdering
62 End_Function
63
64 { NoDoc=True }
65 Function AllDataIsLoaded Returns Boolean
66 Boolean bAtTop bAtEnd
67 Get pbAtTop to bAtTop
68 Get pbAtEnd to bAtEnd
69 Function_Return (bAtTop and bAtEnd)
70 End_Function
71
72 { NoDoc=True }
73 Function RowOffset Returns Integer
74 Integer iTop
75 Get piRowOffset to iTop
76 Function_Return iTop
77 End_Function
78
79 { NoDoc=True }
80 Function RowCount Returns Integer
81 Integer iRowCount
82 Get piRowCount to iRowCount
83 Function_Return iRowCount
84 End_Function
85
86 // return the maximum cache size needed for this grid.
87 // This is tied to the logic in PageInRows and how it caches records. It uses
88 // the current maximum range passed in.
89 { NoDoc=True }
90 Function CurrentMaxCache Returns Integer
91 Integer iMax iPage iMaxC
92 Get piMaxCacheRange to iMax
93 Get piMaxCacheSizeAllowed to iMaxC
94 If (iMax=-1 or iMaxC=0) Begin
95 Function_Return iMaxC
96 End
97 // cache must be big enough for 3X the range so we can cache a page before and after
98 // plus it must be big enough handle the min-page, which basically says if you need
99 // even one row, you should page in this minimum number of extra rows
100 Get piMinPageSize to iPage
101 Move ((3 * iMax) + (2*iPage)) to iMax
102 // use the required iMax size or if we've set a larger maximum cache, use that
103 Function_Return (iMax max iMaxC)
104 End_Function
105
106 // currently I adjust first and last row but I don't do anything with the information
107 // First row is the current top row (first displayable row)
108 // Last row is at-least the last displayable. Last - first gives us the range
109 { NoDoc=True }
110 Procedure PageInRows Integer ByRef iFirstRow Integer ByRef iLastRow
111 tDataSourceRow[] DataSource
112 Boolean bAtTop bAtEnd bDirty bLoadAll
113 Integer iSize iRowCount iNewRowCount iRowOffset iCacheSize iMinPage
114 Integer iNewTop iNewRows iRowsToAdd iMaxCacheSizeAllowed iMaxRange iCrntMaxRange iCrntMaxCache
115 Integer iMain
116 Handle hoDD
117 RowID riCurrentRow
118
119 // We need to make sure our cache size is big enough to handle the range of records
120 // requested. To do that we must keep track of the range of records requested and always
121 // track the largest range.
122 Get piMaxCacheRange to iMaxRange
123 Move (iLastRow - iFirstRow +1) to iCrntMaxRange
124 If (iMaxRange<iCrntMaxRange) Begin
125 Set piMaxCacheRange to iCrntMaxRange
126 End
127 // adjust what we are looking for in a first and last row
128 Move (iFirstRow-iCrntMaxRange) to iFirstRow // allow a page before the first row
129 Move (iLastRow+iCrntMaxRange) to iLastRow // allow a fill page after the last row
130
131
132 Get pDataSource to DataSource
133 Get pbAtTop to bAtTop
134 Get pbAtEnd to bAtEnd
135 Get pbLoadAll to bLoadAll
136 Get piRowOffset to iRowOffset
137 Move (SizeOfArray(DataSource)) to iCacheSize
138
139 // note that piRowOffset can only be 0 or negative. If negative it means that rows have been added to the top
140 // but the grid has not been normalized. When normalized, the offset is set back to 0.
141
142 // within range. nothing to do
143 If ( (iFirstRow>=iRowOffset or bAtTop) and ((iLastRow<iCacheSize+iRowOffset) or bAtEnd)) Begin
144 Procedure_Return
145 End
146
147 If bLoadAll Begin
148 Move 0 to iMaxCacheSizeAllowed
149 Move 0 to iMinPage
150 End
151 Else Begin
152 Get CurrentMaxCache to iMaxCacheSizeAllowed
153 Get piMinPageSize to iMinPage
154 End
155
156 Get Server to hoDD
157 Get Main_File of hoDD to iMain
158 Move (GetRowID(iMain)) to riCurrentRow
159
160
161 // See if we need to page above, add to top
162 If (iFirstRow<iRowOffset and not(bAtTop) ) Begin
163
164 // Ok to pass negative rows. means find up
165 If (iMinPage=0) Begin
166 Move -1 to iRowsToAdd
167 End
168 Else Begin
169 // if we are adding any rows, we make sure we add at least a minimum number
170 Move ( (iRowOffset-iFirstRow) max iMinPage) to iRowsToAdd
171 End
172
173 Send OnPageData True iRowsToAdd (&DataSource) (&bAtTop) (&bAtEnd)
174 Set pDataSource to DataSource
175 Set pbAtEnd to bAtEnd
176 Set pbAtTop to bAtTop
177
178 Get RowCount to iRowCount // this is the old rowcount and will not change
179 Move (SizeOfArray(DataSource)) to iSize // new size of cache
180 Move (iSize - iCacheSize) to iNewRows // number of rows added
181 Move (iRowOffset - iNewRows ) to iNewTop // reduce cache top by that amount. This can only be negative
182
183 // if we could not add all the rows we needed adjust first-row
184 If (iNewRows<iRowsToAdd) Begin
185 Move (iFirstRow + (iRowsToAdd - iNewRows)) to iFirstRow
186 End
187
188 // a synch is needed if:
189 // 1) rowoffset is not zero (can only be negative or 0), if negative, we've added rows to the top.
190 // 2) the max cache size is exceeded
191 If ( (iNewTop<0) or (iMaxCacheSizeAllowed<>0 and iMaxCacheSizeAllowed<iSize) ) Begin
192 Set pbDataSourceSynchRequired to True
193 End
194
195 Set piRowOffset to iNewTop
196
197 Move iSize to iCacheSize
198 Move iNewTop to iRowOffset
199
200 End
201
202 // if the last row requires we find down
203
204 If (iLastRow>=iRowOffset+iCacheSize and not(bAtEnd)) Begin
205
206 If (iMinPage=0) Begin
207 Move -1 to iRowsToAdd
208 End
209 Else Begin
210 // if we are adding any rows, we make sure we add at least a minimum number
211 Move ( (iLastrow+1 - (iRowOffset+iCacheSize)) max iMinPage) to iRowsToAdd
212 End
213
214 Send OnPageData False iRowsToAdd (&DataSource) (&bAtTop) (&bAtEnd)
215 Set pDataSource to DataSource
216 Set pbAtEnd to bAtEnd
217 Set pbAtTop to bAtTop
218
219 Get RowCount to iRowCount // this is the old rowcount and will not change
220 Move (SizeOfArray(DataSource)) to iSize // new size of cache
221 Move (iSize - iCacheSize) to iNewRows // number of rows added
222
223 // if we could add all the rows we needed adjust lastrow
224 If (iNewRows<iRowsToAdd) Begin
225 Move (iLastRow - (iRowsToAdd - iNewRows)) to iLastRow
226 End
227
228 // a synch is needed if:
229 // 1) rowoffset is not zero (can only be negative or 0),
230 // 2) at End and the old rowcount and the new size don't agree
231 // 3) the max cache size is exceeded
232 If ( (iRowOffset<0) or (bAtEnd and (iSize<>iRowCount)) or (iSize>iRowCount ) or (iMaxCacheSizeAllowed<>0 and iMaxCacheSizeAllowed<iSize)) Begin
233 Set pbDataSourceSynchRequired to True
234 End
235 End
236
237 If (not(IsSameRowID(riCurrentRow,GetRowID(iMain)))) Begin
238 Send ReadByRowId of hoDD iMain riCurrentRow
239 End
240
241 End_Procedure
242
243 // Adjust RowCount and RowOffset to best fit the cache data.
244 { NoDoc=True }
245 Function NormalizeDataSource Integer iTopRow Returns Integer
246
247 tDataSourceRow[] DataSource
248 Boolean bAtTop bAtEnd bLoadAll bDataSourceSynchRequired
249 Integer iSize iRowCount iNewRowCount iRowOffset iCacheSize iMinPage iNewOffset
250 Integer iNewRows iRowsToAdd iSelectedRow iMaxCacheSizeAllowed iOffsetChange
251 Integer iNewStart iNewEnd
252 Move 0 to iOffsetChange
253
254 Get pDataSource to DataSource
255 Get pbAtTop to bAtTop
256 Get pbAtEnd to bAtEnd
257 Get piRowOffset to iRowOffset
258 Get piRowCount to iRowCount
259
260 Get pbLoadAll to bLoadAll
261
262 If (not(bLoadAll)) Begin
263 Get CurrentMaxCache to iMaxCacheSizeAllowed
264 End
265
266 Move (SizeOfArray(DataSource)) to iCacheSize
267
268 Move iRowCount to iNewRowCount
269 Move iRowOffset to iNewOffset
270
271 // if at top adjust rowcount and RowOffset
272 If (bAtTop) Begin
273 Move (-iRowOffset) to iRowsToAdd
274 Move (iRowCount + iRowsToAdd) to iNewRowCount
275 Move (iRowOffset + iRowsToAdd) to iNewOffset
276 End
277 // else if new top is negative, must normalize to 0
278 Else If (iNewOffset<0) Begin
279 Move (-iRowOffset) to iRowsToAdd
280 Move (iRowCount + iRowsToAdd) to iNewRowCount
281 Move (iRowOffset + iRowsToAdd) to iNewOffset
282 End
283
284 If bAtEnd Begin
285 Move (iNewOffset + iCacheSize) to iNewRowCount
286 End
287 Else If (iNewRowCount < (iNewOffset +iCacheSize)) Begin
288 Move ((iNewOffset + iCacheSize) - iNewRowCount ) to iRowsToAdd
289 Move (iNewRowCount + iRowsToAdd) to iNewRowCount
290 End
291
292 Move (iNewOffset - iRowOffset) to iOffsetChange
293
294 // adjust selected row by offset change
295
296 Get piSelectedRow to iSelectedRow
297 If (iSelectedRow<>-1) Begin
298 Move (iSelectedRow + iOffsetChange) to iSelectedRow
299
300 If (iSelectedRow<0 or ((iSelectedRow - iNewOffset) >=iCacheSize)) Begin
301 Error DFERR_PROGRAM "Assert: Invalid SelectedRow in NormalizeDataSource"
302 End
303
304 End
305 Move False to bDataSourceSynchRequired
306
307 // Handle shrinking the cache if needed.
308 // Before shrinking the cache we make sure that the selected row will not
309 // be cached out. If it is, we don't shrink the cache
310 If (iMaxCacheSizeAllowed<>0 and iCacheSize>iMaxCacheSizeAllowed) Begin
311
312 // shrink cache. Shrink part that is furthest away from the displayed rows
313 If (iTopRow > (iMaxCacheSizeAllowed/2)) Begin
314
315 // remove from top.
316 Move (iCacheSize-iMaxCacheSizeAllowed) to iNewStart
317 Move (iCacheSize-1) to iNewEnd
318 If (iSelectedRow<>-1 and iSelectedRow>=iNewStart) Begin
319 Move (iSelectedRow-iNewStart) to iSelectedRow
320 Move (CopyArray(DataSource,iNewStart,iNewEnd)) to DataSource
321 Move (iOffsetChange-iNewStart) to iOffsetChange
322 Move False to bAtTop
323 Move iMaxCacheSizeAllowed to iNewRowCount
324 Set pDataSource to DataSource
325 End
326 Else Begin
327// if we set this it checks too often. If here, our cache is too big because the user is hanging onto a selected
328// record that's out of range. Once a selection is made and the user does something to change the cache size, this will be adjusted anyway
329// Move True to bDataSourceSynchRequired
330 End
331 End
332 Else Begin
333
334 // Remove from bottom
335 Move 0 to iNewStart
336 Move (iMaxCacheSizeAllowed-1) to iNewEnd
337 If (iSelectedRow<>-1 and iSelectedRow<=iNewEnd) Begin
338 Move (CopyArray(DataSource,iNewStart,iNewEnd)) to DataSource
339 Move False to bAtEnd
340 Move iMaxCacheSizeAllowed to iNewRowCount
341 Set pDataSource to DataSource
342 End
343 Else Begin
344// see above note
345// Move True to bDataSourceSynchRequired
346 End
347 End
348 End
349
350 Set piSelectedRow to iSelectedRow
351 Set piRowCount to iNewRowCount
352 Set piRowOffset to 0 // iNewOffset
353 Set pbAtTop to bAtTop
354 Set pbAtEnd to bAtEnd
355 Set pbDataSourceSynchRequired to bDataSourceSynchRequired
356
357 Function_Return iOffsetChange
358
359 End_Function
360
361 { Visibility=Private }
362 Function AdjustRowForOffset Integer iRow Returns Integer
363 Integer iOffset
364 // if not normalized (dirty) adjust Row so it points to correct datasource array index
365 Get piRowOffset to iOffset
366 Function_Return (iRow - iOffset)
367 End_Function
368
369 { NoDoc=True }
370 Function PageInMatchingRow RowID riId Returns Integer
371 tDataSourceRow[] DataSource
372 Boolean bAtTop bAtBottom bStaticData
373 Integer iSize iIndex iRowCount iCacheIndex iNewOffset
374 Integer iOffsetChange
375 Integer iFirst iLast
376
377 Move 0 to iCacheIndex
378 Get pbAtEnd to bAtBottom
379 Get pbAtTop to bAtTop
380 Get pbStaticData to bStaticData
381
382 If (IsNullRowID(riId)) Begin
383 Function_Return -1
384 End
385
386 Get FindRowIdInCache riId to iIndex
387
388 // first attempt to find in the cache
389 If (iIndex<>-1) Begin
390 Get piRowOffset to iNewOffset
391 Function_Return (iIndex + iNewOffset)
392 End
393
394 // if data is all loaded and it is static, it doesn't exist
395 If (bStaticData and bAtTop and bAtBottom) Begin
396 Function_Return -1
397 End
398// If (bAtTop and bAtBottom) Begin
399// Function_Return -1 // the entire grid is loaded and this record does not exist
400// End
401
402 Send SelectRow -1 False
403
404 // this finds the one matching record
405 Send OnPageInMatchingRow riId (&DataSource)
406 If (SizeOfArray(DataSource)=0) Begin
407 Function_Return -1 // not found nothing changes
408 End
409
410 Move 0 to iIndex
411 Set pDataSource to DataSource
412 Set pbAtTop to False
413 Set pbAtEnd to False
414 Set piRowCount to (SizeOfArray(DataSource))
415 Set piRowOffset to 0
416
417 // now page in a set or data around the matching records
418 // pass in a good range, which we can get from piMaxCacheRange
419 Move 0 to iFirst
420 Get piMaxCacheRange to iLast // will be -1 if it has never been set
421 If (iLast=-1) Begin
422 Get piMinPageSize to iLast
423 Move (iLast/2) to iLast
424 End
425 Decrement iLast
426 Send PageInRows (&iFirst) (&iLast)
427 Get NormalizeDataSource 0 to iNewOffset
428 Get FindRowIdInCache riId to iIndex
429
430 Set pbDataSourceSynchRequired to True
431
432 Function_Return iIndex
433
434 End_Function
435
436 { NoDoc=True }
437 Procedure PageInLastRow
438 Integer iIndex
439 RowID riId
440 Boolean bAtEnd bStaticData
441 Get pbAtEnd to bAtEnd
442 Get pbStaticData to bStaticData
443 If (not(bStaticData and bAtEnd)) Begin
444 Send Reset
445 Get OnReadLastRecord to riID
446 Get PageInMatchingRow riId to iIndex
447 End
448 End_Procedure
449
450 { NoDoc=True }
451 Procedure PageInFirstRow
452 Integer iIndex
453 RowID riId
454 Boolean bAtTop bStaticData
455 Get pbAtTop to bAtTop
456 Get pbStaticData to bStaticData
457 If (not(bStaticData and bAtTop)) Begin
458 Send Reset
459 Get OnReadFirstRecord to riID
460 Get PageInMatchingRow riId to iIndex
461 End
462 End_Procedure
463
464 { Visibility=Private }
465 Function FindRowIdInCache RowID rId Returns Integer
466 tDataSourceRow[] DataSource
467 tDataSourceRow DataSourceRow
468 Integer iIndex
469 Move rId to DataSourceRow.riID
470 Get pDataSource to DataSource
471 Move (SearchArray(DataSourceRow,DataSource,Desktop,RefFunc(ComparetDataSourceRowId))) to iIndex
472 Function_Return iIndex
473 End_Function
474
475 Function FindExternalDataInCache Returns Integer
476 Handle hoServer
477 Integer iFile iIndex iNewOffset
478 RowID riID
479 Get Server to hoServer
480 Get Main_File of hoServer to iFile
481 Move (GetRowID(iFile)) to riID
482 Get FindRowIdInCache riID to iIndex
483 If (iIndex<>-1) Begin
484 // if not normalized (dirty) adjust index
485 Get piRowOffset to iNewOffset
486 Move (iIndex + iNewOffset) to iIndex
487 End
488 Function_Return iIndex
489 End_Function
490
491
492 { NoDoc=True }
493 Procedure Reset
494 tDataSourceRow[] DataSource
495 Send SelectRow -1 False
496 Set piRowOffset to 0
497 Set piRowCount to 0
498 Set pbAtTop to False
499 Set pbAtEnd to False
500 Set pDataSource to DataSource
501 Set pbDataSourceSynchRequired to True
502 End_Procedure
503
504 // This loads all data passed and assumes that this is all of the data.
505 { NoDoc=True }
506 Procedure InitializeDataSource tDataSourceRow[] DataSource
507 Integer iSize
508 Integer iOffsetChange
509
510 Send Reset
511 Move (SizeOfArray(DataSource)) to iSize
512 Set pDataSource to DataSource
513 Set pbAtTop to True
514 Set pbAtEnd to True
515 Set pbStaticData to True
516 Set piRowCount to iSize
517 Set piRowOffset to 0
518 Get NormalizeDataSource 0 to iOffsetChange
519 End_Procedure
520
521 { NoDoc=True }
522 Function CreateDataSourceRow Returns tDataSourceRow
523 tDataSourceRow DataSourceRow
524 Handle[] DataSourceColumnObjects
525 Integer iColumn iColumns
526 String sValue
527
528 Get pDataSourceColumnObjects to DataSourceColumnObjects
529 Get ColumnCount to iColumns
530 Send OnSetTag (&DataSourceRow)
531 For iColumn from 0 to (iColumns-1)
532 Get InitialValue of DataSourceColumnObjects[iColumn] to sValue
533 Move sValue to DataSourceRow.sValue[iColumn]
534 Loop
535 Function_Return DataSourceRow
536 End_Function
537
538 // This handles translation of find modes to make reverse ordering
539 // work. Pass the mode and return the mode, translated if reverse ordering is needed
540 { Visibility=Private }
541 Function FindMode Integer eFindMode Returns Integer
542 Boolean bReverseOrdering
543 Get pbReverseOrdering to bReverseOrdering
544 If (bReverseOrdering) Begin
545 Case Begin
546 Case (eFindMode=GE) Move (LE) to eFindMode
547 Case (eFindMode=GT) Move (LT) to eFindMode
548 Case (eFindMode=LT) Move (GT) to eFindMode
549 Case (eFindMode=LE) Move (GE) to eFindMode
550 Case (eFindMode=FIRST_RECORD) Move (LAST_RECORD) to eFindMode
551 Case (eFindMode=LAST_RECORD) Move (FIRST_RECORD) to eFindMode
552 Case End
553 End
554 Function_Return eFindMode
555 End_Function
556
557 { Visibility=Private }
558 Procedure Establish_Find_Mode Integer eFindMode
559 Handle hoServer
560 Integer iFile iOrdering
561 Get Server to hoServer
562 Get FindMode eFindMode to eFindMode // mode might change if reverse ordering
563 Get Main_File of hoServer to iFile
564 Get Ordering to iOrdering
565 Send Establish_Find_Direction of hoServer eFindMode iFile iOrdering
566 End_Procedure
567
568 { Visibility=Private }
569 Procedure Read_Next_Record
570 Handle hoServer
571 Get Server to hoServer
572 If hoServer Begin
573 Send Locate_Next of hoServer
574 End
575 End_Procedure
576
577 { Visibility=Private }
578 Function ReadRecordInBuffer Returns Boolean
579 Boolean bFound
580 RowID riId
581 Handle hoServer
582 Integer iFile
583 Send Establish_Find_mode Ge
584 Send Read_Next_record
585 Move (Found) to bFound
586 If not bFound Begin
587 Get OnReadLastRecord to riId
588 End
589 Else Begin
590 Get Server to hoServer
591 Get Main_File of hoServer to iFile
592 Move (GetRowID(iFile)) to riId
593 End
594 Function_Return (not(IsNullRowID(riId)))
595 End_Function
596
597
598 { Visibility=Private }
599 Procedure OnPageInMatchingRow RowID riId tDataSourceRow[] ByRef DataSource
600 tDataSourceRow DataSourceRow
601 Boolean bFound
602 Handle hoDD
603 Integer iIndex iFile
604 Get Server to hoDD
605 Get Main_File of hoDD to iFile
606 Get Ordering to iIndex
607 Send ReadByRowId of hoDD iFile riId
608 Move (Found) to bFound
609 If bFound Begin
610 Get CreateDataSourceRow to DataSourceRow
611 Move DataSourceRow to DataSource[0]
612 End
613 End_Procedure
614
615 // if iRowstoAdd is minus, add to top, else add to bottom
616 { Visibility=Private }
617 Procedure OnPageData Boolean bFindUp Integer iRowsToAdd tDataSourceRow[] ByRef DataSource Boolean ByRef bAtTop Boolean ByRef bAtEnd
618 tDataSourceRow DataSourceRow
619 Boolean bFound bFindAll
620 Integer iRow_Count iSize iNew
621 Handle hoDD
622 Integer iFile iIndex iMax
623
624 Move (SizeOfArray(DataSource)) to iRow_Count
625 Move (iRowsToAdd=-1) to bFindAll
626
627 Get Server to hoDD
628 Get Main_File of hoDD to iFile
629 Get Ordering to iIndex
630
631 // find down
632 If (not(bFindUp)) Begin
633
634 If (iRow_Count>0) Begin
635 Send ReadByRowId of hoDD iFile DataSource[iRow_Count-1].riID
636 End
637 Else Begin
638 Move True to bAtTop
639 End
640
641 Move True to bAtEnd
642 Move (iRowsToAdd + iRow_Count) to iMax
643
644 Send Establish_Find_Mode (GT)
645 Send Read_Next_Record
646 Move (Found) to bFound
647 Move True to Found
648 While (bFound)
649 Get CreateDataSourceRow to DataSourceRow
650 Move DataSourceRow to DataSource[iRow_Count]
651 Increment iRow_Count
652 Send Read_Next_Record
653 Move (Found) to bFound
654
655 If ( not(bFindAll) and (bFound) and (iMax <iRow_Count)) Begin
656 Move False to bFound
657 Move False to bAtEnd
658 End
659 Loop
660
661 End
662 // find up
663 Else Begin
664
665 If (iRow_Count>0) Begin
666 // if the top row is null we assume we are at the top
667 If (IsNullRowID(DataSource[0].riID)) Begin
668 Move True to bAtTop
669 Procedure_Return
670 End
671 Send ReadByRowId of hoDD iFile DataSource[0].riID
672 End
673
674 Move True to bAtTop
675 Move (iRowsToAdd) to iMax
676
677 Send Establish_Find_Mode (LT)
678 Send Read_Next_Record
679 Move (Found) to bFound
680 While (bFound)
681
682 Get CreateDataSourceRow to DataSourceRow
683 Move (InsertInArray(DataSource,0,DataSourceRow)) to DataSource
684 Decrement iMax
685 Increment iRow_Count
686 Send Read_Next_Record
687 Move (Found) to bFound
688
689 If (not(bFindAll) and (bFound) and (iMax<=0 )) Begin
690 Move False to bFound
691 Move False to bAtTop
692 End
693 Loop
694
695 End
696 End_Procedure
697
698 { Visibility=Private }
699 Function OnReadFirstRecord Returns RowID
700 Handle hoDD
701 Integer iFile eFindMode iOrder
702 Get Server to hoDD
703 Get Ordering to iOrder
704 Get Main_File of hoDD to iFile
705 Get FindMode FIRST_RECORD to eFindMode
706 Send Request_Read of hoDD eFindMode iFile iOrder
707 Function_Return (GetRowID(iFile))
708 End_Function
709
710
711 { Visibility=Private }
712 Function OnReadLastRecord Returns RowID
713 Handle hoDD
714 Integer iFile eFindMode iOrder
715 Get Server to hoDD
716 Get Ordering to iOrder
717 Get Main_File of hoDD to iFile
718 Get FindMode LAST_RECORD to eFindMode
719 Send Request_Read of hoDD eFindMode iFile iOrder
720 Function_Return (GetRowID(iFile))
721 End_Function
722
723 { Visibility=Private }
724 Procedure OnSetTag tDataSourceRow ByRef DataSourceRow
725 Handle hoDD
726 Integer iMain
727 Get Server to hoDD
728 Get Main_File of hoDD to iMain
729 Move (GetRowID(iMain)) to DataSourceRow.riID
730 End_Procedure
731
732
733End_Class
734
735Class cDbCJGridDataSource is a cCJGridCachedDataSource
736
737 Procedure Construct_Object
738 Forward Send Construct_Object
739 { Visibility=Private }
740 Property Boolean pbNotifyingExternalDD False
741 End_Procedure
742
743 { NoDoc=True }
744 Function IsSelectedRowNew Returns Boolean
745 Handle hoServer
746 Boolean bHasRecord bDDReadMode
747 Integer iSel
748 tDataSourceRow[] Datasource
749
750 Get SelectedRow to iSel
751 If (iSel=-1) Begin
752 Function_Return False
753 End
754 Get pbDDReadMode to bDDReadMode
755 If bDDReadMode Begin
756 Get AdjustRowForOffset iSel to iSel
757 Get pDataSource to Datasource
758 Move (not(Datasource[iSel].bNewRow)) to bHasRecord
759 End
760 Else Begin
761 Get Server to hoServer
762 Get HasRecord of hoServer to bHasRecord
763 End
764 Function_Return (not(bHasRecord))
765 End_Function
766
767 { NoDoc=True }
768 Function IsSelectedRowChanged Returns Boolean
769 Handle hoServer
770 Boolean bChanged bDDReadMode
771 Get pbDDReadMode to bDDReadMode
772 If bDDReadMode Begin
773 // if deferred, we have no way of knowing if the row is changed so we just assum
774 // it's not. That means that changes are accepted as they are
775 Function_Return False
776 End
777 Get Server to hoServer
778 Get Should_Save_Row of hoServer to bChanged
779 Function_Return bChanged
780 End_Function
781
782 // only can be saved if there is a change
783 { NoDoc=True }
784 Function ShouldSaveSelectedRow Returns Boolean
785 Boolean bChanged
786 Get IsSelectedRowChanged to bChanged
787 Function_Return (bChanged)
788 End_Function
789
790 { NoDoc=True }
791 Function CanSaveRow Returns Boolean
792 Boolean bReadOnly bDDReadMode
793 Handle hoServer
794 Get pbDDReadMode to bDDReadMode
795 Get Server to hoServer
796 Get Read_Only_State of hoServer to bReadOnly
797 Function_Return (not(bDDReadMode) and not(bReadOnly))
798 End_Function
799
800 { NoDoc=True }
801 Function CanDeleteRow Returns Boolean
802 Handle hoServer
803 Boolean bCanDelete bDDReadMode
804 Get pbDDReadMode to bDDReadMode
805 Get Server to hoServer
806 Get Can_Delete of hoServer to bCanDelete
807 Function_Return (not(bDDReadMode) and bCanDelete)
808 End_Function
809
810 { NoDoc=True }
811 Function CanAddRow Returns Boolean
812 Boolean bReadOnly //bIsNew
813 Handle hoServer
814 Get Server to hoServer
815 Get Read_Only_State of hoServer to bReadOnly
816 Function_Return (not(bReadOnly))
817 End_Function
818
819 { NoDoc=True }
820 Function SaveSelectedRow Returns Boolean
821 Handle hoServer
822 Boolean bCancel bDDReadMode
823 Get pbDDReadMode to bDDReadMode
824 If bDDReadMode Begin
825 // should never get called. Perhaps should be an error
826 Function_Return True
827 End
828 Get Server to hoServer
829 Send Request_Save of hoServer
830 Move (Err) to bCancel
831 Function_Return bCancel
832 End_Function
833
834 { NoDoc=True }
835 Function DeleteSelectedRow Returns Boolean
836 Handle hoServer
837 Integer iMain iSel
838 RowID riID
839 Boolean bCancel bDDReadMode bNotifyingExternalDDOld
840 Get pbDDReadMode to bDDReadMode
841 If bDDReadMode Begin
842 // should never get called. Perhaps should be an error
843 Function_Return True
844 End
845
846 Get SelectedRow to iSel
847 Get RowTag iSel to riID
848 If (IsNullRowID(riID)) Begin
849 Error DFERR_PROGRAM "DeleteSelectedRow has no selectedrow"
850 Function_Return True
851 End
852 Get Server to hoServer
853 Get Main_File of hoServer to iMain
854
855 // This find is required to set the internal Done_Array file bits.
856 // This will trigger a DD refresh and we only want the find to update the row and not the grid.
857 Get pbNotifyingExternalDD to bNotifyingExternalDDOld
858 Set pbNotifyingExternalDD to True
859 Send FindByRowId of hoServer iMain riID
860 Set pbNotifyingExternalDD to bNotifyingExternalDDOld
861
862 Send Request_Delete of hoServer
863 Move (Err) to bCancel
864 Function_Return bCancel
865 End_Function
866
867 { NoDoc=True }
868 Function DataForCell Integer iRow Integer iColumn Returns String
869 tDataSourceRow[] DataSource
870 Integer iSize
871 String sValue
872 Get pDataSource to DataSource
873 Get AdjustRowForOffset iRow to iRow
874 Move (SizeOfArray(DataSource)) to iSize
875 If (iRow>=0 and iRow<iSize and (SizeOfArray(DataSource[iRow].sValue)>iColumn)) Begin
876 Move DataSource[iRow].sValue[iColumn] to sValue
877 End
878 Function_Return sValue
879 End_Function
880
881 { NoDoc=True }
882 Function ValidateSelectedRow Returns Handle
883 Handle hoServer hoCol
884 Boolean bError bDDReadMode
885 Get pbDDReadMode to bDDReadMode
886
887 If bDDReadMode Begin
888 // should never get called. Perhaps should be an error
889 Function_Return -1
890 End
891
892 Forward Get ValidateSelectedRow to hoCol
893 If hoCol Begin
894 Function_Return hoCol
895 End
896
897 Get Server to hoServer
898 Get Request_Validate of hoServer to bError
899 Function_Return (If(bError,-1,0))
900
901 End_Function
902
903 { NoDoc=True }
904 Procedure UpdateDataForSelectedRow Integer iColumn String sValue Boolean bUpdateExternalData
905 tDataSourceRow[] DataSource
906 Handle[] DataSourceColumnObjects
907 Integer iRow
908 Boolean bDDReadMode
909 String sOldValue
910
911 // never update the DD when deferred
912 Get pbDDReadMode to bDDReadMode
913 Get SelectedRow to iRow
914 If (iRow=-1) Begin
915 Procedure_Return
916 End
917 If (iRow>=0) Begin
918 Get AdjustRowForOffset iRow to iRow
919 Get pDataSource to DataSource
920 Move DataSource[iRow].sValue[iColumn] to sOldValue
921 Move sValue to DataSource[iRow].sValue[iColumn]
922 Set pDataSource to DataSource
923 Get pDataSourceColumnObjects to DataSourceColumnObjects
924
925 // update DD
926 If (bUpdateExternalData and not(bDDReadMode)) Begin
927 Send UpdateDataToExternalSource of DataSourceColumnObjects[iColumn] sValue ufUpdateToDD 0
928 End
929 Send NotifySelectedRowChanged of DataSourceColumnObjects[iColumn] sOldValue sValue
930 End
931 End_Procedure
932
933 // this can get called with the Row out of range for the cache
934 // because rowcount can exceed the cache size
935 { NoDoc=True }
936 Procedure SelectRow Integer iRow Boolean bUpdateExternalData
937 tDataSourceRow[] DataSource
938 Boolean bOk bNotify
939 Integer iRowCount iMain
940 Handle hoDD
941
942 Get RowCount to iRowCount
943 If (iRow=-1 or (iRow<0) or (iRow>=iRowCount)) Begin
944 Set piSelectedRow to -1
945 End
946 Else Begin
947 Get pDataSource to DataSource
948 Set piSelectedRow to iRow
949 If (bUpdateExternalData) Begin
950 Get pbNotifyingExternalDD to bNotify
951 Set pbNotifyingExternalDD to True
952 Get AdjustRowForOffset iRow to iRow
953 Send OnNotifyExternalDDofSelect DataSource[iRow]
954 Set pbNotifyingExternalDD to bNotify
955 End
956 End
957 End_Procedure
958
959 { NoDoc=True }
960 Procedure ResetSelectedRow
961 Integer iRow
962 Get SelectedRow to iRow
963 Send SelectRow iRow True
964 End_Procedure
965
966 { Visibility=Private }
967 Procedure OnNotifyExternalDDofSelect tDataSourceRow DataSourceRow
968 Handle hoDD
969 Integer iMain
970 Boolean bDDReadMode
971 RowID riCurrentDD
972 Get Server to hoDD
973 Get Main_File of hoDD to iMain
974 Get pbDDReadMode to bDDReadMode
975 If bDDReadMode Begin
976 // if deferred, we will not read the record. There is no need since we are
977 // are not displaying the latest changes anyway (refresh would do that and it doesn't).
978 //Send ReadByRowId of hoDD iMain DataSourceRow.riID
979 End
980 Else Begin
981 Send FindByRowId of hoDD iMain DataSourceRow.riID
982 End
983 End_Procedure
984
985
986
987 { NoDoc=True }
988 Procedure SynchronizeDataForSelectedRow Boolean bPushData Integer iFlags
989 If bPushData Begin
990 Send UpdateExternalSourceFromDataSource iFlags
991 End
992 Else Begin
993 Send UpdateDataSourceFromExternalSource iFlags
994 End
995 End_Procedure
996
997 // move data from datasource to the DD's global file buffer.
998 { Visibility=Private }
999 Procedure UpdateExternalSourceFromDataSource Integer iFlags
1000 Handle[] DataSourceColumnObjects
1001 tDataSourceRow[] DataSource
1002 Integer iRow iCol iCols
1003 String sValue
1004 Get SelectedRow to iRow
1005 If (iRow<>-1) Begin
1006 Get AdjustRowForOffset iRow to iRow
1007 Get pDataSource to DataSource
1008 Get pDataSourceColumnObjects to DataSourceColumnObjects
1009 Move (SizeOfArray(DataSourceColumnObjects)) to iCols
1010 For iCol from 0 to (iCols-1)
1011 If (SizeOfArray(DataSource[iRow].sValue)>iCol) Begin
1012 Move DataSource[iRow].sValue[iCol] to sValue
1013 End
1014 Else Begin
1015 Move "" to sValue
1016 End
1017 // iFlags contains the file number of the entry update.
1018 Send UpdateDataToExternalSource of DataSourceColumnObjects[iCol] sValue ufUpdateToBuffer iFlags
1019 Loop
1020 End
1021 End_Procedure
1022
1023 // move data from the DD's global file buffer to the datasource
1024 // iFlags contains the refresh mode. Done and Cleared array should be set.
1025 // called as part of a DD refresh
1026 { Visibility=Private }
1027 Procedure UpdateDataSourceFromExternalSource Integer iFlags
1028 Boolean bChanged
1029 Integer iRow
1030 tDataSourceRow[] DataSource
1031 tDataSourceRow DataSourceRow
1032 Get SelectedRow to iRow
1033 If (iRow<>-1) Begin
1034 Get pDataSource to DataSource
1035 Get AdjustRowForOffset iRow to iRow
1036 Move DataSource[iRow] to DataSourceRow
1037
1038 Get UpdateDataSourceRowFromExternalSource iFlags (&DataSourceRow) to bChanged
1039 // only update the array if there is an actual change
1040 If (bChanged) Begin
1041 Move DataSourceRow to DataSource[iRow]
1042 Set pDataSource to DataSource
1043 End
1044 End
1045 End_Procedure
1046
1047 // update this row from the DDs, the file buffers and the done arrays. Called during a DD operation
1048 // returns new datasourcerow (byref) and True if there was a change the change test can be used to
1049 // optimize updating of the datasource array
1050 {Visibility=Private }
1051 Function UpdateDataSourceRowFromExternalSource Integer iFlags tDataSourceRow ByRef DataSourceRow Returns Boolean
1052 Handle[] DataSourceColumnObjects
1053 Handle hoServer
1054 Integer iBindingTable iBindingCol iMain
1055 Boolean bFound bFoundClear bUseDDDefault bError bIsEQ bChanged
1056 String sValue sOldValue
1057 Integer iCol iCols
1058 RowID riOld
1059
1060 Get Server to hoServer
1061 Get Main_File of hoServer to iMain
1062
1063 is_file_included iMain 1 to bFound // see if main file is in find done array
1064 is_file_included iMain 0 to bFoundClear // see if main file is in clear done array
1065 Move (bFound or bFoundClear) to bFound
1066 If bFound Begin
1067 // only set rowid if this is a main file update
1068 Move DataSourceRow.riID to riOld
1069 Send OnSetTag (&DataSourceRow)
1070 Move (not(IsSameRowID(riOld,DataSourceRow.riID))) to bChanged
1071 End
1072
1073 If (iFlags=MODE_SAVE and DataSourceRow.bNewRow) Begin
1074 Move False to DataSourceRow.bNewRow
1075 Move True to bChanged
1076 End
1077
1078 Get pDataSourceColumnObjects to DataSourceColumnObjects
1079 Move (SizeOfArray(DataSourceColumnObjects)) to iCols
1080 For iCol from 0 to (iCols-1)
1081
1082 Move False to bFound
1083 Move False to bFoundClear
1084 Move False to bUseDDDefault
1085
1086 // if we have a binding table we only update the column if it
1087 // is part of the refresh (cleared or found). If no binding table
1088 // we assume it is calcuated and we always update
1089 Get piBindingTable of DataSourceColumnObjects[iCol] to iBindingTable
1090 Get piBindingColumn of DataSourceColumnObjects[iCol] to iBindingCol
1091 If iBindingTable Begin
1092 is_file_included iBindingTable 1 to bFound // see if main file is in find done array
1093 is_file_included iBindingTable 0 to bFoundClear // see if main file is in clear done array
1094 Move (bFound or bFoundClear) to bFound
1095 End
1096 Else Begin
1097 Move True to bFound
1098 End
1099
1100 If (bFound) Begin
1101 If (bFoundClear) Begin
1102 // if the DD's field changed state is true, we must have a default value to use
1103 Get File_field_Changed_state of hoServer iBindingTable iBindingCol to bUseDDDefault
1104 End
1105
1106 If bUseDDDefault Begin
1107 Get File_Field_Current_Value of hoServer iBindingTable iBindingCol to sValue
1108 End
1109 Else Begin
1110 Get InitialValue of DataSourceColumnObjects[iCol] to sValue
1111 End
1112 Move DataSourceRow.sValue[iCol] to sOldValue
1113 Send DataTypeEQTest of DataSourceColumnObjects[iCol] DataSourceRow.sValue[iCol] sValue (&bError) (&bIsEQ)
1114 If (not(bError) and not(bIsEQ)) Begin
1115 Move sValue to DataSourceRow.sValue[iCol]
1116 Send NotifySelectedRowChanged of DataSourceColumnObjects[iCol] sOldValue sValue
1117 Move True to bChanged
1118 End
1119 End
1120 Loop
1121 Function_Return bChanged
1122 End_Procedure
1123
1124
1125 // augmented to clear the DD and get DD defaults as needed
1126 Function CreateClearedDataSourceRow Returns tDataSourceRow
1127 tDataSourceRow DataSourceRow
1128 Handle[] DataSourceColumnObjects
1129 Integer iColumns
1130 Handle hoServer
1131 Boolean bChanged
1132
1133 Get Server to hoServer
1134 // if operation_mode is set, this was probably called by Refresh in reaction to another
1135 // DEO performing a clear. We don't need to clear in this case.
1136 If (OPERATION_MODE=MODE_WAITING) Begin
1137 Send Clear of hoServer
1138 End
1139 Get pDataSourceColumnObjects to DataSourceColumnObjects
1140 Move (SizeOfArray(DataSourceColumnObjects)) to iColumns
1141 Move True to DataSourceRow.bNewRow
1142 Move (ResizeArray(DataSourceRow.sValue,iColumns)) to DataSourceRow.sValue
1143 Get UpdateDataSourceRowFromExternalSource MODE_CLEAR (&DataSourceRow) to bChanged
1144 Function_Return DataSourceRow
1145
1146 End_Function
1147
1148
1149End_Class