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();
39 static void updateScrollerProportion();
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
);
67 if (!sPtr
->viewport
) {
68 W_DestroyView(sPtr
->view
);
72 sPtr
->view
->self
= sPtr
;
73 sPtr
->viewport
->self
= sPtr
;
75 sPtr
->view
->delegate
= &_ScrollViewViewDelegate
;
77 sPtr
->viewport
->flags
.mapWhenRealized
= 1;
79 WMCreateEventHandler(sPtr
->view
, StructureNotifyMask
|ExposureMask
,
81 WMCreateEventHandler(sPtr
->viewport
, SubstructureNotifyMask
,
82 handleViewportEvents
, sPtr
);
93 applyScrollerValues(WMScrollView
*sPtr
)
97 if (sPtr
->contentView
== NULL
)
100 if (sPtr
->flags
.hasHScroller
) {
101 float v
= WMGetScrollerValue(sPtr
->hScroller
);
104 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
111 if (sPtr
->flags
.hasVScroller
) {
112 float v
= WMGetScrollerValue(sPtr
->vScroller
);
116 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
126 W_MoveView(sPtr
->contentView
, -x
, -y
);
128 W_RaiseView(sPtr
->viewport
);
133 reorganizeInterior(WMScrollView
*sPtr
)
140 cw
= hw
= sPtr
->view
->size
.width
;
141 vh
= ch
= sPtr
->view
->size
.height
;
143 if (sPtr
->flags
.relief
== WRSimple
) {
148 } else if (sPtr
->flags
.relief
!= WRFlat
) {
158 if (sPtr
->flags
.hasHScroller
) {
163 if (sPtr
->flags
.relief
== WRSimple
) {
165 hy
= sPtr
->view
->size
.height
- h
;
166 } else if (sPtr
->flags
.relief
!= WRFlat
) {
168 hy
= sPtr
->view
->size
.height
- h
- 1;
172 hy
= sPtr
->view
->size
.height
- h
;
175 /* make compiler shutup */
180 if (sPtr
->flags
.hasVScroller
) {
187 if (sPtr
->flags
.relief
== WRSimple
) {
190 } else if (sPtr
->flags
.relief
!= WRFlat
) {
199 /* make compiler shutup */
204 W_ResizeView(sPtr
->viewport
, cw
, ch
);
205 W_MoveView(sPtr
->viewport
, cx
, cy
);
207 if (sPtr
->flags
.hasHScroller
) {
208 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
209 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
211 if (sPtr
->flags
.hasVScroller
) {
212 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
213 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
216 applyScrollerValues(sPtr
);
221 resizeScrollView(W_ViewDelegate
*self
, WMView
*view
)
223 reorganizeInterior(view
->self
);
224 updateScrollerProportion(view
->self
);
230 WMResizeScrollViewContent(WMScrollView
*sPtr
, unsigned int width
,
239 if (sPtr
->flags
.relief
== WRSimple
) {
242 } else if (sPtr
->flags
.relief
!= WRFlat
) {
248 if (sPtr
->flags
.hasVScroller
) {
249 width
-= W_VIEW(sPtr
->hScroller
)->size
.width
;
250 WMResizeWidget(sPtr
->vScroller
, 20, h
);
252 if (sPtr
->flags
.hasHScroller
) {
253 height
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
254 WMResizeWidget(sPtr
->hScroller
, w
, 20);
255 WMMoveWidget(sPtr
->hScroller
, x
, h
);
258 W_ResizeView(sPtr
->view
, w
, h
);
260 W_ResizeView(sPtr
->viewport
, width
, height
);
265 WMSetScrollViewLineScroll(WMScrollView
*sPtr
, int amount
)
269 sPtr
->lineScroll
= amount
;
274 WMSetScrollViewPageScroll(WMScrollView
*sPtr
, int amount
)
278 sPtr
->pageScroll
= amount
;
283 WMGetScrollViewVisibleRect(WMScrollView
*sPtr
)
287 rect
.pos
.x
= -sPtr
->contentView
->pos
.x
;
288 rect
.pos
.y
= -sPtr
->contentView
->pos
.y
;
289 rect
.size
= sPtr
->viewport
->size
;
296 WMScrollViewScrollPoint(WMScrollView
*sPtr
, WMPoint point
)
301 xsize
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
302 ysize
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
304 xpos
= point
.x
/ xsize
;
305 ypos
= point
.y
/ ysize
;
308 WMSetScrollerParameters(sPtr
->hScroller
, xpos
,
309 WMGetScrollerKnobProportion(sPtr
->hScroller
));
311 WMSetScrollerParameters(sPtr
->vScroller
, ypos
,
312 WMGetScrollerKnobProportion(sPtr
->vScroller
));
314 W_MoveView(sPtr
->contentView
, -point
.x
, -point
.y
);
319 doScrolling(WMWidget
*self
, void *data
)
321 ScrollView
*sPtr
= (ScrollView
*)data
;
327 if (sPtr
->hScroller
== (WMScroller
*)self
) {
328 pos
= -sPtr
->contentView
->pos
.x
;
329 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
330 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
332 pos
= -sPtr
->contentView
->pos
.y
;
333 size
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
334 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
339 switch (WMGetScrollerHitPart(self
)) {
340 case WSDecrementLine
:
342 pos
-=sPtr
->lineScroll
;
345 value
= (float)pos
/ size
;
346 WMSetScrollerParameters(self
, value
,
347 WMGetScrollerKnobProportion(self
));
350 case WSIncrementLine
:
352 pos
+=sPtr
->lineScroll
;
355 value
= (float)pos
/ size
;
356 WMSetScrollerParameters(self
, value
,
357 WMGetScrollerKnobProportion(self
));
362 value
= WMGetScrollerValue(self
);
366 case WSDecrementPage
:
371 value
= (float)pos
/ size
;
372 WMSetScrollerParameters(self
, value
,
373 WMGetScrollerKnobProportion(self
));
377 case WSDecrementWheel
:
382 value
= (float)pos
/ size
;
383 WMSetScrollerParameters(self
, value
,
384 WMGetScrollerKnobProportion(self
));
388 case WSIncrementPage
:
393 value
= (float)pos
/ size
;
394 WMSetScrollerParameters(self
, value
,
395 WMGetScrollerKnobProportion(self
));
399 case WSIncrementWheel
:
404 value
= (float)pos
/ size
;
405 WMSetScrollerParameters(self
, value
,
406 WMGetScrollerKnobProportion(self
));
415 if (sPtr
->hScroller
== (WMScroller
*)self
) {
416 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
418 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
424 WMGetScrollViewHorizontalScroller(WMScrollView
*sPtr
)
426 return sPtr
->hScroller
;
432 WMGetScrollViewVerticalScroller(WMScrollView
*sPtr
)
434 return sPtr
->vScroller
;
439 WMSetScrollViewHasHorizontalScroller(WMScrollView
*sPtr
, Bool flag
)
442 if (sPtr
->flags
.hasHScroller
)
444 sPtr
->flags
.hasHScroller
= 1;
446 sPtr
->hScroller
= WMCreateScroller(sPtr
);
447 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
448 /* make it a horiz. scroller */
449 WMResizeWidget(sPtr
->hScroller
, 2, 1);
451 reorganizeInterior(sPtr
);
453 WMMapWidget(sPtr
->hScroller
);
455 if (!sPtr
->flags
.hasHScroller
)
458 WMUnmapWidget(sPtr
->hScroller
);
459 WMDestroyWidget(sPtr
->hScroller
);
460 sPtr
->hScroller
= NULL
;
461 sPtr
->flags
.hasHScroller
= 0;
463 reorganizeInterior(sPtr
);
469 WMSetScrollViewHasVerticalScroller(WMScrollView
*sPtr
, Bool flag
)
472 if (sPtr
->flags
.hasVScroller
)
474 sPtr
->flags
.hasVScroller
= 1;
476 sPtr
->vScroller
= WMCreateScroller(sPtr
);
477 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
478 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
479 /* make it a vert. scroller */
480 WMResizeWidget(sPtr
->vScroller
, 1, 2);
482 reorganizeInterior(sPtr
);
484 WMMapWidget(sPtr
->vScroller
);
486 if (!sPtr
->flags
.hasVScroller
)
488 sPtr
->flags
.hasVScroller
= 0;
490 WMUnmapWidget(sPtr
->vScroller
);
491 WMDestroyWidget(sPtr
->vScroller
);
492 sPtr
->vScroller
= NULL
;
494 reorganizeInterior(sPtr
);
500 WMSetScrollViewContentView(WMScrollView
*sPtr
, WMView
*view
)
502 assert(sPtr
->contentView
== NULL
);
504 sPtr
->contentView
= view
;
506 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
508 if (sPtr
->flags
.hasHScroller
) {
511 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
512 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
514 if (sPtr
->flags
.hasVScroller
) {
517 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
519 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
525 WMSetScrollViewRelief(WMScrollView
*sPtr
, WMReliefType type
)
527 sPtr
->flags
.relief
= type
;
529 reorganizeInterior(sPtr
);
531 if (sPtr
->view
->flags
.mapped
)
532 paintScrollView(sPtr
);
540 paintScrollView(ScrollView
*sPtr
)
542 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
543 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
,
549 updateScrollerProportion(ScrollView
*sPtr
)
553 if (sPtr
->flags
.hasHScroller
) {
554 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
555 value
= WMGetScrollerValue(sPtr
->hScroller
);
557 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
559 if (sPtr
->flags
.hasVScroller
) {
560 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
562 value
= WMGetScrollerValue(sPtr
->vScroller
);
564 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
570 handleViewportEvents(XEvent
*event
, void *data
)
572 ScrollView
*sPtr
= (ScrollView
*)data
;
574 if (sPtr
->contentView
575 && event
->xconfigure
.window
== sPtr
->contentView
->window
)
576 updateScrollerProportion(sPtr
);
581 handleEvents(XEvent
*event
, void *data
)
583 ScrollView
*sPtr
= (ScrollView
*)data
;
585 CHECK_CLASS(data
, WC_ScrollView
);
587 switch (event
->type
) {
589 if (event
->xexpose
.count
!=0)
591 if (event
->xexpose
.serial
== 0) /* means it's artificial */
592 W_RedisplayView(sPtr
->contentView
);
594 paintScrollView(sPtr
);
598 destroyScrollView(sPtr
);
606 destroyScrollView(ScrollView
*sPtr
)