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
WMResizeWidget(sPtr->vScroller, 20, h);
252
width -= W_VIEW(sPtr->vScroller)->size.width;
255
if (sPtr->flags.hasHScroller) {
256
WMResizeWidget(sPtr->hScroller, w, 20);
257
WMMoveWidget(sPtr->hScroller, x, h);
258
height -= W_VIEW(sPtr->hScroller)->size.height;
261
W_ResizeView(sPtr->view, w, h);
263
W_ResizeView(sPtr->viewport, width, height);
268
WMSetScrollViewLineScroll(WMScrollView *sPtr, int amount)
272
sPtr->lineScroll = amount;
277
WMSetScrollViewPageScroll(WMScrollView *sPtr, int amount)
281
sPtr->pageScroll = amount;
286
WMGetScrollViewVisibleRect(WMScrollView *sPtr)
290
rect.pos.x = -sPtr->contentView->pos.x;
291
rect.pos.y = -sPtr->contentView->pos.y;
292
rect.size = sPtr->viewport->size;
299
WMScrollViewScrollPoint(WMScrollView *sPtr, WMPoint point)
304
xsize = sPtr->contentView->size.width-sPtr->viewport->size.width;
305
ysize = sPtr->contentView->size.height-sPtr->viewport->size.height;
307
xpos = point.x / xsize;
308
ypos = point.y / ysize;
311
WMSetScrollerParameters(sPtr->hScroller, xpos,
312
WMGetScrollerKnobProportion(sPtr->hScroller));
314
WMSetScrollerParameters(sPtr->vScroller, ypos,
315
WMGetScrollerKnobProportion(sPtr->vScroller));
317
W_MoveView(sPtr->contentView, -point.x, -point.y);
322
doScrolling(WMWidget *self, void *data)
324
ScrollView *sPtr = (ScrollView*)data;
330
if (sPtr->hScroller == (WMScroller *)self) {
331
pos = -sPtr->contentView->pos.x;
332
size = sPtr->contentView->size.width-sPtr->viewport->size.width;
333
vpsize = sPtr->viewport->size.width - sPtr->pageScroll;
335
pos = -sPtr->contentView->pos.y;
336
size = sPtr->contentView->size.height-sPtr->viewport->size.height;
337
vpsize = sPtr->viewport->size.height - sPtr->pageScroll;
342
switch (WMGetScrollerHitPart(self)) {
343
case WSDecrementLine:
345
pos-=sPtr->lineScroll;
348
value = (float)pos / size;
349
WMSetScrollerParameters(self, value,
350
WMGetScrollerKnobProportion(self));
353
case WSIncrementLine:
355
pos+=sPtr->lineScroll;
358
value = (float)pos / size;
359
WMSetScrollerParameters(self, value,
360
WMGetScrollerKnobProportion(self));
365
value = WMGetScrollerValue(self);
369
case WSDecrementPage:
374
value = (float)pos / size;
375
WMSetScrollerParameters(self, value,
376
WMGetScrollerKnobProportion(self));
380
case WSDecrementWheel:
385
value = (float)pos / size;
386
WMSetScrollerParameters(self, value,
387
WMGetScrollerKnobProportion(self));
391
case WSIncrementPage:
396
value = (float)pos / size;
397
WMSetScrollerParameters(self, value,
398
WMGetScrollerKnobProportion(self));
402
case WSIncrementWheel:
407
value = (float)pos / size;
408
WMSetScrollerParameters(self, value,
409
WMGetScrollerKnobProportion(self));
418
if (sPtr->hScroller == (WMScroller *)self) {
419
W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y);
421
W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos);
427
WMGetScrollViewHorizontalScroller(WMScrollView *sPtr)
429
return sPtr->hScroller;
435
WMGetScrollViewVerticalScroller(WMScrollView *sPtr)
437
return sPtr->vScroller;
442
WMSetScrollViewHasHorizontalScroller(WMScrollView *sPtr, Bool flag)
445
if (sPtr->flags.hasHScroller)
447
sPtr->flags.hasHScroller = 1;
449
sPtr->hScroller = WMCreateScroller(sPtr);
450
WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr);
451
/* make it a horiz. scroller */
452
WMResizeWidget(sPtr->hScroller, 2, 1);
454
if (W_VIEW_REALIZED(sPtr->view)) {
455
WMRealizeWidget(sPtr->hScroller);
458
reorganizeInterior(sPtr);
460
WMMapWidget(sPtr->hScroller);
462
if (!sPtr->flags.hasHScroller)
465
WMUnmapWidget(sPtr->hScroller);
466
WMDestroyWidget(sPtr->hScroller);
467
sPtr->hScroller = NULL;
468
sPtr->flags.hasHScroller = 0;
470
reorganizeInterior(sPtr);
476
WMSetScrollViewHasVerticalScroller(WMScrollView *sPtr, Bool flag)
479
if (sPtr->flags.hasVScroller)
481
sPtr->flags.hasVScroller = 1;
483
sPtr->vScroller = WMCreateScroller(sPtr);
484
WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr);
485
WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd);
486
/* make it a vert. scroller */
487
WMResizeWidget(sPtr->vScroller, 1, 2);
489
if (W_VIEW_REALIZED(sPtr->view)) {
490
WMRealizeWidget(sPtr->vScroller);
493
reorganizeInterior(sPtr);
495
WMMapWidget(sPtr->vScroller);
497
if (!sPtr->flags.hasVScroller)
499
sPtr->flags.hasVScroller = 0;
501
WMUnmapWidget(sPtr->vScroller);
502
WMDestroyWidget(sPtr->vScroller);
503
sPtr->vScroller = NULL;
505
reorganizeInterior(sPtr);
511
WMSetScrollViewContentView(WMScrollView *sPtr, WMView *view)
513
assert(sPtr->contentView == NULL);
515
sPtr->contentView = view;
517
W_ReparentView(sPtr->contentView, sPtr->viewport, 0, 0);
519
if (sPtr->flags.hasHScroller) {
522
prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
523
WMSetScrollerParameters(sPtr->hScroller, 0, prop);
525
if (sPtr->flags.hasVScroller) {
528
prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
530
WMSetScrollerParameters(sPtr->vScroller, 0, prop);
536
WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type)
538
sPtr->flags.relief = type;
540
reorganizeInterior(sPtr);
542
if (sPtr->view->flags.mapped)
543
paintScrollView(sPtr);
551
paintScrollView(ScrollView *sPtr)
553
W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0,
554
sPtr->view->size.width, sPtr->view->size.height,
560
updateScrollerProportion(ScrollView *sPtr)
565
if (sPtr->flags.hasHScroller) {
566
oldV = WMGetScrollerValue(sPtr->hScroller);
567
oldP = WMGetScrollerKnobProportion(sPtr->hScroller);
569
prop = (float)sPtr->viewport->size.width/(float)sPtr->contentView->size.width;
574
value = (prop * oldV) / oldP;
575
WMSetScrollerParameters(sPtr->hScroller, value, prop);
577
if (sPtr->flags.hasVScroller) {
578
oldV = WMGetScrollerValue(sPtr->vScroller);
579
oldP = WMGetScrollerKnobProportion(sPtr->vScroller);
581
prop = (float)sPtr->viewport->size.height/(float)sPtr->contentView->size.height;
586
value = (prop * oldV) / oldP;
587
WMSetScrollerParameters(sPtr->vScroller, value, prop);
589
applyScrollerValues(sPtr);
594
handleViewportEvents(XEvent *event, void *data)
596
ScrollView *sPtr = (ScrollView*)data;
598
if (sPtr->contentView
599
&& event->xconfigure.window == sPtr->contentView->window)
600
updateScrollerProportion(sPtr);
605
handleEvents(XEvent *event, void *data)
607
ScrollView *sPtr = (ScrollView*)data;
609
CHECK_CLASS(data, WC_ScrollView);
611
switch (event->type) {
613
if (event->xexpose.count!=0)
615
if (event->xexpose.serial == 0) /* means it's artificial */
616
W_RedisplayView(sPtr->contentView);
618
paintScrollView(sPtr);
622
destroyScrollView(sPtr);
630
destroyScrollView(ScrollView *sPtr)