1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/scrolwin.cpp
3 // Purpose: wxScrolledWindow implementation
4 // Author: Robert Roebling
5 // Modified by: Ron Lee
6 // Vadim Zeitlin: removed 90% of duplicated common code
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
19 #include "wx/scrolwin.h"
22 #include "wx/gtk/private/gtk2-compat.h"
24 // ----------------------------------------------------------------------------
25 // wxScrollHelper implementation
26 // ----------------------------------------------------------------------------
28 void wxScrollHelper::SetScrollbars(int pixelsPerUnitX
, int pixelsPerUnitY
,
29 int noUnitsX
, int noUnitsY
,
33 // prevent programmatic position changes from causing scroll events
34 m_win
->SetScrollPos(wxHORIZONTAL
, xPos
);
35 m_win
->SetScrollPos(wxVERTICAL
, yPos
);
37 base_type::SetScrollbars(
38 pixelsPerUnitX
, pixelsPerUnitY
, noUnitsX
, noUnitsY
, xPos
, yPos
, noRefresh
);
41 void wxScrollHelper::DoAdjustScrollbar(GtkRange
* range
,
54 if (pixelsPerLine
> 0 && winSize
> 0 && winSize
< virtSize
)
56 upper
= (virtSize
+ pixelsPerLine
- 1) / pixelsPerLine
;
57 page_size
= winSize
/ pixelsPerLine
;
59 *linesPerPage
= page_size
;
63 // GtkRange won't allow upper == lower, so for disabled state use [0,1]
64 // with a page size of 1. This will also clamp position to 0.
71 gtk_range_set_increments(range
, 1, page_size
);
72 gtk_adjustment_set_page_size(gtk_range_get_adjustment(range
), page_size
);
73 gtk_range_set_range(range
, 0, upper
);
75 // ensure that the scroll position is always in valid range
80 void wxScrollHelper::AdjustScrollbars()
83 m_targetWindow
->GetVirtualSize(&vw
, &vh
);
86 const wxSize availSize
= GetSizeAvailableForScrollTarget(
87 m_win
->GetSize() - m_win
->GetWindowBorderSize());
88 if ( availSize
.x
>= vw
&& availSize
.y
>= vh
)
93 // we know that the scrollbars will be removed
94 DoAdjustHScrollbar(w
, vw
);
95 DoAdjustVScrollbar(h
, vh
);
100 m_targetWindow
->GetClientSize(&w
, NULL
);
101 DoAdjustHScrollbar(w
, vw
);
103 m_targetWindow
->GetClientSize(NULL
, &h
);
104 DoAdjustVScrollbar(h
, vh
);
107 m_targetWindow
->GetClientSize(&w
, NULL
);
110 // It is necessary to repeat the calculations in this case to avoid an
111 // observed infinite series of size events, involving alternating
112 // changes in visibility of the scrollbars.
113 // At this point, GTK+ has already queued a resize, which will cause
114 // AdjustScrollbars() to be called again. If the scrollbar visibility
115 // is not correct before then, yet another resize will occur, possibly
116 // leading to an unending series if the sizes are just right.
117 DoAdjustHScrollbar(w
, vw
);
119 m_targetWindow
->GetClientSize(NULL
, &h
);
120 DoAdjustVScrollbar(h
, vh
);
124 void wxScrollHelper::DoScrollOneDir(int orient
,
129 if ( pos
!= -1 && pos
!= *posOld
&& pixelsPerLine
)
131 m_win
->SetScrollPos(orient
, pos
);
132 pos
= m_win
->GetScrollPos(orient
);
134 int diff
= (*posOld
- pos
)*pixelsPerLine
;
135 m_targetWindow
->ScrollWindow(orient
== wxHORIZONTAL
? diff
: 0,
136 orient
== wxHORIZONTAL
? 0 : diff
);
142 void wxScrollHelper::DoScroll( int x_pos
, int y_pos
)
144 wxCHECK_RET( m_targetWindow
!= 0, wxT("No target window") );
146 DoScrollOneDir(wxHORIZONTAL
, x_pos
, m_xScrollPixelsPerLine
, &m_xScrollPosition
);
147 DoScrollOneDir(wxVERTICAL
, y_pos
, m_yScrollPixelsPerLine
, &m_yScrollPosition
);
150 // ----------------------------------------------------------------------------
151 // scrollbars visibility
152 // ----------------------------------------------------------------------------
157 GtkPolicyType
GtkPolicyFromWX(wxScrollbarVisibility visibility
)
159 GtkPolicyType policy
;
160 switch ( visibility
)
162 case wxSHOW_SB_NEVER
:
163 policy
= GTK_POLICY_NEVER
;
166 case wxSHOW_SB_DEFAULT
:
167 policy
= GTK_POLICY_AUTOMATIC
;
171 wxFAIL_MSG( wxS("unknown scrollbar visibility") );
174 case wxSHOW_SB_ALWAYS
:
175 policy
= GTK_POLICY_ALWAYS
;
182 } // anonymous namespace
184 bool wxScrollHelper::IsScrollbarShown(int orient
) const
186 GtkScrolledWindow
* const scrolled
= GTK_SCROLLED_WINDOW(m_win
->m_widget
);
189 // By default, all windows are scrollable.
193 GtkPolicyType hpolicy
, vpolicy
;
194 gtk_scrolled_window_get_policy(scrolled
, &hpolicy
, &vpolicy
);
196 GtkPolicyType policy
= orient
== wxHORIZONTAL
? hpolicy
: vpolicy
;
198 return policy
!= GTK_POLICY_NEVER
;
201 void wxScrollHelper::DoShowScrollbars(wxScrollbarVisibility horz
,
202 wxScrollbarVisibility vert
)
204 GtkScrolledWindow
* const scrolled
= GTK_SCROLLED_WINDOW(m_win
->m_widget
);
205 wxCHECK_RET( scrolled
, "window must be created" );
207 gtk_scrolled_window_set_policy(scrolled
,
208 GtkPolicyFromWX(horz
),
209 GtkPolicyFromWX(vert
));