X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/150c8d89c7f5e04045e55391b34167f2c4165b8b..b40a9d371f0e89e2e43c5d6ec440fefcd3d1a434:/src/gtk1/scrolwin.cpp diff --git a/src/gtk1/scrolwin.cpp b/src/gtk1/scrolwin.cpp index 9a792a679e..79cfe5d3a3 100644 --- a/src/gtk1/scrolwin.cpp +++ b/src/gtk1/scrolwin.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// // Name: gtk/scrolwin.cpp // Purpose: wxScrolledWindow implementation -// Author: Julian Smart +// Author: Robert Roebling // Modified by: Ron Lee // Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Robert Roebling +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,7 +17,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "scrolwin.h" #endif @@ -28,10 +28,9 @@ #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" @@ -73,6 +72,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 +83,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 +107,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 +130,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 +175,7 @@ static gint gtk_scrollbar_button_release_callback( GtkRange *widget, return FALSE; } +} //----------------------------------------------------------------------------- // InsertChild for wxScrolledWindow @@ -288,7 +295,7 @@ bool wxScrolledWindow::Create(wxWindow *parent, GtkHConnectEvent(); // these handlers block mouse events to any window during scrolling such as - // motion events and prevent GTK and wxWindows from fighting over where the + // motion events and prevent GTK and wxWidgets from fighting over where the // slider should be gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event", @@ -326,10 +333,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; } /* @@ -340,8 +399,11 @@ void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, int noUnitsX, int noUnitsY, int xPos, int yPos, bool noRefresh ) { - int old_x = m_xScrollPixelsPerLine * m_xScrollPosition; - int old_y = m_yScrollPixelsPerLine * m_yScrollPosition; + int xs, ys; + GetViewStart (& xs, & ys); + + int old_x = m_xScrollPixelsPerLine * xs; + int old_y = m_yScrollPixelsPerLine * ys; m_xScrollPixelsPerLine = pixelsPerUnitX; m_yScrollPixelsPerLine = pixelsPerUnitY; @@ -351,9 +413,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) { @@ -371,17 +436,25 @@ void wxScrolledWindow::AdjustScrollbars() m_targetWindow->GetClientSize( &w, &h ); m_targetWindow->GetVirtualSize( &vw, &vh ); - + if (m_xScrollPixelsPerLine == 0) { m_hAdjust->upper = 1.0; + m_hAdjust->page_increment = 1.0; m_hAdjust->page_size = 1.0; } else { - m_hAdjust->upper = vw / m_xScrollPixelsPerLine; - m_hAdjust->page_size = (w / m_xScrollPixelsPerLine); - + 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. @@ -401,12 +474,17 @@ void wxScrolledWindow::AdjustScrollbars() if (m_yScrollPixelsPerLine == 0) { m_vAdjust->upper = 1.0; + m_vAdjust->page_increment = 1.0; m_vAdjust->page_size = 1.0; } else { - m_vAdjust->upper = vh / m_yScrollPixelsPerLine; - m_vAdjust->page_size = (h / m_yScrollPixelsPerLine); + 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)) { @@ -421,8 +499,8 @@ void wxScrolledWindow::AdjustScrollbars() } } - m_xScrollLinesPerPage = (int)(m_hAdjust->page_size + 0.5); - m_yScrollLinesPerPage = (int)(m_vAdjust->page_size + 0.5); + m_xScrollLinesPerPage = (int)(m_hAdjust->page_increment + 0.5); + m_yScrollLinesPerPage = (int)(m_vAdjust->page_increment + 0.5); gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); @@ -439,14 +517,14 @@ void wxScrolledWindow::SetTargetWindow( wxWindow *target, bool WXUNUSED(pushEven m_targetWindow = target; } -wxWindow *wxScrolledWindow::GetTargetWindow() +wxWindow *wxScrolledWindow::GetTargetWindow() const { return m_targetWindow; } // Override this function if you don't want to have wxScrolledWindow // automatically change the origin according to the scroll position. -void wxScrolledWindow::PrepareDC(wxDC& dc) +void wxScrolledWindow::DoPrepareDC(wxDC& dc) { dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine, -m_yScrollPosition * m_yScrollPixelsPerLine ); @@ -555,7 +633,7 @@ void wxScrolledWindow::Scroll( int x_pos, int y_pos ) m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 ); - // Just update the scrollbar, don't send any wxWindows event + // Just update the scrollbar, don't send any wxWidgets event GtkHDisconnectEvent(); gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); GtkHConnectEvent(); @@ -574,7 +652,7 @@ void wxScrolledWindow::Scroll( int x_pos, int y_pos ) m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); - // Just update the scrollbar, don't send any wxWindows event + // Just update the scrollbar, don't send any wxWidgets event GtkVDisconnectEvent(); gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); GtkVConnectEvent(); @@ -638,18 +716,24 @@ void wxScrolledWindow::GetViewStart (int *x, int *y) const void wxScrolledWindow::DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const { + int xs, ys; + GetViewStart (& xs, & ys); + if ( xx ) - *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine; + *xx = x - xs * m_xScrollPixelsPerLine; if ( yy ) - *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine; + *yy = y - ys * m_yScrollPixelsPerLine; } void wxScrolledWindow::DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const { + int xs, ys; + GetViewStart (& xs, & ys); + if ( xx ) - *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine; + *xx = x + xs * m_xScrollPixelsPerLine; if ( yy ) - *yy = y + m_yScrollPosition * m_yScrollPixelsPerLine; + *yy = y + ys * m_yScrollPixelsPerLine; } int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) @@ -770,14 +854,14 @@ void wxScrolledWindow::SetScrollPos( int orient, int pos, bool refresh ) { if (orient == wxHORIZONTAL) { - // Just update the scrollbar, don't send any wxWindows event + // Just update the scrollbar, don't send any wxWidgets event GtkHDisconnectEvent(); gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); GtkHConnectEvent(); } else { - // Just update the scrollbar, don't send any wxWindows event + // Just update the scrollbar, don't send any wxWidgets event GtkVDisconnectEvent(); gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); GtkVConnectEvent(); @@ -833,19 +917,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(); - - 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(); + wxSize size = m_targetWindow->GetBestVirtualSize(); + + // This will call ::Layout() and ::AdjustScrollbars() + SetVirtualSize( size ); } else {