]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/scroll/scroll.cpp
In virtual list mode, map first row to 1, not to 0 as this is reserved for an invalid...
[wxWidgets.git] / samples / scroll / scroll.cpp
index 6cc25e7a4bb13e41007d77897ee58bfbc57e60e4..874783a1bbb4f179e4fbf1b5822686bcbe1703c8 100644 (file)
 
 #include "wx/sizer.h"
 #include "wx/log.h"
+#include "wx/tglbtn.h"
+
+#ifndef __WXMSW__
+    #include "../sample.xpm"
+#endif
 
 // ----------------------------------------------------------------------------
 // a trivial example
@@ -449,19 +454,62 @@ public:
     MyScrolledWindowBase(wxWindow *parent)
         : wxScrolledWindow(parent, wxID_ANY,
                            wxDefaultPosition, wxDefaultSize,
-                           wxBORDER_SUNKEN),
-          m_nLines( 100 )
+                           wxBORDER_SUNKEN)
     {
+        m_nLines = 50;
+        m_winSync = NULL;
+        m_inDoSync = false;
+
         wxClientDC dc(this);
         dc.GetTextExtent("Line 17", NULL, &m_hLine);
     }
 
+    // this scrolled window can be synchronized with another one: if this
+    // function is called with a non-NULL pointer, the given window will be
+    // scrolled to the same position as this one
+    void SyncWith(MyScrolledWindowBase *win)
+    {
+        m_winSync = win;
+
+        DoSyncIfNecessary();
+    }
+
+    virtual void ScrollWindow(int dx, int dy, const wxRect *rect = NULL)
+    {
+        wxScrolledWindow::ScrollWindow(dx, dy, rect);
+
+        DoSyncIfNecessary();
+    }
+
 protected:
     // the height of one line on screen
     int m_hLine;
 
     // the number of lines we draw
     size_t m_nLines;
+
+private:
+    bool WasScrolledFirst() const { return m_inDoSync; }
+
+    void DoSyncIfNecessary()
+    {
+        if ( m_winSync && !m_winSync->WasScrolledFirst() )
+        {
+            m_inDoSync = true;
+
+            m_winSync->Scroll(GetViewStart());
+
+            m_inDoSync = false;
+        }
+    }
+
+    // the window to synchronize with this one or NULL
+    MyScrolledWindowBase *m_winSync;
+
+    // the flag preventing infinite recursion which would otherwise happen if
+    // one window synchronized the other one which in turn synchronized this
+    // one and so on
+    bool m_inDoSync;
 };
 
 // this class does "stupid" redrawing - it redraws everything each time
@@ -576,6 +624,12 @@ private:
     void OnTestSub(wxCommandEvent& WXUNUSED(event)) { new MySubFrame(this); }
     void OnTestAuto(wxCommandEvent& WXUNUSED(event)) { new MyAutoFrame(this); }
 
+    void OnToggleSync(wxCommandEvent& event);
+    void OnScrollbarVisibility(wxCommandEvent& event);
+
+    MyScrolledWindowBase *m_win1,
+                         *m_win2;
+
     DECLARE_EVENT_TABLE()
 };
 
@@ -719,9 +773,7 @@ void MyCanvas::OnScrollWin( wxCommandEvent &WXUNUSED(event) )
 {
     wxLogMessage("Scrolling 2 units up.\n"
                  "The white square and the controls should move equally!");
-    int x,y;
-    GetViewStart( &x, &y );
-    Scroll( wxDefaultCoord, y+2 );
+    Scroll( wxDefaultCoord, GetViewStart().y+2 );
 }
 
 // ----------------------------------------------------------------------------
@@ -786,6 +838,9 @@ const wxWindowID Scroll_Test_Sizers = wxWindow::NewControlId();
 const wxWindowID Scroll_Test_Sub    = wxWindow::NewControlId();
 const wxWindowID Scroll_Test_Auto   = wxWindow::NewControlId();
 
+const wxWindowID Scroll_TglBtn_Sync = wxWindow::NewControlId();
+const wxWindowID Scroll_Radio_ShowScrollbar = wxWindow::NewControlId();
+
 BEGIN_EVENT_TABLE(MyFrame,wxFrame)
     EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
     EVT_MENU(wxID_EXIT,  MyFrame::OnQuit)
@@ -795,11 +850,16 @@ BEGIN_EVENT_TABLE(MyFrame,wxFrame)
     EVT_MENU(Scroll_Test_Sizers, MyFrame::OnTestSizer)
     EVT_MENU(Scroll_Test_Sub, MyFrame::OnTestSub)
     EVT_MENU(Scroll_Test_Auto, MyFrame::OnTestAuto)
+
+    EVT_TOGGLEBUTTON(Scroll_TglBtn_Sync, MyFrame::OnToggleSync)
+    EVT_RADIOBOX(Scroll_Radio_ShowScrollbar, MyFrame::OnScrollbarVisibility)
 END_EVENT_TABLE()
 
 MyFrame::MyFrame()
        : wxFrame(NULL, wxID_ANY, "wxWidgets scroll sample")
 {
+    SetIcon(wxICON(sample));
+
     wxMenu *menuFile = new wxMenu;
     menuFile->Append(wxID_ABOUT, "&About..");
     menuFile->AppendSeparator();
@@ -825,10 +885,12 @@ MyFrame::MyFrame()
     SetMenuBar( mbar );
 
 
+    wxPanel *panel = new wxPanel(this);
+
     const wxSizerFlags flagsExpand(wxSizerFlags(1).Expand());
 
     wxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
-    topsizer->Add(new wxStaticText(this, wxID_ANY,
+    topsizer->Add(new wxStaticText(panel, wxID_ANY,
         "The windows below should behave in the same way, even though\n"
         "they're implemented quite differently, see the code for details.\n"
         "\n"
@@ -837,17 +899,63 @@ MyFrame::MyFrame()
         "don't be surprised by this."),
         wxSizerFlags().Centre().Border());
 
-    wxSizer *sizerBtm = new wxBoxSizer(wxHORIZONTAL);
-    sizerBtm->Add(new MyScrolledWindowDumb(this), flagsExpand);
-    sizerBtm->Add(new MyScrolledWindowSmart(this), flagsExpand);
-    topsizer->Add(sizerBtm, flagsExpand);
+    m_win1 = new MyScrolledWindowDumb(panel);
+    m_win2 = new MyScrolledWindowSmart(panel);
+
+    wxSizer *sizerScrollWin = new wxBoxSizer(wxHORIZONTAL);
+    sizerScrollWin->Add(m_win1, flagsExpand);
+    sizerScrollWin->Add(m_win2, flagsExpand);
+    topsizer->Add(sizerScrollWin, flagsExpand);
+
+    const wxSizerFlags
+        flagsHBorder(wxSizerFlags().Centre().Border(wxLEFT | wxRIGHT));
+
+    wxSizer *sizerBtns = new wxBoxSizer(wxHORIZONTAL);
+
+    // the radio buttons are in the same order as wxSHOW_SB_XXX values but
+    // offset by 1
+    const wxString visibilities[] = { "&never", "&default", "&always" };
+    wxRadioBox *radio = new wxRadioBox(panel, Scroll_Radio_ShowScrollbar,
+                                       "Left &scrollbar visibility: ",
+                                       wxDefaultPosition, wxDefaultSize,
+                                       WXSIZEOF(visibilities), visibilities);
+    radio->SetSelection(wxSHOW_SB_DEFAULT + 1);
+    sizerBtns->Add(radio, flagsHBorder);
+
+    sizerBtns->Add(new wxToggleButton(panel, Scroll_TglBtn_Sync, "S&ynchronize"),
+                   flagsHBorder);
+
+    topsizer->Add(sizerBtns, wxSizerFlags().Centre().Border());
 
-    SetSizer(topsizer);
+    panel->SetSizer(topsizer);
 
+    wxSize size = panel->GetBestSize();
+    SetSizeHints(size);
+    SetClientSize(2*size);
 
     Show();
 }
 
+void MyFrame::OnToggleSync(wxCommandEvent& event)
+{
+    if ( event.IsChecked() )
+    {
+        m_win1->SyncWith(m_win2);
+        m_win2->SyncWith(m_win1);
+    }
+    else
+    {
+        m_win1->SyncWith(NULL);
+        m_win2->SyncWith(NULL);
+    }
+}
+
+void MyFrame::OnScrollbarVisibility(wxCommandEvent& event)
+{
+    m_win1->ShowScrollbars(wxSHOW_SB_NEVER,
+                           wxScrollbarVisibility(event.GetSelection() - 1));
+}
+
 void MyFrame::OnQuit(wxCommandEvent &WXUNUSED(event))
 {
     Close(true);
@@ -982,20 +1090,14 @@ MyAutoScrollingWindow::DeviceCoordsToGraphicalChars(wxPoint pos) const
 {
     pos.x /= m_fontW;
     pos.y /= m_fontH;
-    int vX, vY;
-    GetViewStart(&vX, &vY);
-    pos.x += vX;
-    pos.y += vY;
+    pos += GetViewStart();
     return pos;
 }
 
 wxPoint
 MyAutoScrollingWindow::GraphicalCharToDeviceCoords(wxPoint pos) const
 {
-    int vX, vY;
-    GetViewStart(&vX, &vY);
-    pos.x -= vX;
-    pos.y -= vY;
+    pos -= GetViewStart();
     pos.x *= m_fontW;
     pos.y *= m_fontH;
     return pos;
@@ -1138,7 +1240,7 @@ void MyAutoScrollingWindow::OnDraw(wxDC& dc)
     dc.SetPen(*wxTRANSPARENT_PEN);
     const wxString str = sm_testData;
     size_t strLength = str.length();
-    wxString::const_iterator str_i;
+    wxString::const_iterator str_i = str.begin();
 
     // draw the characters
     // 1. for each update region
@@ -1212,7 +1314,7 @@ void MyAutoScrollingWindow::OnMouseMove(wxMouseEvent& event)
         // set the new cursor position
         m_cursor = DeviceCoordsToGraphicalChars(event.GetPosition());
         // draw/erase selection
-        MyRefresh();
+        // MyRefresh();
         // capture mouse to activate auto-scrolling
         if (!HasCapture()) {
             CaptureMouse();