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