1 #include "CtrlCore.h"
2
3 namespace Upp {
4
5 #define LLOG(x) // DLOG(x)
6 #define LTIMING(x) // DTIMING(x)
7
8 bool Ctrl::globalbackpaint;
9 bool Ctrl::globalbackbuffer;
10
sCheckGuiLock()11 static void sCheckGuiLock()
12 {
13 ASSERT_(ThreadHasGuiLock(), "Using GUI in non-main thread without GuiLock");
14 }
15
RefreshFrame(const Rect & r)16 void Ctrl::RefreshFrame(const Rect& r) {
17 sCheckGuiLock();
18 GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
19 if(!IsOpen() || !IsVisible() || r.IsEmpty()) return;
20 LTIMING("RefreshFrame");
21 LLOG("RefreshRect " << Name() << ' ' << r);
22 if(GuiPlatformRefreshFrameSpecial(r))
23 return;
24 if(!top && !IsDHCtrl()) {
25 if(InFrame())
26 parent->RefreshFrame(r + GetRect().TopLeft());
27 else
28 parent->Refresh(r + GetRect().TopLeft());
29 }
30 else {
31 LLOG("WndInvalidateRect: " << r << ' ' << Name());
32 LTIMING("RefreshFrame InvalidateRect");
33 WndInvalidateRect(r);
34 }
35 }
36
Refresh0(const Rect & area)37 void Ctrl::Refresh0(const Rect& area) {
38 RefreshFrame((area + GetView().TopLeft()) & GetView().Inflated(OverPaint()));
39 }
40
Refresh(const Rect & area)41 void Ctrl::Refresh(const Rect& area) {
42 sCheckGuiLock();
43 GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
44 if(fullrefresh || !IsVisible() || !IsOpen()) return;
45 LLOG("Refresh " << Name() << ' ' << area);
46 Refresh0(area);
47 }
48
Refresh()49 void Ctrl::Refresh() {
50 sCheckGuiLock();
51 GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
52 if(fullrefresh || !IsVisible() || !IsOpen()) return;
53 LLOG("Refresh " << Name() << " full:" << fullrefresh);
54 if(!GuiPlatformSetFullRefreshSpecial())
55 fullrefresh = true; // Needs to be set ahead because of possible MT ICall that can cause repaint during Refresh0
56 Refresh0(Rect(GetSize()).Inflated(OverPaint()));
57 }
58
Refresh(int x,int y,int cx,int cy)59 void Ctrl::Refresh(int x, int y, int cx, int cy) {
60 Refresh(RectC(x, y, cx, cy));
61 }
62
RefreshFrame(int x,int y,int cx,int cy)63 void Ctrl::RefreshFrame(int x, int y, int cx, int cy) {
64 RefreshFrame(RectC(x, y, cx, cy));
65 }
66
RefreshFrame()67 void Ctrl::RefreshFrame() {
68 LLOG("RefreshFrame " << Name());
69 RefreshFrame(Rect(GetRect().Size()).Inflated(overpaint));
70 }
71
ScrollRefresh(const Rect & r,int dx,int dy)72 void Ctrl::ScrollRefresh(const Rect& r, int dx, int dy)
73 {
74 sCheckGuiLock();
75 GuiLock __; // Beware: Even if we have ThreadHasGuiLock ASSERT, we still can be the main thread!
76 LLOG("ScrollRefresh " << r << " " << dx << " " << dy);
77 if(!IsOpen() || !IsVisible() || r.IsEmpty()) return;
78 int tdx = tabs(dx), tdy = tabs(dy);
79 if(dx) WndInvalidateRect(RectC(dx >= 0 ? r.left : r.right - tdx, r.top - tdy, tdx, r.Height()));
80 if(dy) WndInvalidateRect(RectC(r.left - tdx, dy >= 0 ? r.top : r.bottom - tdy, r.Width(), tdy));
81 }
82
AddScroll(const Rect & sr,int dx,int dy)83 bool Ctrl::AddScroll(const Rect& sr, int dx, int dy)
84 {
85 GuiLock __;
86 if(!top)
87 return true;
88 for(int i = 0; i < top->scroll.GetCount(); i++) {
89 Scroll& sc = top->scroll[i];
90 if(sc.rect == sr && sgn(dx) == sgn(sc.dx) && sgn(dy) == sgn(sc.dy)) {
91 sc.dx += dx;
92 sc.dy += dy;
93 ScrollRefresh(sc.rect, sc.dx, sc.dy);
94 return false;
95 }
96 if(sc.rect.Intersects(sr)) {
97 sc.rect |= sr;
98 sc.dx = sc.dy = 0;
99 WndInvalidateRect(sc.rect);
100 return true;
101 }
102 }
103 Scroll& sc = top->scroll.Add();
104 sc.rect = sr;
105 sc.dx = dx;
106 sc.dy = dy;
107 ScrollRefresh(sc.rect, sc.dx, sc.dy);
108 return false;
109 }
110
GetClippedView()111 Rect Ctrl::GetClippedView()
112 {
113 GuiLock __;
114 Rect sv = GetScreenView();
115 Rect view = sv;
116 Ctrl *q = parent;
117 Ctrl *w = this;
118 while(q) {
119 view &= w->InFrame() ? q->GetScreenRect() : q->GetScreenView();
120 w = q;
121 q = q->parent;
122 }
123 return view - GetScreenRect().TopLeft();
124 }
125
ScrollCtrl(Top * top,Ctrl * q,const Rect & r,Rect cr,int dx,int dy)126 void Ctrl::ScrollCtrl(Top *top, Ctrl *q, const Rect& r, Rect cr, int dx, int dy)
127 {
128 if(top && r.Intersects(cr)) { // Uno: Contains -> Intersetcs
129 Rect to = cr;
130 GetTopRect(to, false);
131 if(r.Intersects(cr.Offseted(-dx, -dy))) { // Uno's suggestion 06/11/26 Contains -> Intersetcs
132 Rect from = cr.Offseted(-dx, -dy);
133 GetTopRect(from, false);
134 MoveCtrl *m = FindMoveCtrlPtr(top->move, q);
135 if(m && m->from == from && m->to == to) {
136 LLOG("ScrollView Matched " << from << " -> " << to);
137 m->ctrl = NULL;
138 return;
139 }
140 }
141
142 if(r.Intersects(cr.Offseted(dx, dy))) { // Uno's suggestion 06/11/26 Contains -> Intersetcs
143 Rect from = to;
144 to = cr.Offseted(dx, dy);
145 GetTopRect(to, false);
146 MoveCtrl& m = top->scroll_move.Add(q);
147 m.from = from;
148 m.to = to;
149 m.ctrl = q;
150 LLOG("ScrollView Add " << UPP::Name(q) << from << " -> " << to);
151 return;
152 }
153 cr &= r;
154 if(!cr.IsEmpty()) {
155 Refresh(cr);
156 Refresh(cr + Point(dx, dy));
157 }
158 }
159 }
160
ScrollView(const Rect & _r,int dx,int dy)161 void Ctrl::ScrollView(const Rect& _r, int dx, int dy)
162 {
163 GuiLock __;
164 LLOG("ScrollView " << _r << " " << dx << " " << dy);
165 #ifdef GUIPLATFORM_NOSCROLL
166 LLOG("NOSCROLL");
167 Refresh(_r);
168 #else
169 if(IsFullRefresh() || !IsVisible())
170 return;
171 if(IsDHCtrl()) {
172 Refresh(_r);
173 return;
174 }
175 Size vsz = GetSize();
176 dx = sgn(dx) * min(abs(dx), vsz.cx);
177 dy = sgn(dy) * min(abs(dy), vsz.cy);
178 Rect r = _r & vsz;
179 LLOG("ScrollView2 " << r << " " << dx << " " << dy);
180 Ctrl *w;
181 for(w = this; w->parent; w = w->parent)
182 if(w->InFrame()) {
183 Refresh();
184 return;
185 }
186 if(!w || !w->top) return;
187 Rect view = InFrame() ? GetView() : GetClippedView();
188 Rect sr = (r + view.TopLeft()) & view;
189 sr += GetScreenRect().TopLeft() - w->GetScreenRect().TopLeft();
190 if(w->AddScroll(sr, dx, dy))
191 Refresh();
192 else {
193 LTIMING("ScrollCtrls1");
194 Top *top = GetTopCtrl()->top;
195 for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
196 if(q->InView())
197 ScrollCtrl(top, q, r, q->GetRect(), dx, dy);
198 if(parent)
199 for(Ctrl *q = parent->GetFirstChild(); q; q = q->GetNext())
200 if(q->InView() && q != this)
201 ScrollCtrl(top, q, r, q->GetScreenRect() - GetScreenView().TopLeft(), dx, dy);
202 }
203 #endif
204 }
205
ScrollView(int x,int y,int cx,int cy,int dx,int dy)206 void Ctrl::ScrollView(int x, int y, int cx, int cy, int dx, int dy) {
207 ScrollView(RectC(x, y, cx, cy), dx, dy);
208 }
209
ScrollView(int dx,int dy)210 void Ctrl::ScrollView(int dx, int dy) {
211 ScrollView(Rect(GetSize()), dx, dy);
212 }
213
SyncScroll()214 void Ctrl::SyncScroll()
215 {
216 GuiLock __;
217 if(!top)
218 return;
219 Vector<Scroll> scroll = pick(top->scroll);
220 top->scroll.Clear();
221 if(IsFullRefresh())
222 return;
223 for(int i = 0; i < scroll.GetCount(); i++) {
224 Scroll& sc = scroll[i];
225 if(abs(sc.dx) > 3 * sc.rect.Width() / 4 || abs(sc.dy) > 3 * sc.rect.Height() / 4) {
226 LLOG("Sync scroll Invalidate rect" << sc.rect);
227 WndInvalidateRect(sc.rect);
228 }
229 else
230 if(sc.dx || sc.dy) {
231 LLOG("WndScrollView " << sc.rect);
232 WndScrollView(sc.rect, sc.dx, sc.dy);
233 }
234 }
235 }
236
GetOpaqueRect() const237 Rect Ctrl::GetOpaqueRect() const
238 {
239 return IsTransparent() ? Rect(0, 0, 0, 0) : GetSize();
240 }
241
GetVoidRect() const242 Rect Ctrl::GetVoidRect() const
243 {
244 return Rect(0, 0, 0, 0);
245 }
246
247
248 #ifdef _DEBUG
249
250 struct sDrawLevelCheck {
251 Draw& w;
252 int lvl;
253 const Ctrl *q;
254
CheckUpp::sDrawLevelCheck255 void Check() {
256 ASSERT_(lvl == w.GetCloffLevel(), "Draw::Begin/End mismatch for " + UPP::Name(q));
257 }
258
sDrawLevelCheckUpp::sDrawLevelCheck259 sDrawLevelCheck(Draw& w, const Ctrl *q) : w(w), lvl(w.GetCloffLevel()), q(q) {}
260 // NOTE: Checking level in destructor is a bad idea because of exceptions
261 };
262
263 #define LEVELCHECK(w, q) sDrawLevelCheck _x_(w, q)
264 #define DOLEVELCHECK _x_.Check();
265 #else
266 #define LEVELCHECK(w, q)
267 #define DOLEVELCHECK
268 #endif
269
CtrlPaint(SystemDraw & w,const Rect & clip)270 void Ctrl::CtrlPaint(SystemDraw& w, const Rect& clip) {
271 GuiLock __;
272 LEVELCHECK(w, this);
273 LTIMING("CtrlPaint");
274 LLOG("=== CtrlPaint " << UPP::Name(this) << ", clip: " << clip << ", rect: " << GetRect() << ", view: " << GetView());
275 Rect rect = GetRect().GetSize();
276 Rect orect = rect.Inflated(overpaint);
277 if(!IsShown() || orect.IsEmpty() || clip.IsEmpty() || !clip.Intersects(orect))
278 return;
279 Ctrl *q;
280 Rect view = rect;
281 for(int i = 0; i < frame.GetCount(); i++) {
282 LEVELCHECK(w, NULL);
283 frame[i].frame->FramePaint(w, view);
284 view = frame[i].view;
285 }
286 Rect oview = view.Inflated(overpaint);
287 bool hasviewctrls = false;
288 bool viewexcluded = false;
289 bool hiddenbychild = false;
290 for(q = firstchild; q; q = q->next)
291 if(q->IsShown()) {
292 if(q->GetRect().Contains(orect) && !q->IsTransparent())
293 hiddenbychild = true;
294 if(q->InFrame()) {
295 if(!viewexcluded && IsTransparent() && q->GetRect().Intersects(view)) {
296 w.Begin();
297 w.ExcludeClip(view);
298 viewexcluded = true;
299 }
300 LEVELCHECK(w, q);
301 Point off = q->GetRect().TopLeft();
302 w.Offset(off);
303 q->CtrlPaint(w, clip - off);
304 w.End();
305 }
306 else
307 hasviewctrls = true;
308 }
309 if(viewexcluded)
310 w.End();
311 DOLEVELCHECK;
312 if(!hiddenbychild && !oview.IsEmpty() && oview.Intersects(clip) && w.IsPainting(oview)) {
313 LEVELCHECK(w, this);
314 if(overpaint) {
315 w.Clip(oview);
316 w.Offset(view.left, view.top);
317 Paint(w);
318 PaintCaret(w);
319 w.End();
320 w.End();
321 }
322 else {
323 w.Clipoff(view);
324 Paint(w);
325 PaintCaret(w);
326 w.End();
327 }
328 }
329 if(hasviewctrls && !view.IsEmpty()) {
330 Rect cl = clip & view;
331 w.Clip(cl);
332 for(q = firstchild; q; q = q->next)
333 if(q->IsShown() && q->InView()) {
334 LEVELCHECK(w, q);
335 Rect qr = q->GetRect();
336 Point off = qr.TopLeft() + view.TopLeft();
337 Rect ocl = cl - off;
338 if(ocl.Intersects(Rect(qr.GetSize()).Inflated(overpaint))) {
339 w.Offset(off);
340 q->CtrlPaint(w, ocl);
341 w.End();
342 }
343 }
344 w.End();
345 }
346 DOLEVELCHECK;
347 }
348
349 int sShowRepaint;
350
ShowRepaint(int q)351 void Ctrl::ShowRepaint(int q)
352 {
353 sShowRepaint = q;
354 }
355
ShowRepaintRect(SystemDraw & w,const Rect & r,Color c)356 void ShowRepaintRect(SystemDraw& w, const Rect& r, Color c)
357 {
358 if(sShowRepaint) {
359 w.DrawRect(r, c);
360 SystemDraw::Flush();
361 Sleep(sShowRepaint);
362 }
363 }
364
PaintOpaqueAreas(SystemDraw & w,const Rect & r,const Rect & clip,bool nochild)365 bool Ctrl::PaintOpaqueAreas(SystemDraw& w, const Rect& r, const Rect& clip, bool nochild)
366 {
367 GuiLock __;
368 LTIMING("PaintOpaqueAreas");
369 if(!IsShown() || r.IsEmpty() || !r.Intersects(clip) || !w.IsPainting(r))
370 return true;
371 Point off = r.TopLeft();
372 Point viewpos = off + GetView().TopLeft();
373 if(backpaint == EXCLUDEPAINT)
374 return w.ExcludeClip(r);
375 Rect cview = clip & (GetView() + off);
376 for(Ctrl *q = lastchild; q; q = q->prev)
377 if(!q->PaintOpaqueAreas(w, q->GetRect() + (q->InView() ? viewpos : off),
378 q->InView() ? cview : clip))
379 return false;
380 if(nochild && (lastchild || GetNext()))
381 return true;
382 Rect opaque = (GetOpaqueRect() + viewpos) & clip;
383 if(opaque.IsEmpty())
384 return true;
385 #ifdef SYSTEMDRAW
386 if(backpaint == FULLBACKPAINT && !dynamic_cast<BackDraw *>(&w))
387 #else
388 if(backpaint == FULLBACKPAINT && !w.IsBack())
389 #endif
390 {
391 ShowRepaintRect(w, opaque, LtRed());
392 BackDraw bw;
393 bw.Create(w, opaque.GetSize());
394 bw.Offset(viewpos - opaque.TopLeft());
395 bw.SetPaintingDraw(w, opaque.TopLeft());
396 {
397 LEVELCHECK(bw, this);
398 Paint(bw);
399 PaintCaret(bw);
400 DOLEVELCHECK;
401 }
402 bw.Put(w, opaque.TopLeft());
403 }
404 else {
405 w.Clip(opaque);
406 ShowRepaintRect(w, opaque, Green());
407 w.Offset(viewpos);
408 {
409 LEVELCHECK(w, this);
410 Paint(w);
411 PaintCaret(w);
412 DOLEVELCHECK;
413 }
414 w.End();
415 w.End();
416 }
417 LLOG("Exclude " << opaque);
418 return w.ExcludeClip(opaque);
419 }
420
Area(const Rect & r)421 inline int Area(const Rect& r)
422 {
423 return r.GetHeight() * r.GetWidth();
424 }
425
CombineArea(Vector<Rect> & area,const Rect & r)426 void CombineArea(Vector<Rect>& area, const Rect& r)
427 {
428 LTIMING("CombineArea");
429 if(r.IsEmpty()) return;
430 int ra = Area(r);
431 for(int i = 0; i < area.GetCount(); i++) {
432 Rect ur = r | area[i];
433 int a = Area(ur);
434 if(a < 2 * (ra + Area(area[i])) || a < 16000) {
435 area[i] = ur;
436 return;
437 }
438 }
439 area.Add(r);
440 }
441
GatherTransparentAreas(Vector<Rect> & area,SystemDraw & w,Rect r,const Rect & clip)442 void Ctrl::GatherTransparentAreas(Vector<Rect>& area, SystemDraw& w, Rect r, const Rect& clip)
443 {
444 GuiLock __;
445 LTIMING("GatherTransparentAreas");
446 Point off = r.TopLeft();
447 Point viewpos = off + GetView().TopLeft();
448 r.Inflate(overpaint);
449 Rect notr = GetVoidRect();
450 if(notr.IsEmpty())
451 notr = GetOpaqueRect();
452 notr += viewpos;
453 if(!IsShown() || r.IsEmpty() || !clip.Intersects(r) || !w.IsPainting(r))
454 return;
455 if(notr.IsEmpty())
456 CombineArea(area, r & clip);
457 else {
458 if(notr != r) {
459 CombineArea(area, clip & Rect(r.left, r.top, notr.left, r.bottom));
460 CombineArea(area, clip & Rect(notr.right, r.top, r.right, r.bottom));
461 CombineArea(area, clip & Rect(notr.left, r.top, notr.right, notr.top));
462 CombineArea(area, clip & Rect(notr.left, notr.bottom, notr.right, r.bottom));
463 }
464 for(Ctrl *q = firstchild; q; q = q->next) {
465 Point qoff = q->InView() ? viewpos : off;
466 Rect qr = q->GetRect() + qoff;
467 if(clip.Intersects(qr))
468 q->GatherTransparentAreas(area, w, qr, clip);
469 }
470 }
471 }
472
FindBestOpaque(const Rect & clip)473 Ctrl *Ctrl::FindBestOpaque(const Rect& clip)
474 {
475 GuiLock __;
476 Ctrl *w = NULL;
477 for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) {
478 if(q->IsVisible() && GetScreenView().Contains(q->GetScreenRect())) {
479 Rect sw = q->GetScreenView();
480 if((q->GetOpaqueRect() + sw.TopLeft()).Contains(clip)) {
481 w = q;
482 Ctrl *h = q->FindBestOpaque(clip);
483 if(h) w = h;
484 }
485 else
486 if(q->GetScreenView().Contains(clip))
487 w = q->FindBestOpaque(clip);
488 else
489 if(q->GetScreenRect().Intersects(clip))
490 w = NULL;
491 }
492 }
493 return w;
494 }
495
ExcludeDHCtrls(SystemDraw & w,const Rect & r,const Rect & clip)496 void Ctrl::ExcludeDHCtrls(SystemDraw& w, const Rect& r, const Rect& clip)
497 {
498 GuiLock __;
499 LTIMING("PaintOpaqueAreas");
500 if(!IsShown() || r.IsEmpty() || !r.Intersects(clip) || !w.IsPainting(r))
501 return;
502 Point off = r.TopLeft();
503 Point viewpos = off + GetView().TopLeft();
504 if(dynamic_cast<DHCtrl *>(this)) {
505 w.ExcludeClip(r);
506 return;
507 }
508 Rect cview = clip & (GetView() + off);
509 for(Ctrl *q = lastchild; q; q = q->prev)
510 q->ExcludeDHCtrls(w, q->GetRect() + (q->InView() ? viewpos : off),
511 q->InView() ? cview : clip);
512 }
513
UpdateArea0(SystemDraw & draw,const Rect & clip,int backpaint)514 void Ctrl::UpdateArea0(SystemDraw& draw, const Rect& clip, int backpaint)
515 {
516 GuiLock __;
517 LTIMING("UpdateArea");
518 LLOG("========== UPDATE AREA " << UPP::Name(this) << ", clip: " << clip << " ==========");
519 ExcludeDHCtrls(draw, GetRect().GetSize(), clip);
520 if(globalbackbuffer) {
521 CtrlPaint(draw, clip);
522 LLOG("========== END (TARGET IS BACKBUFFER)");
523 return;
524 }
525 if(backpaint == FULLBACKPAINT || globalbackpaint) {
526 ShowRepaintRect(draw, clip, LtRed());
527 BackDraw bw;
528 bw.Create(draw, clip.GetSize());
529 bw.Offset(-clip.TopLeft());
530 bw.SetPaintingDraw(draw, clip.TopLeft());
531 CtrlPaint(bw, clip);
532 bw.Put(draw, clip.TopLeft());
533 LLOG("========== END (FULLBACKPAINT)");
534 return;
535 }
536 if(backpaint == TRANSPARENTBACKPAINT) {
537 LLOG("TransparentBackpaint");
538 Vector<Rect> area;
539 GatherTransparentAreas(area, draw, GetRect().GetSize(), clip);
540 for(int i = 0; i < area.GetCount(); i++) {
541 Rect ar = area[i];
542 LLOG("Painting area: " << ar);
543 ShowRepaintRect(draw, ar, LtBlue());
544 BackDraw bw;
545 bw.Create(draw, ar.GetSize());
546 bw.Offset(-ar.TopLeft());
547 bw.SetPaintingDraw(draw, ar.TopLeft());
548 CtrlPaint(bw, ar);
549 bw.Put(draw, ar.TopLeft());
550 if(!draw.ExcludeClip(ar)) {
551 LLOG("========== END");
552 return;
553 }
554 }
555 PaintOpaqueAreas(draw, GetRect().GetSize(), clip);
556 LLOG("========== END");
557 return;
558 }
559 CtrlPaint(draw, clip);
560 LLOG("========== END");
561 }
562
563 void SweepMkImageCache();
564
UpdateArea(SystemDraw & draw,const Rect & clip)565 void Ctrl::UpdateArea(SystemDraw& draw, const Rect& clip)
566 {
567 GuiLock __;
568 if(IsPanicMode())
569 return;
570 RemoveFullRefresh();
571 Point sp = GetScreenRect().TopLeft();
572 Ctrl *b = FindBestOpaque(clip + sp);
573 if(b) {
574 Point p = b->GetScreenRect().TopLeft() - sp;
575 draw.Offset(p);
576 b->UpdateArea0(draw, clip.Offseted(-p), backpaint);
577 draw.End();
578 }
579 else
580 UpdateArea0(draw, clip, backpaint);
581 SweepMkImageCache();
582 }
583
RemoveFullRefresh()584 void Ctrl::RemoveFullRefresh()
585 {
586 GuiLock __;
587 fullrefresh = false;
588 for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
589 q->RemoveFullRefresh();
590 }
591
GetTopRect(Rect & r,bool inframe,bool clip)592 Ctrl *Ctrl::GetTopRect(Rect& r, bool inframe, bool clip)
593 {
594 GuiLock __;
595 if(!inframe) {
596 if(clip)
597 r &= Rect(GetSize());
598 r.Offset(GetView().TopLeft());
599 }
600 if(parent) {
601 r.Offset(GetRect().TopLeft());
602 return parent->GetTopRect(r, InFrame(), clip);
603 }
604 return this;
605 }
606
DoSync(Ctrl * q,Rect r,bool inframe)607 void Ctrl::DoSync(Ctrl *q, Rect r, bool inframe)
608 {
609 GuiLock __;
610 ASSERT(q);
611 LLOG("DoSync " << UPP::Name(q) << " " << r);
612 Ctrl *top = q->GetTopRect(r, inframe);
613 if(top && top->IsOpen()) {
614 top->SyncScroll();
615 top->WndUpdate(r);
616 }
617 }
618
Sync()619 void Ctrl::Sync()
620 {
621 GuiLock __;
622 LLOG("Sync " << Name());
623 if(top && IsOpen()) {
624 LLOG("Sync UpdateWindow " << Name());
625 SyncScroll();
626 WndUpdate();
627 }
628 else
629 if(parent)
630 DoSync(parent, GetRect(), inframe);
631 SyncCaret();
632 }
633
Sync(const Rect & sr)634 void Ctrl::Sync(const Rect& sr)
635 {
636 GuiLock __;
637 LLOG("Sync " << Name() << " " << sr);
638 DoSync(this, sr, true);
639 SyncCaret();
640 }
641
DrawCtrlWithParent(Draw & w,int x,int y)642 void Ctrl::DrawCtrlWithParent(Draw& w, int x, int y)
643 {
644 GuiLock __;
645 if(parent) {
646 Rect r = GetRect();
647 Ctrl *top = parent->GetTopRect(r, inframe);
648 w.Clip(x, y, r.Width(), r.Height());
649 w.Offset(x - r.left, y - r.top);
650 SystemDraw *ws = dynamic_cast<SystemDraw *>(&w);
651 if(ws)
652 top->UpdateArea(*ws, r);
653 w.End();
654 w.End();
655 }
656 else
657 DrawCtrl(w, x, y);
658 }
659
DrawCtrl(Draw & w,int x,int y)660 void Ctrl::DrawCtrl(Draw& w, int x, int y)
661 {
662 GuiLock __;
663 w.Offset(x, y);
664
665 SystemDraw *ws = dynamic_cast<SystemDraw *>(&w);
666 if(ws)
667 UpdateArea(*ws, GetRect().GetSize());
668
669 // CtrlPaint(w, GetSize()); _DBG_
670
671 w.End();
672 }
673
SyncMoves()674 void Ctrl::SyncMoves()
675 {
676 GuiLock __;
677 if(!top)
678 return;
679 for(int i = 0; i < top->move.GetCount(); i++) {
680 MoveCtrl& m = top->move[i];
681 if(m.ctrl) {
682 RefreshFrame(m.from);
683 RefreshFrame(m.to);
684 }
685 }
686 for(int i = 0; i < top->scroll_move.GetCount(); i++) {
687 MoveCtrl& s = top->scroll_move[i];
688 if(s.ctrl) {
689 RefreshFrame(s.from);
690 RefreshFrame(s.to);
691 }
692 }
693 top->move.Clear();
694 top->scroll_move.Clear();
695 }
696
BackPaintHint()697 Ctrl& Ctrl::BackPaintHint()
698 {
699 GuiLock __;
700 BackPaint();
701 return *this;
702 }
703
GlobalBackPaint(bool b)704 void Ctrl::GlobalBackPaint(bool b)
705 {
706 GuiLock __;
707 globalbackpaint = b;
708 }
709
GlobalBackPaintHint()710 void Ctrl::GlobalBackPaintHint()
711 {
712 GlobalBackPaint();
713 }
714
GlobalBackBuffer(bool b)715 void Ctrl::GlobalBackBuffer(bool b)
716 {
717 GuiLock __;
718 globalbackbuffer = b;
719 }
720
721 }
722