8 typedef struct W_ScrollView
{
15 WMScroller
*vScroller
;
16 WMScroller
*hScroller
;
22 WMReliefType relief
:3;
23 unsigned int hasVScroller
:1;
24 unsigned int hasHScroller
:1;
33 static void destroyScrollView(ScrollView
*sPtr
);
35 static void paintScrollView(ScrollView
*sPtr
);
36 static void handleEvents(XEvent
*event
, void *data
);
37 static void handleViewportEvents(XEvent
*event
, void *data
);
38 static void resizeScrollView();
41 W_ViewDelegate _ScrollViewViewDelegate
= {
52 WMCreateScrollView(WMWidget
*parent
)
56 sPtr
= wmalloc(sizeof(ScrollView
));
57 memset(sPtr
, 0, sizeof(ScrollView
));
59 sPtr
->widgetClass
= WC_ScrollView
;
61 sPtr
->view
= W_CreateView(W_VIEW(parent
));
66 sPtr
->viewport
= W_CreateView(sPtr
->view
);
68 W_DestroyView(sPtr
->view
);
72 sPtr
->view
->self
= sPtr
;
74 sPtr
->view
->delegate
= &_ScrollViewViewDelegate
;
76 sPtr
->viewport
->flags
.mapWhenRealized
= 1;
78 WMCreateEventHandler(sPtr
->view
, StructureNotifyMask
|ExposureMask
,
80 WMCreateEventHandler(sPtr
->viewport
, SubstructureNotifyMask
,
81 handleViewportEvents
, sPtr
);
93 reorganizeInterior(WMScrollView
*sPtr
)
100 cw
= hw
= sPtr
->view
->size
.width
;
101 vh
= ch
= sPtr
->view
->size
.height
;
103 if (sPtr
->flags
.relief
== WRSimple
) {
108 } else if (sPtr
->flags
.relief
!= WRFlat
) {
118 if (sPtr
->flags
.hasHScroller
) {
119 int h
= W_VIEW(sPtr
->hScroller
)->size
.height
;
123 if (sPtr
->flags
.relief
== WRSimple
) {
125 hy
= sPtr
->view
->size
.height
- h
;
126 } else if (sPtr
->flags
.relief
!= WRFlat
) {
128 hy
= sPtr
->view
->size
.height
- h
- 1;
132 hy
= sPtr
->view
->size
.height
- h
;
135 /* make compiler shutup */
140 if (sPtr
->flags
.hasVScroller
) {
141 int w
= W_VIEW(sPtr
->vScroller
)->size
.width
;
147 if (sPtr
->flags
.relief
== WRSimple
) {
150 } else if (sPtr
->flags
.relief
!= WRFlat
) {
159 /* make compiler shutup */
164 W_ResizeView(sPtr
->viewport
, cw
, ch
);
165 W_MoveView(sPtr
->viewport
, cx
, cy
);
167 if (sPtr
->flags
.hasHScroller
) {
168 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
169 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
171 if (sPtr
->flags
.hasVScroller
) {
172 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
173 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
179 resizeScrollView(W_ViewDelegate
*self
, WMView
*view
)
181 reorganizeInterior(view
->self
);
187 WMResizeScrollViewContent(WMScrollView
*sPtr
, unsigned int width
,
196 if (sPtr
->flags
.relief
== WRSimple
) {
199 } else if (sPtr
->flags
.relief
!= WRFlat
) {
205 if (sPtr
->flags
.hasVScroller
) {
206 w
-= W_VIEW(sPtr
->hScroller
)->size
.width
;
207 WMResizeWidget(sPtr
->vScroller
, 20, h
);
209 if (sPtr
->flags
.hasHScroller
) {
210 h
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
211 WMResizeWidget(sPtr
->hScroller
, w
, 20);
212 WMMoveWidget(sPtr
->hScroller
, x
, h
);
215 W_ResizeView(sPtr
->view
, w
, h
);
217 W_ResizeView(sPtr
->viewport
, width
, height
);
222 WMSetScrollViewLineScroll(WMScrollView
*sPtr
, int amount
)
226 sPtr
->lineScroll
= amount
;
231 WMSetScrollViewPageScroll(WMScrollView
*sPtr
, int amount
)
235 sPtr
->pageScroll
= amount
;
240 doScrolling(WMWidget
*self
, void *data
)
242 ScrollView
*sPtr
= (ScrollView
*)data
;
248 if (sPtr
->hScroller
== (WMScroller
*)self
) {
249 pos
= -sPtr
->contentView
->pos
.x
;
250 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
251 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
253 pos
= -sPtr
->contentView
->pos
.y
;
254 size
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
255 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
260 switch (WMGetScrollerHitPart(self
)) {
261 case WSDecrementLine
:
263 pos
-=sPtr
->lineScroll
;
266 value
= (float)pos
/ size
;
267 WMSetScrollerParameters(self
, value
,
268 WMGetScrollerKnobProportion(self
));
271 case WSIncrementLine
:
273 pos
+=sPtr
->lineScroll
;
276 value
= (float)pos
/ size
;
277 WMSetScrollerParameters(self
, value
,
278 WMGetScrollerKnobProportion(self
));
282 value
= WMGetScrollerValue(self
);
286 case WSDecrementPage
:
291 value
= (float)pos
/ size
;
292 WMSetScrollerParameters(self
, value
,
293 WMGetScrollerKnobProportion(self
));
297 case WSIncrementPage
:
302 value
= (float)pos
/ size
;
303 WMSetScrollerParameters(self
, value
,
304 WMGetScrollerKnobProportion(self
));
313 if (sPtr
->hScroller
== (WMScroller
*)self
) {
314 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
316 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
322 WMGetScrollViewHorizontalScroller(WMScrollView
*sPtr
)
324 return sPtr
->hScroller
;
330 WMGetScrollViewVerticalScroller(WMScrollView
*sPtr
)
332 return sPtr
->vScroller
;
337 WMSetScrollViewHasHorizontalScroller(WMScrollView
*sPtr
, Bool flag
)
340 if (sPtr
->flags
.hasHScroller
)
342 sPtr
->flags
.hasHScroller
= 1;
344 sPtr
->hScroller
= WMCreateScroller(sPtr
);
345 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
346 /* make it a horiz. scroller */
347 WMResizeWidget(sPtr
->hScroller
, 2, 1);
349 reorganizeInterior(sPtr
);
351 WMMapWidget(sPtr
->hScroller
);
353 if (!sPtr
->flags
.hasHScroller
)
356 WMUnmapWidget(sPtr
->hScroller
);
357 WMDestroyWidget(sPtr
->hScroller
);
358 sPtr
->hScroller
= NULL
;
359 sPtr
->flags
.hasHScroller
= 0;
361 reorganizeInterior(sPtr
);
367 WMSetScrollViewHasVerticalScroller(WMScrollView
*sPtr
, Bool flag
)
370 if (sPtr
->flags
.hasVScroller
)
372 sPtr
->flags
.hasVScroller
= 1;
374 sPtr
->vScroller
= WMCreateScroller(sPtr
);
375 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
376 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
377 /* make it a vert. scroller */
378 WMResizeWidget(sPtr
->vScroller
, 1, 2);
380 reorganizeInterior(sPtr
);
382 WMMapWidget(sPtr
->vScroller
);
384 if (!sPtr
->flags
.hasVScroller
)
386 sPtr
->flags
.hasVScroller
= 0;
388 WMUnmapWidget(sPtr
->vScroller
);
389 WMDestroyWidget(sPtr
->vScroller
);
390 sPtr
->vScroller
= NULL
;
392 reorganizeInterior(sPtr
);
398 WMSetScrollViewContentView(WMScrollView
*sPtr
, WMView
*view
)
400 assert(sPtr
->contentView
== NULL
);
402 sPtr
->contentView
= view
;
404 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
406 if (sPtr
->flags
.hasHScroller
) {
409 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
410 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
412 if (sPtr
->flags
.hasVScroller
) {
415 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
417 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
423 WMSetScrollViewRelief(WMScrollView
*sPtr
, WMReliefType type
)
425 sPtr
->flags
.relief
= type
;
427 if (sPtr
->view
->flags
.mapped
)
428 paintScrollView(sPtr
);
435 paintScrollView(ScrollView
*sPtr
)
437 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
438 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
,
444 updateScrollerProportion(ScrollView
*sPtr
)
448 if (sPtr
->flags
.hasHScroller
) {
449 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
450 value
= WMGetScrollerValue(sPtr
->hScroller
);
452 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
454 if (sPtr
->flags
.hasVScroller
) {
455 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
457 value
= WMGetScrollerValue(sPtr
->vScroller
);
459 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
465 handleViewportEvents(XEvent
*event
, void *data
)
467 ScrollView
*sPtr
= (ScrollView
*)data
;
469 if (sPtr
->contentView
470 && event
->xconfigure
.window
== sPtr
->contentView
->window
)
471 updateScrollerProportion(sPtr
);
476 handleEvents(XEvent
*event
, void *data
)
478 ScrollView
*sPtr
= (ScrollView
*)data
;
480 CHECK_CLASS(data
, WC_ScrollView
);
482 switch (event
->type
) {
484 if (event
->xexpose
.count
!=0)
486 paintScrollView(sPtr
);
490 destroyScrollView(sPtr
);
498 destroyScrollView(ScrollView
*sPtr
)