wxMAC wxListCtrl visible item range not stable while adding items (Issue #24669)

10 views
Skip to first unread message

alcontre

unread,
Jul 3, 2024, 1:44:21 AM (2 days ago) Jul 3
to wx-...@googlegroups.com, Subscribed

Description

Bug description:

When using SetItemCount() to add items to a virtual wxListCtrl that already contains many items (millions), the calculated range of visible items is slightly different on each repaint. This causes the range of visible items to "dance" around on screen.

I believe this is because, in the wxMAC implementation, the visible range is calculated by using the native control position value in range [0,1] times the maximum number of items in the list. This value is computed and set as a double:

    void SetScrollThumb( wxInt32 value, wxInt32 thumbSize ) override
    {   
        double v = ((double) value)/m_maximum;
        double t = ((double) thumbSize)/(m_maximum+thumbSize);
        [(wxNSScroller*) m_osxView setDoubleValue:v];
        [(wxNSScroller*) m_osxView setKnobProportion:t];
    }   

I believe the issue is that GetValue() retrieves it as a float and rounds, leading to issues with numerical precision.

    virtual wxInt32 GetValue() const override
    {   
        return wxRound([(wxNSScroller*) m_osxView floatValue] * m_maximum);
    } 

Using doubleValue appears to fix the behavior. I briefly tried updating wxOSXScrollBarCocoaImpl to track its integer position as a member variable directly, which seems like a more robust solution, but I wasn't quite sure how to update the integer position a result of click-and-drag on the scroll thumb.

diff --git a/src/osx/cocoa/scrolbar.mm b/src/osx/cocoa/scrolbar.mm
index ed77223596..58d1f5d407 100644
--- a/src/osx/cocoa/scrolbar.mm
+++ b/src/osx/cocoa/scrolbar.mm
@@ -62,7 +62,7 @@ void    SetScrollThumb( wxInt32 value, wxInt32 thumbSize ) override
 
     virtual wxInt32 GetValue() const override
     {
-        return wxRound([(wxNSScroller*) m_osxView floatValue] * m_maximum);
+        return wxRound([(wxNSScroller*) m_osxView doubleValue] * m_maximum);
     }

Expected vs observed behaviour:

I would expect the visible range of items to not change, as additional items are added through SetItemCount().

Patch or snippet allowing to reproduce the problem:

#include <wx/listctrl.h>
#include <wx/timer.h>
#include <wx/wx.h>

const long itemcount = 20000000;

class MyListCtrl : public wxListCtrl {
  public:
   MyListCtrl(wxWindow* parent, wxWindowID id)
       : wxListCtrl(parent, id, wxDefaultPosition, wxDefaultSize,
                    wxLC_REPORT | wxLC_VIRTUAL) {
      AppendColumn("Column", wxLIST_FORMAT_LEFT);

      SetItemCount(itemcount + 100);
      EnsureVisible(itemcount); 
   }    
   wxString OnGetItemText(long item, long column) const override {
      return wxString::Format("Item %ld", item);
   }        
};

class MyFrame : public wxFrame {
  public:
   MyListCtrl *listCtrl;
   MyFrame() : wxFrame(NULL, wxID_ANY, "example") {
      listCtrl = new MyListCtrl(this, wxID_ANY);
      wxTimer* timer = new wxTimer(this, 3 /*timer ID*/);
      Bind(wxEVT_TIMER, &MyFrame::OnTimer, this, 3 /*timer ID*/);
      timer->Start(300);
   }        
   void OnTimer(wxTimerEvent& e) {
      static auto i = 0;
      listCtrl->SetItemCount(itemcount + (i++)); 
   }
};

class MyApp : public wxApp {
  public:
   virtual bool OnInit() {
      MyFrame* frame = new MyFrame();
      frame->Show(true);
      return true;
   }
};

wxIMPLEMENT_APP(MyApp);

To Reproduce:

Compile above program, and run. The GUI will update on a timer and the set of visible items will dance around a bit. The window may need to be resized a bit to trigger the behavior, if the behavior is not observed.

Platform and version information

  • wxWidgets version you use: bug is present on master, 3.2 branch
  • wxWidgets port you use: wxMAC
  • OS and its version: macOS 14.5


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/24669@github.com>

Reply all
Reply to author
Forward
0 new messages