Hello,
thank you very much for this report. You have encountered an error. In particular cases the selection worked unreliably if the list was configured as endless. I have redesigned the related code. Since we are actually in the preparation phase of the next release 9.0 it would be very helpful for us if you could try this modification. The modification affects the UpdateViewState() method in the Mosaic class Core::VerticalList. To test it, you would need to replace the original code of this method by following code:
// Avoid Chora warnings
aState;
// No class to create items
if ( pure ItemClass == null )
{
// Inform the owner of the list, that it has been changed
postsignal OnUpdate;
return;
}
// From now the list is performing the update of its items.
loading = true;
var int32 paddingTop = 0;
if ( !pure Endless )
paddingTop = pure PaddingTop;
// Calculate the index of the first and the last visible item. How many items
// can be shown?
var int32 head = ( -paddingTop - pure ScrollOffset ) / pure ItemHeight;
var int32 tail = ( pure Bounds.h - paddingTop - pure ScrollOffset - 1 ) / pure ItemHeight;
var int32 count = ( pure Bounds.h + pure ItemHeight - 1 ) / pure ItemHeight;
// Try to maintain at least 1 item in the cache - even if the list boundary
// area has reached the height <= 0 pixel.
if ( count < 1 )
count = 1;
// How many invisible items should additionally be cached in the list to optimize
// the scrolling?
var int32 cache2 = count / 2;
var int32 cache3 = count / 3;
// ... at least one item!
if ( cache2 == 0 ) cache2 = 1;
if ( cache3 == 0 ) cache3 = 1;
// Take in account additional items above the visible area
if ( head < validHead )
{
head = head - cache2;
tail = tail + cache3;
}
// ... or below the area
else if ( tail > validTail )
{
head = head - cache3;
tail = tail + cache2;
}
// Otherwise all visible items lie still within the valid area
else
{
head = validHead;
tail = validTail;
}
// Respect the lower/upper boundary
if ( !pure Endless )
{
if ( head >= pure NoOfItems ) { head = 0; tail = -1; }
else if ( tail < 0 ) { head = 0; tail = -1; }
if ( tail >= pure NoOfItems ) tail = pure NoOfItems - 1;
if ( head < 0 ) head = 0;
}
// Endless list without any content?
else if ( pure NoOfItems <= 0 )
{
head = 0;
tail = -1;
}
var int32 reuseHead = validHead;
var int32 reuseTail = validTail;
var int32 loadHead = 0;
var int32 loadTail = -1;
// Does the new and the old areas intersect? If true reuse the affected items
if ( head > reuseHead ) reuseHead = head;
if ( tail < reuseTail ) reuseTail = tail;
// Can we reuse already confirmed items?
if ( reuseHead <= reuseTail )
{
// Restack leading items to the tail
while (( validTail < tail ) && ( validHead < reuseHead ))
{
releaseHeadItem();
confirmTailItem();
}
// Restack items to the head
while (( validHead > head ) && ( validTail > reuseTail ))
{
releaseTailItem();
confirmHeadItem();
}
}
// None of the currently confirmed items can be reused. The confirmed
// area should be reloaded completely
else
{
validTail = validTail - validHead + head;
validHead = head;
loadHead = validHead;
loadTail = validTail;
}
// Remove superfluous items or append and load items if necessary
while ( validHead < head ) releaseHeadItem();
while ( validTail > tail ) releaseTailItem();
while ( validHead > head ) confirmHeadItem();
while ( validTail < tail ) confirmTailItem();
var Core::View item = first;
var int32 inx = validHead;
var point pos = point( 0, paddingTop + pure ScrollOffset + ( inx * pure ItemHeight ));
var int32 h = Bounds.h;
var int32 ih = ItemHeight;
var Core::View fi = null;
// Initialize and arrange items
while ( item != null )
{
var point ofs = pos - item.GetExtent().origin;
var int32 iy1 = pos.y;
var int32 iy2 = pos.y + ih;
var int32 inxN = inx;
// In case of endless lists calculate the index of the real item
if ( pure Endless )
{
if ( inxN < 0 ) inxN = pure NoOfItems - ( -inxN % pure NoOfItems );
if ( inxN > 0 ) inxN = inxN % pure NoOfItems;
}
// Arrange the item at its position
if ( ofs != <0,0>)
item.MoveView( ofs, true );
// Should the items content be reloaded? In the first pass reload the visible
// items only
if (((( inxN >= invalidHead ) && ( inxN <= invalidTail )) ||
(( inx >= loadHead ) && ( inx <= loadTail ))) &&
( iy1 < h ) && ( iy2 > 0 ))
{
View = item;
Item = inxN;
signal OnLoadItem;
}
// Continue with the next following item
item = item.next;
inx = inx + 1;
pos.y = pos.y + pure ItemHeight;
}
inx = validHead;
item = first;
pos = point( 0, paddingTop + pure ScrollOffset + ( inx * pure ItemHeight ));
// Second pass -> reload invisible cached items
while ( item != null )
{
var int32 iy1 = pos.y;
var int32 iy2 = pos.y + ih;
var int32 inxN = inx;
// In case of endless lists calculate the index of the real item
if ( pure Endless )
{
if ( inxN < 0 ) inxN = pure NoOfItems - ( -inxN % pure NoOfItems );
if ( inxN > 0 ) inxN = inxN % pure NoOfItems;
}
// Should the items content be reloaded? In the second pass reload the invisible
// items only
if (((( inxN >= invalidHead ) && ( inxN <= invalidTail )) ||
(( inx >= loadHead ) && ( inx <= loadTail ))) &&
!(( iy1 < h ) && ( iy2 > 0 )))
{
View = item;
Item = inxN;
signal OnLoadItem;
}
// Focus the item? Special case of an endless list. Always try to select the
// first visible item if there are several copies of the same item.
if (( inxN == pure SelectedItem ) && pure Endless && ( fi != null ))
{
var rect b = pure Bounds.orect;
if (( item.GetExtent() & b ).area > ( fi.GetExtent() & b ).area )
fi = item;
}
// Otherwise just select this item
else if ( inxN == pure SelectedItem )
fi = item;
// Continue with the next following item
item = item.next;
inx = inx + 1;
pos.y = pos.y + pure ItemHeight;
}
// Finished
invalidHead = 0;
invalidTail = -1;
View = null;
Item = -1;
// Assign the focus to the selected item. If the list is endless and there are
// several items with the same selected index visible, the first of the items
// which is most visible will become focused.
Focus = fi;
// Update is finished
loading = false;
// Inform the owner of the list, that it has been changed
postsignal OnUpdate;
Does it work now as expected?
If yes, you can retain this modification in your Mosaic. The unique difficulty here, the entire Embedded Wizard installation including the Mosaic is write-protected. You will need to use an external text editor and edit the file Core.ewu found in the directory Mosaic just below the directory where your Embedded Wizard Studio is installed. Depending on your text editor, Windows will ask you to override the protected file.
Hope it solves the problem.
Best regards
Paul Banach