mknob.c 24.2 KB
Newer Older
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Copyright (c) 1997-1999 Miller Puckette.
 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* mknob.c written by Antoine Rousseau from g_vslider.c.*/
/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"

17
#include "g_all_guis.h"
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <math.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif


#define MKNOB_TANGLE 100
#define MKNOB_DEFAULTH 100
#define MKNOB_DEFAULTSIZE 25
#define MKNOB_MINSIZE 12
#define MKNOB_THICK 3
/* ------------ mknob  ----------------------- */
typedef struct _mknob
{
    t_iemgui x_gui;
    int      x_pos;
    int      x_val;
    int      x_center;
    int      x_thick;
    int      x_lin0_log1;
    int      x_steady;
    double   x_min;
    double   x_max;
44
    int      x_H;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
45
46
47
48
49
50
51
52
53
    double   x_k;
} t_mknob;

t_widgetbehavior mknob_widgetbehavior;
static t_class *mknob_class;

/* widget helper functions */
static void mknob_update_knob(t_mknob *x, t_glist *glist)
{
54
55
56
57
58
59
    t_canvas *canvas = glist_getcanvas(glist);
    float val = (x->x_val + 50.0)/100.0/x->x_H;
    float angle,
        radius = x->x_gui.x_w/2.0*.98,
        miniradius = MKNOB_THICK,
        xp, yp, xc, yc, xpc, ypc;
60
    int x0,y0,x1,y1;
61
62
63
64
65
66
67
68
69
70
71
    //x0=text_xpix(&x->x_gui.x_obj, glist);
    //y0=text_ypix(&x->x_gui.x_obj, glist);
    x0 = 0;
    y0 = 0;
    x1 = x0 + x->x_gui.x_w;
    y1 = y0 + x->x_gui.x_w;
    xc = (x0+x1) / 2.0;
    yc = (y0+y1) / 2.0;

    if (x->x_gui.x_h < 0)
        angle = val * (M_PI * 2.0) + M_PI / 2.0;
72
    else
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        angle = val * (M_PI * 1.5) + 3.0 * M_PI / 4.0;

    xp = xc + radius * cos(angle);
    yp = yc + radius * sin(angle);
    xpc = miniradius * cos(angle - M_PI / 2.0);
    ypc = miniradius * sin(angle - M_PI / 2.0);

    gui_vmess("gui_turn_mknob", "xxffff",
        canvas,
        x,
        xp,
        yp,
        xc,
        yc
    );
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
88
89
90
91
92
}

static void mknob_draw_update(t_mknob *x, t_glist *glist)
{
    if (glist_isvisible(glist))
93
        mknob_update_knob(x,glist);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
94
95
}

96
97
98
99
100
101
102
103
104
static void mknob_draw_config(t_mknob *x,t_glist *glist)
{
    t_canvas *canvas = glist_getcanvas(glist);
    char bcol[8], fcol[8], lcol[8];

    sprintf(bcol, "#%6.6x", x->x_gui.x_bcol);
    sprintf(fcol, "#%6.6x", x->x_gui.x_fcol);
    sprintf(lcol, "#%6.6x", x->x_gui.x_lcol);

105
    gui_vmess("gui_configure_mknob", "xxiss",
106
107
108
109
        canvas,
        x,
        x->x_gui.x_w,
        bcol,
110
        fcol
111
112
113
114
    );
    mknob_update_knob(x,glist);
}

Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
115
116
static void mknob_draw_new(t_mknob *x, t_glist *glist)
{
117
118
119
120
    int xpos = text_xpix(&x->x_gui.x_obj, glist);
    int ypos = text_ypix(&x->x_gui.x_obj, glist);
    t_canvas *canvas = glist_getcanvas(glist);

121
122
123
124
125
126
    gui_vmess("gui_mknob_new", "xxiiiii",
        canvas,
        x,
        xpos,
        ypos,
        glist_istoplevel(glist),
127
128
        !iemgui_has_snd(x),
        !iemgui_has_rcv(x)
129
130
    );
    mknob_draw_config(x, glist);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
131
132
133
134
}

void mknob_draw(t_mknob *x, t_glist *glist, int mode)
{
135
    if (mode == IEM_GUI_DRAW_MODE_UPDATE)
136
        mknob_draw_update(x, glist);
137
    else if (mode == IEM_GUI_DRAW_MODE_MOVE)
138
        iemgui_base_draw_move(&x->x_gui);
139
    else if (mode == IEM_GUI_DRAW_MODE_NEW)
140
        mknob_draw_new(x, glist);
141
    else if (mode == IEM_GUI_DRAW_MODE_CONFIG)
142
        mknob_draw_config(x, glist);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
143
144
145
146
147
148
}

/* ------------------------ mknob widgetbehaviour----------------------------- */


static void mknob_getrect(t_gobj *z, t_glist *glist,
149
                          int *xp1, int *yp1, int *xp2, int *yp2)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
150
{
151
    t_mknob *x = (t_mknob *)z;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
152
153
154
155
156
157
158
159
160
161

    *xp1 = text_xpix(&x->x_gui.x_obj, glist);
    *yp1 = text_ypix(&x->x_gui.x_obj, glist);
    *xp2 = *xp1 + x->x_gui.x_w;
    *yp2 = *yp1 + x->x_gui.x_w;
}

static void mknob_save(t_gobj *z, t_binbuf *b)
{
    t_mknob *x = (t_mknob *)z;
162
    int bflcol[3];
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
163
164
165
166
    t_symbol *srl[3];

    iemgui_save(&x->x_gui, srl, bflcol);
    binbuf_addv(b, "ssiisiiffiisssiiiiiiiii", gensym("#X"),gensym("obj"),
167
168
169
170
                (t_int)x->x_gui.x_obj.te_xpix, (t_int)x->x_gui.x_obj.te_ypix,
                atom_getsymbol(binbuf_getvec(x->x_gui.x_obj.te_binbuf)),
                x->x_gui.x_w, x->x_gui.x_h,
                (float)x->x_min, (float)x->x_max,
171
                x->x_lin0_log1, iem_symargstoint(x),
172
173
                srl[0], srl[1], srl[2],
                x->x_gui.x_ldx, x->x_gui.x_ldy,
174
                iem_fstyletoint(x), x->x_gui.x_fontsize,
175
176
                bflcol[0], bflcol[1], bflcol[2],
                x->x_val, x->x_steady);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
177
178
179
180
181
182
    binbuf_addv(b, ";");
}

void mknob_check_wh(t_mknob *x, int w, int h)
{
    int H;
183
184

    if(w < MKNOB_MINSIZE) w = MKNOB_MINSIZE;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
185
    x->x_gui.x_w = w;
186

Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
187
188
189
    if(h < -1) h=-1;
    if((h>0)&&(h<20)) h=20;
    x->x_gui.x_h = h;
190
191
192
193
194
195

    H=x->x_gui.x_h;
    if(H<0) H=360;
    if(H==0) H=270;
    x->x_H=H;

Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
196
    if(x->x_lin0_log1)
197
        x->x_k = log(x->x_max/x->x_min)/(double)(x->x_H - 1);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
198
    else
199
        x->x_k = (x->x_max - x->x_min)/(double)(x->x_H - 1);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
200
201
202
203
204
}

void mknob_check_minmax(t_mknob *x, double min, double max)
{
    int H;
205
206

    if(x->x_lin0_log1)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
207
    {
208
209
210
211
212
213
214
215
216
217
218
219
        if((min == 0.0)&&(max == 0.0))
            max = 1.0;
        if(max > 0.0)
        {
            if(min <= 0.0)
                min = 0.01*max;
        }
        else
        {
            if(min > 0.0)
                max = 0.01*min;
        }
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
220
221
222
223
    }
    x->x_min = min;
    x->x_max = max;
    if(x->x_min > x->x_max)                /* bugfix */
224
        x->x_gui.x_reverse = 1;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
225
    else
226
        x->x_gui.x_reverse = 0;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
227
228

    if(x->x_lin0_log1)
229
        x->x_k = log(x->x_max/x->x_min)/(double)(x->x_H - 1);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
230
    else
231
        x->x_k = (x->x_max - x->x_min)/(double)(x->x_H - 1);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
232
    /*if(x->x_lin0_log1)
233
    	x->x_k = log(x->x_max/x->x_min)/(double)(MKNOB_TANGLE - 1);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
234
    else
235
    	x->x_k = (x->x_max - x->x_min)/(double)(MKNOB_TANGLE - 1);*/
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
236
237
238
239
240
241
}

static void mknob_properties(t_gobj *z, t_glist *owner)
{
    t_mknob *x = (t_mknob *)z;
    char buf[800];
242
    char *gfx_tag;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
243
244
245
    t_symbol *srl[3];

    iemgui_properties(&x->x_gui, srl);
246
247
248
249
250
251
252
    gfx_tag = gfxstub_new2(&x->x_gui.x_obj.ob_pd, x);

    gui_start_vmess("gui_iemgui_dialog", "s", gfx_tag);
    gui_start_array();

    gui_s("type");             gui_s("mknob");
    /* Since mknob reuses the iemgui dialog code, we just
253
254
255
       use the "width" slot for "size" and the "height" slot
       for the number of steps and re-label it on the GUI side. */
    gui_s("width");            gui_i(x->x_gui.x_w);
256
257
258
259
    gui_s("height");           gui_i(x->x_gui.x_h);
    gui_s("minimum_range");    gui_f(x->x_min);
    gui_s("maximum_range");    gui_f(x->x_max);
    gui_s("log_scaling");      gui_i(x->x_lin0_log1);
260
    gui_s("init");             gui_i(x->x_gui.x_loadinit);
261
262
263
264
265
266
    gui_s("steady_on_click");   gui_i(x->x_steady);
    gui_s("send_symbol");      gui_s(srl[0]->s_name);
    gui_s("receive_symbol");   gui_s(srl[1]->s_name);
    gui_s("label");            gui_s(srl[2]->s_name);
    gui_s("x_offset");         gui_i(x->x_gui.x_ldx);
    gui_s("y_offset");         gui_i(x->x_gui.x_ldy);
267
    gui_s("font_style");       gui_i(x->x_gui.x_font_style);
268
269
270
271
272
273
274
    gui_s("font_size");        gui_i(x->x_gui.x_fontsize);
    gui_s("background_color"); gui_i(0xffffff & x->x_gui.x_bcol);
    gui_s("foreground_color"); gui_i(0xffffff & x->x_gui.x_fcol);
    gui_s("label_color");      gui_i(0xffffff & x->x_gui.x_lcol);

    gui_end_array();
    gui_end_vmess();
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
275
276
277
278
279
280
}

static void mknob_set(t_mknob *x, t_floatarg f)    /* bugfix */
{
    double g;

281
    if(x->x_gui.x_reverse)    /* bugfix */
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
282
    {
283
284
285
286
        if(f > x->x_min)
            f = x->x_min;
        if(f < x->x_max)
            f = x->x_max;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
287
288
289
    }
    else
    {
290
291
292
293
        if(f > x->x_max)
            f = x->x_max;
        if(f < x->x_min)
            f = x->x_min;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
294
295
    }
    if(x->x_lin0_log1)
296
        g = log(f/x->x_min)/x->x_k;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
297
    else
298
        g = (f - x->x_min) / x->x_k;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
299
300
301
302
303
304
305
306
307
308
    x->x_val = (int)(100.0*g + 0.49999);
    x->x_pos = x->x_val;
    (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
}

static void mknob_bang(t_mknob *x)
{
    double out;

    if(x->x_lin0_log1)
309
        out = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
310
    else
311
        out = (double)(x->x_val)*0.01*x->x_k + x->x_min;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
312
    if((out < 1.0e-10)&&(out > -1.0e-10))
313
        out = 0.0;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
314
    outlet_float(x->x_gui.x_obj.ob_outlet, out);
315
    if (iemgui_has_snd(x) && x->x_gui.x_snd->s_thing)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
316
317
318
319
320
        pd_float(x->x_gui.x_snd->s_thing, out);
}

static void mknob_dialog(t_mknob *x, t_symbol *s, int argc, t_atom *argv)
{
321
    canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
322
323
324
325
326
327
328
329
330
    t_symbol *srl[3];
    int w = (int)atom_getintarg(0, argc, argv);
    int h = (int)atom_getintarg(1, argc, argv);
    double min = (double)atom_getfloatarg(2, argc, argv);
    double max = (double)atom_getfloatarg(3, argc, argv);
    int lilo = (int)atom_getintarg(4, argc, argv);
    int steady = (int)atom_getintarg(17, argc, argv);
    int sr_flags;

331
    if (lilo != 0) lilo = 1;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
332
    x->x_lin0_log1 = lilo;
333
    if (steady)
334
        x->x_steady = 1;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
335
    else
336
        x->x_steady = 0;
337
    sr_flags = iemgui_dialog(&x->x_gui, argc, argv);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
338
339
340
341
    //x->x_gui.x_h = iemgui_clip_size(h);
    //x->x_gui.x_w = iemgui_clip_size(w);
    mknob_check_wh(x, w, h);
    mknob_check_minmax(x, min, max);
342
343
    iemgui_draw_config(&x->x_gui);
    //(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
344
    //(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
345
346
347
    iemgui_draw_io(&x->x_gui, sr_flags);
    iemgui_draw_move(&x->x_gui);
    //(*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
348
    canvas_fixlinesfor(x->x_gui.x_glist, (t_text *)x);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
349
350
}

351
static int xm0, ym0, xm, ym;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
352
353
354
355

static void mknob_motion(t_mknob *x, t_floatarg dx, t_floatarg dy)
{
    int old = x->x_val;
356
357
358
    float d=-dy;

    if (abs(dx)>abs(dy)) d=dx;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
359

360
    if(x->x_gui.x_finemoved)
361
        x->x_pos += (int)d;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
362
    else
363
        x->x_pos += 100*(int)d;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
364
365
366
    x->x_val = x->x_pos;
    if(x->x_val > (100*x->x_H - 100))
    {
367
368
369
        x->x_val = 100*x->x_H - 100;
        x->x_pos += 50;
        x->x_pos -= x->x_pos%100;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
370
371
372
    }
    if(x->x_val < 0)
    {
373
374
375
        x->x_val = 0;
        x->x_pos -= 50;
        x->x_pos -= x->x_pos%100;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
376
377
378
    }
    if(old != x->x_val)
    {
379
380
        (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
        mknob_bang(x);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
381
382
383
384
385
386
387
388
    }
}

static void mknob_motion_circular(t_mknob *x, t_floatarg dx, t_floatarg dy)
{
    int xc=text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2;
    int yc=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2;
    int old = x->x_val;
389
390
391
392
393
394
395
396
397
398
    float alpha;

    xm+=dx;
    ym+=dy;

    alpha=atan2(xm-xc,ym-yc)*180.0/M_PI;

    x->x_pos=(int)(31500-alpha*100.0)%36000;
    if(x->x_pos>31500) x->x_pos=0;
    else if(x->x_pos>(27000-100)) x->x_pos=(27000-100);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
399
400

    x->x_val=x->x_pos;
401
402

    if(old != x->x_val)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
403
    {
404
405
        (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
        mknob_bang(x);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
406
407
408
409
410
411
412
413
    }
}

static void mknob_motion_fullcircular(t_mknob *x, t_floatarg dx, t_floatarg dy)
{
    int xc=text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2;
    int yc=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2;
    int old = x->x_val;
414
415
416
417
418
419
420
421
422
423
424
    float alpha;

    xm+=dx;
    ym+=dy;

    alpha=atan2(xm-xc,ym-yc)*180.0/M_PI;

    x->x_pos=(int)(36000-alpha*100.0)%36000;
    /*if(x->x_pos>31500) x->x_pos=0;
    else if(x->x_pos>(27000-100)) x->x_pos=(27000-100);*/

425
426
427
428
    if (x->x_pos > (36000-100))
    {
        x->x_pos=(36000-100);
    }
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
429
    x->x_val=x->x_pos;
430

431
    if (old != x->x_val)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
432
    {
433
434
        (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
        mknob_bang(x);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
435
436
437
438
    }
}

static void mknob_click(t_mknob *x, t_floatarg xpos, t_floatarg ypos,
439
                        t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
440
{
441
442
443
    xm0 = xm = xpos;
    ym0 = ym = ypos;
    if (x->x_val > (100*x->x_H - 100))
444
        x->x_val = 100*x->x_H - 100;
445
    if (x->x_val < 0)
446
        x->x_val = 0;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
447
448
449
450
    x->x_pos = x->x_val;
    (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
    mknob_bang(x);

451
    if (x->x_gui.x_h<0)
452
453
        glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g,
                   (t_glistmotionfn)mknob_motion_fullcircular, 0, xpos, ypos);
454
    else if (x->x_gui.x_h==0)
455
456
457
458
459
        glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g,
                   (t_glistmotionfn)mknob_motion_circular, 0, xpos, ypos);
    else
        glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g,
                   (t_glistmotionfn)mknob_motion, 0, xpos, ypos);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
460
461
462
}

static int mknob_newclick(t_gobj *z, struct _glist *glist,
463
                          int xpix, int ypix, int shift, int alt, int dbl, int doit)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
464
{
465
    t_mknob *x = (t_mknob *)z;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
466

467
    if (doit)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
468
    {
469
470
        mknob_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift,
                     0, (t_floatarg)alt);
471
        if (shift)
472
            x->x_gui.x_finemoved = 1;
473
        else
474
            x->x_gui.x_finemoved = 0;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
475
476
477
478
479
480
    }
    return (1);
}

static void mknob_size(t_mknob *x, t_symbol *s, int ac, t_atom *av)
{
481
482
    int w = (int)atom_getintarg(0, ac, av),
        h = x->x_gui.x_h;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
483

484
    if (ac > 1) h = (int)atom_getintarg(1, ac, av);
485
486

    mknob_check_wh(x, w, h);
487
    iemgui_size((t_iemgui *)x);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
488
489
490
}

static void mknob_delta(t_mknob *x, t_symbol *s, int ac, t_atom *av)
491
{
492
    iemgui_delta((t_iemgui *)x, s, ac, av);
493
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
494
495

static void mknob_pos(t_mknob *x, t_symbol *s, int ac, t_atom *av)
496
{
497
    iemgui_pos((t_iemgui *)x, s, ac, av);
498
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
499
500
501
502

static void mknob_range(t_mknob *x, t_symbol *s, int ac, t_atom *av)
{
    mknob_check_minmax(x, (double)atom_getfloatarg(0, ac, av),
503
                       (double)atom_getfloatarg(1, ac, av));
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
504
505
506
}

static void mknob_color(t_mknob *x, t_symbol *s, int ac, t_atom *av)
507
{
508
    iemgui_color((t_iemgui *)x, s, ac, av);
509
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
510
511

static void mknob_send(t_mknob *x, t_symbol *s)
512
{
513
    iemgui_send((t_iemgui *)x, s);
514
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
515
516

static void mknob_receive(t_mknob *x, t_symbol *s)
517
{
518
    iemgui_receive((t_iemgui *)x, s);
519
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
520
521

static void mknob_label(t_mknob *x, t_symbol *s)
522
{
523
    iemgui_label((t_iemgui *)x, s);
524
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
525
526

static void mknob_label_pos(t_mknob *x, t_symbol *s, int ac, t_atom *av)
527
{
528
    iemgui_label_pos((t_iemgui *)x, s, ac, av);
529
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
530
531

static void mknob_label_font(t_mknob *x, t_symbol *s, int ac, t_atom *av)
532
{
533
    iemgui_label_font((t_iemgui *)x, s, ac, av);
534
}
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549

static void mknob_log(t_mknob *x)
{
    x->x_lin0_log1 = 1;
    mknob_check_minmax(x, x->x_min, x->x_max);
}

static void mknob_lin(t_mknob *x)
{
    x->x_lin0_log1 = 0;
    x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_w - 1);
}

static void mknob_init(t_mknob *x, t_floatarg f)
{
550
    x->x_gui.x_loadinit = (f==0.0)?0:1;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
551
552
553
554
555
556
557
558
559
560
561
562
}

static void mknob_steady(t_mknob *x, t_floatarg f)
{
    x->x_steady = (f==0.0)?0:1;
}

static void mknob_float(t_mknob *x, t_floatarg f)
{
    double out;

    mknob_set(x, f);
563
    if (x->x_lin0_log1)
564
        out = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
565
    else
566
        out = (double)(x->x_val)*0.01*x->x_k + x->x_min;
567
    if ((out < 1.0e-10)&&(out > -1.0e-10))
568
        out = 0.0;
569
    if (x->x_gui.x_put_in2out)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
570
    {
571
        outlet_float(x->x_gui.x_obj.ob_outlet, out);
572
        if (iemgui_has_snd(x) && x->x_gui.x_snd->s_thing)
573
            pd_float(x->x_gui.x_snd->s_thing, out);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
574
575
576
577
578
    }
}

static void mknob_loadbang(t_mknob *x)
{
579
    if (!sys_noloadbang && x->x_gui.x_loadinit)
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
580
    {
581
582
        (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
        mknob_bang(x);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
583
584
585
    }
}

586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
/* we may no longer need h_dragon... */
static void mknob__clickhook(t_scalehandle *sh, int newstate)
{
    t_mknob *x = (t_mknob *)(sh->h_master);
    if (newstate)
    {
        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
        if (!sh->h_scale) /* click on a label handle */
            scalehandle_click_label(sh);
    }
    /* We no longer need this "clickhook", as we can handle the dragging
       either in the GUI (for the label handle) or or in canvas_doclick */
    //iemgui__clickhook3(sh,newstate);
    sh->h_dragon = newstate;
}

static void mknob__motionhook(t_scalehandle *sh,
                    t_floatarg mouse_x, t_floatarg mouse_y)
{
    if (sh->h_scale)
    {
        t_mknob *x = (t_mknob *)(sh->h_master);
        int width = x->x_gui.x_w,
            height = x->x_gui.x_h;
        int x1, y1, x2, y2, d;
        x1 = text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist);
        y1 = text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist);
        x2 = x1 + width;
        y2 = y1 + height;

        /* This is convoluted, but I can't think of another
           way to get this behavior... */
        if (mouse_x <= x2)
        {
            if (mouse_y > y2)
                d = mouse_y - y2;
            else if (abs(mouse_y - y2) < abs(mouse_x - x2))
                d = mouse_y - y2;
            else
                d = mouse_x - x2;
        }
        else
        {
            if (mouse_y <= y2)
                d = mouse_x - x2;
            else
                d = maxi(mouse_y - y2, mouse_x - x2);
        }
        sh->h_dragx = d;
        sh->h_dragy = d;
        scalehandle_drag_scale(sh);

        width = maxi(width + d, IEM_GUI_MINSIZE);
        height = width;

        x->x_gui.x_w = width;
        x->x_gui.x_h = height;

        if (glist_isvisible(x->x_gui.x_glist))
        {
            mknob_draw_config(x, x->x_gui.x_glist);
            scalehandle_unclick_scale(sh);
        }

        int properties = gfxstub_haveproperties((void *)x);
        if (properties)
        {
            int new_w = x->x_gui.x_w + sh->h_dragx;
654
655
656
657
            // This should actually be "size", but we're using the
            // "width" input in dialog_iemgui and just relabelling it
            // as a kluge.
            properties_set_field_int(properties, "width", new_w);
658
659
660
661
662
        }
    }
    scalehandle_dragon_label(sh,mouse_x, mouse_y);
}

Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
663
664
665
static void *mknob_new(t_symbol *s, int argc, t_atom *argv)
{
    t_mknob *x = (t_mknob *)pd_new(mknob_class);
666
    int bflcol[]= {-262144, -1, -1};
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
667
668
669
670
671
672
673
674
675
676
    //t_symbol *srl[3];
    int w=MKNOB_DEFAULTSIZE, h=MKNOB_DEFAULTH;
    int fs=8 ,lilo=0, ldx=-2, ldy=-6, f=0, v=0, steady=1;
    //int  iinit=0, ifstyle=0;
    double min=0.0, max=(double)(IEM_SL_DEFAULTSIZE-1);
    //t_iem_init_symargs *init=(t_iem_init_symargs *)(&iinit);
    //t_iem_fstyle_flags *fstyle=(t_iem_fstyle_flags *)(&ifstyle);
    char str[144];

    if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
677
678
679
680
681
682
683
684
            &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3)
            &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5)
            &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
            &&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7))
            &&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8))
            &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)
            &&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,13)
            &&IS_A_FLOAT(argv,14)&&IS_A_FLOAT(argv,15)&&IS_A_FLOAT(argv,16))
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
685
    {
686
687
688
689
690
        w = (int)atom_getintarg(0, argc, argv);
        h = (int)atom_getintarg(1, argc, argv);
        min = (double)atom_getfloatarg(2, argc, argv);
        max = (double)atom_getfloatarg(3, argc, argv);
        lilo = (int)atom_getintarg(4, argc, argv);
691
        iem_inttosymargs(&x->x_gui, atom_getintarg(5, argc, argv));
692
693
694
        iemgui_new_getnames(&x->x_gui, 6, argv);
        ldx = (int)atom_getintarg(9, argc, argv);
        ldy = (int)atom_getintarg(10, argc, argv);
695
        iem_inttofstyle(x, atom_getintarg(11, argc, argv));
696
697
698
699
700
        fs = (int)atom_getintarg(12, argc, argv);
        bflcol[0] = (int)atom_getintarg(13, argc, argv);
        bflcol[1] = (int)atom_getintarg(14, argc, argv);
        bflcol[2] = (int)atom_getintarg(15, argc, argv);
        v = (int)atom_getintarg(16, argc, argv);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
701
702
703
704
    }
    else iemgui_new_getnames(&x->x_gui, 6, 0);

    if((argc == 18)&&IS_A_FLOAT(argv,17))
705
        steady = (int)atom_getintarg(17, argc, argv);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
706
707
708

    x->x_gui.x_draw = (t_iemfunptr)mknob_draw;
    x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
709
    if(x->x_gui.x_loadinit)
710
        x->x_val = v;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
711
    else
712
        x->x_val = 0;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
713
714
715
716
717
    x->x_pos = x->x_val;
    if(lilo != 0) lilo = 1;
    x->x_lin0_log1 = lilo;
    if(steady != 0) steady = 1;
    x->x_steady = steady;
718
719
720
721
722
723
724
725
    if (x->x_gui.x_font_style == 1)
    {
        //strcpy(x->x_gui.x_font, "helvetica");
    }
    else if (x->x_gui.x_font_style == 2)
    {
        //strcpy(x->x_gui.x_font, "times");
    }
726
727
    else
    {
728
        x->x_gui.x_font_style = 0;
729
    }
730
    if (iemgui_has_rcv(x)) pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
731
732
733
    x->x_gui.x_ldx = ldx;
    x->x_gui.x_ldy = ldy;
    if(fs < 4)
734
        fs = 4;
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
735
736
737
738
739
740
741
742
743
744
    x->x_gui.x_fontsize = fs;
    //x->x_gui.x_h = iemgui_clip_size(h);
    //x->x_gui.x_w = iemgui_clip_size(w);
    mknob_check_wh(x, w, h);
    //mknob_check_width(x, w);
    mknob_check_minmax(x, min, max);
    iemgui_all_colfromload(&x->x_gui, bflcol);
    x->x_thick = 0;
    iemgui_verify_snd_ne_rcv(&x->x_gui);
    outlet_new(&x->x_gui.x_obj, &s_float);
745
	x->x_gui.x_obj.te_iemgui = 1;
746
747
748
749
750
751

    x->x_gui.x_handle = scalehandle_new((t_object *)x,
        x->x_gui.x_glist, 1, mknob__clickhook, mknob__motionhook);
    x->x_gui.x_lhandle = scalehandle_new((t_object *)x,
        x->x_gui.x_glist, 0, mknob__clickhook, mknob__motionhook);

Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
752
753
754
755
756
    return (x);
}

static void mknob_free(t_mknob *x)
{
757
    if (iemgui_has_rcv(x))
758
        pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
759
760
761
762
763
764
765
766
767
768
769
770
771
    gfxstub_deleteforkey(x);
}

extern void canvas_iemguis(t_glist *gl, t_symbol *guiobjname);

void canvas_mknob(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
{
    canvas_iemguis(gl, gensym("mknob"));
}

void mknob_setup(void)
{
    mknob_class = class_new(gensym("mknob"), (t_newmethod)mknob_new,
772
                            (t_method)mknob_free, sizeof(t_mknob), 0, A_GIMME, 0);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
773
774
775
776
777
778
779
#ifndef GGEE_mknob_COMPATIBLE
//    class_addcreator((t_newmethod)mknob_new, gensym("mknob"), A_GIMME, 0);
#endif
    class_addbang(mknob_class,mknob_bang);
    class_addfloat(mknob_class,mknob_float);
    //class_addlist(mknob_class, mknob_list);
    class_addmethod(mknob_class, (t_method)mknob_click, gensym("click"),
780
                    A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
781
    class_addmethod(mknob_class, (t_method)mknob_motion, gensym("motion"),
782
                    A_FLOAT, A_FLOAT, 0);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
    class_addmethod(mknob_class, (t_method)mknob_dialog, gensym("dialog"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_loadbang, gensym("loadbang"), 0);
    class_addmethod(mknob_class, (t_method)mknob_set, gensym("set"), A_FLOAT, 0);
    class_addmethod(mknob_class, (t_method)mknob_size, gensym("size"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_delta, gensym("delta"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_pos, gensym("pos"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_range, gensym("range"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_color, gensym("color"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_send, gensym("send"), A_DEFSYM, 0);
    class_addmethod(mknob_class, (t_method)mknob_receive, gensym("receive"), A_DEFSYM, 0);
    class_addmethod(mknob_class, (t_method)mknob_label, gensym("label"), A_DEFSYM, 0);
    class_addmethod(mknob_class, (t_method)mknob_label_pos, gensym("label_pos"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_label_font, gensym("label_font"), A_GIMME, 0);
    class_addmethod(mknob_class, (t_method)mknob_log, gensym("log"), 0);
    class_addmethod(mknob_class, (t_method)mknob_lin, gensym("lin"), 0);
    class_addmethod(mknob_class, (t_method)mknob_init, gensym("init"), A_FLOAT, 0);
    class_addmethod(mknob_class, (t_method)mknob_steady, gensym("steady"), A_FLOAT, 0);
    /*if(!iemgui_key_sym)
801
    iemgui_key_sym = gensym("#keyname");*/
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
802
803
    mknob_widgetbehavior.w_getrectfn =    mknob_getrect;
    mknob_widgetbehavior.w_displacefn =   iemgui_displace;
804
805
806
#ifdef PDL2ORK
    mknob_widgetbehavior.w_displacefnwtag =   iemgui_displace_withtag;
#endif
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
807
808
809
810
811
812
813
814
815
816
817
818
    mknob_widgetbehavior.w_selectfn =     iemgui_select;
    mknob_widgetbehavior.w_activatefn =   NULL;
    mknob_widgetbehavior.w_deletefn =     iemgui_delete;
    mknob_widgetbehavior.w_visfn =        iemgui_vis;
    mknob_widgetbehavior.w_clickfn =      mknob_newclick;
    //mknob_widgetbehavior.w_propertiesfn = mknob_properties;
    //mknob_widgetbehavior.w_savefn =       mknob_save;
    class_setwidget(mknob_class, &mknob_widgetbehavior);

    class_setsavefn(mknob_class, mknob_save);
    class_setpropertiesfn(mknob_class, mknob_properties);
    class_addmethod(canvas_class, (t_method)canvas_mknob, gensym("mknob"),
819
                    A_GIMME, A_NULL);
Ivica Ico Bukvic's avatar
Ivica Ico Bukvic committed
820
}