g_all_guis.c 41.4 KB
Newer Older
Miller Puckette's avatar
Miller Puckette committed
1
2
3
4
5
6
7
/* 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. */

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

Hans-Christoph Steiner's avatar
Hans-Christoph Steiner committed
8
#include "config.h"
Miller Puckette's avatar
Miller Puckette committed
9
10
11
12
13
14
15

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "m_pd.h"
#include "g_canvas.h"
16
#include "m_imp.h"
Miller Puckette's avatar
Miller Puckette committed
17
18
19
#include "g_all_guis.h"
#include <math.h>

20
t_symbol *s_empty;
21
t_class *scalehandle_class;
22

23
24
25
26
int iemgui_color_hex[] = {
    0xfcfcfc, 0xa0a0a0, 0x404040, 0xfce0e0, 0xfce0c0, 0xfcfcc8, 0xd8fcd8, 0xd8fcfc, 0xdce4fc, 0xf8d8fc,
    0xe0e0e0, 0x7c7c7c, 0x202020, 0xfc2828, 0xfcac44, 0xe8e828, 0x14e814, 0x28f4f4, 0x3c50fc, 0xf430f0,
    0xbcbcbc, 0x606060, 0x000000, 0x8c0808, 0x583000, 0x782814, 0x285014, 0x004450, 0x001488, 0x580050
Miller Puckette's avatar
Miller Puckette committed
27
28
};

29
30
int iemgui_clip_size(int size) {return maxi(size,IEM_GUI_MINSIZE);}
int iemgui_clip_font(int size) {return maxi(size,IEM_FONT_MINSIZE);}
31
static void scalehandle_check_and_redraw(t_iemgui *x);
Miller Puckette's avatar
Miller Puckette committed
32

33
34
35
36
37
38
39
40
/* helper function to negate legacy draw offset for labels
*/
void iemgui_getrect_legacy_label(t_iemgui *x, int *xp1, int *yp1)
{
    *xp1 -= x->legacy_x;
    *yp1 -= x->legacy_y;
}

41
static int iemgui_modulo_color(int col)
Miller Puckette's avatar
Miller Puckette committed
42
{
43
    const int IEM_GUI_MAX_COLOR = 30;
44
45
46
    col %= IEM_GUI_MAX_COLOR;
    if (col<0) col += IEM_GUI_MAX_COLOR;
    return col;
Miller Puckette's avatar
Miller Puckette committed
47
48
49
50
51
52
53
54
55
}

t_symbol *iemgui_dollar2raute(t_symbol *s)
{
    char buf[MAXPDSTRING+1], *s1, *s2;
    if (strlen(s->s_name) >= MAXPDSTRING)
        return (s);
    for (s1 = s->s_name, s2 = buf; ; s1++, s2++)
    {
56
        if (*s1 == '$' && *s1 && isdigit(s1[1]))
Miller Puckette's avatar
Miller Puckette committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
            *s2 = '#';
        else if (!(*s2 = *s1))
            break;
    }
    return(gensym(buf));
}

t_symbol *iemgui_raute2dollar(t_symbol *s)
{
    char buf[MAXPDSTRING+1], *s1, *s2;
    if (strlen(s->s_name) >= MAXPDSTRING)
        return (s);
    for (s1 = s->s_name, s2 = buf; ; s1++, s2++)
    {
71
        if (*s1 == '#' && *s1 && isdigit(s1[1]))
Miller Puckette's avatar
Miller Puckette committed
72
73
74
75
76
77
78
            *s2 = '$';
        else if (!(*s2 = *s1))
            break;
    }
    return(gensym(buf));
}

79
void iemgui_verify_snd_ne_rcv(t_iemgui *x)
Miller Puckette's avatar
Miller Puckette committed
80
{
81
82
    x->x_put_in2out = 
        !(iemgui_has_snd(x) && iemgui_has_rcv(x) && x->x_snd==x->x_rcv);
Miller Puckette's avatar
Miller Puckette committed
83
84
}

85
t_symbol *iemgui_getfloatsym(t_atom *a)
Miller Puckette's avatar
Miller Puckette committed
86
{
87
88
89
90
91
    if (IS_A_SYMBOL(a,0)) return (atom_getsymbol(a));
    if (IS_A_FLOAT(a,0)) {
        char str[40];
        sprintf(str, "%d", (int)atom_getint(a));
        return gensym(str);
Miller Puckette's avatar
Miller Puckette committed
92
    }
93
94
95
96
97
98
    return s_empty;
}
t_symbol *iemgui_getfloatsymarg(int i, int argc, t_atom *argv)
{
    if (i>=0 && i<argc) return iemgui_getfloatsym(argv+i);
    return s_empty;
Miller Puckette's avatar
Miller Puckette committed
99
100
}

101
void iemgui_new_getnames(t_iemgui *x, int indx, t_atom *argv)
Miller Puckette's avatar
Miller Puckette committed
102
103
104
{
    if (argv)
    {
105
106
107
        x->x_snd = iemgui_getfloatsym(argv+indx+0);
        x->x_rcv = iemgui_getfloatsym(argv+indx+1);
        x->x_lab = iemgui_getfloatsym(argv+indx+2);
Miller Puckette's avatar
Miller Puckette committed
108
    }
109
110
111
112
    else x->x_snd = x->x_rcv = x->x_lab = s_empty;
    x->x_snd_unexpanded = x->x_rcv_unexpanded = x->x_lab_unexpanded = 0;
    x->x_binbufindex = indx;
    x->x_labelbindex = indx + 3;
Miller Puckette's avatar
Miller Puckette committed
113
114
}

115
116
117
118
/* initialize a single symbol in unexpanded form.  We reach into the
   binbuf to grab them; if there's nothing there, set it to the
   fallback; if still nothing, set to "empty". */
static void iemgui_init_sym2dollararg(t_iemgui *x, t_symbol **symp,
Miller Puckette's avatar
Miller Puckette committed
119
120
121
122
    int indx, t_symbol *fallback)
{
    if (!*symp)
    {
123
        t_binbuf *b = x->x_obj.ob_binbuf;
Miller Puckette's avatar
Miller Puckette committed
124
125
126
127
128
129
130
131
        if (binbuf_getnatom(b) > indx)
        {
            char buf[80];
            atom_string(binbuf_getvec(b) + indx, buf, 80);
            *symp = gensym(buf);
        }
        else if (fallback)
            *symp = fallback;
132
        else *symp = s_empty;
Miller Puckette's avatar
Miller Puckette committed
133
134
135
    }
}

136
/* get the unexpanded versions of the symbols; initialize them if necessary. */
137
void iemgui_all_sym2dollararg(t_iemgui *x, t_symbol **srlsym)
Miller Puckette's avatar
Miller Puckette committed
138
{
139
140
141
142
143
144
    iemgui_init_sym2dollararg(x, &x->x_snd_unexpanded, x->x_binbufindex+1, x->x_snd);
    iemgui_init_sym2dollararg(x, &x->x_rcv_unexpanded, x->x_binbufindex+2, x->x_rcv);
    iemgui_init_sym2dollararg(x, &x->x_lab_unexpanded, x->x_labelbindex, x->x_lab);
    srlsym[0] = x->x_snd_unexpanded;
    srlsym[1] = x->x_rcv_unexpanded;
    srlsym[2] = x->x_lab_unexpanded;
Miller Puckette's avatar
Miller Puckette committed
145
146
}

147
148
149
static int col2save(int col) {
    return -1-(((0xfc0000 & col) >> 6)|((0xfc00 & col) >> 4)|((0xfc & col) >> 2));
}
150
void iemgui_all_col2save(t_iemgui *x, int *bflcol)
Miller Puckette's avatar
Miller Puckette committed
151
{
152
153
154
    bflcol[0] = col2save(x->x_bcol);
    bflcol[1] = col2save(x->x_fcol);
    bflcol[2] = col2save(x->x_lcol);
Miller Puckette's avatar
Miller Puckette committed
155
156
}

157
158
static int colfromload(int col) {
    if(col)
Miller Puckette's avatar
Miller Puckette committed
159
    {
160
161
        col = -1-col;
        return ((col & 0x3f000) << 6)|((col & 0xfc0) << 4)|((col & 0x3f) << 2);
Miller Puckette's avatar
Miller Puckette committed
162
163
    }
    else
164
165
        return iemgui_color_hex[iemgui_modulo_color(col)];
}
166
void iemgui_all_colfromload(t_iemgui *x, int *bflcol)
167
{
168
169
170
    x->x_bcol = colfromload(bflcol[0]);
    x->x_fcol = colfromload(bflcol[1]);
    x->x_lcol = colfromload(bflcol[2]);
Miller Puckette's avatar
Miller Puckette committed
171
172
}

173
static int iemgui_compatible_col(int i)
Miller Puckette's avatar
Miller Puckette committed
174
175
{
    if(i >= 0)
176
177
        return(iemgui_color_hex[(iemgui_modulo_color(i))]);
    return((-1-i)&0xffffff);
Miller Puckette's avatar
Miller Puckette committed
178
179
180
181
182
183
184
185
186
}

void iemgui_all_raute2dollar(t_symbol **srlsym)
{
    srlsym[0] = iemgui_raute2dollar(srlsym[0]);
    srlsym[1] = iemgui_raute2dollar(srlsym[1]);
    srlsym[2] = iemgui_raute2dollar(srlsym[2]);
}

187
void iemgui_send(t_iemgui *x, t_symbol *s)
Miller Puckette's avatar
Miller Puckette committed
188
189
{
    t_symbol *snd;
190
    if (s == &s_) s = s_empty; //tb: fix for empty label
191
192
193
    int oldsndrcvable=0;
    if(iemgui_has_rcv(x)) oldsndrcvable += IEM_GUI_OLD_RCV_FLAG;
    if(iemgui_has_snd(x)) oldsndrcvable += IEM_GUI_OLD_SND_FLAG;
Miller Puckette's avatar
Miller Puckette committed
194
195

    snd = iemgui_raute2dollar(s);
196
197
198
    x->x_snd_unexpanded = snd;
    x->x_snd = snd = canvas_realizedollar(x->x_glist, snd);
    iemgui_verify_snd_ne_rcv(x);
199
    iemgui_draw_io(x, oldsndrcvable);
Miller Puckette's avatar
Miller Puckette committed
200
201
}

202
void iemgui_receive(t_iemgui *x, t_symbol *s)
Miller Puckette's avatar
Miller Puckette committed
203
204
{
    t_symbol *rcv;
205
    if (s == &s_) s = s_empty; //tb: fix for empty label
206
207
208
    int oldsndrcvable=0;
    if(iemgui_has_rcv(x)) oldsndrcvable += IEM_GUI_OLD_RCV_FLAG;
    if(iemgui_has_snd(x)) oldsndrcvable += IEM_GUI_OLD_SND_FLAG;
Miller Puckette's avatar
Miller Puckette committed
209
210

    rcv = iemgui_raute2dollar(s);
211
212
    x->x_rcv_unexpanded = rcv;
    rcv = canvas_realizedollar(x->x_glist, rcv);
213
    if(s!=s_empty)
Miller Puckette's avatar
Miller Puckette committed
214
    {
215
        if(rcv!=x->x_rcv)
Miller Puckette's avatar
Miller Puckette committed
216
        {
217
218
219
220
            if(iemgui_has_rcv(x))
                pd_unbind((t_pd *)x, x->x_rcv);
            x->x_rcv = rcv;
            pd_bind((t_pd *)x, x->x_rcv);
Miller Puckette's avatar
Miller Puckette committed
221
222
        }
    }
223
    else if(s==s_empty && iemgui_has_rcv(x))
Miller Puckette's avatar
Miller Puckette committed
224
    {
225
226
        pd_unbind((t_pd *)x, x->x_rcv);
        x->x_rcv = rcv;
Miller Puckette's avatar
Miller Puckette committed
227
    }
228
    iemgui_verify_snd_ne_rcv(x);
229
    iemgui_draw_io(x, oldsndrcvable);
Miller Puckette's avatar
Miller Puckette committed
230
231
}

232
void iemgui_label(t_iemgui *x, t_symbol *s)
Miller Puckette's avatar
Miller Puckette committed
233
{
234
    t_symbol *old;
235
    if (s == &s_) s = s_empty; //tb: fix for empty label
236
    old = x->x_lab;
237
238
239
    t_symbol *lab = iemgui_raute2dollar(s);
    x->x_lab_unexpanded = lab;
    x->x_lab = lab = canvas_realizedollar(x->x_glist, lab);
Miller Puckette's avatar
Miller Puckette committed
240

241
    if (glist_isvisible(x->x_glist) && lab != old)
242
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_CONFIG);
Miller Puckette's avatar
Miller Puckette committed
243
244
}

245
void iemgui_label_pos(t_iemgui *x, t_symbol *s, int ac, t_atom *av)
Miller Puckette's avatar
Miller Puckette committed
246
{
247
248
    x->x_ldx = atom_getintarg(0, ac, av);
    x->x_ldy = atom_getintarg(1, ac, av);
249
    if(glist_isvisible(x->x_glist))
250
    {
251
252
253
254
        int x1 = x->x_ldx;
        int y1 = x->x_ldy;
        //iemgui_getrect_legacy_label(x, &x1, &y1);

255
256
257
        gui_vmess("gui_iemgui_label_coords", "xxii",
            glist_getcanvas(x->x_glist),
            x,
258
259
            x1,
            y1);
260
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_CONFIG);
261
    }
Miller Puckette's avatar
Miller Puckette committed
262
263
}

264
void iemgui_label_font(t_iemgui *x, t_symbol *s, int ac, t_atom *av)
Miller Puckette's avatar
Miller Puckette committed
265
{
266
    int f = atom_getintarg(0, ac, av);
267
268
    if (f<0 || f>2) f=0;
    x->x_font_style = f;
269
    x->x_fontsize = maxi(atom_getintarg(1, ac, av),4);
270
    if(glist_isvisible(x->x_glist))
271
    {
272
        gui_vmess("gui_iemgui_label_font", "xxssi",
273
274
            glist_getcanvas(x->x_glist),
            x,
275
276
277
            iemgui_typeface(x),
            sys_fontweight,
            x->x_fontsize);
278
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_CONFIG);
279
    }
280
281
282
283
284
285
}

//Sans: 84 x 10 (14) -> 6 x 10 -> 1.0
//Helvetica: 70 x 10 (14) -> 5 x 10 -> 0.83333
//Times: 61 x 10 (14) -> 4.357 x 10 -> 0.72619; 0.735 appears to work better

286
287
288
289
290
291
// We use this global var to check when getrect should report label:
// It should report it when drawing inside gop to see if we truly fit.
// Otherwise we should not report it while inside gop to avoid label being
// misinterpreted as part of the "hot" area of a widget (e.g. toggle)
extern int gop_redraw;

292
293
294
295
void iemgui_label_getrect(t_iemgui x_gui, t_glist *x,
    int *xp1, int *yp1, int *xp2, int *yp2)
{
    //fprintf(stderr,"gop_redraw = %d\n", gop_redraw);
296
    if (!gop_redraw || sys_legacy)
297
298
    {
        //fprintf(stderr,"ignoring label\n");
299
        return;
300
301
302
    }

    t_float width_multiplier;
303
    int label_length;
304
305
306
307
    int label_x1;
    int label_y1;
    int label_x2;
    int label_y2;
308
    int actual_fontsize; //seems tk does its own thing when rendering
309
310
311
312
    int actual_height;

    if (x->gl_isgraph && !glist_istoplevel(x))
    {
313
        if (x_gui.x_lab!=s_empty)
314
        {
315
            switch(x_gui.x_font_style)
316
            {
317
318
319
                case 1:  width_multiplier = 0.83333; break;
                case 2:  width_multiplier = 0.735;   break;
                default: width_multiplier = 1.0;     break;
320
            }
321
            actual_fontsize = x_gui.x_fontsize;
322
            actual_height = actual_fontsize;
323
            //exceptions
324
            if (x_gui.x_font_style == 0 &&
325
326
327
328
329
330
331
                (actual_fontsize == 8 || actual_fontsize == 13 ||
                actual_fontsize % 10 == 1 || actual_fontsize % 10 == 6 ||
                    (actual_fontsize > 48 && actual_fontsize < 100 &&
                    (actual_fontsize %10 == 4 || actual_fontsize %10 == 9))))
            {
                actual_fontsize += 1;
            }
332
            else if (x_gui.x_font_style == 1 && actual_fontsize >= 5 &&
333
334
                actual_fontsize < 13 && actual_fontsize % 2 == 1)
                actual_fontsize += 1;
335
            else if (x_gui.x_font_style == 2 && actual_fontsize >= 5 &&
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
                actual_fontsize % 2 == 1)
                actual_fontsize += 1;
            if (actual_height == 9)
                actual_height += 1;
            //done with exceptions

            width_multiplier = width_multiplier * (actual_fontsize * 0.6);

            label_length = strlen(x_gui.x_lab->s_name);
            label_x1 = *xp1 + x_gui.x_ldx;
            label_y1 = *yp1 + x_gui.x_ldy - actual_height/2;
            label_x2 = label_x1 + (label_length * width_multiplier);
            label_y2 = label_y1 + actual_height*1.1;

            //DEBUG
351
352
            // Note: we may want to port this debug code to the
            // new interface, but we haven't had a need to do it yet
353
            //fprintf(stderr,"%f %d %d\n", width_multiplier,
354
            //    label_length, x_gui.x_font_style);
355
356
357
358
359
360
361
362
363
364
365
366
367
368
            //sys_vgui(".x%lx.c delete iemguiDEBUG\n", x);
            //sys_vgui(".x%lx.c create rectangle %d %d %d %d "
            //    "-tags iemguiDEBUG\n",
            //    x, label_x1, label_y1, label_x2, label_y2);
            if (label_x1 < *xp1) *xp1 = label_x1;
            if (label_x2 > *xp2) *xp2 = label_x2;
            if (label_y1 < *yp1) *yp1 = label_y1;
            if (label_y2 > *yp2) *yp2 = label_y2;
            //DEBUG
            //sys_vgui(".x%lx.c delete iemguiDEBUG\n", x);
            //sys_vgui(".x%lx.c create rectangle %d %d %d %d "
            //    "-tags iemguiDEBUG\n", x, *xp1, *yp1, *xp2, *yp2);
        }
    }
369
370
}

371
372
373
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
#if 0 // future way of reordering stuff for iemgui_shouldvis
/*
    // some day when the object tagging is
    // properly done for all GUI objects
    glist_noselect(canvas);
    glist_select(canvas, y);
    t_gobj *yy = canvas->gl_list;
    if (yy != y)
    {
        while (yy && yy->g_next != y)
            yy = yy->g_next;
        // now we have yy which is right before our y graph
        t_rtext *yr = NULL;
        if (yy)
        {
            yr = glist_findrtext(canvas, (t_text *)yy);
        }
        if (yr)
        {
            fprintf(stderr,"lower\n");
            sys_vgui(".x%lx.c lower selected %s\n", canvas, rtext_gettag(yr));
            sys_vgui(".x%lx.c raise selected %s\n", canvas, rtext_gettag(yr));
            //canvas_raise_all_cords(canvas);
        }
        else
        {
            // fall back to legacy redraw for objects
            //   that are not patchable
            fprintf(stderr,"lower fallback redraw\n");
            canvas_redraw(canvas);
        }
    }
    else
    {
        // we get here if we are supposed to go
        //   all the way to the bottom
        fprintf(stderr,"lower to the bottom\n");
        sys_vgui(".x%lx.c lower selected\n", canvas);
    }
    glist_noselect(canvas);
*/
#endif

414
void iemgui_shouldvis(t_iemgui *x, int mode)
415
{
416
    gop_redraw = 1;
417
    if(gobj_shouldvis((t_gobj *)x, x->x_glist))
418
    {
419
        if (!x->x_vis)
420
421
        {
            //fprintf(stderr,"draw new %d\n", mode);
422
            iemgui_draw_new(x);
423
424
425
            canvas_fixlinesfor(glist_getcanvas(x->x_glist), (t_text*)x);
            x->x_vis = 1;
            if (x->x_glist != glist_getcanvas(x->x_glist))
426
427
428
429
            {
                /* if we are inside gop and just have had our object's
                   properties changed we'll adjust our layer position
                   to ensure that ordering is honored */
430
431
                t_canvas *canvas = glist_getcanvas(x->x_glist);
                t_gobj *y = (t_gobj *)x->x_glist;
432
433
434
435
436
437
                // this crashes when the label goes invisible and then
                // needs to be made visible again, so for the time being
                // we use the brute force redraw below for both the
                // vis/unvis-ing of the object and its reordering
                //gobj_vis(y, canvas, 0);
                //gobj_vis(y, canvas, 1);
438
439
440
441
442
                // reorder it visually
                glist_redraw(canvas);

            }
        }
443
        //fprintf(stderr,"draw move x->x_w=%d\n", x->x_w);
444
445
446
447
        if      (mode==IEM_GUI_DRAW_MODE_NEW)    iemgui_draw_new(   x);
        else if (mode==IEM_GUI_DRAW_MODE_MOVE)   iemgui_draw_move(  x);
        else if (mode==IEM_GUI_DRAW_MODE_CONFIG) iemgui_draw_config(x);
        else bug("iemgui_shouldvis");
448
        scalehandle_check_and_redraw(x);
449
        canvas_fixlinesfor(glist_getcanvas(x->x_glist), (t_text*)x);
450
    }
451
    else if (x->x_vis)
452
453
    {
        //fprintf(stderr,"draw erase %d\n", mode);
454
        iemgui_draw_erase(x);
455
        x->x_vis = 0;
456
457
    }
    gop_redraw = 0;
Miller Puckette's avatar
Miller Puckette committed
458
459
}

460
void iemgui_size(t_iemgui *x)
Miller Puckette's avatar
Miller Puckette committed
461
{
Jonathan Wilkes's avatar
Jonathan Wilkes committed
462
    if (glist_isvisible(x->x_glist))
463
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_MOVE);
Miller Puckette's avatar
Miller Puckette committed
464
465
}

466
void iemgui_delta(t_iemgui *x, t_symbol *s, int ac, t_atom *av)
Miller Puckette's avatar
Miller Puckette committed
467
{
468
469
    x->x_obj.te_xpix += atom_getintarg(0, ac, av);
    x->x_obj.te_ypix += atom_getintarg(1, ac, av);
470
471
    if(glist_isvisible(x->x_glist))
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_MOVE);
Miller Puckette's avatar
Miller Puckette committed
472
473
}

474
void iemgui_pos(t_iemgui *x, t_symbol *s, int ac, t_atom *av)
Miller Puckette's avatar
Miller Puckette committed
475
{
476
477
    x->x_obj.te_xpix = atom_getintarg(0, ac, av);
    x->x_obj.te_ypix = atom_getintarg(1, ac, av);
478
479
    if(glist_isvisible(x->x_glist))
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_MOVE);
Miller Puckette's avatar
Miller Puckette committed
480
481
}

482
void iemgui_color(t_iemgui *x, t_symbol *s, int ac, t_atom *av)
Miller Puckette's avatar
Miller Puckette committed
483
{
484
    x->x_bcol = iemgui_compatible_col(atom_getintarg(0, ac, av));
Miller Puckette's avatar
Miller Puckette committed
485
486
    if(ac > 2)
    {
487
488
        x->x_fcol = iemgui_compatible_col(atom_getintarg(1, ac, av));
        x->x_lcol = iemgui_compatible_col(atom_getintarg(2, ac, av));
Miller Puckette's avatar
Miller Puckette committed
489
490
    }
    else
491
492
        x->x_lcol = iemgui_compatible_col(atom_getintarg(1, ac, av));
    if(glist_isvisible(x->x_glist))
493
    {
494
        x->x_draw(x, x->x_glist, IEM_GUI_DRAW_MODE_CONFIG);
495
496
        iemgui_label_draw_config(x);
    }
Miller Puckette's avatar
Miller Puckette committed
497
498
499
500
}

void iemgui_displace(t_gobj *z, t_glist *glist, int dx, int dy)
{
501
502
503
    t_iemgui *x = (t_iemgui *)z;
    x->x_obj.te_xpix += dx;
    x->x_obj.te_ypix += dy;
504
505
    if (glist_isvisible(glist))
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_MOVE);
Miller Puckette's avatar
Miller Puckette committed
506
507
}

508
509
void iemgui_displace_withtag(t_gobj *z, t_glist *glist, int dx, int dy)
{
510
511
512
    t_iemgui *x = (t_iemgui *)z;
    x->x_obj.te_xpix += dx;
    x->x_obj.te_ypix += dy;
513
    //iemgui_draw_move(x);
514
515
516
517
    canvas_fixlinesfor(glist_getcanvas(glist), (t_text *)z);
}


Miller Puckette's avatar
Miller Puckette committed
518
519
void iemgui_select(t_gobj *z, t_glist *glist, int selected)
{
520
    t_iemgui *x = (t_iemgui *)z;
521
    t_canvas *canvas=glist_getcanvas(glist);
522
523
524
525
    if (selected)
        x->x_selected = canvas;
    else
        x->x_selected = NULL;
526
    x->x_draw((void *)z, glist, IEM_GUI_DRAW_MODE_SELECT);
527
528
529
530
531
532
533
534
535
536
537
538
539
540
    if (selected < 2)
    {
        scalehandle_draw(x);
    }
    else
    {
        // exception where we get rid of handles when moving tiny objects
        // because tkpath's slowness sometimes makes mouse pointer go over
        // a handle and messes things up. we only do this when using
        // startmotion (see g_editor.c).
        // LATER: get rid of this because we will deal with this better using
        // the new toolkit.
        scalehandle_draw_erase2(x);
    }
541
542
    iemgui_label_draw_select(x);
    iemgui_tag_selected(x);
Miller Puckette's avatar
Miller Puckette committed
543
544
545
546
547
548
549
550
551
}

void iemgui_delete(t_gobj *z, t_glist *glist)
{
    canvas_deletelinesfor(glist, (t_text *)z);
}

void iemgui_vis(t_gobj *z, t_glist *glist, int vis)
{
552
    t_iemgui *x = (t_iemgui *)z;
553
554
555
    if (gobj_shouldvis(z, glist))
    {
        if (vis)
556
            iemgui_draw_new(x);
557
558
        else
        {
559
            iemgui_draw_erase(x);
560
561
            sys_unqueuegui(z);
        }
562
        x->x_vis = vis;
563
    }
Miller Puckette's avatar
Miller Puckette committed
564
565
}

566
void iemgui_save(t_iemgui *x, t_symbol **srl, int *bflcol)
Miller Puckette's avatar
Miller Puckette committed
567
{
568
569
570
571
572
573
574
    if (srl) {
       srl[0] = x->x_snd;
       srl[1] = x->x_rcv;
       srl[2] = x->x_lab;
    }
    iemgui_all_sym2dollararg(x, srl);
    iemgui_all_col2save(x, bflcol);
Miller Puckette's avatar
Miller Puckette committed
575
576
}

577
void iemgui_properties(t_iemgui *x, t_symbol **srl)
Miller Puckette's avatar
Miller Puckette committed
578
{
579
580
581
582
583
584
585
    srl[0] = x->x_snd;
    srl[1] = x->x_rcv;
    srl[2] = x->x_lab;
    iemgui_all_sym2dollararg(x, srl);
    srl[0] = iemgui_dollar2raute(srl[0]);
    srl[1] = iemgui_dollar2raute(srl[1]);
    srl[2] = iemgui_dollar2raute(srl[2]);
Miller Puckette's avatar
Miller Puckette committed
586
587
}

588
int iemgui_dialog(t_iemgui *x, int argc, t_atom *argv)
Miller Puckette's avatar
Miller Puckette committed
589
{
590
    t_symbol *srl[3];
591
592
593
594
595
596
597
598
599
600
601
602
    x->x_loadinit = !!atom_getintarg(5, argc, argv);
    srl[0] = iemgui_getfloatsymarg(7,argc,argv);
    srl[1] = iemgui_getfloatsymarg(8,argc,argv);
    srl[2] = iemgui_getfloatsymarg(9,argc,argv);
    x->x_ldx = atom_getintarg(10, argc, argv);
    x->x_ldy = atom_getintarg(11, argc, argv);
    int f = atom_getintarg(12, argc, argv);
    x->x_fontsize = maxi(atom_getintarg(13, argc, argv),4);
    x->x_bcol = atom_getintarg(14, argc, argv) & 0xffffff;
    x->x_fcol = atom_getintarg(15, argc, argv) & 0xffffff;
    x->x_lcol = atom_getintarg(16, argc, argv) & 0xffffff;
    int oldsndrcvable=0;
603
604
    if(iemgui_has_rcv(x)) oldsndrcvable |= IEM_GUI_OLD_RCV_FLAG;
    if(iemgui_has_snd(x)) oldsndrcvable |= IEM_GUI_OLD_SND_FLAG;
Miller Puckette's avatar
Miller Puckette committed
605
    iemgui_all_raute2dollar(srl);
606
607
608
609
610
611
612
613
614
615
616
617
618

    // replace ascii code 11 (\v or vertical tab) with spaces
    // we do this so that the string with spaces can survive argc,argv
    // conversion when coming from dialog side of things where it is parsed
    char *c;
    for(c = srl[2]->s_name; c != NULL && *c != '\0'; c++)
    {
        if(*c == '\v')
        {
            *c = ' ';
        }
    }

619
620
621
622
    x->x_snd_unexpanded=srl[0]; srl[0]=canvas_realizedollar(x->x_glist, srl[0]);
    x->x_rcv_unexpanded=srl[1]; srl[1]=canvas_realizedollar(x->x_glist, srl[1]);
    x->x_lab_unexpanded=srl[2]; srl[2]=canvas_realizedollar(x->x_glist, srl[2]);
    if(srl[1]!=x->x_rcv)
Miller Puckette's avatar
Miller Puckette committed
623
    {
624
625
626
627
        if(iemgui_has_rcv(x))
            pd_unbind((t_pd *)x, x->x_rcv);
        x->x_rcv = srl[1];
        pd_bind((t_pd *)x, x->x_rcv);
Miller Puckette's avatar
Miller Puckette committed
628
    }
629
630
    x->x_snd = srl[0];
    x->x_lab = srl[2];
631
    if(f<0 || f>2) f=0;
632
633
634
    x->x_font_style = f;
    iemgui_verify_snd_ne_rcv(x);
    canvas_dirty(x->x_glist, 1);
635
    return oldsndrcvable;
Miller Puckette's avatar
Miller Puckette committed
636
637
}

638
void iem_inttosymargs(t_iemgui *x, int n)
Miller Puckette's avatar
Miller Puckette committed
639
{
640
641
642
    x->x_loadinit = (n >>  0);
    x->x_locked = 0;
    x->x_reverse = 0;
Miller Puckette's avatar
Miller Puckette committed
643
644
}

645
int iem_symargstoint(t_iemgui *x)
Miller Puckette's avatar
Miller Puckette committed
646
{
647
    return ((x->x_loadinit & 1) <<  0);
Miller Puckette's avatar
Miller Puckette committed
648
649
}

650
void iem_inttofstyle(t_iemgui *x, int n)
Miller Puckette's avatar
Miller Puckette committed
651
{
652
    x->x_font_style = (n >> 0);
653
    x->x_selected = NULL;
654
655
656
657
658
659
    x->x_finemoved = 0;
    x->x_put_in2out = 0;
    x->x_change = 0;
}

int iem_fstyletoint(t_iemgui *x)
Miller Puckette's avatar
Miller Puckette committed
660
{
661
    return ((x->x_font_style << 0) & 63);
Miller Puckette's avatar
Miller Puckette committed
662
}
663

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
char *iem_get_tag(t_canvas *glist, t_iemgui *iem_obj)
{
    t_gobj *y = (t_gobj *)iem_obj;
    t_object *ob = pd_checkobject(&y->g_pd);

    /* GOP objects are unable to call findrtext
       triggering consistency check error */
    t_rtext *yyyy = NULL;
    if (!glist->gl_isgraph || glist_istoplevel(glist))
        yyyy = glist_findrtext(glist_getcanvas(glist), (t_text *)&ob->ob_g);

    /* on GOP we cause segfault as text_gettag() returns bogus data */
    if (yyyy) return(rtext_gettag(yyyy));
    else return("bogus");
}

680
//----------------------------------------------------------------
681
// SCALEHANDLE COMMON CODE (by Mathieu, refactored from existing code)
682

683
684
extern int gfxstub_haveproperties(void *key);

685
686
687
688
int   mini(int   a, int   b) {return a<b?a:b;}
int   maxi(int   a, int   b) {return a>b?a:b;}
float minf(float a, float b) {return a<b?a:b;}
float maxf(float a, float b) {return a>b?a:b;}
689

690
691
extern t_class *my_canvas_class;

692
// in 18 cases only, because canvas does not fit the pattern below.
693
694
// canvas has no label handle and has a motion handle
// but in the case of canvas, the "iemgui" tag is added (it wasn't the case originally)
695
void scalehandle_draw_select(t_scalehandle *h, int px, int py) {
696
    char tagbuf[MAXPDSTRING];
697
    t_object *x = h->h_master;
698
    t_canvas *canvas=glist_getcanvas(h->h_glist);
699
700
701
702

    int sx = h->h_scale ? SCALEHANDLE_WIDTH  : LABELHANDLE_WIDTH;
    int sy = h->h_scale ? SCALEHANDLE_HEIGHT : LABELHANDLE_HEIGHT;

703
    scalehandle_draw_erase(h);
704

705
    if (!h->h_vis) {
706
        sprintf(tagbuf, "x%lx", (long unsigned int)x);
707
708
        gui_vmess("gui_iemgui_label_show_drag_handle", "xsiiii",
            canvas, tagbuf, 1, px - sx, py - sy, h->h_scale);
709
        h->h_vis = 1;
710
    }
711
712
}

713
714
void scalehandle_draw_select2(t_iemgui *x) {
    t_canvas *canvas=glist_getcanvas(x->x_glist);
715
    t_class *c = pd_class((t_pd *)x);
716
    int sx,sy;
717
    if (c == my_canvas_class)
718
    {
719
        t_my_canvas *y = (t_my_canvas *)x;
720
721
        sx = y->x_vis_w;
        sy = y->x_vis_h;
722
723
724
    }
    else
    {
725
726
        int x1,y1,x2,y2;
        c->c_wb->w_getrectfn((t_gobj *)x,canvas,&x1,&y1,&x2,&y2);
727
        //iemgui_getrect_draw(x, &x1, &y1, &x2, &y2);
728
729
        sx=x2-x1; sy=y2-y1;
    }
730
731
    /* we're not drawing the scalehandle for the actual iemgui-- just
       the one for the label. */
732
    if (c == my_canvas_class)
733
        scalehandle_draw_select(x->x_handle,sx+8,sy+3);
734
    if (x->x_lab != s_empty)
735
        scalehandle_draw_select(x->x_lhandle,x->x_ldx,x->x_ldy);
736
737
}

738
void scalehandle_draw_erase(t_scalehandle *h) {
739
    t_canvas *canvas = glist_getcanvas(h->h_glist);
740
    if (!h->h_vis) return;
741
742
    gui_vmess("gui_iemgui_label_show_drag_handle", "xxiiii",
        h->h_glist, h->h_master, 0, 0, 0, h->h_scale);
743
    h->h_vis = 0;
744
745
}

746
void scalehandle_draw_erase2(t_iemgui *x) {
747
748
    t_scalehandle *sh = (t_scalehandle *)(x->x_handle);
    t_scalehandle *lh = (t_scalehandle *)(x->x_lhandle);
749
750
    if (sh->h_vis) scalehandle_draw_erase(sh);
    if (lh->h_vis) scalehandle_draw_erase(lh);
751
752
}

753
754
void scalehandle_draw(t_iemgui *x) {
    if (x->x_glist == glist_getcanvas(x->x_glist)) {
755
        if (x->x_selected == x->x_glist) scalehandle_draw_select2(x);
756
        else scalehandle_draw_erase2(x);
757
    }
758
759
}

760
761
t_scalehandle *scalehandle_new(t_object *x, t_glist *glist, int scale, t_clickhandlefn chf, t_motionhandlefn mhf) {
    t_scalehandle *h = (t_scalehandle *)pd_new(scalehandle_class);
762
763
    char buf[19]; // 3 + max size of %lx
    h->h_master = x;
764
    h->h_glist = glist;
765
766
    if (!scale) /* Only bind for labels-- scaling uses pd_vmess in g_editor.c */
    {
767
        sprintf(buf, "_l%lx", (long unsigned int)x);
768
769
770
771
        pd_bind((t_pd *)h, h->h_bindsym = gensym(buf));
    }
    else if (scale && pd_class((t_pd *)x) == my_canvas_class)
    {
772
        sprintf(buf, "_s%lx", (long unsigned int)x);
773
774
        pd_bind((t_pd *)h, h->h_bindsym = gensym(buf));
    }
775
776
777
    sprintf(h->h_outlinetag, "h%lx", (t_int)h);
    h->h_dragon = 0;
    h->h_scale = scale;
778
779
    h->h_offset_x = 0;
    h->h_offset_y = 0;
780
    h->h_vis = 0;
781
    sprintf(h->h_pathname, ".x%lx.h%lx", (t_int)h->h_glist, (t_int)h);
782
783
    h->h_clickfn = chf;
    h->h_motionfn = mhf;
784
785
786
787
    return h;
}

void scalehandle_free(t_scalehandle *h) {
788
789
    if (!h->h_scale || pd_class((t_pd *)(h->h_master)) == my_canvas_class)
    { /* only binding label handles and my_canvas resize handle */
790
791
        pd_unbind((t_pd *)h, h->h_bindsym);
    }
792
    pd_free((t_pd *)h);
793
}
794
795

void properties_set_field_int(long props, const char *gui_field, int value) {
796
797
798
799
800
801
    char tagbuf[MAXPDSTRING];
    sprintf(tagbuf, ".gfxstub%lx", props);
    gui_vmess("gui_dialog_set_field", "ssi",
        tagbuf,
        gui_field,
        value);
802
803
};

804
void scalehandle_dragon_label(t_scalehandle *h, float mouse_x, float mouse_y) {
805
806
807
    if (h->h_dragon && !h->h_scale)
    {
        t_iemgui *x = (t_iemgui *)(h->h_master);
808
809
        int dx = (int)mouse_x - (int)h->h_offset_x,
            dy = (int)mouse_y - (int)h->h_offset_y;
810
811
        h->h_dragx = dx;
        h->h_dragy = dy;
812

813
814
815
        int properties = gfxstub_haveproperties((void *)x);
        if (properties)
        {
816
817
            int new_x = x->x_ldx + h->h_dragx;
            int new_y = x->x_ldy + h->h_dragy;
818
819
            properties_set_field_int(properties, "x_offset", new_x);
            properties_set_field_int(properties, "y_offset", new_y);
820
        }
821
822
823
        x->x_ldx += dx;
        x->x_ldy += dy;

824
825
826
827
        if (glist_isvisible(x->x_glist))
        {
            int xpos=text_xpix(&x->x_obj, x->x_glist);
            int ypos=text_ypix(&x->x_obj, x->x_glist);
828
            //iemgui_getrect_legacy_label(x, &xpos, &ypos);
829
            t_canvas *canvas=glist_getcanvas(x->x_glist);
830
831
832
833
834
            gui_vmess("gui_iemgui_label_coords", "xxii",
                canvas,
                x,
                x->x_ldx,
                x->x_ldy);
835
836
837
        }
    }
}
838
839
840
841
842

void scalehandle_click_label(t_scalehandle *h) {
    t_iemgui *x = (t_iemgui *)h->h_master;
    if (glist_isvisible(x->x_glist))
    {
843
        //sys_vgui("lower %s\n", h->h_pathname);
844
        t_scalehandle *othersh = x->x_handle;
845
846
        //sys_vgui("lower .x%lx.h%lx\n",
        //    (t_int)glist_getcanvas(x->x_glist), (t_int)othersh);
847
848
849
850
851
852
853
854
855
    }
    h->h_dragx = 0;
    h->h_dragy = 0;
}

void scalehandle_getrect_master(t_scalehandle *h, int *x1, int *y1, int *x2, int *y2) {
    t_iemgui *x = (t_iemgui *)h->h_master;
    t_class *c = pd_class((t_pd *)x);
    c->c_wb->w_getrectfn((t_gobj *)x,x->x_glist,x1,y1,x2,y2);
856
857
858
    //fprintf(stderr,"%d %d %d %d\n",*x1,*y1,*x2,*y2);
    //iemgui_getrect_draw((t_iemgui *)x, x1, y1, x2, y2);
    //fprintf(stderr,"%d %d %d %d\n",*x1,*y1,*x2,*y2);
859
860
861
862
863
864
865
866
867
868
869
870
    //printf("%s\n",c->c_name->s_name);
    if (c==my_canvas_class) {
        t_my_canvas *xx = (t_my_canvas *)x;
        *x2=*x1+xx->x_vis_w;
        *y2=*y1+xx->x_vis_h;
    }
}

void scalehandle_click_scale(t_scalehandle *h) {
    int x1,y1,x2,y2;
    t_iemgui *x = (t_iemgui *)h->h_master;
    scalehandle_getrect_master(h,&x1,&y1,&x2,&y2);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
871
872
873
874
875
    if (glist_isvisible(x->x_glist))
    {
        //sys_vgui("lower %s\n", h->h_pathname);
        //sys_vgui(".x%x.c create prect %d %d %d %d -stroke $pd_colors(selection) -strokewidth 1 -tags %s\n",
        //    x->x_glist, x1, y1, x2, y2, h->h_outlinetag);
876
877
878
879
880
    }
    h->h_dragx = 0;
    h->h_dragy = 0;
}

881
882
883
// here we don't need to use glist_getcanvas(t_canvas *)
// because scalehandle on iemgui objects appears only when
// they are on their own canvas
884
885
void scalehandle_unclick_scale(t_scalehandle *h) {
    t_iemgui *x = (t_iemgui *)h->h_master;
886
    //sys_vgui(".x%x.c delete %s\n", x->x_glist, h->h_outlinetag);
887
    iemgui_io_draw_move(x);
888
889
    iemgui_select((t_gobj *)x, x->x_glist, 1);
    canvas_fixlinesfor(x->x_glist, (t_text *)x);
890
    canvas_getscroll(x->x_glist);
891
892
893
894
895
896
}

void scalehandle_drag_scale(t_scalehandle *h) {
    int x1,y1,x2,y2;
    t_iemgui *x = (t_iemgui *)h->h_master;
    scalehandle_getrect_master(h,&x1,&y1,&x2,&y2);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
897
898
899
900
    if (glist_isvisible(x->x_glist))
    {
        //sys_vgui(".x%x.c coords %s %d %d %d %d\n", x->x_glist, h->h_outlinetag,
        //    x1, y1, x2+h->h_dragx, y2+h->h_dragy);
901
902
903
    }
}

904
905
906
907
908
909
910
911
912
913
914
static void scalehandle_clickhook(t_scalehandle *h, t_floatarg f,
    t_floatarg xxx, t_floatarg yyy)
{
    h->h_offset_x=xxx;
    h->h_offset_y=yyy;
    h->h_clickfn(h,f);
}

static void scalehandle_motionhook(t_scalehandle *h,
    t_floatarg f1, t_floatarg f2)
{
915
916
917
918
    h->h_motionfn(h,f1,f2);
    // Now set the offset to the new mouse position
    h->h_offset_x = f1;
    h->h_offset_y = f2;
919
920
}

921
922
923
924
925
926
927
928
void iemgui__clickhook3(t_scalehandle *sh, int newstate) {
    if (!sh->h_dragon && newstate && sh->h_scale)
        scalehandle_click_scale(sh);
    else if (!sh->h_dragon && newstate && !sh->h_scale)
        scalehandle_click_label(sh);
    sh->h_dragon = newstate;
}

929
930
931
932
933
// function for updating of handles on iemgui objects
// we don't need glist_getcanvas() because handles are only
// drawn when object is selected on its canvas (instead of GOP)
static void scalehandle_check_and_redraw(t_iemgui *x)
{
Jonathan Wilkes's avatar
Jonathan Wilkes committed
934
    if (x->x_selected == x->x_glist)
935
        scalehandle_draw_select2(x);
936
937
}

938
939
940
//----------------------------------------------------------------
// IEMGUI refactor (by Mathieu)

941
942
void iemgui_tag_selected(t_iemgui *x) {
    t_canvas *canvas=glist_getcanvas(x->x_glist);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
943
    if (x->x_selected)
944
        gui_vmess("gui_gobj_select", "xx", canvas, x);
945
    else
946
        gui_vmess("gui_gobj_deselect", "xx", canvas, x);
947
948
}

949
void iemgui_label_draw_new(t_iemgui *x) {
950
    char col[8];
951
    t_canvas *canvas=glist_getcanvas(x->x_glist);
952
953
954
    int x1=text_xpix(&x->x_obj, x->x_glist)+x->legacy_x;
    int y1=text_ypix(&x->x_obj, x->x_glist)+x->legacy_y;
    iemgui_getrect_legacy_label(x, &x1, &y1);
955
    sprintf(col, "#%6.6x", x->x_lcol);
956
    gui_vmess("gui_iemgui_label_new", "xxiissssi",
957
958
        canvas,
        x,
959
960
961
962
        x->x_ldx,
        x->x_ldy,
        col,
        x->x_lab != s_empty ? x->x_lab->s_name : "",
963
964
965
        iemgui_typeface(x),
        sys_fontweight,
        x->x_fontsize);
966
}
967

968
969
void iemgui_label_draw_move(t_iemgui *x) {
    t_canvas *canvas=glist_getcanvas(x->x_glist);
970
971
972
    int x1=text_xpix(&x->x_obj, x->x_glist)+x->legacy_x;
    int y1=text_ypix(&x->x_obj, x->x_glist)+x->legacy_y;
    //iemgui_getrect_legacy_label(x, &x1, &y1);
973
974
    //sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
    //    canvas, x, x1+x->x_ldx, y1+x->x_ldy);
975
976
977
978

    /* Note-- since we're not using x1/y1 above in the new GUI call,
       Ivica's legacy logic isn't affecting us. Quick fix below by
       just adding the legacy offsets... */
979
980
981
    gui_vmess("gui_iemgui_label_coords", "xxii",
        glist_getcanvas(x->x_glist),
        x,
982
983
        x->x_ldx + x->legacy_x,
        x->x_ldy + x->legacy_y);
984
}
985

986
void iemgui_label_draw_config(t_iemgui *x) {
987
    char col[8];
988
    t_canvas *canvas=glist_getcanvas(x->x_glist);
989
    if (x->x_selected == canvas && x->x_glist == canvas)
990
    {
991
        gui_vmess("gui_iemgui_label_font", "xxssi",
992
993
            glist_getcanvas(x->x_glist),
            x,
994
995
996
            iemgui_typeface(x),
            sys_fontweight,
            x->x_fontsize);
997
998
999
        gui_vmess("gui_iemgui_label_set", "xxs",
            glist_getcanvas(x->x_glist),
            x,
1000
1001
            x->x_lab != s_empty ? x->x_lab->s_name: "");
        sprintf(col, "#%6.6x", x->x_lcol);
1002
1003
1004
        gui_vmess("gui_iemgui_label_color", "xxs",
            canvas,
            x,
1005
1006
            col);
    }
1007
    else
1008
    {
1009
        gui_vmess("gui_iemgui_label_font", "xxssi",
user's avatar