Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fwl / src / core / fwl_noteimp.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../foxitlib.h"\r
8 #include "include/fwl_targetimp.h"\r
9 #include "include/fwl_widgetimp.h"\r
10 #include "include/fwl_widgetmgrimp.h"\r
11 #include "include/fwl_panelimp.h"\r
12 #include "include/fwl_formimp.h"\r
13 #include "include/fwl_noteimp.h"\r
14 #include "include/fwl_threadimp.h"\r
15 #include "include/fwl_appimp.h"\r
16 #include "../../src/basewidget/include/fwl_tooltipctrlimp.h"\r
17 CFWL_NoteLoop::CFWL_NoteLoop(CFWL_WidgetImp *pForm )\r
18     : m_pForm(pForm)\r
19     , m_bContinueModal(TRUE)\r
20 {\r
21 }\r
22 FX_BOOL CFWL_NoteLoop::PreProcessMessage(CFWL_Message *pMessage)\r
23 {\r
24     if (!m_pForm) {\r
25         return FALSE;\r
26     }\r
27     return TranslateAccelerator(pMessage);\r
28 }\r
29 FWL_ERR CFWL_NoteLoop::Idle(FX_INT32 count)\r
30 {\r
31 #if (_FX_OS_==_FX_WIN32_DESKTOP_)\r
32     if (count <= 0)\r
33 #endif\r
34     {\r
35         CFWL_EvtIdle ev;\r
36         IFWL_App *pApp = FWL_GetApp();\r
37         _FWL_RETURN_VALUE_IF_FAIL(pApp, FWL_ERR_Indefinite);\r
38         IFWL_NoteDriver *pDriver = pApp->GetNoteDriver();\r
39         _FWL_RETURN_VALUE_IF_FAIL(pDriver, FWL_ERR_Indefinite);\r
40         pDriver->SendNote(&ev);\r
41     }\r
42     return FWL_ERR_Indefinite;\r
43 }\r
44 CFWL_WidgetImp* CFWL_NoteLoop::GetForm()\r
45 {\r
46     return m_pForm;\r
47 }\r
48 FX_BOOL CFWL_NoteLoop::ContinueModal()\r
49 {\r
50     return m_bContinueModal;\r
51 }\r
52 FWL_ERR CFWL_NoteLoop::EndModalLoop()\r
53 {\r
54     m_bContinueModal = FALSE;\r
55 #if (_FX_OS_==_FX_MACOSX_)\r
56     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
57     IFWL_AdapterWidgetMgr * adapterWidgetMgr = pWidgetMgr->GetAdapterWidgetMgr();\r
58     adapterWidgetMgr->EndLoop();\r
59 #endif\r
60     return FWL_ERR_Succeeded;\r
61 }\r
62 FX_BOOL CFWL_NoteLoop::TranslateAccelerator(CFWL_Message *pMessage)\r
63 {\r
64     if (pMessage->GetClassID() != FWL_MSGHASH_Key) {\r
65         return FALSE;\r
66     }\r
67     if (((CFWL_MsgKey*)pMessage)->m_dwCmd != FWL_MSGKEYCMD_KeyDown) {\r
68         return FALSE;\r
69     }\r
70     CFWL_MsgKey *pMsgKey = (CFWL_MsgKey*)pMessage;\r
71     CFX_MapAccelerators &accel = ((CFWL_FormImp*)m_pForm)->GetAccelerator();\r
72     FX_POSITION pos = accel.GetStartPosition();\r
73     if (!pos) {\r
74         return FALSE;\r
75     }\r
76     FX_DWORD vrKey, rValue;\r
77     while (pos) {\r
78         accel.GetNextAssoc(pos, vrKey, rValue);\r
79         FX_DWORD dwFlags = (vrKey & 0xFF00) >> 8;\r
80         FX_DWORD m_dwKeyCode = vrKey & 0x00FF;\r
81         if (pMsgKey->m_dwFlags == dwFlags && pMsgKey->m_dwKeyCode == m_dwKeyCode) {\r
82             GenerateCommondEvent(rValue);\r
83             return TRUE;\r
84         }\r
85     }\r
86     return FALSE;\r
87 }\r
88 FWL_ERR CFWL_NoteLoop::SetMainForm(CFWL_WidgetImp *pForm)\r
89 {\r
90     m_pForm = pForm;\r
91     return FWL_ERR_Succeeded;\r
92 }\r
93 void CFWL_NoteLoop::GenerateCommondEvent(FX_DWORD dwCommand)\r
94 {\r
95     CFWL_EvtMenuCommand ev;\r
96     ev.m_iCommand = dwCommand;\r
97     IFWL_NoteThread *pThread = m_pForm->GetOwnerThread();\r
98     _FWL_RETURN_IF_FAIL(pThread);\r
99     IFWL_NoteDriver *pDriver = pThread->GetNoteDriver();\r
100     _FWL_RETURN_IF_FAIL(pDriver);\r
101     pDriver->SendNote(&ev);\r
102 }\r
103 CFWL_NoteDriver::CFWL_NoteDriver()\r
104     : m_sendEventCalled(0)\r
105     , m_maxSize(500)\r
106     , m_bFullScreen(FALSE)\r
107     , m_pFocus(NULL)\r
108     , m_pHover(NULL)\r
109     , m_pGrab(NULL)\r
110     , m_hook(NULL)\r
111 {\r
112     m_pNoteLoop = FX_NEW CFWL_NoteLoop;\r
113     PushNoteLoop((IFWL_NoteLoop*)m_pNoteLoop);\r
114 }\r
115 CFWL_NoteDriver::~CFWL_NoteDriver()\r
116 {\r
117     if (m_pNoteLoop) {\r
118         delete m_pNoteLoop;\r
119         m_pNoteLoop = NULL;\r
120     }\r
121     ClearInvalidEventTargets(TRUE);\r
122 }\r
123 FX_BOOL CFWL_NoteDriver::SendNote(CFWL_Note *pNote)\r
124 {\r
125     if (pNote->IsEvent()) {\r
126         FX_INT32 iCount = m_eventTargets.GetCount();\r
127         if (iCount < 1) {\r
128             return TRUE;\r
129         }\r
130         if (FWL_EVTHASH_Mouse == ((CFWL_Event*)pNote)->GetClassID()) {\r
131             CFWL_EvtMouse * pMouse = (CFWL_EvtMouse*)pNote;\r
132             if (FWL_MSGMOUSECMD_MouseHover == pMouse->m_dwCmd) {\r
133                 if (m_pNoteLoop->GetForm() && CFWL_ToolTipContainer::getInstance()->ProcessEnter(pMouse, m_pNoteLoop->GetForm()->GetInterface())) {\r
134                 }\r
135             } else if (FWL_MSGMOUSECMD_MouseLeave == pMouse->m_dwCmd) {\r
136                 if (CFWL_ToolTipContainer::getInstance()->ProcessLeave(pMouse)) {\r
137                 }\r
138             } else if ((FWL_MSGMOUSECMD_LButtonDown <= pMouse->m_dwCmd) && (FWL_MSGMOUSECMD_MButtonDblClk >= pMouse->m_dwCmd)) {\r
139                 if (CFWL_ToolTipContainer::getInstance()->ProcessLeave(pMouse)) {\r
140                 }\r
141             }\r
142         }\r
143         m_sendEventCalled ++;\r
144         FX_POSITION pos = m_eventTargets.GetStartPosition();\r
145         while (pos) {\r
146             FX_LPVOID key = NULL;\r
147             CFWL_EventTarget *pEventTarget;\r
148             m_eventTargets.GetNextAssoc(pos, key, (void*&)pEventTarget);\r
149             if (pEventTarget && !pEventTarget->IsInvalid()) {\r
150                 pEventTarget->ProcessEvent((CFWL_Event*)pNote);\r
151             }\r
152         }\r
153         m_sendEventCalled --;\r
154     } else {\r
155         _FWL_RETURN_VALUE_IF_FAIL(pNote->m_pDstTarget, FALSE);\r
156         IFWL_WidgetDelegate *pDelegate = pNote->m_pDstTarget->SetDelegate(NULL);\r
157         if (pDelegate) {\r
158             pDelegate->OnProcessMessage((CFWL_Message*)pNote);\r
159         }\r
160     }\r
161     return TRUE;\r
162 }\r
163 extern void FWL_PostMessageToMainRoop(CFWL_Message *pMessage);\r
164 FX_BOOL CFWL_NoteDriver::PostMessage(CFWL_Message *pMessage)\r
165 {\r
166     FWL_PostMessageToMainRoop(pMessage);\r
167     return TRUE;\r
168 }\r
169 #define FWL_NoteDriver_EventKey 1100\r
170 FWL_ERR CFWL_NoteDriver::RegisterEventTarget(IFWL_Widget *pListener, IFWL_Widget *pEventSource , FX_DWORD dwFilter )\r
171 {\r
172     FX_DWORD dwkey = (FX_DWORD)(FX_UINTPTR)pListener->GetPrivateData((FX_LPVOID)(FX_UINTPTR)FWL_NoteDriver_EventKey);\r
173     if (dwkey == 0) {\r
174         FX_LPVOID random = FX_Random_MT_Start(0);\r
175         dwkey = rand();\r
176         FX_Random_MT_Close(random);\r
177         pListener->SetPrivateData((FX_LPVOID)(FX_UINTPTR)FWL_NoteDriver_EventKey, (FX_LPVOID)(FX_UINTPTR)dwkey, NULL);\r
178     }\r
179     CFWL_EventTarget *value = NULL;\r
180     if (!m_eventTargets.Lookup((void*)(FX_UINTPTR)dwkey, (FX_LPVOID&)value)) {\r
181         value = FX_NEW CFWL_EventTarget(this, pListener);\r
182         m_eventTargets.SetAt((void*)(FX_UINTPTR)dwkey, value);\r
183     }\r
184     value->SetEventSource(pEventSource, dwFilter);\r
185     return FWL_ERR_Succeeded;\r
186 }\r
187 FWL_ERR CFWL_NoteDriver::UnregisterEventTarget(IFWL_Widget *pListener)\r
188 {\r
189     FX_DWORD dwkey = (FX_DWORD)(FX_UINTPTR)pListener->GetPrivateData((FX_LPVOID)(FX_UINTPTR)FWL_NoteDriver_EventKey);\r
190     if (dwkey == 0) {\r
191         return FWL_ERR_Indefinite;\r
192     }\r
193     CFWL_EventTarget *value = NULL;\r
194     if (m_eventTargets.Lookup((void*)(FX_UINTPTR)dwkey, (FX_LPVOID&)value)) {\r
195         value->FlagInvalid();\r
196     }\r
197     return FWL_ERR_Succeeded;\r
198 }\r
199 void CFWL_NoteDriver::ClearEventTargets(FX_BOOL bRemoveAll)\r
200 {\r
201     ClearInvalidEventTargets(bRemoveAll);\r
202 }\r
203 FX_INT32 CFWL_NoteDriver::GetQueueMaxSize() const\r
204 {\r
205     return m_maxSize;\r
206 }\r
207 FWL_ERR CFWL_NoteDriver::SetQueueMaxSize(const FX_INT32 size)\r
208 {\r
209     m_maxSize = size;\r
210     return FWL_ERR_Succeeded;\r
211 }\r
212 IFWL_NoteThread* CFWL_NoteDriver::GetOwnerThread() const\r
213 {\r
214     return (IFWL_NoteThread *) FWL_GetApp();\r
215 }\r
216 FWL_ERR CFWL_NoteDriver::PushNoteLoop(IFWL_NoteLoop *pNoteLoop)\r
217 {\r
218     m_noteLoopQueue.Add(pNoteLoop);\r
219     return FWL_ERR_Succeeded;\r
220 }\r
221 IFWL_NoteLoop* CFWL_NoteDriver::PopNoteLoop()\r
222 {\r
223     FX_INT32 pos = m_noteLoopQueue.GetSize();\r
224     _FWL_RETURN_VALUE_IF_FAIL(pos > 0, NULL);\r
225     IFWL_NoteLoop * p = (IFWL_NoteLoop *) m_noteLoopQueue.GetAt(pos - 1);\r
226     m_noteLoopQueue.RemoveAt(pos - 1);\r
227     return p;\r
228 }\r
229 FX_BOOL CFWL_NoteDriver::SetFocus(IFWL_Widget *pFocus, FX_BOOL bNotify )\r
230 {\r
231     if (m_pFocus == pFocus) {\r
232         return TRUE;\r
233     }\r
234     IFWL_Widget* pPrev = m_pFocus;\r
235     m_pFocus = pFocus;\r
236     if (pPrev) {\r
237         IFWL_Widget *pWidget = FWL_GetWidgetMgr()->GetWidget(m_pFocus, FWL_WGTRELATION_SystemForm);\r
238         CFWL_FormImp *pForm = pWidget ? (CFWL_FormImp*)((IFWL_TargetData*)pWidget)->GetData() : NULL;\r
239         CFWL_MsgKillFocus ms;\r
240         ms.m_pDstTarget = pPrev;\r
241         ms.m_pSrcTarget = pPrev;\r
242         if (bNotify) {\r
243             ms.m_dwExtend = 1;\r
244         }\r
245         IFWL_WidgetDelegate *pDelegate = pPrev->SetDelegate(NULL);\r
246         if (pDelegate) {\r
247             pDelegate->OnProcessMessage(&ms);\r
248         }\r
249     }\r
250     if (pFocus) {\r
251         IFWL_Widget *pWidget = FWL_GetWidgetMgr()->GetWidget(pFocus, FWL_WGTRELATION_SystemForm);\r
252         CFWL_FormImp *pForm = pWidget ? (CFWL_FormImp*)((IFWL_TargetData*)pWidget)->GetData() : NULL;\r
253         if (pForm) {\r
254             CFWL_WidgetImp *pNewFocus = (CFWL_WidgetImp*)((IFWL_TargetData*)pFocus)->GetData();\r
255             pForm->SetSubFocus(pNewFocus);\r
256         }\r
257         CFWL_MsgSetFocus ms;\r
258         ms.m_pDstTarget = pFocus;\r
259         if (bNotify) {\r
260             ms.m_dwExtend = 1;\r
261         }\r
262         IFWL_WidgetDelegate *pDelegate = pFocus->SetDelegate(NULL);\r
263         if (pDelegate) {\r
264             pDelegate->OnProcessMessage(&ms);\r
265         }\r
266     }\r
267     return TRUE;\r
268 }\r
269 FWL_ERR CFWL_NoteDriver::Run()\r
270 {\r
271     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
272     _FWL_RETURN_VALUE_IF_FAIL(pWidgetMgr, FWL_ERR_Indefinite);\r
273 #if (_FX_OS_==_FX_MACOSX_)\r
274     IFWL_AdapterWidgetMgr * adapterWidgetMgr = pWidgetMgr->GetAdapterWidgetMgr();\r
275     CFWL_NoteLoop *pTopLoop = GetTopLoop();\r
276     if (pTopLoop) {\r
277         CFWL_WidgetImp *formImp = pTopLoop->GetForm();\r
278         if (formImp) {\r
279             IFWL_Widget *pForm = formImp->GetInterface();\r
280             adapterWidgetMgr->RunLoop(pForm);\r
281         }\r
282     }\r
283 #elif (_FX_OS_==_FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_)\r
284     FX_BOOL             bIdle = TRUE;\r
285     FX_INT32    iIdleCount = 0;\r
286     CFWL_NoteLoop *pTopLoop = NULL;\r
287     for (;;) {\r
288         pTopLoop = GetTopLoop();\r
289         if (!pTopLoop || !pTopLoop->ContinueModal()) {\r
290             break;\r
291         }\r
292         if (UnqueueMessage(pTopLoop)) {\r
293             continue;\r
294         }\r
295         while (bIdle && !(pWidgetMgr->CheckMessage_Native())) {\r
296             if (FWL_ERR_Indefinite == pTopLoop->Idle(iIdleCount++)) {\r
297                 bIdle = FALSE;\r
298             }\r
299         }\r
300         do {\r
301             if (FWL_ERR_Indefinite == pWidgetMgr->DispatchMessage_Native()) {\r
302                 break;\r
303             }\r
304             if (pWidgetMgr->IsIdleMessage_Native()) {\r
305                 bIdle = TRUE;\r
306                 iIdleCount = 0;\r
307             }\r
308         } while (pWidgetMgr->CheckMessage_Native());\r
309     }\r
310 #elif (_FX_OS_==_FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_LINUX_EMBEDDED_)\r
311     CFWL_NoteLoop *pTopLoop = NULL;\r
312     for (;;) {\r
313         pTopLoop = GetTopLoop();\r
314         if (!pTopLoop || !pTopLoop->ContinueModal()) {\r
315             break;\r
316         }\r
317         if (UnqueueMessage(pTopLoop)) {\r
318             continue;\r
319         }\r
320         if(pWidgetMgr->CheckMessage_Native()) {\r
321             pWidgetMgr->DispatchMessage_Native();\r
322         }\r
323     }\r
324 #endif\r
325     return FWL_ERR_Succeeded;\r
326 }\r
327 IFWL_Widget* CFWL_NoteDriver::GetFocus()\r
328 {\r
329     return m_pFocus;\r
330 }\r
331 IFWL_Widget* CFWL_NoteDriver::GetHover()\r
332 {\r
333     return m_pHover;\r
334 }\r
335 void CFWL_NoteDriver::SetHover(IFWL_Widget *pHover)\r
336 {\r
337     m_pHover = pHover;\r
338 }\r
339 void CFWL_NoteDriver::SetGrab(IFWL_Widget *pGrab, FX_BOOL bSet)\r
340 {\r
341     m_pGrab = bSet ? pGrab : NULL;\r
342 }\r
343 void CFWL_NoteDriver::NotifyTargetHide(IFWL_Widget *pNoteTarget)\r
344 {\r
345     if (m_pFocus == pNoteTarget) {\r
346         m_pFocus = NULL;\r
347     }\r
348     if (m_pHover == pNoteTarget) {\r
349         m_pHover = NULL;\r
350     }\r
351     if (m_pGrab == pNoteTarget) {\r
352         m_pGrab = NULL;\r
353     }\r
354 }\r
355 void CFWL_NoteDriver::NotifyTargetDestroy(IFWL_Widget *pNoteTarget)\r
356 {\r
357     if (m_pFocus == pNoteTarget) {\r
358         m_pFocus = NULL;\r
359     }\r
360     if (m_pHover == pNoteTarget) {\r
361         m_pHover = NULL;\r
362     }\r
363     if (m_pGrab == pNoteTarget) {\r
364         m_pGrab = NULL;\r
365     }\r
366     UnregisterEventTarget(pNoteTarget);\r
367     FX_INT32 count = m_forms.GetSize();\r
368     for (FX_INT32 nIndex = 0; nIndex < count; nIndex ++) {\r
369         CFWL_FormImp *pForm = (CFWL_FormImp*)m_forms[nIndex];\r
370         if (!pForm) {\r
371             continue;\r
372         }\r
373         CFWL_WidgetImp *pSubFocus = pForm->GetSubFocus();\r
374         _FWL_RETURN_IF_FAIL(pSubFocus);\r
375         if (pSubFocus && pSubFocus->GetInterface() == pNoteTarget) {\r
376             pForm->SetSubFocus(NULL);\r
377         }\r
378     }\r
379 }\r
380 void CFWL_NoteDriver::NotifyFullScreenMode(IFWL_Widget *pNoteTarget, FX_BOOL bFullScreen)\r
381 {\r
382     m_bFullScreen = bFullScreen;\r
383 }\r
384 FWL_ERR CFWL_NoteDriver::RegisterForm(CFWL_WidgetImp *pForm)\r
385 {\r
386     _FWL_RETURN_VALUE_IF_FAIL(pForm, FWL_ERR_Indefinite);\r
387     if (m_forms.Find(pForm) >= 0) {\r
388         return FWL_ERR_Indefinite;\r
389     }\r
390     m_forms.Add(pForm);\r
391     if (m_forms.GetSize() == 1) {\r
392         CFWL_NoteLoop *pLoop = (CFWL_NoteLoop*)m_noteLoopQueue.GetAt(0);\r
393         _FWL_RETURN_VALUE_IF_FAIL(pLoop, FWL_ERR_Indefinite);\r
394         pLoop->SetMainForm(pForm);\r
395     }\r
396     return FWL_ERR_Succeeded;\r
397 }\r
398 FWL_ERR CFWL_NoteDriver::UnRegisterForm(CFWL_WidgetImp *pForm)\r
399 {\r
400     _FWL_RETURN_VALUE_IF_FAIL(pForm, FWL_ERR_Indefinite);\r
401     FX_INT32 nIndex = m_forms.Find(pForm);\r
402     if (nIndex < 0) {\r
403         return FWL_ERR_Indefinite;\r
404     }\r
405     m_forms.RemoveAt(nIndex);\r
406     return FWL_ERR_Succeeded;\r
407 }\r
408 FX_BOOL CFWL_NoteDriver::QueueMessage(CFWL_Message *pMessage)\r
409 {\r
410     pMessage->Retain();\r
411     m_noteQueue.Add(pMessage);\r
412     return TRUE;\r
413 }\r
414 FX_BOOL CFWL_NoteDriver::UnqueueMessage(CFWL_NoteLoop *pNoteLoop)\r
415 {\r
416     if (m_noteQueue.GetSize() < 1) {\r
417         return FALSE;\r
418     }\r
419     CFWL_Message *pMessage = (CFWL_Message*)m_noteQueue[0];\r
420     m_noteQueue.RemoveAt(0);\r
421     if (!IsValidMessage(pMessage)) {\r
422         pMessage->Release();\r
423         return TRUE;\r
424     }\r
425     FX_BOOL bHookMessage = FALSE;\r
426     if (m_hook) {\r
427         bHookMessage = (*m_hook)(pMessage, m_hookInfo);\r
428     }\r
429     if (!bHookMessage && !pNoteLoop->PreProcessMessage(pMessage)) {\r
430         ProcessMessage(pMessage);\r
431     }\r
432     pMessage->Release();\r
433     return TRUE;\r
434 }\r
435 CFWL_NoteLoop* CFWL_NoteDriver::GetTopLoop()\r
436 {\r
437     FX_INT32 size = m_noteLoopQueue.GetSize();\r
438     _FWL_RETURN_VALUE_IF_FAIL(size > 0, NULL);\r
439     return (CFWL_NoteLoop*)m_noteLoopQueue[size - 1];\r
440 }\r
441 FX_INT32 CFWL_NoteDriver::CountLoop()\r
442 {\r
443     return m_noteLoopQueue.GetSize();\r
444 }\r
445 void CFWL_NoteDriver::SetHook(FWLMessageHookCallback callback, FX_LPVOID info)\r
446 {\r
447     m_hook = callback;\r
448     m_hookInfo = info;\r
449 }\r
450 FX_BOOL CFWL_NoteDriver::ProcessMessage(CFWL_Message *pMessage)\r
451 {\r
452     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
453     IFWL_Widget *pMessageForm = pWidgetMgr->IsFormDisabled() ? pMessage->m_pDstTarget : GetMessageForm(pMessage->m_pDstTarget);\r
454     _FWL_RETURN_VALUE_IF_FAIL(pMessageForm, FALSE);\r
455     if (DispatchMessage(pMessage, pMessageForm)) {\r
456         if (pMessage->GetClassID() == FWL_MSGHASH_Mouse) {\r
457             MouseSecondary((CFWL_MsgMouse*)pMessage);\r
458         }\r
459         return TRUE;\r
460     }\r
461     return FALSE;\r
462 }\r
463 FX_BOOL CFWL_NoteDriver::DispatchMessage(CFWL_Message *pMessage, IFWL_Widget *pMessageForm)\r
464 {\r
465     FX_BOOL bRet = FALSE;\r
466     switch (pMessage->GetClassID()) {\r
467         case FWL_MSGHASH_Activate: {\r
468                 bRet = DoActivate((CFWL_MsgActivate*)pMessage, pMessageForm);\r
469                 break;\r
470             }\r
471         case FWL_MSGHASH_Deactivate: {\r
472                 bRet = DoDeactivate((CFWL_MsgDeactivate*)pMessage, pMessageForm);\r
473                 break;\r
474             }\r
475         case FWL_MSGHASH_SetFocus: {\r
476                 bRet = DoSetFocus((CFWL_MsgSetFocus*)pMessage, pMessageForm);\r
477                 break;\r
478             }\r
479         case FWL_MSGHASH_KillFocus: {\r
480                 bRet = DoKillFocus((CFWL_MsgKillFocus*)pMessage, pMessageForm);\r
481                 break;\r
482             }\r
483         case FWL_MSGHASH_Key: {\r
484                 bRet = DoKey((CFWL_MsgKey*)pMessage, pMessageForm);\r
485                 break;\r
486             }\r
487         case FWL_MSGHASH_Mouse: {\r
488                 bRet = DoMouse((CFWL_MsgMouse*)pMessage, pMessageForm);\r
489                 break;\r
490             }\r
491         case FWL_MSGHASH_MouseWheel: {\r
492                 bRet = DoWheel((CFWL_MsgMouseWheel*)pMessage, pMessageForm);\r
493                 break;\r
494             }\r
495         case FWL_MSGHASH_Size: {\r
496                 bRet = DoSize((CFWL_MsgSize*)pMessage);\r
497                 break;\r
498             }\r
499         case FWL_MSGHASH_Cursor: {\r
500                 bRet = TRUE;\r
501                 break;\r
502             }\r
503         case FWL_MSGHASH_WindowMove: {\r
504                 bRet = DoWindowMove((CFWL_MsgWindowMove*)pMessage, pMessageForm);\r
505                 break;\r
506             }\r
507         case FWL_MSGHASH_DropFiles: {\r
508                 bRet = DoDragFiles((CFWL_MsgDropFiles*)pMessage, pMessageForm);\r
509                 break;\r
510             }\r
511         case FWL_MSGHASH_TaskClicked: {\r
512                 bRet = TRUE;\r
513                 break;\r
514             }\r
515         case FWL_MSGHASH_Close: {\r
516                 bRet = TRUE;\r
517                 break;\r
518             }\r
519         default: {\r
520                 bRet = TRUE;\r
521                 break;\r
522             }\r
523     }\r
524     if (bRet) {\r
525         IFWL_WidgetDelegate *pDelegate = pMessage->m_pDstTarget->SetDelegate(NULL);\r
526         if (pDelegate) {\r
527             pDelegate->OnProcessMessage(pMessage);\r
528         }\r
529     }\r
530     return bRet;\r
531 }\r
532 FX_BOOL CFWL_NoteDriver::DoActivate(CFWL_MsgActivate *pMsg, IFWL_Widget *pMessageForm)\r
533 {\r
534     if (m_bFullScreen) {\r
535         return FALSE;\r
536     }\r
537     pMsg->m_pDstTarget = pMessageForm;\r
538     return (pMsg->m_pDstTarget)->GetStates() & FWL_WGTSTATE_Deactivated;\r
539 }\r
540 FX_BOOL CFWL_NoteDriver::DoDeactivate(CFWL_MsgDeactivate *pMsg, IFWL_Widget *pMessageForm)\r
541 {\r
542     if (m_bFullScreen) {\r
543         return FALSE;\r
544     }\r
545     FX_INT32 iTrackLoop = m_noteLoopQueue.GetSize();\r
546     _FWL_RETURN_VALUE_IF_FAIL(iTrackLoop > 0, FALSE);\r
547     if (iTrackLoop == 1) {\r
548         if (pMessageForm->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"))) {\r
549             return FALSE;\r
550         }\r
551         if (pMsg->m_pSrcTarget && pMsg->m_pSrcTarget->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"))) {\r
552             return FALSE;\r
553         }\r
554         if (pMsg->m_pSrcTarget &&  pMsg->m_pSrcTarget->GetClassID() == 1111984755) {\r
555             return FALSE;\r
556         }\r
557         return TRUE;\r
558     }\r
559     IFWL_Widget *pDst = pMsg->m_pDstTarget;\r
560     _FWL_RETURN_VALUE_IF_FAIL(pDst, FALSE);\r
561 #if (_FX_OS_==_FX_MACOSX_)\r
562     if (pDst == pMessageForm && pDst->IsInstance(L"FWL_FORMPROXY")) {\r
563         return TRUE;\r
564     }\r
565 #endif\r
566     return pDst != pMessageForm &&\r
567            !pDst->IsInstance(FX_WSTRC(L"FWL_FORMPROXY")) &&\r
568            !pMessageForm->IsInstance(FX_WSTRC(L"FWL_FORMPROXY"));\r
569 }\r
570 FX_BOOL CFWL_NoteDriver::DoSetFocus(CFWL_MsgSetFocus *pMsg, IFWL_Widget *pMessageForm)\r
571 {\r
572     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
573     if (pWidgetMgr->IsFormDisabled()) {\r
574         m_pFocus = (IFWL_Widget*)pMsg->m_pDstTarget;\r
575         return TRUE;\r
576     } else {\r
577         IFWL_Widget* pWidget = pMsg->m_pDstTarget;\r
578         CFWL_FormImp *pForm = pWidget ? (CFWL_FormImp*)((IFWL_TargetData*)pWidget)->GetData() : NULL;\r
579         if(pForm) {\r
580             CFWL_WidgetImp *pSubFocus = pForm->GetSubFocus();\r
581             if (pSubFocus && ((pSubFocus->GetStates() & FWL_WGTSTATE_Focused) == 0)) {\r
582                 pMsg->m_pDstTarget = pSubFocus->GetInterface();\r
583                 if(m_pFocus != pMsg->m_pDstTarget) {\r
584                     m_pFocus = pMsg->m_pDstTarget;\r
585                     return TRUE;\r
586                 }\r
587             }\r
588         }\r
589     }\r
590     return FALSE;\r
591 }\r
592 FX_BOOL CFWL_NoteDriver::DoKillFocus(CFWL_MsgKillFocus *pMsg, IFWL_Widget *pMessageForm)\r
593 {\r
594     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
595     if (pWidgetMgr->IsFormDisabled()) {\r
596         if (m_pFocus == pMsg->m_pDstTarget) {\r
597             m_pFocus = NULL;\r
598         }\r
599         return TRUE;\r
600     } else {\r
601         IFWL_Widget* pWidget =  pMsg->m_pDstTarget;\r
602         CFWL_FormImp *pForm = pWidget ? (CFWL_FormImp*)((IFWL_TargetData*)pWidget)->GetData() : NULL;\r
603         if(pForm) {\r
604             CFWL_WidgetImp *pSubFocus = pForm->GetSubFocus();\r
605             if (pSubFocus && (pSubFocus->GetStates() & FWL_WGTSTATE_Focused)) {\r
606                 pMsg->m_pDstTarget = pSubFocus->GetInterface();\r
607                 if (m_pFocus == pMsg->m_pDstTarget) {\r
608                     m_pFocus = NULL;\r
609                     return TRUE;\r
610                 }\r
611             }\r
612         }\r
613     }\r
614     return FALSE;\r
615 }\r
616 FX_BOOL CFWL_NoteDriver::DoKey(CFWL_MsgKey *pMsg, IFWL_Widget *pMessageForm)\r
617 {\r
618 #if(_FX_OS_ != _FX_MACOSX_)\r
619     if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown && pMsg->m_dwKeyCode == FWL_VKEY_Tab) {\r
620         CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
621         IFWL_Widget *pForm = GetMessageForm(pMsg->m_pDstTarget);\r
622         IFWL_Widget *pFocus = m_pFocus;\r
623         if (m_pFocus) {\r
624             if (pWidgetMgr->GetWidget(m_pFocus, FWL_WGTRELATION_SystemForm) != pForm) {\r
625                 pFocus = NULL;\r
626             }\r
627         }\r
628         FX_BOOL bFind = FALSE;\r
629         IFWL_Widget *pNextTabStop = pWidgetMgr->nextTab(pForm, pFocus, bFind);\r
630         if (!pNextTabStop) {\r
631             bFind = FALSE;\r
632             pNextTabStop = pWidgetMgr->nextTab(pForm, NULL, bFind);\r
633         }\r
634         if (pNextTabStop == pFocus) {\r
635             return TRUE;\r
636         }\r
637         if (pNextTabStop) {\r
638             SetFocus(pNextTabStop);\r
639         }\r
640         return TRUE;\r
641     }\r
642 #endif\r
643     if (!m_pFocus) {\r
644         if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown && pMsg->m_dwKeyCode == FWL_VKEY_Return) {\r
645             CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
646             IFWL_Widget *defButton = pWidgetMgr->GetDefaultButton(pMessageForm);\r
647             if (defButton) {\r
648                 pMsg->m_pDstTarget = defButton;\r
649                 return TRUE;\r
650             }\r
651         }\r
652         return FALSE;\r
653     }\r
654     pMsg->m_pDstTarget = m_pFocus;\r
655     return TRUE;\r
656 }\r
657 FX_BOOL CFWL_NoteDriver::DoMouse(CFWL_MsgMouse *pMsg, IFWL_Widget *pMessageForm)\r
658 {\r
659     if (pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseLeave ||\r
660             pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseHover ||\r
661             pMsg->m_dwCmd == FWL_MSGMOUSECMD_MouseEnter) {\r
662         return pMsg->m_pDstTarget != NULL;\r
663     }\r
664     if (pMsg->m_pDstTarget != pMessageForm) {\r
665         pMsg->m_pDstTarget->TransformTo(pMessageForm, pMsg->m_fx, pMsg->m_fy);\r
666     }\r
667     if (!DoMouseEx(pMsg, pMessageForm)) {\r
668         pMsg->m_pDstTarget = pMessageForm;\r
669     }\r
670     return TRUE;\r
671 }\r
672 FX_BOOL CFWL_NoteDriver::DoWheel(CFWL_MsgMouseWheel *pMsg, IFWL_Widget *pMessageForm)\r
673 {\r
674     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
675     _FWL_RETURN_VALUE_IF_FAIL(pWidgetMgr, FALSE);\r
676     IFWL_Widget *pDst = pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_fx, pMsg->m_fy);\r
677     if (!pDst) {\r
678         return FALSE;\r
679     }\r
680     while (pDst && pDst->GetClassID() == FWL_CLASSHASH_Grid) {\r
681         pDst = pDst->GetParent();\r
682     }\r
683     pMessageForm->TransformTo(pDst, pMsg->m_fx, pMsg->m_fy);\r
684     pMsg->m_pDstTarget = pDst;\r
685     return TRUE;\r
686 }\r
687 FX_BOOL CFWL_NoteDriver::DoSize(CFWL_MsgSize *pMsg)\r
688 {\r
689     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
690     _FWL_RETURN_VALUE_IF_FAIL(pWidgetMgr, FALSE);\r
691     pWidgetMgr->NotifySizeChanged(pMsg->m_pDstTarget, (FX_FLOAT)pMsg->m_iWidth, (FX_FLOAT)pMsg->m_iHeight);\r
692     return TRUE;\r
693 }\r
694 FX_BOOL CFWL_NoteDriver::DoWindowMove(CFWL_MsgWindowMove *pMsg, IFWL_Widget *pMessageForm)\r
695 {\r
696     return pMsg->m_pDstTarget == pMessageForm;\r
697 }\r
698 FX_BOOL CFWL_NoteDriver::DoDragFiles(CFWL_MsgDropFiles *pMsg, IFWL_Widget *pMessageForm)\r
699 {\r
700     return pMsg->m_pDstTarget == pMessageForm;\r
701 }\r
702 FX_BOOL CFWL_NoteDriver::DoMouseEx(CFWL_MsgMouse *pMsg, IFWL_Widget *pMessageForm)\r
703 {\r
704     CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
705     _FWL_RETURN_VALUE_IF_FAIL(pWidgetMgr, FALSE);\r
706     IFWL_Widget *pTarget = NULL;\r
707     if (m_pGrab) {\r
708         {\r
709             pTarget = m_pGrab;\r
710         }\r
711     }\r
712     if (!pTarget) {\r
713         pTarget = pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_fx, pMsg->m_fy);\r
714         while (pTarget && pTarget->GetClassID() == FWL_CLASSHASH_Grid) {\r
715             pTarget = pTarget->GetParent();\r
716         }\r
717     }\r
718     if (pTarget) {\r
719         if (pMessageForm != pTarget) {\r
720             pMessageForm->TransformTo(pTarget, pMsg->m_fx, pMsg->m_fy);\r
721         }\r
722     }\r
723     if (!pTarget) {\r
724         return FALSE;\r
725     }\r
726     pMsg->m_pDstTarget = pTarget;\r
727     return TRUE;\r
728 }\r
729 void CFWL_NoteDriver::MouseSecondary(CFWL_MsgMouse *pMsg)\r
730 {\r
731     IFWL_Widget *pTarget = pMsg->m_pDstTarget;\r
732     if (pTarget == m_pHover) {\r
733         return;\r
734     }\r
735     if (m_pHover) {\r
736         CFWL_MsgMouse msLeave;\r
737         msLeave.m_pDstTarget = m_pHover;\r
738         msLeave.m_fx = pMsg->m_fx;\r
739         msLeave.m_fy = pMsg->m_fy;\r
740         pTarget->TransformTo(m_pHover, msLeave.m_fx, msLeave.m_fy);\r
741         msLeave.m_dwFlags = 0;\r
742         msLeave.m_dwCmd = FWL_MSGMOUSECMD_MouseLeave;\r
743         DispatchMessage(&msLeave, NULL);\r
744     }\r
745     if (pTarget->GetClassID() == FWL_CLASSHASH_Form) {\r
746         m_pHover = NULL;\r
747         return;\r
748     }\r
749     m_pHover = pTarget;\r
750     CFWL_MsgMouse msHover;\r
751     msHover.m_pDstTarget = pTarget;\r
752     msHover.m_fx = pMsg->m_fx;\r
753     msHover.m_fy = pMsg->m_fy;\r
754     msHover.m_dwFlags = 0;\r
755     msHover.m_dwCmd = FWL_MSGMOUSECMD_MouseHover;\r
756     DispatchMessage(&msHover, NULL);\r
757 }\r
758 FX_BOOL CFWL_NoteDriver::IsValidMessage(CFWL_Message *pMessage)\r
759 {\r
760     if (pMessage->GetClassID() == FWL_MSGHASH_Post) {\r
761         return TRUE;\r
762     }\r
763     FX_INT32 iCount = m_noteLoopQueue.GetSize();\r
764     for (FX_INT32 i = 0; i < iCount; i ++) {\r
765         CFWL_NoteLoop *pNoteLoop = (CFWL_NoteLoop*)m_noteLoopQueue[i];\r
766         CFWL_WidgetImp *pForm = pNoteLoop->GetForm();\r
767         if (pForm && (pForm->GetInterface() == pMessage->m_pDstTarget)) {\r
768             return TRUE;\r
769         }\r
770     }\r
771     iCount = m_forms.GetSize();\r
772     for (FX_INT32 j = 0; j < iCount; j ++) {\r
773         CFWL_FormImp *pForm = (CFWL_FormImp*)m_forms[j];\r
774         if (pForm->GetInterface() == pMessage->m_pDstTarget) {\r
775             return TRUE;\r
776         }\r
777     }\r
778     return FALSE;\r
779 }\r
780 IFWL_Widget* CFWL_NoteDriver::GetMessageForm(IFWL_Widget *pDstTarget)\r
781 {\r
782     FX_INT32 iTrackLoop = m_noteLoopQueue.GetSize();\r
783     _FWL_RETURN_VALUE_IF_FAIL(iTrackLoop > 0, NULL);\r
784     IFWL_Widget *pMessageForm = NULL;\r
785     if (iTrackLoop > 1) {\r
786         CFWL_NoteLoop *pNootLoop = (CFWL_NoteLoop*)m_noteLoopQueue[iTrackLoop - 1];\r
787         pMessageForm = pNootLoop->GetForm()->GetInterface();\r
788     } else {\r
789         pMessageForm = (m_forms.Find(pDstTarget) < 0) ? NULL : pDstTarget;\r
790     }\r
791     if (!pMessageForm && pDstTarget) {\r
792         CFWL_WidgetMgr *pWidgetMgr = (CFWL_WidgetMgr*)FWL_GetWidgetMgr();\r
793         _FWL_RETURN_VALUE_IF_FAIL(pWidgetMgr, NULL);\r
794         pMessageForm = pWidgetMgr->GetWidget(pDstTarget, FWL_WGTRELATION_SystemForm);\r
795     }\r
796     return pMessageForm;\r
797 }\r
798 void CFWL_NoteDriver::ClearInvalidEventTargets(FX_BOOL bRemoveAll)\r
799 {\r
800     FX_POSITION pos = m_eventTargets.GetStartPosition();\r
801     while (pos) {\r
802         FX_LPVOID key = NULL;\r
803         CFWL_EventTarget *pEventTarget = NULL;\r
804         m_eventTargets.GetNextAssoc(pos, key, (void*&)pEventTarget);\r
805         if (pEventTarget && (bRemoveAll || pEventTarget->IsInvalid())) {\r
806             m_eventTargets.RemoveKey(key);\r
807             delete pEventTarget;\r
808         }\r
809     }\r
810 }\r
811 class CFWL_CoreToopTipDP : public IFWL_ToolTipDP, public CFX_Object\r
812 {\r
813 public:\r
814     FWL_ERR                     GetCaption(IFWL_Widget *pWidget, CFX_WideString &wsCaption);\r
815     FX_INT32            GetInitialDelay(IFWL_Widget *pWidget);\r
816     FX_INT32            GetAutoPopDelay(IFWL_Widget *pWidget);\r
817     CFX_DIBitmap*       GetToolTipIcon(IFWL_Widget *pWidget);\r
818     CFX_SizeF           GetToolTipIconSize(IFWL_Widget *pWidget);\r
819     CFX_RectF           GetAnchor();\r
820     CFWL_CoreToopTipDP();\r
821 \r
822     CFX_WideString      m_wsCaption;\r
823     FX_INT32            m_nInitDelayTime;\r
824     FX_INT32            m_nAutoPopDelayTime;\r
825     CFX_RectF           m_fAnchor;\r
826 };\r
827 CFWL_CoreToopTipDP::CFWL_CoreToopTipDP()\r
828 {\r
829     m_nInitDelayTime = 500;\r
830     m_nAutoPopDelayTime = 50000;\r
831     m_fAnchor.Set( 0.0, 0.0, 0.0, 0.0);\r
832 }\r
833 FWL_ERR CFWL_CoreToopTipDP::GetCaption(IFWL_Widget *pWidget, CFX_WideString &wsCaption)\r
834 {\r
835     wsCaption = m_wsCaption;\r
836     return FWL_ERR_Succeeded;\r
837 }\r
838 FX_INT32 CFWL_CoreToopTipDP::GetInitialDelay(IFWL_Widget *pWidget)\r
839 {\r
840     return m_nInitDelayTime;\r
841 }\r
842 FX_INT32 CFWL_CoreToopTipDP::GetAutoPopDelay(IFWL_Widget *pWidget)\r
843 {\r
844     return m_nAutoPopDelayTime;\r
845 }\r
846 CFX_DIBitmap* CFWL_CoreToopTipDP::GetToolTipIcon(IFWL_Widget *pWidget)\r
847 {\r
848     return NULL;\r
849 }\r
850 CFX_SizeF CFWL_CoreToopTipDP::GetToolTipIconSize(IFWL_Widget *pWidget)\r
851 {\r
852     CFX_SizeF sz;\r
853     sz.Set(0, 0);\r
854     return sz;\r
855 }\r
856 CFX_RectF CFWL_CoreToopTipDP::GetAnchor()\r
857 {\r
858     return m_fAnchor;\r
859 }\r
860 CFWL_EventTarget::~CFWL_EventTarget()\r
861 {\r
862     m_eventSources.RemoveAll();\r
863 }\r
864 FX_INT32 CFWL_EventTarget::SetEventSource(IFWL_Widget *pSource, FX_DWORD dwFilter)\r
865 {\r
866     if (pSource) {\r
867         m_eventSources.SetAt(pSource, dwFilter);\r
868         return m_eventSources.GetCount();\r
869     }\r
870     return 1;\r
871 }\r
872 FX_BOOL CFWL_EventTarget::ProcessEvent(CFWL_Event *pEvent)\r
873 {\r
874     IFWL_WidgetDelegate *pDelegate = m_pListener->SetDelegate(NULL);\r
875     _FWL_RETURN_VALUE_IF_FAIL(pDelegate, FALSE);\r
876     if (m_eventSources.GetCount() == 0) {\r
877         pDelegate->OnProcessEvent(pEvent);\r
878         return TRUE;\r
879     }\r
880     FX_POSITION pos = m_eventSources.GetStartPosition();\r
881     while (pos) {\r
882         IFWL_Widget *pSource = NULL;\r
883         FX_DWORD dwFilter = 0;\r
884         m_eventSources.GetNextAssoc(pos, (void*&)pSource, dwFilter);\r
885         if (pSource == pEvent->m_pSrcTarget || pEvent->GetClassID() == FWL_EVTHASH_Idle) {\r
886             if (IsFilterEvent(pEvent, dwFilter)) {\r
887                 pDelegate->OnProcessEvent(pEvent);\r
888                 return TRUE;\r
889             }\r
890         }\r
891     }\r
892     return FALSE;\r
893 }\r
894 FX_BOOL CFWL_EventTarget::IsFilterEvent(CFWL_Event *pEvent, FX_DWORD dwFilter)\r
895 {\r
896     if (dwFilter == FWL_EVENT_ALL_MASK) {\r
897         return TRUE;\r
898     }\r
899     FX_BOOL bRet = FALSE;\r
900     switch (pEvent->GetClassID()) {\r
901         case FWL_EVTHASH_Mouse: {\r
902                 bRet = dwFilter & FWL_EVENT_MOUSE_MASK;\r
903                 break;\r
904             }\r
905         case FWL_EVTHASH_MouseWheel: {\r
906                 bRet = dwFilter & FWL_EVENT_MOUSEWHEEL_MASK;\r
907                 break;\r
908             }\r
909         case FWL_EVTHASH_Key: {\r
910                 bRet = dwFilter & FWL_EVENT_KEY_MASK;\r
911                 break;\r
912             }\r
913         case FWL_EVTHASH_SetFocus:\r
914         case FWL_EVTHASH_KillFocus: {\r
915                 bRet = dwFilter & FWL_EVENT_FOCUSCHANGED_MASK;\r
916                 break;\r
917             }\r
918         case FWL_EVTHASH_Draw: {\r
919                 bRet = dwFilter & FWL_EVENT_DRAW_MASK;\r
920                 break;\r
921             }\r
922         case FWL_EVTHASH_Close: {\r
923                 bRet = dwFilter & FWL_EVENT_CLOSE_MASK;\r
924                 break;\r
925             }\r
926         case FWL_EVTHASH_SizeChanged: {\r
927                 bRet = dwFilter & FWL_EVENT_SIZECHANGED_MASK;\r
928                 break;\r
929             }\r
930         case FWL_EVTHASH_Idle: {\r
931                 bRet = dwFilter & FWL_EVENT_IDLE_MASK;\r
932                 break;\r
933             }\r
934         default: {\r
935                 bRet = dwFilter & FWL_EVENT_CONTROL_MASK;\r
936                 break;\r
937             }\r
938     }\r
939     return bRet;\r
940 }\r
941 CFWL_ToolTipContainer::CFWL_ToolTipContainer()\r
942     : pCurTarget(NULL)\r
943     , m_pToolTipImp(NULL)\r
944 {\r
945     m_ToolTipDp = FX_NEW CFWL_CoreToopTipDP;\r
946     m_ToolTipDp->m_nInitDelayTime = 0;\r
947     m_ToolTipDp->m_nAutoPopDelayTime = 2000;\r
948 }\r
949 CFWL_ToolTipContainer::~CFWL_ToolTipContainer()\r
950 {\r
951     if (m_pToolTipImp) {\r
952         IFWL_ToolTip *pToolTip = (IFWL_ToolTip*)m_pToolTipImp->GetInterface();\r
953         pToolTip->Finalize();\r
954         pToolTip->Release();\r
955         m_pToolTipImp = NULL;\r
956     }\r
957     if (m_ToolTipDp) {\r
958         delete m_ToolTipDp;\r
959         m_ToolTipDp = NULL;\r
960     }\r
961 }\r
962 CFWL_ToolTipContainer* CFWL_ToolTipContainer::getInstance()\r
963 {\r
964     static CFWL_ToolTipContainer * _toolTipContainer = NULL;\r
965     if (!_toolTipContainer) {\r
966         _toolTipContainer = FX_NEW CFWL_ToolTipContainer;\r
967     }\r
968     return _toolTipContainer;\r
969 }\r
970 FX_ERR CFWL_ToolTipContainer::AddToolTipTarget(IFWL_ToolTipTarget *pTarget)\r
971 {\r
972     if (m_arrWidget.Find((void *)pTarget) < 0) {\r
973         m_arrWidget.Add((void *)pTarget);\r
974         return FWL_ERR_Succeeded;\r
975     }\r
976     return FWL_ERR_Indefinite;\r
977 }\r
978 FX_ERR CFWL_ToolTipContainer::RemoveToolTipTarget(IFWL_ToolTipTarget *pTarget)\r
979 {\r
980     int index = m_arrWidget.Find((void *)pTarget);\r
981     if (index >= 0) {\r
982         m_arrWidget.RemoveAt(index);\r
983         return FWL_ERR_Succeeded;\r
984     }\r
985     return FWL_ERR_Indefinite;\r
986 }\r
987 FX_BOOL CFWL_ToolTipContainer::HasToolTip(IFWL_Widget *pWedget)\r
988 {\r
989     FX_INT32 iCount = m_arrWidget.GetSize();\r
990     for (FX_INT32 i = 0; i < iCount; i++) {\r
991         IFWL_ToolTipTarget *p = (IFWL_ToolTipTarget *)m_arrWidget[i];\r
992         if (p->GetWidget() == pWedget) {\r
993             pCurTarget = p;\r
994             return TRUE;\r
995         }\r
996     }\r
997     return FALSE;\r
998 }\r
999 FX_BOOL CFWL_ToolTipContainer::ProcessEnter(CFWL_EvtMouse *pEvt, IFWL_Widget *pOwner)\r
1000 {\r
1001     if (HasToolTip(pEvt->m_pDstTarget)) {\r
1002         if (NULL == m_pToolTipImp) {\r
1003             CFWL_WidgetImpProperties prop;\r
1004             prop.m_pDataProvider = m_ToolTipDp;\r
1005             prop.m_pOwner = pOwner;\r
1006             CFX_RectF rtTooltip;\r
1007             rtTooltip.Set(150, 150, 100, 50);\r
1008             prop.m_rtWidget = rtTooltip;\r
1009             m_pToolTipImp = FX_NEW CFWL_ToolTipImp(prop);\r
1010             IFWL_ToolTip *pToolTip = IFWL_ToolTip::Create();\r
1011             m_pToolTipImp->SetInterface(pToolTip);\r
1012             ((IFWL_TargetData*)pToolTip)->SetData(m_pToolTipImp);\r
1013             m_pToolTipImp->Initialize();\r
1014             m_pToolTipImp->ModifyStylesEx( FWL_STYLEEXT_TTP_Multiline, 0);\r
1015             m_pToolTipImp->SetStates( FWL_WGTSTATE_Invisible, TRUE);\r
1016         }\r
1017         if (pCurTarget->IsShowed()) {\r
1018             CFX_WideString wsCaption;\r
1019             pCurTarget->GetCaption(wsCaption);\r
1020             if (!wsCaption.IsEmpty()) {\r
1021                 m_ToolTipDp->m_wsCaption = wsCaption;\r
1022             }\r
1023             CFX_RectF rt;\r
1024             rt.Reset();\r
1025             CFX_SizeF sz;\r
1026             sz.Reset();\r
1027             pCurTarget->GetToolTipSize(sz);\r
1028             if (sz.x > 0 && sz.y > 0) {\r
1029                 rt.width = sz.x;\r
1030                 rt.height = sz.y;\r
1031             } else {\r
1032                 CFX_RectF r;\r
1033                 m_pToolTipImp->GetWidgetRect(r, TRUE);\r
1034                 rt.width = r.width;\r
1035                 rt.height = r.height;\r
1036             }\r
1037             CFX_PointF pt;\r
1038             pt.Set(pEvt->m_fx, pEvt->m_fy);\r
1039             if (pCurTarget->GetToolTipPos(pt) == FWL_ERR_Succeeded) {\r
1040                 rt.left = pt.x;\r
1041                 rt.top = pt.y;\r
1042                 m_pToolTipImp->ModifyStylesEx(FWL_STYLEEXT_TTP_NoAnchor, 0);\r
1043             } else {\r
1044                 CFX_RectF rtAnchor;\r
1045                 pCurTarget->GetWidget()->GetClientRect(rtAnchor);\r
1046                 pCurTarget->GetWidget()->TransformTo(NULL, rtAnchor.left, rtAnchor.top);\r
1047                 m_pToolTipImp->SetAnchor(rtAnchor);\r
1048                 m_pToolTipImp->ModifyStylesEx(0, FWL_STYLEEXT_TTP_NoAnchor);\r
1049             }\r
1050             m_pToolTipImp->SetWidgetRect(rt);\r
1051             m_pToolTipImp->Update();\r
1052             m_pToolTipImp->Show();\r
1053         }\r
1054         return TRUE;\r
1055     }\r
1056     return FALSE;\r
1057 }\r
1058 FX_BOOL CFWL_ToolTipContainer::ProcessLeave(CFWL_EvtMouse *pEvt)\r
1059 {\r
1060     if (HasToolTip(pEvt->m_pDstTarget) && NULL != m_pToolTipImp) {\r
1061         m_pToolTipImp->Hide();\r
1062         pCurTarget = NULL;\r
1063         return TRUE;\r
1064     }\r
1065     return FALSE;\r
1066 }\r
1067 IFWL_ToolTipTarget* CFWL_ToolTipContainer::GetCurrentToolTipTarget()\r
1068 {\r
1069     return pCurTarget;\r
1070 }\r
1071 FX_ERR CFWL_ToolTipContainer::SetToolTipInitialDelay(FX_INT32 nDelayTime)\r
1072 {\r
1073     m_ToolTipDp->m_nInitDelayTime = nDelayTime;\r
1074     return FWL_ERR_Succeeded;\r
1075 }\r
1076 FX_ERR CFWL_ToolTipContainer::SetToolTipAutoPopDelay(FX_INT32 nDelayTime)\r
1077 {\r
1078     m_ToolTipDp->m_nAutoPopDelayTime = nDelayTime;\r
1079     return FWL_ERR_Succeeded;\r
1080 }\r
1081 FWL_ERR FWL_AddToolTipTarget(IFWL_ToolTipTarget *pTarget)\r
1082 {\r
1083     return      CFWL_ToolTipContainer::getInstance()->AddToolTipTarget(pTarget);\r
1084 }\r
1085 FWL_ERR FWL_RemoveToolTipTarget(IFWL_ToolTipTarget *pTarget)\r
1086 {\r
1087     return CFWL_ToolTipContainer::getInstance()->RemoveToolTipTarget(pTarget);\r
1088 }\r
1089 FWL_ERR FWL_SetToolTipInitialDelay(FX_INT32 nDelayTime)\r
1090 {\r
1091     return CFWL_ToolTipContainer::getInstance()->SetToolTipInitialDelay(nDelayTime);\r
1092 }\r
1093 FWL_ERR FWL_SetToolTipAutoPopDelay(FX_INT32 nDelayTime)\r
1094 {\r
1095     return CFWL_ToolTipContainer::getInstance()->SetToolTipAutoPopDelay(nDelayTime);\r
1096 }\r
1097 IFWL_Widget* FWL_GetCurrentThreadModalWidget(IFWL_NoteThread *pNoteThread)\r
1098 {\r
1099     _FWL_RETURN_VALUE_IF_FAIL(pNoteThread, NULL);\r
1100     CFWL_NoteDriver *noteDriver = (CFWL_NoteDriver*)pNoteThread->GetNoteDriver();\r
1101     _FWL_RETURN_VALUE_IF_FAIL(noteDriver, NULL);\r
1102     if (noteDriver->CountLoop() == 1) {\r
1103         return NULL;\r
1104     }\r
1105     CFWL_NoteLoop *topLoop = noteDriver->GetTopLoop();\r
1106     _FWL_RETURN_VALUE_IF_FAIL(topLoop, NULL);\r
1107     CFWL_WidgetImp *widget = topLoop->GetForm();\r
1108     _FWL_RETURN_VALUE_IF_FAIL(widget, NULL);\r
1109     return widget->GetInterface();\r
1110 }\r
1111 FWL_ERR FWL_SetHook(IFWL_NoteDriver *driver, FWLMessageHookCallback callback, FX_LPVOID info)\r
1112 {\r
1113     CFWL_NoteDriver *noteDriver = (CFWL_NoteDriver*)driver;\r
1114     noteDriver->SetHook(callback, info);\r
1115     return FWL_ERR_Succeeded;\r
1116 }\r