g_numbox.c 28.4 KB
Newer Older
Miller Puckette's avatar
Miller Puckette committed
1
2
3
4
5
6
7
8
9
10
11
12
13
/* 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. */

/* my_numbox.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "m_pd.h"
#include "g_canvas.h"
#include "g_all_guis.h"
#include <math.h>
14
#define IEM_GUI_COLOR_EDITED 0xff0000
Miller Puckette's avatar
Miller Puckette committed
15

16
17
18
19
20
21
#if PD_FLOATSIZE == 32
#define MY_NUMBOX_FLOAT_SPECIFIER "%.6g"
#elif PD_FLOATSIZE == 64
#define MY_NUMBOX_FLOAT_SPECIFIER "%.14lg"
#endif

22
23
extern int gfxstub_haveproperties(void *key);
static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist);
Miller Puckette's avatar
Miller Puckette committed
24
25
26
static void my_numbox_key(void *z, t_floatarg fkey);
static void my_numbox_draw_update(t_gobj *client, t_glist *glist);
t_widgetbehavior my_numbox_widgetbehavior;
27
/*static*/ t_class *my_numbox_class;
Miller Puckette's avatar
Miller Puckette committed
28
29
30

static void my_numbox_tick_reset(t_my_numbox *x)
{
31
    //printf("tick_reset\n");
32
    if(x->x_gui.x_change && x->x_gui.x_glist)
Miller Puckette's avatar
Miller Puckette committed
33
    {
34
        //printf("    success\n");
35
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
36
37
38
39
40
41
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
    }
}

static void my_numbox_tick_wait(t_my_numbox *x)
{
42
    //printf("tick_wait\n");
Miller Puckette's avatar
Miller Puckette committed
43
44
45
46
47
48
49
50
51
52
53
    sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
}

void my_numbox_clip(t_my_numbox *x)
{
    if(x->x_val < x->x_min)
        x->x_val = x->x_min;
    if(x->x_val > x->x_max)
        x->x_val = x->x_max;
}

54
int my_numbox_calc_fontwidth2(t_my_numbox *x, int w, int h, int fontsize)
Miller Puckette's avatar
Miller Puckette committed
55
{
56
    int f=31;
57
58
    if     (x->x_gui.x_font_style == 1) f = 27;
    else if(x->x_gui.x_font_style == 2) f = 25;
59
60
    return (fontsize * f * w) / 36 + (h / 2) + 4;
}
Miller Puckette's avatar
Miller Puckette committed
61

62
63
64
65
int my_numbox_calc_fontwidth(t_my_numbox *x)
{
    return my_numbox_calc_fontwidth2(x,x->x_gui.x_w,x->x_gui.x_h,
        x->x_gui.x_fontsize);
Miller Puckette's avatar
Miller Puckette committed
66
67
68
69
70
71
72
}

void my_numbox_ftoa(t_my_numbox *x)
{
    double f=x->x_val;
    int bufsize, is_exp=0, i, idecimal;

73
    sprintf(x->x_buf, MY_NUMBOX_FLOAT_SPECIFIER, f);
Miller Puckette's avatar
Miller Puckette committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
    bufsize = strlen(x->x_buf);
    if(bufsize >= 5)/* if it is in exponential mode */
    {
        i = bufsize - 4;
        if((x->x_buf[i] == 'e') || (x->x_buf[i] == 'E'))
            is_exp = 1;
    }
    if(bufsize > x->x_gui.x_w)/* if to reduce */
    {
        if(is_exp)
        {
            if(x->x_gui.x_w <= 5)
            {
                x->x_buf[0] = (f < 0.0 ? '-' : '+');
                x->x_buf[1] = 0;
            }
            i = bufsize - 4;
            for(idecimal=0; idecimal < i; idecimal++)
                if(x->x_buf[idecimal] == '.')
                    break;
            if(idecimal > (x->x_gui.x_w - 4))
            {
                x->x_buf[0] = (f < 0.0 ? '-' : '+');
                x->x_buf[1] = 0;
            }
            else
            {
                int new_exp_index=x->x_gui.x_w-4, old_exp_index=bufsize-4;

                for(i=0; i < 4; i++, new_exp_index++, old_exp_index++)
                    x->x_buf[new_exp_index] = x->x_buf[old_exp_index];
                x->x_buf[x->x_gui.x_w] = 0;
            }

        }
        else
        {
            for(idecimal=0; idecimal < bufsize; idecimal++)
                if(x->x_buf[idecimal] == '.')
                    break;
            if(idecimal > x->x_gui.x_w)
            {
                x->x_buf[0] = (f < 0.0 ? '-' : '+');
                x->x_buf[1] = 0;
            }
            else
                x->x_buf[x->x_gui.x_w] = 0;
        }
    }
}

static void my_numbox_draw_update(t_gobj *client, t_glist *glist)
{
    t_my_numbox *x = (t_my_numbox *)client;
128
129
130
131
132
133
134

    // we cannot ignore this call even if there is no change
    // since that will mess up number highlighting while editing
    // the code is left here as it is similar to other iemguis
    // but should not be used for this reason
    // if (!x->x_gui.x_changed) return;

135
136
137
    x->x_gui.x_changed = 0;
    if (!glist_isvisible(glist)) return;
    if(x->x_gui.x_change && x->x_buf[0])
Ivica Bukvic's avatar
Ivica Bukvic committed
138
    {
139
        //printf("draw_update 1\n");
140
141
142
143
144
145
        char *cp=x->x_buf;
        int sl = strlen(x->x_buf);
        x->x_buf[sl] = '>';
        x->x_buf[sl+1] = 0;
        if(sl >= x->x_gui.x_w)
            cp += sl - x->x_gui.x_w + 1;
146
147
148
149
        gui_vmess("gui_text_set", "xxs",
            glist_getcanvas(glist),
            x,
            cp);
150
        x->x_buf[sl] = 0;
151
    }
152
    else
Miller Puckette's avatar
Miller Puckette committed
153
    {
154
155
156
157
158
159
160
        my_numbox_ftoa(x); /* mmm... side-effects */
        gui_vmess("gui_text_set", "xxs",
            glist_getcanvas(glist),
            x,
            x->x_buf);
        x->x_buf[0] = 0; /* mmm... more side-effects... no clue why we'd need
                            to mutate a struct member in order to draw stuff */
Miller Puckette's avatar
Miller Puckette committed
161
162
163
164
165
    }
}

static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
{
166
    t_canvas *canvas=glist_getcanvas(glist);
167
168
    char cbuf[8];
    sprintf(cbuf, "#%6.6x", x->x_gui.x_bcol);
Miller Puckette's avatar
Miller Puckette committed
169
    int half=x->x_gui.x_h/2, d=1+x->x_gui.x_h/34;
170
171
    int x1=text_xpix(&x->x_gui.x_obj, glist), x2=x1+x->x_numwidth;
    int y1=text_ypix(&x->x_gui.x_obj, glist), y2=y1+x->x_gui.x_h;
Ivica Bukvic's avatar
Ivica Bukvic committed
172

173
    gui_vmess("gui_numbox_new", "xxsiiiii",
174
175
        canvas,
        x,
176
        cbuf,
177
178
179
180
        x1,
        y1,
        x2 - x1,
        y2 - y1,
181
        glist_istoplevel(glist));
182
183
    /* Not sure when it is necessary to hide the frame... perhaps for
       k12? */
184
    if (!x->x_hide_frame || x->x_hide_frame == 2)
185
186
187
188
189
190
    {
        //sys_vgui(".x%lx.c create polyline %d %d %d %d %d %d -stroke #%6.6x "
        //    "-tags {%lxBASE2 x%lx text iemgui}\n",
        //    canvas, x1, y1, x1 + half, y1 + half, x1, y2,
        //    x->x_gui.x_fcol, x, x);
    }
191
    my_numbox_ftoa(x);
192
193
    sprintf(cbuf, "#%6.6x", x->x_gui.x_fcol);
    gui_vmess("gui_numbox_draw_text", "xxsisiiii",
194
195
196
197
        canvas,
        x,
        x->x_buf,
        x->x_gui.x_fontsize,
198
        cbuf,
199
        x1+half+2, y1+half+d, x1, y1);
Miller Puckette's avatar
Miller Puckette committed
200
201
}

202
/* Not sure that this is needed anymore */
Miller Puckette's avatar
Miller Puckette committed
203
204
205
static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
206
207
208
209
210
    if (!glist_isvisible(canvas)) return;
    int half = x->x_gui.x_h/2, d=1+x->x_gui.x_h/34;
    int x1=text_xpix(&x->x_gui.x_obj, glist), x2=x1+x->x_numwidth;
    int y1=text_ypix(&x->x_gui.x_obj, glist), y2=y1+x->x_gui.x_h;

Jonathan Wilkes's avatar
Jonathan Wilkes committed
211
212
    iemgui_base_draw_move(&x->x_gui);

213
    if (x->x_hide_frame <= 1)
214
        iemgui_io_draw_move(&x->x_gui);
215
    if (!x->x_hide_frame || x->x_hide_frame == 2)
216
217
218
219
    {
        //sys_vgui(".x%lx.c coords %lxBASE2 %d %d %d %d %d %d\n",
        //    canvas, x, x1, y1, x1 + half, y1 + half, x1, y2);
    }
220
221
222
223
224
225
226

    gui_vmess("gui_numbox_coords", "xxii",
        canvas,
        x,
        x2 - x1,
        y2 - y1);

227
    gui_vmess("gui_numbox_update_text_position", "xxii",
228
229
230
231
        canvas,
        x,
        half + 2,
        half + d);
Miller Puckette's avatar
Miller Puckette committed
232
233
234
235
236
}

static void my_numbox_draw_config(t_my_numbox* x,t_glist* glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
237
238
239
240
    char fg[8], bg[8];
    sprintf(fg, "#%6.6x",  x->x_gui.x_fcol);
    sprintf(bg, "#%6.6x",  x->x_gui.x_bcol);
    gui_vmess("gui_numbox_update", "xxsssii",
241
242
        canvas,
        x,
243
244
245
        fg,
        bg,
        iemgui_typeface((t_iemgui *)x),
246
247
        x->x_gui.x_fontsize,
        sys_fontweight);
Miller Puckette's avatar
Miller Puckette committed
248
249
250
251
252
}

static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
253
    int issel = x->x_gui.x_selected == canvas && x->x_gui.x_glist == canvas;
254
    if(x->x_gui.x_selected && x->x_gui.x_change)
255
    {
256
257
258
259
        x->x_gui.x_change = 0;
        clock_unset(x->x_clock_reset);
        x->x_buf[0] = 0;
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
260
    }
261
262
    char fcol[8]; sprintf(fcol, "#%6.6x", x->x_gui.x_fcol);
    char bcol[8]; sprintf(bcol, "#%6.6x", x->x_gui.x_bcol);
263
264
    // The logic in these sys_vgui calls is being taken care
    // of in the gui now...
265
266
267
268
269
270
    //sys_vgui(".x%lx.c itemconfigure %lxBASE1 -stroke %s\n", canvas, x,
    //    issel ? selection_color : x->x_hide_frame <= 1 ? "$pd_colors(iemgui_border)" : bcol);
    //sys_vgui(".x%lx.c itemconfigure %lxBASE2 -stroke %s\n", canvas, x,
    //    issel ? selection_color : fcol);
    //sys_vgui(".x%lx.c itemconfigure %lxNUMBER -fill %s\n", canvas, x,
    //    issel ? selection_color : fcol);
271
    if(issel) 
272
        scalehandle_draw_select2(&x->x_gui);
273
    else
274
        scalehandle_draw_erase2(&x->x_gui);
275
276
}

277
static void my_numbox__clickhook(t_scalehandle *sh, int newstate)
278
{
Ivica Bukvic's avatar
Ivica Bukvic committed
279
    t_my_numbox *x = (t_my_numbox *)(sh->h_master);
280
    if (newstate)
Miller Puckette's avatar
Miller Puckette committed
281
    {
Ivica Bukvic's avatar
Ivica Bukvic committed
282
        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
283
284
        if (!sh->h_scale)
            scalehandle_click_label(sh);
285
    }
286
    /* not sure if we need this */
287
288
289
290
    sh->h_dragon = newstate;
}

static void my_numbox__motionhook(t_scalehandle *sh,
291
    t_floatarg mouse_x, t_floatarg mouse_y)
292
{
293
    if (sh->h_scale)
Miller Puckette's avatar
Miller Puckette committed
294
    {
Ivica Bukvic's avatar
Ivica Bukvic committed
295
        t_my_numbox *x = (t_my_numbox *)(sh->h_master);
296
297
        //int dx = (int)mouse_x - sh->h_offset_x;
        int dy = (int)mouse_y - sh->h_offset_y;
Ivica Bukvic's avatar
Ivica Bukvic committed
298
299

        /* first calculate y */
300
301
        int newy = maxi(x->x_gui.x_obj.te_ypix + x->x_gui.x_h +
            dy, x->x_gui.x_obj.te_ypix + SCALE_NUM_MINHEIGHT);
Ivica Bukvic's avatar
Ivica Bukvic committed
302
303

        /* then readjust fontsize */
304
305
        x->x_tmpfontsize = maxi((newy - x->x_gui.x_obj.te_ypix) * 0.8,
            IEM_FONT_MINSIZE);
Ivica Bukvic's avatar
Ivica Bukvic committed
306
307

        int f = 31;
308
309
        if     (x->x_gui.x_font_style == 1) f = 27;
        else if(x->x_gui.x_font_style == 2) f = 25;
310
        int char_w = (x->x_tmpfontsize * f) / 36;
Ivica Bukvic's avatar
Ivica Bukvic committed
311
312

        /* get the new total width */
313
314
315
        int new_total_width = x->x_numwidth + (int)mouse_x -
            (text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist) + x->x_numwidth);

Ivica Bukvic's avatar
Ivica Bukvic committed
316
317
318
319
320
321
322
323
324
325
        /* now figure out what does this translate into in terms of
           character length */
        int new_char_len = (new_total_width -
            ((newy - x->x_gui.x_obj.te_ypix) / 2) - 4) / char_w;
        if (new_char_len < SCALE_NUM_MINWIDTH)
            new_char_len = SCALE_NUM_MINWIDTH;

        x->x_scalewidth = new_char_len;
        x->x_scaleheight = newy - x->x_gui.x_obj.te_ypix;

326
327
328
329
330
331
332
333
        int numwidth = my_numbox_calc_fontwidth2(x,new_char_len,
            x->x_scaleheight,x->x_tmpfontsize);
        sh->h_dragx = numwidth - x->x_numwidth;
        sh->h_dragy = dy;
        //printf("dx=%-4d dy=%-4d scalewidth=%-4d scaleheight=%-4d numwidth=%-4d dragx=%-4d\n",
        //    dx,dy,x->x_scalewidth,x->x_scaleheight,numwidth,sh->h_dragx);
        scalehandle_drag_scale(sh);

334
        x->x_gui.x_fontsize = x->x_tmpfontsize;
335
        x->x_gui.x_w = new_char_len;
336
337
338
339
340
341
342
343
344
        x->x_gui.x_h = x->x_scaleheight;
        x->x_numwidth = my_numbox_calc_fontwidth(x);
        canvas_dirty(x->x_gui.x_glist, 1);

        if (glist_isvisible(x->x_gui.x_glist))
        {
            my_numbox_draw_move(x, x->x_gui.x_glist);
            my_numbox_draw_config(x, x->x_gui.x_glist);
            my_numbox_draw_update((t_gobj*)x, x->x_gui.x_glist);
345
346
347
348
349
            /* These were just a crude way to guarantee correct
               redrawing when testing, but it looks like the calls
               above take care of it. */
            //gobj_vis(x, x->x_gui.x_glist, 0);
            //gobj_vis(x, x->x_gui.x_glist, 1);
350
351
            scalehandle_unclick_scale(sh);
        }
Ivica Bukvic's avatar
Ivica Bukvic committed
352
353
354
        int properties = gfxstub_haveproperties((void *)x);
        if (properties)
        {
355
356
            properties_set_field_int(properties,"width",x->x_scalewidth);
            properties_set_field_int(properties,"height",x->x_scaleheight);
357
            properties_set_field_int(properties,"font_size",x->x_tmpfontsize);
Ivica Bukvic's avatar
Ivica Bukvic committed
358
        }
359
    }
360
    scalehandle_dragon_label(sh,mouse_x, mouse_y);
Miller Puckette's avatar
Miller Puckette committed
361
362
363
364
}

void my_numbox_draw(t_my_numbox *x, t_glist *glist, int mode)
{
365
366
367
368
369
    if(mode == IEM_GUI_DRAW_MODE_UPDATE)      sys_queuegui(x, glist, my_numbox_draw_update);
    else if(mode == IEM_GUI_DRAW_MODE_MOVE)   my_numbox_draw_move(x, glist);
    else if(mode == IEM_GUI_DRAW_MODE_NEW)    my_numbox_draw_new(x, glist);
    else if(mode == IEM_GUI_DRAW_MODE_SELECT) my_numbox_draw_select(x, glist);
    else if(mode == IEM_GUI_DRAW_MODE_CONFIG) my_numbox_draw_config(x, glist);
Miller Puckette's avatar
Miller Puckette committed
370
371
372
373
374
375
376
377
378
379
380
381
382
383
}

/* ------------------------ nbx widgetbehaviour----------------------------- */


static void my_numbox_getrect(t_gobj *z, t_glist *glist,
                              int *xp1, int *yp1, int *xp2, int *yp2)
{
    t_my_numbox* x = (t_my_numbox*)z;

    *xp1 = text_xpix(&x->x_gui.x_obj, glist);
    *yp1 = text_ypix(&x->x_gui.x_obj, glist);
    *xp2 = *xp1 + x->x_numwidth;
    *yp2 = *yp1 + x->x_gui.x_h;
Ivica Bukvic's avatar
Ivica Bukvic committed
384
    iemgui_label_getrect(x->x_gui, glist, xp1, yp1, xp2, yp2);
Miller Puckette's avatar
Miller Puckette committed
385
386
387
388
389
390
391
392
393
}

static void my_numbox_save(t_gobj *z, t_binbuf *b)
{
    t_my_numbox *x = (t_my_numbox *)z;
    int bflcol[3];
    t_symbol *srl[3];

    iemgui_save(&x->x_gui, srl, bflcol);
394
    if(x->x_gui.x_change)
Miller Puckette's avatar
Miller Puckette committed
395
    {
396
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
397
        clock_unset(x->x_clock_reset);
398
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
399
400
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
    }
401
402
403
404
405
406
407
408
409
    binbuf_addv(b, "ssiisiiffiisssiiiiiiifii;", gensym("#X"),gensym("obj"),
        (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
        gensym("nbx"), x->x_gui.x_w, x->x_gui.x_h,
        (t_float)x->x_min, (t_float)x->x_max,
        x->x_lin0_log1, iem_symargstoint(&x->x_gui),
        srl[0], srl[1], srl[2], x->x_gui.x_ldx, x->x_gui.x_ldy,
        iem_fstyletoint(&x->x_gui), x->x_gui.x_fontsize,
        bflcol[0], bflcol[1], bflcol[2],
        x->x_val, x->x_log_height, x->x_hide_frame);
Miller Puckette's avatar
Miller Puckette committed
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
}

int my_numbox_check_minmax(t_my_numbox *x, double min, double max)
{
    int ret=0;

    if(x->x_lin0_log1)
    {
        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;
        }
    }
    x->x_min = min;
    x->x_max = max;
    if(x->x_val < x->x_min)
    {
        x->x_val = x->x_min;
        ret = 1;
    }
    if(x->x_val > x->x_max)
    {
        x->x_val = x->x_max;
        ret = 1;
    }
    if(x->x_lin0_log1)
        x->x_k = exp(log(x->x_max/x->x_min)/(double)(x->x_log_height));
    else
        x->x_k = 1.0;
    return(ret);
}

static void my_numbox_properties(t_gobj *z, t_glist *owner)
{
    t_my_numbox *x = (t_my_numbox *)z;
453
    char buf[800], *gfx_tag;
Miller Puckette's avatar
Miller Puckette committed
454
455
456
    t_symbol *srl[3];

    iemgui_properties(&x->x_gui, srl);
457
    if(x->x_gui.x_change)
Miller Puckette's avatar
Miller Puckette committed
458
    {
459
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
460
        clock_unset(x->x_clock_reset);
461
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
462
463
464
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);

    }
Miller Puckette's avatar
Miller Puckette committed
465
    sprintf(buf, "pdtk_iemgui_dialog %%s |nbx| \
466
467
468
469
470
471
472
473
474
475
476
477
        -------dimensions(digits)(pix):------- %d %d width: %d %d height: \
        -----------output-range:----------- %g min: %g max: %d \
        %d lin log %d %d log-height: %d {%s} {%s} {%s} %d %d %d %d %d %d %d\n",
        x->x_gui.x_w, 1, x->x_gui.x_h, 8, x->x_min, x->x_max,
        x->x_hide_frame, /*EXCEPTION: x_hide_frame instead of schedule*/
        x->x_lin0_log1, x->x_gui.x_loadinit, -1,
        x->x_log_height, /*no multi, but iem-characteristic*/
        srl[0]->s_name, srl[1]->s_name, srl[2]->s_name,
        x->x_gui.x_ldx, x->x_gui.x_ldy,
        x->x_gui.x_font_style, x->x_gui.x_fontsize,
        0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol,
        0xffffff & x->x_gui.x_lcol);
478
479
480
481
482
483
484
485
    //gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
    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("nbx");
    gui_s("width");  gui_i(x->x_gui.x_w);
    gui_s("height"); gui_i(x->x_gui.x_h);
486
487
488
489
    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);
    gui_s("log_height"); gui_i(x->x_log_height);
490
    gui_s("init"); gui_i(x->x_gui.x_loadinit);
491
492
    gui_s("send_symbol");      gui_s(srl[0]->s_name);
    gui_s("receive_symbol");   gui_s(srl[1]->s_name);
493
    gui_s("label");            gui_s(srl[2]->s_name);
494
495
496
497
498
499
500
501
    gui_s("x_offset");         gui_i(x->x_gui.x_ldx);
    gui_s("y_offset");         gui_i(x->x_gui.x_ldy);
    gui_s("font_style");       gui_i(x->x_gui.x_font_style);
    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_s("hide_frame");       gui_i(x->x_hide_frame);
502
503
    gui_end_array();
    gui_end_vmess();
Miller Puckette's avatar
Miller Puckette committed
504
505
506
507
}

static void my_numbox_bang(t_my_numbox *x)
{
508
    iemgui_out_float(&x->x_gui, 0, 0, x->x_val);
Miller Puckette's avatar
Miller Puckette committed
509
510
511
512
513
}

static void my_numbox_dialog(t_my_numbox *x, t_symbol *s, int argc,
    t_atom *argv)
{
514
515
    if (atom_getintarg(19, argc, argv))
        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
516
517
518
519
520
521
    x->x_gui.x_w = maxi(atom_getintarg(0, argc, argv),1);
    x->x_gui.x_h = maxi(atom_getintarg(1, argc, argv),8);
    double min = atom_getfloatarg(2, argc, argv);
    double max = atom_getfloatarg(3, argc, argv);
    x->x_lin0_log1 = !!atom_getintarg(4, argc, argv);
    x->x_log_height = maxi(atom_getintarg(6, argc, argv),10);
Ivica Bukvic's avatar
Ivica Bukvic committed
522
523
    if (argc > 17)
        x->x_hide_frame = (int)atom_getintarg(18, argc, argv);
524
    iemgui_dialog(&x->x_gui, argc, argv);
525
    x->x_numwidth = my_numbox_calc_fontwidth(x);
526

Miller Puckette's avatar
Miller Puckette committed
527
    my_numbox_check_minmax(x, min, max);
528
529
530
531
532
533
534
    // normally, you'd do move+config, but here you have to do erase+new
    // because iemgui_draw_io does not support changes to x_hide_frame.
    iemgui_draw_erase(&x->x_gui);
    iemgui_draw_new(&x->x_gui);
    //iemgui_draw_move(&x->x_gui);
    //iemgui_draw_config(&x->x_gui);
    scalehandle_draw(&x->x_gui);
535
536
    if (x->x_gui.x_selected)
        iemgui_select((t_gobj *)x,x->x_gui.x_glist,1);
537
    //canvas_restore_original_position(x->x_gui.x_glist, (t_gobj *)x,"bogus",-1);
538
    scrollbar_update(x->x_gui.x_glist);
Miller Puckette's avatar
Miller Puckette committed
539
540
541
542
543
}

static void my_numbox_motion(t_my_numbox *x, t_floatarg dx, t_floatarg dy)
{
    double k2=1.0;
544
    int old = x->x_val;
Miller Puckette's avatar
Miller Puckette committed
545

546
    if(x->x_gui.x_finemoved)
Miller Puckette's avatar
Miller Puckette committed
547
548
549
550
551
552
        k2 = 0.01;
    if(x->x_lin0_log1)
        x->x_val *= pow(x->x_k, -k2*dy);
    else
        x->x_val -= k2*dy;
    my_numbox_clip(x);
Ivica Bukvic's avatar
Ivica Bukvic committed
553
554
555
556
557
558
559
    if (old != x->x_val)
    {
        x->x_gui.x_changed = 1;
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
        my_numbox_bang(x);
    }
    clock_unset(x->x_clock_reset);
Miller Puckette's avatar
Miller Puckette committed
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
}

static void my_numbox_click(t_my_numbox *x, t_floatarg xpos, t_floatarg ypos,
                            t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
    glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g,
        (t_glistmotionfn)my_numbox_motion, my_numbox_key, xpos, ypos);
}

static int my_numbox_newclick(t_gobj *z, struct _glist *glist,
    int xpix, int ypix, int shift, int alt, int dbl, int doit)
{
    t_my_numbox* x = (t_my_numbox *)z;

    if(doit)
    {
576
        //printf("newclick doit\n");
Miller Puckette's avatar
Miller Puckette committed
577
578
579
        my_numbox_click( x, (t_floatarg)xpix, (t_floatarg)ypix,
            (t_floatarg)shift, 0, (t_floatarg)alt);
        if(shift)
580
            x->x_gui.x_finemoved = 1;
Miller Puckette's avatar
Miller Puckette committed
581
        else
582
583
            x->x_gui.x_finemoved = 0;
        if(!x->x_gui.x_change)
Miller Puckette's avatar
Miller Puckette committed
584
        {
585
            //printf("    change=0\n");
Miller Puckette's avatar
Miller Puckette committed
586
            clock_delay(x->x_clock_wait, 50);
587
            x->x_gui.x_change = 1;
Miller Puckette's avatar
Miller Puckette committed
588
589
590
591
592
593
            clock_delay(x->x_clock_reset, 3000);

            x->x_buf[0] = 0;
        }
        else
        {
594
            //printf("    change=1\n");
595
            x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
596
597
            clock_unset(x->x_clock_reset);
            x->x_buf[0] = 0;
598
            x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
599
600
601
602
603
604
605
606
            sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
        }
    }
    return (1);
}

static void my_numbox_set(t_my_numbox *x, t_floatarg f)
{
Ivica Bukvic's avatar
Ivica Bukvic committed
607
608
609
610
611
612
    if (x->x_val != f)
    {
        x->x_val = f;
        my_numbox_clip(x);
        x->x_gui.x_changed = 1;
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
613
    }
Miller Puckette's avatar
Miller Puckette committed
614
615
616
617
618
619
620
621
622
623
624
625
626
}

static void my_numbox_log_height(t_my_numbox *x, t_floatarg lh)
{
    if(lh < 10.0)
        lh = 10.0;
    x->x_log_height = (int)lh;
    if(x->x_lin0_log1)
        x->x_k = exp(log(x->x_max/x->x_min)/(double)(x->x_log_height));
    else
        x->x_k = 1.0;
}

627
628
629
630
static void my_numbox_hide_frame(t_my_numbox *x, t_floatarg lh)
{
    if(lh < 0.0)
        lh = 0.0;
Ivica Bukvic's avatar
Ivica Bukvic committed
631
632
    if (lh > 3.0)
        lh = 3.0;
633
    x->x_hide_frame = (int)lh;
Ivica Bukvic's avatar
Ivica Bukvic committed
634
635
    my_numbox_draw(x, x->x_gui.x_glist, 4);
    my_numbox_draw(x, x->x_gui.x_glist, 2);  
636
637
}

Miller Puckette's avatar
Miller Puckette committed
638
639
640
static void my_numbox_float(t_my_numbox *x, t_floatarg f)
{
    my_numbox_set(x, f);
641
    if(x->x_gui.x_put_in2out)
Miller Puckette's avatar
Miller Puckette committed
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
        my_numbox_bang(x);
}

static void my_numbox_size(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{
    int h, w;

    w = (int)atom_getintarg(0, ac, av);
    if(w < 1)
        w = 1;
    x->x_gui.x_w = w;
    if(ac > 1)
    {
        h = (int)atom_getintarg(1, ac, av);
        if(h < 8)
            h = 8;
        x->x_gui.x_h = h;
    }
660
    x->x_numwidth = my_numbox_calc_fontwidth(x);
661
    iemgui_size(&x->x_gui);
Miller Puckette's avatar
Miller Puckette committed
662
663
664
665
666
667
668
}

static void my_numbox_range(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{
    if(my_numbox_check_minmax(x, (double)atom_getfloatarg(0, ac, av),
                              (double)atom_getfloatarg(1, ac, av)))
    {
Ivica Bukvic's avatar
Ivica Bukvic committed
669
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
670
671
672
673
674
675
676
677
678
679
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
        /*my_numbox_bang(x);*/
    }
}

static void my_numbox_log(t_my_numbox *x)
{
    x->x_lin0_log1 = 1;
    if(my_numbox_check_minmax(x, x->x_min, x->x_max))
    {
Ivica Bukvic's avatar
Ivica Bukvic committed
680
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
681
682
683
684
685
686
687
688
689
690
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
        /*my_numbox_bang(x);*/
    }
}

static void my_numbox_lin(t_my_numbox *x)
{
    x->x_lin0_log1 = 0;
}

691
static void my_numbox_loadbang(t_my_numbox *x, t_floatarg action)
Miller Puckette's avatar
Miller Puckette committed
692
{
693
    if (action == LB_LOAD && x->x_gui.x_loadinit)
Miller Puckette's avatar
Miller Puckette committed
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
    {
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
        my_numbox_bang(x);
    }
}

static void my_numbox_key(void *z, t_floatarg fkey)
{
    t_my_numbox *x = z;
    char c=fkey;
    char buf[3];
    buf[1] = 0;

    if (c == 0)
    {
709
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
710
        clock_unset(x->x_clock_reset);
711
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
712
713
714
715
716
717
718
719
720
721
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
        return;
    }
    if(((c>='0')&&(c<='9'))||(c=='.')||(c=='-')||
        (c=='e')||(c=='+')||(c=='E'))
    {
        if(strlen(x->x_buf) < (IEMGUI_MAX_NUM_LEN-2))
        {
            buf[0] = c;
            strcat(x->x_buf, buf);
722
            x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
723
724
725
726
727
728
729
730
731
732
            sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
        }
    }
    else if((c=='\b')||(c==127))
    {
        int sl=strlen(x->x_buf)-1;

        if(sl < 0)
            sl = 0;
        x->x_buf[sl] = 0;
733
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
734
735
736
737
738
739
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
    }
    else if((c=='\n')||(c==13))
    {
        x->x_val = atof(x->x_buf);
        x->x_buf[0] = 0;
740
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
741
742
743
        clock_unset(x->x_clock_reset);
        my_numbox_clip(x);
        my_numbox_bang(x);
744
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
    }
    clock_delay(x->x_clock_reset, 3000);
}

static void my_numbox_list(t_my_numbox *x, t_symbol *s, int ac, t_atom *av)
{
    if (IS_A_FLOAT(av,0))
    {
        my_numbox_set(x, atom_getfloatarg(0, ac, av));
        my_numbox_bang(x);
    }
}

static void *my_numbox_new(t_symbol *s, int argc, t_atom *argv)
{
    t_my_numbox *x = (t_my_numbox *)pd_new(my_numbox_class);
    int bflcol[]={-262144, -1, -1};
    int w=5, h=14;
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
764
    int lilo=0, ldx=0, ldy=-8;
765
    int fs=10;
Miller Puckette's avatar
Miller Puckette committed
766
767
768
769
770
771
772
773
774
775
776
777
778
    int log_height=256;
    double min=-1.0e+37, max=1.0e+37,v=0.0;

    if((argc >= 17)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
       &&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))
    {
779
780
781
782
783
        w = maxi(atom_getintarg(0, argc, argv),1);
        h = maxi(atom_getintarg(1, argc, argv),8);
        min = atom_getfloatarg(2, argc, argv);
        max = atom_getfloatarg(3, argc, argv);
        lilo = !!atom_getintarg(4, argc, argv);
784
        iem_inttosymargs(&x->x_gui, atom_getintarg(5, argc, argv));
Miller Puckette's avatar
Miller Puckette committed
785
        iemgui_new_getnames(&x->x_gui, 6, argv);
786
787
        ldx = atom_getintarg(9, argc, argv);
        ldy = atom_getintarg(10, argc, argv);
788
        iem_inttofstyle(&x->x_gui, atom_getintarg(11, argc, argv));
789
790
791
792
        fs = maxi(atom_getintarg(12, argc, argv),4);
        bflcol[0] = atom_getintarg(13, argc, argv);
        bflcol[1] = atom_getintarg(14, argc, argv);
        bflcol[2] = atom_getintarg(15, argc, argv);
Miller Puckette's avatar
Miller Puckette committed
793
794
795
796
        v = atom_getfloatarg(16, argc, argv);
    }
    else iemgui_new_getnames(&x->x_gui, 6, 0);
    if((argc == 18)&&IS_A_FLOAT(argv,17))
797
        log_height = maxi(atom_getintarg(17, argc, argv),10);
Ivica Bukvic's avatar
Ivica Bukvic committed
798
    x->x_hide_frame = 0; // default behavior
799
800
    if((argc == 19)&&IS_A_FLOAT(argv,18))
        x->x_hide_frame = (int)atom_getintarg(18, argc, argv);
Miller Puckette's avatar
Miller Puckette committed
801
802
    x->x_gui.x_draw = (t_iemfunptr)my_numbox_draw;
    x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
803
    x->x_val = x->x_gui.x_loadinit ? v : 0.0;
Miller Puckette's avatar
Miller Puckette committed
804
805
    x->x_lin0_log1 = lilo;
    x->x_log_height = log_height;
806
807
    if (x->x_gui.x_font_style<0 || x->x_gui.x_font_style>2) x->x_gui.x_font_style=0;
    if (iemgui_has_rcv(&x->x_gui))
Miller Puckette's avatar
Miller Puckette committed
808
809
810
811
812
813
814
        pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
    x->x_gui.x_ldx = ldx;
    x->x_gui.x_ldy = ldy;
    x->x_gui.x_fontsize = fs;
    x->x_gui.x_w = w;
    x->x_gui.x_h = h;
    x->x_buf[0] = 0;
815
    x->x_numwidth = my_numbox_calc_fontwidth(x);
Miller Puckette's avatar
Miller Puckette committed
816
817
818
819
820
    my_numbox_check_minmax(x, min, max);
    iemgui_all_colfromload(&x->x_gui, bflcol);
    iemgui_verify_snd_ne_rcv(&x->x_gui);
    x->x_clock_reset = clock_new(x, (t_method)my_numbox_tick_reset);
    x->x_clock_wait = clock_new(x, (t_method)my_numbox_tick_wait);
821
    x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
822
    outlet_new(&x->x_gui.x_obj, &s_float);
823

824
    x->x_gui.x_handle = scalehandle_new((t_object *)x,x->x_gui.x_glist,1,my_numbox__clickhook,my_numbox__motionhook);
825
    x->x_gui.x_lhandle = scalehandle_new((t_object *)x,x->x_gui.x_glist,0,my_numbox__clickhook,my_numbox__motionhook);
Ivica Bukvic's avatar
Ivica Bukvic committed
826
827
828
829
830
    x->x_scalewidth = 0;
    x->x_scaleheight = 0;
    x->x_tmpfontsize = 0;
    x->x_gui.x_obj.te_iemgui = 1;
    x->x_gui.x_changed = 0;
831

832
    x->x_gui.legacy_x = 0;
833
    x->x_gui.legacy_y = 1;
834

Miller Puckette's avatar
Miller Puckette committed
835
836
837
838
839
    return (x);
}

static void my_numbox_free(t_my_numbox *x)
{
840
    if(iemgui_has_rcv(&x->x_gui))
Miller Puckette's avatar
Miller Puckette committed
841
842
843
844
        pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
    clock_free(x->x_clock_reset);
    clock_free(x->x_clock_wait);
    gfxstub_deleteforkey(x);
845

846
847
    if (x->x_gui. x_handle) scalehandle_free(x->x_gui. x_handle);
    if (x->x_gui.x_lhandle) scalehandle_free(x->x_gui.x_lhandle);
Miller Puckette's avatar
Miller Puckette committed
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
}

void g_numbox_setup(void)
{
    my_numbox_class = class_new(gensym("nbx"), (t_newmethod)my_numbox_new,
        (t_method)my_numbox_free, sizeof(t_my_numbox), 0, A_GIMME, 0);
    class_addcreator((t_newmethod)my_numbox_new, gensym("my_numbox"),
        A_GIMME, 0);
    class_addbang(my_numbox_class,my_numbox_bang);
    class_addfloat(my_numbox_class,my_numbox_float);
    class_addlist(my_numbox_class, my_numbox_list);
    class_addmethod(my_numbox_class, (t_method)my_numbox_click,
        gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_motion,
        gensym("motion"), A_FLOAT, A_FLOAT, 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_dialog,
        gensym("dialog"), A_GIMME, 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_loadbang,
866
        gensym("loadbang"), A_DEFFLOAT, 0);
Miller Puckette's avatar
Miller Puckette committed
867
868
869
870
    class_addmethod(my_numbox_class, (t_method)my_numbox_set,
        gensym("set"), A_FLOAT, 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_size,
        gensym("size"), A_GIMME, 0);
871
    iemgui_class_addmethods(my_numbox_class);
Miller Puckette's avatar
Miller Puckette committed
872
873
874
875
876
877
    class_addmethod(my_numbox_class, (t_method)my_numbox_range,
        gensym("range"), A_GIMME, 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_log,
        gensym("log"), 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_lin,
        gensym("lin"), 0);
878
    class_addmethod(my_numbox_class, (t_method)iemgui_init,
Miller Puckette's avatar
Miller Puckette committed
879
880
881
        gensym("init"), A_FLOAT, 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_log_height,
        gensym("log_height"), A_FLOAT, 0);
882
883
    class_addmethod(my_numbox_class, (t_method)my_numbox_hide_frame,
        gensym("hide_frame"), A_FLOAT, 0);
884
885

    wb_init(&my_numbox_widgetbehavior,my_numbox_getrect,my_numbox_newclick);
Miller Puckette's avatar
Miller Puckette committed
886
887
888
889
890
    class_setwidget(my_numbox_class, &my_numbox_widgetbehavior);
    class_sethelpsymbol(my_numbox_class, gensym("numbox2"));
    class_setsavefn(my_numbox_class, my_numbox_save);
    class_setpropertiesfn(my_numbox_class, my_numbox_properties);
}