1 #include "CtrlCore.h"
2 
3 namespace Upp {
4 
5 #define LLOG(x)    // DLOG(x)
6 
GetDesc() const7 String TopWindow::GetDesc() const
8 {
9 	return title.ToString();
10 }
11 
GetMinSize() const12 Size TopWindow::GetMinSize() const
13 {
14 	return minsize;
15 }
16 
GetStdSize() const17 Size TopWindow::GetStdSize() const
18 {
19 	return GetMinSize();
20 }
21 
ActiveFocus0(Ctrl & ctrl)22 void TopWindow::ActiveFocus0(Ctrl& ctrl)
23 {
24 	if(IsChild()) return;
25 	activefocus = &ctrl;
26 	LLOG("ActiveFocus0");
27 	if(IsForeground())
28 		ctrl.SetWantFocus();
29 }
30 
Activate()31 void TopWindow::Activate()
32 {
33 	LLOG("Activate " << Name() << " activefocus = " << UPP::Name(activefocus));
34 	USRLOG("   ACTIVATE " + Desc(this));
35 	if(activefocus && (HasFocus() || !GetFocusChildDeep()) && IsEnabled()) {
36 		LLOG("activefocus->SetWantFocus()");
37 		activefocus->SetWantFocus();
38 	}
39 	if(urgent)
40 		SyncCaption();
41 	LLOG("Activate End");
42 }
43 
ChildGotFocus()44 void TopWindow::ChildGotFocus()
45 {
46 	activefocus = GetFocusCtrl();
47 }
48 
Deactivate()49 void TopWindow::Deactivate()
50 {
51 	LLOG("DeActivate current focus " << UPP::Name(GetFocusCtrl()));
52 	if(HasFocusDeep())
53 		activefocus = GetFocusCtrl();
54 	USRLOG("   DEACTIVATE " + Desc(this));
55 	LLOG("DeActivate " << Name() << " activefocus = " << UPP::Name(activefocus));
56 }
57 
PlaceFocus()58 void TopWindow::PlaceFocus()
59 {
60 	LLOG("PlaceFocus " << Upp::Name(this));
61 	if(activefocus)
62 		activefocus->SetFocus();
63 	else
64 		IterateFocusForward(this, this, true, true);
65 }
66 
IsShowEnabled() const67 bool TopWindow::IsShowEnabled() const
68 {
69 	return true;
70 }
71 
DefaultBreak()72 void TopWindow::DefaultBreak()
73 {
74 	if(FindAction(IDCANCEL) || close_rejects)
75 		RejectBreak(IDCANCEL);
76 	else
77 	if(FindAction(IDNO))
78 		RejectBreak(IDNO);
79 	else
80 	if(FindAction(IDEXIT))
81 		AcceptBreak(IDEXIT);
82 	else
83 	if(FindAction(IDYES))
84 		AcceptBreak(IDYES);
85 	else
86 		AcceptBreak(IDOK);
87 }
88 
Close()89 void TopWindow::Close()
90 {
91 	if(InLoop()) {
92 		if(!InCurrentLoop()) return;
93 		DefaultBreak();
94 		return;
95 	}
96 	backup.Clear();
97 	if(IsOpen()) IgnoreMouseUp();
98 	Ctrl::Close();
99 }
100 
Backup()101 void TopWindow::Backup()
102 {
103 	StringStream s;
104 	Ctrl::Serialize(s);
105 	backup = s;
106 }
107 
Restore()108 void TopWindow::Restore()
109 {
110 	StringStream s(backup);
111 	Ctrl::Serialize(s);
112 }
113 
Accept()114 bool TopWindow::Accept()
115 {
116 	Ctrl *q;
117 	for(q = GetFirstChild(); q; q = q->GetNext())
118 		if(!q->Accept())
119 			return false;
120 	return true;
121 }
122 
Reject()123 void TopWindow::Reject()
124 {
125 	for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
126 		q->Reject();
127 	if(!backup.IsEmpty())
128 		Restore();
129 }
130 
Break(int ID)131 void TopWindow::Break(int ID)
132 {
133 	EndLoop(ID);
134 }
135 
AcceptBreak(int ID)136 bool TopWindow::AcceptBreak(int ID)
137 {
138 	if(Accept()) {
139 		Break(ID);
140 		return true;
141 	}
142 	return false;
143 }
144 
RejectBreak(int ID)145 void TopWindow::RejectBreak(int ID)
146 {
147 	Reject();
148 	Break(ID);
149 }
150 
SetupRect(Ctrl * owner)151 void TopWindow::SetupRect(Ctrl *owner)
152 {
153 	Rect r = GetRect();
154 	if(r.IsEmpty())
155 	   SetRect(GetDefaultWindowRect());
156 	else {
157 		r.SetSize(max(r.GetSize(), GetMinSize()));
158 		SetRect(r);
159 		if(r.left == 0 && r.top == 0 && center == 1) {
160 			Rect area = owner ? owner->GetWorkArea() : Ctrl::GetWorkArea();
161 			SetRect(area.CenterRect(min(area.Size(), r.Size())));
162 		}
163 	}
164 }
165 
FixIcons()166 void TopWindow::FixIcons()
167 {
168 	TopWindow *q = GetMainWindow();
169 	if(q) {
170 		if(IsNull(icon)) {
171 			icon = q->GetIcon();
172 			SyncCaption();
173 		}
174 		if(IsNull(largeicon)) {
175 			largeicon = q->GetIcon();
176 			SyncCaption();
177 		}
178 	}
179 }
180 
FindAction(int ID)181 TopWindow::Abreak *TopWindow::FindAction(int ID)
182 {
183 	for(int i = 0; i < action.GetCount(); i++)
184 		if(action[i].ID == ID) return &action[i];
185 	return NULL;
186 }
187 
FindAddAction(int ID)188 TopWindow::Abreak *TopWindow::FindAddAction(int ID)
189 {
190 	Abreak *x = FindAction(ID);
191 	if(x) return x;
192 	Abreak& a = action.Add();
193 	a.ID = ID;
194 	a.dlg = this;
195 	return &a;
196 }
197 
Breaker(int ID)198 Callback TopWindow::Breaker(int ID)
199 {
200 	return callback(FindAddAction(ID), &Abreak::Break);
201 }
202 
Acceptor(int ID)203 Callback TopWindow::Acceptor(int ID)
204 {
205 	return callback(FindAddAction(ID), &Abreak::Accept);
206 }
207 
Rejector(int ID)208 Callback TopWindow::Rejector(int ID)
209 {
210 	return callback(FindAddAction(ID), &Abreak::Reject);
211 }
212 
Breaker(Ctrl & m,int ID)213 TopWindow& TopWindow::Breaker(Ctrl& m, int ID)
214 {
215 	m.WhenAction = Breaker(ID);
216 	return *this;
217 }
218 
Acceptor(Ctrl & m,int ID)219 TopWindow& TopWindow::Acceptor(Ctrl& m, int ID)
220 {
221 	m.WhenAction = Acceptor(ID);
222 	return *this;
223 }
224 
Rejector(Ctrl & m,int ID)225 TopWindow& TopWindow::Rejector(Ctrl& m, int ID)
226 {
227 	m.WhenAction = Rejector(ID);
228 	return *this;
229 }
230 
Paint(Draw & w)231 void TopWindow::Paint(Draw& w)
232 {
233 	if(!IsNull(st->background))
234 		ChPaint(w, GetSize(), st->background);
235 	else
236 		background.Paint(w, GetSize(), SColorText, SColorShadow);
237 }
238 
Background(const PaintRect & prect)239 TopWindow& TopWindow::Background(const PaintRect& prect)
240 {
241 	background = prect;
242 	Refresh();
243 	return *this;
244 }
245 
Key(dword key,int count)246 bool TopWindow::Key(dword key, int count)
247 {
248 	if(Ctrl::Key(key, count))
249 		return true;
250 	if(IsChild()) return false;
251 	if(key == K_DOWN || key == K_RIGHT || key == K_TAB) {
252 		Ctrl *ctrl = GetFocusChildDeep();
253 		if(ctrl && IterateFocusForward(ctrl, this))
254 			return true;
255 		ctrl = GetFirstChild();
256 		if(ctrl) {
257 			if(ctrl->SetWantFocus()) return true;
258 			return IterateFocusForward(ctrl, this);
259 		}
260 	}
261 	if(key == K_UP || key == K_LEFT || key == K_SHIFT_TAB) {
262 		Ctrl *ctrl = GetFocusChildDeep();
263 		if(ctrl && IterateFocusBackward(ctrl, this))
264 			return true;
265 		ctrl = GetLastChild();
266 		if(ctrl) {
267 			if(ctrl->SetWantFocus()) return true;
268 			return IterateFocusBackward(ctrl, this);
269 		}
270 	}
271 	return false;
272 }
273 
WorkAreaTrim()274 void TopWindow::WorkAreaTrim()
275 {
276 	Rect a = GetWorkArea();
277 	Rect h = GetRect();
278 	h.left = max(h.left, a.left);
279 	h.right = min(h.right, a.right);
280 	h.top = max(h.top, a.top);
281 	h.bottom = min(h.bottom, a.bottom);
282 	if(h != GetRect() && !IsChild())
283 		SetRect(h);
284 }
285 
286 
GatherWindowTree(Ctrl * w,const Vector<Ctrl * > & ws,Vector<Ctrl * > & es)287 void GatherWindowTree(Ctrl *w, const Vector<Ctrl *>& ws, Vector<Ctrl *>& es)
288 {
289 	if(!w->InLoop())
290 		es.Add(w);
291 	for(int i = 0; i < ws.GetCount(); i++)
292 		if(ws[i]->GetOwner() == w)
293 			GatherWindowTree(ws[i], ws, es);
294 }
295 
Run(bool appmodal)296 int  TopWindow::Run(bool appmodal)
297 {
298 	GuiLock __;
299 	LLOG("TopWindow::Run() <- " << typeid(*this).name());
300 	LLOG("Focus = " << UPP::Name(GetFocusCtrl()));
301 	if(!IsOpen())
302 		Open();
303 	if(!IsVisible()) Show();
304 	bool pinloop = inloop;
305 	int  pexitcode = exitcode;
306 	exitcode = Null;
307 	Vector<Ctrl *> es;
308 	if(appmodal)
309 		es = GetTopCtrls();
310 	else {
311 		Vector<Ctrl *> ws = GetTopCtrls();
312 		for(int i = 0; i < ws.GetCount(); i++)
313 			if(ws[i]->InLoop())
314 				es.Add(ws[i]);
315 		Ctrl *mw = GetMainWindow();
316 		if(mw) GatherWindowTree(mw, ws, es);
317 	}
318 	Vector< Ptr<Ctrl> > disabled = DisableCtrls(es, this);
319 #ifdef _DEBUG
320 	for(int d = 0; d < disabled.GetCount(); d++)
321 		LLOG("DisableCtrls[" << d << "] = " << UPP::Name(disabled[d]));
322 	LLOG("Running EventLoop in " << UPP::Name(this));
323 #endif
324 	EventLoop(this);
325 #ifdef _DEBUG
326 	LLOG("Finished EventLoop in " << UPP::Name(this));
327 	for(int e = 0; e < disabled.GetCount(); e++)
328 		LLOG("EnableCtrls[" << e << "] = " << UPP::Name(disabled[e]));
329 #endif
330 	EnableCtrls(disabled);
331 	if(IsNull(exitcode)) {
332 		WhenClose();
333 		if(IsNull(exitcode))
334 			DefaultBreak();
335 	}
336 	int q = exitcode;
337 	inloop = pinloop;
338 	exitcode = pexitcode;
339 	LLOG("TopWindow::Run() = " << q << " -> " << typeid(*this).name());
340 #ifdef GUI_WIN
341 	LLOG("Focus = " << UPP::Name(GetFocusCtrl()) << ", raw " << (void *)::GetFocus());
342 #endif
343 	return q;
344 }
345 
Execute()346 int  TopWindow::Execute()
347 {
348 	int m = Run();
349 	Close();
350 	return m;
351 }
352 
Title(const WString & _title)353 TopWindow& TopWindow::Title(const WString& _title)
354 {
355 	if(title != _title) {
356 		title = _title;
357 		SyncTitle();
358 	}
359 	return *this;
360 }
361 
Title(const char * s)362 TopWindow& TopWindow::Title(const char *s)
363 {
364 	return Title(WString(s));
365 }
366 
SetMinSize(Size sz)367 void TopWindow::SetMinSize(Size sz)
368 {
369 	minsize = sz;
370 	SyncSizeHints();
371 }
372 
Sizeable(bool b)373 TopWindow& TopWindow::Sizeable(bool b)
374 {
375 	sizeable = b;
376 	SyncCaption();
377 	SyncSizeHints();
378 	return *this;
379 }
380 
MinimizeBox(bool b)381 TopWindow& TopWindow::MinimizeBox(bool b)
382 {
383 	minimizebox = b;
384 	SyncCaption();
385 	SyncSizeHints();
386 	return *this;
387 }
388 
MaximizeBox(bool b)389 TopWindow& TopWindow::MaximizeBox(bool b)
390 {
391 	maximizebox = b;
392 	SyncCaption();
393 	SyncSizeHints();
394 	return *this;
395 }
396 
Icon(const Image & m)397 TopWindow& TopWindow::Icon(const Image& m)
398 {
399 	if(!icon.IsSame(m)) {
400 		icon = m;
401 		SyncCaption();
402 	}
403 	return *this;
404 }
405 
LargeIcon(const Image & m)406 TopWindow& TopWindow::LargeIcon(const Image& m)
407 {
408 	if(!largeicon.IsSame(m)) {
409 		largeicon = m;
410 		SyncCaption();
411 	}
412 	return *this;
413 }
414 
Icon(const Image & smallicon,const Image & _largeicon)415 TopWindow& TopWindow::Icon(const Image& smallicon, const Image& _largeicon)
416 {
417 	if(!icon.IsSame(smallicon) || !largeicon.IsSame(_largeicon)) {
418 		icon = smallicon;
419 		largeicon = _largeicon;
420 		SyncCaption();
421 	}
422 	return *this;
423 }
424 
ToolWindow(bool b)425 TopWindow& TopWindow::ToolWindow(bool b)
426 {
427 	tool = b;
428 	SyncCaption();
429 	return *this;
430 }
431 
Urgent(bool b)432 TopWindow& TopWindow::Urgent(bool b)
433 {
434 	GuiLock __;
435 	urgent = b;
436 	SyncCaption();
437 	return *this;
438 }
439 
FrameLess(bool b)440 TopWindow& TopWindow::FrameLess(bool b)
441 {
442 	GuiLock __;
443 	frameless = b;
444 	SyncCaption();
445 	return *this;
446 }
447 
ShutdownWindow()448 void TopWindow::ShutdownWindow()
449 {
450 }
451 
ShutdownWindows()452 void TopWindow::ShutdownWindows()
453 {
454 	bool again = true;
455 	while(again) {
456 		Vector<Ctrl *> tc = GetTopCtrls();
457 		again = false;
458 		for(int i = 0; i < tc.GetCount(); i++) {
459 			Ptr<TopWindow> w = dynamic_cast<TopWindow *>(tc[i]);
460 			if(w && w->IsOpen() && w->IsEnabled()) {
461 				again = true;
462 				w->SetForeground();
463 				w->ShutdownWindow();
464 				if(w && w->IsOpen())
465 					w->WhenClose();
466 				if(!w || !w->IsOpen())
467 					break;
468 			}
469 		}
470 	}
471 }
472 
473 struct DialogBackground : public Display {
PaintUpp::DialogBackground474 	void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
475 	{
476 		w.DrawRect(r, SColorFace());
477 	}
478 };
479 
480 
CH_STYLE(TopWindow,TopStyle,StyleDefault)481 CH_STYLE(TopWindow, TopStyle, StyleDefault)
482 {
483 	background = Null;
484 }
485 
SetStyle(const TopWindow::TopStyle & s)486 TopWindow& TopWindow::SetStyle(const TopWindow::TopStyle& s)
487 {
488 	st = &s;
489 	RefreshLayout();
490 	RefreshFrame();
491 	return *this;
492 }
493 
TopWindow()494 TopWindow::TopWindow()
495 {
496 	GuiLock __;
497 	GuiPlatformConstruct();
498 	TransparentBackPaint();
499 	background = PaintRect(Single<DialogBackground>(), Null);
500 	SetStyle(StyleDefault());
501 	center = 1;
502 	minsize = Size(80, 20);
503 	maximizebox = minimizebox = sizeable = tool = noclosebox = false;
504 	state = OVERLAPPED;
505 	WhenClose = THISBACK(Close);
506 	overlapped.Clear();
507 	dokeys = true;
508 	fullscreen = frameless = urgent = false;
509 	close_rejects = false;
510 }
511 
~TopWindow()512 TopWindow::~TopWindow()
513 {
514 	GuiLock __;
515 	destroying = true;
516 	if(InLoop())
517 		EndLoop(IDOK);
518 	if(!IsChild())
519 		Close();
520 	GuiPlatformDestruct();
521 }
522 
Maxisize(TopWindow & win,int screencxmax)523 void Maxisize(TopWindow& win, int screencxmax)
524 {
525 	if(win.GetWorkArea().Width() <= screencxmax)
526 		win.Maximize();
527 }
528 
529 CH_INT(SwapOKCancel, 0);
530 
ArrangeOKCancel(Ctrl & ok,Ctrl & cancel)531 void ArrangeOKCancel(Ctrl& ok, Ctrl& cancel)
532 {
533 	if(SwapOKCancel() &&
534 	   ok.GetPos().x.GetB() == cancel.GetPos().x.GetB() &&
535 	   ok.GetPos().y.GetB() == cancel.GetPos().y.GetB()) {
536 	       Ctrl::LogPos h = ok.GetPos();
537 	       ok.SetPos(cancel.GetPos());
538 	       cancel.SetPos(h);
539 	}
540 }
541 
SetLayout_Size(Ctrl & ctrl,Size sz)542 void SetLayout_Size(Ctrl& ctrl, Size sz)
543 {
544 	sz = ctrl.AddFrameSize(sz);
545 	ctrl.SetMinSize(sz);
546 }
547 
SetLayout_Size(Ctrl & ctrl,int cx,int cy)548 void SetLayout_Size(Ctrl& ctrl, int cx, int cy)
549 {
550 	SetLayout_Size(ctrl, Size(cx, cy));
551 }
552 
553 }
554