4 typedef struct W_ScrollView
{
11 WMScroller
*vScroller
;
12 WMScroller
*hScroller
;
18 WMReliefType relief
:3;
19 unsigned int hasVScroller
:1;
20 unsigned int hasHScroller
:1;
26 static void destroyScrollView(ScrollView
* sPtr
);
28 static void paintScrollView(ScrollView
* sPtr
);
29 static void handleEvents(XEvent
* event
, void *data
);
30 static void handleViewportEvents(XEvent
* event
, void *data
);
31 static void resizeScrollView(W_ViewDelegate
*self
, WMView
*view
);
32 static void updateScrollerProportion(ScrollView
*sPtr
);
34 W_ViewDelegate _ScrollViewViewDelegate
= {
42 WMScrollView
*WMCreateScrollView(WMWidget
* parent
)
46 sPtr
= wmalloc(sizeof(ScrollView
));
47 sPtr
->widgetClass
= WC_ScrollView
;
49 sPtr
->view
= W_CreateView(W_VIEW(parent
));
54 sPtr
->viewport
= W_CreateView(sPtr
->view
);
55 if (!sPtr
->viewport
) {
56 W_DestroyView(sPtr
->view
);
60 sPtr
->view
->self
= sPtr
;
61 sPtr
->viewport
->self
= sPtr
;
63 sPtr
->view
->delegate
= &_ScrollViewViewDelegate
;
65 sPtr
->viewport
->flags
.mapWhenRealized
= 1;
67 WMCreateEventHandler(sPtr
->view
, StructureNotifyMask
| ExposureMask
, handleEvents
, sPtr
);
68 WMCreateEventHandler(sPtr
->viewport
, SubstructureNotifyMask
, handleViewportEvents
, sPtr
);
77 static void applyScrollerValues(WMScrollView
* sPtr
)
81 if (sPtr
->contentView
== NULL
)
84 if (sPtr
->flags
.hasHScroller
) {
85 float v
= WMGetScrollerValue(sPtr
->hScroller
);
88 size
= sPtr
->contentView
->size
.width
- sPtr
->viewport
->size
.width
;
95 if (sPtr
->flags
.hasVScroller
) {
96 float v
= WMGetScrollerValue(sPtr
->vScroller
);
100 size
= sPtr
->contentView
->size
.height
- sPtr
->viewport
->size
.height
;
110 W_MoveView(sPtr
->contentView
, -x
, -y
);
112 W_RaiseView(sPtr
->viewport
);
115 static void reorganizeInterior(WMScrollView
* sPtr
)
121 cw
= hw
= sPtr
->view
->size
.width
;
122 vh
= ch
= sPtr
->view
->size
.height
;
124 if (sPtr
->flags
.relief
== WRSimple
) {
129 } else if (sPtr
->flags
.relief
!= WRFlat
) {
139 if (sPtr
->flags
.hasHScroller
) {
144 if (sPtr
->flags
.relief
== WRSimple
) {
146 hy
= sPtr
->view
->size
.height
- h
;
147 } else if (sPtr
->flags
.relief
!= WRFlat
) {
149 hy
= sPtr
->view
->size
.height
- h
- 1;
153 hy
= sPtr
->view
->size
.height
- h
;
156 /* make compiler shutup */
161 if (sPtr
->flags
.hasVScroller
) {
168 if (sPtr
->flags
.relief
== WRSimple
) {
171 } else if (sPtr
->flags
.relief
!= WRFlat
) {
180 /* make compiler shutup */
185 W_ResizeView(sPtr
->viewport
, cw
, ch
);
186 W_MoveView(sPtr
->viewport
, cx
, cy
);
188 if (sPtr
->flags
.hasHScroller
) {
189 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
190 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
192 if (sPtr
->flags
.hasVScroller
) {
193 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
194 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
197 applyScrollerValues(sPtr
);
200 static void resizeScrollView(W_ViewDelegate
* self
, WMView
* view
)
202 /* Parameter not used, but tell the compiler that it is ok */
205 reorganizeInterior(view
->self
);
206 updateScrollerProportion(view
->self
);
209 void WMResizeScrollViewContent(WMScrollView
* sPtr
, unsigned int width
, unsigned int height
)
217 if (sPtr
->flags
.relief
== WRSimple
) {
220 } else if (sPtr
->flags
.relief
!= WRFlat
) {
226 if (sPtr
->flags
.hasVScroller
) {
227 WMResizeWidget(sPtr
->vScroller
, 20, h
);
228 width
-= W_VIEW(sPtr
->vScroller
)->size
.width
;
231 if (sPtr
->flags
.hasHScroller
) {
232 WMResizeWidget(sPtr
->hScroller
, w
, 20);
233 WMMoveWidget(sPtr
->hScroller
, x
, h
);
234 height
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
237 W_ResizeView(sPtr
->view
, w
, h
);
239 W_ResizeView(sPtr
->viewport
, width
, height
);
242 void WMSetScrollViewLineScroll(WMScrollView
* sPtr
, int amount
)
246 sPtr
->lineScroll
= amount
;
249 void WMSetScrollViewPageScroll(WMScrollView
* sPtr
, int amount
)
253 sPtr
->pageScroll
= amount
;
256 WMRect
WMGetScrollViewVisibleRect(WMScrollView
* sPtr
)
260 rect
.pos
.x
= -sPtr
->contentView
->pos
.x
;
261 rect
.pos
.y
= -sPtr
->contentView
->pos
.y
;
262 rect
.size
= sPtr
->viewport
->size
;
267 void WMScrollViewScrollPoint(WMScrollView
* sPtr
, WMPoint point
)
272 xsize
= sPtr
->contentView
->size
.width
- sPtr
->viewport
->size
.width
;
273 ysize
= sPtr
->contentView
->size
.height
- sPtr
->viewport
->size
.height
;
275 xpos
= point
.x
/ xsize
;
276 ypos
= point
.y
/ ysize
;
279 WMSetScrollerParameters(sPtr
->hScroller
, xpos
, WMGetScrollerKnobProportion(sPtr
->hScroller
));
281 WMSetScrollerParameters(sPtr
->vScroller
, ypos
, WMGetScrollerKnobProportion(sPtr
->vScroller
));
283 W_MoveView(sPtr
->contentView
, -point
.x
, -point
.y
);
286 static void doScrolling(WMWidget
* self
, void *data
)
288 ScrollView
*sPtr
= (ScrollView
*) data
;
294 if (sPtr
->hScroller
== (WMScroller
*) self
) {
295 pos
= -sPtr
->contentView
->pos
.x
;
296 size
= sPtr
->contentView
->size
.width
- sPtr
->viewport
->size
.width
;
297 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
299 pos
= -sPtr
->contentView
->pos
.y
;
300 size
= sPtr
->contentView
->size
.height
- sPtr
->viewport
->size
.height
;
301 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
306 switch (WMGetScrollerHitPart(self
)) {
307 case WSDecrementLine
:
309 pos
-= sPtr
->lineScroll
;
312 value
= (float)pos
/ size
;
313 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
316 case WSIncrementLine
:
318 pos
+= sPtr
->lineScroll
;
321 value
= (float)pos
/ size
;
322 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
327 value
= WMGetScrollerValue(self
);
331 case WSDecrementPage
:
336 value
= (float)pos
/ size
;
337 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
341 case WSDecrementWheel
:
346 value
= (float)pos
/ size
;
347 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
351 case WSIncrementPage
:
356 value
= (float)pos
/ size
;
357 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
361 case WSIncrementWheel
:
366 value
= (float)pos
/ size
;
367 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
376 if (sPtr
->hScroller
== (WMScroller
*) self
) {
377 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
379 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
383 WMScroller
*WMGetScrollViewHorizontalScroller(WMScrollView
* sPtr
)
385 return sPtr
->hScroller
;
388 WMScroller
*WMGetScrollViewVerticalScroller(WMScrollView
* sPtr
)
390 return sPtr
->vScroller
;
393 void WMSetScrollViewHasHorizontalScroller(WMScrollView
* sPtr
, Bool flag
)
396 if (sPtr
->flags
.hasHScroller
)
398 sPtr
->flags
.hasHScroller
= 1;
400 sPtr
->hScroller
= WMCreateScroller(sPtr
);
401 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
402 /* make it a horiz. scroller */
403 WMResizeWidget(sPtr
->hScroller
, 2, 1);
405 if (W_VIEW_REALIZED(sPtr
->view
)) {
406 WMRealizeWidget(sPtr
->hScroller
);
409 reorganizeInterior(sPtr
);
411 WMMapWidget(sPtr
->hScroller
);
413 if (!sPtr
->flags
.hasHScroller
)
416 WMUnmapWidget(sPtr
->hScroller
);
417 WMDestroyWidget(sPtr
->hScroller
);
418 sPtr
->hScroller
= NULL
;
419 sPtr
->flags
.hasHScroller
= 0;
421 reorganizeInterior(sPtr
);
425 void WMSetScrollViewHasVerticalScroller(WMScrollView
* sPtr
, Bool flag
)
428 if (sPtr
->flags
.hasVScroller
)
430 sPtr
->flags
.hasVScroller
= 1;
432 sPtr
->vScroller
= WMCreateScroller(sPtr
);
433 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
434 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
435 /* make it a vert. scroller */
436 WMResizeWidget(sPtr
->vScroller
, 1, 2);
438 if (W_VIEW_REALIZED(sPtr
->view
)) {
439 WMRealizeWidget(sPtr
->vScroller
);
442 reorganizeInterior(sPtr
);
444 WMMapWidget(sPtr
->vScroller
);
446 if (!sPtr
->flags
.hasVScroller
)
448 sPtr
->flags
.hasVScroller
= 0;
450 WMUnmapWidget(sPtr
->vScroller
);
451 WMDestroyWidget(sPtr
->vScroller
);
452 sPtr
->vScroller
= NULL
;
454 reorganizeInterior(sPtr
);
458 void WMSetScrollViewContentView(WMScrollView
* sPtr
, WMView
* view
)
460 assert(sPtr
->contentView
== NULL
);
462 sPtr
->contentView
= view
;
464 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
466 if (sPtr
->flags
.hasHScroller
) {
469 prop
= (float)sPtr
->viewport
->size
.width
/ sPtr
->contentView
->size
.width
;
470 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
472 if (sPtr
->flags
.hasVScroller
) {
475 prop
= (float)sPtr
->viewport
->size
.height
/ sPtr
->contentView
->size
.height
;
477 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
481 void WMSetScrollViewRelief(WMScrollView
* sPtr
, WMReliefType type
)
483 sPtr
->flags
.relief
= type
;
485 reorganizeInterior(sPtr
);
487 if (sPtr
->view
->flags
.mapped
)
488 paintScrollView(sPtr
);
492 static void paintScrollView(ScrollView
* sPtr
)
494 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
495 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
, sPtr
->flags
.relief
);
498 static void updateScrollerProportion(ScrollView
* sPtr
)
503 if (sPtr
->flags
.hasHScroller
) {
504 oldV
= WMGetScrollerValue(sPtr
->hScroller
);
505 oldP
= WMGetScrollerKnobProportion(sPtr
->hScroller
);
507 prop
= (float)sPtr
->viewport
->size
.width
/ (float)sPtr
->contentView
->size
.width
;
510 value
= (prop
* oldV
) / oldP
;
513 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
515 if (sPtr
->flags
.hasVScroller
) {
516 oldV
= WMGetScrollerValue(sPtr
->vScroller
);
517 oldP
= WMGetScrollerKnobProportion(sPtr
->vScroller
);
519 prop
= (float)sPtr
->viewport
->size
.height
/ (float)sPtr
->contentView
->size
.height
;
522 value
= (prop
* oldV
) / oldP
;
525 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
527 applyScrollerValues(sPtr
);
530 static void handleViewportEvents(XEvent
* event
, void *data
)
532 ScrollView
*sPtr
= (ScrollView
*) data
;
534 if (sPtr
->contentView
&& event
->xconfigure
.window
== sPtr
->contentView
->window
)
535 updateScrollerProportion(sPtr
);
538 static void handleEvents(XEvent
* event
, void *data
)
540 ScrollView
*sPtr
= (ScrollView
*) data
;
542 CHECK_CLASS(data
, WC_ScrollView
);
544 switch (event
->type
) {
546 if (event
->xexpose
.count
!= 0)
548 if (event
->xexpose
.serial
== 0) /* means it's artificial */
549 W_RedisplayView(sPtr
->contentView
);
551 paintScrollView(sPtr
);
555 destroyScrollView(sPtr
);
561 static void destroyScrollView(ScrollView
* sPtr
)