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  * DockOption
22  *
23  * [dock]オプションのタブ内容
24  * (定規、入り抜き)
25  ********************************************/
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <math.h>
30 
31 #include "mDef.h"
32 #include "mStr.h"
33 #include "mContainerDef.h"
34 #include "mWidget.h"
35 #include "mContainer.h"
36 #include "mEvent.h"
37 #include "mLabel.h"
38 #include "mComboBox.h"
39 #include "mButton.h"
40 #include "mCheckButton.h"
41 #include "mMenu.h"
42 #include "mTrans.h"
43 #include "mPixbuf.h"
44 #include "mSysCol.h"
45 
46 #include "defDraw.h"
47 
48 #include "DockOption_sub.h"
49 #include "ValueBar.h"
50 
51 #include "draw_rule.h"
52 
53 #include "trgroup.h"
54 
55 
56 //--------------------
57 
58 //定規タイプイメージ (1bit: 121x21)
59 static const unsigned char g_img_rule[]={
60 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,
61 0x01,0x00,0x10,0x21,0x84,0x21,0x84,0x30,0x40,0x80,0x01,0x00,0x10,0x00,0x00,0x01,
62 0x01,0x00,0x90,0x10,0x42,0x21,0x84,0x50,0x40,0x40,0x01,0x1f,0x10,0x00,0x00,0x01,
63 0x79,0x9e,0x57,0x08,0x21,0x21,0x84,0x90,0x40,0x20,0xc1,0x60,0x10,0x00,0x00,0x01,
64 0xfd,0x9e,0x37,0x84,0x10,0x21,0x84,0x10,0x41,0x10,0x21,0x80,0x10,0xf0,0x01,0x01,
65 0xcd,0x9e,0x17,0x42,0x08,0xff,0xff,0x1f,0x42,0x08,0x11,0x00,0x11,0x0c,0x06,0x01,
66 0x85,0x82,0x10,0x21,0x84,0x21,0x84,0x10,0x44,0x04,0x09,0x0e,0x12,0x02,0x08,0x01,
67 0x85,0x82,0x90,0x10,0x42,0x21,0x84,0x10,0x48,0x02,0x09,0x11,0x12,0x01,0x10,0x01,
68 0x85,0x82,0x50,0x08,0x21,0x21,0x84,0x10,0x50,0x01,0x85,0x20,0x94,0xe0,0x20,0x01,
69 0x85,0x9e,0x37,0x84,0x10,0x21,0x84,0x10,0xe0,0x00,0x45,0x40,0x54,0x10,0x41,0x01,
70 0x85,0x9e,0x17,0x42,0x08,0xff,0xff,0xff,0xff,0xff,0x45,0x40,0x54,0x08,0x42,0x01,
71 0x85,0x9e,0x17,0x21,0x84,0x21,0x84,0x10,0xe0,0x00,0x45,0x40,0x54,0x10,0x41,0x01,
72 0x85,0x82,0x90,0x10,0x42,0x21,0x84,0x10,0x50,0x01,0x85,0x20,0x94,0xe0,0x20,0x01,
73 0x85,0x82,0x50,0x08,0x21,0x21,0x84,0x10,0x48,0x02,0x09,0x11,0x12,0x01,0x10,0x01,
74 0x85,0x82,0x30,0x84,0x10,0x21,0x84,0x10,0x44,0x04,0x09,0x0e,0x12,0x02,0x08,0x01,
75 0xcd,0x82,0x10,0x42,0x08,0xff,0xff,0x1f,0x42,0x08,0x11,0x00,0x11,0x0c,0x06,0x01,
76 0xfd,0x82,0x10,0x21,0x84,0x21,0x84,0x10,0x41,0x10,0x21,0x80,0x10,0xf0,0x01,0x01,
77 0x79,0x82,0x90,0x10,0x42,0x21,0x84,0x90,0x40,0x20,0xc1,0x60,0x10,0x00,0x00,0x01,
78 0x01,0x00,0x50,0x08,0x21,0x21,0x84,0x50,0x40,0x40,0x01,0x1f,0x10,0x00,0x00,0x01,
79 0x01,0x00,0x30,0x84,0x10,0x21,0x84,0x30,0x40,0x80,0x01,0x00,0x10,0x00,0x00,0x01,
80 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01 };
81 
82 //--------------------
83 
84 
85 //******************************
86 // 定規
87 //******************************
88 
89 
90 typedef struct
91 {
92 	mWidget wg;
93 	mContainerData ct;
94 
95 	mWidget *wg_type;
96 	mLabel *lb_type;
97 }_tab_rule;
98 
99 enum
100 {
101 	WID_RULE_TYPE = 100,
102 	WID_RULE_BTT_CALL,
103 	WID_RULE_BTT_RECORD
104 };
105 
106 
107 //----------- タイプ選択ウィジェット
108 
109 /** 描画 */
110 
_rule_type_draw_handle(mWidget * wg,mPixbuf * pixbuf)111 static void _rule_type_draw_handle(mWidget *wg,mPixbuf *pixbuf)
112 {
113 	//背景
114 
115 	mPixbufFillBox(pixbuf, 0, 0, wg->w, wg->h, MSYSCOL(WHITE));
116 
117 	//選択の背景
118 
119 	mPixbufFillBox(pixbuf, APP_DRAW->rule.type * 20 + 1, 1, 19, 19, mRGBtoPix(0xff9999));
120 
121 	//イメージ
122 
123 	mPixbufDrawBitPattern(pixbuf, 0, 0, g_img_rule, wg->w, wg->h, 0);
124 }
125 
126 /** イベント */
127 
_rule_type_event_handle(mWidget * wg,mEvent * ev)128 static int _rule_type_event_handle(mWidget *wg,mEvent *ev)
129 {
130 	if(ev->type == MEVENT_POINTER
131 		&& ev->pt.type == MEVENT_POINTER_TYPE_PRESS
132 		&& ev->pt.btt == M_BTT_LEFT)
133 	{
134 		//左ボタン押し時、定規タイプ変更
135 
136 		int n;
137 
138 		n = ev->pt.x / 20;
139 		if(n >= RULE_TYPE_NUM) n = RULE_TYPE_NUM - 1;
140 
141 		if(n != APP_DRAW->rule.type)
142 		{
143 			drawRule_setType(APP_DRAW, n);
144 
145 			mWidgetAppendEvent_notify(NULL, wg, 0, 0, 0);
146 
147 			mWidgetUpdate(wg);
148 		}
149 	}
150 
151 	return 1;
152 }
153 
154 //-----------
155 
156 /** 記録メニュー実行 */
157 
_rule_run_record_menu(mWidget * bttwg)158 static int _rule_run_record_menu(mWidget *bttwg)
159 {
160 	mMenu *menu;
161 	int i,n;
162 	RuleRecord *rec;
163 	mStr str = MSTR_INIT;
164 	mMenuItemInfo *pi;
165 	mBox box;
166 
167 	M_TR_G(TRGROUP_DOCKOPT_RULE);
168 
169 	//メニュー
170 
171 	menu = mMenuNew();
172 
173 	rec = APP_DRAW->rule.record;
174 
175 	for(i = 0; i < RULE_RECORD_NUM; i++, rec++)
176 	{
177 		mStrSetFormat(&str, "[%d] ", i + 1);
178 
179 		if(rec->type == 0)
180 			mStrAppendText(&str, "---");
181 		else
182 		{
183 			mStrAppendFormat(&str, "%s : ", M_TR_T(rec->type));
184 
185 			switch(rec->type)
186 			{
187 				//角度
188 				case RULE_TYPE_PARALLEL_LINE:
189 				case RULE_TYPE_GRID_LINE:
190 					n = round(-rec->d[0] * 18000 / M_MATH_PI);
191 					mStrAppendFormat(&str, "angle %d.%d", n / 100, abs(n % 100));
192 					break;
193 				//位置
194 				case RULE_TYPE_CONC_LINE:
195 				case RULE_TYPE_CIRCLE:
196 					mStrAppendFormat(&str, "(%d,%d)", (int)rec->d[0], (int)rec->d[1]);
197 					break;
198 				//楕円
199 				case RULE_TYPE_ELLIPSE:
200 					n = round(rec->d[3] * 18000 / M_MATH_PI);
201 					mStrAppendFormat(&str, "(%d,%d) angle %d.%d",
202 						(int)rec->d[0], (int)rec->d[1], n / 100, abs(n % 100));
203 					break;
204 			}
205 		}
206 
207 		mMenuAddText_copy(menu, i, str.buf);
208 	}
209 
210 	mWidgetGetRootBox(bttwg, &box);
211 
212 	pi = mMenuPopup(menu, NULL, box.x, box.y + box.h, 0);
213 
214 	n = (pi)? pi->id: -1;
215 
216 	mMenuDestroy(menu);
217 
218 	mStrFree(&str);
219 
220 	return n;
221 }
222 
223 /** イベント */
224 
_rule_event_handle(mWidget * wg,mEvent * ev)225 static int _rule_event_handle(mWidget *wg,mEvent *ev)
226 {
227 	if(ev->type == MEVENT_NOTIFY)
228 	{
229 		_tab_rule *p = (_tab_rule *)wg;
230 		int no;
231 
232 		switch(ev->notify.id)
233 		{
234 			//タイプ変更
235 			case WID_RULE_TYPE:
236 				mLabelSetText(p->lb_type, M_TR_T2(TRGROUP_DOCKOPT_RULE, APP_DRAW->rule.type));
237 				break;
238 			//呼び出し
239 			case WID_RULE_BTT_CALL:
240 				no = _rule_run_record_menu(ev->notify.widgetFrom);
241 				if(no != -1)
242 				{
243 					drawRule_callRecord(APP_DRAW, no);
244 
245 					//タイプ選択
246 					mWidgetUpdate(p->wg_type);
247 					mLabelSetText(p->lb_type, M_TR_T2(TRGROUP_DOCKOPT_RULE, APP_DRAW->rule.type));
248 				}
249 				break;
250 			//記録
251 			case WID_RULE_BTT_RECORD:
252 				no = _rule_run_record_menu(ev->notify.widgetFrom);
253 				if(no != -1)
254 					drawRule_setRecord(APP_DRAW, no);
255 				break;
256 		}
257 	}
258 
259 	return 1;
260 }
261 
262 /** 定規ウィジェット作成 */
263 
DockOption_createTab_rule(mWidget * parent)264 mWidget *DockOption_createTab_rule(mWidget *parent)
265 {
266 	_tab_rule *p;
267 	mWidget *ct,*wg;
268 
269 	M_TR_G(TRGROUP_DOCKOPT_RULE);
270 
271 	//メインコンテナ
272 
273 	p = (_tab_rule *)DockOption_createMainContainer(
274 		sizeof(_tab_rule), parent, _rule_event_handle);
275 
276 	p->ct.sepW = 7;
277 
278 	//タイプ
279 
280 	p->wg_type = wg = mWidgetNew(0, M_WIDGET(p));
281 
282 	wg->id = WID_RULE_TYPE;
283 	wg->hintW = 121;
284 	wg->hintH = 21;
285 	wg->draw = _rule_type_draw_handle;
286 	wg->event = _rule_type_event_handle;
287 	wg->fEventFilter |= MWIDGET_EVENTFILTER_POINTER;
288 
289 	//タイプ名
290 
291 	p->lb_type = mLabelCreate(M_WIDGET(p), MLABEL_S_BORDER, MLF_EXPAND_W, 0, 0);
292 
293 	mLabelSetText(p->lb_type, M_TR_T(APP_DRAW->rule.type));
294 
295 	//ボタン
296 
297 	ct = mContainerCreate(M_WIDGET(p), MCONTAINER_TYPE_HORZ, 0, 4, 0);
298 
299 	mButtonCreate(ct, WID_RULE_BTT_CALL, 0, 0, 0, M_TR_T(100));
300 	mButtonCreate(ct, WID_RULE_BTT_RECORD, 0, 0, 0, M_TR_T(101));
301 
302 	return (mWidget *)p;
303 }
304 
305 
306 //******************************
307 // 入り抜き
308 //******************************
309 
310 
311 typedef struct
312 {
313 	mWidget wg;
314 	mContainerData ct;
315 
316 	ValueBar *bar[2];
317 }_tab_headtail;
318 
319 enum
320 {
321 	WID_HEADTAIL_LINE = 100,
322 	WID_HEADTAIL_BEZIER,
323 	WID_HEADTAIL_BAR_HEAD,
324 	WID_HEADTAIL_BAR_TAIL,
325 	WID_HEADTAIL_BTT_CALL,
326 	WID_HEADTAIL_BTT_RECORD
327 };
328 
329 enum
330 {
331 	TRID_HEADTAIL_LINE,
332 	TRID_HEADTAIL_BEZIER,
333 	TRID_HEADTAIL_HEAD,
334 	TRID_HEADTAIL_TAIL,
335 	TRID_HEADTAIL_CALL,
336 	TRID_HEADTAIL_RECORD
337 };
338 
339 
340 /** 呼出/記録メニュー実行 */
341 
_headtail_run_record_menu(mWidget * bttwg)342 static int _headtail_run_record_menu(mWidget *bttwg)
343 {
344 	mMenu *menu;
345 	mMenuItemInfo *mi;
346 	int i,n1,n2;
347 	uint32_t *prec;
348 	mBox box;
349 	char m[32];
350 
351 	menu = mMenuNew();
352 
353 	prec = APP_DRAW->headtail.record;
354 
355 	for(i = 0; i < HEADTAIL_RECORD_NUM; i++, prec++)
356 	{
357 		n1 = *prec >> 16;
358 		n2 = *prec & 0xffff;
359 
360 		snprintf(m, 32, "[%d] %d.%d - %d.%d", i + 1,
361 			n1 / 10, n1 % 10, n2 / 10, n2 % 10);
362 
363 		mMenuAddText_copy(menu, i, m);
364 	}
365 
366 	mWidgetGetRootBox(bttwg, &box);
367 
368 	mi = mMenuPopup(menu, NULL, box.x, box.y + box.h, 0);
369 
370 	n1 = (mi)? mi->id: -1;
371 
372 	mMenuDestroy(menu);
373 
374 	return n1;
375 }
376 
377 /** バーの値セット */
378 
_headtail_set_bar_value(_tab_headtail * p)379 static void _headtail_set_bar_value(_tab_headtail *p)
380 {
381 	uint32_t val;
382 
383 	val = APP_DRAW->headtail.curval[APP_DRAW->headtail.selno];
384 
385 	ValueBar_setPos(p->bar[0], val >> 16);
386 	ValueBar_setPos(p->bar[1], val & 0xffff);
387 }
388 
389 /** イベント */
390 
_headtail_event_handle(mWidget * wg,mEvent * ev)391 static int _headtail_event_handle(mWidget *wg,mEvent *ev)
392 {
393 	if(ev->type == MEVENT_NOTIFY)
394 	{
395 		_tab_headtail *p = (_tab_headtail *)wg;
396 		int no;
397 
398 		switch(ev->notify.id)
399 		{
400 			//タイプ選択
401 			case WID_HEADTAIL_LINE:
402 			case WID_HEADTAIL_BEZIER:
403 				APP_DRAW->headtail.selno = ev->notify.id - WID_HEADTAIL_LINE;
404 
405 				_headtail_set_bar_value(p);
406 				break;
407 			//バー:入り
408 			case WID_HEADTAIL_BAR_HEAD:
409 				if(ev->notify.param2)
410 				{
411 					APP_DRAW->headtail.curval[APP_DRAW->headtail.selno] &= 0xffff;
412 					APP_DRAW->headtail.curval[APP_DRAW->headtail.selno] |= (uint32_t)ev->notify.param1 << 16;
413 				}
414 				break;
415 			//バー:抜き
416 			case WID_HEADTAIL_BAR_TAIL:
417 				if(ev->notify.param2)
418 				{
419 					APP_DRAW->headtail.curval[APP_DRAW->headtail.selno] &= 0xffff0000;
420 					APP_DRAW->headtail.curval[APP_DRAW->headtail.selno] |= ev->notify.param1;
421 				}
422 				break;
423 			//呼び出し
424 			case WID_HEADTAIL_BTT_CALL:
425 				no = _headtail_run_record_menu(ev->notify.widgetFrom);
426 				if(no != -1)
427 				{
428 					APP_DRAW->headtail.curval[APP_DRAW->headtail.selno] =
429 						APP_DRAW->headtail.record[no];
430 
431 					_headtail_set_bar_value(p);
432 				}
433 				break;
434 			//記録
435 			case WID_HEADTAIL_BTT_RECORD:
436 				no = _headtail_run_record_menu(ev->notify.widgetFrom);
437 				if(no != -1)
438 				{
439 					APP_DRAW->headtail.record[no] =
440 						APP_DRAW->headtail.curval[APP_DRAW->headtail.selno];
441 				}
442 				break;
443 		}
444 	}
445 
446 	return 1;
447 }
448 
449 /** 入り抜きウィジェット作成 */
450 
DockOption_createTab_headtail(mWidget * parent)451 mWidget *DockOption_createTab_headtail(mWidget *parent)
452 {
453 	_tab_headtail *p;
454 	mWidget *ct;
455 	int i;
456 
457 	M_TR_G(TRGROUP_DOCKOPT_HEADTAIL);
458 
459 	//メインコンテナ
460 
461 	p = (_tab_headtail *)DockOption_createMainContainer(
462 		sizeof(_tab_headtail), parent, _headtail_event_handle);
463 
464 	p->ct.sepW = 7;
465 
466 	//タイプ選択
467 
468 	ct = mContainerCreate(M_WIDGET(p), MCONTAINER_TYPE_HORZ, 0, 5, 0);
469 
470 	for(i = 0; i < 2; i++)
471 	{
472 		mCheckButtonCreate(ct, WID_HEADTAIL_LINE + i, MCHECKBUTTON_S_RADIO, 0, 0,
473 			M_TR_T(TRID_HEADTAIL_LINE + i), (APP_DRAW->headtail.selno == i));
474 	}
475 
476 	//バー
477 
478 	ct = mContainerCreateGrid(M_WIDGET(p), 2, 4, 5, MLF_EXPAND_W);
479 
480 	for(i = 0; i < 2; i++)
481 	{
482 		mLabelCreate(ct, 0, MLF_RIGHT | MLF_MIDDLE, 0, M_TR_T(TRID_HEADTAIL_HEAD + i));
483 
484 		p->bar[i] = ValueBar_new(ct, WID_HEADTAIL_BAR_HEAD + i, MLF_EXPAND_W | MLF_MIDDLE,
485 			1, 0, 1000, 0);
486 	}
487 
488 	_headtail_set_bar_value(p);
489 
490 	//ボタン
491 
492 	ct = mContainerCreate(M_WIDGET(p), MCONTAINER_TYPE_HORZ, 0, 4, MLF_RIGHT);
493 	ct->margin.top = 4;
494 
495 	for(i = 0; i < 2; i++)
496 		mButtonCreate(ct, WID_HEADTAIL_BTT_CALL + i, 0, 0, 0, M_TR_T(TRID_HEADTAIL_CALL + i));
497 
498 	return (mWidget *)p;
499 }
500