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();
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
);
68 W_DestroyView(sPtr
->view
);
72 sPtr
->view
->self
= sPtr
;
74 sPtr
->view
->delegate
= &_ScrollViewViewDelegate
;
76 W_SetViewBackgroundColor(sPtr
->viewport
,
77 WMBlackColor(WMWidgetScreen(parent
)));
78 sPtr
->viewport
->flags
.mapWhenRealized
= 1;
80 WMCreateEventHandler(sPtr
->view
, StructureNotifyMask
|ExposureMask
,
82 WMCreateEventHandler(sPtr
->viewport
, SubstructureNotifyMask
,
83 handleViewportEvents
, sPtr
);
95 reorganizeInterior(WMScrollView
*sPtr
)
102 cw
= hw
= sPtr
->view
->size
.width
;
103 vh
= ch
= sPtr
->view
->size
.height
;
105 if (sPtr
->flags
.relief
== WRSimple
) {
110 } else if (sPtr
->flags
.relief
!= WRFlat
) {
120 if (sPtr
->flags
.hasHScroller
) {
121 int h
= W_VIEW(sPtr
->hScroller
)->size
.height
;
125 if (sPtr
->flags
.relief
== WRSimple
) {
127 hy
= sPtr
->view
->size
.height
- h
;
128 } else if (sPtr
->flags
.relief
!= WRFlat
) {
130 hy
= sPtr
->view
->size
.height
- h
- 1;
134 hy
= sPtr
->view
->size
.height
- h
;
137 /* make compiler shutup */
142 if (sPtr
->flags
.hasVScroller
) {
143 int w
= W_VIEW(sPtr
->vScroller
)->size
.width
;
149 if (sPtr
->flags
.relief
== WRSimple
) {
152 } else if (sPtr
->flags
.relief
!= WRFlat
) {
161 /* make compiler shutup */
166 W_ResizeView(sPtr
->viewport
, cw
, ch
);
167 W_MoveView(sPtr
->viewport
, cx
, cy
);
169 if (sPtr
->flags
.hasHScroller
) {
170 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
171 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
173 if (sPtr
->flags
.hasVScroller
) {
174 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
175 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
181 resizeScrollView(W_ViewDelegate
*self
, WMView
*view
)
183 reorganizeInterior(view
->self
);
189 WMResizeScrollViewContent(WMScrollView
*sPtr
, unsigned int width
,
198 if (sPtr
->flags
.relief
== WRSimple
) {
201 } else if (sPtr
->flags
.relief
!= WRFlat
) {
207 if (sPtr
->flags
.hasVScroller
) {
208 w
-= W_VIEW(sPtr
->hScroller
)->size
.width
;
209 WMResizeWidget(sPtr
->vScroller
, 20, h
);
211 if (sPtr
->flags
.hasHScroller
) {
212 h
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
213 WMResizeWidget(sPtr
->hScroller
, w
, 20);
214 WMMoveWidget(sPtr
->hScroller
, x
, h
);
217 W_ResizeView(sPtr
->view
, w
, h
);
219 W_ResizeView(sPtr
->viewport
, width
, height
);
224 WMSetScrollViewLineScroll(WMScrollView
*sPtr
, int amount
)
228 sPtr
->lineScroll
= amount
;
233 WMSetScrollViewPageScroll(WMScrollView
*sPtr
, int amount
)
237 sPtr
->pageScroll
= amount
;
242 WMGetScrollViewVisibleRect(WMScrollView
*sPtr
)
246 rect
.pos
= sPtr
->contentView
->pos
;
247 rect
.size
= sPtr
->viewport
->size
;
253 doScrolling(WMWidget
*self
, void *data
)
255 ScrollView
*sPtr
= (ScrollView
*)data
;
261 if (sPtr
->hScroller
== (WMScroller
*)self
) {
262 pos
= -sPtr
->contentView
->pos
.x
;
263 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
264 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
266 pos
= -sPtr
->contentView
->pos
.y
;
267 size
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
268 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
273 switch (WMGetScrollerHitPart(self
)) {
274 case WSDecrementLine
:
276 pos
-=sPtr
->lineScroll
;
279 value
= (float)pos
/ size
;
280 WMSetScrollerParameters(self
, value
,
281 WMGetScrollerKnobProportion(self
));
284 case WSIncrementLine
:
286 pos
+=sPtr
->lineScroll
;
289 value
= (float)pos
/ size
;
290 WMSetScrollerParameters(self
, value
,
291 WMGetScrollerKnobProportion(self
));
296 value
= WMGetScrollerValue(self
);
300 case WSDecrementPage
:
305 value
= (float)pos
/ size
;
306 WMSetScrollerParameters(self
, value
,
307 WMGetScrollerKnobProportion(self
));
311 case WSDecrementWheel
:
316 value
= (float)pos
/ size
;
317 WMSetScrollerParameters(self
, value
,
318 WMGetScrollerKnobProportion(self
));
322 case WSIncrementPage
:
327 value
= (float)pos
/ size
;
328 WMSetScrollerParameters(self
, value
,
329 WMGetScrollerKnobProportion(self
));
333 case WSIncrementWheel
:
338 value
= (float)pos
/ size
;
339 WMSetScrollerParameters(self
, value
,
340 WMGetScrollerKnobProportion(self
));
349 if (sPtr
->hScroller
== (WMScroller
*)self
) {
350 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
352 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
358 WMGetScrollViewHorizontalScroller(WMScrollView
*sPtr
)
360 return sPtr
->hScroller
;
366 WMGetScrollViewVerticalScroller(WMScrollView
*sPtr
)
368 return sPtr
->vScroller
;
373 WMSetScrollViewHasHorizontalScroller(WMScrollView
*sPtr
, Bool flag
)
376 if (sPtr
->flags
.hasHScroller
)
378 sPtr
->flags
.hasHScroller
= 1;
380 sPtr
->hScroller
= WMCreateScroller(sPtr
);
381 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
382 /* make it a horiz. scroller */
383 WMResizeWidget(sPtr
->hScroller
, 2, 1);
385 reorganizeInterior(sPtr
);
387 WMMapWidget(sPtr
->hScroller
);
389 if (!sPtr
->flags
.hasHScroller
)
392 WMUnmapWidget(sPtr
->hScroller
);
393 WMDestroyWidget(sPtr
->hScroller
);
394 sPtr
->hScroller
= NULL
;
395 sPtr
->flags
.hasHScroller
= 0;
397 reorganizeInterior(sPtr
);
403 WMSetScrollViewHasVerticalScroller(WMScrollView
*sPtr
, Bool flag
)
406 if (sPtr
->flags
.hasVScroller
)
408 sPtr
->flags
.hasVScroller
= 1;
410 sPtr
->vScroller
= WMCreateScroller(sPtr
);
411 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
412 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
413 /* make it a vert. scroller */
414 WMResizeWidget(sPtr
->vScroller
, 1, 2);
416 reorganizeInterior(sPtr
);
418 WMMapWidget(sPtr
->vScroller
);
420 if (!sPtr
->flags
.hasVScroller
)
422 sPtr
->flags
.hasVScroller
= 0;
424 WMUnmapWidget(sPtr
->vScroller
);
425 WMDestroyWidget(sPtr
->vScroller
);
426 sPtr
->vScroller
= NULL
;
428 reorganizeInterior(sPtr
);
434 WMSetScrollViewContentView(WMScrollView
*sPtr
, WMView
*view
)
436 assert(sPtr
->contentView
== NULL
);
438 sPtr
->contentView
= view
;
440 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
442 if (sPtr
->flags
.hasHScroller
) {
445 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
446 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
448 if (sPtr
->flags
.hasVScroller
) {
451 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
453 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
459 WMSetScrollViewRelief(WMScrollView
*sPtr
, WMReliefType type
)
461 sPtr
->flags
.relief
= type
;
463 reorganizeInterior(sPtr
);
465 if (sPtr
->view
->flags
.mapped
)
466 paintScrollView(sPtr
);
473 paintScrollView(ScrollView
*sPtr
)
475 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
476 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
,
482 updateScrollerProportion(ScrollView
*sPtr
)
486 if (sPtr
->flags
.hasHScroller
) {
487 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
488 value
= WMGetScrollerValue(sPtr
->hScroller
);
490 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
492 if (sPtr
->flags
.hasVScroller
) {
493 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
495 value
= WMGetScrollerValue(sPtr
->vScroller
);
497 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
503 handleViewportEvents(XEvent
*event
, void *data
)
505 ScrollView
*sPtr
= (ScrollView
*)data
;
507 if (sPtr
->contentView
508 && event
->xconfigure
.window
== sPtr
->contentView
->window
)
509 updateScrollerProportion(sPtr
);
514 handleEvents(XEvent
*event
, void *data
)
516 ScrollView
*sPtr
= (ScrollView
*)data
;
518 CHECK_CLASS(data
, WC_ScrollView
);
520 switch (event
->type
) {
522 if (event
->xexpose
.count
!=0)
524 paintScrollView(sPtr
);
528 destroyScrollView(sPtr
);
536 destroyScrollView(ScrollView
*sPtr
)
538 puts("destroyScrollView not implemented");