1 #include "Form.hpp"
2 #include "IniConfig.hpp"
3 
4 static int tempFormsCount = 0;
5 
Form()6 Form:: Form() : _Current(-1) {}
~Form()7 Form::~Form() { Clear(); }
8 
Load(const String & file)9 bool Form::Load(const String& file)
10 {
11 	Clear();
12 
13 	if (!FileExists(file))
14 		return false;
15 
16 	if (GetFileExt(file) == ".fz")
17 	{
18 		String s = ZDecompress(LoadFile(file));
19 		if (!LoadFromXML(*this, s))
20 			return false;
21 		_File = file;
22 		return true;
23 	}
24 
25 	if (!LoadFromXMLFile(*this, file))
26 		return false;
27 	_File = file;
28 	return true;
29 }
30 
Layout(const String & layout,Font font)31 bool Form::Layout(const String& layout, Font font)
32 {
33 	_Current = -1;
34 	for (int i = 0; i < _Layouts.GetCount(); ++i)
35 		if (_Layouts[i].Get("Form.Name") == layout)
36 		{
37 			_Current = i;
38 			return Generate(font);
39 		}
40 	return false;
41 }
42 
Generate(Font font)43 bool Form::Generate(Font font)
44 {
45 	if (!IsLayout())
46 		return false;
47 
48 	Clear(false);
49 
50 	Size sz = _Layouts[_Current].GetFormSize();
51 	SetRect( Rect(Point(0, 0), Size(HorzLayoutZoom(sz.cx), VertLayoutZoom(sz.cy))) );
52 
53 	Vector<FormObject>* p = &_Layouts[_Current].GetObjects();
54 
55 	if (_Layouts[_Current].GetBool("Form.MinimizeBox", false)) MinimizeBox();
56 	if (_Layouts[_Current].GetBool("Form.MaximizeBox", false)) MaximizeBox();
57 
58 #ifdef PLATFORM_WIN32
59 	if (_Layouts[_Current].GetBool("Form.ToolWindow", false)) ToolWindow();
60 #endif
61 
62 	if (_Layouts[_Current].GetBool("Form.Sizeable", false)) Sizeable();
63 
64 	Title(_Layouts[_Current].Get("Form.Title"));
65 
66 	for (int i = 0; i < p->GetCount(); ++i)
67 	{
68 		Font objFont = font;
69 		int h = (*p)[i].GetNumber("Font.Height", 0);
70 		if (h != 0) objFont.Height( VertLayoutZoom(h) );
71 		if (font.GetHeight() == 0) objFont.Height( StdFont().GetHeight() );
72 		Ctrl *c = NULL;
73 
74 		if ((*p)[i].Get("Type") == "Button")
75 		{
76 			Button *b = &_Ctrls.Create<Button>((*p)[i].Get("Variable"));
77 			b->SetFont(objFont);
78 			b->SetLabel((*p)[i].Get("Label"));
79 			b->Tip((*p)[i].Get("Tip"));
80 			*b <<= THISBACK1(OnAction, (*p)[i].Get("Action"));
81 			c = b;
82 		}
83 
84 		if ((*p)[i].Get("Type") == "EditField")
85 		{
86 			EditField *e = &_Ctrls.Create<EditField>((*p)[i].Get("Variable"));
87 			e->SetFont(objFont);
88 			if ((*p)[i].Get("Style") == "Password")
89 				e->Password();
90 			e->Tip((*p)[i].Get("Tip"));
91 			if ((*p)[i].Get("TextAlign") == "Right")
92 				e->AlignRight();
93 
94 			c = e;
95 		}
96 
97 		if ((*p)[i].Get("Type") == "Label")
98 		{
99 			Label *e = &_Ctrls.Create<Label>((*p)[i].Get("Variable"));
100 			e->SetFont(objFont);
101 			Color fontColor = Black();
102 			LoadFromString(fontColor, Decode64((*p)[i].Get("Font.Color",
103 				StoreAsString(fontColor))));
104 			e->SetInk(fontColor);
105 			String align = (*p)[i].Get("Text.Align");
106 			if (align == "Center") e->SetAlign(ALIGN_CENTER);
107 			if (align == "Right") e->SetAlign(ALIGN_RIGHT);
108 			if (align == "Left") e->SetAlign(ALIGN_LEFT);
109 			e->SetLabel((*p)[i].Get("Label"));
110 			c = e;
111 		}
112 
113 		if ((*p)[i].Get("Type") == "DropDate")
114 		{
115 			DropDate *e = &_Ctrls.Create<DropDate>((*p)[i].Get("Variable"));
116 			e->SetFont(objFont);
117 			c = e;
118 		}
119 
120 		if ((*p)[i].Get("Type") == "ProgressBar")
121 		{
122 			ProgressIndicator *e = &_Ctrls.Create<ProgressIndicator>((*p)[i].Get("Variable"));
123 			e->Set(
124 				(*p)[i].GetNumber("ProgressBar.Initial", 0),
125 				(*p)[i].GetNumber("ProgressBar.Total", 100));
126 			c = e;
127 		}
128 
129 		if ((*p)[i].Get("Type") == "EditInt")
130 		{
131 			EditInt *e = &_Ctrls.Create<EditInt>((*p)[i].Get("Variable"));
132 			e->SetFont(objFont);
133 			e->Min((*p)[i].GetNumber("Min", INT_MIN, INT_MAX, INT_MIN));
134 			e->Max((*p)[i].GetNumber("Max", INT_MIN, INT_MAX, INT_MAX));
135 			c = e;
136 		}
137 
138 		if ((*p)[i].Get("Type") == "GridCtrl")
139 		{
140 			GridCtrl *e = &_Ctrls.Create<GridCtrl>((*p)[i].Get("Variable"));
141 			e->Chameleon();
142 			c = e;
143 
144 			String src = (*p)[i].Get("Grid.Columns");
145 			ReplaceString(src, ";", "\r\n");
146 			StringStream s;
147 			s.Open(src);
148 			IniFile f;
149 			f.Load(s);
150 
151 			Vector<String> names = f.EnumNames("Columns");
152 
153 			for (int j = 0; j < names.GetCount(); ++j)
154 			{
155 				int n = ScanInt(names[j]);
156 
157 				if (AsString(n) != names[j])
158 					continue;
159 
160 				Vector<String> values = f.GetArray("Columns", names[j]);
161 				if (values.GetCount() != 3)
162 					continue;
163 				if (values[1] == "Left") e->AddColumn(values[0]).HeaderAlignCenterLeft();
164 				else if (values[1] == "Right") e->AddColumn(values[0]).HeaderAlignCenterRight();
165 				else e->AddColumn(values[0]).HeaderAlignCenter();
166 			}
167 		}
168 
169 		if ((*p)[i].Get("Type") == "TabCtrl")
170 		{
171 			TabCtrl *e = &_Ctrls.Create<TabCtrl>((*p)[i].Get("Variable"));
172 			TabCtrl::Style& style = e->StyleDefault().Write();
173 			style.font = objFont;
174 			style.tabheight = objFont.GetHeight() + VertLayoutZoom(10);
175 			e->SetStyle(style);
176 
177 			String src = (*p)[i].Get("Tab.Content");
178 			ReplaceString(src, ";", "\r\n");
179 			StringStream s;
180 			s.Open(src);
181 			IniFile f;
182 			f.Load(s);
183 
184 			Vector<String> names = f.EnumNames("Tabs");
185 			VectorMap<int, Vector<String> > cache;
186 
187 			for (int j = 0; j < names.GetCount(); ++j)
188 			{
189 				int n = ScanInt(names[j]);
190 
191 				if (AsString(n) != names[j])
192 					continue;
193 
194 				Vector<String> values = f.GetArray("Tabs", names[j]);
195 				if (values.GetCount() != 3)
196 					continue;
197 
198 				if (values[0] == t_("Current form"))
199 					values[0] = _File;
200 
201 				Container *cont = &_Ctrls.Create<Container>("TemporaryContainer"
202 					+ AsString(tempFormsCount));
203 
204 				Form *f = &_Ctrls.Create<Form>("TemporaryForm" + AsString(tempFormsCount++));
205 
206 				if (values[0] != _File)
207 				{
208 					if (!f->Load(GetFileDirectory(_File) + "\\" + values[0]))
209 						continue;
210 				}
211 				else
212 				{
213 					int lay = HasLayout(values[1]);
214 					if (lay < 0)
215 						continue;
216 					f->GetLayouts().Add(_Layouts[lay]);
217 				}
218 
219 				if (!f->Layout(values[1], objFont))
220 					continue;
221 
222 				cont->Set(*f, f->GetSize());
223 				cont->SizePos();
224 				e->Add(*cont, values[2]);
225 			}
226 
227 			if (e->GetCount())
228 			{
229 				int active = (*p)[i].GetNumber("Tab.Active", -1, -1);
230 
231 				if (active < 0)
232 					active = 0;
233 
234 				if (active >= e->GetCount())
235 					active  = e->GetCount() - 1;
236 
237 				e->Set(active);
238 			}
239 
240 			c = e;
241 		}
242 
243 		if ((*p)[i].Get("Type") == "Form")
244 		{
245 			Form *f = &_Ctrls.Create<Form>((*p)[i].Get("Variable"));
246 			f->SignalHandler = SignalHandler;
247 			String path = (*p)[i].Get("Form.Path");
248 			(*p)[i].Get("Form.PathType") == "Relative"
249 				? f->Load(::GetFileDirectory(_File) + "\\" + path)
250 				: f->Load(path);
251 			f->Layout((*p)[i].Get("Form.Layout"), objFont);
252 			f->Script = Script;
253 			c = f;
254 		}
255 
256 		if (!c) continue;
257 
258 		switch((*p)[i].GetHAlign())
259 		{
260 			case Ctrl::LEFT:
261 				c->LeftPosZ((*p)[i].GetRect().left, (*p)[i].GetRect().Width());
262 				break;
263 			case Ctrl::RIGHT:
264 				c->RightPosZ(sz.cx - (*p)[i].GetRect().left - (*p)[i].GetRect().Width(), (*p)[i].GetRect().Width());
265 				break;
266 			case Ctrl::SIZE:
267 				c->HSizePosZ((*p)[i].GetRect().left, sz.cx - (*p)[i].GetRect().left - (*p)[i].GetRect().Width());
268 				break;
269 			case Ctrl::CENTER:
270 				c->HCenterPosZ((*p)[i].GetRect().Width());
271 		}
272 
273 		switch((*p)[i].GetVAlign())
274 		{
275 			case Ctrl::TOP:
276 				c->TopPosZ((*p)[i].GetRect().top, (*p)[i].GetRect().Height());
277 				break;
278 			case Ctrl::BOTTOM:
279 				c->BottomPosZ(sz.cy - (*p)[i].GetRect().top - (*p)[i].GetRect().Height(), (*p)[i].GetRect().Height());
280 				break;
281 			case Ctrl::SIZE:
282 				c->VSizePosZ((*p)[i].GetRect().top, sz.cy - (*p)[i].GetRect().top - (*p)[i].GetRect().Height());
283 				break;
284 			case Ctrl::CENTER:
285 				c->VCenterPosZ((*p)[i].GetRect().Height());
286 		}
287 
288 		String frame = (*p)[i].Get("Frame");
289 
290 		if (frame == "Null frame")             c->SetFrame(NullFrame());
291 		if (frame == "Field frame")            c->SetFrame(FieldFrame());
292 		if (frame == "Inset frame")            c->SetFrame(InsetFrame());
293 		if (frame == "Outset frame")           c->SetFrame(OutsetFrame());
294 		if (frame == "Thin inset frame")       c->SetFrame(ThinInsetFrame());
295 		if (frame == "Thin outset frame")      c->SetFrame(ThinOutsetFrame());
296 		if (frame == "Black frame")            c->SetFrame(BlackFrame());
297 		if (frame == "Button frame")           c->SetFrame(ButtonFrame());
298 		if (frame == "Top separator frame")    c->SetFrame(TopSeparatorFrame());
299 		if (frame == "Left separator frame")   c->SetFrame(LeftSeparatorFrame());
300 		if (frame == "Right separator frame")  c->SetFrame(RightSeparatorFrame());
301 		if (frame == "Bottom separator frame") c->SetFrame(BottomSeparatorFrame());
302 
303 		AddChild(c);
304 	}
305 
306 	return true;
307 }
308 
ExecuteForm()309 String Form::ExecuteForm()
310 {
311 	if (!IsLayout())
312 		return "Error";
313 
314 	WhenClose = TopWindow::Breaker(0);
315 	int result;
316 
317 	for (;;)
318 	{
319 		result = TopWindow::Execute();
320 
321 		if (result == 0)
322 			return "Close";
323 
324 		if (result < 0)
325 			return _Rejectors[ abs(result) - 1 ];
326 
327 		Vector<FormObject>* p = &_Layouts[_Current].GetObjects();
328 		bool null = false;
329 		for (int i = 0; i < p->GetCount(); ++i)
330 		{
331 			if ((*p)[i].GetBool("NotNull"))
332 				if (IsNull(~_Ctrls[i]))
333 				{
334 					PromptOK("Необходимо заполнить поле: " + (*p)[i].Get("Variable"));
335 					null = true;
336 					break;
337 				}
338 		}
339 		if (null)
340 			continue;
341 
342 		break;
343 	}
344 
345 	return _Acceptors[ result - 1 ];
346 }
347 
Clear(bool all)348 void Form::Clear(bool all)
349 {
350 	if (all) _Layouts.Clear();
351 	_Rejectors.Clear();
352 	_Acceptors.Clear();
353 	_Ctrls.Clear();
354 	Script.Clear();
355 }
356 
HasLayout(const String & layout)357 int Form::HasLayout(const String& layout)
358 {
359 	for (int i = 0; i < _Layouts.GetCount(); ++i)
360 		if (_Layouts[i].Get("Form.Name") == layout)
361 			return i;
362 	return -1;
363 }
364 
OnAction(const String & action)365 void Form::OnAction(const String& action)
366 {
367 	SignalHandler(Script, "OnAction", action);
368 }
369 
Exit(const String & action)370 bool Form::Exit(const String& action)
371 {
372 	return SetCallback(action, TopWindow::Rejector(0));
373 }
374 
Acceptor(const String & action)375 bool Form::Acceptor(const String& action)
376 {
377 	if (SetCallback(action, TopWindow::Acceptor( _Acceptors.GetCount() + 1 )))
378 	{
379 		_Acceptors << action;
380 		return true;
381 	}
382 	return false;
383 }
384 
Rejector(const String & action)385 bool Form::Rejector(const String& action)
386 {
387 	if (SetCallback(action, TopWindow::Rejector( -(_Rejectors.GetCount() + 1) )))
388 	{
389 		_Rejectors << action;
390 		return true;
391 	}
392 	return false;
393 }
394 
SetCallback(const String & action,Callback c)395 bool Form::SetCallback(const String& action, Callback c)
396 {
397 	if (!IsLayout())
398 		return false;
399 
400 	Vector<FormObject>* p = &_Layouts[_Current].GetObjects();
401 	for (int i = 0; i < p->GetCount(); ++i)
402 	{
403 		if ((*p)[i].Get("Type") == "Button")
404 			if ((*p)[i].Get("Action") == action)
405 			{
406 				_Ctrls[i] <<= c;
407 				return true;
408 			}
409 	}
410 
411 	return false;
412 }
413 
GetData(const String & var)414 Value Form::GetData(const String& var)
415 {
416 	if (!IsLayout())
417 		return false;
418 
419 	Vector<FormObject>* p = &_Layouts[_Current].GetObjects();
420 	for (int i = 0; i < p->GetCount(); ++i)
421 	{
422 		if ((*p)[i].Get("Variable") == var)
423 			return ~_Ctrls[i];
424 	}
425 	return Value();
426 }
427 
GetCtrl(const String & var)428 Ctrl* Form::GetCtrl(const String& var)
429 {
430 	if (!IsLayout())
431 		return NULL;
432 
433 	Vector<FormObject>* p = &_Layouts[_Current].GetObjects();
434 	for (int i = 0; i < p->GetCount(); ++i)
435 	{
436 		if ((*p)[i].Get("Variable") == var)
437 			return &_Ctrls[i];
438 	}
439 	return NULL;
440 }
441