1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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
9 // Copyright: (c) Robert Roebling
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
28 #include "wx/scrolwin.h"
29 #include "wx/gtk/private.h"
31 // ============================================================================
33 // ============================================================================
35 // ----------------------------------------------------------------------------
36 // wxScrollHelper implementation
37 // ----------------------------------------------------------------------------
39 void wxScrollHelper::SetScrollbars(int pixelsPerUnitX
, int pixelsPerUnitY
,
40 int noUnitsX
, int noUnitsY
,
44 int old_x
= m_xScrollPosition
* m_xScrollPixelsPerLine
;
45 int old_y
= m_yScrollPosition
* m_yScrollPixelsPerLine
;
47 m_xScrollPixelsPerLine
= pixelsPerUnitX
;
48 m_yScrollPixelsPerLine
= pixelsPerUnitY
;
50 m_win
->m_scrollBar
[wxWindow::ScrollDir_Horz
]->adjustment
->value
=
51 m_xScrollPosition
= xPos
;
52 m_win
->m_scrollBar
[wxWindow::ScrollDir_Vert
]->adjustment
->value
=
53 m_yScrollPosition
= yPos
;
55 // To get everything right, have to call ScrollWindow()
56 // both before and after calling SetVirtualSize()
57 int new_x
= m_xScrollPosition
* m_xScrollPixelsPerLine
;
58 int new_y
= m_yScrollPosition
* m_yScrollPixelsPerLine
;
61 m_targetWindow
->ScrollWindow(old_x
- new_x
, old_y
- new_y
);
66 int w
= noUnitsX
* pixelsPerUnitX
;
67 int h
= noUnitsY
* pixelsPerUnitY
;
68 m_targetWindow
->SetVirtualSize( w
? w
: wxDefaultCoord
,
69 h
? h
: wxDefaultCoord
);
73 new_x
= m_xScrollPosition
* m_xScrollPixelsPerLine
;
74 new_y
= m_yScrollPosition
* m_yScrollPixelsPerLine
;
75 m_targetWindow
->ScrollWindow(old_x
- new_x
, old_y
- new_y
);
78 // If the target is not the same as the window with the scrollbars,
79 // then we need to update the scrollbars here, since they won't have
80 // been updated by SetVirtualSize().
81 if (m_targetWindow
!= m_win
)
87 void wxScrollHelper::DoAdjustScrollbar(GtkRange
* range
,
97 if (pixelsPerLine
> 0 && winSize
> 0 && winSize
< virtSize
)
99 upper
= (virtSize
+ pixelsPerLine
- 1) / pixelsPerLine
;
100 page_size
= winSize
/ pixelsPerLine
;
102 *linesPerPage
= page_size
;
106 // GtkRange won't allow upper == lower, so for disabled state use [0,1]
107 // with a page size of 1. This will also clamp position to 0.
114 GtkAdjustment
* adj
= range
->adjustment
;
115 adj
->step_increment
= 1;
116 adj
->page_increment
=
117 adj
->page_size
= page_size
;
118 gtk_range_set_range(range
, 0, upper
);
120 // ensure that the scroll position is always in valid range
125 void wxScrollHelper::AdjustScrollbars()
128 m_targetWindow
->GetVirtualSize(&vw
, &vh
);
131 const wxSize availSize
= GetSizeAvailableForScrollTarget(
132 m_win
->GetSize() - m_win
->GetWindowBorderSize());
133 if ( availSize
.x
>= vw
&& availSize
.y
>= vh
)
138 // we know that the scrollbars will be removed
139 DoAdjustHScrollbar(w
, vw
);
140 DoAdjustVScrollbar(h
, vh
);
145 m_targetWindow
->GetClientSize(&w
, NULL
);
146 DoAdjustHScrollbar(w
, vw
);
148 m_targetWindow
->GetClientSize(NULL
, &h
);
149 DoAdjustVScrollbar(h
, vh
);
152 m_targetWindow
->GetClientSize(&w
, NULL
);
155 // It is necessary to repeat the calculations in this case to avoid an
156 // observed infinite series of size events, involving alternating
157 // changes in visibility of the scrollbars.
158 // At this point, GTK+ has already queued a resize, which will cause
159 // AdjustScrollbars() to be called again. If the scrollbar visibility
160 // is not correct before then, yet another resize will occur, possibly
161 // leading to an unending series if the sizes are just right.
162 DoAdjustHScrollbar(w
, vw
);
164 m_targetWindow
->GetClientSize(NULL
, &h
);
165 DoAdjustVScrollbar(h
, vh
);
169 void wxScrollHelper::DoScrollOneDir(int orient
,
174 if ( pos
!= -1 && pos
!= *posOld
&& pixelsPerLine
)
176 m_win
->SetScrollPos(orient
, pos
);
177 pos
= m_win
->GetScrollPos(orient
);
179 int diff
= (*posOld
- pos
)*pixelsPerLine
;
180 m_targetWindow
->ScrollWindow(orient
== wxHORIZONTAL
? diff
: 0,
181 orient
== wxHORIZONTAL
? 0 : diff
);
187 void wxScrollHelper::DoScroll( int x_pos
, int y_pos
)
189 wxCHECK_RET( m_targetWindow
!= 0, _T("No target window") );
191 DoScrollOneDir(wxHORIZONTAL
, x_pos
, m_xScrollPixelsPerLine
, &m_xScrollPosition
);
192 DoScrollOneDir(wxVERTICAL
, y_pos
, m_yScrollPixelsPerLine
, &m_yScrollPosition
);
195 // ----------------------------------------------------------------------------
196 // scrollbars visibility
197 // ----------------------------------------------------------------------------
202 GtkPolicyType
GtkPolicyFromWX(wxScrollbarVisibility visibility
)
204 GtkPolicyType policy
;
205 switch ( visibility
)
207 case wxSHOW_SB_NEVER
:
208 policy
= GTK_POLICY_NEVER
;
211 case wxSHOW_SB_DEFAULT
:
212 policy
= GTK_POLICY_AUTOMATIC
;
215 case wxSHOW_SB_ALWAYS
:
216 policy
= GTK_POLICY_ALWAYS
;
223 } // anonymous namespace
225 void wxScrollHelper::DoShowScrollbars(wxScrollbarVisibility horz
,
226 wxScrollbarVisibility vert
)
228 GtkScrolledWindow
* const scrolled
= GTK_SCROLLED_WINDOW(m_win
->m_widget
);
229 wxCHECK_RET( scrolled
, "window must be created" );
231 gtk_scrolled_window_set_policy(scrolled
,
232 GtkPolicyFromWX(horz
),
233 GtkPolicyFromWX(vert
));