1 #include "CtrlCore.h"
2 
3 namespace Upp {
4 
5 #define LLOG(x)   // DLOG(x)
6 
IsDHCtrl() const7 bool Ctrl::IsDHCtrl() const {
8 	return dynamic_cast<const DHCtrl *>(this);
9 }
10 
AddChild(Ctrl * q,Ctrl * p)11 void Ctrl::AddChild(Ctrl *q, Ctrl *p)
12 {
13 	GuiLock __;
14 	ASSERT(q);
15 	LLOG("Add " << UPP::Name(q) << " to: " << Name());
16 	if(p == q) return;
17 	bool updaterect = true;
18 	if(q->parent) {
19 		ASSERT(!q->inframe);
20 		if(q->parent == this) {
21 			RemoveChild0(q);
22 			updaterect = false;
23 		}
24 		else
25 			q->parent->RemoveChild(q);
26 	}
27 	q->parent = this;
28 	if(p) {
29 		ASSERT(p->parent == this);
30 		q->prev = p;
31 		q->next = p->next;
32 		if(p == lastchild)
33 			lastchild = q;
34 		else
35 			p->next->prev = q;
36 		p->next = q;
37 	}
38 	else
39 		if(firstchild) {
40 			q->prev = NULL;
41 			q->next = firstchild;
42 			firstchild->prev = q;
43 			firstchild = q;
44 		}
45 		else {
46 			ASSERT(lastchild == NULL);
47 			firstchild = lastchild = q;
48 			q->prev = q->next = NULL;
49 		}
50 	q->CancelModeDeep();
51 	if(updaterect)
52 		q->UpdateRect();
53 	ChildAdded(q);
54 	q->ParentChange();
55 	if(updaterect && GetTopCtrl()->IsOpen())
56 		q->StateH(OPEN);
57 }
58 
AddChild(Ctrl * child)59 void Ctrl::AddChild(Ctrl *child)
60 {
61 	AddChild(child, lastchild);
62 }
63 
AddChildBefore(Ctrl * child,Ctrl * insbefore)64 void Ctrl::AddChildBefore(Ctrl *child, Ctrl *insbefore)
65 {
66 	if(insbefore)
67 		AddChild(child, insbefore->prev);
68 	else
69 		AddChild(child);
70 }
71 
RemoveChild0(Ctrl * q)72 void  Ctrl::RemoveChild0(Ctrl *q)
73 {
74 	GuiLock __;
75 	ChildRemoved(q);
76 	q->DoRemove();
77 	q->parent = NULL;
78 	if(q == firstchild)
79 		firstchild = firstchild->next;
80 	if(q == lastchild)
81 		lastchild = lastchild->prev;
82 	if(q->prev)
83 		q->prev->next = q->next;
84 	if(q->next)
85 		q->next->prev = q->prev;
86 	q->next = q->prev = NULL;
87 }
88 
RemoveChild(Ctrl * q)89 void  Ctrl::RemoveChild(Ctrl *q)
90 {
91 	GuiLock __;
92 	if(q->parent != this) return;
93 	q->RefreshFrame();
94 	RemoveChild0(q);
95 	q->ParentChange();
96 	if(GetTopCtrl()->IsOpen())
97 		q->StateH(CLOSE);
98 }
99 
Remove()100 void  Ctrl::Remove()
101 {
102 	GuiLock __;
103 	if(parent)
104 		parent->RemoveChild(this);
105 }
106 
GetChildIndex(const Ctrl * child) const107 int Ctrl::GetChildIndex(const Ctrl *child) const
108 {
109 	GuiLock __;
110 	int i = 0;
111 	for (Ctrl *c = GetFirstChild(); c; c = c->GetNext()) {
112 		if(c == child) return i;
113 		i++;
114 	}
115 	return -1;
116 }
117 
GetChildCount() const118 int Ctrl::GetChildCount() const
119 {
120 	GuiLock __;
121 	int n = 0;
122 	for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
123 		n++;
124 	return n;
125 }
126 
GetIndexChild(int ii) const127 Ctrl * Ctrl::GetIndexChild(int ii) const
128 {
129 	GuiLock __;
130 	Ctrl *c = GetFirstChild();
131 	for(int i = 0; i < ii && c; i++)
132 		c = c->GetNext();
133 	return c;
134 }
135 
GetViewChildIndex(const Ctrl * child) const136 int Ctrl::GetViewChildIndex(const Ctrl *child) const
137 {
138 	GuiLock __;
139 	int i = 0;
140 	for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
141 		if(!c->InFrame()) {
142 			if(c == child) return i;
143 			i++;
144 		}
145 	return -1;
146 }
147 
GetViewChildCount() const148 int Ctrl::GetViewChildCount() const
149 {
150 	GuiLock __;
151 	int n = 0;
152 	for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
153 		if(!c->InFrame())
154 			n++;
155 	return n;
156 }
157 
GetViewIndexChild(int ii) const158 Ctrl * Ctrl::GetViewIndexChild(int ii) const
159 {
160 	GuiLock __;
161 	int i = 0;
162 	for (Ctrl *c = GetFirstChild(); c; c = c->GetNext())
163 		if(!c->InFrame()) {
164 			if(i == ii)
165 				return c;
166 			i++;
167 		}
168 	return NULL;
169 }
170 
HasChild(Ctrl * q) const171 bool Ctrl::HasChild(Ctrl *q) const
172 {
173 	GuiLock __;
174 	return q && q->IsChild() && q->parent == this;
175 }
176 
HasChildDeep(Ctrl * q) const177 bool Ctrl::HasChildDeep(Ctrl *q) const
178 {
179 	GuiLock __;
180 	while(q && q->IsChild()) {
181 		if(q->parent == this) return true;
182 		q = q->parent;
183 	}
184 	return false;
185 }
186 
IterateFocusFw(Ctrl * ctrl,bool noframe,bool init,bool all)187 static bool IterateFocusFw(Ctrl *ctrl, bool noframe, bool init, bool all)
188 {
189 	LLOG("IterateFocusFw(" << UPP::Name(ctrl) << ")");
190 	while(ctrl) {
191 		if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled()) {
192 			if(!(noframe && ctrl->InFrame())) {
193 				if(all) {
194 					ctrl->SetFocus();
195 					return true;
196 				}
197 				if((!init || ctrl->IsInitFocus()) && ctrl->SetWantFocus())
198 					return true;
199 			}
200 			if(IterateFocusFw(ctrl->GetFirstChild(), noframe, init, all))
201 				return true;
202 		}
203 		ctrl = ctrl->GetNext();
204 	}
205 	return false;
206 }
207 
IterateFocusForward(Ctrl * ctrl,Ctrl * top,bool noframe,bool init,bool all)208 bool Ctrl::IterateFocusForward(Ctrl *ctrl, Ctrl *top, bool noframe, bool init, bool all)
209 {
210 	GuiLock __;
211 	LLOG("IterateFocusForward(" << UPP::Name(ctrl) << ", top " << UPP::Name(top) << ", noframe " << noframe << ", init " << init << ")");
212 	if(!ctrl) return false;
213 	if(IterateFocusFw(ctrl->GetFirstChild(), noframe, init, all))
214 		return true;
215 	if(ctrl->GetNext() && IterateFocusFw(ctrl->GetNext(), noframe, init, all))
216 		return true;
217 	while(ctrl->GetParent() != top && (ctrl = ctrl->GetParent()) != NULL)
218 		if(IterateFocusFw(ctrl->GetNext(), noframe, init, all))
219 			return true;
220 	return false;
221 }
222 
IterateFocusBw(Ctrl * ctrl,bool noframe,bool all)223 static bool IterateFocusBw(Ctrl *ctrl, bool noframe, bool all)
224 {
225 	while(ctrl) {
226 		if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled()) {
227 			if(IterateFocusBw(ctrl->GetLastChild(), noframe, all))
228 				return true;
229 			if(!(noframe && ctrl->InFrame())) {
230 				if(all) {
231 					ctrl->SetFocus();
232 					return true;
233 				}
234 				if(ctrl->SetWantFocus())
235 					return true;
236 			}
237 		}
238 		ctrl = ctrl->GetPrev();
239 	}
240 	return false;
241 }
242 
IterateFocusBackward(Ctrl * ctrl,Ctrl * top,bool noframe,bool all)243 bool Ctrl::IterateFocusBackward(Ctrl *ctrl, Ctrl *top, bool noframe, bool all)
244 {
245 	GuiLock __;
246 	if(!ctrl || ctrl == top) return false;
247 	if(IterateFocusBw(ctrl->GetPrev(), noframe, all))
248 		return true;
249 	while(ctrl->GetParent() != top) {
250 		ctrl = ctrl->GetParent();
251 		if(ctrl->SetWantFocus())
252 			return true;
253 		if(IterateFocusBw(ctrl->GetPrev(), noframe, all))
254 			return true;
255 	}
256 	return false;
257 }
258 
GetTopCtrl()259 Ctrl *Ctrl::GetTopCtrl()
260 {
261 	GuiLock __;
262 	Ctrl *q = this;
263 	while(q->parent)
264 		q = q->parent;
265 	return q;
266 }
267 
GetTopCtrl() const268 const Ctrl *Ctrl::GetTopCtrl() const      { return const_cast<Ctrl *>(this)->GetTopCtrl(); }
GetOwner() const269 const Ctrl *Ctrl::GetOwner() const        { return const_cast<Ctrl *>(this)->GetOwner(); }
GetTopCtrlOwner()270 Ctrl       *Ctrl::GetTopCtrlOwner()       { return GetTopCtrl()->GetOwner(); }
GetTopCtrlOwner() const271 const Ctrl *Ctrl::GetTopCtrlOwner() const { return GetTopCtrl()->GetOwner(); }
272 
GetOwnerCtrl()273 Ctrl       *Ctrl::GetOwnerCtrl()          { GuiLock __; return !IsChild() && top ? top->owner : NULL; }
GetOwnerCtrl() const274 const Ctrl *Ctrl::GetOwnerCtrl() const    { return const_cast<Ctrl *>(this)->GetOwnerCtrl(); }
275 
GetTopWindow()276 TopWindow *Ctrl::GetTopWindow()
277 {
278 	GuiLock __;
279 	Ctrl *q = this;
280 	while(q) {
281 		q = q->GetTopCtrl();
282 		TopWindow *w = dynamic_cast<TopWindow *>(q);
283 		if(w) return w;
284 		q = q->GetOwner();
285 	}
286 	return NULL;
287 }
288 
GetTopWindow() const289 const TopWindow *Ctrl::GetTopWindow() const
290 {
291 	return const_cast<Ctrl *>(this)->GetTopWindow();
292 }
293 
GetMainWindow()294 TopWindow *Ctrl::GetMainWindow()
295 {
296 	GuiLock __;
297 	Ctrl *q = GetTopCtrl();
298 	for(;;) {
299 		Ctrl *w = q->GetOwner();
300 		if(!w)
301 			return dynamic_cast<TopWindow *>(q);
302 		q = w;
303 	}
304 }
305 
GetMainWindow() const306 const TopWindow *Ctrl::GetMainWindow() const
307 {
308 	return const_cast<Ctrl *>(this)->GetMainWindow();
309 }
310 
311 }
312