g_all_guis.c 41.1 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
}

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++)
    {
        if (*s1 == '$')
            *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++)
    {
        if (*s1 == '#')
            *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
235
236
237
    if (s == &s_) s = s_empty; //tb: fix for empty label
    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
238

239
    if(glist_isvisible(x->x_glist))
240
    {
241
242
243
        gui_vmess("gui_iemgui_label_set", "xxs",
            glist_getcanvas(x->x_glist),
            x,
244
            s != s_empty ? x->x_lab->s_name : "");
245
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_CONFIG);
246
    }
Miller Puckette's avatar
Miller Puckette committed
247
248
}

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

259
260
261
        gui_vmess("gui_iemgui_label_coords", "xxii",
            glist_getcanvas(x->x_glist),
            x,
262
263
            x1,
            y1);
264
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_CONFIG);
265
    }
Miller Puckette's avatar
Miller Puckette committed
266
267
}

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

//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

290
291
292
293
294
295
// 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;

296
297
298
299
300
301
302
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);
    if (!gop_redraw)
    {
        //fprintf(stderr,"ignoring label\n");
303
        return;
304
305
306
    }

    t_float width_multiplier;
307
    int label_length;
308
309
310
311
    int label_x1;
    int label_y1;
    int label_x2;
    int label_y2;
312
    int actual_fontsize; //seems tk does its own thing when rendering
313
314
315
316
    int actual_height;

    if (x->gl_isgraph && !glist_istoplevel(x))
    {
317
        if (x_gui.x_lab!=s_empty)
318
        {
319
            switch(x_gui.x_font_style)
320
            {
321
322
323
                case 1:  width_multiplier = 0.83333; break;
                case 2:  width_multiplier = 0.735;   break;
                default: width_multiplier = 1.0;     break;
324
            }
325
            actual_fontsize = x_gui.x_fontsize;
326
            actual_height = actual_fontsize;
327
            //exceptions
328
            if (x_gui.x_font_style == 0 &&
329
330
331
332
333
334
335
                (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;
            }
336
            else if (x_gui.x_font_style == 1 && actual_fontsize >= 5 &&
337
338
                actual_fontsize < 13 && actual_fontsize % 2 == 1)
                actual_fontsize += 1;
339
            else if (x_gui.x_font_style == 2 && actual_fontsize >= 5 &&
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
                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
355
356
            // Note: we may want to port this debug code to the
            // new interface, but we haven't had a need to do it yet
357
            //fprintf(stderr,"%f %d %d\n", width_multiplier,
358
            //    label_length, x_gui.x_font_style);
359
360
361
362
363
364
365
366
367
368
369
370
371
372
            //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);
        }
    }
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
414
415
416
417
#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

418
void iemgui_shouldvis(t_iemgui *x, int mode)
419
{
420
    gop_redraw = 1;
421
    if(gobj_shouldvis((t_gobj *)x, x->x_glist))
422
    {
423
        if (!x->x_vis)
424
425
        {
            //fprintf(stderr,"draw new %d\n", mode);
426
            iemgui_draw_new(x);
427
428
429
            canvas_fixlinesfor(glist_getcanvas(x->x_glist), (t_text*)x);
            x->x_vis = 1;
            if (x->x_glist != glist_getcanvas(x->x_glist))
430
431
432
433
            {
                /* 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 */
434
435
                t_canvas *canvas = glist_getcanvas(x->x_glist);
                t_gobj *y = (t_gobj *)x->x_glist;
436
437
438
439
440
441
                // 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);
442
443
444
445
446
                // reorder it visually
                glist_redraw(canvas);

            }
        }
447
        //fprintf(stderr,"draw move x->x_w=%d\n", x->x_w);
448
449
450
451
        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");
452
        scalehandle_check_and_redraw(x);
453
        canvas_fixlinesfor(glist_getcanvas(x->x_glist), (t_text*)x);
454
    }
455
    else if (x->x_vis)
456
457
    {
        //fprintf(stderr,"draw erase %d\n", mode);
458
        iemgui_draw_erase(x);
459
        x->x_vis = 0;
460
461
    }
    gop_redraw = 0;
Miller Puckette's avatar
Miller Puckette committed
462
463
}

464
void iemgui_size(t_iemgui *x)
Miller Puckette's avatar
Miller Puckette committed
465
{
466
467
    if(glist_isvisible(x->x_glist))
        iemgui_shouldvis(x, IEM_GUI_DRAW_MODE_MOVE);
Miller Puckette's avatar
Miller Puckette committed
468
469
}

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

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

486
void iemgui_color(t_iemgui *x, t_symbol *s, int ac, t_atom *av)
Miller Puckette's avatar
Miller Puckette committed
487
{
488
    x->x_bcol = iemgui_compatible_col(atom_getintarg(0, ac, av));
Miller Puckette's avatar
Miller Puckette committed
489
490
    if(ac > 2)
    {
491
492
        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
493
494
    }
    else
495
496
        x->x_lcol = iemgui_compatible_col(atom_getintarg(1, ac, av));
    if(glist_isvisible(x->x_glist))
497
    {
498
        x->x_draw(x, x->x_glist, IEM_GUI_DRAW_MODE_CONFIG);
499
500
        iemgui_label_draw_config(x);
    }
Miller Puckette's avatar
Miller Puckette committed
501
502
503
504
}

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

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


Miller Puckette's avatar
Miller Puckette committed
522
523
void iemgui_select(t_gobj *z, t_glist *glist, int selected)
{
524
    t_iemgui *x = (t_iemgui *)z;
525
    t_canvas *canvas=glist_getcanvas(glist);
526
527
528
529
    if (selected)
        x->x_selected = canvas;
    else
        x->x_selected = NULL;
530
    x->x_draw((void *)z, glist, IEM_GUI_DRAW_MODE_SELECT);
531
532
533
534
535
536
537
538
539
540
541
542
543
544
    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);
    }
545
546
    iemgui_label_draw_select(x);
    iemgui_tag_selected(x);
Miller Puckette's avatar
Miller Puckette committed
547
548
549
550
551
552
553
554
555
}

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)
{
556
    t_iemgui *x = (t_iemgui *)z;
557
558
559
    if (gobj_shouldvis(z, glist))
    {
        if (vis)
560
            iemgui_draw_new(x);
561
562
        else
        {
563
            iemgui_draw_erase(x);
564
565
            sys_unqueuegui(z);
        }
566
        x->x_vis = vis;
567
    }
Miller Puckette's avatar
Miller Puckette committed
568
569
}

570
void iemgui_save(t_iemgui *x, t_symbol **srl, int *bflcol)
Miller Puckette's avatar
Miller Puckette committed
571
{
572
573
574
575
576
577
578
    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
579
580
}

581
void iemgui_properties(t_iemgui *x, t_symbol **srl)
Miller Puckette's avatar
Miller Puckette committed
582
{
583
584
585
586
587
588
589
    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
590
591
}

592
int iemgui_dialog(t_iemgui *x, int argc, t_atom *argv)
Miller Puckette's avatar
Miller Puckette committed
593
{
594
    t_symbol *srl[3];
595
596
597
598
599
600
601
602
603
604
605
606
    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;
607
608
    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
609
    iemgui_all_raute2dollar(srl);
610
611
612
613
614
615
616
617
618
619
620
621
622

    // 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 = ' ';
        }
    }

623
624
625
626
    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
627
    {
628
629
630
631
        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
632
    }
633
634
    x->x_snd = srl[0];
    x->x_lab = srl[2];
635
    if(f<0 || f>2) f=0;
636
637
638
    x->x_font_style = f;
    iemgui_verify_snd_ne_rcv(x);
    canvas_dirty(x->x_glist, 1);
639
    return oldsndrcvable;
Miller Puckette's avatar
Miller Puckette committed
640
641
}

642
void iem_inttosymargs(t_iemgui *x, int n)
Miller Puckette's avatar
Miller Puckette committed
643
{
644
645
646
    x->x_loadinit = (n >>  0);
    x->x_locked = 0;
    x->x_reverse = 0;
Miller Puckette's avatar
Miller Puckette committed
647
648
}

649
int iem_symargstoint(t_iemgui *x)
Miller Puckette's avatar
Miller Puckette committed
650
{
651
    return ((x->x_loadinit & 1) <<  0);
Miller Puckette's avatar
Miller Puckette committed
652
653
}

654
void iem_inttofstyle(t_iemgui *x, int n)
Miller Puckette's avatar
Miller Puckette committed
655
{
656
    x->x_font_style = (n >> 0);
657
    x->x_selected = NULL;
658
659
660
661
662
663
    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
664
{
665
    return ((x->x_font_style << 0) & 63);
Miller Puckette's avatar
Miller Puckette committed
666
}
667

668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
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");
}

684
//----------------------------------------------------------------
685
// SCALEHANDLE COMMON CODE (by Mathieu, refactored from existing code)
686

687
688
extern int gfxstub_haveproperties(void *key);

689
690
691
692
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;}
693

694
// in 18 cases only, because canvas does not fit the pattern below.
695
696
// 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)
697
void scalehandle_draw_select(t_scalehandle *h, int px, int py) {
698
    char tagbuf[MAXPDSTRING];
699
    t_object *x = h->h_master;
700
    t_canvas *canvas=glist_getcanvas(h->h_glist);
701
702
703
704

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

705
    scalehandle_draw_erase(h);
706

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

715
716
extern t_class *my_canvas_class;

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

741
void scalehandle_draw_erase(t_scalehandle *h) {
742
    t_canvas *canvas = glist_getcanvas(h->h_glist);
743
    if (!h->h_vis) return;
744
745
    gui_vmess("gui_iemgui_label_show_drag_handle", "xxiii",
        h->h_glist, h->h_master, 0, 0, 0);
746
    h->h_vis = 0;
747
748
}

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

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

763
764
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);
765
766
    char buf[19]; // 3 + max size of %lx
    h->h_master = x;
767
    h->h_glist = glist;
768
769
770
771
772
    if (!scale) /* Only bind for labels-- scaling uses pd_vmess in g_editor.c */
    {
        sprintf(buf, "_h%lx", (t_int)x);
        pd_bind((t_pd *)h, h->h_bindsym = gensym(buf));
    }
773
774
775
    sprintf(h->h_outlinetag, "h%lx", (t_int)h);
    h->h_dragon = 0;
    h->h_scale = scale;
776
777
    h->h_offset_x = 0;
    h->h_offset_y = 0;
778
    h->h_vis = 0;
779
    sprintf(h->h_pathname, ".x%lx.h%lx", (t_int)h->h_glist, (t_int)h);
780
781
    h->h_clickfn = chf;
    h->h_motionfn = mhf;
782
783
784
785
    return h;
}

void scalehandle_free(t_scalehandle *h) {
786
787
788
    if (!h->h_scale) { /* only binding handles labels, not for scaling guis */
        pd_unbind((t_pd *)h, h->h_bindsym);
    }
789
    pd_free((t_pd *)h);
790
}
791
792

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

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

810
811
812
        int properties = gfxstub_haveproperties((void *)x);
        if (properties)
        {
813
814
            int new_x = x->x_ldx + h->h_dragx;
            int new_y = x->x_ldy + h->h_dragy;
815
816
            properties_set_field_int(properties, "x-offset", new_x);
            properties_set_field_int(properties, "y-offset", new_y);
817
        }
818
819
820
        x->x_ldx += dx;
        x->x_ldy += dy;

821
822
823
824
        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);
825
            //iemgui_getrect_legacy_label(x, &xpos, &ypos);
826
            t_canvas *canvas=glist_getcanvas(x->x_glist);
827
828
829
830
831
            gui_vmess("gui_iemgui_label_coords", "xxii",
                canvas,
                x,
                x->x_ldx,
                x->x_ldy);
832
833
834
        }
    }
}
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852

void scalehandle_click_label(t_scalehandle *h) {
    t_iemgui *x = (t_iemgui *)h->h_master;
    if (glist_isvisible(x->x_glist))
    {
        sys_vgui("lower %s\n", h->h_pathname);
        t_scalehandle *othersh = x->x_handle;
        sys_vgui("lower .x%lx.h%lx\n",
            (t_int)glist_getcanvas(x->x_glist), (t_int)othersh);
    }
    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);
853
854
855
    //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);
856
857
858
859
860
861
862
863
864
865
866
867
    //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
868
869
870
871
872
    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);
873
874
875
876
877
    }
    h->h_dragx = 0;
    h->h_dragy = 0;
}

878
879
880
// 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
881
882
void scalehandle_unclick_scale(t_scalehandle *h) {
    t_iemgui *x = (t_iemgui *)h->h_master;
883
    //sys_vgui(".x%x.c delete %s\n", x->x_glist, h->h_outlinetag);
884
    iemgui_io_draw_move(x);
885
886
    iemgui_select((t_gobj *)x, x->x_glist, 1);
    canvas_fixlinesfor(x->x_glist, (t_text *)x);
887
    canvas_getscroll(x->x_glist);
888
889
890
891
892
893
}

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
894
895
896
897
    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);
898
899
900
    }
}

901
902
903
904
905
906
907
908
909
910
911
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)
{
912
913
914
915
    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;
916
917
}

918
919
920
921
922
923
924
925
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;
}

926
927
928
929
930
// 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
931
    if (x->x_selected == x->x_glist)
932
        scalehandle_draw_select2(x);
933
934
}

935
936
937
//----------------------------------------------------------------
// IEMGUI refactor (by Mathieu)

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

946
void iemgui_label_draw_new(t_iemgui *x) {
947
    char col[8];
948
    t_canvas *canvas=glist_getcanvas(x->x_glist);
949
950
951
    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);
952
    sprintf(col, "#%6.6x", x->x_lcol);
953
    gui_vmess("gui_iemgui_label_new", "xxiissssi",
954
955
        canvas,
        x,
956
957
958
959
        x->x_ldx,
        x->x_ldy,
        col,
        x->x_lab != s_empty ? x->x_lab->s_name : "",
960
961
962
        iemgui_typeface(x),
        sys_fontweight,
        x->x_fontsize);
963
}
964

965
966
void iemgui_label_draw_move(t_iemgui *x) {
    t_canvas *canvas=glist_getcanvas(x->x_glist);
967
968
969
    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);
970
971
    //sys_vgui(".x%lx.c coords %lxLABEL %d %d\n",
    //    canvas, x, x1+x->x_ldx, y1+x->x_ldy);
972
973
974
975

    /* 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... */
976
977
978
    gui_vmess("gui_iemgui_label_coords", "xxii",
        glist_getcanvas(x->x_glist),
        x,
979
980
        x->x_ldx + x->legacy_x,
        x->x_ldy + x->legacy_y);
981
}
982

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