/// <inheritdoc/>
        public override void Update()
        {
            int numVisibleEntries = MathEx.CeilToInt(height / (float)entryHeight) + 1;

            numVisibleEntries = MathEx.Min(numVisibleEntries, entries.Count);

            while (visibleEntries.Count < numVisibleEntries)
            {
                TEntry newEntry = new TEntry();
                newEntry.Initialize(this);
                newEntry.panel.SetHeight(entryHeight);

                visibleEntries.Add(newEntry);
                contentsDirty = true;
            }

            while (numVisibleEntries < visibleEntries.Count)
            {
                int lastIdx = visibleEntries.Count - 1;

                visibleEntries[lastIdx].Destroy();
                visibleEntries.RemoveAt(lastIdx);

                contentsDirty = true;
            }

            if (scrollPct != scrollArea.VerticalScroll)
            {
                scrollPct     = scrollArea.VerticalScroll;
                contentsDirty = true;
            }

            if (contentsDirty)
            {
                int newHeight = entries.Count * entryHeight;
                if (scrollToLatest)
                {
                    if (totalHeight > height && scrollPct < 1.0f)
                    {
                        scrollToLatest = false;
                    }
                }
                else
                {
                    if (totalHeight <= height || scrollPct >= 1.0f)
                    {
                        scrollToLatest = true;
                    }
                }

                totalHeight = newHeight;
                int maxScrollOffset = MathEx.Max(0, totalHeight - height - 1);

                float newScrollPct;
                if (!scrollToLatest)
                {
                    // Calculate the new scroll pct (which will be active after we change the top/bottom padding element
                    // sizes). If we use the existing scroll pct instead then the elements will lag one frame behind, which
                    // can be very noticeable on quickly updating lists.
                    newScrollPct = (scrollPct * scrollArea.Layout.Bounds.height) / totalHeight;
                }
                else
                {
                    newScrollPct = 1.0f;
                }

                int startPos   = MathEx.FloorToInt(newScrollPct * maxScrollOffset);
                int startIndex = MathEx.FloorToInt(startPos / (float)entryHeight);

                // Check if we're at the list bottom and the extra element is out of bounds
                if ((startIndex + visibleEntries.Count) > entries.Count)
                {
                    startIndex--; // Keep the extra element at the top always
                }
                topPadding.SetHeight(startIndex * entryHeight);

                for (int i = 0; i < visibleEntries.Count; i++)
                {
                    visibleEntries[i].UpdateContents(startIndex + i, entries[startIndex + i]);
                }

                int bottomPosition = MathEx.Min(totalHeight, (startIndex + visibleEntries.Count) * entryHeight);
                bottomPadding.SetHeight(totalHeight - bottomPosition);

                if (scrollToLatest)
                {
                    if (newHeight <= height)
                    {
                        scrollArea.VerticalScroll = 0.0f;
                    }
                    else
                    {
                        scrollArea.VerticalScroll = 1.0f;
                    }
                }

                contentsDirty = false;
            }
        }