]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/scrolwin.cpp
fix bug introduced in last commit, contents not scrolling when selecting treectrl...
[wxWidgets.git] / src / gtk / scrolwin.cpp
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
7 // Created: 01/02/97
8 // RCS-ID: $Id$
9 // Copyright: (c) Robert Roebling
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #include "wx/scrolwin.h"
29 #include "wx/gtk/private.h"
30
31 // ============================================================================
32 // implementation
33 // ============================================================================
34
35 // ----------------------------------------------------------------------------
36 // wxScrollHelper implementation
37 // ----------------------------------------------------------------------------
38
39 void wxScrollHelper::SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY,
40 int noUnitsX, int noUnitsY,
41 int xPos, int yPos,
42 bool noRefresh)
43 {
44 int old_x = m_xScrollPosition * m_xScrollPixelsPerLine;
45 int old_y = m_yScrollPosition * m_yScrollPixelsPerLine;
46
47 m_xScrollPixelsPerLine = pixelsPerUnitX;
48 m_yScrollPixelsPerLine = pixelsPerUnitY;
49
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;
54
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;
59 if (!noRefresh)
60 {
61 m_targetWindow->ScrollWindow(old_x - new_x, old_y - new_y);
62 old_x = new_x;
63 old_y = new_y;
64 }
65
66 int w = noUnitsX * pixelsPerUnitX;
67 int h = noUnitsY * pixelsPerUnitY;
68 m_targetWindow->SetVirtualSize( w ? w : wxDefaultCoord,
69 h ? h : wxDefaultCoord);
70
71 if (!noRefresh)
72 {
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);
76 }
77
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)
82 {
83 AdjustScrollbars();
84 }
85 }
86
87 void wxScrollHelper::DoAdjustScrollbar(GtkRange* range,
88 int pixelsPerLine,
89 int winSize,
90 int virtSize,
91 int *pos,
92 int *lines,
93 int *linesPerPage)
94 {
95 int upper;
96 int page_size;
97 if (pixelsPerLine > 0 && winSize > 0 && winSize < virtSize)
98 {
99 upper = (virtSize + pixelsPerLine - 1) / pixelsPerLine;
100 page_size = winSize / pixelsPerLine;
101 *lines = upper;
102 *linesPerPage = page_size;
103 }
104 else
105 {
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.
108 upper = 1;
109 page_size = 1;
110 *lines = 0;
111 *linesPerPage = 0;
112 }
113
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);
119
120 // ensure that the scroll position is always in valid range
121 if (*pos > *lines)
122 *pos = *lines;
123 }
124
125 void wxScrollHelper::AdjustScrollbars()
126 {
127 int vw, vh;
128 m_targetWindow->GetVirtualSize(&vw, &vh);
129
130 int w, h;
131 const wxSize availSize = GetSizeAvailableForScrollTarget(
132 m_win->GetSize() - m_win->GetWindowBorderSize());
133 if ( availSize.x >= vw && availSize.y >= vh )
134 {
135 w = availSize.x;
136 h = availSize.y;
137
138 // we know that the scrollbars will be removed
139 DoAdjustHScrollbar(w, vw);
140 DoAdjustVScrollbar(h, vh);
141
142 return;
143 }
144
145 m_targetWindow->GetClientSize(&w, NULL);
146 DoAdjustHScrollbar(w, vw);
147
148 m_targetWindow->GetClientSize(NULL, &h);
149 DoAdjustVScrollbar(h, vh);
150
151 const int w_old = w;
152 m_targetWindow->GetClientSize(&w, NULL);
153 if ( w != w_old )
154 {
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);
163
164 m_targetWindow->GetClientSize(NULL, &h);
165 DoAdjustVScrollbar(h, vh);
166 }
167 }
168
169 void wxScrollHelper::DoScrollOneDir(int orient,
170 int pos,
171 int pixelsPerLine,
172 int *posOld)
173 {
174 if ( pos != -1 && pos != *posOld && pixelsPerLine )
175 {
176 m_win->SetScrollPos(orient, pos);
177 pos = m_win->GetScrollPos(orient);
178
179 int diff = (*posOld - pos)*pixelsPerLine;
180 m_targetWindow->ScrollWindow(orient == wxHORIZONTAL ? diff : 0,
181 orient == wxHORIZONTAL ? 0 : diff);
182
183 *posOld = pos;
184 }
185 }
186
187 void wxScrollHelper::DoScroll( int x_pos, int y_pos )
188 {
189 wxCHECK_RET( m_targetWindow != 0, _T("No target window") );
190
191 DoScrollOneDir(wxHORIZONTAL, x_pos, m_xScrollPixelsPerLine, &m_xScrollPosition);
192 DoScrollOneDir(wxVERTICAL, y_pos, m_yScrollPixelsPerLine, &m_yScrollPosition);
193 }
194
195 // ----------------------------------------------------------------------------
196 // scrollbars visibility
197 // ----------------------------------------------------------------------------
198
199 namespace
200 {
201
202 GtkPolicyType GtkPolicyFromWX(wxScrollbarVisibility visibility)
203 {
204 GtkPolicyType policy;
205 switch ( visibility )
206 {
207 case wxSHOW_SB_NEVER:
208 policy = GTK_POLICY_NEVER;
209 break;
210
211 case wxSHOW_SB_DEFAULT:
212 policy = GTK_POLICY_AUTOMATIC;
213 break;
214
215 case wxSHOW_SB_ALWAYS:
216 policy = GTK_POLICY_ALWAYS;
217 break;
218 }
219
220 return policy;
221 }
222
223 } // anonymous namespace
224
225 void wxScrollHelper::DoShowScrollbars(wxScrollbarVisibility horz,
226 wxScrollbarVisibility vert)
227 {
228 GtkScrolledWindow * const scrolled = GTK_SCROLLED_WINDOW(m_win->m_widget);
229 wxCHECK_RET( scrolled, "window must be created" );
230
231 gtk_scrolled_window_set_policy(scrolled,
232 GtkPolicyFromWX(horz),
233 GtkPolicyFromWX(vert));
234 }
235