1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: n:/project/cit/src/RCS/mfdgadg.c $
21  * $Revision: 1.5 $
22  * $Author: mahk $
23  * $Date: 1994/02/16 09:26:50 $
24  *
25  * $Log: mfdgadg.c $
26  * Revision 1.5  1994/02/16  09:26:50  mahk
27  * Hey, fixed my goofy bugs.
28  *
29  * Revision 1.4  1994/02/16  09:19:57  mahk
30  * Wrote goofy resizing code.
31  *
32  * Revision 1.3  1994/01/15  15:12:04  mahk
33  * Changed buttonarray spacing.
34  *
35  * Revision 1.2  1993/10/20  05:41:33  mahk
36  * Added a slider gadget.
37  *
38  * Revision 1.1  1993/09/15  10:54:30  mahk
39  * Initial revision
40  *
41  *
42  */
43 
44 #include <stdlib.h>
45 
46 #include "mfdgadg.h"
47 
48 extern void mouse_unconstrain(void);
49 uchar mfd_buttonarray_handlerproc(MFD *mfd, uiEvent *ev, MFDhandler *h);
50 uchar mfd_slider_handler(MFD *mfd, uiEvent *ev, MFDhandler *h);
51 
52 // =======================
53 // BUTTON ARRAYS
54 // =======================
55 
56 // ---------
57 // INTERNALS
58 // ---------
59 
60 typedef struct _mfd_bttnarray {
61     LGPoint bdims;  // Diminsions of button array
62     LGPoint bspace; // pixel spacing between buttons.
63     LGPoint bsize;  // pixel size of buttons.
64     MFDBttnCallback cb;
65     void *cbdata;
66 } MFDBttnArray;
67 
mfd_buttonarray_handlerproc(MFD * mfd,uiEvent * ev,MFDhandler * h)68 uchar mfd_buttonarray_handlerproc(MFD *mfd, uiEvent *ev, MFDhandler *h) {
69     MFDBttnArray *ba = (MFDBttnArray *)(h->data);
70     LGPoint bttn;
71     LGPoint pos;
72     if (ev->type != UI_EVENT_MOUSE || !(ev->subtype & ~MOUSE_MOTION))
73         return FALSE;
74     pos.x = ev->pos.x - mfd->rect.ul.x - h->r.ul.x;
75     pos.y = ev->pos.y - mfd->rect.ul.y - h->r.ul.y;
76     // Make sure its on a button, not a space.
77     if (pos.x % (ba->bspace.x + ba->bsize.x) >= ba->bsize.x || pos.y % (ba->bspace.y + ba->bsize.y) >= ba->bsize.y)
78         return FALSE;
79     bttn.x = lg_min(pos.x / (ba->bspace.x + ba->bsize.x), ba->bdims.x - 1);
80     bttn.y = lg_min(pos.y / (ba->bspace.y + ba->bsize.y), ba->bdims.y - 1);
81     return ba->cb(mfd, bttn, ev, ba->cbdata);
82 }
83 
84 // ---------
85 // EXTERNALS
86 // ---------
87 
MFDBttnArrayInit(MFDhandler * h,LGRect * r,LGPoint bdims,LGPoint bsize,MFDBttnCallback cb,void * cbdata)88 errtype MFDBttnArrayInit(MFDhandler *h, LGRect *r, LGPoint bdims, LGPoint bsize, MFDBttnCallback cb, void *cbdata) {
89     if (bsize.x < 1 || bsize.y < 1)
90         return ERR_RANGE;
91     MFDBttnArray *ba = (MFDBttnArray *)malloc(sizeof(MFDBttnArray));
92     if (ba == NULL)
93         return ERR_NOMEM;
94     h->r = *r;
95     h->data = ba;
96     h->proc = mfd_buttonarray_handlerproc;
97     ba->bdims = bdims;
98     ba->bsize = bsize;
99     if (bdims.x > 1)
100         ba->bspace.x = (RectWidth(r) - bsize.x) / (bdims.x - 1) - bsize.x;
101     else
102         ba->bspace.x = RectWidth(r) - bsize.x;
103     if (bdims.y > 1)
104         ba->bspace.y = (RectHeight(r) - bsize.y) / (bdims.y - 1) - bsize.y;
105     else
106         ba->bspace.y = RectHeight(r) - bsize.y;
107     ba->cb = cb;
108     ba->cbdata = cbdata;
109     return OK;
110 }
111 
MFDBttnArrayShutdown(MFDhandler * h)112 errtype MFDBttnArrayShutdown(MFDhandler *h) {
113     free(h->data);
114     h->proc = NULL;
115     return OK;
116 }
117 
MFDBttnArrayResize(MFDhandler * h,LGRect * r,LGPoint bdims,LGPoint bsize)118 errtype MFDBttnArrayResize(MFDhandler *h, LGRect *r, LGPoint bdims, LGPoint bsize) {
119     MFDBttnArray *ba = (MFDBttnArray *)h->data;
120     if (bsize.x < 1 || bsize.y < 1)
121         return ERR_RANGE;
122     h->r = *r;
123     ba->bdims = bdims;
124     ba->bsize = bsize;
125     if (bdims.x > 1)
126         ba->bspace.x = (RectWidth(r) - bsize.x) / (bdims.x - 1) - bsize.x;
127     else
128         ba->bspace.x = RectWidth(r) - bsize.x;
129     if (bdims.y > 1)
130         ba->bspace.y = (RectHeight(r) - bsize.y) / (bdims.y - 1) - bsize.y;
131     else
132         ba->bspace.y = RectHeight(r) - bsize.y;
133     return OK;
134 }
135 
136 // ======================
137 //        SLIDERS
138 // ======================
139 
140 // ---------
141 // INTERNALS
142 // ---------
143 
144 typedef struct _mfd_slider {
145     MFDSliderCallback cb;
146     void *data;
147     uchar bttndown;
148 } MFDSlider;
149 
mfd_slider_handler(MFD * mfd,uiEvent * ev,MFDhandler * h)150 uchar mfd_slider_handler(MFD *mfd, uiEvent *ev, MFDhandler *h) {
151     short x = mfd->rect.ul.x + h->r.ul.x;
152     short y = mfd->rect.ul.y + h->r.ul.y;
153     uchar retval = TRUE;
154     MFDSlider *sl = (MFDSlider *)(h->data);
155     LGPoint pos = ev->pos;
156     pos.x -= x;
157     pos.y -= y;
158     if (ev->type != UI_EVENT_MOUSE && ev->type != UI_EVENT_MOUSE_MOVE)
159         return FALSE;
160     if (ev->mouse_data.action & MOUSE_LDOWN) {
161         mouse_constrain_xy(x, y, x + RectWidth(&h->r) - 1, y + RectHeight(&h->r) - 1);
162         sl->bttndown = TRUE;
163     }
164     if (sl->bttndown) {
165         retval = sl->cb(mfd, pos.x, (uiEvent *)ev, sl->data);
166     }
167     if (!(ev->mouse_data.buttons & (1 << MOUSE_LBUTTON))) {
168         sl->bttndown = FALSE;
169         mouse_unconstrain();
170     }
171     return retval;
172 }
173 
174 // ---------
175 // EXTERNALS
176 // ---------
177 
MFDSliderInit(MFDhandler * h,LGRect * r,MFDSliderCallback cb,void * data)178 errtype MFDSliderInit(MFDhandler *h, LGRect *r, MFDSliderCallback cb, void *data) {
179     MFDSlider *sl = (MFDSlider *)malloc(sizeof(MFDSlider));
180     if (sl == NULL)
181         return ERR_NOMEM;
182     h->r = *r;
183     h->data = sl;
184     h->proc = (MFD_handlerProc)mfd_slider_handler;
185     sl->cb = cb;
186     sl->data = data;
187     sl->bttndown = FALSE;
188     return OK;
189 }
190