1
|
#include "CtrlCore.h"
|
2
|
|
3
|
NAMESPACE_UPP
|
4
|
|
5
|
#define LLOG(x)
|
6
|
|
7
|
Ptr<Ctrl> Ctrl::focusCtrl;
|
8
|
Ptr<Ctrl> Ctrl::focusCtrlWnd;
|
9
|
Ptr<Ctrl> Ctrl::lastActiveWnd;
|
10
|
Ptr<Ctrl> Ctrl::caretCtrl;
|
11
|
Rect Ctrl::caretRect;
|
12
|
bool Ctrl::ignorekeyup;
|
13
|
|
14
|
Ptr<Ctrl> Ctrl::defferedSetFocus;
|
15
|
Vector< Ptr<Ctrl> > Ctrl::defferedChildLostFocus;
|
16
|
|
17
|
|
18
|
#ifdef flagSO
|
19
|
Ptr<Ctrl> Ctrl::FocusCtrl() { return focusCtrl; }
|
20
|
void Ctrl::FocusCtrl(Ptr<Ctrl> fc) { focusCtrl = fc; }
|
21
|
#endif
|
22
|
|
23
|
static bool s_hotkey;
|
24
|
|
25
|
void Ctrl::RefreshAccessKeys()
|
26
|
{
|
27
|
GuiLock __;
|
28
|
if(GetAccessKeys())
|
29
|
Refresh();
|
30
|
for(Ctrl *ctrl = GetFirstChild(); ctrl; ctrl = ctrl->GetNext())
|
31
|
ctrl->RefreshAccessKeys();
|
32
|
}
|
33
|
|
34
|
void Ctrl::RefreshAccessKeysDo(bool vis)
|
35
|
{
|
36
|
GuiLock __;
|
37
|
if(GUI_AltAccessKeys() && vis != akv) {
|
38
|
akv = vis;
|
39
|
RefreshAccessKeys();
|
40
|
}
|
41
|
}
|
42
|
|
43
|
bool Ctrl::DispatchKey(dword keycode, int count)
|
44
|
{
|
45
|
GuiLock __;
|
46
|
if(GUI_AltAccessKeys()) {
|
47
|
bool alt = GetAlt();
|
48
|
Ctrl *c = GetActiveCtrl();
|
49
|
if(c)
|
50
|
c->RefreshAccessKeysDo(alt);
|
51
|
}
|
52
|
|
53
|
|
54
|
LLOG("DispatchKey " << keycode << " (0x" << Sprintf("%08x", keycode)
|
55
|
<< ", " << GetKeyDesc(keycode) << "), count:" << count
|
56
|
<< " focusCtrl:" << UPP::Name(focusCtrl) << " focusCtrlWnd:" << UPP::Name(focusCtrlWnd));
|
57
|
if((keycode & K_KEYUP) && ignorekeyup)
|
58
|
{
|
59
|
ignorekeyup = false;
|
60
|
return true;
|
61
|
}
|
62
|
for(int i = 0; i < keyhook().GetCount(); i++)
|
63
|
if((*keyhook()[i])(focusCtrl, keycode, count))
|
64
|
return true;
|
65
|
dword k = keycode;
|
66
|
word l = LOWORD(keycode);
|
67
|
if(!(k & K_DELTA) && l >= 32 && l != 127 && GetDefaultCharset() != CHARSET_UNICODE)
|
68
|
k = MAKELONG((word)FromUnicode(l, CHARSET_DEFAULT), HIWORD(keycode));
|
69
|
if(!focusCtrl)
|
70
|
return false;
|
71
|
Ptr<Ctrl> p = focusCtrl;
|
72
|
if(Ini::user_log) {
|
73
|
String kl;
|
74
|
dword k = keycode;
|
75
|
const char *l = "";
|
76
|
if(k < 65536) {
|
77
|
kl << "CHAR \'" << ToUtf8((wchar)keycode) << "\' (" << keycode << ')';
|
78
|
l = " ";
|
79
|
}
|
80
|
else {
|
81
|
kl << "KEY";
|
82
|
if(k & K_KEYUP) {
|
83
|
kl << "UP";
|
84
|
k &= ~K_KEYUP;
|
85
|
l = " ";
|
86
|
}
|
87
|
kl << " " << GetKeyDesc(k);
|
88
|
}
|
89
|
USRLOG(l << kl);
|
90
|
}
|
91
|
for(;;) {
|
92
|
LLOG("Trying to DispatchKey: p = " << Desc(p));
|
93
|
if(p->IsEnabled() && p->Key(p->unicode ? keycode : k, count))
|
94
|
{
|
95
|
LLOG("Ctrl::DispatchKey(" << FormatIntHex(keycode) << ", " << GetKeyDesc(keycode)
|
96
|
<< "): eaten in " << Desc(p));
|
97
|
if(Ini::user_log)
|
98
|
USRLOG(" -> " << Desc(p));
|
99
|
eventCtrl = focusCtrl;
|
100
|
return true;
|
101
|
}
|
102
|
s_hotkey = true;
|
103
|
if(!p->GetParent()) {
|
104
|
if(p->HotKey(keycode)) {
|
105
|
eventCtrl = focusCtrl;
|
106
|
return true;
|
107
|
}
|
108
|
return false;
|
109
|
}
|
110
|
p = p->GetParent();
|
111
|
}
|
112
|
|
113
|
USRLOG(" key was ignored");
|
114
|
|
115
|
return false;
|
116
|
}
|
117
|
|
118
|
bool Ctrl::HotKey(dword key)
|
119
|
{
|
120
|
GuiLock __;
|
121
|
LLOG("HotKey " << GetKeyDesc(key) << " at " << Name(this));
|
122
|
if(!IsEnabled() || !IsVisible()) return false;
|
123
|
for(Ptr<Ctrl> ctrl = firstchild; ctrl; ctrl = ctrl->next)
|
124
|
{
|
125
|
LLOG("Trying HotKey " << GetKeyDesc(key) << " at " << Name(ctrl));
|
126
|
if(ctrl->IsOpen() && ctrl->IsVisible() && ctrl->IsEnabled() && ctrl->HotKey(key))
|
127
|
{
|
128
|
if(Ini::user_log && s_hotkey) {
|
129
|
USRLOG(" HOT-> " << UPP::Name(ctrl));
|
130
|
s_hotkey = false;
|
131
|
}
|
132
|
LLOG("ACCEPTED");
|
133
|
return true;
|
134
|
}
|
135
|
}
|
136
|
return false;
|
137
|
}
|
138
|
|
139
|
void Ctrl::DoDeactivate(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl)
|
140
|
{
|
141
|
GuiLock __;
|
142
|
if(pfocusCtrl) {
|
143
|
Ptr<Ctrl> ptop = pfocusCtrl->GetTopCtrl();
|
144
|
Ctrl *ntop = nfocusCtrl ? nfocusCtrl->GetTopCtrl() : NULL;
|
145
|
LLOG("DoDeactivate " << UPP::Name(ptop) << " in favor of " << UPP::Name(ntop));
|
146
|
if(ntop != ptop && !ptop->destroying) {
|
147
|
ptop->Deactivate();
|
148
|
if(ptop)
|
149
|
ptop->StateH(DEACTIVATE);
|
150
|
if(ptop)
|
151
|
ptop->RefreshAccessKeysDo(false);
|
152
|
}
|
153
|
}
|
154
|
}
|
155
|
|
156
|
void Ctrl::DoKillFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl)
|
157
|
{
|
158
|
GuiLock __;
|
159
|
if(pfocusCtrl && !pfocusCtrl->destroying) {
|
160
|
pfocusCtrl->StateH(FOCUS);
|
161
|
LLOG("LostFocus: " << Name(pfocusCtrl));
|
162
|
pfocusCtrl->LostFocus();
|
163
|
}
|
164
|
if(pfocusCtrl && pfocusCtrl->parent && !pfocusCtrl->parent->destroying)
|
165
|
pfocusCtrl->parent->ChildLostFocus();
|
166
|
SyncCaret();
|
167
|
}
|
168
|
|
169
|
void Ctrl::DoSetFocus(Ptr<Ctrl> pfocusCtrl, Ptr<Ctrl> nfocusCtrl, bool activate)
|
170
|
{
|
171
|
GuiLock __;
|
172
|
if(activate && focusCtrl == nfocusCtrl && nfocusCtrl) {
|
173
|
Ctrl *top = nfocusCtrl->GetTopCtrl();
|
174
|
if((!pfocusCtrl || pfocusCtrl->GetTopCtrl() != top) && !top->destroying) {
|
175
|
top->StateH(ACTIVATE);
|
176
|
top->Activate();
|
177
|
top->RefreshAccessKeysDo(top->VisibleAccessKeys());
|
178
|
}
|
179
|
}
|
180
|
|
181
|
if(focusCtrl == nfocusCtrl && nfocusCtrl && !nfocusCtrl->destroying) {
|
182
|
nfocusCtrl->GotFocus();
|
183
|
nfocusCtrl->StateH(FOCUS);
|
184
|
}
|
185
|
if(focusCtrl == nfocusCtrl && nfocusCtrl && nfocusCtrl->parent &&
|
186
|
!nfocusCtrl->parent->destroying)
|
187
|
nfocusCtrl->parent->ChildGotFocus();
|
188
|
SyncCaret();
|
189
|
}
|
190
|
|
191
|
|
192
|
|
193
|
|
194
|
|
195
|
|
196
|
|
197
|
|
198
|
|
199
|
|
200
|
|
201
|
|
202
|
|
203
|
|
204
|
|
205
|
|
206
|
|
207
|
|
208
|
|
209
|
|
210
|
|
211
|
|
212
|
|
213
|
|
214
|
|
215
|
|
216
|
|
217
|
|
218
|
|
219
|
|
220
|
|
221
|
|
222
|
|
223
|
|
224
|
|
225
|
bool Ctrl::SetFocus0(bool activate)
|
226
|
{
|
227
|
GuiLock __;
|
228
|
USRLOG(" SETFOCUS " << Desc(this));
|
229
|
LLOG("Ctrl::SetFocus " << Desc(this));
|
230
|
LLOG("focusCtrlWnd " << UPP::Name(focusCtrlWnd));
|
231
|
LLOG("Ctrl::SetFocus0 -> deferredSetFocus = NULL; was: " << UPP::Name(defferedSetFocus));
|
232
|
defferedSetFocus = NULL;
|
233
|
if(focusCtrl == this) return true;
|
234
|
if(!IsOpen() || !IsEnabled() || !IsVisible()) return false;
|
235
|
Ptr<Ctrl> pfocusCtrl = focusCtrl;
|
236
|
Ptr<Ctrl> topwindow = GetTopWindow();
|
237
|
Ptr<Ctrl> topctrl = GetTopCtrl();
|
238
|
Ptr<Ctrl> _this = this;
|
239
|
if(!topwindow) topwindow = topctrl;
|
240
|
LLOG("SetFocus -> SetWndFocus: topwindow = " << UPP::Name(topwindow) << ", focusCtrlWnd = " << UPP::Name(focusCtrlWnd));
|
241
|
if(!topwindow->HasWndFocus() && !topwindow->SetWndFocus()) return false;
|
242
|
#ifdef PLATFORM_OSX11
|
243
|
|
244
|
|
245
|
if(activate)
|
246
|
topctrl->SetWndForeground();
|
247
|
#else
|
248
|
topwindow->SetWndForeground();
|
249
|
#endif
|
250
|
LLOG("SetFocus -> focusCtrl = this: " << FormatIntHex(this) << ", _this = " << FormatIntHex(~_this) << ", " << UPP::Name(_this));
|
251
|
focusCtrl = _this;
|
252
|
focusCtrlWnd = topwindow;
|
253
|
DoKillFocus(pfocusCtrl, _this);
|
254
|
LLOG("SetFocus 2");
|
255
|
DoDeactivate(pfocusCtrl, _this);
|
256
|
DoSetFocus(pfocusCtrl, _this, activate);
|
257
|
if(topwindow)
|
258
|
lastActiveWnd = topwindow;
|
259
|
return true;
|
260
|
}
|
261
|
|
262
|
|
263
|
bool Ctrl::SetFocus()
|
264
|
{
|
265
|
GuiLock __;
|
266
|
LLOG("Ctrl::SetFocus(" << Name() << ")");
|
267
|
return SetFocus0(true);
|
268
|
}
|
269
|
|
270
|
void Ctrl::ActivateWnd()
|
271
|
{
|
272
|
GuiLock __;
|
273
|
|
274
|
LLOG("ActivateWnd " << Name());
|
275
|
Ptr<Ctrl> nfocusCtrl = this;
|
276
|
Ptr<Ctrl> pfocusCtrl = focusCtrl;
|
277
|
LLOG("About to set focus: " << UPP::Name(nfocusCtrl));
|
278
|
DoDeactivate(pfocusCtrl, nfocusCtrl);
|
279
|
focusCtrl = nfocusCtrl;
|
280
|
focusCtrlWnd = this;
|
281
|
DoKillFocus(pfocusCtrl, nfocusCtrl);
|
282
|
DoSetFocus(pfocusCtrl, nfocusCtrl, true);
|
283
|
LLOG("Focus: " << UPP::Name(focusCtrl) << " FocusWnd:" << UPP::Name(focusCtrlWnd));
|
284
|
}
|
285
|
|
286
|
void Ctrl::SetFocusWnd()
|
287
|
{
|
288
|
GuiLock __;
|
289
|
|
290
|
LLOG("Ctrl::SetFocusWnd");
|
291
|
if(focusCtrlWnd != this) {
|
292
|
LLOG("Ctrl::SetFocusWnd->ActivateWnd");
|
293
|
ActivateWnd();
|
294
|
}
|
295
|
}
|
296
|
|
297
|
void Ctrl::KillFocusWnd()
|
298
|
{
|
299
|
GuiLock __;
|
300
|
|
301
|
LLOG("KillFocusWnd " << Name());
|
302
|
if(this == ~focusCtrlWnd) {
|
303
|
Ptr<Ctrl> pfocusCtrl = focusCtrl;
|
304
|
DoDeactivate(pfocusCtrl, NULL);
|
305
|
focusCtrl = focusCtrlWnd = NULL;
|
306
|
DoKillFocus(pfocusCtrl, NULL);
|
307
|
}
|
308
|
}
|
309
|
|
310
|
void Ctrl::ClickActivateWnd()
|
311
|
{
|
312
|
GuiLock __;
|
313
|
LLOG("Ctrl::ClickActivateWnd");
|
314
|
if(this == ~focusCtrlWnd && focusCtrl && focusCtrl->GetTopCtrl() != this) {
|
315
|
LLOG("Ctrl::ClickActivateWnd -> ActivateWnd");
|
316
|
ActivateWnd();
|
317
|
}
|
318
|
}
|
319
|
|
320
|
void Ctrl::DefferedFocusSync()
|
321
|
{
|
322
|
GuiLock __;
|
323
|
while(defferedChildLostFocus.GetCount() || defferedSetFocus) {
|
324
|
LLOG("Ctrl::DeferredFocusSync, defferedSetFocus = " << UPP::Name(defferedSetFocus));
|
325
|
Vector< Ptr<Ctrl> > b = pick(defferedChildLostFocus);
|
326
|
defferedChildLostFocus.Clear();
|
327
|
for(int i = 0; i < b.GetCount(); i++)
|
328
|
if(b[i]) {
|
329
|
LLOG("Ctrl::DeferredFocusSync -> ChildLostFocus " << UPP::Name(b[i]));
|
330
|
b[i]->ChildLostFocus();
|
331
|
}
|
332
|
if(defferedSetFocus) {
|
333
|
LLOG("Ctrl::DeferredFocusSync -> SetFocus " << UPP::Name(defferedSetFocus));
|
334
|
defferedSetFocus->SetFocus();
|
335
|
}
|
336
|
defferedSetFocus = NULL;
|
337
|
SyncCaret();
|
338
|
}
|
339
|
}
|
340
|
|
341
|
void Ctrl::RefreshCaret()
|
342
|
{
|
343
|
GuiLock __;
|
344
|
if(caretCtrl)
|
345
|
caretCtrl->Refresh(caretCtrl->caretx, caretCtrl->carety,
|
346
|
caretCtrl->caretcx, caretCtrl->caretcy);
|
347
|
}
|
348
|
|
349
|
Ctrl *Ctrl::GetActiveWindow()
|
350
|
{
|
351
|
GuiLock __;
|
352
|
Ctrl *q = GetActiveCtrl();
|
353
|
return q ? q->GetTopWindow() : NULL;
|
354
|
}
|
355
|
|
356
|
bool Ctrl::HasFocusDeep() const
|
357
|
{
|
358
|
GuiLock __;
|
359
|
if(HasFocus() || HasChildDeep(FocusCtrl())) return true;
|
360
|
Ctrl *a = GetActiveCtrl();
|
361
|
if(!a || !a->IsPopUp()) return false;
|
362
|
a = a->GetOwnerCtrl();
|
363
|
return a && HasChildDeep(a);
|
364
|
}
|
365
|
|
366
|
String GetKeyDesc(dword key)
|
367
|
{
|
368
|
String desc;
|
369
|
|
370
|
|
371
|
if(key == 0)
|
372
|
return desc;
|
373
|
|
374
|
if(key & K_CTRL) desc << t_("key\vCtrl+");
|
375
|
if(key & K_ALT) desc << t_("key\vAlt+");
|
376
|
if(key & K_SHIFT) desc << t_("key\vShift+");
|
377
|
if(key & K_KEYUP) desc << t_("key\vUP ");
|
378
|
|
379
|
|
380
|
key &= ~(K_CTRL | K_ALT | K_SHIFT | K_KEYUP);
|
381
|
if(key < K_DELTA && key > 32 && key != K_DELETE)
|
382
|
return desc + ToUtf8((wchar)key);
|
383
|
if(key >= K_NUMPAD0 && key <= K_NUMPAD9)
|
384
|
desc << "Num " << (char)(key - K_NUMPAD0 + '0');
|
385
|
else if(key >= K_0 && key <= K_9)
|
386
|
desc << (char)('0' + key - K_0);
|
387
|
else if(key >= K_A && key <= K_Z)
|
388
|
desc << (char)('A' + key - K_A);
|
389
|
else if(key >= K_F1 && key <= K_F12)
|
390
|
desc << Format("F%d", (int)key - K_F1 + 1);
|
391
|
else {
|
392
|
static struct {
|
393
|
dword key;
|
394
|
const char *name;
|
395
|
} nkey[] = {
|
396
|
{ K_TAB, tt_("key\vTab") }, { K_SPACE, tt_("key\vSpace") },
|
397
|
{ K_RETURN, tt_("key\vEnter") }, { K_BACKSPACE, tt_("key\vBackspace") },
|
398
|
{ K_CAPSLOCK, tt_("key\vCaps Lock") }, { K_ESCAPE, tt_("key\vEsc") },
|
399
|
{ K_PAGEUP, tt_("key\vPage Up") }, { K_PAGEDOWN, tt_("key\vPage Down") },
|
400
|
{ K_END, tt_("key\vEnd") }, { K_HOME, tt_("key\vHome") },
|
401
|
{ K_LEFT, tt_("key\vLeft") }, { K_UP, tt_("key\vUp") },
|
402
|
{ K_RIGHT, tt_("key\vRight") }, { K_DOWN, tt_("key\vDown") },
|
403
|
{ K_INSERT, tt_("key\vInsert") }, { K_DELETE, tt_("key\vDelete") },{ K_BREAK, tt_("key\vBreak") },
|
404
|
{ K_MULTIPLY, tt_("key\vNum[*]") }, { K_ADD, tt_("key\vNum[+]") }, { K_SUBTRACT, tt_("key\vNum[-]") }, { K_DIVIDE, tt_("key\vNum[/]") },
|
405
|
{ K_ALT_KEY, tt_("key\vAlt") }, { K_SHIFT_KEY, tt_("key\vShift") }, { K_CTRL_KEY, tt_("key\vCtrl") },
|
406
|
{ K_PLUS, tt_("key\v[+]") }, { K_MINUS, tt_("key\v[-]") }, { K_COMMA, tt_("key\v[,]") }, { K_PERIOD, tt_("key\v[.]") },
|
407
|
{ K_SEMICOLON, tt_("key\v[;]") }, { K_SLASH, tt_("key\v[/]") }, { K_GRAVE, tt_("key\v[`]") }, { K_LBRACKET, tt_("key\v[[]") },
|
408
|
{ K_BACKSLASH, tt_("key\v[\\]") }, { K_RBRACKET, tt_("key\v[]]") }, { K_QUOTEDBL, tt_("key\v[']") },
|
409
|
{ 0, NULL }
|
410
|
};
|
411
|
for(int i = 0; nkey[i].key; i++)
|
412
|
if(nkey[i].key == key) {
|
413
|
desc << GetLngString(nkey[i].name);
|
414
|
return desc;
|
415
|
}
|
416
|
desc << Format("%04x", (int)key);
|
417
|
}
|
418
|
return desc;
|
419
|
}
|
420
|
|
421
|
END_UPP_NAMESPACE
|