1 /*$
2 Copyright (C) 2013-2020 Azel.
3
4 This file is part of AzPainter.
5
6 AzPainter is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 AzPainter is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 $*/
19
20 /*****************************************
21 * NewImageDlg
22 *
23 * イメージ新規作成ダイアログ
24 *****************************************/
25
26 #include "mDef.h"
27 #include "mStr.h"
28 #include "mWidget.h"
29 #include "mWindow.h"
30 #include "mDialog.h"
31 #include "mContainer.h"
32 #include "mLabel.h"
33 #include "mComboBox.h"
34 #include "mLineEdit.h"
35 #include "mListView.h"
36 #include "mTab.h"
37 #include "mEvent.h"
38 #include "mWidgetBuilder.h"
39 #include "mMessageBox.h"
40 #include "mTrans.h"
41
42 #include "defMacros.h"
43 #include "defConfig.h"
44
45 #include "trgroup.h"
46
47
48 //------------------------
49
50 static const char *g_builder =
51 "ct#h:sep=12:lf=wh;"
52 "ct#v:lf=m;"
53 "ct#g3:sep=6,7;"
54 //幅
55 "lb:lf=rm:TR=0,0;"
56 "le#c:id=100:wlen=8;"
57 "sp;"
58 //高さ
59 "lb:lf=rm:TR=0,1;"
60 "le#c:id=101:wlen=8;"
61 "cb:id=102:t=px\tcm\tinch;"
62 //解像度
63 "lb:lf=rm:tr=1;"
64 "le#cs:id=103:wlen=6;"
65 "lb:lf=m:t=dpi;"
66 "-;"
67 //レイヤタイプ
68 "ct#h:sep=6:mg=t15;"
69 "lb:lf=m:tr=2;"
70 "cb:id=104;"
71 "-;"
72 //pxプレビュー
73 "lb#cB:id=105:lf=w:mg=t18;"
74 "-;"
75 //リスト
76 "ct#v:sep=4:lf=wh;"
77 "tab#ts:id=106:lf=w;"
78 "lv#,fv:id=107:lf=wh;"
79 "ct#h:sep=3:lf=r;"
80 "bt:id=108:tr=3;"
81 "bt:id=109:tr=4;";
82
83 //------------------------
84
85 #define TABNO_RECENT 0
86 #define TABNO_RECORD 1
87 #define TABNO_DEFINED 2
88
89 #define WIDGETID_TOP 100
90 #define TRID_MES_LIMIT 1000
91
92 enum
93 {
94 WNO_WIDTH,
95 WNO_HEIGHT,
96 WNO_UNIT,
97 WNO_DPI,
98 WNO_LAYERTYPE,
99 WNO_LABEL_PX,
100 WNO_TAB,
101 WNO_LIST,
102 WNO_BTT_ADD,
103 WNO_BTT_DEL,
104
105 WIDGET_NUM
106 };
107
108 //------------------------
109
110 typedef struct
111 {
112 mWidget wg;
113 mContainerData ct;
114 mWindowData win;
115 mDialogData dlg;
116
117 mWidget *widgets[WIDGET_NUM];
118 int tabno;
119 }NewImageDlg;
120
121 //------------------------
122
123
124 //========================
125 // 設定データ
126 //========================
127
128
129 /** 新規作成の履歴に追加 */
130
_set_config_recent(ImageSizeData * src)131 static void _set_config_recent(ImageSizeData *src)
132 {
133 ImageSizeData *dst = APP_CONF->imgsize_recent;
134 int i,del;
135
136 del = CONFIG_IMAGESIZE_NUM - 1;
137
138 //同じ値が存在するか
139
140 for(i = 0; i < CONFIG_IMAGESIZE_NUM; i++)
141 {
142 if(dst[i].unit == 255) break;
143
144 if(src->unit == dst[i].unit && src->dpi == dst[i].dpi
145 && src->w == dst[i].w && src->h == dst[i].h)
146 {
147 del = i;
148 break;
149 }
150 }
151
152 //挿入位置を空ける
153
154 for(i = del; i > 0; i--)
155 dst[i] = dst[i - 1];
156
157 //先頭にセット
158
159 dst[0] = *src;
160 }
161
162
163 //========================
164 // リストにデータセット
165 //========================
166
167
168 /** 履歴/登録リストセット */
169
_set_list_recent_record(mListView * lv,ImageSizeData * p)170 static void _set_list_recent_record(mListView *lv,ImageSizeData *p)
171 {
172 mStr str = MSTR_INIT;
173 int i;
174
175 for(i = 0; i < CONFIG_IMAGESIZE_NUM; i++, p++)
176 {
177 if(p->unit == 255) break;
178
179 if(p->unit == 0)
180 //px
181 mStrSetFormat(&str, "%d x %d px : %ddpi", p->w, p->h, p->dpi);
182 else
183 {
184 //cm,inch
185
186 mStrSetFormat(&str, "%d.%02d x %d.%02d %s : %ddpi",
187 p->w / 100, p->w % 100,
188 p->h / 100, p->h % 100,
189 (p->unit == 1)? "cm": "inch", p->dpi);
190 }
191
192 mListViewAddItem_textparam(lv, str.buf, i);
193 }
194
195 mStrFree(&str);
196 }
197
198 /** 規定リストセット */
199
_set_list_defined(mListView * lv)200 static void _set_list_defined(mListView *lv)
201 {
202 int i,j;
203 mStr str = MSTR_INIT;
204 uint32_t num[2][7] = { //mm 単位
205 {
206 (594 << 16) | 841, (420 << 16) | 594, (297 << 16) | 420,
207 (210 << 16) | 297, (148 << 16) | 210, (105 << 16) | 148,
208 (74 << 16) | 105
209 },
210 {
211 (728 << 16) | 1030, (515 << 16) | 728, (364 << 16) | 515,
212 (257 << 16) | 364, (182 << 16) | 257, (128 << 16) | 182,
213 (91 << 16) | 128
214 }
215 };
216
217 for(i = 0; i < 2; i++)
218 {
219 for(j = 0; j < 7; j++)
220 {
221 mStrSetFormat(&str, "%c%d : %d x %d mm",
222 'A' + i, j + 1, num[i][j] >> 16, num[i][j] & 0xffff);
223
224 mListViewAddItem_textparam(lv, str.buf, num[i][j]);
225 }
226 }
227
228 mStrFree(&str);
229 }
230
231 /** タブ番号からリストセット */
232
_set_list(NewImageDlg * p,int no)233 static void _set_list(NewImageDlg *p,int no)
234 {
235 mListView *lv;
236
237 lv = M_LISTVIEW(p->widgets[WNO_LIST]);
238
239 mListViewDeleteAllItem(lv);
240
241 if(no == TABNO_RECENT)
242 _set_list_recent_record(lv, APP_CONF->imgsize_recent);
243 else if(no == TABNO_RECORD)
244 _set_list_recent_record(lv, APP_CONF->imgsize_record);
245 else
246 _set_list_defined(lv);
247 }
248
249
250 //========================
251 // sub
252 //========================
253
254
255 /** ウィジェットに幅・高さの値セット */
256
_set_width_height(NewImageDlg * p,int wno,int size,int unit)257 static void _set_width_height(NewImageDlg *p,int wno,int size,int unit)
258 {
259 if(unit == 0)
260 mLineEditSetInt(M_LINEEDIT(p->widgets[wno]), size);
261 else
262 mLineEditSetDouble(M_LINEEDIT(p->widgets[wno]), size * 0.01, 2);
263 }
264
265 /** 履歴/登録リストからウィジェットに値セット */
266
_set_from_data(NewImageDlg * p,ImageSizeData * dat)267 static void _set_from_data(NewImageDlg *p,ImageSizeData *dat)
268 {
269 mComboBoxSetSel_index(M_COMBOBOX(p->widgets[WNO_UNIT]), dat->unit);
270
271 _set_width_height(p, WNO_WIDTH, dat->w, dat->unit);
272 _set_width_height(p, WNO_HEIGHT, dat->h, dat->unit);
273
274 mLineEditSetInt(M_LINEEDIT(p->widgets[WNO_DPI]), dat->dpi);
275 }
276
277 /** リストボタンの有効/無効 */
278
_enable_list_button(NewImageDlg * p)279 static void _enable_list_button(NewImageDlg *p)
280 {
281 int f = (p->tabno == TABNO_RECORD);
282
283 mWidgetEnable(p->widgets[WNO_BTT_ADD], f);
284 mWidgetEnable(p->widgets[WNO_BTT_DEL], f);
285 }
286
287 /** 幅か高さ取得 */
288
_get_width_height(NewImageDlg * p,int wno,int unit)289 static int _get_width_height(NewImageDlg *p,int wno,int unit)
290 {
291 int n;
292
293 if(unit == 0)
294 n = mLineEditGetInt(M_LINEEDIT(p->widgets[wno]));
295 else
296 n = mLineEditGetDouble(M_LINEEDIT(p->widgets[wno])) * 100 + 0.5;
297
298 return (n < 1)? 1: n;
299 }
300
301 /** ウィジェットからデータ取得 */
302
_get_data_from_widget(NewImageDlg * p,ImageSizeData * dat)303 static void _get_data_from_widget(NewImageDlg *p,ImageSizeData *dat)
304 {
305 int n;
306
307 n = mComboBoxGetSelItemIndex(M_COMBOBOX(p->widgets[WNO_UNIT]));
308
309 dat->unit = n;
310 dat->w = _get_width_height(p, WNO_WIDTH, n);
311 dat->h = _get_width_height(p, WNO_HEIGHT, n);
312 dat->dpi = mLineEditGetNum(M_LINEEDIT(p->widgets[WNO_DPI]));
313 }
314
315 /** 登録リストに追加 */
316
_add_record(NewImageDlg * p)317 static void _add_record(NewImageDlg *p)
318 {
319 int i;
320
321 //空き位置取得
322
323 for(i = 0; i < CONFIG_IMAGESIZE_NUM; i++)
324 {
325 if(APP_CONF->imgsize_record[i].unit == 255) break;
326 }
327
328 if(i == CONFIG_IMAGESIZE_NUM) return;
329
330 //セット
331
332 _get_data_from_widget(p, APP_CONF->imgsize_record + i);
333
334 if(i != CONFIG_IMAGESIZE_NUM - 1)
335 APP_CONF->imgsize_record[i + 1].unit = 255;
336
337 //リスト
338
339 _set_list(p, p->tabno);
340 }
341
342 /** 登録リストから削除 */
343
_del_record(NewImageDlg * p)344 static void _del_record(NewImageDlg *p)
345 {
346 mListView *lv;
347 int i,no;
348
349 lv = M_LISTVIEW(p->widgets[WNO_LIST]);
350
351 no = mListViewGetItemIndex(lv, NULL);
352 if(no == -1) return;
353
354 mListViewDeleteItem_sel(lv, NULL);
355
356 //データ削除
357
358 for(i = no; i < CONFIG_IMAGESIZE_NUM - 1; i++)
359 APP_CONF->imgsize_record[i] = APP_CONF->imgsize_record[i + 1];
360
361 APP_CONF->imgsize_record[CONFIG_IMAGESIZE_NUM - 1].unit = 255;
362 }
363
364 /** px サイズを取得 */
365
_get_pxsize(mSize * size,ImageSizeData * dat)366 static void _get_pxsize(mSize *size,ImageSizeData *dat)
367 {
368 double dw,dh;
369 int w,h;
370
371 w = dat->w;
372 h = dat->h;
373
374 if(dat->unit != 0)
375 {
376 dw = dat->w * 0.01 * dat->dpi;
377 dh = dat->h * 0.01 * dat->dpi;
378
379 if(dat->unit == 1)
380 {
381 dw /= 2.54;
382 dh /= 2.54;
383 }
384
385 w = (int)(dw + 0.5);
386 h = (int)(dh + 0.5);
387
388 if(w < 1) w = 1;
389 if(h < 1) h = 1;
390 }
391
392 size->w = w;
393 size->h = h;
394 }
395
396 /** px サイズをセット */
397
_set_label_pxsize(NewImageDlg * p)398 static void _set_label_pxsize(NewImageDlg *p)
399 {
400 ImageSizeData dat;
401 mSize size;
402 mStr str = MSTR_INIT;
403
404 _get_data_from_widget(p, &dat);
405 _get_pxsize(&size, &dat);
406
407 mStrSetFormat(&str, "%d x %d px", size.w, size.h);
408
409 mLabelSetText(M_LABEL(p->widgets[WNO_LABEL_PX]), str.buf);
410
411 mStrFree(&str);
412 }
413
414
415 //========================
416 // イベント
417 //========================
418
419
420 /** OK 終了時 */
421
_end_ok(NewImageDlg * p)422 static void _end_ok(NewImageDlg *p)
423 {
424 ImageSizeData dat;
425 mSize size;
426
427 _get_data_from_widget(p, &dat);
428 _get_pxsize(&size, &dat);
429
430 //サイズ制限チェック
431
432 if(size.w > IMAGE_SIZE_MAX || size.h > IMAGE_SIZE_MAX)
433 {
434 mStr str = MSTR_INIT;
435
436 mStrSetFormat(&str, M_TR_T2(TRGROUP_DLG_NEWIMAGE, TRID_MES_LIMIT), IMAGE_SIZE_MAX);
437
438 mMessageBox(M_WINDOW(p), NULL, str.buf, MMESBOX_OK, MMESBOX_OK);
439
440 mStrFree(&str);
441
442 return;
443 }
444
445 //履歴の先頭にセット
446
447 _set_config_recent(&dat);
448
449 mDialogEnd(M_DIALOG(p), TRUE);
450 }
451
452 /** リスト項目選択時 */
453
_change_list_sel(NewImageDlg * p,int param)454 static void _change_list_sel(NewImageDlg *p,int param)
455 {
456 if(p->tabno == TABNO_RECENT)
457 //履歴
458 _set_from_data(p, APP_CONF->imgsize_recent + param);
459 else if(p->tabno == TABNO_RECORD)
460 //登録
461 _set_from_data(p, APP_CONF->imgsize_record + param);
462 else
463 {
464 //規定
465
466 mComboBoxSetSel_index(M_COMBOBOX(p->widgets[WNO_UNIT]), 1);
467
468 mLineEditSetDouble(M_LINEEDIT(p->widgets[WNO_WIDTH]), (param >> 16) * 0.1, 1);
469 mLineEditSetDouble(M_LINEEDIT(p->widgets[WNO_HEIGHT]), (param & 0xffff) * 0.1, 1);
470 }
471
472 //px
473
474 _set_label_pxsize(p);
475 }
476
477 /** イベント */
478
_event_handle(mWidget * wg,mEvent * ev)479 static int _event_handle(mWidget *wg,mEvent *ev)
480 {
481 NewImageDlg *p = (NewImageDlg *)wg;
482
483 if(ev->type == MEVENT_NOTIFY)
484 {
485 switch(ev->notify.id)
486 {
487 //幅、高さ、DPI
488 case WIDGETID_TOP + WNO_WIDTH:
489 case WIDGETID_TOP + WNO_HEIGHT:
490 case WIDGETID_TOP + WNO_DPI:
491 if(ev->notify.type == MLINEEDIT_N_CHANGE)
492 _set_label_pxsize(p);
493 break;
494 //単位
495 case WIDGETID_TOP + WNO_UNIT:
496 if(ev->notify.type == MCOMBOBOX_N_CHANGESEL)
497 _set_label_pxsize(p);
498 break;
499
500 //リスト項目選択時
501 case WIDGETID_TOP + WNO_LIST:
502 if(ev->notify.type == MLISTVIEW_N_CHANGE_FOCUS
503 || ev->notify.type == MLISTVIEW_N_CLICK_ON_FOCUS)
504 _change_list_sel(p, (int)ev->notify.param2);
505 break;
506 //タブ変更時
507 case WIDGETID_TOP + WNO_TAB:
508 if(ev->notify.type == MTAB_N_CHANGESEL)
509 {
510 p->tabno = ev->notify.param1;
511
512 _enable_list_button(p);
513
514 _set_list(p, p->tabno);
515 }
516 break;
517 //追加
518 case WIDGETID_TOP + WNO_BTT_ADD:
519 _add_record(p);
520 break;
521 //削除
522 case WIDGETID_TOP + WNO_BTT_DEL:
523 _del_record(p);
524 break;
525
526 //OK
527 case M_WID_OK:
528 _end_ok(p);
529 break;
530 //CANCEL
531 case M_WID_CANCEL:
532 mDialogEnd(M_DIALOG(wg), FALSE);
533 break;
534 }
535 }
536
537 return mDialogEventHandle(wg, ev);
538 }
539
540
541 //========================
542 // 作成
543 //========================
544
545
546 /** ウィジェット初期化 */
547
_init_widget(NewImageDlg * p)548 static void _init_widget(NewImageDlg *p)
549 {
550 int i;
551 ImageSizeData dat;
552
553 for(i = 0; i < WIDGET_NUM; i++)
554 p->widgets[i] = mWidgetFindByID(M_WIDGET(p), WIDGETID_TOP + i);
555
556 //解像度
557
558 mLineEditSetNumStatus(M_LINEEDIT(p->widgets[WNO_DPI]), 1, 9999, 0);
559
560 //レイヤタイプ
561
562 M_TR_G(TRGROUP_LAYERTYPE);
563 mComboBoxAddTrItems(M_COMBOBOX(p->widgets[WNO_LAYERTYPE]), 4, 0, 0);
564 M_TR_G(TRGROUP_DLG_NEWIMAGE);
565
566 mComboBoxSetWidthAuto(M_COMBOBOX(p->widgets[WNO_LAYERTYPE]));
567 mComboBoxSetSel_index(M_COMBOBOX(p->widgets[WNO_LAYERTYPE]), 0);
568
569 //最新の履歴から値セット
570
571 if(APP_CONF->imgsize_recent[0].unit != 255)
572 dat = APP_CONF->imgsize_recent[0];
573 else
574 {
575 dat.unit = 0;
576 dat.dpi = 300;
577 dat.w = dat.h = 500;
578 }
579
580 _set_from_data(p, &dat);
581
582 //px
583
584 _set_label_pxsize(p);
585
586 //----------
587
588 //タブ
589
590 for(i = 0; i < 3; i++)
591 mTabAddItemText(M_TAB(p->widgets[WNO_TAB]), M_TR_T(100 + i));
592
593 mTabSetSel_index(M_TAB(p->widgets[WNO_TAB]), TABNO_RECENT);
594
595 //リスト
596
597 _set_list(p, TABNO_RECENT);
598
599 mWidgetSetInitSize_fontHeight(p->widgets[WNO_LIST], 16, 12);
600
601 //ボタン無効
602
603 _enable_list_button(p);
604 }
605
606 /** 作成 */
607
_create_dlg(mWindow * owner)608 static NewImageDlg *_create_dlg(mWindow *owner)
609 {
610 NewImageDlg *p;
611
612 //作成
613
614 p = (NewImageDlg *)mDialogNew(sizeof(NewImageDlg), owner, MWINDOW_S_DIALOG_NORMAL);
615 if(!p) return NULL;
616
617 p->wg.event = _event_handle;
618
619 //
620
621 M_TR_G(TRGROUP_DLG_NEWIMAGE);
622
623 mContainerSetPadding_one(M_CONTAINER(p), 8);
624 p->ct.sepW = 15;
625
626 mWindowSetTitle(M_WINDOW(p), M_TR_T(0));
627
628 //ウィジェット
629
630 mWidgetBuilderCreateFromText(M_WIDGET(p), g_builder);
631
632 _init_widget(p);
633
634 //OK/Cancel
635
636 mContainerCreateOkCancelButton(M_WIDGET(p));
637
638 return p;
639 }
640
641
642 //=====================
643
644
645 /** 新規作成ダイアログ実行 */
646
NewImageDialog_run(mWindow * owner,mSize * size,int * dpi,int * layertype)647 mBool NewImageDialog_run(mWindow *owner,mSize *size,int *dpi,int *layertype)
648 {
649 NewImageDlg *p;
650 mBool ret;
651
652 p = _create_dlg(owner);
653 if(!p) return FALSE;
654
655 mWindowMoveResizeShow_hintSize(M_WINDOW(p));
656
657 ret = mDialogRun(M_DIALOG(p), FALSE);
658
659 if(ret)
660 {
661 _get_pxsize(size, APP_CONF->imgsize_recent);
662
663 *dpi = APP_CONF->imgsize_recent[0].dpi;
664
665 *layertype = mComboBoxGetSelItemIndex(M_COMBOBOX(p->widgets[WNO_LAYERTYPE]));
666 }
667
668 mWidgetDestroy(M_WIDGET(p));
669
670 return ret;
671 }
672