1 /********************************************************************
2 This file is part of the abs 0.907 distribution.  abs is a spreadsheet
3 with graphical user interface.
4 
5 Copyright (C) 1998-2001  Andr� Bertin (Andre.Bertin@ping.be)
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version if in the same spirit as version 2.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 Concact: abs@pi.be
22          http://home.pi.be/bertin/abs.shtml
23 
24 *********************************************************************/
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 #include "myscroll.h"
52 #include "worksheet.h"
53 #include "gr_interf.h"
54 #include "memory.h"
55 #include "callback.h"
56 #include "button.h"
57 
58 #include <math.h>
59 
60 #include "pixmaps/up.xpm"
61 #include "pixmaps/down.xpm"
62 #include "pixmaps/left.xpm"
63 #include "pixmaps/right.xpm"
64 
65 
66 static int nosetval = 0;
67 static int downonthumb = 0;
68 
69 int
val2pos(vmin,vmax,h,val)70 val2pos (vmin, vmax, h, val)
71      int vmin, vmax, val, h;
72 {
73   int pos = (val - vmin) * (h - 36) / (vmax - vmin) + 18;
74 
75 
76   return pos;
77 }
78 
79 int
pos2val(vmin,vmax,h,pos)80 pos2val (vmin, vmax, h, pos)
81      int vmin, vmax, pos, h;
82 {
83   int val = (vmax - vmin) * (pos - 18) / (h - 36) + vmin;
84 
85   return val;
86 }
87 
88 int
redrawthumb(ms)89 redrawthumb (ms)
90      Myscroll *ms;
91 {
92   if (ms->orientation == horizontal)
93     {
94       desactivate_zoom ();
95       fillrectangle (XtDisplay (ms->back), XtWindow (ms->back), 3, 17, 2, ms->backlen, ms->h - 4, 0, 0, 0);
96       drawbuttonup (XtDisplay (ms->back), XtWindow (ms->back),
97 	      ms->thumbpos, 3, ms->thumbpos + ms->thumblen, 14, NULL, 0, 0);
98       reactivate_zoom ();
99     }
100   else
101     {
102       desactivate_zoom ();
103       fillrectangle (XtDisplay (ms->back), XtWindow (ms->back), 3, 2, 17, ms->w - 4, ms->backlen, 0, 0, 0);
104       drawbuttonup (XtDisplay (ms->back), XtWindow (ms->back), 3, ms->thumbpos, 14, ms->thumbpos + ms->thumblen, NULL, 0, 0);
105       reactivate_zoom ();
106     }
107   return 0;
108 }
109 
110 
111 
112 
113 
114 
115 
116 
117 int
sethpos(ms,pos)118 sethpos (ms, pos)
119      Myscroll *ms;
120      int pos;
121 {
122 
123   double p, l;
124   int val;
125 
126 
127 
128   if (pos < ms->thumbmin)
129     pos = ms->thumbmin;
130   if (pos > ms->thumbmax - ms->thumbminlen)
131     pos = ms->thumbmax - ms->thumbminlen;
132 
133   p = pos - ms->thumbmin;
134   l = ms->thumbmax - ms->thumbminlen - ms->thumbmin;
135   if (l <= 0)
136     l = 1;
137   val = p / l * (ms->vmax - ms->vmin) + ms->vmin;
138 
139   setscrollval (ms, val);
140   return 0;
141 
142 }
143 
144 void
resizescroll(widget,pointer,event,ctd)145 resizescroll (widget, pointer, event, ctd)
146      Widget widget;
147      XtPointer pointer;
148      XEvent *event;
149      Boolean *ctd;
150 {
151   int n;
152   Dimension h, w;
153   Myscroll *ms;
154   int butsize = 18;
155   Arg args[2];
156   ms = (Myscroll *) pointer;
157 
158   n = 0;
159   XtSetArg (args[n], XtNheight, &h);
160   n++;
161   XtSetArg (args[n], XtNwidth, &w);
162   n++;
163   XtGetValues (widget, args, n);
164 
165   ms->h = h;
166   ms->w = w;
167 
168   if (ms->orientation == horizontal)
169     {
170       ms->thumbmax = w - butsize;
171     }
172   else
173     {
174       ms->thumbmax = h - butsize;
175 
176     }
177   ms->backlen = ms->thumbmax - ms->thumbmin;
178   if (ms->backlen < ms->thumbminlen)
179     ms->backlen = ms->thumbminlen;
180   setscrollval (ms, ms->val);
181 }
182 
183 
184 
185 
186 
187 void
btncb(widget,pointer,junk)188 btncb (widget, pointer, junk)
189      Widget widget;
190      XtPointer pointer;
191      XtPointer junk;
192 {
193 
194 
195   Myscroll *ms = (Myscroll *) pointer;
196 
197   if (widget == ms->up || widget == ms->left)
198     {
199       setscrollval (ms, ms->val - 1);
200     }
201   if (widget == ms->down || widget == ms->right)
202     {
203       setscrollval (ms, ms->val + 1);
204     }
205   if (widget == ms->thumb)
206     {
207     }
208 
209   nosetval = 1;
210   ms->cbfunction (ms->val);
211   nosetval = 0;
212 }
213 
214 void
thumbupcb(w,pointer,event,ctd)215 thumbupcb (w, pointer, event, ctd)
216      Widget w;
217      XtPointer pointer;
218      XEvent *event;
219      Boolean *ctd;
220 {
221 
222 
223 }
224 
225 void
movecb(w,pointer,event,ctd)226 movecb (w, pointer, event, ctd)
227      Widget w;
228      XtPointer pointer;
229      XEvent *event;
230      Boolean *ctd;
231 {
232   int x, y;
233   int delta;
234   Window root_return, child_return;
235   int root_x_return, root_y_return;
236   int win_x_return, win_y_return;
237   unsigned int mask_return;
238   Myscroll *ms = (Myscroll *) pointer;
239   XQueryPointer (XtDisplay (w), XtWindow (w), &root_return, &child_return, &root_x_return,
240 		 &root_y_return, &win_x_return, &win_y_return, &mask_return);
241 
242   if (!downonthumb)
243     return;
244 
245   x = root_x_return;
246   y = root_y_return;
247 
248 
249 
250   if (ms->orientation == vertical)
251     {
252       delta = y - ms->ssy;
253     }
254   else
255     {
256       delta = x - ms->ssx;
257     }
258 
259 
260   sethpos (ms, ms->thumbpos0 + delta);
261   nosetval = 1;
262   ms->cbfunction (ms->val);
263   nosetval = 0;
264 }
265 
266 void
redrawcb(w,pointer,event,ctd)267 redrawcb (w, pointer, event, ctd)
268      Widget w;
269      XtPointer pointer;
270      XEvent *event;
271      Boolean *ctd;
272 {
273   Myscroll *ms = (Myscroll *) pointer;
274   redrawthumb (ms);
275 }
276 
277 void
stepcb(w,pointer,event,ctd)278 stepcb (w, pointer, event, ctd)
279      Widget w;
280      XtPointer pointer;
281      XEvent *event;
282      Boolean *ctd;
283 {
284   int x, y;
285   int delta;
286 
287   Myscroll *ms = (Myscroll *) pointer;
288 
289   x = event->xbutton.x;
290   y = event->xbutton.y;
291 
292 
293   if ((ms->orientation == horizontal && x > ms->thumbpos && x < ms->thumbpos + ms->thumblen) ||
294       (ms->orientation == vertical && y > ms->thumbpos && y < ms->thumbpos + ms->thumblen))
295     {
296       downonthumb = 1;
297       ms->ssx = event->xbutton.x_root;
298       ms->ssy = event->xbutton.y_root;
299       ms->thumbpos0 = ms->thumbpos;
300       return;
301     }
302 
303 
304   if (ms->orientation == horizontal)
305     {
306       y = x;
307     }
308 
309   if (y < ms->thumbmin || y > ms->thumbmax)
310     return;
311 
312   delta = (y - ms->thumbpos) / 5.0;
313   if (fabs (delta / 1.0) < 2)
314     return;
315 
316   sethpos (ms, ms->thumbpos + delta);
317 
318   nosetval = 1;
319   ms->cbfunction (ms->val);
320   nosetval = 0;
321 
322 
323 }
324 
325 void
presscb(w,pointer,event,ctd)326 presscb (w, pointer, event, ctd)
327      Widget w;
328      XtPointer pointer;
329      XEvent *event;
330      Boolean *ctd;
331 {
332   int x, y;
333 
334   Myscroll *ms = (Myscroll *) pointer;
335 
336   x = event->xbutton.x_root;
337   y = event->xbutton.y_root;
338   fprintf (stderr, "in presscb\n");
339   ms->thumbpy = y;
340   ms->thumbpx = x;
341   ms->ssx = x;
342   ms->ssy = y;
343 }
344 
345 
346 int
setscrolllimit(ms,vmin,vmax)347 setscrolllimit (ms, vmin, vmax)
348      Myscroll *ms;
349      int vmin, vmax;
350 {
351   ms->vmin = vmin;
352   ms->vmax = vmax;
353   if (vmax == vmin)
354     vmax = vmin + 1;
355   return 0;
356 }
357 
358 void
setscrollval(ms,val)359 setscrollval (ms, val)
360      Myscroll *ms;
361      int val;
362 {
363   if (nosetval)
364     return;
365 
366   ms->val = val;
367   if (ms->val < ms->vmin)
368     ms->val = ms->vmin;
369   if (ms->val > ms->vmax)
370     ms->val = ms->vmax;
371 
372   {
373     double v = val;
374     double vmin = ms->vmin;
375     double vmax = ms->vmax;
376     double loc = (v - vmin) / (vmax - vmin);
377     int i1, j1, i2, j2;
378     get_visible_cells (&i1, &j1, &i2, &j2);
379     if (ms->orientation == horizontal)
380       {
381 
382 
383 
384 	ms->thumblen = (j2 - j1) / (vmax - vmin) * ms->backlen;
385       }
386     else
387       {
388 	ms->thumblen = (i2 - i1) / (vmax - vmin) * ms->backlen;
389       }
390 
391     if (ms->thumblen < ms->thumbminlen)
392       ms->thumblen = ms->thumbminlen;
393     if (ms->thumblen > ms->backlen)
394       ms->thumblen = ms->backlen;
395 
396     if (loc < 0)
397       loc = 0;
398     if (loc > 1)
399       loc = 1;
400     ms->thumbpos = loc * (ms->backlen - ms->thumblen) + ms->thumbmin;
401 
402 
403 
404     redrawthumb (ms);
405 
406     if (ms->orientation == horizontal)
407       {
408 	ms->cury = ms->thumbpos;
409 
410       }
411     else
412       {
413 	ms->curx = ms->thumbpos;
414       }
415 
416   }
417 
418 
419 }
420 
421 
422 Myscroll *
CreateMyscroll(parent,h,w,vmin,vmax,func)423 CreateMyscroll (parent, h, w, vmin, vmax, func)
424      Widget parent;
425      int h, w, vmin, vmax;
426      void (*func) ();
427 {
428   Arg args[16];
429   int n;
430   Myscroll *ms;
431   int butsize = 18;
432 
433 
434   ms = (Myscroll *) absmalloc (sizeof (Myscroll), "CreateMyscroll:ms ");
435 
436   ms->parent = parent;
437   ms->cbfunction = func;
438   ms->h = h;
439   ms->w = w;
440   ms->vmin = vmin;
441   ms->vmax = vmax;
442   ms->val = 0;
443   ms->thumblen = 30;
444   ms->thumbminlen = 15;
445   ms->thumbmin = butsize;
446   ms->thumbpos = butsize;
447 
448 
449   XtSetArg (w_args[w_n], XtNheight, h);
450   w_n++;
451   XtSetArg (w_args[w_n], XtNwidth, w);
452   w_n++;
453   XtSetArg (w_args[w_n], XtNborderWidth, 0);
454   w_n++;
455   ms->back = (Widget) XtCreateManagedWidget ("window", formWidgetClass, parent,
456 					     w_args, w_n);
457   if (h > w)
458     {
459       ms->orientation = vertical;
460       ms->thumbmax = h - butsize;
461 
462       ms->up = (Widget) make_repeater_pixmap (ms->back, "up", up_xpm, btncb, (XtPointer) ms);
463       n = 0;
464       XtSetArg (args[n], XtNfromHoriz, NULL);
465       n++;
466       XtSetArg (args[n], XtNhorizDistance, 1);
467       n++;
468       XtSetArg (args[n], XtNfromVert, NULL);
469       n++;
470       XtSetArg (args[n], XtNvertDistance, 1);
471       n++;
472       XtSetValues (ms->up, args, n);
473 
474       ms->cury = 18;
475 
476       ms->down = (Widget) make_repeater_pixmap (ms->back, "down", down_xpm, btncb, (XtPointer) ms);
477       n = 0;
478       XtSetArg (args[n], XtNfromVert, (XtPointer) NULL);
479       n++;
480       XtSetArg (args[n], XtNvertDistance, h - 14);
481       n++;
482       XtSetArg (args[n], XtNfromHoriz, NULL);
483       n++;
484       XtSetArg (args[n], XtNhorizDistance, 1);
485       n++;
486       XtSetValues (ms->down, args, n);
487     }
488   else
489     {
490       ms->orientation = horizontal;
491       ms->thumbmax = w - butsize;
492 
493       ms->left = (Widget) make_repeater_pixmap (ms->back, "left", left_xpm, btncb, (XtPointer) ms);
494       n = 0;
495       XtSetArg (args[n], XtNfromHoriz, NULL);
496       n++;
497       XtSetArg (args[n], XtNhorizDistance, 1);
498       n++;
499       XtSetArg (args[n], XtNfromVert, NULL);
500       n++;
501       XtSetArg (args[n], XtNvertDistance, 1);
502       n++;
503       XtSetValues (ms->left, args, n);
504 
505       ms->curx = 18;
506 
507       ms->right = (Widget) make_repeater_pixmap (ms->back, "right", right_xpm, btncb, (XtPointer)
508 						 ms);
509       n = 0;
510       XtSetArg (args[n], XtNfromHoriz, NULL);
511       n++;
512       XtSetArg (args[n], XtNhorizDistance, w - 14);
513       n++;
514       XtSetArg (args[n], XtNfromVert, NULL);
515       n++;
516       XtSetArg (args[n], XtNvertDistance, 1);
517       n++;
518       XtSetValues (ms->right, args, n);
519 
520     }
521 
522   ms->backlen = ms->thumbmax - ms->thumbmin;
523   if (ms->backlen < ms->thumbminlen)
524     ms->backlen = ms->thumbminlen;
525 
526 
527   XtAddEventHandler (ms->back, ButtonPressMask, False, stepcb, (XtPointer) ms);
528   XtAddEventHandler (ms->back, ExposureMask, FALSE, shadow2, (XtPointer) ms->back);
529   XtAddEventHandler (ms->back, ButtonReleaseMask, False, thumbupcb, (XtPointer) ms);
530 
531   XtAddEventHandler (ms->back, VisibilityChangeMask, False, redrawcb, (XtPointer) ms);
532 
533 
534   XtAddEventHandler (ms->back, Button1MotionMask, False, movecb, (XtPointer) ms);
535 
536   XtAddEventHandler (ms->back, StructureNotifyMask, False, resizescroll, (XtPointer) ms);
537   return ms;
538 }
539