Subversion Repositories filter_foundry

Rev

Rev 85 | Rev 92 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 toby 1
/*
18 toby 2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
78 toby 3
    Copyright (C) 2003-7 Toby Thain, toby@telegraphics.com.au
2 toby 4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by  
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License  
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*/
19
 
20
/* This is PLATFORM INDEPENDENT user interface code - mainly dialog logic */
21
 
22
#include "ff.h"
23
 
24
#include "node.h"
25
#include "funcs.h"
26
#include "y.tab.h"
27
#include "choosefile.h"
28
#include "sprintf_tiny.h"
29
 
30
#ifdef MAC_ENV
31
        #include <files.h>
32
        #include <plstringfuncs.h>
33
 
34
        #define GETSLIDERVALUE GetDlgControlValue
35
        #define SETSLIDERVALUE SetDlgControlValue
36
        #define GETCTLTEXT getctltext
37
        #define SETCTLTEXT setctltext
38
        #define GETCTLTEXTINT getctltextint
39
        #define SETCTLTEXTINT setctltextint
40
        #define SELECTCTLTEXT selectctltext
41
#else
42
        #include <commctrl.h>
43
        #include "compat_string.h"
44
 
45
        #define GETSLIDERVALUE(d,i) SendDlgItemMessage(d,i,TBM_GETPOS,0,0)
46
        #define SETSLIDERVALUE(d,i,v) SendDlgItemMessage(d,i,TBM_SETPOS,TRUE,v)
47
        #define GETCTLTEXT GetDlgItemText
48
        #define SETCTLTEXT SetDlgItemText
49
        #define SELECTCTLTEXT SELECTDLGITEMTEXT
50
        #define GETCTLTEXTINT GetDlgItemInt
51
        #define SETCTLTEXTINT SetDlgItemInt
52
#endif
53
 
54
Boolean doupdates = true;
55
double zoomfactor,fitzoom;
56
 
57
void updateglobals(DIALOGREF dp);
58
struct node *updateexpr(DIALOGREF dp,int i);
59
void updatedialog(DIALOGREF dp);
60
void slidertextchanged(DIALOGREF dp,int item);
61
void updatezoom(DIALOGREF dp);
62
 
63
void updatedialog(DIALOGREF dp){
64
        int i;
65
 
66
        doupdates = false;
67
 
78 toby 68
        for(i = 0; i < 8; ++i){
2 toby 69
                SETSLIDERVALUE(dp,FIRSTCTLITEM+i,slider[i]);
70
                SETCTLTEXTINT(dp,FIRSTCTLTEXTITEM+i,slider[i],false);
71
        }
72
 
78 toby 73
        for(i = 0; i < 4; ++i){
74
                if(!gdata->standalone)
75
                        SETCTLTEXT(dp,FIRSTEXPRITEM+i,expr[i] ? expr[i] : "");
76
                if(i < nplanes)
2 toby 77
                        updateexpr(dp,FIRSTEXPRITEM+i);
78
        }
79
 
78 toby 80
        if(!gdata->standalone)
81
                SELECTCTLTEXT(dp,FIRSTEXPRITEM,0,-1);
2 toby 82
 
83
        doupdates = true;
84
}
85
 
86
/* copy dialog settings to global variables (sliders, expressions) */
87
 
88
void updateglobals(DIALOGREF dp){
89
        int i;
90
        char s[MAXEXPR+1];
91
 
78 toby 92
        for(i = 0; i < 8; ++i)
2 toby 93
                slider[i] = GETSLIDERVALUE(dp,FIRSTCTLITEM+i);
94
 
95
        if(!gdata->standalone)
78 toby 96
                for(i = 0; i < 4; ++i){
2 toby 97
                        /* stash expression strings */
98
                        if(GETCTLTEXT(dp,FIRSTEXPRITEM+i,s,MAXEXPR)){
99
                                if(expr[i])
100
                                        free(expr[i]);
101
                                if(!(expr[i] = my_strdup(s)))
102
                                        dbg("updateglobals: my_strdup returned zero??");
103
                        }else
104
                                dbg("updateglobals: GETCTLTEXT returned zero??");
105
                }
106
}
107
 
108
struct node *updateexpr(DIALOGREF dp,int item){
109
        char s[MAXEXPR+1];
110
        int i;
111
 
112
        i = item - FIRSTEXPRITEM;
113
 
114
        freetree(tree[i]);
115
 
116
        if(!gdata->standalone){
117
                GETCTLTEXT(dp,item,s,MAXEXPR);
118
 
119
                if(expr[i])
120
                        free(expr[i]);
121
                expr[i] = my_strdup(s);
122
        }
123
 
124
        tree[i] = parseexpr(expr[i]);
125
 
126
        if(!gdata->standalone){
127
                if(tree[i])
128
                        HideDialogItem(dp,FIRSTICONITEM+i);
129
                else{
130
                        err[i] = errstr;
131
                        errstart[i] = tokstart;
132
                        errpos[i] = tokpos;
133
                        ShowDialogItem(dp,FIRSTICONITEM+i);
134
                }
135
        }
136
        return tree[i];
137
}
138
 
139
void updatezoom(DIALOGREF dp){
140
        char s[10],*q = int_str(s,(int)(100./zoomfactor),10);
141
        *q++ = '%';
142
        *q = 0;
143
        SETCTLTEXT(dp,ZOOMLEVELITEM,s);
78 toby 144
        if(zoomfactor > 1.)
145
                ShowDialogItem(dp,ZOOMINITEM);
146
        else
147
                HideDialogItem(dp,ZOOMINITEM);
148
        if(zoomfactor < fitzoom)
149
                ShowDialogItem(dp,ZOOMOUTITEM);
150
        else
151
                HideDialogItem(dp,ZOOMOUTITEM);
2 toby 152
}
153
 
154
/* traverse expression tree, looking for constant references to sliders */
155
 
89 toby 156
static int checksl(struct node*p,int ctlflags[],int mapflags[]){
78 toby 157
        int s;
158
 
2 toby 159
        if(p){
160
                if( (p->kind==TOK_FN1 && p->v.sym->fn == (pfunc_type)ff_ctl)
161
                 || (p->kind==TOK_FN3 && p->v.sym->fn == (pfunc_type)ff_val) ){
162
                        if(p->child[0]->kind == TOK_NUM){
163
                                s = p->child[0]->v.value;
164
                                if(s>=0 && s<=7)
165
                                        ctlflags[s] = 1;
166
                        }else
167
                                return true; /* can't determine which ctl() */
78 toby 168
                }else if(p->kind==TOK_FN2 && p->v.sym->fn == (pfunc_type)ff_map){
2 toby 169
                        if(p->child[0]->kind == TOK_NUM){
170
                                s = p->child[0]->v.value;
171
                                if(s>=0 && s<=3){
172
                                        mapflags[s] = 1;
173
                                        ctlflags[s*2] = ctlflags[s*2+1] = 1;
174
                                }
175
                        }else
176
                                return true; /* can't determine which map() */
23 toby 177
                 }
2 toby 178
 
179
                return checksl(p->child[0],ctlflags,mapflags)
180
                        || checksl(p->child[1],ctlflags,mapflags)
181
                        || checksl(p->child[2],ctlflags,mapflags)
182
                        || checksl(p->child[3],ctlflags,mapflags)
183
                        || checksl(p->child[4],ctlflags,mapflags);     
89 toby 184
        }else
185
                return false;
2 toby 186
}
187
 
188
Boolean checksliders(int exprs,int ctlflags[],int mapflags[]){
189
        int i,f = false;
190
 
78 toby 191
        for(i = 4; i--;)
2 toby 192
                mapflags[i] = 0;
78 toby 193
        for(i = 8; i--;)
2 toby 194
                ctlflags[i] = 0;
195
 
78 toby 196
        for(i = 0; i < exprs; i++)
2 toby 197
                if(checksl(tree[i],ctlflags,mapflags))
198
                        f = true;
199
 
200
        return f;
201
}
202
 
203
void slidermoved(DIALOGREF dp,int i){
204
        int v = GETSLIDERVALUE(dp,i);
205
        i -= FIRSTCTLITEM;
206
        slider[i] = v;
207
        SETCTLTEXTINT(dp,i+FIRSTCTLTEXTITEM,v,false);
208
}
209
 
210
void slidertextchanged(DIALOGREF dp,int i){
211
        int v = GETCTLTEXTINT(dp,i,NULL,false);
212
        i -= FIRSTCTLTEXTITEM;
213
        SETSLIDERVALUE(dp,i+FIRSTCTLITEM,v);
214
        slider[i] = v;
215
}
216
 
217
void maindlgupdate(DIALOGREF dp){
218
        int i,unknown,ctls[8],maps[4];
219
 
220
        unknown = checksliders(nplanes,ctls,maps);
221
 
78 toby 222
        for(i = 0; i < 8; i++)
2 toby 223
                if(unknown || ctls[i]){
224
                        ENABLEDLGITEM(dp,FIRSTCTLITEM+i);
225
                        ShowDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
226
                }else{
227
                        DISABLEDLGITEM(dp,FIRSTCTLITEM+i);
228
                        HideDialogItem(dp,FIRSTCTLTEXTITEM+i); /* FIXME: this changes keyboard focus */
229
                }
230
 
78 toby 231
        for(i = 0; i < nplanes; i++)
2 toby 232
                if(!tree[i]){
233
                        /* uh oh, couldn't parse one of the saved expressions...this is fatal */
234
                        DISABLEDLGITEM(dp,IDOK);
235
                        if(gdata->standalone){
236
                                alertuser("Can't run this filter (there is a problem with the saved expressions).","");
237
                        }else{
238
                                DISABLEDLGITEM(dp,SAVEITEM);
239
                                DISABLEDLGITEM(dp,MAKEITEM);
240
                        }
241
                        return;
242
                }
243
 
244
        /* we have valid expression trees in all slots...proceed! */
245
        updateglobals(dp);
246
        if(setup(gpb))
247
                recalc_preview(gpb,dp);
248
 
249
        ENABLEDLGITEM(dp,IDOK);
250
        if(!gdata->standalone){
251
                ENABLEDLGITEM(dp,SAVEITEM);
252
                ENABLEDLGITEM(dp,MAKEITEM);
253
        }
254
}
255
 
256
/* one-time initialisation of dialog box */
257
 
258
void maindlginit(DIALOGREF dp){
259
        char s[0x100];
260
        int i;
89 toby 261
        char *channelsuffixes[] = {
262
                "", "GA", "I", "RGBA",
263
                "CMYK", "HSL", "HSB", "1234",
264
                "DA", "LabA"
265
        };
2 toby 266
 
267
        /* hide unused expression items */
268
        if(gdata->standalone){
85 toby 269
#ifdef WIN_ENV
270
                myp2cstrcpy(s,gdata->parm.title);
271
                SetWindowText(dp,s); // window title bar
272
#endif
78 toby 273
                myp2cstrcpy(s,gdata->parm.author);
274
                SetDlgItemText(dp,PARAMAUTHORITEM,s);
275
                myp2cstrcpy(s,gdata->parm.copyright);
276
                SetDlgItemText(dp,PARAMCOPYITEM,s);
57 toby 277
 
278
                // update labels for map() or ctl() sliders
78 toby 279
                for(i = 0; i < 8; ++i){
2 toby 280
                        if(gdata->parm.ctl_used[i]){
78 toby 281
                                myp2cstrcpy(s,gdata->parm.ctl[i]);
282
                                SetDlgItemText(dp,FIRSTCTLLABELITEM+i,s);
2 toby 283
                        }else if(gdata->parm.map_used[i/2]){
284
                                if(i&1)
285
                                        HideDialogItem(dp,FIRSTCTLLABELITEM+i);
286
                                else{
78 toby 287
                                        myp2cstrcpy(s,gdata->parm.map[i/2]);
288
                                        SetDlgItemText(dp,FIRSTCTLLABELITEM+i,s);
2 toby 289
                                }
290
                        }else{
291
                                HideDialogItem(dp,FIRSTCTLITEM+i);
292
                                HideDialogItem(dp,FIRSTCTLTEXTITEM+i);
293
                                HideDialogItem(dp,FIRSTCTLLABELITEM+i);
294
                        }
295
                }
89 toby 296
        }
297
 
298
        strcpy(s,"X =");
299
        for(i = 0; i < 4; ++i){
300
                if(i >= nplanes){
2 toby 301
                        HideDialogItem(dp,FIRSTICONITEM+i);
302
                        HideDialogItem(dp,FIRSTEXPRITEM+i);
303
                        HideDialogItem(dp,FIRSTLABELITEM+i);
89 toby 304
                }else{
305
                        s[0] = channelsuffixes[gpb->imageMode][i];
306
                        SetDlgItemText(dp,FIRSTLABELITEM+i,s);
2 toby 307
                }
89 toby 308
        }
2 toby 309
 
310
        if(setup_preview(gpb)){
311
                extern int preview_w,preview_h;
89 toby 312
                double zh = (gpb->filterRect.right - gpb->filterRect.left)/(double)preview_w,
313
                       zv = (gpb->filterRect.bottom - gpb->filterRect.top)/(double)preview_h;
2 toby 314
                fitzoom = zh > zv ? zh : zv;
37 toby 315
 
316
                // On very large images, processing a fully zoomed out preview (the initial default)
317
                // can cause out of memory errors, because Photoshop can't page in all data
318
                // during advanceState. To prevent this problem, zoom in until we aren't
319
                // previewing more than say 10% of Photoshop's indicated maxSpace.
320
                // (e.g., on a 1GB WinXP system, PS CS2 reports 520MB maxSpace, so this will let us
321
                // preview about 50MB of image data.)
322
 
85 toby 323
                zoomfactor = sqrt(maxSpace/(10.*preview_w*preview_h*nplanes));
324
                if(zoomfactor > fitzoom)
325
                        zoomfactor = fitzoom;
326
                if(zoomfactor < 1.)
327
                        zoomfactor = 1.;
37 toby 328
 
2 toby 329
                updatezoom(dp);
330
        }else{
331
                HideDialogItem(dp,ZOOMINITEM);
332
                HideDialogItem(dp,ZOOMOUTITEM);
333
                HideDialogItem(dp,ZOOMLEVELITEM);
334
        }
335
 
336
#ifdef WIN_ENV
9 toby 337
  // can't build standalone filter on less than NT platform :-(
338
  // due to absence of resource editing API (UpdateResource etc)
339
  if(!isWin32NT())
340
    HideDialogItem(dp,MAKEITEM);
2 toby 341
#endif
342
 
343
        updatedialog(dp);
344
        maindlgupdate(dp);
345
}
346
 
347
 
348
/* process an item hit. return false if the dialog is finished; otherwise return true. */
349
 
350
Boolean maindlgitem(DIALOGREF dp,int item){
37 toby 351
        extern int previewerr;
352
 
2 toby 353
        StandardFileReply sfr;
354
        NavReplyRecord reply;
355
        static OSType types[] = {TEXT_FILETYPE,PS_FILTER_FILETYPE};
356
        char *reason;
357
        Str255 fname;
358
 
359
        switch(item){
78 toby 360
        case IDOK:
2 toby 361
        case IDCANCEL:
362
                dispose_preview();
363
                return false; // end dialog
364
        case OPENITEM:
32 toby 365
                if(!gdata->standalone && choosefiletypes("\pChoose filter settings",&sfr,&reply,types,2,
78 toby 366
                                        "All supported files (.afs, .8bf, .txt)\0*.afs;*.8bf;*.txt\0All files (*.*)\0*.*\0\0")){
2 toby 367
                        if(loadfile(&sfr,&reason)){
368
                                updatedialog(dp);
369
                                maindlgupdate(dp);
78 toby 370
                        }else
371
                                alertuser("Cannot load settings.",reason);
2 toby 372
                }
373
                break;
374
        case SAVEITEM:
39 toby 375
                if(!gdata->standalone && putfile("\pSave filter settings",(StringPtr)"",
32 toby 376
                                                                                 TEXT_FILETYPE,SIG_SIMPLETEXT,&reply,&sfr,
78 toby 377
                                                                                 "afs","Settings file (.afs, .txt)\0*.afs;*.txt\0\0",1)){
2 toby 378
                        if(savefile(&sfr))
379
                                completesave(&reply);
380
                }
381
                break;
382
        case MAKEITEM:
383
                if( !gdata->standalone && builddialog(gpb) ){
384
                        PLstrcpy(fname,gdata->parm.title);
11 toby 385
#ifdef MACMACHO
78 toby 386
                        PLstrcat(fname,(StringPtr)"\p.plugin");
11 toby 387
#endif
2 toby 388
                        if( putfile("\pMake standalone filter",fname,
32 toby 389
                                                PS_FILTER_FILETYPE,kPhotoshopSignature,&reply,&sfr,
78 toby 390
                                                "8bf","Filter plugin file (.8bf)\0*.8bf\0\0",1) )
2 toby 391
                                make_standalone(&sfr);
392
                }
393
                break;
394
        case ZOOMINITEM:
78 toby 395
                zoomfactor = zoomfactor > 2. ? zoomfactor/2. : 1.;
2 toby 396
                updatezoom(dp);
37 toby 397
                previewerr = false;
2 toby 398
                recalc_preview(gpb,dp);
399
                break;
400
        case ZOOMOUTITEM:
401
                zoomfactor *= 2.;
402
                if(zoomfactor > fitzoom)
403
                        zoomfactor = fitzoom;
404
                updatezoom(dp);
37 toby 405
                previewerr = false;
2 toby 406
                recalc_preview(gpb,dp);
407
                break;
408
        case ZOOMLEVELITEM:
41 toby 409
                zoomfactor = zoomfactor > 1. ? 1. : fitzoom;
2 toby 410
                updatezoom(dp);
37 toby 411
                previewerr = false;
2 toby 412
                recalc_preview(gpb,dp);
413
                break;
414
        case FIRSTCTLITEM:
415
        case FIRSTCTLITEM+1:
416
        case FIRSTCTLITEM+2:
417
        case FIRSTCTLITEM+3:
418
        case FIRSTCTLITEM+4:
419
        case FIRSTCTLITEM+5:
420
        case FIRSTCTLITEM+6:
421
        case FIRSTCTLITEM+7:
422
                slidermoved(dp,item);
423
                recalc_preview(gpb,dp);
424
                break;
425
        case FIRSTCTLTEXTITEM:
426
        case FIRSTCTLTEXTITEM+1:
427
        case FIRSTCTLTEXTITEM+2:
428
        case FIRSTCTLTEXTITEM+3:
429
        case FIRSTCTLTEXTITEM+4:
430
        case FIRSTCTLTEXTITEM+5:
431
        case FIRSTCTLTEXTITEM+6:
432
        case FIRSTCTLTEXTITEM+7:
433
                slidertextchanged(dp,item);
434
                recalc_preview(gpb,dp);
435
                break;
436
        case FIRSTICONITEM:
437
        case FIRSTICONITEM+1:
438
        case FIRSTICONITEM+2:
439
        case FIRSTICONITEM+3:
440
                item -= FIRSTICONITEM;
441
                alertuser(err[item],"");
442
                SELECTCTLTEXT(dp,FIRSTEXPRITEM+item,errstart[item],errpos[item]);
443
                break;
444
        case FIRSTEXPRITEM:
445
        case FIRSTEXPRITEM+1:
446
        case FIRSTEXPRITEM+2:
447
        case FIRSTEXPRITEM+3:
78 toby 448
                if((item-FIRSTEXPRITEM) < nplanes){
2 toby 449
                        updateexpr(dp,item);
450
                        maindlgupdate(dp);
451
                }
452
                break;
453
        }
454
 
455
        return true; // keep going
456
}
457
 
458
Boolean alertuser(char *err,char *more){
459
        char *s = malloc(strlen(err)+strlen(more)+2),*q;
460
        Boolean res;
461
 
462
        q = cat(s,err);
463
        *q++ = '\n';
464
        q = cat(q,more);
465
        *q = 0;
466
        res = simplealert(s);
467
        free(s);
468
        return res;
469
}