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
.height
-sPtr
->viewport
->size
.height
;
128 W_MoveView(sPtr
->contentView
, -x
, -y
);
130 W_RaiseView(sPtr
->viewport
);
135 reorganizeInterior(WMScrollView
*sPtr
)
142 cw
= hw
= sPtr
->view
->size
.width
;
143 vh
= ch
= sPtr
->view
->size
.height
;
145 if (sPtr
->flags
.relief
== WRSimple
) {
150 } else if (sPtr
->flags
.relief
!= WRFlat
) {
160 if (sPtr
->flags
.hasHScroller
) {
165 if (sPtr
->flags
.relief
== WRSimple
) {
167 hy
= sPtr
->view
->size
.height
- h
;
168 } else if (sPtr
->flags
.relief
!= WRFlat
) {
170 hy
= sPtr
->view
->size
.height
- h
- 1;
174 hy
= sPtr
->view
->size
.height
- h
;
177 /* make compiler shutup */
182 if (sPtr
->flags
.hasVScroller
) {
189 if (sPtr
->flags
.relief
== WRSimple
) {
192 } else if (sPtr
->flags
.relief
!= WRFlat
) {
201 /* make compiler shutup */
206 W_ResizeView(sPtr
->viewport
, cw
, ch
);
207 W_MoveView(sPtr
->viewport
, cx
, cy
);
209 if (sPtr
->flags
.hasHScroller
) {
210 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
211 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
213 if (sPtr
->flags
.hasVScroller
) {
214 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
215 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
218 applyScrollerValues(sPtr
);
223 resizeScrollView(W_ViewDelegate
*self
, WMView
*view
)
225 reorganizeInterior(view
->self
);
226 updateScrollerProportion(view
->self
);
232 WMResizeScrollViewContent(WMScrollView
*sPtr
, unsigned int width
,
241 if (sPtr
->flags
.relief
== WRSimple
) {
244 } else if (sPtr
->flags
.relief
!= WRFlat
) {
250 if (sPtr
->flags
.hasVScroller
) {
251 WMResizeWidget(sPtr
->vScroller
, 20, h
);
252 width
-= W_VIEW(sPtr
->vScroller
)->size
.width
;
255 if (sPtr
->flags
.hasHScroller
) {
256 WMResizeWidget(sPtr
->hScroller
, w
, 20);
257 WMMoveWidget(sPtr
->hScroller
, x
, h
);
258 height
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
261 W_ResizeView(sPtr
->view
, w
, h
);
263 W_ResizeView(sPtr
->viewport
, width
, height
);
268 WMSetScrollViewLineScroll(WMScrollView
*sPtr
, int amount
)
272 sPtr
->lineScroll
= amount
;
277 WMSetScrollViewPageScroll(WMScrollView
*sPtr
, int amount
)
281 sPtr
->pageScroll
= amount
;
286 WMGetScrollViewVisibleRect(WMScrollView
*sPtr
)
290 rect
.pos
.x
= -sPtr
->contentView
->pos
.x
;
291 rect
.pos
.y
= -sPtr
->contentView
->pos
.y
;
292 rect
.size
= sPtr
->viewport
->size
;
299 WMScrollViewScrollPoint(WMScrollView
*sPtr
, WMPoint point
)
304 xsize
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
305 ysize
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
307 xpos
= point
.x
/ xsize
;
308 ypos
= point
.y
/ ysize
;
311 WMSetScrollerParameters(sPtr
->hScroller
, xpos
,
312 WMGetScrollerKnobProportion(sPtr
->hScroller
));
314 WMSetScrollerParameters(sPtr
->vScroller
, ypos
,
315 WMGetScrollerKnobProportion(sPtr
->vScroller
));
317 W_MoveView(sPtr
->contentView
, -point
.x
, -point
.y
);
322 doScrolling(WMWidget
*self
, void *data
)
324 ScrollView
*sPtr
= (ScrollView
*)data
;
330 if (sPtr
->hScroller
== (WMScroller
*)self
) {
331 pos
= -sPtr
->contentView
->pos
.x
;
332 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
333 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
335 pos
= -sPtr
->contentView
->pos
.y
;
336 size
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
337 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
342 switch (WMGetScrollerHitPart(self
)) {
343 case WSDecrementLine
:
345 pos
-=sPtr
->lineScroll
;
348 value
= (float)pos
/ size
;
349 WMSetScrollerParameters(self
, value
,
350 WMGetScrollerKnobProportion(self
));
353 case WSIncrementLine
:
355 pos
+=sPtr
->lineScroll
;
358 value
= (float)pos
/ size
;
359 WMSetScrollerParameters(self
, value
,
360 WMGetScrollerKnobProportion(self
));
365 value
= WMGetScrollerValue(self
);
369 case WSDecrementPage
:
374 value
= (float)pos
/ size
;
375 WMSetScrollerParameters(self
, value
,
376 WMGetScrollerKnobProportion(self
));
380 case WSDecrementWheel
:
385 value
= (float)pos
/ size
;
386 WMSetScrollerParameters(self
, value
,
387 WMGetScrollerKnobProportion(self
));
391 case WSIncrementPage
:
396 value
= (float)pos
/ size
;
397 WMSetScrollerParameters(self
, value
,
398 WMGetScrollerKnobProportion(self
));
402 case WSIncrementWheel
:
407 value
= (float)pos
/ size
;
408 WMSetScrollerParameters(self
, value
,
409 WMGetScrollerKnobProportion(self
));
418 if (sPtr
->hScroller
== (WMScroller
*)self
) {
419 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
421 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
427 WMGetScrollViewHorizontalScroller(WMScrollView
*sPtr
)
429 return sPtr
->hScroller
;
435 WMGetScrollViewVerticalScroller(WMScrollView
*sPtr
)
437 return sPtr
->vScroller
;
442 WMSetScrollViewHasHorizontalScroller(WMScrollView
*sPtr
, Bool flag
)
445 if (sPtr
->flags
.hasHScroller
)
447 sPtr
->flags
.hasHScroller
= 1;
449 sPtr
->hScroller
= WMCreateScroller(sPtr
);
450 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
451 /* make it a horiz. scroller */
452 WMResizeWidget(sPtr
->hScroller
, 2, 1);
454 if (W_VIEW_REALIZED(sPtr
->view
)) {
455 WMRealizeWidget(sPtr
->hScroller
);
458 reorganizeInterior(sPtr
);
460 WMMapWidget(sPtr
->hScroller
);
462 if (!sPtr
->flags
.hasHScroller
)
465 WMUnmapWidget(sPtr
->hScroller
);
466 WMDestroyWidget(sPtr
->hScroller
);
467 sPtr
->hScroller
= NULL
;
468 sPtr
->flags
.hasHScroller
= 0;
470 reorganizeInterior(sPtr
);
476 WMSetScrollViewHasVerticalScroller(WMScrollView
*sPtr
, Bool flag
)
479 if (sPtr
->flags
.hasVScroller
)
481 sPtr
->flags
.hasVScroller
= 1;
483 sPtr
->vScroller
= WMCreateScroller(sPtr
);
484 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
485 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
486 /* make it a vert. scroller */
487 WMResizeWidget(sPtr
->vScroller
, 1, 2);
489 if (W_VIEW_REALIZED(sPtr
->view
)) {
490 WMRealizeWidget(sPtr
->vScroller
);
493 reorganizeInterior(sPtr
);
495 WMMapWidget(sPtr
->vScroller
);
497 if (!sPtr
->flags
.hasVScroller
)
499 sPtr
->flags
.hasVScroller
= 0;
501 WMUnmapWidget(sPtr
->vScroller
);
502 WMDestroyWidget(sPtr
->vScroller
);
503 sPtr
->vScroller
= NULL
;
505 reorganizeInterior(sPtr
);
511 WMSetScrollViewContentView(WMScrollView
*sPtr
, WMView
*view
)
513 assert(sPtr
->contentView
== NULL
);
515 sPtr
->contentView
= view
;
517 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
519 if (sPtr
->flags
.hasHScroller
) {
522 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
523 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
525 if (sPtr
->flags
.hasVScroller
) {
528 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
530 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
536 WMSetScrollViewRelief(WMScrollView
*sPtr
, WMReliefType type
)
538 sPtr
->flags
.relief
= type
;
540 reorganizeInterior(sPtr
);
542 if (sPtr
->view
->flags
.mapped
)
543 paintScrollView(sPtr
);
551 paintScrollView(ScrollView
*sPtr
)
553 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
554 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
,
560 updateScrollerProportion(ScrollView
*sPtr
)
565 if (sPtr
->flags
.hasHScroller
) {
566 oldV
= WMGetScrollerValue(sPtr
->hScroller
);
567 oldP
= WMGetScrollerKnobProportion(sPtr
->hScroller
);
569 prop
= (float)sPtr
->viewport
->size
.width
/(float)sPtr
->contentView
->size
.width
;
574 value
= (prop
* oldV
) / oldP
;
575 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
577 if (sPtr
->flags
.hasVScroller
) {
578 oldV
= WMGetScrollerValue(sPtr
->vScroller
);
579 oldP
= WMGetScrollerKnobProportion(sPtr
->vScroller
);
581 prop
= (float)sPtr
->viewport
->size
.height
/(float)sPtr
->contentView
->size
.height
;
586 value
= (prop
* oldV
) / oldP
;
587 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
589 applyScrollerValues(sPtr
);
594 handleViewportEvents(XEvent
*event
, void *data
)
596 ScrollView
*sPtr
= (ScrollView
*)data
;
598 if (sPtr
->contentView
599 && event
->xconfigure
.window
== sPtr
->contentView
->window
)
600 updateScrollerProportion(sPtr
);
605 handleEvents(XEvent
*event
, void *data
)
607 ScrollView
*sPtr
= (ScrollView
*)data
;
609 CHECK_CLASS(data
, WC_ScrollView
);
611 switch (event
->type
) {
613 if (event
->xexpose
.count
!=0)
615 if (event
->xexpose
.serial
== 0) /* means it's artificial */
616 W_RedisplayView(sPtr
->contentView
);
618 paintScrollView(sPtr
);
622 destroyScrollView(sPtr
);
630 destroyScrollView(ScrollView
*sPtr
)