ide/i18n: Added some more i18n'ed strings
[sdk] / ide / src / documents / PictureEdit.ec
1 /****************************************************************************
2    ECERE IDE
3
4    Copyright (c) 2003 Jerome Jacovella-St-Louis
5    All Rights Reserved.
6    
7    pictureEdit.ec - Picture Editor Control
8 ****************************************************************************/
9 #ifdef ECERE_STATIC
10 import static "ecere"
11 #else
12 import "ecere"
13 #endif
14
15 #define ID_IMAGE_MODE_COLORTABLE 9
16 #define ID_IMAGE_MODE_INDEXED    10
17 #define ID_IMAGE_MODE_RGB        11
18
19 static Array<FileFilter> filters
20 { [
21    { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
22    { $"All files", null }
23 ] };
24
25 static Array<FileType> types
26 { [
27    { $"Based on extension", null,  never },
28    { $"JPG Image",          "jpg", always },
29    { $"BMP Image",          "bmp", always },
30    { $"PCX Image",          "pcx", always },
31    { $"PNG Image",          "png", always },
32    { $"GIF Image",          "gif", always }
33 ] };
34
35 FileDialog pictureEditFileDialog { filters = filters.array, sizeFilters = filters.count * sizeof(FileFilter), types = types.array, sizeTypes = types.count * sizeof(FileType) };
36
37 class PictureEdit : Window
38 {
39    background = black;
40    isDocument = true;
41    isActiveClient = true;
42    menu = Menu { };
43
44    OnHScroll = OnScroll;
45    OnVScroll = OnScroll;
46
47    float zoomFactor;
48    char fileName[MAX_LOCATION];
49    Bitmap bitmap;
50    
51    //saveDialog = pictureEditFileDialog;
52    
53    Menu fileMenu { menu, $"File", f }
54       MenuItem { fileMenu, $"Save", s, ctrlS, NotifySelect = MenuFileSave };
55       MenuItem { fileMenu, $"Save As...", a, NotifySelect = MenuFileSaveAs };
56    Menu imageMenu { menu, $"Image", i };
57       Menu modeMenu { imageMenu, $"Mode", m };
58          MenuItem imageModeIndexedItem
59          {
60             modeMenu, $"Indexed Color...", i, isRadio = true;
61             bool NotifySelect(MenuItem selection, Modifiers mods)
62             {
63                ColorAlpha * palette = bitmap.Quantize(0, 255);
64                /*
65                eBitmap_Convert(null, bitmap, PixelFormat8, palette);
66                bitmap.allocatePalette = true;
67                */               
68                
69                imageModeColorTableItem.disabled = false;
70                Update(null);
71                modifiedDocument = true;
72                return true;
73             }
74          };
75          MenuItem imageModeRGBItem
76          {
77             modeMenu, $"RGB Color", r, isRadio = true;
78             bool NotifySelect(MenuItem selection, Modifiers mods)
79             {
80                bitmap.Convert(null, pixelFormat888, null);
81                imageModeColorTableItem.disabled = true;
82                Update(null);
83                modifiedDocument = true;
84                return true;
85             }
86          };
87          MenuDivider { modeMenu };
88          MenuItem imageModeColorTableItem
89          {
90             modeMenu, $"Color Table", r;
91             bool NotifySelect(MenuItem selection, Modifiers mods)
92             {
93                PictureEditColorTable colorTable { master = this };
94                colorTable.Modal();
95                Update(null);
96                return true;
97             }
98          };
99          #ifdef _DEBUG
100          MenuDivider { imageMenu };
101          MenuItem adjustHSVItem
102          {
103             imageMenu, $"Adjust Hue, Saturation, Value", h;
104             bool NotifySelect(MenuItem selection, Modifiers mods)
105             {
106                AdjustHSV adjustHSV { master = this };
107                adjustHSV.Modal();
108                Update(null);
109                return true;
110             }
111          };
112          #endif
113    
114    property char * bitmapFile
115    {
116       set
117       {
118          if(value)
119          {
120             strcpy(fileName, value);
121          }
122          if(fileName[0])
123          {
124             bitmap = Bitmap {};
125             if(bitmap.Load(fileName, null, null))
126             {
127                if(bitmap.pixelFormat == pixelFormatRGBA)
128                   bitmap.Convert(null, pixelFormat888, null);
129
130                //if(!eWindow_GetStartWidth(window) || !eWindow_GetStartHeight(window))
131                {
132                   Size size = initSize;  // what's the use of retrieving initSize
133                   size.w = bitmap.width;
134                   size.h = bitmap.height;
135                   clientSize = size;
136
137                   /*
138                   Move(eWindow_GetStartX(window), eWindow_GetStartY(window), 
139                      (!eWindow_GetStartWidth(window)) ? (A_CLIENT|bitmap.width) : eWindow_GetStartWidth(window), 
140                      (!eWindow_GetStartHeight(window)) ? (A_CLIENT|bitmap.height) : eWindow_GetStartHeight(window));
141                   */
142
143                   /*
144                   Move(eWindow_GetStartX(window), eWindow_GetStartY(window), 
145                      (!) ? (A_CLIENT|bitmap.width) : eWindow_GetStartWidth(window), 
146                      (!eWindow_GetStartHeight(window)) ? (A_CLIENT|bitmap.height) : eWindow_GetStartHeight(window));
147                   */
148                }
149                scrollArea = Size {bitmap.width, bitmap.height };
150             }
151             else
152                delete bitmap;
153          }
154
155          if(bitmap)
156          {
157             switch(bitmap.pixelFormat)
158             {
159                case pixelFormat8:
160                   imageModeIndexedItem.checked = true;
161                   break;
162                case pixelFormat888:
163                   imageModeRGBItem.checked = true;
164                   imageModeColorTableItem.disabled = true;
165                   break;
166             }
167          }
168       }
169    }
170
171    void OnRedraw(Surface surface)
172    {
173       if(bitmap)
174       {
175          int w = (int)(bitmap.width * zoomFactor);
176          int h = (int)(bitmap.height * zoomFactor);
177          if(w == bitmap.width && h == bitmap.height)
178          {
179             surface.Blit(bitmap, 
180                Max(0, (clientSize.w - w) / 2), Max(0, (clientSize.h - h) / 2), 
181                scroll.x, scroll.y, w, h);
182          }
183          else
184          {
185             surface.Filter(bitmap, 
186                Max(0, (clientSize.w - w) / 2), Max(0, (clientSize.h - h) / 2), 
187                (int)(scroll.x / zoomFactor), (int)(scroll.y / zoomFactor), w, h, 
188                bitmap.width, bitmap.height);
189          }
190       }
191    }
192
193    void OnScroll(ScrollBarAction action, int position, Key key)
194    {
195       Update(null);
196    }
197
198    bool OnKeyHit(Key key, unichar ch)
199    {
200       switch(key)
201       {
202          case equal:
203          case keyPadPlus:
204             if(zoomFactor < 25)
205             {
206                float x = 0.5f, y = 0.5f;
207                if(bitmap.width * zoomFactor > clientSize.w) 
208                   x = scroll.x / (bitmap.width * zoomFactor - clientSize.w);
209                if(bitmap.height * zoomFactor > clientSize.h) 
210                   y = scroll.y / (bitmap.height * zoomFactor - clientSize.h);
211
212                zoomFactor *= 1.5;
213                scrollArea = Size { bitmap.width * zoomFactor,  bitmap.height * zoomFactor };
214
215                scroll = Point { 
216                      (int)(Max(0, bitmap.width * zoomFactor - clientSize.w) * x), 
217                      (int)(Max(0, bitmap.height * zoomFactor - clientSize.h) * y) };
218
219                Update(null);
220             }
221             break;
222          case minus:
223          case keyPadMinus:
224             if(zoomFactor > 0.05)
225             {
226                float x = 0.5f, y = 0.5f;
227                if(bitmap.width * zoomFactor > clientSize.w) 
228                   x = scroll.x / (bitmap.width * zoomFactor - clientSize.w);
229                if(bitmap.height * zoomFactor > clientSize.w) 
230                   y = scroll.y / (bitmap.height * zoomFactor - clientSize.h);
231
232                zoomFactor /= 1.5;
233                scrollArea = Size { bitmap.width * zoomFactor, bitmap.height * zoomFactor };
234
235                scroll = Point { 
236                      (int)(Max(0, bitmap.width * zoomFactor - clientSize.w) * x),
237                      (int)(Max(0, bitmap.height * zoomFactor - clientSize.h) * y) };
238
239                Update(null);
240             }
241             break;
242       }
243       return true;
244    }
245
246    bool OnSaveFile(char * fileName)
247    {
248       bool result = false;
249       if(bitmap)
250       {
251          if(bitmap.Save(fileName, 
252             ((FileType *)pictureEditFileDialog.types)[pictureEditFileDialog.fileType].typeExtension, (void *) bool::true))
253          {
254             modifiedDocument = false;
255             result = true;
256          }
257       }
258       return result;
259    }
260    
261    PictureEdit()
262    {
263       zoomFactor = 1.0f;
264       return true;
265    }
266
267 }
268
269 class PictureEditColorTable : Window
270 {
271    hasClose = true;
272    text = $"Color Table";
273    background = activeBorder;
274    minClientSize = Size { 400, 400 };
275
276    Button button
277    {
278       parent = this, hotKey = escape, size = { 80 }, text = $"Close";
279       anchor = Anchor { right = 10, bottom = 10 };
280       NotifyClicked = ButtonCloseDialog;
281    };
282
283    void OnRedraw(Surface surface)
284    {
285       PictureEdit picture = (PictureEdit)master;
286       Bitmap bitmap = picture.bitmap;
287       int c;
288       for(c = 0; c < 256; c++)
289       {
290          int x = (c % 16) * 16;
291          int y = (c / 16) * 16;
292          surface.SetBackground(bitmap.palette[c]);
293          surface.Area(10 + x, 30 + y, 10 + x + 15, 30 + y + 15);
294       }
295    }
296 }
297
298 class ColorBox : Window
299 {
300    size = { 32, 32 };
301    borderStyle = deepContour;
302 }
303
304 #ifdef _DEBUG
305 class AdjustHSV : Window
306 {
307    size = { 400, 300 };
308
309    background = activeBorder;
310    ColorHSV target;
311    ColorHSV replace;
312    replace = { 248, 100, 71 }; //Color { 26, 0, 183 };
313    target = { 207, 61, 71 };
314    hasClose = true;
315
316    Button button1
317    {
318       this, text = $"Go", position = { 296, 104 }, isDefault = true;
319
320       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
321       {
322          PictureEdit picture = (PictureEdit)master;
323          Bitmap bitmap = picture.bitmap;
324          double h = 1.0f, s = 0.80f, v = 1.24f;
325          double tolH = 1;
326          double tolS = 1;
327          double tolV = 1;
328          
329          h = target.h - replace.h;
330          s = target.s / replace.s;
331          v = target.v / replace.v;
332
333          for(y = 0; y<bitmap.height; y++)
334          {
335             for(x = 0; x<bitmap.width; x++)
336             {
337                ColorAlpha color = ((ColorAlpha *)bitmap.picture)[y * bitmap.stride + x];
338                ColorHSV hsv = color;
339                double diffH = Abs(hsv.h/360 - replace.h/360);
340                double diffS = Abs(hsv.s - replace.s)/100.0;
341                double diffV = Abs(hsv.v - replace.v)/100.0;
342                if(diffH <= tolH && diffS <= tolS && diffV <= tolV)
343                {
344                   hsv.h += h;
345                   hsv.s *= s;
346                   hsv.v *= v;
347                   color.color = hsv;
348                   ((ColorAlpha *)bitmap.picture)[y * bitmap.stride + x] = color;
349                }
350             }
351          }
352          picture.Update(null);
353          picture.modifiedDocument = true;
354          Destroy(0);
355          return true;
356       }
357    };
358
359    EditBox hBox { this, text = "H", size = { 78, 19 }, position = { 176, 80 } };
360    EditBox sBox { this, text = "S", size = { 78, 19 }, position = { 176, 120 } };
361    EditBox vBox { this, text = "V", size = { 78, 19 }, position = { 176, 160 } };
362    Label label1 { this, size = { 7, 13 }, position = { 152, 80 }, labeledWindow = hBox };
363    Label label2 { this, size = { 6, 13 }, position = { 152, 120 }, labeledWindow = sBox };
364    Label label3 { this, size = { 6, 13 }, position = { 152, 168 }, labeledWindow = vBox };
365    ColorBox original { this, position = { 10, 10 }, background = replace };
366    ColorBox result { this, position = { 10, 100 }, background = target };
367 }
368 #endif