Subversion Repositories filter_foundry

Rev

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