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 /* This has a very bad effect when the scrollview is mapped, making it
77 * flicker with each item added to it. It also seems to draw slower.
78 * Why should it be black anyway? -Dan
80 /*W_SetViewBackgroundColor(sPtr->viewport,
81 WMBlackColor(WMWidgetScreen(parent)));*/
82 sPtr
->viewport
->flags
.mapWhenRealized
= 1;
84 WMCreateEventHandler(sPtr
->view
, StructureNotifyMask
|ExposureMask
,
86 WMCreateEventHandler(sPtr
->viewport
, SubstructureNotifyMask
,
87 handleViewportEvents
, sPtr
);
99 reorganizeInterior(WMScrollView
*sPtr
)
106 cw
= hw
= sPtr
->view
->size
.width
;
107 vh
= ch
= sPtr
->view
->size
.height
;
109 if (sPtr
->flags
.relief
== WRSimple
) {
114 } else if (sPtr
->flags
.relief
!= WRFlat
) {
124 if (sPtr
->flags
.hasHScroller
) {
125 int h
= W_VIEW(sPtr
->hScroller
)->size
.height
;
129 if (sPtr
->flags
.relief
== WRSimple
) {
131 hy
= sPtr
->view
->size
.height
- h
;
132 } else if (sPtr
->flags
.relief
!= WRFlat
) {
134 hy
= sPtr
->view
->size
.height
- h
- 1;
138 hy
= sPtr
->view
->size
.height
- h
;
141 /* make compiler shutup */
146 if (sPtr
->flags
.hasVScroller
) {
147 int w
= W_VIEW(sPtr
->vScroller
)->size
.width
;
153 if (sPtr
->flags
.relief
== WRSimple
) {
156 } else if (sPtr
->flags
.relief
!= WRFlat
) {
165 /* make compiler shutup */
170 W_ResizeView(sPtr
->viewport
, cw
, ch
);
171 W_MoveView(sPtr
->viewport
, cx
, cy
);
173 if (sPtr
->flags
.hasHScroller
) {
174 WMResizeWidget(sPtr
->hScroller
, hw
, 20);
175 WMMoveWidget(sPtr
->hScroller
, hx
, hy
);
177 if (sPtr
->flags
.hasVScroller
) {
178 WMResizeWidget(sPtr
->vScroller
, 20, vh
);
179 WMMoveWidget(sPtr
->vScroller
, vx
, vy
);
185 resizeScrollView(W_ViewDelegate
*self
, WMView
*view
)
187 reorganizeInterior(view
->self
);
193 WMResizeScrollViewContent(WMScrollView
*sPtr
, unsigned int width
,
202 if (sPtr
->flags
.relief
== WRSimple
) {
205 } else if (sPtr
->flags
.relief
!= WRFlat
) {
211 if (sPtr
->flags
.hasVScroller
) {
212 w
-= W_VIEW(sPtr
->hScroller
)->size
.width
;
213 WMResizeWidget(sPtr
->vScroller
, 20, h
);
215 if (sPtr
->flags
.hasHScroller
) {
216 h
-= W_VIEW(sPtr
->hScroller
)->size
.height
;
217 WMResizeWidget(sPtr
->hScroller
, w
, 20);
218 WMMoveWidget(sPtr
->hScroller
, x
, h
);
221 W_ResizeView(sPtr
->view
, w
, h
);
223 W_ResizeView(sPtr
->viewport
, width
, height
);
228 WMSetScrollViewLineScroll(WMScrollView
*sPtr
, int amount
)
232 sPtr
->lineScroll
= amount
;
237 WMSetScrollViewPageScroll(WMScrollView
*sPtr
, int amount
)
241 sPtr
->pageScroll
= amount
;
246 WMGetScrollViewVisibleRect(WMScrollView
*sPtr
)
250 rect
.pos
= sPtr
->contentView
->pos
;
251 rect
.size
= sPtr
->viewport
->size
;
257 doScrolling(WMWidget
*self
, void *data
)
259 ScrollView
*sPtr
= (ScrollView
*)data
;
265 if (sPtr
->hScroller
== (WMScroller
*)self
) {
266 pos
= -sPtr
->contentView
->pos
.x
;
267 size
= sPtr
->contentView
->size
.width
-sPtr
->viewport
->size
.width
;
268 vpsize
= sPtr
->viewport
->size
.width
- sPtr
->pageScroll
;
270 pos
= -sPtr
->contentView
->pos
.y
;
271 size
= sPtr
->contentView
->size
.height
-sPtr
->viewport
->size
.height
;
272 vpsize
= sPtr
->viewport
->size
.height
- sPtr
->pageScroll
;
277 switch (WMGetScrollerHitPart(self
)) {
278 case WSDecrementLine
:
280 pos
-=sPtr
->lineScroll
;
283 value
= (float)pos
/ size
;
284 WMSetScrollerParameters(self
, value
,
285 WMGetScrollerKnobProportion(self
));
288 case WSIncrementLine
:
290 pos
+=sPtr
->lineScroll
;
293 value
= (float)pos
/ size
;
294 WMSetScrollerParameters(self
, value
,
295 WMGetScrollerKnobProportion(self
));
300 value
= WMGetScrollerValue(self
);
304 case WSDecrementPage
:
309 value
= (float)pos
/ size
;
310 WMSetScrollerParameters(self
, value
,
311 WMGetScrollerKnobProportion(self
));
315 case WSDecrementWheel
:
320 value
= (float)pos
/ size
;
321 WMSetScrollerParameters(self
, value
,
322 WMGetScrollerKnobProportion(self
));
326 case WSIncrementPage
:
331 value
= (float)pos
/ size
;
332 WMSetScrollerParameters(self
, value
,
333 WMGetScrollerKnobProportion(self
));
337 case WSIncrementWheel
:
342 value
= (float)pos
/ size
;
343 WMSetScrollerParameters(self
, value
,
344 WMGetScrollerKnobProportion(self
));
353 if (sPtr
->hScroller
== (WMScroller
*)self
) {
354 W_MoveView(sPtr
->contentView
, -pos
, sPtr
->contentView
->pos
.y
);
356 W_MoveView(sPtr
->contentView
, sPtr
->contentView
->pos
.x
, -pos
);
362 WMGetScrollViewHorizontalScroller(WMScrollView
*sPtr
)
364 return sPtr
->hScroller
;
370 WMGetScrollViewVerticalScroller(WMScrollView
*sPtr
)
372 return sPtr
->vScroller
;
377 WMSetScrollViewHasHorizontalScroller(WMScrollView
*sPtr
, Bool flag
)
380 if (sPtr
->flags
.hasHScroller
)
382 sPtr
->flags
.hasHScroller
= 1;
384 sPtr
->hScroller
= WMCreateScroller(sPtr
);
385 WMSetScrollerAction(sPtr
->hScroller
, doScrolling
, sPtr
);
386 /* make it a horiz. scroller */
387 WMResizeWidget(sPtr
->hScroller
, 2, 1);
389 reorganizeInterior(sPtr
);
391 WMMapWidget(sPtr
->hScroller
);
393 if (!sPtr
->flags
.hasHScroller
)
396 WMUnmapWidget(sPtr
->hScroller
);
397 WMDestroyWidget(sPtr
->hScroller
);
398 sPtr
->hScroller
= NULL
;
399 sPtr
->flags
.hasHScroller
= 0;
401 reorganizeInterior(sPtr
);
407 WMSetScrollViewHasVerticalScroller(WMScrollView
*sPtr
, Bool flag
)
410 if (sPtr
->flags
.hasVScroller
)
412 sPtr
->flags
.hasVScroller
= 1;
414 sPtr
->vScroller
= WMCreateScroller(sPtr
);
415 WMSetScrollerAction(sPtr
->vScroller
, doScrolling
, sPtr
);
416 WMSetScrollerArrowsPosition(sPtr
->vScroller
, WSAMaxEnd
);
417 /* make it a vert. scroller */
418 WMResizeWidget(sPtr
->vScroller
, 1, 2);
420 reorganizeInterior(sPtr
);
422 WMMapWidget(sPtr
->vScroller
);
424 if (!sPtr
->flags
.hasVScroller
)
426 sPtr
->flags
.hasVScroller
= 0;
428 WMUnmapWidget(sPtr
->vScroller
);
429 WMDestroyWidget(sPtr
->vScroller
);
430 sPtr
->vScroller
= NULL
;
432 reorganizeInterior(sPtr
);
438 WMSetScrollViewContentView(WMScrollView
*sPtr
, WMView
*view
)
440 assert(sPtr
->contentView
== NULL
);
442 sPtr
->contentView
= view
;
444 W_ReparentView(sPtr
->contentView
, sPtr
->viewport
, 0, 0);
446 if (sPtr
->flags
.hasHScroller
) {
449 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
450 WMSetScrollerParameters(sPtr
->hScroller
, 0, prop
);
452 if (sPtr
->flags
.hasVScroller
) {
455 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
457 WMSetScrollerParameters(sPtr
->vScroller
, 0, prop
);
463 WMSetScrollViewRelief(WMScrollView
*sPtr
, WMReliefType type
)
465 sPtr
->flags
.relief
= type
;
467 reorganizeInterior(sPtr
);
469 if (sPtr
->view
->flags
.mapped
)
470 paintScrollView(sPtr
);
477 paintScrollView(ScrollView
*sPtr
)
479 W_DrawRelief(sPtr
->view
->screen
, sPtr
->view
->window
, 0, 0,
480 sPtr
->view
->size
.width
, sPtr
->view
->size
.height
,
486 updateScrollerProportion(ScrollView
*sPtr
)
490 if (sPtr
->flags
.hasHScroller
) {
491 prop
= (float)sPtr
->viewport
->size
.width
/sPtr
->contentView
->size
.width
;
492 value
= WMGetScrollerValue(sPtr
->hScroller
);
494 WMSetScrollerParameters(sPtr
->hScroller
, value
, prop
);
496 if (sPtr
->flags
.hasVScroller
) {
497 prop
= (float)sPtr
->viewport
->size
.height
/sPtr
->contentView
->size
.height
;
499 value
= WMGetScrollerValue(sPtr
->vScroller
);
501 WMSetScrollerParameters(sPtr
->vScroller
, value
, prop
);
507 handleViewportEvents(XEvent
*event
, void *data
)
509 ScrollView
*sPtr
= (ScrollView
*)data
;
511 if (sPtr
->contentView
512 && event
->xconfigure
.window
== sPtr
->contentView
->window
)
513 updateScrollerProportion(sPtr
);
518 handleEvents(XEvent
*event
, void *data
)
520 ScrollView
*sPtr
= (ScrollView
*)data
;
522 CHECK_CLASS(data
, WC_ScrollView
);
524 switch (event
->type
) {
526 if (event
->xexpose
.count
!=0)
528 paintScrollView(sPtr
);
532 destroyScrollView(sPtr
);
540 destroyScrollView(ScrollView
*sPtr
)
542 puts("destroyScrollView not implemented");