various table widget updates
[wmaker-crm.git] / WINGs / wscrollview.c
blob5e47e91d0e99cdda3db768157f6ceced72872021
5 #include "WINGsP.h"
8 typedef struct W_ScrollView {
9 W_Class widgetClass;
10 WMView *view;
12 WMView *contentView;
13 WMView *viewport;
15 WMScroller *vScroller;
16 WMScroller *hScroller;
18 short lineScroll;
19 short pageScroll;
21 struct {
22 WMReliefType relief:3;
23 unsigned int hasVScroller:1;
24 unsigned int hasHScroller:1;
26 } flags;
28 } ScrollView;
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 = {
42 NULL,
43 NULL,
44 resizeScrollView,
45 NULL,
46 NULL
51 WMScrollView*
52 WMCreateScrollView(WMWidget *parent)
54 ScrollView *sPtr;
56 sPtr = wmalloc(sizeof(ScrollView));
57 memset(sPtr, 0, sizeof(ScrollView));
59 sPtr->widgetClass = WC_ScrollView;
61 sPtr->view = W_CreateView(W_VIEW(parent));
62 if (!sPtr->view) {
63 wfree(sPtr);
64 return NULL;
66 sPtr->viewport = W_CreateView(sPtr->view);
67 if (!sPtr->viewport) {
68 W_DestroyView(sPtr->view);
69 wfree(sPtr);
70 return NULL;
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,
80 handleEvents, sPtr);
81 WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask,
82 handleViewportEvents, sPtr);
84 sPtr->lineScroll = 4;
86 sPtr->pageScroll = 0;
88 return sPtr;
92 static void
93 applyScrollerValues(WMScrollView *sPtr)
95 int x, y;
97 if (sPtr->contentView == NULL)
98 return;
100 if (sPtr->flags.hasHScroller) {
101 float v = WMGetScrollerValue(sPtr->hScroller);
102 int size;
104 size = sPtr->contentView->size.width-sPtr->viewport->size.width;
106 x = v * size;
107 } else {
108 x = 0;
111 if (sPtr->flags.hasVScroller) {
112 float v = WMGetScrollerValue(sPtr->vScroller);
114 int size;
116 size = sPtr->contentView->size.width-sPtr->viewport->size.width;
118 y = v * size;
119 } else {
120 y = 0;
123 x = WMAX(0, x);
124 y = WMAX(0, y);
126 W_MoveView(sPtr->contentView, -x, -y);
128 W_RaiseView(sPtr->viewport);
132 static void
133 reorganizeInterior(WMScrollView *sPtr)
135 int hx, hy, hw;
136 int vx, vy, vh;
137 int cx, cy, cw, ch;
140 cw = hw = sPtr->view->size.width;
141 vh = ch = sPtr->view->size.height;
143 if (sPtr->flags.relief == WRSimple) {
144 cw -= 2;
145 ch -= 2;
146 cx = 1;
147 cy = 1;
148 } else if (sPtr->flags.relief != WRFlat) {
149 cw -= 3;
150 ch -= 3;
151 cx = 2;
152 cy = 2;
153 } else {
154 cx = 0;
155 cy = 0;
158 if (sPtr->flags.hasHScroller) {
159 int h = 20;
161 ch -= h;
163 if (sPtr->flags.relief == WRSimple) {
164 hx = 0;
165 hy = sPtr->view->size.height - h;
166 } else if (sPtr->flags.relief != WRFlat) {
167 hx = 1;
168 hy = sPtr->view->size.height - h - 1;
169 hw -= 2;
170 } else {
171 hx = 0;
172 hy = sPtr->view->size.height - h;
174 } else {
175 /* make compiler shutup */
176 hx = 0;
177 hy = 0;
180 if (sPtr->flags.hasVScroller) {
181 int w = 20;
182 cw -= w;
183 cx += w;
184 hx += w - 1;
185 hw -= w - 1;
187 if (sPtr->flags.relief == WRSimple) {
188 vx = 0;
189 vy = 0;
190 } else if (sPtr->flags.relief != WRFlat) {
191 vx = 1;
192 vy = 1;
193 vh -= 2;
194 } else {
195 vx = 0;
196 vy = 0;
198 } else {
199 /* make compiler shutup */
200 vx = 0;
201 vy = 0;
204 W_ResizeView(sPtr->viewport, cw, ch);
205 W_MoveView(sPtr->viewport, cx, cy);
207 if (sPtr->flags.hasHScroller) {
208 WMResizeWidget(sPtr->hScroller, hw, 20);
209 WMMoveWidget(sPtr->hScroller, hx, hy);
211 if (sPtr->flags.hasVScroller) {
212 WMResizeWidget(sPtr->vScroller, 20, vh);
213 WMMoveWidget(sPtr->vScroller, vx, vy);
216 applyScrollerValues(sPtr);
220 static void
221 resizeScrollView(W_ViewDelegate *self, WMView *view)
223 reorganizeInterior(view->self);
224 updateScrollerProportion(view->self);
229 void
230 WMResizeScrollViewContent(WMScrollView *sPtr, unsigned int width,
231 unsigned int height)
233 int w, h, x;
235 w = width;
236 h = height;
238 x = 0;
239 if (sPtr->flags.relief == WRSimple) {
240 w += 2;
241 h += 2;
242 } else if (sPtr->flags.relief != WRFlat) {
243 w += 4;
244 h += 4;
245 x = 1;
248 if (sPtr->flags.hasVScroller) {
249 width -= W_VIEW(sPtr->hScroller)->size.width;
250 WMResizeWidget(sPtr->vScroller, 20, h);
252 if (sPtr->flags.hasHScroller) {
253 height -= W_VIEW(sPtr->hScroller)->size.height;
254 WMResizeWidget(sPtr->hScroller, w, 20);
255 WMMoveWidget(sPtr->hScroller, x, h);
258 W_ResizeView(sPtr->view, w, h);
260 W_ResizeView(sPtr->viewport, width, height);
264 void
265 WMSetScrollViewLineScroll(WMScrollView *sPtr, int amount)
267 assert(amount > 0);
269 sPtr->lineScroll = amount;
273 void
274 WMSetScrollViewPageScroll(WMScrollView *sPtr, int amount)
276 assert(amount >= 0);
278 sPtr->pageScroll = amount;
282 WMRect
283 WMGetScrollViewVisibleRect(WMScrollView *sPtr)
285 WMRect rect;
287 rect.pos.x = -sPtr->contentView->pos.x;
288 rect.pos.y = -sPtr->contentView->pos.y;
289 rect.size = sPtr->viewport->size;
291 return rect;
295 void
296 WMScrollViewScrollPoint(WMScrollView *sPtr, WMPoint point)
298 float xsize, ysize;
299 float xpos, ypos;
301 xsize = sPtr->contentView->size.width-sPtr->viewport->size.width;
302 ysize = sPtr->contentView->size.height-sPtr->viewport->size.height;
304 xpos = point.x / xsize;
305 ypos = point.y / ysize;
307 if (sPtr->hScroller)
308 WMSetScrollerParameters(sPtr->hScroller, xpos,
309 WMGetScrollerKnobProportion(sPtr->hScroller));
310 if (sPtr->vScroller)
311 WMSetScrollerParameters(sPtr->vScroller, ypos,
312 WMGetScrollerKnobProportion(sPtr->vScroller));
314 W_MoveView(sPtr->contentView, -point.x, -point.y);
318 static void
319 doScrolling(WMWidget *self, void *data)
321 ScrollView *sPtr = (ScrollView*)data;
322 float value;
323 int pos;
324 int vpsize;
325 float size;
327 if (sPtr->hScroller == (WMScroller *)self) {
328 pos = -sPtr->contentView->pos.x;
329 size = sPtr->contentView->size.width-sPtr->viewport->size.width;
330 vpsize = sPtr->viewport->size.width - sPtr->pageScroll;
331 } else {
332 pos = -sPtr->contentView->pos.y;
333 size = sPtr->contentView->size.height-sPtr->viewport->size.height;
334 vpsize = sPtr->viewport->size.height - sPtr->pageScroll;
336 if (vpsize <= 0)
337 vpsize = 1;
339 switch (WMGetScrollerHitPart(self)) {
340 case WSDecrementLine:
341 if (pos > 0) {
342 pos-=sPtr->lineScroll;
343 if (pos < 0)
344 pos = 0;
345 value = (float)pos / size;
346 WMSetScrollerParameters(self, value,
347 WMGetScrollerKnobProportion(self));
349 break;
350 case WSIncrementLine:
351 if (pos < size) {
352 pos+=sPtr->lineScroll;
353 if (pos > size)
354 pos = size;
355 value = (float)pos / size;
356 WMSetScrollerParameters(self, value,
357 WMGetScrollerKnobProportion(self));
359 break;
361 case WSKnob:
362 value = WMGetScrollerValue(self);
363 pos = value*size;
364 break;
366 case WSDecrementPage:
367 if (pos > 0) {
368 pos -= vpsize;
369 if (pos < 0)
370 pos = 0;
371 value = (float)pos / size;
372 WMSetScrollerParameters(self, value,
373 WMGetScrollerKnobProportion(self));
375 break;
377 case WSDecrementWheel:
378 if (pos > 0) {
379 pos -= vpsize/3;
380 if (pos < 0)
381 pos = 0;
382 value = (float)pos / size;
383 WMSetScrollerParameters(self, value,
384 WMGetScrollerKnobProportion(self));
386 break;
388 case WSIncrementPage:
389 if (pos < size) {
390 pos += vpsize;
391 if (pos > size)
392 pos = size;
393 value = (float)pos / size;
394 WMSetScrollerParameters(self, value,
395 WMGetScrollerKnobProportion(self));
397 break;
399 case WSIncrementWheel:
400 if (pos < size) {
401 pos += vpsize/3;
402 if (pos > size)
403 pos = size;
404 value = (float)pos / size;
405 WMSetScrollerParameters(self, value,
406 WMGetScrollerKnobProportion(self));
408 break;
410 case WSNoPart:
411 case WSKnobSlot:
412 break;
415 if (sPtr->hScroller == (WMScroller *)self) {
416 W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y);
417 } else {
418 W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos);
423 WMScroller*
424 WMGetScrollViewHorizontalScroller(WMScrollView *sPtr)
426 return sPtr->hScroller;
431 WMScroller*
432 WMGetScrollViewVerticalScroller(WMScrollView *sPtr)
434 return sPtr->vScroller;
438 void
439 WMSetScrollViewHasHorizontalScroller(WMScrollView *sPtr, Bool flag)
441 if (flag) {
442 if (sPtr->flags.hasHScroller)
443 return;
444 sPtr->flags.hasHScroller = 1;
446 sPtr->hScroller = WMCreateScroller(sPtr);
447 WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr);
448 /* make it a horiz. scroller */
449 WMResizeWidget(sPtr->hScroller, 2, 1);
451 reorganizeInterior(sPtr);
453 WMMapWidget(sPtr->hScroller);
454 } else {
455 if (!sPtr->flags.hasHScroller)
456 return;
458 WMUnmapWidget(sPtr->hScroller);
459 WMDestroyWidget(sPtr->hScroller);
460 sPtr->hScroller = NULL;
461 sPtr->flags.hasHScroller = 0;
463 reorganizeInterior(sPtr);
468 void
469 WMSetScrollViewHasVerticalScroller(WMScrollView *sPtr, Bool flag)
471 if (flag) {
472 if (sPtr->flags.hasVScroller)
473 return;
474 sPtr->flags.hasVScroller = 1;
476 sPtr->vScroller = WMCreateScroller(sPtr);
477 WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr);
478 WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd);
479 /* make it a vert. scroller */
480 WMResizeWidget(sPtr->vScroller, 1, 2);
482 reorganizeInterior(sPtr);
484 WMMapWidget(sPtr->vScroller);
485 } else {
486 if (!sPtr->flags.hasVScroller)
487 return;
488 sPtr->flags.hasVScroller = 0;
490 WMUnmapWidget(sPtr->vScroller);
491 WMDestroyWidget(sPtr->vScroller);
492 sPtr->vScroller = NULL;
494 reorganizeInterior(sPtr);
499 void
500 WMSetScrollViewContentView(WMScrollView *sPtr, WMView *view)
502 assert(sPtr->contentView == NULL);
504 sPtr->contentView = view;
506 W_ReparentView(sPtr->contentView, sPtr->viewport, 0, 0);
508 if (sPtr->flags.hasHScroller) {
509 float prop;
511 prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
512 WMSetScrollerParameters(sPtr->hScroller, 0, prop);
514 if (sPtr->flags.hasVScroller) {
515 float prop;
517 prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
519 WMSetScrollerParameters(sPtr->vScroller, 0, prop);
524 void
525 WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type)
527 sPtr->flags.relief = type;
529 reorganizeInterior(sPtr);
531 if (sPtr->view->flags.mapped)
532 paintScrollView(sPtr);
539 static void
540 paintScrollView(ScrollView *sPtr)
542 W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0,
543 sPtr->view->size.width, sPtr->view->size.height,
544 sPtr->flags.relief);
548 static void
549 updateScrollerProportion(ScrollView *sPtr)
551 float prop, value;
553 if (sPtr->flags.hasHScroller) {
554 prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
555 value = WMGetScrollerValue(sPtr->hScroller);
557 WMSetScrollerParameters(sPtr->hScroller, value, prop);
559 if (sPtr->flags.hasVScroller) {
560 prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
562 value = WMGetScrollerValue(sPtr->vScroller);
564 WMSetScrollerParameters(sPtr->vScroller, value, prop);
569 static void
570 handleViewportEvents(XEvent *event, void *data)
572 ScrollView *sPtr = (ScrollView*)data;
574 if (sPtr->contentView
575 && event->xconfigure.window == sPtr->contentView->window)
576 updateScrollerProportion(sPtr);
580 static void
581 handleEvents(XEvent *event, void *data)
583 ScrollView *sPtr = (ScrollView*)data;
585 CHECK_CLASS(data, WC_ScrollView);
587 switch (event->type) {
588 case Expose:
589 if (event->xexpose.count!=0)
590 break;
591 paintScrollView(sPtr);
592 break;
594 case DestroyNotify:
595 destroyScrollView(sPtr);
596 break;
602 static void
603 destroyScrollView(ScrollView *sPtr)
605 puts("destroyScrollView not implemented");
607 wfree(sPtr);