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