1 /*$
2  Copyright (C) 2016-2020 Azel.
3 
4  This file is part of AzPainterB.
5 
6  AzPainterB 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  AzPainterB 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  * グラデーション編集ダイアログ
22  ********************************/
23 
24 #include "mDef.h"
25 #include "mWidget.h"
26 #include "mDialog.h"
27 #include "mContainer.h"
28 #include "mWindow.h"
29 #include "mWidgetBuilder.h"
30 #include "mCheckButton.h"
31 #include "mColorButton.h"
32 #include "mArrowButton.h"
33 #include "mLineEdit.h"
34 #include "mSliderBar.h"
35 #include "mMenu.h"
36 #include "mTrans.h"
37 #include "mEvent.h"
38 #include "mUtilStr.h"
39 
40 #include "GradationList.h"
41 #include "GradationEditWidget.h"
42 
43 #include "trgroup.h"
44 
45 
46 //--------------------
47 
48 typedef struct
49 {
50 	mWidget wg;
51 	mContainerData ct;
52 	mWindowData win;
53 	mDialogData dlg;
54 
55 	GradItem *item;
56 
57 	GradEditWidget *editwg[2];
58 	mLineEdit *ledit_pos[2],
59 		*ledit_opa;
60 	mSliderBar *sl_opa;
61 	mArrowButton *menubtt[2];
62 	mColorButton *colbt;
63 	mCheckButton *ck_coltype,
64 		*ck_flag[2];
65 }_edit_dlg;
66 
67 //--------------------
68 
69 static const char *g_wb_gradeditdlg =
70 //色
71 "gb:cts=h:lf=w:tr=1:sep=5;"
72   "lb:lf=m:tr=2;"
73   "le#cs:id=100:wlen=7;"
74   "colbt#d:id=105:lf=m;"
75   "ck#r:id=102:tr=3:lf=m;"
76   "ck#r:id=103:tr=4:lf=m;"
77   "ck#r:id=104:tr=5:lf=m;"
78 "-;"
79 //不透明度
80 "gb:cts=h:lf=w:tr=6:sep=5:mg=0,8,0,10;"
81   "lb:tr=2:lf=m;"
82   "le#cs:id=101:wlen=7;"
83   "lb:tr=7:lf=m;"
84   "sl:id=106:lf=wm:range=0,255;"
85   "le#cs:id=107:wlen=4:range=0,255;"
86 "-;"
87 //チェック
88 "ct#h:sep=4:mg=b10;"
89   "ck:id=108:tr=8;"
90   "ck:id=109:tr=9;"
91 "-;"
92 //ヘルプ
93 "lb#B:tr=10:lf=w:mg=b12;"
94 ;
95 
96 //--------------------
97 
98 enum
99 {
100 	WID_EDIT_COL_POS = 100,
101 	WID_EDIT_A_POS,
102 	WID_CK_COL_SPEC,
103 	WID_CK_COL_DRAW,
104 	WID_CK_COL_BKGND,
105 	WID_COLBTT,
106 	WID_SLIDER_A,
107 	WID_EDIT_A_VAL,
108 	WID_CK_LOOP,
109 	WID_CK_SINGLE_COL,
110 
111 	WID_EDITWG_COL = 200,
112 	WID_EDITWG_A,
113 	WID_BTT_COL_MOVELEFT,
114 	WID_BTT_A_MOVELEFT,
115 	WID_BTT_COL_MOVERIGHT,
116 	WID_BTT_A_MOVERIGHT,
117 	WID_MENUBTT_COL,
118 	WID_MENUBTT_A
119 };
120 
121 enum
122 {
123 	TRID_MENU_DELETE = 100,
124 	TRID_MENU_DIVIDE,
125 	TRID_MENU_MOVE_CENTER,
126 	TRID_MENU_ALL_EVEN,
127 	TRID_MENU_REVERSE
128 };
129 
130 //--------------------
131 
132 
133 
134 //==========================
135 // sub
136 //==========================
137 
138 
139 /** GradEditWidget の更新 */
140 
_update_editwg(_edit_dlg * p,int no)141 static void _update_editwg(_edit_dlg *p,int no)
142 {
143 	mWidgetUpdate(M_WIDGET(p->editwg[no]));
144 }
145 
146 /** カレントポイントの情報セット */
147 
_set_curinfo(_edit_dlg * p,int no)148 static void _set_curinfo(_edit_dlg *p,int no)
149 {
150 	int n;
151 	uint32_t col;
152 
153 	//位置
154 
155 	mLineEditSetNum(p->ledit_pos[no],
156 		(int)((double)GradEditWidget_getCurrentPos(p->editwg[no]) / (1 << GRADDAT_POS_BIT) * 1000+ 0.5));
157 
158 	//値
159 
160 	if(no == 0)
161 	{
162 		//RGB
163 
164 		n = GradEditWidget_getCurrentColor(p->editwg[no], &col);
165 
166 		mCheckButtonSetRadioSel(p->ck_coltype, n);
167 
168 		mColorButtonSetColor(p->colbt, col);
169 		mWidgetEnable(M_WIDGET(p->colbt), (n == 0));
170 	}
171 	else
172 	{
173 		//A
174 
175 		n = GradEditWidget_getCurrentOpacity(p->editwg[no]);
176 
177 		mSliderBarSetPos(p->sl_opa, n);
178 		mLineEditSetNum(p->ledit_opa, n);
179 	}
180 }
181 
182 /** メニュー実行 */
183 
_run_menu(_edit_dlg * p,int no)184 static void _run_menu(_edit_dlg *p,int no)
185 {
186 	GradEditWidget *editwg;
187 	mMenu *menu,*sub;
188 	mMenuItemInfo *mi;
189 	int i,n;
190 	char m[4];
191 	mBox box;
192 	uint16_t id[] = {
193 		TRID_MENU_DELETE, 0xfffe, TRID_MENU_DIVIDE, 0xfffe,
194 		TRID_MENU_MOVE_CENTER, TRID_MENU_ALL_EVEN, TRID_MENU_REVERSE, 0xffff
195 	};
196 
197 	editwg = p->editwg[no];
198 
199 	//------- メニュー作成
200 
201 	M_TR_G(TRGROUP_DLG_GRADATION_EDIT);
202 
203 	menu = mMenuNew();
204 
205 	mMenuAddTrArray16(menu, id);
206 
207 	//無効
208 
209 	n = GradEditWidget_getCurrentPos(editwg);
210 
211 	if(n == 0 || n == GRADDAT_POS_MAX)
212 	{
213 		mMenuSetEnable(menu, TRID_MENU_DELETE, 0);
214 		mMenuSetEnable(menu, TRID_MENU_MOVE_CENTER, 0);
215 	}
216 
217 	//分割数
218 
219 	n = GradEditWidget_getMaxSplitNum_toright(editwg);
220 
221 	if(n < 2)
222 		mMenuSetEnable(menu, TRID_MENU_DIVIDE, FALSE);
223 	else
224 	{
225 		sub = mMenuNew();
226 
227 		for(i = 2; i <= n && i <= 10; i++)
228 		{
229 			mIntToStr(m, i);
230 			mMenuAddText_copy(sub, 1000 + i, m);
231 		}
232 
233 		mMenuSetSubmenu(menu, TRID_MENU_DIVIDE, sub);
234 	}
235 
236 	//--------- メニュー実行
237 
238 	mWidgetGetRootBox(M_WIDGET(p->menubtt[no]), &box);
239 
240 	mi = mMenuPopup(menu, NULL, box.x + box.w, box.y + box.h, MMENU_POPUP_F_RIGHT);
241 	i = (mi)? mi->id: -1;
242 
243 	mMenuDestroy(menu);
244 
245 	if(i == -1) return;
246 
247 	//-------- コマンド実行
248 
249 	if(i >= 1000)
250 	{
251 		//分割
252 		GradEditWidget_splitPoint_toright(editwg, i - 1000);
253 	}
254 	else
255 	{
256 		switch(i)
257 		{
258 			//カレント削除
259 			case TRID_MENU_DELETE:
260 				GradEditWidget_deletePoint(editwg, -1);
261 				break;
262 			//中間位置へ
263 			case TRID_MENU_MOVE_CENTER:
264 				GradEditWidget_moveCurrentPos_middle(editwg);
265 				break;
266 			//すべて等間隔に
267 			case TRID_MENU_ALL_EVEN:
268 				GradEditWidget_evenAllPoints(editwg);
269 				break;
270 			//反転
271 			case TRID_MENU_REVERSE:
272 				GradEditWidget_reversePoints(editwg);
273 				break;
274 		}
275 	}
276 }
277 
278 
279 //==========================
280 // イベント
281 //==========================
282 
283 
284 /** OK 時、グラデーションデータをセット */
285 
_set_graddat(_edit_dlg * p)286 static void _set_graddat(_edit_dlg *p)
287 {
288 	int colnum,anum;
289 	uint8_t flags;
290 
291 	colnum = GradEditWidget_getPointNum(p->editwg[0]);
292 	anum = GradEditWidget_getPointNum(p->editwg[1]);
293 
294 	//フラグ
295 
296 	flags = 0;
297 	if(mCheckButtonIsChecked(p->ck_flag[0])) flags |= GRADDAT_F_LOOP;
298 	if(mCheckButtonIsChecked(p->ck_flag[1])) flags |= GRADDAT_F_SINGLE_COL;
299 
300 	//セット
301 
302 	GradItem_setDat(p->item, flags, colnum, anum,
303 		GradEditWidget_getBuf(p->editwg[0]),
304 		GradEditWidget_getBuf(p->editwg[1]));
305 }
306 
307 /** イベント */
308 
_event_handle(mWidget * wg,mEvent * ev)309 static int _event_handle(mWidget *wg,mEvent *ev)
310 {
311 	_edit_dlg *p = (_edit_dlg *)wg;
312 
313 	if(ev->type == MEVENT_NOTIFY)
314 	{
315 		int id,type,n;
316 
317 		id = ev->notify.id;
318 		type = ev->notify.type;
319 
320 		switch(id)
321 		{
322 			//グラデ編集 (col)
323 			case WID_EDITWG_COL:
324 				_set_curinfo(p, 0);
325 				break;
326 			//グラデ編集 (A)
327 			case WID_EDITWG_A:
328 				_set_curinfo(p, 1);
329 
330 				//ポインタに変更があれば色のグラデーションも再描画
331 				if(type == GRADEDITWIDGET_N_MODIFY)
332 					_update_editwg(p, 0);
333 				break;
334 
335 			//位置 エディット
336 			case WID_EDIT_COL_POS:
337 			case WID_EDIT_A_POS:
338 				if(type == MLINEEDIT_N_CHANGE)
339 				{
340 					id -= WID_EDIT_COL_POS;
341 
342 					if(GradEditWidget_setCurrentPos(p->editwg[id], mLineEditGetNum(p->ledit_pos[id]))
343 						&& id == 1)
344 					{
345 						//A の値が変わったらカラーを再描画
346 						_update_editwg(p, 0);
347 					}
348 				}
349 				break;
350 			//色タイプ
351 			case WID_CK_COL_SPEC:
352 			case WID_CK_COL_DRAW:
353 			case WID_CK_COL_BKGND:
354 				n = id - WID_CK_COL_SPEC;
355 
356 				mWidgetEnable(M_WIDGET(p->colbt), (n == 0));
357 
358 				GradEditWidget_setColorType(p->editwg[0], n);
359 				break;
360 			//指定色
361 			case WID_COLBTT:
362 				if(type == MCOLORBUTTON_N_PRESS)
363 					GradEditWidget_setColorRGB(p->editwg[0], ev->notify.param1);
364 				break;
365 			//不透明度スライダー
366 			case WID_SLIDER_A:
367 				if(type == MSLIDERBAR_N_HANDLE
368 					&& (ev->notify.param2 & MSLIDERBAR_HANDLE_F_CHANGE))
369 				{
370 					GradEditWidget_setOpacity(p->editwg[1], ev->notify.param1);
371 
372 					mLineEditSetNum(p->ledit_opa, ev->notify.param1);
373 
374 					_update_editwg(p, 0);
375 				}
376 				break;
377 			//不透明度、値のエディット
378 			case WID_EDIT_A_VAL:
379 				if(type == MLINEEDIT_N_CHANGE)
380 				{
381 					n = mLineEditGetNum(p->ledit_opa);
382 
383 					GradEditWidget_setOpacity(p->editwg[1], n);
384 
385 					mSliderBarSetPos(p->sl_opa, n);
386 
387 					_update_editwg(p, 0);
388 				}
389 				break;
390 
391 			//カレントポイント変更
392 			case WID_BTT_COL_MOVELEFT:
393 			case WID_BTT_A_MOVELEFT:
394 			case WID_BTT_COL_MOVERIGHT:
395 			case WID_BTT_A_MOVERIGHT:
396 				id -= WID_BTT_COL_MOVELEFT;
397 
398 				GradEditWidget_moveCurrentPoint(p->editwg[id & 1], (id >= 2));
399 				_set_curinfo(p, id & 1);
400 				break;
401 			//メニューボタン
402 			case WID_MENUBTT_COL:
403 			case WID_MENUBTT_A:
404 				_run_menu(p, id - WID_MENUBTT_COL);
405 				break;
406 
407 			//単色化
408 			case WID_CK_SINGLE_COL:
409 				GradEditWidget_setSingleColor(p->editwg[0], -1);
410 
411 				_update_editwg(p, 0);
412 				break;
413 
414 			//OK
415 			case M_WID_OK:
416 				_set_graddat(p);
417 				mDialogEnd(M_DIALOG(wg), TRUE);
418 				break;
419 			//キャンセル
420 			case M_WID_CANCEL:
421 				mDialogEnd(M_DIALOG(wg), FALSE);
422 				break;
423 		}
424 	}
425 
426 	return mDialogEventHandle(wg, ev);
427 }
428 
429 
430 //==========================
431 // 作成
432 //==========================
433 
434 
435 /** 編集部分のウィジェット作成 */
436 
_create_edit_widget(_edit_dlg * p,int no)437 static void _create_edit_widget(_edit_dlg *p,int no)
438 {
439 	mWidget *ct_toph,*ct_v,*ct_h;
440 	mArrowButton *abtt;
441 
442 	ct_toph = mContainerCreate(M_WIDGET(p), MCONTAINER_TYPE_HORZ, 0, 8, MLF_EXPAND_W);
443 	ct_toph->margin.bottom = 6;
444 
445 	p->editwg[no] = GradEditWidget_new(ct_toph, WID_EDITWG_COL + no, no, p->item->buf);
446 
447 	//----- ボタン
448 
449 	ct_v = mContainerCreate(ct_toph, MCONTAINER_TYPE_VERT, 0, 4, 0);
450 	ct_h = mContainerCreate(ct_v, MCONTAINER_TYPE_HORZ, 0, 0, 0);
451 
452 	//移動
453 
454 	abtt = mArrowButtonCreate(ct_h, WID_BTT_COL_MOVELEFT + no, MARROWBUTTON_S_LEFT, 0, 0);
455 	abtt->wg.hintOverW = abtt->wg.hintOverH = 19;
456 
457 	abtt = mArrowButtonCreate(ct_h, WID_BTT_COL_MOVERIGHT + no, MARROWBUTTON_S_RIGHT, 0, 0);
458 	abtt->wg.hintOverW = abtt->wg.hintOverH = 19;
459 
460 	//メニューボタン
461 
462 	p->menubtt[no] = mArrowButtonCreate(ct_v,
463 		WID_MENUBTT_COL + no, MARROWBUTTON_S_DOWN, MLF_RIGHT, 0);
464 }
465 
466 /** ダイアログ作成 */
467 
_create_dlg(mWindow * owner,GradItem * item)468 static _edit_dlg *_create_dlg(mWindow *owner,GradItem *item)
469 {
470 	_edit_dlg *p;
471 	int i,flag;
472 
473 	p = (_edit_dlg *)mDialogNew(sizeof(_edit_dlg),
474 			owner, MWINDOW_S_DIALOG_NORMAL);
475 	if(!p) return NULL;
476 
477 	p->item = item;
478 	p->wg.event = _event_handle;
479 
480 	//
481 
482 	mContainerSetPadding_one(M_CONTAINER(p), 8);
483 
484 	M_TR_G(TRGROUP_DLG_GRADATION_EDIT);
485 
486 	mWindowSetTitle(M_WINDOW(p), M_TR_T(0));
487 
488 	//------- 編集部分
489 
490 	_create_edit_widget(p, 0);
491 	_create_edit_widget(p, 1);
492 
493 	GradEditWidget_setAnotherModeBuf(p->editwg[0], GradEditWidget_getBuf(p->editwg[1]));
494 	GradEditWidget_setAnotherModeBuf(p->editwg[1], GradEditWidget_getBuf(p->editwg[0]));
495 
496 	//------- 以降
497 
498 	mWidgetBuilderCreateFromText(M_WIDGET(p), g_wb_gradeditdlg);
499 
500 	//位置
501 
502 	for(i = 0; i < 2; i++)
503 	{
504 		p->ledit_pos[i] = (mLineEdit *)mWidgetFindByID(M_WIDGET(p), WID_EDIT_COL_POS + i);
505 		mLineEditSetNumStatus(p->ledit_pos[i], 0, 1000, 1);
506 	}
507 
508 	//色
509 
510 	p->ck_coltype = (mCheckButton *)mWidgetFindByID(M_WIDGET(p), WID_CK_COL_SPEC);
511 
512 	p->colbt = (mColorButton *)mWidgetFindByID(M_WIDGET(p), WID_COLBTT);
513 
514 	//不透明度、値
515 
516 	p->sl_opa = (mSliderBar *)mWidgetFindByID(M_WIDGET(p), WID_SLIDER_A);
517 
518 	p->ledit_opa = (mLineEdit *)mWidgetFindByID(M_WIDGET(p), WID_EDIT_A_VAL);
519 
520 	//フラグ
521 
522 	flag = item->buf[0];
523 
524 	for(i = 0; i < 2; i++)
525 	{
526 		p->ck_flag[i] = (mCheckButton *)mWidgetFindByID(M_WIDGET(p), WID_CK_LOOP + i);
527 
528 		mCheckButtonSetState(p->ck_flag[i], flag & (1 << i));
529 	}
530 
531 	//OK/キャンセル
532 
533 	mContainerCreateOkCancelButton(M_WIDGET(p));
534 
535 	//------ 初期化
536 
537 	_set_curinfo(p, 0);
538 	_set_curinfo(p, 1);
539 
540 	GradEditWidget_setSingleColor(p->editwg[0], flag & GRADDAT_F_SINGLE_COL);
541 
542 	return p;
543 }
544 
545 
546 //==========================
547 //
548 //==========================
549 
550 
551 /** ダイアログ実行 */
552 
GradationEditDlg_run(mWindow * owner,GradItem * item)553 mBool GradationEditDlg_run(mWindow *owner,GradItem *item)
554 {
555 	_edit_dlg *p;
556 
557 	p = _create_dlg(owner, item);
558 	if(!p) return FALSE;
559 
560 	mWindowMoveResizeShow_hintSize(M_WINDOW(p));
561 
562 	return mDialogRun(M_DIALOG(p), TRUE);
563 }
564