g_numbox.c 26.8 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
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
18
19
20
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;
21
/*static*/ t_class *my_numbox_class;
Miller Puckette's avatar
Miller Puckette committed
22
23
24

static void my_numbox_tick_reset(t_my_numbox *x)
{
25
    if(x->x_gui.x_change && x->x_gui.x_glist)
Miller Puckette's avatar
Miller Puckette committed
26
    {
27
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
    }
}

static void my_numbox_tick_wait(t_my_numbox *x)
{
    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;
}

45
int my_numbox_calc_fontwidth2(t_my_numbox *x, int w, int h, int fontsize)
Miller Puckette's avatar
Miller Puckette committed
46
{
47
    int f=31;
48
49
    if     (x->x_gui.x_font_style == 1) f = 27;
    else if(x->x_gui.x_font_style == 2) f = 25;
50
51
    return (fontsize * f * w) / 36 + (h / 2) + 4;
}
Miller Puckette's avatar
Miller Puckette committed
52

53
54
55
56
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
}

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

    sprintf(x->x_buf, "%g", f);
    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;
119
120
121
122
    if (!x->x_gui.x_changed) return;
    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
123
    {
124
125
126
127
128
129
130
131
132
133
        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;
        sys_vgui(
            ".x%lx.c itemconfigure %lxNUMBER -fill #%6.6x -text {%s}\n",
                glist_getcanvas(glist), x, IEM_GUI_COLOR_EDITED, cp);
        x->x_buf[sl] = 0;
134
    }
135
    else
Miller Puckette's avatar
Miller Puckette committed
136
    {
137
138
139
140
141
142
        char fcol[8]; sprintf(fcol, "#%6.6x",
            x->x_gui.x_change ? IEM_GUI_COLOR_EDITED : x->x_gui.x_fcol);
        my_numbox_ftoa(x);
        sys_vgui(
            ".x%lx.c itemconfigure %lxNUMBER -fill %s -text {%s} \n",
            glist_getcanvas(glist), x,
143
144
            x->x_gui.x_selected == glist_getcanvas(glist) && 
                !x->x_gui.x_change ? selection_color : fcol, x->x_buf);
145
        x->x_buf[0] = 0;
Miller Puckette's avatar
Miller Puckette committed
146
147
148
149
150
    }
}

static void my_numbox_draw_new(t_my_numbox *x, t_glist *glist)
{
151
    t_canvas *canvas=glist_getcanvas(glist);
Miller Puckette's avatar
Miller Puckette committed
152
    int half=x->x_gui.x_h/2, d=1+x->x_gui.x_h/34;
153
154
155
    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;
    char bcol[8]; sprintf(bcol, "#%6.6x", x->x_gui.x_bcol);
Ivica Bukvic's avatar
Ivica Bukvic committed
156

157
158
    sys_vgui(
        ".x%lx.c create ppolygon %d %d %d %d %d %d %d %d %d %d -stroke %s"
159
        " -fill %s -tags {%lxBASE1 x%lx text iemgui}\n",
160
        canvas, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2,
161
        x->x_hide_frame <= 1 ? "$pd_colors(iemgui_border)" : bcol,
162
        bcol, x, x);
Ivica Bukvic's avatar
Ivica Bukvic committed
163

164
165
    if (!x->x_hide_frame || x->x_hide_frame == 2)
        sys_vgui(".x%lx.c create polyline %d %d %d %d %d %d -stroke #%6.6x "
166
            "-tags {%lxBASE2 x%lx text iemgui}\n",
167
            canvas, x1, y1, x1 + half, y1 + half, x1, y2,
168
            x->x_gui.x_fcol, x, x);
169
170
    my_numbox_ftoa(x);
    sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w "
171
172
        "-font %s -fill #%6.6x -tags {%lxNUMBER x%lx noscroll text iemgui}\n",
        canvas, x1+half+2, y1+half+d, x->x_buf, iemgui_font(&x->x_gui),
173
        x->x_gui.x_fcol, x, x);
Miller Puckette's avatar
Miller Puckette committed
174
175
176
177
178
}

static void my_numbox_draw_move(t_my_numbox *x, t_glist *glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
179
180
181
182
183
184
185
186
    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;

    sys_vgui(".x%lx.c coords %lxBASE1 %d %d %d %d %d %d %d %d %d %d\n",
        canvas, x, x1, y1, x2-4, y1, x2, y1+4, x2, y2, x1, y2);
    if (x->x_hide_frame <= 1)
187
        iemgui_io_draw_move(&x->x_gui);
188
189
190
191
192
    if (!x->x_hide_frame || x->x_hide_frame == 2)
        sys_vgui(".x%lx.c coords %lxBASE2 %d %d %d %d %d %d\n",
            canvas, x, x1, y1, x1 + half, y1 + half, x1, y2);
    sys_vgui(".x%lx.c coords %lxNUMBER %d %d\n",
        canvas, x, x1+half+2, y1+half+d);
Miller Puckette's avatar
Miller Puckette committed
193
194
195
196
197
}

static void my_numbox_draw_config(t_my_numbox* x,t_glist* glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
198
    char fcol[8]; sprintf(fcol, "#%6.6x", x->x_gui.x_fcol);
199
    int issel = x->x_gui.x_selected == canvas && x->x_gui.x_glist == canvas;
200
201
    sys_vgui(".x%lx.c itemconfigure %lxNUMBER -font %s -fill %s\n",
        canvas, x, iemgui_font(&x->x_gui), issel ? selection_color : fcol);
202
    sys_vgui(".x%lx.c itemconfigure %lxBASE2 -stroke %s\n",
203
        canvas, x, issel ? selection_color : fcol);
204
    sys_vgui(".x%lx.c itemconfigure %lxBASE1 -fill #%6.6x\n", canvas,
Miller Puckette's avatar
Miller Puckette committed
205
206
207
208
209
210
             x, x->x_gui.x_bcol);
}

static void my_numbox_draw_select(t_my_numbox *x, t_glist *glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
211
    int issel = x->x_gui.x_selected == canvas && x->x_gui.x_glist == canvas;
212
    if(x->x_gui.x_selected && x->x_gui.x_change)
213
    {
214
215
216
217
        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);
218
    }
219
220
221
    char fcol[8]; sprintf(fcol, "#%6.6x", x->x_gui.x_fcol);
    char bcol[8]; sprintf(bcol, "#%6.6x", x->x_gui.x_bcol);
    sys_vgui(".x%lx.c itemconfigure %lxBASE1 -stroke %s\n", canvas, x,
222
        issel ? selection_color : x->x_hide_frame <= 1 ? "$pd_colors(iemgui_border)" : bcol);
223
224
225
226
227
    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);
    if(issel) 
228
        scalehandle_draw_select2(&x->x_gui);
229
    else
230
        scalehandle_draw_erase2(&x->x_gui);
231
232
}

233
static void my_numbox__clickhook(t_scalehandle *sh, int newstate)
234
{
Ivica Bukvic's avatar
Ivica Bukvic committed
235
    t_my_numbox *x = (t_my_numbox *)(sh->h_master);
236
    if (sh->h_dragon && newstate == 0 && sh->h_scale)
Miller Puckette's avatar
Miller Puckette committed
237
    {
Ivica Bukvic's avatar
Ivica Bukvic committed
238
239
240
241
242
243
244
245
246
247
248
249
250
251
        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
        if (sh->h_dragx || sh->h_dragy)
        {
            x->x_gui.x_fontsize = x->x_tmpfontsize;
            x->x_gui.x_w = x->x_scalewidth;
            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);
252
            scalehandle_unclick_scale(sh);
Ivica Bukvic's avatar
Ivica Bukvic committed
253
        }
Miller Puckette's avatar
Miller Puckette committed
254
    }
255
    else if (!sh->h_dragon && newstate && sh->h_scale)
256
    {
257
        scalehandle_click_scale(sh);
Ivica Bukvic's avatar
Ivica Bukvic committed
258
259
260
        x->x_scalewidth = x->x_gui.x_w;
        x->x_scaleheight = x->x_gui.x_h;
        x->x_tmpfontsize = x->x_gui.x_fontsize;
261
    }
Ivica Bukvic's avatar
Ivica Bukvic committed
262
    else if (sh->h_dragon && newstate == 0 && !sh->h_scale)
263
    {
264
        scalehandle_unclick_label(sh);
265
266
267
    }
    else if (!sh->h_dragon && newstate && !sh->h_scale)
    {
268
        scalehandle_click_label(sh);
269
    }
270
271
272
273
    sh->h_dragon = newstate;
}

static void my_numbox__motionhook(t_scalehandle *sh,
Ivica Bukvic's avatar
Ivica Bukvic committed
274
                    t_floatarg f1, t_floatarg f2)
275
{
276
    if (sh->h_dragon && sh->h_scale)
Miller Puckette's avatar
Miller Puckette committed
277
    {
Ivica Bukvic's avatar
Ivica Bukvic committed
278
279
280
281
        t_my_numbox *x = (t_my_numbox *)(sh->h_master);
        int dx = (int)f1, dy = (int)f2;

        /* first calculate y */
282
283
        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
284
285

        /* then readjust fontsize */
286
287
        x->x_tmpfontsize = maxi((newy - x->x_gui.x_obj.te_ypix) * 0.8,
            IEM_FONT_MINSIZE);
Ivica Bukvic's avatar
Ivica Bukvic committed
288
289

        int f = 31;
290
291
        if     (x->x_gui.x_font_style == 1) f = 27;
        else if(x->x_gui.x_font_style == 2) f = 25;
292
        int char_w = (x->x_tmpfontsize * f) / 36;
Ivica Bukvic's avatar
Ivica Bukvic committed
293
294

        /* get the new total width */
295
        int new_total_width = x->x_numwidth + dx;
Ivica Bukvic's avatar
Ivica Bukvic committed
296
297
298
299
300
301
302
303
304
305
306
        
        /* 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;

307
308
309
310
311
312
313
314
        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);

Ivica Bukvic's avatar
Ivica Bukvic committed
315
316
317
        int properties = gfxstub_haveproperties((void *)x);
        if (properties)
        {
318
319
320
            properties_set_field_int(properties,"dim.w_ent",x->x_scalewidth);
            properties_set_field_int(properties,"dim.h_ent",x->x_scaleheight);
            properties_set_field_int(properties,"label.fontsize_entry",x->x_tmpfontsize);
Ivica Bukvic's avatar
Ivica Bukvic committed
321
        }
322
    }
323
    scalehandle_dragon_label(sh,f1,f2);
Miller Puckette's avatar
Miller Puckette committed
324
325
326
327
}

void my_numbox_draw(t_my_numbox *x, t_glist *glist, int mode)
{
328
329
330
331
332
    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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
}

/* ------------------------ 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;
347

Ivica Bukvic's avatar
Ivica Bukvic committed
348
    iemgui_label_getrect(x->x_gui, glist, xp1, yp1, xp2, yp2);
Miller Puckette's avatar
Miller Puckette committed
349
350
351
352
353
354
355
356
357
}

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);
358
    if(x->x_gui.x_change)
Miller Puckette's avatar
Miller Puckette committed
359
    {
360
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
361
        clock_unset(x->x_clock_reset);
362
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
363
364
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);
    }
365
366
367
368
369
370
371
372
373
    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
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
}

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;
    char buf[800];
    t_symbol *srl[3];

    iemgui_properties(&x->x_gui, srl);
421
    if(x->x_gui.x_change)
Miller Puckette's avatar
Miller Puckette committed
422
    {
423
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
424
        clock_unset(x->x_clock_reset);
425
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
426
427
428
        sys_queuegui(x, x->x_gui.x_glist, my_numbox_draw_update);

    }
Miller Puckette's avatar
Miller Puckette committed
429
    sprintf(buf, "pdtk_iemgui_dialog %%s |nbx| \
430
431
432
433
434
435
436
437
438
439
440
441
        -------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);
Miller Puckette's avatar
Miller Puckette committed
442
443
444
445
446
    gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void my_numbox_bang(t_my_numbox *x)
{
447
    iemgui_out_float(&x->x_gui, 0, 0, x->x_val);
Miller Puckette's avatar
Miller Puckette committed
448
449
450
451
452
}

static void my_numbox_dialog(t_my_numbox *x, t_symbol *s, int argc,
    t_atom *argv)
{
Ivica Bukvic's avatar
Ivica Bukvic committed
453
    canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
454
455
456
457
458
459
    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
460
461
    if (argc > 17)
        x->x_hide_frame = (int)atom_getintarg(18, argc, argv);
462
    iemgui_dialog(&x->x_gui, argc, argv);
463
    x->x_numwidth = my_numbox_calc_fontwidth(x);
Miller Puckette's avatar
Miller Puckette committed
464
    my_numbox_check_minmax(x, min, max);
465
466
467
468
469
470
471
    // 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);
472
473
    if (x->x_gui.x_selected)
        iemgui_select((t_gobj *)x,x->x_gui.x_glist,1);
474
    //canvas_restore_original_position(x->x_gui.x_glist, (t_gobj *)x,"bogus",-1);
475
    scrollbar_update(x->x_gui.x_glist);
Miller Puckette's avatar
Miller Puckette committed
476
477
478
479
480
}

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

483
    if(x->x_gui.x_finemoved)
Miller Puckette's avatar
Miller Puckette committed
484
485
486
487
488
489
        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
490
491
492
493
494
495
496
    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
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
}

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)
    {
        my_numbox_click( x, (t_floatarg)xpix, (t_floatarg)ypix,
            (t_floatarg)shift, 0, (t_floatarg)alt);
        if(shift)
516
            x->x_gui.x_finemoved = 1;
Miller Puckette's avatar
Miller Puckette committed
517
        else
518
519
            x->x_gui.x_finemoved = 0;
        if(!x->x_gui.x_change)
Miller Puckette's avatar
Miller Puckette committed
520
521
        {
            clock_delay(x->x_clock_wait, 50);
522
            x->x_gui.x_change = 1;
Miller Puckette's avatar
Miller Puckette committed
523
524
525
526
527
528
            clock_delay(x->x_clock_reset, 3000);

            x->x_buf[0] = 0;
        }
        else
        {
529
            x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
530
531
            clock_unset(x->x_clock_reset);
            x->x_buf[0] = 0;
532
            x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
533
534
535
536
537
538
539
540
            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
541
542
543
544
545
546
    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);
547
    }
Miller Puckette's avatar
Miller Puckette committed
548
549
550
551
552
553
554
555
556
557
558
559
560
561
}

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;
    
}

562
563
564
565
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
566
567
    if (lh > 3.0)
        lh = 3.0;
568
    x->x_hide_frame = (int)lh;
Ivica Bukvic's avatar
Ivica Bukvic committed
569
570
    my_numbox_draw(x, x->x_gui.x_glist, 4);
    my_numbox_draw(x, x->x_gui.x_glist, 2);  
571
572
}

Miller Puckette's avatar
Miller Puckette committed
573
574
575
static void my_numbox_float(t_my_numbox *x, t_floatarg f)
{
    my_numbox_set(x, f);
576
    if(x->x_gui.x_put_in2out)
Miller Puckette's avatar
Miller Puckette committed
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
        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;
    }
595
    x->x_numwidth = my_numbox_calc_fontwidth(x);
596
    iemgui_size(&x->x_gui);
Miller Puckette's avatar
Miller Puckette committed
597
598
599
600
601
602
603
}

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
604
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
605
606
607
608
609
610
611
612
613
614
        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
615
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
616
617
618
619
620
621
622
623
624
625
626
627
        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;
}

static void my_numbox_loadbang(t_my_numbox *x)
{
628
    if(!sys_noloadbang && x->x_gui.x_loadinit)
Miller Puckette's avatar
Miller Puckette committed
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
    {
        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)
    {
644
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
645
        clock_unset(x->x_clock_reset);
646
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
647
648
649
650
651
652
653
654
655
656
        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);
657
            x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
658
659
660
661
662
663
664
665
666
667
            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;
668
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
669
670
671
672
673
674
        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;
675
        x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
676
677
678
        clock_unset(x->x_clock_reset);
        my_numbox_clip(x);
        my_numbox_bang(x);
679
        x->x_gui.x_changed = 1;
Miller Puckette's avatar
Miller Puckette committed
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
        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
699
    int lilo=0, ldx=0, ldy=-8;
700
    int fs=10;
Miller Puckette's avatar
Miller Puckette committed
701
702
703
704
705
706
707
708
709
710
711
712
713
    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))
    {
714
715
716
717
718
        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);
719
        iem_inttosymargs(&x->x_gui, atom_getintarg(5, argc, argv));
Miller Puckette's avatar
Miller Puckette committed
720
        iemgui_new_getnames(&x->x_gui, 6, argv);
721
722
        ldx = atom_getintarg(9, argc, argv);
        ldy = atom_getintarg(10, argc, argv);
723
        iem_inttofstyle(&x->x_gui, atom_getintarg(11, argc, argv));
724
725
726
727
        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
728
729
730
731
        v = atom_getfloatarg(16, argc, argv);
    }
    else iemgui_new_getnames(&x->x_gui, 6, 0);
    if((argc == 18)&&IS_A_FLOAT(argv,17))
732
        log_height = maxi(atom_getintarg(17, argc, argv),10);
Ivica Bukvic's avatar
Ivica Bukvic committed
733
    x->x_hide_frame = 0; // default behavior
734
735
    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
736
737
    x->x_gui.x_draw = (t_iemfunptr)my_numbox_draw;
    x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
738
    x->x_val = x->x_gui.x_loadinit ? v : 0.0;
Miller Puckette's avatar
Miller Puckette committed
739
740
    x->x_lin0_log1 = lilo;
    x->x_log_height = log_height;
741
742
    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
743
744
745
746
747
748
749
        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;
750
    x->x_numwidth = my_numbox_calc_fontwidth(x);
Miller Puckette's avatar
Miller Puckette committed
751
752
753
754
755
    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);
756
    x->x_gui.x_change = 0;
Miller Puckette's avatar
Miller Puckette committed
757
    outlet_new(&x->x_gui.x_obj, &s_float);
758

759
760
    x->x_gui. x_handle = scalehandle_new((t_object *)x,x->x_gui.x_glist,1,my_numbox__clickhook,my_numbox__motionhook);
    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
761
762
763
764
765
    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;
766

Miller Puckette's avatar
Miller Puckette committed
767
768
769
770
771
    return (x);
}

static void my_numbox_free(t_my_numbox *x)
{
772
    if(iemgui_has_rcv(&x->x_gui))
Miller Puckette's avatar
Miller Puckette committed
773
774
775
776
        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);
777

778
779
    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
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
}

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,
        gensym("loadbang"), 0);
    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);
803
    iemgui_class_addmethods(my_numbox_class);
Miller Puckette's avatar
Miller Puckette committed
804
805
806
807
808
809
    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);
810
    class_addmethod(my_numbox_class, (t_method)iemgui_init,
Miller Puckette's avatar
Miller Puckette committed
811
812
813
        gensym("init"), A_FLOAT, 0);
    class_addmethod(my_numbox_class, (t_method)my_numbox_log_height,
        gensym("log_height"), A_FLOAT, 0);
814
815
    class_addmethod(my_numbox_class, (t_method)my_numbox_hide_frame,
        gensym("hide_frame"), A_FLOAT, 0);
816
817

    wb_init(&my_numbox_widgetbehavior,my_numbox_getrect,my_numbox_newclick);
Miller Puckette's avatar
Miller Puckette committed
818
819
820
821
822
    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);
}