X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5de9f492eca0bde0b23d762e614c21b30c74adb5..4b2322641a8c15b849c7221438ad9f1a7366afa6:/src/gtk/scrolwin.cpp?ds=sidebyside diff --git a/src/gtk/scrolwin.cpp b/src/gtk/scrolwin.cpp index 4d82bb3209..80ba00f515 100644 --- a/src/gtk/scrolwin.cpp +++ b/src/gtk/scrolwin.cpp @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "scrolwin.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -28,12 +24,12 @@ #pragma hdrstop #endif +#include "wx/scrolwin.h" #include "wx/utils.h" #include "wx/dcclient.h" - -#include "wx/scrolwin.h" #include "wx/panel.h" #include "wx/sizer.h" +#include "wx/math.h" #include "wx/gtk/private.h" #include "wx/gtk/win_gtk.h" @@ -73,6 +69,7 @@ extern bool g_isIdle; // "value_changed" from m_vAdjust //----------------------------------------------------------------------------- +extern "C" { static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, SCROLLBAR_CBACK_ARG wxScrolledWindow *win ) @@ -83,15 +80,17 @@ static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, if (g_blockEventsOnDrag) return; if (!win->m_hasVMT) return; - + win->GtkVScroll( adjust->value, GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->vscrollbar) ); } +} //----------------------------------------------------------------------------- // "value_changed" from m_hAdjust //----------------------------------------------------------------------------- +extern "C" { static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, SCROLLBAR_CBACK_ARG wxScrolledWindow *win ) @@ -105,11 +104,13 @@ static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, win->GtkHScroll( adjust->value, GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->hscrollbar) ); } +} //----------------------------------------------------------------------------- // "button_press_event" from scrollbar //----------------------------------------------------------------------------- +extern "C" { static gint gtk_scrollbar_button_press_callback( GtkRange *widget, GdkEventButton *gdk_event, wxWindowGTK *win) @@ -126,11 +127,13 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *widget, return FALSE; } +} //----------------------------------------------------------------------------- // "button_release_event" from scrollbar //----------------------------------------------------------------------------- +extern "C" { static gint gtk_scrollbar_button_release_callback( GtkRange *widget, GdkEventButton *WXUNUSED(gdk_event), wxWindowGTK *win) @@ -169,6 +172,7 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *widget, return FALSE; } +} //----------------------------------------------------------------------------- // InsertChild for wxScrolledWindow @@ -313,7 +317,7 @@ bool wxScrolledWindow::Create(wxWindow *parent, PostCreation(); Show( TRUE ); - + return TRUE; } @@ -326,10 +330,62 @@ void wxScrolledWindow::DoSetVirtualSize( int x, int y ) wxPanel::DoSetVirtualSize( x, y ); AdjustScrollbars(); -#if wxUSE_CONSTRAINTS if (GetAutoLayout()) Layout(); -#endif +} + +// wxWindow's GetBestVirtualSize returns the actual window size, +// whereas we want to return the virtual size +wxSize wxScrolledWindow::GetBestVirtualSize() const +{ + wxSize clientSize( GetClientSize() ); + if (GetSizer()) + { + wxSize minSize( GetSizer()->CalcMin() ); + + return wxSize( wxMax( clientSize.x, minSize.x ), wxMax( clientSize.y, minSize.y ) ); + } + else + return clientSize; +} + +// return the size best suited for the current window +// (this isn't a virtual size, this is a sensible size for the window) +wxSize wxScrolledWindow::DoGetBestSize() const +{ + wxSize best; + + if ( GetSizer() ) + { + wxSize b = GetSizer()->GetMinSize(); + + // Only use the content to set the window size in the direction + // where there's no scrolling; otherwise we're going to get a huge + // window in the direction in which scrolling is enabled + int ppuX, ppuY; + GetScrollPixelsPerUnit(& ppuX, & ppuY); + + wxSize minSize; + if ( GetMinSize().IsFullySpecified() ) + minSize = GetMinSize(); + else + minSize = GetSize(); + + if (ppuX > 0) + b.x = minSize.x; + if (ppuY > 0) + b.y = minSize.y; + best = b; + } + else + return wxWindow::DoGetBestSize(); + + // Add any difference between size and client size + wxSize diff = GetSize() - GetClientSize(); + best.x += wxMax(0, diff.x); + best.y += wxMax(0, diff.y); + + return best; } /* @@ -342,7 +398,7 @@ void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, { int xs, ys; GetViewStart (& xs, & ys); - + int old_x = m_xScrollPixelsPerLine * xs; int old_y = m_yScrollPixelsPerLine * ys; @@ -354,9 +410,12 @@ void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, // Setting hints here should arguably be deprecated, but without it // a sizer might override this manual scrollbar setting in old code. - m_targetWindow->SetVirtualSizeHints( noUnitsX * pixelsPerUnitX, noUnitsY * pixelsPerUnitY ); + // m_targetWindow->SetVirtualSizeHints( noUnitsX * pixelsPerUnitX, noUnitsY * pixelsPerUnitY ); - m_targetWindow->SetVirtualSize( noUnitsX * pixelsPerUnitX, noUnitsY * pixelsPerUnitY ); + int w = noUnitsX * pixelsPerUnitX; + int h = noUnitsY * pixelsPerUnitY; + m_targetWindow->SetVirtualSize( w ? w : wxDefaultCoord, + h ? h : wxDefaultCoord); if (!noRefresh) { @@ -383,19 +442,26 @@ void wxScrolledWindow::AdjustScrollbars() } else { - m_hAdjust->upper = vw / m_xScrollPixelsPerLine; - m_hAdjust->page_increment = (w / m_xScrollPixelsPerLine); - m_hAdjust->page_size = m_hAdjust->page_increment; + m_hAdjust->upper = (vw+m_xScrollPixelsPerLine-1) / m_xScrollPixelsPerLine; + m_hAdjust->page_size = w / m_xScrollPixelsPerLine; + m_hAdjust->page_increment = w / m_xScrollPixelsPerLine; + + // Special case. When client and virtual size are very close but + // the client is big enough, kill scrollbar. + + if ((m_hAdjust->page_size < m_hAdjust->upper) && (w >= vw)) + m_hAdjust->page_size += 1.0; // If the scrollbar hits the right side, move the window // right to keep it from over extending. - if ((m_hAdjust->value != 0.0) && (m_hAdjust->value + m_hAdjust->page_size > m_hAdjust->upper)) + if ( !wxIsNullDouble(m_hAdjust->value) && + (m_hAdjust->value + m_hAdjust->page_size > m_hAdjust->upper) ) { m_hAdjust->value = m_hAdjust->upper - m_hAdjust->page_size; if (m_hAdjust->value < 0.0) m_hAdjust->value = 0.0; - + if (GetChildren().GetCount() == 0) m_xScrollPosition = (int)m_hAdjust->value; // This is enough without child windows else @@ -411,18 +477,22 @@ void wxScrolledWindow::AdjustScrollbars() } else { - m_vAdjust->upper = vh / m_yScrollPixelsPerLine; - m_vAdjust->page_increment = (h / m_yScrollPixelsPerLine); - m_vAdjust->page_size = m_vAdjust->page_increment; + m_vAdjust->upper = (vh+m_yScrollPixelsPerLine-1) / m_yScrollPixelsPerLine; + m_vAdjust->page_size = h / m_yScrollPixelsPerLine; + m_vAdjust->page_increment = h / m_yScrollPixelsPerLine; + + if ((m_vAdjust->page_size < m_vAdjust->upper) && (h >= vh)) + m_vAdjust->page_size += 1.0; - if ((m_vAdjust->value != 0.0) && (m_vAdjust->value + m_vAdjust->page_size > m_vAdjust->upper)) + if ( !wxIsNullDouble(m_vAdjust->value) && + (m_vAdjust->value + m_vAdjust->page_size > m_vAdjust->upper) ) { m_vAdjust->value = m_vAdjust->upper - m_vAdjust->page_size; if (m_vAdjust->value < 0.0) m_vAdjust->value = 0.0; - + if (GetChildren().GetCount() == 0) - m_yScrollPosition = (int)m_vAdjust->value; + m_yScrollPosition = (int)m_vAdjust->value; else gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); } @@ -647,7 +717,7 @@ void wxScrolledWindow::DoCalcScrolledPosition(int x, int y, int *xx, int *yy) co { int xs, ys; GetViewStart (& xs, & ys); - + if ( xx ) *xx = x - xs * m_xScrollPixelsPerLine; if ( yy ) @@ -658,7 +728,7 @@ void wxScrolledWindow::DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) { int xs, ys; GetViewStart (& xs, & ys); - + if ( xx ) *xx = x + xs * m_xScrollPixelsPerLine; if ( yy ) @@ -846,19 +916,12 @@ bool wxScrolledWindow::Layout() // Default OnSize resets scrollbars, if any void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) { - if( GetAutoLayout() || m_targetWindow->GetAutoLayout() ) + if ( m_targetWindow->GetAutoLayout() ) { - if( m_targetWindow != this ) - m_targetWindow->FitInside(); + wxSize size = m_targetWindow->GetBestVirtualSize(); - FitInside(); - - // FIXME: Something is really weird here... This should be - // called by FitInside above (and apparently is), yet the - // scrollsub sample will get the scrollbar wrong if resized - // quickly. This masks the bug, but is surely not the right - // answer at all. - AdjustScrollbars(); + // This will call ::Layout() and ::AdjustScrollbars() + SetVirtualSize( size ); } else { @@ -961,19 +1024,19 @@ void wxScrolledWindow::OnChar(wxKeyEvent& event) int xScroll = GetScrollPos(wxHORIZONTAL); if ( xScroll != xScrollOld ) { - wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, xScroll, - wxHORIZONTAL); - event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event); + wxScrollWinEvent eventS(wxEVT_SCROLLWIN_THUMBTRACK, xScroll, + wxHORIZONTAL); + eventS.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventS); } int yScroll = GetScrollPos(wxVERTICAL); if ( yScroll != yScrollOld ) { - wxScrollWinEvent event(wxEVT_SCROLLWIN_THUMBTRACK, yScroll, - wxVERTICAL); - event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event); + wxScrollWinEvent eventS(wxEVT_SCROLLWIN_THUMBTRACK, yScroll, + wxVERTICAL); + eventS.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventS); } }