1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk1/scrolbar.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  15 #include "wx/scrolbar.h" 
  22 #include "wx/gtk1/private.h" 
  24 //----------------------------------------------------------------------------- 
  26 //----------------------------------------------------------------------------- 
  28 extern void wxapp_install_idle_handler(); 
  31 //----------------------------------------------------------------------------- 
  33 //----------------------------------------------------------------------------- 
  35 extern bool   g_blockEventsOnDrag
; 
  36 static wxEventType g_currentUpDownEvent 
= wxEVT_NULL
; 
  38 static const float sensitivity 
= 0.02; 
  40 //----------------------------------------------------------------------------- 
  42 //----------------------------------------------------------------------------- 
  44 // FIXME: is GtkScrollType really passed to us as 2nd argument? 
  47 static void gtk_scrollbar_callback( GtkAdjustment 
*adjust
, 
  51     if (g_isIdle
) wxapp_install_idle_handler(); 
  53     if (!win
->m_hasVMT
) return; 
  54     if (g_blockEventsOnDrag
) return; 
  56     float diff 
= adjust
->value 
- win
->m_oldPos
; 
  57     if (fabs(diff
) < sensitivity
) return; 
  59     win
->m_oldPos 
= adjust
->value
; 
  61     wxEventType command 
= GtkScrollTypeToWx(GET_SCROLL_TYPE(win
->m_widget
)); 
  63     double dvalue 
= adjust
->value
; 
  64     int value 
= (int)(dvalue 
< 0 ? dvalue 
- 0.5 : dvalue 
+ 0.5); 
  66     int orient 
= win
->HasFlag(wxSB_VERTICAL
) ? wxVERTICAL 
: wxHORIZONTAL
; 
  68     // throw a LINEUP / LINEDOWN event if necessary 
  69     if (g_currentUpDownEvent 
!= wxEVT_NULL
) 
  71         wxScrollEvent 
event( g_currentUpDownEvent
, win
->GetId(), value
, orient 
); 
  72         event
.SetEventObject( win 
); 
  73         win
->GetEventHandler()->ProcessEvent( event 
); 
  76     // throw other event (wxEVT_SCROLL_THUMBTRACK) 
  77     wxScrollEvent 
event( command
, win
->GetId(), value
, orient 
); 
  78     event
.SetEventObject( win 
); 
  79     win
->GetEventHandler()->ProcessEvent( event 
); 
  82     wxCommandEvent cevent( wxEVT_COMMAND_SCROLLBAR_UPDATED, win->GetId() ); 
  83     cevent.SetEventObject( win ); 
  84     win->ProcessEvent( cevent ); 
  89 //----------------------------------------------------------------------------- 
  90 // "button_press_event" from slider 
  91 //----------------------------------------------------------------------------- 
  93 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
  94                                                  GdkEventButton 
*gdk_event
, 
  97     if (g_isIdle
) wxapp_install_idle_handler(); 
  99     // check if a LINEUP/LINEDOWN event must be thrown 
 100     // I suppose here the size of scrollbar top/bottom buttons is 16px height 
 101     if (gdk_event
->type 
== GDK_BUTTON_PRESS 
&& gdk_event
->button 
== 1) 
 103         int scroll_height
, mouse_pos
; 
 105         // get the mouse position when the click is done 
 106         if (win
->HasFlag(wxSB_VERTICAL
)) 
 108             scroll_height 
= GTK_WIDGET(widget
)->allocation
.height 
- 16; 
 109             mouse_pos 
= (int)gdk_event
->y
; 
 113             scroll_height 
= GTK_WIDGET(widget
)->allocation
.width 
- 16; 
 114             mouse_pos 
= (int)gdk_event
->x
; 
 117         // compare mouse position to scrollbar height 
 118         if  (mouse_pos 
> scroll_height
) 
 119             g_currentUpDownEvent 
= wxEVT_SCROLL_LINEDOWN
; 
 120         else if (mouse_pos 
< 16) 
 121             g_currentUpDownEvent 
= wxEVT_SCROLL_LINEUP
; 
 124     // There is no slider field any more 
 125     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
 131 //----------------------------------------------------------------------------- 
 132 // "button_release_event" from slider 
 133 //----------------------------------------------------------------------------- 
 137 gtk_scrollbar_button_release_callback( GtkRange 
*WXUNUSED(widget
), 
 138                                        GdkEventButton 
*WXUNUSED(gdk_event
), 
 142         wxapp_install_idle_handler(); 
 144     if (win
->m_isScrolling
) 
 146         wxEventType command 
= wxEVT_SCROLL_THUMBRELEASE
; 
 147         int value 
= (int)ceil(win
->m_adjust
->value
); 
 148         int orient 
= win
->HasFlag(wxSB_VERTICAL
) ? wxVERTICAL 
: wxHORIZONTAL
; 
 150         wxScrollEvent 
event( command
, win
->GetId(), value
, orient 
); 
 151         event
.SetEventObject( win 
); 
 152         win
->GetEventHandler()->ProcessEvent( event 
); 
 155     win
->m_isScrolling 
= false; 
 157     // reset the LINEUP/LINEDOWN flag when the mouse button is released 
 158     g_currentUpDownEvent 
= wxEVT_NULL
; 
 164 //----------------------------------------------------------------------------- 
 166 //----------------------------------------------------------------------------- 
 168 IMPLEMENT_DYNAMIC_CLASS(wxScrollBar
,wxControl
) 
 170 wxScrollBar::~wxScrollBar() 
 174 bool wxScrollBar::Create(wxWindow 
*parent
, wxWindowID id
, 
 175            const wxPoint
& pos
, const wxSize
& size
, 
 176            long style
, const wxValidator
& validator
, const wxString
& name 
) 
 179     m_acceptsFocus 
= true; 
 181     if (!PreCreation( parent
, pos
, size 
) || 
 182         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 184         wxFAIL_MSG( wxT("wxScrollBar creation failed") ); 
 190     if ((style 
& wxSB_VERTICAL
) == wxSB_VERTICAL
) 
 191         m_widget 
= gtk_vscrollbar_new( (GtkAdjustment 
*) NULL 
); 
 193         m_widget 
= gtk_hscrollbar_new( (GtkAdjustment 
*) NULL 
); 
 195     m_adjust 
= gtk_range_get_adjustment( GTK_RANGE(m_widget
) ); 
 197     gtk_signal_connect( GTK_OBJECT(m_adjust
), 
 199                         (GtkSignalFunc
) gtk_scrollbar_callback
, 
 201     gtk_signal_connect( GTK_OBJECT(m_widget
), 
 202                         "button_press_event", 
 203                         (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, 
 205     gtk_signal_connect( GTK_OBJECT(m_widget
), 
 206                         "button_release_event", 
 207                         (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, 
 210     m_parent
->DoAddChild( this ); 
 217 int wxScrollBar::GetThumbPosition() const 
 219     double val 
= m_adjust
->value
; 
 220     return (int)(val 
< 0 ? val 
- 0.5 : val 
+ 0.5); 
 223 int wxScrollBar::GetThumbSize() const 
 225     return (int)(m_adjust
->page_size
+0.5); 
 228 int wxScrollBar::GetPageSize() const 
 230     return (int)(m_adjust
->page_increment
+0.5); 
 233 int wxScrollBar::GetRange() const 
 235     return (int)(m_adjust
->upper
+0.5); 
 238 void wxScrollBar::SetThumbPosition( int viewStart 
) 
 240     if (m_isScrolling
) return; 
 242     float fpos 
= (float)viewStart
; 
 244     if (fabs(fpos
-m_adjust
->value
) < 0.2) return; 
 245     m_adjust
->value 
= fpos
; 
 247     gtk_signal_disconnect_by_func( GTK_OBJECT(m_adjust
), 
 248                         (GtkSignalFunc
) gtk_scrollbar_callback
, 
 251     gtk_signal_emit_by_name( GTK_OBJECT(m_adjust
), "value_changed" ); 
 253     gtk_signal_connect( GTK_OBJECT(m_adjust
), 
 255                         (GtkSignalFunc
) gtk_scrollbar_callback
, 
 259 void wxScrollBar::SetScrollbar( int position
, int thumbSize
, int range
, int pageSize
, 
 260       bool WXUNUSED(refresh
) ) 
 262     float fpos 
= (float)position
; 
 263     float frange 
= (float)range
; 
 264     float fthumb 
= (float)thumbSize
; 
 265     float fpage 
= (float)pageSize
; 
 267     if ((fabs(frange
-m_adjust
->upper
) < 0.2) && 
 268         (fabs(fthumb
-m_adjust
->page_size
) < 0.2) && 
 269         (fabs(fpage
-m_adjust
->page_increment
) < 0.2)) 
 271         SetThumbPosition( position 
); 
 277     m_adjust
->lower 
= 0.0; 
 278     m_adjust
->upper 
= frange
; 
 279     m_adjust
->value 
= fpos
; 
 280     m_adjust
->step_increment 
= 1.0; 
 281     m_adjust
->page_increment 
= (float)(wxMax(fpage
,0)); 
 282     m_adjust
->page_size 
= fthumb
; 
 284     gtk_signal_emit_by_name( GTK_OBJECT(m_adjust
), "changed" ); 
 287 /* Backward compatibility */ 
 288 int wxScrollBar::GetValue() const 
 290     return GetThumbPosition(); 
 293 void wxScrollBar::SetValue( int viewStart 
) 
 295     SetThumbPosition( viewStart 
); 
 298 void wxScrollBar::GetValues( int *viewStart
, int *viewLength
, int *objectLength
, int *pageLength 
) const 
 300     int pos 
= (int)(m_adjust
->value
+0.5); 
 301     int thumb 
= (int)(m_adjust
->page_size
+0.5); 
 302     int page 
= (int)(m_adjust
->page_increment
+0.5); 
 303     int range 
= (int)(m_adjust
->upper
+0.5); 
 307     *objectLength 
= thumb
; 
 311 int wxScrollBar::GetViewLength() const 
 313     return (int)(m_adjust
->upper
+0.5); 
 316 int wxScrollBar::GetObjectLength() const 
 318     return (int)(m_adjust
->page_size
+0.5); 
 321 void wxScrollBar::SetPageSize( int pageLength 
) 
 323     int pos 
= (int)(m_adjust
->value
+0.5); 
 324     int thumb 
= (int)(m_adjust
->page_size
+0.5); 
 325     int range 
= (int)(m_adjust
->upper
+0.5); 
 326     SetScrollbar( pos
, thumb
, range
, pageLength 
); 
 329 void wxScrollBar::SetObjectLength( int objectLength 
) 
 331     int pos 
= (int)(m_adjust
->value
+0.5); 
 332     int page 
= (int)(m_adjust
->page_increment
+0.5); 
 333     int range 
= (int)(m_adjust
->upper
+0.5); 
 334     SetScrollbar( pos
, objectLength
, range
, page 
); 
 337 void wxScrollBar::SetViewLength( int viewLength 
) 
 339     int pos 
= (int)(m_adjust
->value
+0.5); 
 340     int thumb 
= (int)(m_adjust
->page_size
+0.5); 
 341     int page 
= (int)(m_adjust
->page_increment
+0.5); 
 342     SetScrollbar( pos
, thumb
, viewLength
, page 
); 
 345 bool wxScrollBar::IsOwnGtkWindow( GdkWindow 
*window 
) 
 347     GtkRange 
*range 
= GTK_RANGE(m_widget
); 
 348     return ( (window 
== GTK_WIDGET(range
)->window
) 
 349                 || (window 
== range
->trough
) 
 350                 || (window 
== range
->slider
) 
 351                 || (window 
== range
->step_forw
) 
 352                 || (window 
== range
->step_back
) 
 356 wxSize 
wxScrollBar::DoGetBestSize() const 
 358     return wxControl::DoGetBestSize(); 
 363 wxScrollBar::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 365     return GetDefaultAttributesFromGTKWidget(gtk_vscrollbar_new
); 
 368 #endif // wxUSE_SCROLLBAR