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 width
-= W_VIEW(sPtr
->hScroller
)->size
.width
;
252 WMResizeWidget(sPtr
->vScroller
, 20, h
);
254 if (sPtr
->flags
.hasHScroller
) {
255 height
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
256 WMResizeWidget(sPtr
->hScroller
, w
, 20);
257 WMMoveWidget(sPtr
->hScroller
, x
, h
);
260 W_ResizeView(sPtr
->view
, w
, h
);
262 W_ResizeView(sPtr
->viewport
, width
, height
);
267 WMSetScrollViewLineScroll(WMScrollView
*sPtr
, int amount
)
271 sPtr
->lineScroll
= amount
;
276 WMSetScrollViewPageScroll(WMScrollView
*sPtr
, int amount
)
280 sPtr
->pageScroll
= amount
;
285 WMGetScrollViewVisibleRect(WMScrollView
*sPtr
)
289 rect
.pos
.x
= -sPtr
->contentView
->pos
.x
;
290 rect
.pos
.y
= -sPtr
->contentView
->pos
.y
;
291 rect
.size
= sPtr
->viewport
->size
;
298 WMScrollViewScrollPoint(WMScrollView
*sPtr
, WMPoint point
)
303 xsize
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
304 ysize
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
306 xpos
= point
.x
/ xsize
;
307 ypos
= point
.y
/ ysize
;
310 WMSetScrollerParameters(sPtr
->hScroller
, xpos
,
311 WMGetScrollerKnobProportion(sPtr
->hScroller
));
313 WMSetScrollerParameters(sPtr
->vScroller
, ypos
,
314 WMGetScrollerKnobProportion(sPtr
->vScroller
));
316 W_MoveView(sPtr
->contentView
, -point
.x
, -point
.y
);
321 doScrolling(WMWidget
*self
, void *data
)
323 ScrollView
*sPtr
= (ScrollView
*)data
;
329 if (sPtr
->hScroller
== (WMScroller
*)self
) {
330 pos
= -sPtr
->contentView
->pos
.x
;
331 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
332 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
334 pos
= -sPtr
->contentView
->pos
.y
;
335 size
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
336 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
341 switch (WMGetScrollerHitPart(self
)) {
342 case WSDecrementLine
:
344 pos
-=sPtr
->lineScroll
;
347 value
= (float)pos
/ size
;
348 WMSetScrollerParameters(self
, value
,
349 WMGetScrollerKnobProportion(self
));
352 case WSIncrementLine
:
354 pos
+=sPtr
->lineScroll
;
357 value
= (float)pos
/ size
;
358 WMSetScrollerParameters(self
, value
,
359 WMGetScrollerKnobProportion(self
));
364 value
= WMGetScrollerValue(self
);
368 case WSDecrementPage
:
373 value
= (float)pos
/ size
;
374 WMSetScrollerParameters(self
, value
,
375 WMGetScrollerKnobProportion(self
));
379 case WSDecrementWheel
:
384 value
= (float)pos
/ size
;
385 WMSetScrollerParameters(self
, value
,
386 WMGetScrollerKnobProportion(self
));
390 case WSIncrementPage
:
395 value
= (float)pos
/ size
;
396 WMSetScrollerParameters(self
, value
,
397 WMGetScrollerKnobProportion(self
));
401 case WSIncrementWheel
:
406 value
= (float)pos
/ size
;
407 WMSetScrollerParameters(self
, value
,
408 WMGetScrollerKnobProportion(self
));
417 if (sPtr
->hScroller
== (WMScroller
*)self
) {
418 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
420 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
426 WMGetScrollViewHorizontalScroller(WMScrollView
*sPtr
)
428 return sPtr
->hScroller
;
434 WMGetScrollViewVerticalScroller(WMScrollView
*sPtr
)
436 return sPtr
->vScroller
;
441 WMSetScrollViewHasHorizontalScroller(WMScrollView
*sPtr
, Bool flag
)
444 if (sPtr
->flags
.hasHScroller
)
446 sPtr
->flags
.hasHScroller
= 1;
448 sPtr
->hScroller
= WMCreateScroller(sPtr
);
449 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
450 /* make it a horiz. scroller */
451 WMResizeWidget(sPtr
->hScroller
, 2, 1);
453 if (W_VIEW_REALIZED(sPtr
->view
)) {
454 WMRealizeWidget(sPtr
->hScroller
);
457 reorganizeInterior(sPtr
);
459 WMMapWidget(sPtr
->hScroller
);
461 if (!sPtr
->flags
.hasHScroller
)
464 WMUnmapWidget(sPtr
->hScroller
);
465 WMDestroyWidget(sPtr
->hScroller
);
466 sPtr
->hScroller
= NULL
;
467 sPtr
->flags
.hasHScroller
= 0;
469 reorganizeInterior(sPtr
);
475 WMSetScrollViewHasVerticalScroller(WMScrollView
*sPtr
, Bool flag
)
478 if (sPtr
->flags
.hasVScroller
)
480 sPtr
->flags
.hasVScroller
= 1;
482 sPtr
->vScroller
= WMCreateScroller(sPtr
);
483 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
484 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
485 /* make it a vert. scroller */
486 WMResizeWidget(sPtr
->vScroller
, 1, 2);
488 if (W_VIEW_REALIZED(sPtr
->view
)) {
489 WMRealizeWidget(sPtr
->vScroller
);
492 reorganizeInterior(sPtr
);
494 WMMapWidget(sPtr
->vScroller
);
496 if (!sPtr
->flags
.hasVScroller
)
498 sPtr
->flags
.hasVScroller
= 0;
500 WMUnmapWidget(sPtr
->vScroller
);
501 WMDestroyWidget(sPtr
->vScroller
);
502 sPtr
->vScroller
= NULL
;
504 reorganizeInterior(sPtr
);
510 WMSetScrollViewContentView(WMScrollView
*sPtr
, WMView
*view
)
512 assert(sPtr
->contentView
== NULL
);
514 sPtr
->contentView
= view
;
516 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
518 if (sPtr
->flags
.hasHScroller
) {
521 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
522 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
524 if (sPtr
->flags
.hasVScroller
) {
527 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
529 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
535 WMSetScrollViewRelief(WMScrollView
*sPtr
, WMReliefType type
)
537 sPtr
->flags
.relief
= type
;
539 reorganizeInterior(sPtr
);
541 if (sPtr
->view
->flags
.mapped
)
542 paintScrollView(sPtr
);
550 paintScrollView(ScrollView
*sPtr
)
552 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
553 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
,
559 updateScrollerProportion(ScrollView
*sPtr
)
564 if (sPtr
->flags
.hasHScroller
) {
565 oldV
= WMGetScrollerValue(sPtr
->hScroller
);
566 oldP
= WMGetScrollerKnobProportion(sPtr
->hScroller
);
568 prop
= (float)sPtr
->viewport
->size
.width
/(float)sPtr
->contentView
->size
.width
;
573 value
= (prop
* oldV
) / oldP
;
574 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
576 if (sPtr
->flags
.hasVScroller
) {
577 oldV
= WMGetScrollerValue(sPtr
->vScroller
);
578 oldP
= WMGetScrollerKnobProportion(sPtr
->vScroller
);
580 prop
= (float)sPtr
->viewport
->size
.height
/(float)sPtr
->contentView
->size
.height
;
585 value
= (prop
* oldV
) / oldP
;
586 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
588 applyScrollerValues(sPtr
);
593 handleViewportEvents(XEvent
*event
, void *data
)
595 ScrollView
*sPtr
= (ScrollView
*)data
;
597 if (sPtr
->contentView
598 && event
->xconfigure
.window
== sPtr
->contentView
->window
)
599 updateScrollerProportion(sPtr
);
604 handleEvents(XEvent
*event
, void *data
)
606 ScrollView
*sPtr
= (ScrollView
*)data
;
608 CHECK_CLASS(data
, WC_ScrollView
);
610 switch (event
->type
) {
612 if (event
->xexpose
.count
!=0)
614 if (event
->xexpose
.serial
== 0) /* means it's artificial */
615 W_RedisplayView(sPtr
->contentView
);
617 paintScrollView(sPtr
);
621 destroyScrollView(sPtr
);
629 destroyScrollView(ScrollView
*sPtr
)