List.cpp

Zbigniew Rebacz, 01/31/2014 09:58 PM

Download (8.76 KB)

 
1
#include "IconDes.h"
2

    
3
NAMESPACE_UPP
4

    
5
static String sFormatImageName(const String& name, const Image& img, bool exp)
6
{
7
        Size sz = img.GetSize();
8
        String r;
9
        r << name << " (" << sz.cx << " x " << sz.cy << ')';
10
        if(exp)
11
                r << " ex.";
12
        return r;
13
}
14

    
15
void IconDes::SyncList()
16
{
17
        int a = list.GetCursorSc();
18
        int ii = list.GetCursor();
19
        list.Clear();
20
        for(int i = 0; i < slot.GetCount(); i++) {
21
                Slot& c = slot[i];
22
                list.Add(sFormatImageName(c.name, c.image, c.exp), c.image);
23
        }
24
        if(ii >= 0) {
25
                list.SetCursor(ii);
26
                list.ScCursor(a);
27
        }
28
}
29

    
30
static int sCharFilterCid(int c)
31
{
32
        return IsAlNum(c) || c == '_' ? c : 0;
33
}
34

    
35
void IconDes::PlaceDlg(TopWindow& dlg)
36
{
37
        Rect r = list.GetScreenRect();
38
        Size sz = dlg.GetSize();
39
        dlg.NoCenter().SetRect(max(0, r.left + (r.Width() - sz.cx) / 2), r.bottom + 32, sz.cx, sz.cy);
40
}
41

    
42
void IconDes::PrepareImageDlg(WithImageLayout<TopWindow>& dlg)
43
{
44
        CtrlLayoutOKCancel(dlg, "New image");
45
        dlg.cx <<= 16;
46
        dlg.cy <<= 16;
47
        if(IsCurrent()) {
48
                Size sz = GetImageSize();
49
                dlg.cx <<= sz.cx;
50
                dlg.cy <<= sz.cy;
51
        }
52
        dlg.name.SetFilter(sCharFilterCid);
53
}
54

    
55
void IconDes::PrepareImageSizeDlg(WithImageSizeLayout<TopWindow>& dlg)
56
{
57
        CtrlLayoutOKCancel(dlg, "New image");
58
        dlg.cx <<= 16;
59
        dlg.cy <<= 16;
60
        if(IsCurrent()) {
61
                Size sz = GetImageSize();
62
                dlg.cx <<= sz.cx;
63
                dlg.cy <<= sz.cy;
64
        }
65
}
66

    
67
bool CheckName(WithImageLayout<TopWindow>& dlg)
68
{
69
        String n = dlg.name;
70
        CParser p(n);
71
        if(p.IsId()) return true;
72
        Exclamation("Invalid name!");
73
        return false;
74
}
75

    
76
void IconDes::InsertRemoved(int q)
77
{
78
        if(q >= 0 && q < removed.GetCount()) {
79
                int ii = list.IsCursor() ? list.GetCursor() : 0;
80
                slot.Insert(ii) = removed[q];
81
                removed.Remove(q);
82
                SyncList();
83
                list.SetCursor(ii);
84
        }
85
}
86

    
87
void IconDes::ImageInsert(const String& name, const Image& m, bool exp)
88
{
89
        int ii = list.IsCursor() ? list.GetCursor() : 0;
90
        if(ii == list.GetCount() - 1)
91
                ii = list.GetCount();
92
        Slot& c = slot.Insert(ii);
93
        c.name = name;
94
        c.image = m;
95
        c.exp = exp;
96
        SyncList();
97
        list.SetCursor(ii);
98
}
99

    
100
void IconDes::InsertImage()
101
{
102
        WithImageLayout<TopWindow> dlg;
103
        PrepareImageDlg(dlg);
104
        do {
105
                if(dlg.Run() != IDOK)
106
                        return;
107
        }
108
        while(!CheckName(dlg));
109
        ImageInsert(~dlg.name, CreateImage(Size(~dlg.cx, ~dlg.cy), Null), dlg.exp);
110
}
111

    
112
void IconDes::Duplicate()
113
{
114
        if(!IsCurrent())
115
                return;
116
        Slot& c = Current();
117
        ImageInsert(c.name, c.image);
118
        EditImage();
119
}
120

    
121
void IconDes::InsertPaste()
122
{
123
        Image m = ReadClipboardImage();
124
        if(IsNull(m)) {
125
                Exclamation("Clipboard does not contain an image.");
126
                return;
127
        }
128
        ImageInsert("", m);
129
        EditImage();
130
}
131

    
132
struct FileImage : ImageMaker {
133
        String filename;
134
        Size   size;
135
        
136
        virtual String Key() const { return filename + '/' + AsString(size); }
137
        virtual Image Make() const {
138
                if(GetFileLength(filename) > 1024 * 1024 * 20)
139
                        return Null;
140
                Image m = StreamRaster::LoadFileAny(filename);
141
                Size sz = m.GetSize();
142
                if(sz.cx > size.cx || sz.cy > size.cy) {
143
                        if(sz.cx * size.cy > sz.cy * size.cx)
144
                                sz = GetRatioSize(sz, size.cx, 0);
145
                        else
146
                                sz = GetRatioSize(sz, 0, size.cy);
147
                        return Rescale(m, sz);
148
                }
149
                return m;
150
        }
151
};
152

    
153
struct ImgPreview : Display {
154
        virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const {
155
                if(!IsNull(q)) {
156
                        FileImage im;
157
                        im.size = r.GetSize();
158
                        im.filename = q;
159
                        w.DrawRect(r, SColorPaper);
160
                        Image m = MakeImage(im);
161
                        Point p = r.CenterPos(m.GetSize());
162
                        w.DrawImage(p.x, p.y, m);
163
                }
164
        }
165
};
166

    
167
FileSel& IconDes::ImgFile()
168
{
169
        static FileSel sel;
170
        ONCELOCK {
171
                sel.Type("Image files", "*.png *.bmp *.jpg *.jpeg *.gif");
172
                sel.AllFilesType();
173
                sel.Multi();
174
                sel.Preview(Single<ImgPreview>());
175
        }
176
        return sel;
177
}
178

    
179
int CharFilterImageId(int c)
180
{
181
        return IsAlNum(c) ? c : '_';
182
}
183

    
184
void IconDes::InsertFile()
185
{
186
        if(!ImgFile().ExecuteOpen()) return;
187
        for(int i = 0; i < ImgFile().GetCount(); i++) {
188
                String fn = ImgFile()[i];
189
                Image m = StreamRaster::LoadFileAny(fn);
190
                if(IsNull(m))
191
                        Exclamation(DeQtf(fn) + " not an image.");
192
                String id = Filter(GetFileTitle(fn), CharFilterImageId);
193
                if(!IsAlpha(*id) && *id != '_')
194
                        id = '_' + id;
195
                ImageInsert(id, m);
196
        }
197
}
198

    
199
void IconDes::ExportPngs()
200
{
201
        String dir = SelectDirectory();
202
        if(!dir.IsEmpty()) 
203
                for(int i = 0; i < GetCount(); i++)
204
                        PNGEncoder().SaveFile(AppendFileName(dir, GetName(i) + ".png"), GetImage(i));
205
}
206

    
207
void IconDes::InsertIml()
208
{
209
        Array<ImlImage> m;
210
        int f;
211
        if(LoadIml(SelectLoadFile("Iml files\t*.iml"), m, f))
212
                for(int i = 0; i < m.GetCount(); i++) {
213
                        ImageInsert(m[i].name, m[i].image, m[i].exp);
214
                        list.SetCursor(list.GetCursor() + 1);
215
                }
216
}
217

    
218
void IconDes::ListCursor()
219
{
220
        SyncImage();
221
}
222

    
223
void IconDes::EditImageSize()
224
{
225
        Slot& c = Current();
226
        WithImageSizeLayout<TopWindow> dlg;
227
        PrepareImageSizeDlg(dlg);
228
        dlg.Breaker(dlg.cx);
229
        dlg.Breaker(dlg.cy);
230
        Image img = c.image;
231
        dlg.cx <<= img.GetWidth();
232
        dlg.cy <<= img.GetHeight();
233
        for(;;) {
234
                switch(dlg.Run()) {
235
                case IDCANCEL:
236
                        c.image = img;
237
                        Reset();
238
                        return;
239
                case IDOK:
240
                        Reset();
241
                        return;
242
                }
243
                c.image = CreateImage(Size(minmax((int)~dlg.cx, 1, 8192), minmax((int)~dlg.cy, 1, 8192)), Null);
244
                UPP::Copy(c.image, Point(0, 0), img, img.GetSize());
245
                Reset();
246
        }
247
}
248

    
249
void IconDes::EditImage()
250
{
251
        if(!IsCurrent())
252
                return;
253
        if(single_mode) {
254
                EditImageSize();
255
                return;
256
        }
257
        Slot& c = Current();
258
        WithImageLayout<TopWindow> dlg;
259
        PrepareImageDlg(dlg);
260
        dlg.Breaker(dlg.cx);
261
        dlg.Breaker(dlg.cy);
262
        Image img = c.image;
263
        dlg.cx <<= img.GetWidth();
264
        dlg.cy <<= img.GetHeight();
265
        dlg.name <<= c.name;
266
        dlg.exp <<= c.exp;
267
        for(;;) {
268
                switch(dlg.Run()) {
269
                case IDCANCEL:
270
                        c.image = img;
271
                        Reset();
272
                        return;
273
                case IDOK:
274
                        if(!CheckName(dlg)) break;
275
                        c.name = ~dlg.name;
276
                        c.exp = ~dlg.exp;
277
                        list.Set(0, sFormatImageName(c.name, c.image, c.exp));
278
                        Reset();
279
                        return;
280
                }
281
                c.image = CreateImage(Size(minmax((int)~dlg.cx, 1, 8192), minmax((int)~dlg.cy, 1, 8192)), Null);
282
                UPP::Copy(c.image, Point(0, 0), img, img.GetSize());
283
                Reset();
284
        }
285
}
286

    
287
void IconDes::RemoveImage()
288
{
289
        if(!IsCurrent() || !PromptYesNo("Remove current image?"))
290
                return;
291
        int ii = list.GetCursor();
292
        while(removed.GetCount() > 12)
293
                removed.Remove(0);
294
        Slot& r = removed.Add();
295
        r = slot[ii];
296
        if(r.image.GetWidth() <= 128 && r.image.GetHeight() <= 128)
297
                r.base_image = Rescale(r.image, Size(16, 16));
298
        else
299
                r.base_image = IconDesImg::LargeImage();
300
        slot.Remove(ii);
301
        list.KillCursor();
302
        SyncList();
303
        if(ii < slot.GetCount())
304
                list.SetCursor(ii);
305
        else
306
                list.GoEnd();
307
}
308

    
309
void IconDes::MoveSlot(int d)
310
{
311
        if(!IsCurrent())
312
                return;
313
        int c = list.GetCursor();
314
        d = c + d;
315
        if(d >= 0 && d < slot.GetCount()) {
316
                slot.Swap(c, d);
317
                SyncList();
318
                list.SetCursor(d);
319
        }
320
}
321

    
322
void IconDes::ChangeSlot(int d)
323
{
324
        if(!IsCurrent())
325
                return;
326
        int c = list.GetCursor();
327
        d = c + d;
328
        if(d >= 0 && d < slot.GetCount())
329
                list.SetCursor(d);
330
}
331

    
332
void IconDes::ListMenu(Bar& bar)
333
{
334
        using namespace IconDesKeys;
335
        if(single_mode)
336
                bar.Add(IsCurrent(), AK_RESIZE_SINGLE, IconDesImg::Edit(), THISBACK(EditImage));
337
        else {
338
                bar.Add(AK_INSERT_IMAGE, IconDesImg::Insert(), THISBACK(InsertImage));
339
                bar.Add(IsCurrent(), AK_IMAGE, IconDesImg::Edit(), THISBACK(EditImage));
340
                bar.Add(IsCurrent(), AK_REMOVE_IMAGE, IconDesImg::Remove(), THISBACK(RemoveImage));
341
                bar.Add(IsCurrent(), AK_DUPLICATE, IconDesImg::Duplicate(), THISBACK(Duplicate));
342
                bar.Add(AK_INSERT_CLIP, IconDesImg::InsertPaste(), THISBACK(InsertPaste));
343
                bar.Add(AK_INSERT_FILE, IconDesImg::InsertFile(), THISBACK(InsertFile));
344
                bar.Add(AK_INSERT_IML, IconDesImg::InsertIml(), THISBACK(InsertIml));
345
                bar.Add(AK_EXPORT_PNGS, IconDesImg::ExportPngs(), THISBACK(ExportPngs));
346
                bar.Separator();
347
                bar.Add(IsCurrent() && list.GetCursor() > 0, AK_MOVE_UP, IconDesImg::MoveUp(),
348
                        THISBACK1(MoveSlot, -1));
349
                bar.Add(IsCurrent() && list.GetCursor() < slot.GetCount() - 1, AK_MOVE_DOWN, IconDesImg::MoveDown(),
350
                        THISBACK1(MoveSlot, 1));
351
                if(removed.GetCount()) {
352
                        bar.Separator();
353
                        for(int i = removed.GetCount() - 1; i >= 0; i--) {
354
                                Slot& r = removed[i];
355
                                bar.Add("Insert " + sFormatImageName(r.name, r.image, r.exp), r.base_image,
356
                                        THISBACK1(InsertRemoved, i));
357
                        }
358
                }
359
        }
360
        bar.Separator();
361
        EditBar(bar);
362
        ListMenuEx(bar);
363
}
364

    
365
void IconDes::ListMenuEx(Bar& bar) {}
366

    
367

    
368
void IconDes::Clear()
369
{
370
        list.Clear();
371
        slot.Clear();
372
        Reset();
373
}
374

    
375
void IconDes::AddImage(const String& name, const Image& image, bool exp)
376
{
377
        Slot& c = slot.Add();
378
        c.name = name;
379
        c.image = image;
380
        c.exp = exp;
381
        list.Add(sFormatImageName(c.name, c.image, c.exp), c.image);
382
        list.GoBegin();
383
}
384

    
385
int IconDes::GetCount() const
386
{
387
        return slot.GetCount();
388
}
389

    
390
Image IconDes::GetImage(int ii) const
391
{
392
        const Slot& c = slot[ii];
393
        Image m = slot[ii].image;
394
        return c.supersampling ? DownSample3x(m) : m;
395
}
396

    
397
String IconDes::GetName(int ii) const
398
{
399
        return slot[ii].name;
400
}
401

    
402
String IconDes::GetCurrentName() const
403
{
404
        if(list.IsCursor())
405
                return slot[list.GetCursor()].name;
406
        return String();
407
}
408

    
409
bool IconDes::GetExport(int ii) const
410
{
411
        return slot[ii].exp;
412
}
413

    
414
END_UPP_NAMESPACE