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_ViewProcedureTable _ScrollViewViewProcedures
= {
50 WMCreateScrollView(WMWidget
*parent
)
54 sPtr
= wmalloc(sizeof(ScrollView
));
55 memset(sPtr
, 0, sizeof(ScrollView
));
57 sPtr
->widgetClass
= WC_ScrollView
;
59 sPtr
->view
= W_CreateView(W_VIEW(parent
));
64 sPtr
->viewport
= W_CreateView(sPtr
->view
);
66 W_DestroyView(sPtr
->view
);
71 sPtr
->viewport
->flags
.mapWhenRealized
= 1;
73 WMCreateEventHandler(sPtr
->view
, StructureNotifyMask
|ExposureMask
,
75 WMCreateEventHandler(sPtr
->viewport
, SubstructureNotifyMask
,
76 handleViewportEvents
, sPtr
);
88 reorganizeInterior(WMScrollView
*sPtr
)
95 cw
= hw
= sPtr
->view
->size
.width
;
96 vh
= ch
= sPtr
->view
->size
.height
;
98 if (sPtr
->flags
.relief
== WRSimple
) {
103 } else if (sPtr
->flags
.relief
!= WRFlat
) {
113 if (sPtr
->flags
.hasHScroller
) {
114 int h
= W_VIEW(sPtr
->hScroller
)->size
.height
;
118 if (sPtr
->flags
.relief
== WRSimple
) {
120 hy
= sPtr
->view
->size
.height
- h
;
121 } else if (sPtr
->flags
.relief
!= WRFlat
) {
123 hy
= sPtr
->view
->size
.height
- h
- 1;
127 hy
= sPtr
->view
->size
.height
- h
;
130 /* make compiler shutup */
135 if (sPtr
->flags
.hasVScroller
) {
136 int w
= W_VIEW(sPtr
->vScroller
)->size
.width
;
142 if (sPtr
->flags
.relief
== WRSimple
) {
145 } else if (sPtr
->flags
.relief
!= WRFlat
) {
154 /* make compiler shutup */
159 W_ResizeView(sPtr
->viewport
, cw
, ch
);
160 W_MoveView(sPtr
->viewport
, cx
, cy
);
162 if (sPtr
->flags
.hasHScroller
) {
163 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
164 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
166 if (sPtr
->flags
.hasVScroller
) {
167 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
168 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
174 resizeScrollView(WMScrollView
*sPtr
, unsigned int width
, unsigned int height
)
176 W_ResizeView(sPtr
->view
, width
, height
);
178 reorganizeInterior(sPtr
);
184 WMResizeScrollViewContent(WMScrollView
*sPtr
, unsigned int width
,
193 if (sPtr
->flags
.relief
== WRSimple
) {
196 } else if (sPtr
->flags
.relief
!= WRFlat
) {
202 if (sPtr
->flags
.hasVScroller
) {
203 w
-= W_VIEW(sPtr
->hScroller
)->size
.width
;
204 WMResizeWidget(sPtr
->vScroller
, 20, h
);
206 if (sPtr
->flags
.hasHScroller
) {
207 h
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
208 WMResizeWidget(sPtr
->hScroller
, w
, 20);
209 WMMoveWidget(sPtr
->hScroller
, x
, h
);
212 W_ResizeView(sPtr
->view
, w
, h
);
214 W_ResizeView(sPtr
->viewport
, width
, height
);
219 WMSetScrollViewLineScroll(WMScrollView
*sPtr
, int amount
)
223 sPtr
->lineScroll
= amount
;
228 WMSetScrollViewPageScroll(WMScrollView
*sPtr
, int amount
)
232 sPtr
->pageScroll
= amount
;
237 doScrolling(WMWidget
*self
, void *data
)
239 ScrollView
*sPtr
= (ScrollView
*)data
;
245 if (sPtr
->hScroller
== self
) {
246 pos
= -sPtr
->contentView
->pos
.x
;
247 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
248 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
250 pos
= -sPtr
->contentView
->pos
.y
;
251 size
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
252 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
257 switch (WMGetScrollerHitPart(self
)) {
258 case WSDecrementLine
:
260 pos
-=sPtr
->lineScroll
;
263 value
= (float)pos
/ size
;
264 WMSetScrollerParameters(self
, value
,
265 WMGetScrollerKnobProportion(self
));
268 case WSIncrementLine
:
270 pos
+=sPtr
->lineScroll
;
273 value
= (float)pos
/ size
;
274 WMSetScrollerParameters(self
, value
,
275 WMGetScrollerKnobProportion(self
));
279 value
= WMGetScrollerValue(self
);
283 case WSDecrementPage
:
288 value
= (float)pos
/ size
;
289 WMSetScrollerParameters(self
, value
,
290 WMGetScrollerKnobProportion(self
));
294 case WSIncrementPage
:
299 value
= (float)pos
/ size
;
300 WMSetScrollerParameters(self
, value
,
301 WMGetScrollerKnobProportion(self
));
310 if (sPtr
->hScroller
== self
) {
311 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
313 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
319 WMGetScrollViewHorizontalScroller(WMScrollView
*sPtr
)
321 return sPtr
->hScroller
;
327 WMGetScrollViewVerticalScroller(WMScrollView
*sPtr
)
329 return sPtr
->vScroller
;
334 WMSetScrollViewHasHorizontalScroller(WMScrollView
*sPtr
, Bool flag
)
337 if (sPtr
->flags
.hasHScroller
)
339 sPtr
->flags
.hasHScroller
= 1;
341 sPtr
->hScroller
= WMCreateScroller(sPtr
);
342 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
343 /* make it a horiz. scroller */
344 WMResizeWidget(sPtr
->hScroller
, 2, 1);
346 reorganizeInterior(sPtr
);
348 WMMapWidget(sPtr
->hScroller
);
350 if (!sPtr
->flags
.hasHScroller
)
353 WMUnmapWidget(sPtr
->hScroller
);
354 WMDestroyWidget(sPtr
->hScroller
);
355 sPtr
->hScroller
= NULL
;
356 sPtr
->flags
.hasHScroller
= 0;
358 reorganizeInterior(sPtr
);
364 WMSetScrollViewHasVerticalScroller(WMScrollView
*sPtr
, Bool flag
)
367 if (sPtr
->flags
.hasVScroller
)
369 sPtr
->flags
.hasVScroller
= 1;
371 sPtr
->vScroller
= WMCreateScroller(sPtr
);
372 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
373 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
374 /* make it a vert. scroller */
375 WMResizeWidget(sPtr
->vScroller
, 1, 2);
377 reorganizeInterior(sPtr
);
379 WMMapWidget(sPtr
->vScroller
);
381 if (!sPtr
->flags
.hasVScroller
)
383 sPtr
->flags
.hasVScroller
= 0;
385 WMUnmapWidget(sPtr
->vScroller
);
386 WMDestroyWidget(sPtr
->vScroller
);
387 sPtr
->vScroller
= NULL
;
389 reorganizeInterior(sPtr
);
395 WMSetScrollViewContentView(WMScrollView
*sPtr
, WMView
*view
)
397 assert(sPtr
->contentView
== NULL
);
399 sPtr
->contentView
= view
;
401 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
403 if (sPtr
->flags
.hasHScroller
) {
406 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
407 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
409 if (sPtr
->flags
.hasVScroller
) {
412 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
414 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
420 WMSetScrollViewRelief(WMScrollView
*sPtr
, WMReliefType type
)
422 sPtr
->flags
.relief
= type
;
424 if (sPtr
->view
->flags
.mapped
)
425 paintScrollView(sPtr
);
432 paintScrollView(ScrollView
*sPtr
)
434 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
435 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
,
441 updateScrollerProportion(ScrollView
*sPtr
)
445 if (sPtr
->flags
.hasHScroller
) {
446 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
447 value
= WMGetScrollerValue(sPtr
->hScroller
);
449 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
451 if (sPtr
->flags
.hasVScroller
) {
452 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
454 value
= WMGetScrollerValue(sPtr
->vScroller
);
456 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
462 handleViewportEvents(XEvent
*event
, void *data
)
464 ScrollView
*sPtr
= (ScrollView
*)data
;
466 if (sPtr
->contentView
467 && event
->xconfigure
.window
== sPtr
->contentView
->window
)
468 updateScrollerProportion(sPtr
);
473 handleEvents(XEvent
*event
, void *data
)
475 ScrollView
*sPtr
= (ScrollView
*)data
;
477 CHECK_CLASS(data
, WC_ScrollView
);
479 switch (event
->type
) {
481 if (event
->xexpose
.count
!=0)
483 paintScrollView(sPtr
);
487 destroyScrollView(sPtr
);
495 destroyScrollView(ScrollView
*sPtr
)