missing function declaration
[wmaker-crm.git] / WINGs / wscrollview.c
blob24560ed2c7ba0e84991a7a0a458d51278f3dadb8
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();
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->view) {
68 W_DestroyView(sPtr->view);
69 wfree(sPtr);
70 return NULL;
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,
81 handleEvents, sPtr);
82 WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask,
83 handleViewportEvents, sPtr);
85 sPtr->lineScroll = 4;
87 sPtr->pageScroll = 0;
89 return sPtr;
94 static void
95 reorganizeInterior(WMScrollView *sPtr)
97 int hx, hy, hw;
98 int vx, vy, vh;
99 int cx, cy, cw, ch;
102 cw = hw = sPtr->view->size.width;
103 vh = ch = sPtr->view->size.height;
105 if (sPtr->flags.relief == WRSimple) {
106 cw -= 2;
107 ch -= 2;
108 cx = 1;
109 cy = 1;
110 } else if (sPtr->flags.relief != WRFlat) {
111 cw -= 3;
112 ch -= 3;
113 cx = 2;
114 cy = 2;
115 } else {
116 cx = 0;
117 cy = 0;
120 if (sPtr->flags.hasHScroller) {
121 int h = W_VIEW(sPtr->hScroller)->size.height;
123 ch -= h;
125 if (sPtr->flags.relief == WRSimple) {
126 hx = 0;
127 hy = sPtr->view->size.height - h;
128 } else if (sPtr->flags.relief != WRFlat) {
129 hx = 1;
130 hy = sPtr->view->size.height - h - 1;
131 hw -= 2;
132 } else {
133 hx = 0;
134 hy = sPtr->view->size.height - h;
136 } else {
137 /* make compiler shutup */
138 hx = 0;
139 hy = 0;
142 if (sPtr->flags.hasVScroller) {
143 int w = W_VIEW(sPtr->vScroller)->size.width;
144 cw -= w;
145 cx += w;
146 hx += w - 1;
147 hw -= w - 1;
149 if (sPtr->flags.relief == WRSimple) {
150 vx = 0;
151 vy = 0;
152 } else if (sPtr->flags.relief != WRFlat) {
153 vx = 1;
154 vy = 1;
155 vh -= 2;
156 } else {
157 vx = 0;
158 vy = 0;
160 } else {
161 /* make compiler shutup */
162 vx = 0;
163 vy = 0;
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);
180 static void
181 resizeScrollView(W_ViewDelegate *self, WMView *view)
183 reorganizeInterior(view->self);
188 void
189 WMResizeScrollViewContent(WMScrollView *sPtr, unsigned int width,
190 unsigned int height)
192 int w, h, x;
194 w = width;
195 h = height;
197 x = 0;
198 if (sPtr->flags.relief == WRSimple) {
199 w += 2;
200 h += 2;
201 } else if (sPtr->flags.relief != WRFlat) {
202 w += 4;
203 h += 4;
204 x = 1;
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);
223 void
224 WMSetScrollViewLineScroll(WMScrollView *sPtr, int amount)
226 assert(amount > 0);
228 sPtr->lineScroll = amount;
232 void
233 WMSetScrollViewPageScroll(WMScrollView *sPtr, int amount)
235 assert(amount >= 0);
237 sPtr->pageScroll = amount;
241 WMRect
242 WMGetScrollViewVisibleRect(WMScrollView *sPtr)
244 WMRect rect;
246 rect.pos = sPtr->contentView->pos;
247 rect.size = sPtr->viewport->size;
249 return rect;
252 static void
253 doScrolling(WMWidget *self, void *data)
255 ScrollView *sPtr = (ScrollView*)data;
256 float value;
257 int pos;
258 int vpsize;
259 float size;
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;
265 } else {
266 pos = -sPtr->contentView->pos.y;
267 size = sPtr->contentView->size.height-sPtr->viewport->size.height;
268 vpsize = sPtr->viewport->size.height - sPtr->pageScroll;
270 if (vpsize <= 0)
271 vpsize = 1;
273 switch (WMGetScrollerHitPart(self)) {
274 case WSDecrementLine:
275 if (pos > 0) {
276 pos-=sPtr->lineScroll;
277 if (pos < 0)
278 pos = 0;
279 value = (float)pos / size;
280 WMSetScrollerParameters(self, value,
281 WMGetScrollerKnobProportion(self));
283 break;
284 case WSIncrementLine:
285 if (pos < size) {
286 pos+=sPtr->lineScroll;
287 if (pos > size)
288 pos = size;
289 value = (float)pos / size;
290 WMSetScrollerParameters(self, value,
291 WMGetScrollerKnobProportion(self));
293 break;
295 case WSKnob:
296 value = WMGetScrollerValue(self);
297 pos = value*size;
298 break;
300 case WSDecrementPage:
301 if (pos > 0) {
302 pos -= vpsize;
303 if (pos < 0)
304 pos = 0;
305 value = (float)pos / size;
306 WMSetScrollerParameters(self, value,
307 WMGetScrollerKnobProportion(self));
309 break;
311 case WSDecrementWheel:
312 if (pos > 0) {
313 pos -= vpsize/3;
314 if (pos < 0)
315 pos = 0;
316 value = (float)pos / size;
317 WMSetScrollerParameters(self, value,
318 WMGetScrollerKnobProportion(self));
320 break;
322 case WSIncrementPage:
323 if (pos < size) {
324 pos += vpsize;
325 if (pos > size)
326 pos = size;
327 value = (float)pos / size;
328 WMSetScrollerParameters(self, value,
329 WMGetScrollerKnobProportion(self));
331 break;
333 case WSIncrementWheel:
334 if (pos < size) {
335 pos += vpsize/3;
336 if (pos > size)
337 pos = size;
338 value = (float)pos / size;
339 WMSetScrollerParameters(self, value,
340 WMGetScrollerKnobProportion(self));
342 break;
344 case WSNoPart:
345 case WSKnobSlot:
346 break;
349 if (sPtr->hScroller == (WMScroller *)self) {
350 W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y);
351 } else {
352 W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos);
357 WMScroller*
358 WMGetScrollViewHorizontalScroller(WMScrollView *sPtr)
360 return sPtr->hScroller;
365 WMScroller*
366 WMGetScrollViewVerticalScroller(WMScrollView *sPtr)
368 return sPtr->vScroller;
372 void
373 WMSetScrollViewHasHorizontalScroller(WMScrollView *sPtr, Bool flag)
375 if (flag) {
376 if (sPtr->flags.hasHScroller)
377 return;
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);
388 } else {
389 if (!sPtr->flags.hasHScroller)
390 return;
392 WMUnmapWidget(sPtr->hScroller);
393 WMDestroyWidget(sPtr->hScroller);
394 sPtr->hScroller = NULL;
395 sPtr->flags.hasHScroller = 0;
397 reorganizeInterior(sPtr);
402 void
403 WMSetScrollViewHasVerticalScroller(WMScrollView *sPtr, Bool flag)
405 if (flag) {
406 if (sPtr->flags.hasVScroller)
407 return;
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);
419 } else {
420 if (!sPtr->flags.hasVScroller)
421 return;
422 sPtr->flags.hasVScroller = 0;
424 WMUnmapWidget(sPtr->vScroller);
425 WMDestroyWidget(sPtr->vScroller);
426 sPtr->vScroller = NULL;
428 reorganizeInterior(sPtr);
433 void
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) {
443 float prop;
445 prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
446 WMSetScrollerParameters(sPtr->hScroller, 0, prop);
448 if (sPtr->flags.hasVScroller) {
449 float prop;
451 prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
453 WMSetScrollerParameters(sPtr->vScroller, 0, prop);
458 void
459 WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type)
461 sPtr->flags.relief = type;
463 reorganizeInterior(sPtr);
465 if (sPtr->view->flags.mapped)
466 paintScrollView(sPtr);
472 static void
473 paintScrollView(ScrollView *sPtr)
475 W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0,
476 sPtr->view->size.width, sPtr->view->size.height,
477 sPtr->flags.relief);
481 static void
482 updateScrollerProportion(ScrollView *sPtr)
484 float prop, value;
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);
502 static void
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);
513 static void
514 handleEvents(XEvent *event, void *data)
516 ScrollView *sPtr = (ScrollView*)data;
518 CHECK_CLASS(data, WC_ScrollView);
520 switch (event->type) {
521 case Expose:
522 if (event->xexpose.count!=0)
523 break;
524 paintScrollView(sPtr);
525 break;
527 case DestroyNotify:
528 destroyScrollView(sPtr);
529 break;
535 static void
536 destroyScrollView(ScrollView *sPtr)
538 puts("destroyScrollView not implemented");
540 wfree(sPtr);