]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/scrolwin.cpp
Use gtk_range_set_value() to set scrollbar and do that after SetVirtualSize() since...
[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 WXUNUSED(noRefresh))
43 {
44 m_xScrollPixelsPerLine = pixelsPerUnitX;
45 m_yScrollPixelsPerLine = pixelsPerUnitY;
46
47 int w = noUnitsX * pixelsPerUnitX;
48 int h = noUnitsY * pixelsPerUnitY;
49 m_targetWindow->SetVirtualSize( w ? w : wxDefaultCoord,
50 h ? h : wxDefaultCoord);
51
52 GtkRange *sb = m_win->m_scrollBar[wxWindow::ScrollDir_Vert];
53 gtk_range_set_value(sb, yPos);
54 sb = m_win->m_scrollBar[wxWindow::ScrollDir_Horz];
55 gtk_range_set_value(sb, xPos);
56
57 m_xScrollPosition = wxRound( m_win->m_scrollBar[wxWindow::ScrollDir_Horz]->adjustment->value );
58 m_yScrollPosition = wxRound( m_win->m_scrollBar[wxWindow::ScrollDir_Vert]->adjustment->value );
59
60 // If the target is not the same as the window with the scrollbars,
61 // then we need to update the scrollbars here, since they won't have
62 // been updated by SetVirtualSize().
63 if (m_targetWindow != m_win)
64 {
65 AdjustScrollbars();
66 }
67
68 #if 0
69 if (!noRefresh)
70 {
71 int new_x = m_xScrollPixelsPerLine * m_xScrollPosition;
72 int new_y = m_yScrollPixelsPerLine * m_yScrollPosition;
73
74 m_targetWindow->ScrollWindow( old_x - new_x, old_y - new_y );
75 }
76 #endif
77 }
78
79 void wxScrollHelper::DoAdjustScrollbar(GtkRange* range,
80 int pixelsPerLine,
81 int winSize,
82 int virtSize,
83 int *pos,
84 int *lines,
85 int *linesPerPage)
86 {
87 int upper;
88 int page_size;
89 if (pixelsPerLine > 0 && winSize > 0 && winSize < virtSize)
90 {
91 upper = (virtSize + pixelsPerLine - 1) / pixelsPerLine;
92 page_size = winSize / pixelsPerLine;
93 *lines = upper;
94 *linesPerPage = page_size;
95 }
96 else
97 {
98 // GtkRange won't allow upper == lower, so for disabled state use [0,1]
99 // with a page size of 1. This will also clamp position to 0.
100 upper = 1;
101 page_size = 1;
102 *lines = 0;
103 *linesPerPage = 0;
104 }
105
106 GtkAdjustment* adj = range->adjustment;
107 adj->step_increment = 1;
108 adj->page_increment =
109 adj->page_size = page_size;
110 gtk_range_set_range(range, 0, upper);
111
112 // ensure that the scroll position is always in valid range
113 if (*pos > *lines)
114 *pos = *lines;
115 }
116
117 void wxScrollHelper::AdjustScrollbars()
118 {
119 int vw, vh;
120 m_targetWindow->GetVirtualSize(&vw, &vh);
121
122 int w, h;
123 const wxSize availSize = GetSizeAvailableForScrollTarget(
124 m_win->GetSize() - m_win->GetWindowBorderSize());
125 if ( availSize.x >= vw && availSize.y >= vh )
126 {
127 w = availSize.x;
128 h = availSize.y;
129
130 // we know that the scrollbars will be removed
131 DoAdjustHScrollbar(w, vw);
132 DoAdjustVScrollbar(h, vh);
133
134 return;
135 }
136
137 m_targetWindow->GetClientSize(&w, NULL);
138 DoAdjustHScrollbar(w, vw);
139
140 m_targetWindow->GetClientSize(NULL, &h);
141 DoAdjustVScrollbar(h, vh);
142
143 const int w_old = w;
144 m_targetWindow->GetClientSize(&w, NULL);
145 if ( w != w_old )
146 {
147 // It is necessary to repeat the calculations in this case to avoid an
148 // observed infinite series of size events, involving alternating
149 // changes in visibility of the scrollbars.
150 // At this point, GTK+ has already queued a resize, which will cause
151 // AdjustScrollbars() to be called again. If the scrollbar visibility
152 // is not correct before then, yet another resize will occur, possibly
153 // leading to an unending series if the sizes are just right.
154 DoAdjustHScrollbar(w, vw);
155
156 m_targetWindow->GetClientSize(NULL, &h);
157 DoAdjustVScrollbar(h, vh);
158 }
159 }
160
161 void wxScrollHelper::DoScrollOneDir(int orient,
162 int pos,
163 int pixelsPerLine,
164 int *posOld)
165 {
166 if ( pos != -1 && pos != *posOld && pixelsPerLine )
167 {
168 m_win->SetScrollPos(orient, pos);
169 pos = m_win->GetScrollPos(orient);
170
171 int diff = (*posOld - pos)*pixelsPerLine;
172 m_targetWindow->ScrollWindow(orient == wxHORIZONTAL ? diff : 0,
173 orient == wxHORIZONTAL ? 0 : diff);
174
175 *posOld = pos;
176 }
177 }
178
179 void wxScrollHelper::DoScroll( int x_pos, int y_pos )
180 {
181 wxCHECK_RET( m_targetWindow != 0, _T("No target window") );
182
183 DoScrollOneDir(wxHORIZONTAL, x_pos, m_xScrollPixelsPerLine, &m_xScrollPosition);
184 DoScrollOneDir(wxVERTICAL, y_pos, m_yScrollPixelsPerLine, &m_yScrollPosition);
185 }
186
187 // ----------------------------------------------------------------------------
188 // scrollbars visibility
189 // ----------------------------------------------------------------------------
190
191 namespace
192 {
193
194 GtkPolicyType GtkPolicyFromWX(wxScrollbarVisibility visibility)
195 {
196 GtkPolicyType policy;
197 switch ( visibility )
198 {
199 case wxSHOW_SB_NEVER:
200 policy = GTK_POLICY_NEVER;
201 break;
202
203 case wxSHOW_SB_DEFAULT:
204 policy = GTK_POLICY_AUTOMATIC;
205 break;
206
207 case wxSHOW_SB_ALWAYS:
208 policy = GTK_POLICY_ALWAYS;
209 break;
210 }
211
212 return policy;
213 }
214
215 } // anonymous namespace
216
217 void wxScrollHelper::DoShowScrollbars(wxScrollbarVisibility horz,
218 wxScrollbarVisibility vert)
219 {
220 GtkScrolledWindow * const scrolled = GTK_SCROLLED_WINDOW(m_win->m_widget);
221 wxCHECK_RET( scrolled, "window must be created" );
222
223 gtk_scrolled_window_set_policy(scrolled,
224 GtkPolicyFromWX(horz),
225 GtkPolicyFromWX(vert));
226 }
227