X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/39c869a6cd3a3faf36cf90e95ec1dc255edc5676..e7300ec6d9ebbd1cfa2fcf12c0ce6e5aee85a152:/src/gtk/scrolwin.cpp diff --git a/src/gtk/scrolwin.cpp b/src/gtk/scrolwin.cpp index ef89c29b5a..fe7bf353ea 100644 --- a/src/gtk/scrolwin.cpp +++ b/src/gtk/scrolwin.cpp @@ -31,10 +31,11 @@ #include "wx/utils.h" #include "wx/dcclient.h" -#include "wx/gtk/scrolwin.h" +#include "wx/scrolwin.h" #include "wx/panel.h" +#include "wx/sizer.h" -#include +#include "wx/gtk/private.h" #include "wx/gtk/win_gtk.h" // ---------------------------------------------------------------------------- @@ -59,6 +60,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxPanel) //----------------------------------------------------------------------------- extern bool g_blockEventsOnDrag; +extern bool g_blockEventsOnScroll; //----------------------------------------------------------------------------- // idle system @@ -71,7 +73,9 @@ extern bool g_isIdle; // "value_changed" from m_vAdjust //----------------------------------------------------------------------------- -static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, wxScrolledWindow *win ) +static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, + SCROLLBAR_CBACK_ARG + wxScrolledWindow *win ) { if (g_isIdle) wxapp_install_idle_handler(); @@ -80,14 +84,17 @@ static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, wxScrol if (!win->m_hasVMT) return; - win->GtkVScroll( adjust->value ); + win->GtkVScroll( adjust->value, + GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->vscrollbar) ); } //----------------------------------------------------------------------------- // "value_changed" from m_hAdjust //----------------------------------------------------------------------------- -static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, wxScrolledWindow *win ) +static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, + SCROLLBAR_CBACK_ARG + wxScrolledWindow *win ) { if (g_isIdle) wxapp_install_idle_handler(); @@ -95,7 +102,72 @@ static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, wxScrol if (g_blockEventsOnDrag) return; if (!win->m_hasVMT) return; - win->GtkHScroll( adjust->value ); + win->GtkHScroll( adjust->value, + GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->hscrollbar) ); +} + +//----------------------------------------------------------------------------- +// "button_press_event" from scrollbar +//----------------------------------------------------------------------------- + +static gint gtk_scrollbar_button_press_callback( GtkRange *widget, + GdkEventButton *gdk_event, + wxWindowGTK *win) +{ + if (g_isIdle) + wxapp_install_idle_handler(); + + g_blockEventsOnScroll = TRUE; + + // FIXME: there is no slider field any more, what was meant here? +#ifndef __WXGTK20__ + win->m_isScrolling = (gdk_event->window == widget->slider); +#endif + + return FALSE; +} + +//----------------------------------------------------------------------------- +// "button_release_event" from scrollbar +//----------------------------------------------------------------------------- + +static gint gtk_scrollbar_button_release_callback( GtkRange *widget, + GdkEventButton *WXUNUSED(gdk_event), + wxWindowGTK *win) +{ +// don't test here as we can release the mouse while being over +// a different window than the slider +// +// if (gdk_event->window != widget->slider) return FALSE; + + g_blockEventsOnScroll = FALSE; + + if (win->m_isScrolling) + { + wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE; + int value = -1; + int dir = -1; + + GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget); + if (widget == GTK_RANGE(scrolledWindow->hscrollbar)) + { + value = (int)(win->m_hAdjust->value+0.5); + dir = wxHORIZONTAL; + } + if (widget == GTK_RANGE(scrolledWindow->vscrollbar)) + { + value = (int)(win->m_vAdjust->value+0.5); + dir = wxVERTICAL; + } + + wxScrollWinEvent event( command, value, dir ); + event.SetEventObject( win ); + win->GetEventHandler()->ProcessEvent( event ); + } + + win->m_isScrolling = FALSE; + + return FALSE; } //----------------------------------------------------------------------------- @@ -204,24 +276,42 @@ bool wxScrolledWindow::Create(wxWindow *parent, m_vAdjust->upper = 1.0; m_vAdjust->value = 0.0; m_vAdjust->step_increment = 1.0; - m_vAdjust->page_increment = 1.0; + m_vAdjust->page_increment = 2.0; gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); m_hAdjust->lower = 0.0; m_hAdjust->upper = 1.0; m_hAdjust->value = 0.0; m_hAdjust->step_increment = 1.0; - m_hAdjust->page_increment = 1.0; + m_hAdjust->page_increment = 2.0; gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); // Handlers for new scrollbar values GtkVConnectEvent(); 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 + // slider should be + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event", + (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event", + (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event", + (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); + + gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event", + (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); + gtk_widget_show( m_wxwindow ); if (m_parent) m_parent->DoAddChild( this ); + m_focusWidget = m_wxwindow; + PostCreation(); Show( TRUE ); @@ -241,12 +331,15 @@ 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; + m_xScrollPixelsPerLine = pixelsPerUnitX; m_yScrollPixelsPerLine = pixelsPerUnitY; - m_xScrollPosition = xPos; - m_yScrollPosition = yPos; m_xScrollLines = noUnitsX; m_yScrollLines = noUnitsY; + m_xScrollPosition = xPos; + m_yScrollPosition = yPos; m_hAdjust->lower = 0.0; m_hAdjust->upper = noUnitsX; @@ -261,6 +354,14 @@ void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY, m_vAdjust->page_increment = 2.0; AdjustScrollbars(); + + if (!noRefresh) + { + int new_x = m_xScrollPixelsPerLine * m_xScrollPosition; + int new_y = m_yScrollPixelsPerLine * m_yScrollPosition; + + m_targetWindow->ScrollWindow( old_x-new_x, old_y-new_y ); + } } void wxScrolledWindow::AdjustScrollbars() @@ -269,15 +370,53 @@ void wxScrolledWindow::AdjustScrollbars() m_targetWindow->GetClientSize( &w, &h ); if (m_xScrollPixelsPerLine == 0) + { + m_hAdjust->upper = 1.0; m_hAdjust->page_size = 1.0; + } else + { m_hAdjust->page_size = (w / m_xScrollPixelsPerLine); + int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); + if (max < 0) max = 0; + + int x_pos = m_xScrollPosition; + if (x_pos > max) x_pos = max; + if (x_pos < 0) x_pos = 0; + + int old_x = m_xScrollPosition; + m_xScrollPosition = x_pos; + m_hAdjust->value = x_pos; + + if (x_pos != old_x) + m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 ); + } + if (m_yScrollPixelsPerLine == 0) + { + m_vAdjust->upper = 1.0; m_vAdjust->page_size = 1.0; + } else + { m_vAdjust->page_size = (h / m_yScrollPixelsPerLine); + int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); + if (max < 0) max = 0; + + int y_pos = m_yScrollPosition; + if (y_pos > max) y_pos = max; + if (y_pos < 0) y_pos = 0; + + int old_y = m_yScrollPosition; + m_yScrollPosition = y_pos; + m_vAdjust->value = y_pos; + + if (y_pos != old_y) + m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); + } + m_xScrollLinesPerPage = (int)(m_hAdjust->page_size + 0.5); m_yScrollLinesPerPage = (int)(m_vAdjust->page_size + 0.5); @@ -289,7 +428,7 @@ void wxScrolledWindow::AdjustScrollbars() // target window handling // ---------------------------------------------------------------------------- -void wxScrolledWindow::SetTargetWindow( wxWindow *target ) +void wxScrolledWindow::SetTargetWindow( wxWindow *target, bool WXUNUSED(pushEventHandler) ) { wxASSERT_MSG( target, wxT("target window must not be NULL") ); m_targetWindow = target; @@ -422,7 +561,9 @@ void wxScrolledWindow::Scroll( int x_pos, int y_pos ) } } -void wxScrolledWindow::GtkVScroll( float value ) +// TODO: [VH]Scroll functions should be combined + +void wxScrolledWindow::GtkVScroll( float value, unsigned int scroll_type ) { if (!m_targetWindow) return; @@ -435,21 +576,14 @@ void wxScrolledWindow::GtkVScroll( float value ) if (y_pos == m_yScrollPosition) return; - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); - GtkRange *range = GTK_RANGE(scrolledWindow->vscrollbar); - - wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK; - if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP; - else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN; - else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP; - else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN; + wxEventType command = GtkScrollWinTypeToWx(scroll_type); wxScrollWinEvent event( command, y_pos, wxVERTICAL ); event.SetEventObject( this ); GetEventHandler()->ProcessEvent( event ); } -void wxScrolledWindow::GtkHScroll( float value ) +void wxScrolledWindow::GtkHScroll( float value, unsigned int scroll_type ) { if (!m_targetWindow) return; @@ -462,14 +596,7 @@ void wxScrolledWindow::GtkHScroll( float value ) if (x_pos == m_xScrollPosition) return; - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); - GtkRange *range = GTK_RANGE(scrolledWindow->hscrollbar); - - wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK; - if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP; - else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN; - else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP; - else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN; + wxEventType command = GtkScrollWinTypeToWx(scroll_type); wxScrollWinEvent event( command, x_pos, wxHORIZONTAL ); event.SetEventObject( this ); @@ -484,10 +611,24 @@ void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll) void wxScrolledWindow::GetVirtualSize (int *x, int *y) const { + wxSize sz(0, 0); + if (m_targetWindow) + sz = m_targetWindow->GetClientSize(); + if ( x ) - *x = m_xScrollPixelsPerLine * m_xScrollLines; + { + if (m_xScrollPixelsPerLine == 0) + *x = sz.x; + else + *x = m_xScrollPixelsPerLine * m_xScrollLines; + } if ( y ) - *y = m_yScrollPixelsPerLine * m_yScrollLines; + { + if (m_yScrollPixelsPerLine == 0) + *y = sz.y; + else + *y = m_yScrollPixelsPerLine * m_yScrollLines; + } } // Where the current view starts from @@ -499,7 +640,7 @@ void wxScrolledWindow::GetViewStart (int *x, int *y) const *y = m_yScrollPosition; } -void wxScrolledWindow::CalcScrolledPosition(int x, int y, int *xx, int *yy) const +void wxScrolledWindow::DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const { if ( xx ) *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine; @@ -507,7 +648,7 @@ void wxScrolledWindow::CalcScrolledPosition(int x, int y, int *xx, int *yy) cons *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine; } -void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const +void wxScrolledWindow::DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const { if ( xx ) *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine; @@ -600,7 +741,7 @@ int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) return nScrollInc; } -void wxScrolledWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) ) +void wxScrolledWindow::SetScrollPos( int orient, int pos, bool refresh ) { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); @@ -672,6 +813,22 @@ void wxScrolledWindow::GtkVDisconnectEvent() (GtkSignalFunc) gtk_scrolled_window_vscroll_callback, (gpointer) this ); } + +bool wxScrolledWindow::Layout() +{ + if (GetSizer()) + { + // Take into account the virtual size and scrolled position of the window + int x, y, w, h; + CalcScrolledPosition(0,0, &x,&y); + GetVirtualSize(&w, &h); + GetSizer()->SetDimension(x, y, w, h); + return TRUE; + } + else + return wxPanel::Layout(); // fall back to default for LayoutConstraints +} + // ---------------------------------------------------------------------------- // event handlers // ----------------------------------------------------------------------------