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();
32 static void updateScrollerProportion();
34 W_ViewDelegate _ScrollViewViewDelegate
= {
42 WMScrollView
*WMCreateScrollView(WMWidget
* parent
)
46 sPtr
= wmalloc(sizeof(ScrollView
));
47 memset(sPtr
, 0, sizeof(ScrollView
));
49 sPtr
->widgetClass
= WC_ScrollView
;
51 sPtr
->view
= W_CreateView(W_VIEW(parent
));
56 sPtr
->viewport
= W_CreateView(sPtr
->view
);
57 if (!sPtr
->viewport
) {
58 W_DestroyView(sPtr
->view
);
62 sPtr
->view
->self
= sPtr
;
63 sPtr
->viewport
->self
= sPtr
;
65 sPtr
->view
->delegate
= &_ScrollViewViewDelegate
;
67 sPtr
->viewport
->flags
.mapWhenRealized
= 1;
69 WMCreateEventHandler(sPtr
->view
, StructureNotifyMask
| ExposureMask
, handleEvents
, sPtr
);
70 WMCreateEventHandler(sPtr
->viewport
, SubstructureNotifyMask
, handleViewportEvents
, sPtr
);
79 static void applyScrollerValues(WMScrollView
* sPtr
)
83 if (sPtr
->contentView
== NULL
)
86 if (sPtr
->flags
.hasHScroller
) {
87 float v
= WMGetScrollerValue(sPtr
->hScroller
);
90 size
= sPtr
->contentView
->size
.width
- sPtr
->viewport
->size
.width
;
97 if (sPtr
->flags
.hasVScroller
) {
98 float v
= WMGetScrollerValue(sPtr
->vScroller
);
102 size
= sPtr
->contentView
->size
.height
- sPtr
->viewport
->size
.height
;
112 W_MoveView(sPtr
->contentView
, -x
, -y
);
114 W_RaiseView(sPtr
->viewport
);
117 static void reorganizeInterior(WMScrollView
* sPtr
)
123 cw
= hw
= sPtr
->view
->size
.width
;
124 vh
= ch
= sPtr
->view
->size
.height
;
126 if (sPtr
->flags
.relief
== WRSimple
) {
131 } else if (sPtr
->flags
.relief
!= WRFlat
) {
141 if (sPtr
->flags
.hasHScroller
) {
146 if (sPtr
->flags
.relief
== WRSimple
) {
148 hy
= sPtr
->view
->size
.height
- h
;
149 } else if (sPtr
->flags
.relief
!= WRFlat
) {
151 hy
= sPtr
->view
->size
.height
- h
- 1;
155 hy
= sPtr
->view
->size
.height
- h
;
158 /* make compiler shutup */
163 if (sPtr
->flags
.hasVScroller
) {
170 if (sPtr
->flags
.relief
== WRSimple
) {
173 } else if (sPtr
->flags
.relief
!= WRFlat
) {
182 /* make compiler shutup */
187 W_ResizeView(sPtr
->viewport
, cw
, ch
);
188 W_MoveView(sPtr
->viewport
, cx
, cy
);
190 if (sPtr
->flags
.hasHScroller
) {
191 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
192 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
194 if (sPtr
->flags
.hasVScroller
) {
195 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
196 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
199 applyScrollerValues(sPtr
);
202 static void resizeScrollView(W_ViewDelegate
* self
, WMView
* view
)
204 reorganizeInterior(view
->self
);
205 updateScrollerProportion(view
->self
);
208 void WMResizeScrollViewContent(WMScrollView
* sPtr
, unsigned int width
, unsigned int height
)
216 if (sPtr
->flags
.relief
== WRSimple
) {
219 } else if (sPtr
->flags
.relief
!= WRFlat
) {
225 if (sPtr
->flags
.hasVScroller
) {
226 WMResizeWidget(sPtr
->vScroller
, 20, h
);
227 width
-= W_VIEW(sPtr
->vScroller
)->size
.width
;
230 if (sPtr
->flags
.hasHScroller
) {
231 WMResizeWidget(sPtr
->hScroller
, w
, 20);
232 WMMoveWidget(sPtr
->hScroller
, x
, h
);
233 height
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
236 W_ResizeView(sPtr
->view
, w
, h
);
238 W_ResizeView(sPtr
->viewport
, width
, height
);
241 void WMSetScrollViewLineScroll(WMScrollView
* sPtr
, int amount
)
245 sPtr
->lineScroll
= amount
;
248 void WMSetScrollViewPageScroll(WMScrollView
* sPtr
, int amount
)
252 sPtr
->pageScroll
= amount
;
255 WMRect
WMGetScrollViewVisibleRect(WMScrollView
* sPtr
)
259 rect
.pos
.x
= -sPtr
->contentView
->pos
.x
;
260 rect
.pos
.y
= -sPtr
->contentView
->pos
.y
;
261 rect
.size
= sPtr
->viewport
->size
;
266 void WMScrollViewScrollPoint(WMScrollView
* sPtr
, WMPoint point
)
271 xsize
= sPtr
->contentView
->size
.width
- sPtr
->viewport
->size
.width
;
272 ysize
= sPtr
->contentView
->size
.height
- sPtr
->viewport
->size
.height
;
274 xpos
= point
.x
/ xsize
;
275 ypos
= point
.y
/ ysize
;
278 WMSetScrollerParameters(sPtr
->hScroller
, xpos
, WMGetScrollerKnobProportion(sPtr
->hScroller
));
280 WMSetScrollerParameters(sPtr
->vScroller
, ypos
, WMGetScrollerKnobProportion(sPtr
->vScroller
));
282 W_MoveView(sPtr
->contentView
, -point
.x
, -point
.y
);
285 static void doScrolling(WMWidget
* self
, void *data
)
287 ScrollView
*sPtr
= (ScrollView
*) data
;
293 if (sPtr
->hScroller
== (WMScroller
*) self
) {
294 pos
= -sPtr
->contentView
->pos
.x
;
295 size
= sPtr
->contentView
->size
.width
- sPtr
->viewport
->size
.width
;
296 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
298 pos
= -sPtr
->contentView
->pos
.y
;
299 size
= sPtr
->contentView
->size
.height
- sPtr
->viewport
->size
.height
;
300 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
305 switch (WMGetScrollerHitPart(self
)) {
306 case WSDecrementLine
:
308 pos
-= sPtr
->lineScroll
;
311 value
= (float)pos
/ size
;
312 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
315 case WSIncrementLine
:
317 pos
+= sPtr
->lineScroll
;
320 value
= (float)pos
/ size
;
321 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
326 value
= WMGetScrollerValue(self
);
330 case WSDecrementPage
:
335 value
= (float)pos
/ size
;
336 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
340 case WSDecrementWheel
:
345 value
= (float)pos
/ size
;
346 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
350 case WSIncrementPage
:
355 value
= (float)pos
/ size
;
356 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
360 case WSIncrementWheel
:
365 value
= (float)pos
/ size
;
366 WMSetScrollerParameters(self
, value
, WMGetScrollerKnobProportion(self
));
375 if (sPtr
->hScroller
== (WMScroller
*) self
) {
376 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
378 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
382 WMScroller
*WMGetScrollViewHorizontalScroller(WMScrollView
* sPtr
)
384 return sPtr
->hScroller
;
387 WMScroller
*WMGetScrollViewVerticalScroller(WMScrollView
* sPtr
)
389 return sPtr
->vScroller
;
392 void WMSetScrollViewHasHorizontalScroller(WMScrollView
* sPtr
, Bool flag
)
395 if (sPtr
->flags
.hasHScroller
)
397 sPtr
->flags
.hasHScroller
= 1;
399 sPtr
->hScroller
= WMCreateScroller(sPtr
);
400 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
401 /* make it a horiz. scroller */
402 WMResizeWidget(sPtr
->hScroller
, 2, 1);
404 if (W_VIEW_REALIZED(sPtr
->view
)) {
405 WMRealizeWidget(sPtr
->hScroller
);
408 reorganizeInterior(sPtr
);
410 WMMapWidget(sPtr
->hScroller
);
412 if (!sPtr
->flags
.hasHScroller
)
415 WMUnmapWidget(sPtr
->hScroller
);
416 WMDestroyWidget(sPtr
->hScroller
);
417 sPtr
->hScroller
= NULL
;
418 sPtr
->flags
.hasHScroller
= 0;
420 reorganizeInterior(sPtr
);
424 void WMSetScrollViewHasVerticalScroller(WMScrollView
* sPtr
, Bool flag
)
427 if (sPtr
->flags
.hasVScroller
)
429 sPtr
->flags
.hasVScroller
= 1;
431 sPtr
->vScroller
= WMCreateScroller(sPtr
);
432 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
433 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
434 /* make it a vert. scroller */
435 WMResizeWidget(sPtr
->vScroller
, 1, 2);
437 if (W_VIEW_REALIZED(sPtr
->view
)) {
438 WMRealizeWidget(sPtr
->vScroller
);
441 reorganizeInterior(sPtr
);
443 WMMapWidget(sPtr
->vScroller
);
445 if (!sPtr
->flags
.hasVScroller
)
447 sPtr
->flags
.hasVScroller
= 0;
449 WMUnmapWidget(sPtr
->vScroller
);
450 WMDestroyWidget(sPtr
->vScroller
);
451 sPtr
->vScroller
= NULL
;
453 reorganizeInterior(sPtr
);
457 void WMSetScrollViewContentView(WMScrollView
* sPtr
, WMView
* view
)
459 assert(sPtr
->contentView
== NULL
);
461 sPtr
->contentView
= view
;
463 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
465 if (sPtr
->flags
.hasHScroller
) {
468 prop
= (float)sPtr
->viewport
->size
.width
/ sPtr
->contentView
->size
.width
;
469 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
471 if (sPtr
->flags
.hasVScroller
) {
474 prop
= (float)sPtr
->viewport
->size
.height
/ sPtr
->contentView
->size
.height
;
476 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
480 void WMSetScrollViewRelief(WMScrollView
* sPtr
, WMReliefType type
)
482 sPtr
->flags
.relief
= type
;
484 reorganizeInterior(sPtr
);
486 if (sPtr
->view
->flags
.mapped
)
487 paintScrollView(sPtr
);
491 static void paintScrollView(ScrollView
* sPtr
)
493 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
494 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
, sPtr
->flags
.relief
);
497 static void updateScrollerProportion(ScrollView
* sPtr
)
502 if (sPtr
->flags
.hasHScroller
) {
503 oldV
= WMGetScrollerValue(sPtr
->hScroller
);
504 oldP
= WMGetScrollerKnobProportion(sPtr
->hScroller
);
506 prop
= (float)sPtr
->viewport
->size
.width
/ (float)sPtr
->contentView
->size
.width
;
511 value
= (prop
* oldV
) / oldP
;
512 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
514 if (sPtr
->flags
.hasVScroller
) {
515 oldV
= WMGetScrollerValue(sPtr
->vScroller
);
516 oldP
= WMGetScrollerKnobProportion(sPtr
->vScroller
);
518 prop
= (float)sPtr
->viewport
->size
.height
/ (float)sPtr
->contentView
->size
.height
;
523 value
= (prop
* oldV
) / oldP
;
524 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
526 applyScrollerValues(sPtr
);
529 static void handleViewportEvents(XEvent
* event
, void *data
)
531 ScrollView
*sPtr
= (ScrollView
*) data
;
533 if (sPtr
->contentView
&& event
->xconfigure
.window
== sPtr
->contentView
->window
)
534 updateScrollerProportion(sPtr
);
537 static void handleEvents(XEvent
* event
, void *data
)
539 ScrollView
*sPtr
= (ScrollView
*) data
;
541 CHECK_CLASS(data
, WC_ScrollView
);
543 switch (event
->type
) {
545 if (event
->xexpose
.count
!= 0)
547 if (event
->xexpose
.serial
== 0) /* means it's artificial */
548 W_RedisplayView(sPtr
->contentView
);
550 paintScrollView(sPtr
);
554 destroyScrollView(sPtr
);
560 static void destroyScrollView(ScrollView
* sPtr
)