bc3348736bdc2996dcf4694b5a830d293dced8f5
[pdfium.git] / fpdfsdk / src / pdfwindow / PWL_Wnd.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4  
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../include/pdfwindow/PDFWindow.h"
8 #include "../../include/pdfwindow/PWL_Wnd.h"
9 #include "../../include/pdfwindow/PWL_Utils.h"
10 #include "../../include/pdfwindow/PWL_ScrollBar.h"
11
12 /* -------------------------- CPWL_Timer -------------------------- */
13
14 static CFX_MapPtrTemplate<FX_INT32, CPWL_Timer*>        g_TimeMap;
15
16 CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached, IFX_SystemHandler* pSystemHandler) : 
17         m_nTimerID(0),
18         m_pAttached(pAttached),
19         m_pSystemHandler(pSystemHandler)
20 {
21         ASSERT(m_pAttached != NULL);
22         ASSERT(m_pSystemHandler != NULL);
23 }
24
25 CPWL_Timer::~CPWL_Timer()
26 {
27         KillPWLTimer();
28 }
29
30 FX_INT32 CPWL_Timer::SetPWLTimer(FX_INT32 nElapse)
31 {       
32         if (m_nTimerID != 0) KillPWLTimer();
33         m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
34         g_TimeMap.SetAt(m_nTimerID, this);
35         return m_nTimerID;
36 }
37
38 void CPWL_Timer::KillPWLTimer()
39 {
40         if (m_nTimerID != 0)
41         {
42                 m_pSystemHandler->KillTimer(m_nTimerID);
43                 g_TimeMap.RemoveKey(m_nTimerID);
44                 m_nTimerID = 0;
45         }
46 }
47
48 void CPWL_Timer::TimerProc(FX_INT32 idEvent)
49 {
50         CPWL_Timer* pTimer = NULL;
51         if (g_TimeMap.Lookup(idEvent, pTimer))
52         {
53                 if (pTimer)
54                 {                       
55                         if (pTimer->m_pAttached) 
56                                 pTimer->m_pAttached->TimerProc();
57                 }
58         }
59 }
60
61 /* -------------------------- CPWL_TimerHandler -------------------------- */
62
63 CPWL_TimerHandler::CPWL_TimerHandler() : m_pTimer(NULL)
64 {
65 }
66
67 CPWL_TimerHandler::~CPWL_TimerHandler()
68 {
69         if (m_pTimer) delete m_pTimer;
70 }
71
72 void CPWL_TimerHandler::BeginTimer(FX_INT32 nElapse)
73 {
74         if (!m_pTimer)
75                 m_pTimer = new CPWL_Timer(this, GetSystemHandler());
76
77         if (m_pTimer)
78                 m_pTimer->SetPWLTimer(nElapse);
79 }
80
81 void CPWL_TimerHandler::EndTimer()
82 {
83         if (m_pTimer)
84                 m_pTimer->KillPWLTimer();
85 }
86
87 void CPWL_TimerHandler::TimerProc()
88 {
89 }
90
91 /* --------------------------- CPWL_MsgControl ---------------------------- */
92
93 class CPWL_MsgControl
94 {
95         friend class CPWL_Wnd;
96
97 public:
98         CPWL_MsgControl(CPWL_Wnd * pWnd)
99         {
100 //              PWL_TRACE("new CPWL_MsgControl\n");
101                 m_pCreatedWnd = pWnd;
102                 Default();
103         }
104
105         ~CPWL_MsgControl()
106         {
107 //              PWL_TRACE("~CPWL_MsgControl\n");
108                 Default();
109         }
110
111         void Default()
112         {
113                 m_aMousePath.RemoveAll();
114                 m_aKeyboardPath.RemoveAll();
115                 m_pMainMouseWnd = NULL;
116                 m_pMainKeyboardWnd = NULL;
117         }
118
119         FX_BOOL IsWndCreated(const CPWL_Wnd * pWnd) const
120         {
121                 return m_pCreatedWnd == pWnd;
122         }
123
124         FX_BOOL IsMainCaptureMouse(const CPWL_Wnd * pWnd) const
125         {
126                 return pWnd == m_pMainMouseWnd;
127         }
128
129         FX_BOOL IsWndCaptureMouse(const CPWL_Wnd * pWnd) const
130         {
131                 if (pWnd)
132                         for( FX_INT32 i=0,sz=m_aMousePath.GetSize(); i<sz; i++)
133                                 if (m_aMousePath.GetAt(i) == pWnd)
134                                         return TRUE;
135
136                 return FALSE;
137         }
138
139         FX_BOOL IsMainCaptureKeyboard(const CPWL_Wnd * pWnd) const
140         {
141                 return pWnd == m_pMainKeyboardWnd;
142         }
143
144
145         FX_BOOL IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const
146         {
147                 if (pWnd)
148                         for( FX_INT32 i=0,sz=m_aKeyboardPath.GetSize(); i<sz; i++)
149                                 if (m_aKeyboardPath.GetAt(i) == pWnd)
150                                         return TRUE;
151                 
152                 return FALSE;
153         }
154
155         void SetFocus(CPWL_Wnd * pWnd)
156         {
157                 m_aKeyboardPath.RemoveAll();
158
159                 if (pWnd)
160                 {
161                         m_pMainKeyboardWnd = pWnd;
162
163                         CPWL_Wnd * pParent = pWnd;
164                         while (pParent)
165                         {
166                                 m_aKeyboardPath.Add(pParent);
167                                 pParent = pParent->GetParentWindow();
168                         }
169
170                         pWnd->OnSetFocus();
171                 }
172         }
173
174         void KillFocus()
175         {
176                 if (m_aKeyboardPath.GetSize() > 0)
177                         if (CPWL_Wnd* pWnd = m_aKeyboardPath.GetAt(0))
178                                 pWnd->OnKillFocus();
179
180                 m_pMainKeyboardWnd = NULL;
181                 m_aKeyboardPath.RemoveAll();
182         }
183
184         void SetCapture(CPWL_Wnd * pWnd)
185         {
186                 m_aMousePath.RemoveAll();
187
188                 if (pWnd)
189                 {
190                         m_pMainMouseWnd = pWnd;
191
192                         CPWL_Wnd * pParent = pWnd;
193                         while (pParent)
194                         {
195                                 m_aMousePath.Add(pParent);
196                                 pParent = pParent->GetParentWindow();
197                         }
198                 }
199         }
200
201         void ReleaseCapture()
202         {
203                 m_pMainMouseWnd = NULL;
204                 m_aMousePath.RemoveAll();
205         }
206
207 private:
208         CFX_ArrayTemplate<CPWL_Wnd*>    m_aMousePath;
209         CFX_ArrayTemplate<CPWL_Wnd*>    m_aKeyboardPath;
210         CPWL_Wnd*                                               m_pCreatedWnd;
211         CPWL_Wnd*                                               m_pMainMouseWnd;
212         CPWL_Wnd*                                               m_pMainKeyboardWnd;
213 };
214
215 /* --------------------------- CPWL_Wnd ---------------------------- */
216
217 CPWL_Wnd::CPWL_Wnd() :
218         m_pVScrollBar(NULL),
219         m_rcWindow(),
220         m_rcClip(),
221         m_bCreated(FALSE),                      
222         m_bVisible(FALSE),
223         m_bNotifying(FALSE),
224         m_bEnabled(TRUE)
225 {
226 }
227
228 CPWL_Wnd::~CPWL_Wnd()
229 {
230         ASSERT(m_bCreated == FALSE);
231 }
232
233 CFX_ByteString CPWL_Wnd::GetClassName() const
234 {
235         return "CPWL_Wnd";
236 }
237
238 void CPWL_Wnd::Create(const PWL_CREATEPARAM & cp)
239 {
240         if (!IsValid())
241         {
242                 m_sPrivateParam = cp;
243
244                 OnCreate(m_sPrivateParam);
245
246                 m_sPrivateParam.rcRectWnd.Normalize();
247                 m_rcWindow = m_sPrivateParam.rcRectWnd;
248                 m_rcClip = CPWL_Utils::InflateRect(m_rcWindow,1.0f);
249
250                 CreateMsgControl();
251
252                 if (m_sPrivateParam.pParentWnd)
253                         m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);
254
255                 PWL_CREATEPARAM ccp = m_sPrivateParam;
256
257                 ccp.dwFlags &= 0xFFFF0000L; //remove sub styles
258                 ccp.mtChild = CPDF_Matrix(1,0,0,1,0,0);
259                 
260                 CreateScrollBar(ccp);
261                 CreateChildWnd(ccp); 
262
263                 m_bVisible = HasFlag(PWS_VISIBLE);
264
265                 OnCreated();
266
267                 RePosChildWnd();
268                 m_bCreated = TRUE;
269         }
270 }
271
272 void CPWL_Wnd::OnCreate(PWL_CREATEPARAM & cp)
273 {
274 }
275
276 void CPWL_Wnd::OnCreated()
277 {
278 }
279
280 void CPWL_Wnd::OnDestroy()
281 {
282 }
283
284 void CPWL_Wnd::Destroy()
285 {
286         KillFocus();
287
288         OnDestroy();
289
290         if (m_bCreated)
291         {
292                 for (FX_INT32 i = m_aChildren.GetSize()-1; i >= 0; i --)
293                 {
294                         if (CPWL_Wnd * pChild = m_aChildren[i])
295                         {
296                                 pChild->Destroy();
297                                 delete pChild;
298                                 pChild = NULL;
299                         }
300                 }
301
302                 if (m_sPrivateParam.pParentWnd)
303                         m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
304                 m_bCreated = FALSE;
305         }
306
307         DestroyMsgControl();
308
309         FXSYS_memset(&m_sPrivateParam, 0, sizeof(PWL_CREATEPARAM));
310         m_aChildren.RemoveAll();        
311         m_pVScrollBar = NULL;
312 }
313
314 void CPWL_Wnd::Move(const CPDF_Rect & rcNew, FX_BOOL bReset,FX_BOOL bRefresh)
315 {
316         if (IsValid())
317         {
318                 CPDF_Rect rcOld = this->GetWindowRect();
319
320                 m_rcWindow = rcNew;
321                 m_rcWindow.Normalize();
322                 //m_rcClip = CPWL_Utils::InflateRect(m_rcWindow,1.0f); //for special caret 
323
324                 if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
325                         rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom)
326                 {
327                         if (bReset)
328                         {
329                                 RePosChildWnd();        
330                         }       
331
332                 }
333                 if (bRefresh)
334                 {       
335                         InvalidateRectMove(rcOld,rcNew);
336                 }
337
338                 m_sPrivateParam.rcRectWnd = m_rcWindow;
339         }
340 }
341
342 void  CPWL_Wnd::InvalidateRectMove(const CPDF_Rect & rcOld, const CPDF_Rect & rcNew)
343 {
344         CPDF_Rect rcUnion = rcOld;
345         rcUnion.Union(rcNew);
346
347         InvalidateRect(&rcUnion);
348
349         /*
350         CPDF_Rect SubArray[4]; 
351
352         rcOld.Substract4(rcNew,SubArray);
353         for (FX_INT32 i=0;i<4;i++)
354         {
355                 if (SubArray[i].left == 0 &&
356                         SubArray[i].right == 0 &&
357                         SubArray[i].top == 0 &&
358                         SubArray[i].bottom == 0)continue;
359
360                 InvalidateRect(&CPWL_Utils::InflateRect(SubArray[i],2));
361         }
362
363         rcNew.Substract4(rcOld,SubArray);
364         for (FX_INT32 j=0;j<4;j++)
365         {
366                 if (SubArray[j].left == 0 &&
367                         SubArray[j].right == 0 &&
368                         SubArray[j].top == 0 &&
369                         SubArray[j].bottom == 0)continue;
370
371                 InvalidateRect(&CPWL_Utils::InflateRect(SubArray[j],2));
372         }
373         */
374 }
375
376 void CPWL_Wnd::GetAppearanceStream(CFX_ByteString & sAppStream)
377 {
378         if (IsValid())
379         {
380                 CFX_ByteTextBuf sTextBuf;
381                 GetAppearanceStream(sTextBuf);
382                 sAppStream += sTextBuf.GetByteString();
383         }
384 }
385
386 void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf & sAppStream)
387 {
388         if (IsValid() && IsVisible())
389         {
390                 GetThisAppearanceStream(sAppStream);
391                 GetChildAppearanceStream(sAppStream);
392         }
393 }
394
395 //if don't set,Get default apperance stream
396 void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
397 {
398         CPDF_Rect rectWnd = GetWindowRect();
399         if (!rectWnd.IsEmpty())
400         {
401                 CFX_ByteTextBuf sThis;
402
403                 if (HasFlag(PWS_BACKGROUND))
404                         sThis << CPWL_Utils::GetRectFillAppStream(rectWnd,this->GetBackgroundColor());
405
406                 if (HasFlag(PWS_BORDER))
407                         sThis << CPWL_Utils::GetBorderAppStream(rectWnd,
408                                                                         (FX_FLOAT)GetBorderWidth(),
409                                                                         GetBorderColor(),
410                                                                         this->GetBorderLeftTopColor(this->GetBorderStyle()),
411                                                                         this->GetBorderRightBottomColor(this->GetBorderStyle()),
412                                                                         this->GetBorderStyle(),
413                                                                         this->GetBorderDash());
414
415                 sAppStream << sThis;
416         }
417 }
418
419 void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf & sAppStream)
420 {
421         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
422         {
423                 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
424                 {
425                         pChild->GetAppearanceStream(sAppStream);
426                 }
427         }
428 }
429
430 void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
431 {
432         if (IsValid() && IsVisible())
433         {
434                 DrawThisAppearance(pDevice,pUser2Device);
435                 DrawChildAppearance(pDevice,pUser2Device);
436         }
437 }
438
439 void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
440 {
441         CPDF_Rect rectWnd = GetWindowRect();
442         if (!rectWnd.IsEmpty())
443         {               
444                 if (HasFlag(PWS_BACKGROUND))
445                 {
446                         CPDF_Rect rcClient = CPWL_Utils::DeflateRect(rectWnd,(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));
447                         CPWL_Utils::DrawFillRect(pDevice,pUser2Device,rcClient,this->GetBackgroundColor(),GetTransparency());
448                 }
449
450                 if (HasFlag(PWS_BORDER))
451                         CPWL_Utils::DrawBorder(pDevice,
452                                                                 pUser2Device,
453                                                                 rectWnd,
454                                                                 (FX_FLOAT)GetBorderWidth(),
455                                                                 GetBorderColor(),
456                                                                 this->GetBorderLeftTopColor(this->GetBorderStyle()),
457                                                                 this->GetBorderRightBottomColor(this->GetBorderStyle()),
458                                                                 this->GetBorderStyle(),
459                                                                 this->GetBorderDash(),
460                                                                 GetTransparency());                                                             
461         }
462 }
463
464 void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
465 {
466         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
467         {
468                 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
469                 {
470                         CPDF_Matrix mt = pChild->GetChildMatrix();
471                         if (mt.IsIdentity())
472                         {
473                                 pChild->DrawAppearance(pDevice,pUser2Device);
474                         }
475                         else
476                         {
477                                 mt.Concat(*pUser2Device);
478                                 pChild->DrawAppearance(pDevice,&mt);
479                         }
480                 }
481         }
482 }
483
484 void CPWL_Wnd::InvalidateRect(CPDF_Rect* pRect)
485 {
486         if (IsValid())
487         {
488                 CPDF_Rect rcRefresh = pRect ? *pRect : GetWindowRect();
489
490                 if (!HasFlag(PWS_NOREFRESHCLIP))
491                 {
492                         CPDF_Rect rcClip = GetClipRect();               
493                         if (!rcClip.IsEmpty())
494                         {
495                                 rcRefresh.Intersect(rcClip);
496                         }
497                 }
498
499                 FX_RECT rcWin = PWLtoWnd(rcRefresh);
500                 rcWin.left -= PWL_INVALIDATE_INFLATE;
501                 rcWin.top -= PWL_INVALIDATE_INFLATE;
502                 rcWin.right += PWL_INVALIDATE_INFLATE;
503                 rcWin.bottom += PWL_INVALIDATE_INFLATE;
504
505                 if (IFX_SystemHandler* pSH = GetSystemHandler())
506                 {
507                         if (FX_HWND hWnd = GetAttachedHWnd())
508                         {
509                                 pSH->InvalidateRect(hWnd, rcWin);
510                         }
511                 }
512         }
513 }
514
515 #define PWL_IMPLEMENT_KEY_METHOD(key_method_name)\
516 FX_BOOL CPWL_Wnd::key_method_name(FX_WORD nChar, FX_DWORD nFlag)\
517 {\
518         if (IsValid() && IsVisible() && IsEnabled())\
519         {\
520                 if (IsWndCaptureKeyboard(this))\
521                 {\
522                         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)\
523                         {\
524                                 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))\
525                                 {\
526                                         if (IsWndCaptureKeyboard(pChild))\
527                                         {\
528                                                 return pChild->key_method_name(nChar,nFlag);\
529                                         }\
530                                 }\
531                         }\
532                 }\
533         }\
534         return FALSE;\
535 }
536
537 #define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name)\
538 FX_BOOL CPWL_Wnd::mouse_method_name(const CPDF_Point & point, FX_DWORD nFlag)\
539 {\
540         if (IsValid() && IsVisible() && IsEnabled())\
541         {\
542                 if (IsWndCaptureMouse(this))\
543                 {\
544                         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)\
545                         {\
546                                 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))\
547                                 {\
548                                         if (IsWndCaptureMouse(pChild))\
549                                         {\
550                                                 return pChild->mouse_method_name(pChild->ParentToChild(point),nFlag);\
551                                         }\
552                                 }\
553                         }\
554                         SetCursor();\
555                 }\
556                 else\
557                 {\
558                         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)\
559                         {\
560                                 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))\
561                                 {\
562                                         if (pChild->WndHitTest(pChild->ParentToChild(point)))\
563                                         {\
564                                                 return pChild->mouse_method_name(pChild->ParentToChild(point),nFlag);\
565                                         }\
566                                 }\
567                         }\
568                         if (this->WndHitTest(point))\
569                                 SetCursor();\
570                 }\
571         }\
572         return FALSE;\
573 }
574
575 PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
576 PWL_IMPLEMENT_KEY_METHOD(OnKeyUp)
577 PWL_IMPLEMENT_KEY_METHOD(OnChar)
578
579 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
580 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
581 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
582 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDblClk)
583 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDown)
584 PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonUp)
585 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDblClk)
586 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
587 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
588 PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)
589
590 FX_BOOL CPWL_Wnd::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)
591 {
592         if (IsValid() && IsVisible() && IsEnabled())
593         {
594                 SetCursor();
595                 if (IsWndCaptureKeyboard(this))
596                 {
597                         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
598                         {
599                                 if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
600                                 {
601                                         if (IsWndCaptureKeyboard(pChild))
602                                         {
603                                                 return pChild->OnMouseWheel(zDelta,pChild->ParentToChild(point), nFlag);
604                                         }
605                                 }
606                         }
607                 }
608         }
609         return FALSE;
610 }
611
612 void CPWL_Wnd::AddChild(CPWL_Wnd * pWnd)
613 {
614         m_aChildren.Add(pWnd);
615 }
616
617 void CPWL_Wnd::RemoveChild(CPWL_Wnd * pWnd)
618 {
619         for (FX_INT32 i = m_aChildren.GetSize()-1; i >= 0; i --)
620         {
621                 if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
622                 {
623                         if (pChild == pWnd)
624                         {
625                                 m_aChildren.RemoveAt(i);
626                                 break;
627                         }
628                 }
629         }
630 }
631
632 void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam)
633 {
634         switch (msg)
635         {
636         case PNM_ADDCHILD:
637                 this->AddChild(pWnd);
638                 break;
639         case PNM_REMOVECHILD:
640                 this->RemoveChild(pWnd);
641                 break;
642         default:
643                 break;
644         }
645 }
646
647 FX_BOOL CPWL_Wnd::IsValid() const
648 {
649         return m_bCreated;
650 }
651
652 PWL_CREATEPARAM CPWL_Wnd::GetCreationParam() const
653 {
654         return m_sPrivateParam;
655 }
656
657 CPWL_Wnd* CPWL_Wnd::GetParentWindow() const
658 {
659         return m_sPrivateParam.pParentWnd;
660 }
661
662 CPDF_Rect CPWL_Wnd::GetOriginWindowRect() const
663 {
664         return m_sPrivateParam.rcRectWnd;
665 }
666
667 CPDF_Rect CPWL_Wnd::GetWindowRect() const
668 {
669         return m_rcWindow;
670 }
671
672 CPDF_Rect CPWL_Wnd::GetClientRect() const
673 {
674         CPDF_Rect rcWindow = GetWindowRect();
675         CPDF_Rect rcClient = CPWL_Utils::DeflateRect(rcWindow,(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));
676
677         if (CPWL_ScrollBar * pVSB = this->GetVScrollBar())
678                 rcClient.right -= pVSB->GetScrollBarWidth();
679
680         rcClient.Normalize();
681
682         if (rcWindow.Contains(rcClient))
683                 return rcClient;
684         else
685                 return CPDF_Rect();
686 }
687
688 CPDF_Point CPWL_Wnd::GetCenterPoint() const
689 {
690         CPDF_Rect rcClient = GetClientRect();
691
692         return CPDF_Point((rcClient.left + rcClient.right) * 0.5f,
693                 (rcClient.top + rcClient.bottom) * 0.5f);
694 }
695
696 CPDF_Rect CPWL_Wnd::GetClientCenterSquare() const
697 {
698         return CPWL_Utils::GetCenterSquare(GetClientRect());
699 }
700
701 CPDF_Rect CPWL_Wnd::GetWindowCenterSquare() const
702 {
703         return CPWL_Utils::GetCenterSquare(CPWL_Utils::DeflateRect(GetWindowRect(),0.1f));
704 }
705
706 FX_BOOL CPWL_Wnd::HasFlag(FX_DWORD dwFlags) const
707 {
708         return (m_sPrivateParam.dwFlags & dwFlags) != 0;
709 }
710
711 void CPWL_Wnd::RemoveFlag(FX_DWORD dwFlags)
712 {
713         m_sPrivateParam.dwFlags &= ~dwFlags;
714 }
715
716 void CPWL_Wnd::AddFlag(FX_DWORD dwFlags)
717 {
718         m_sPrivateParam.dwFlags |= dwFlags;
719 }
720
721 CPWL_Color CPWL_Wnd::GetBackgroundColor() const
722 {
723         return m_sPrivateParam.sBackgroundColor;
724 }
725
726 void CPWL_Wnd::SetBackgroundColor(const CPWL_Color & color)
727 {
728         m_sPrivateParam.sBackgroundColor = color;
729 }
730
731 void CPWL_Wnd::SetTextColor(const CPWL_Color & color)
732 {
733         m_sPrivateParam.sTextColor = color;
734 }
735
736 void CPWL_Wnd::SetTextStrokeColor(const CPWL_Color & color)
737 {
738         m_sPrivateParam.sTextStrokeColor = color;
739 }
740
741 CPWL_Color CPWL_Wnd::GetTextColor() const
742 {
743         return m_sPrivateParam.sTextColor;
744 }
745
746 CPWL_Color CPWL_Wnd::GetTextStrokeColor() const
747 {
748         return m_sPrivateParam.sTextStrokeColor;
749 }
750
751 FX_INT32 CPWL_Wnd::GetBorderStyle() const
752 {
753         return m_sPrivateParam.nBorderStyle;
754 }
755
756 void CPWL_Wnd::SetBorderStyle(FX_INT32 nBorderStyle)
757 {
758         if (HasFlag(PWS_BORDER))
759                 m_sPrivateParam.nBorderStyle = nBorderStyle;
760 }
761
762 FX_INT32 CPWL_Wnd::GetBorderWidth() const
763 {
764         if (HasFlag(PWS_BORDER))
765                 return m_sPrivateParam.dwBorderWidth;
766
767         return 0;
768 }
769
770 FX_INT32 CPWL_Wnd::GetInnerBorderWidth() const
771 {
772         /*
773         switch (GetBorderStyle())
774         {
775         case PBS_BEVELED:
776         case PBS_INSET:
777                 return GetBorderWidth() / 2;
778         }
779         */
780         return 0;
781 }
782
783 void CPWL_Wnd::SetBorderWidth(FX_INT32 nBorderWidth)
784 {
785         if (HasFlag(PWS_BORDER))
786                 m_sPrivateParam.dwBorderWidth = nBorderWidth;
787 }
788
789 CPWL_Color CPWL_Wnd::GetBorderColor() const
790 {
791         if (HasFlag(PWS_BORDER))
792                 return m_sPrivateParam.sBorderColor;
793
794         return CPWL_Color();
795 }
796
797 void CPWL_Wnd::SetBorderColor(const CPWL_Color & color)
798 {
799         if (HasFlag(PWS_BORDER))
800                 m_sPrivateParam.sBorderColor = color;
801 }
802
803 CPWL_Dash CPWL_Wnd::GetBorderDash() const
804 {
805         return m_sPrivateParam.sDash;
806 }
807
808 void* CPWL_Wnd::GetAttachedData() const
809 {
810         return m_sPrivateParam.pAttachedData;
811 }
812
813 void CPWL_Wnd::SetBorderDash(const CPWL_Dash & sDash)
814 {
815         if (HasFlag(PWS_BORDER))
816                 m_sPrivateParam.sDash = sDash;
817 }
818
819 CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const
820 {
821         if (HasFlag(PWS_VSCROLL))
822                 return m_pVScrollBar;
823
824         return NULL;
825 }
826
827 void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM & cp)
828 {
829         CreateVScrollBar(cp);
830 }
831
832 void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM & cp)
833 {
834         if (!m_pVScrollBar && HasFlag(PWS_VSCROLL))
835         {
836                 PWL_CREATEPARAM scp = cp;
837
838                 //flags
839                 scp.dwFlags = PWS_CHILD| PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;
840                 
841                 scp.pParentWnd = this;
842                 scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
843                 scp.eCursorType = FXCT_ARROW;
844                 scp.nTransparency = PWL_SCROLLBAR_TRANSPARANCY;
845
846                 if ((m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL)))
847                         m_pVScrollBar->Create(scp);
848         }
849 }
850
851 void CPWL_Wnd::SetCapture()
852 {
853         if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
854                 pMsgCtrl->SetCapture(this);
855 }
856
857 void CPWL_Wnd::ReleaseCapture()
858 {
859         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
860                 if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
861                         pChild->ReleaseCapture();
862
863         if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
864                 pMsgCtrl->ReleaseCapture();
865 }
866
867 void CPWL_Wnd::SetFocus()
868 {
869         if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
870         {
871                 if (!pMsgCtrl->IsMainCaptureKeyboard(this))
872                         pMsgCtrl->KillFocus();
873                 pMsgCtrl->SetFocus(this);
874         }
875 }
876
877 void CPWL_Wnd::KillFocus()
878 {
879         if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
880         {
881                 if (pMsgCtrl->IsWndCaptureKeyboard(this))
882                         pMsgCtrl->KillFocus();
883         }
884 }
885
886 void CPWL_Wnd::OnSetFocus()
887 {
888 }
889
890 void CPWL_Wnd::OnKillFocus()
891 {
892 }
893
894 FX_BOOL CPWL_Wnd::WndHitTest(const CPDF_Point & point) const
895 {
896         return IsValid() && IsVisible() && GetWindowRect().Contains(point.x,point.y);
897 }
898
899 FX_BOOL CPWL_Wnd::ClientHitTest(const CPDF_Point & point) const
900 {
901         return IsValid() && IsVisible() && GetClientRect().Contains(point.x,point.y);
902 }
903
904 const CPWL_Wnd * CPWL_Wnd::GetRootWnd() const
905 {
906         if (m_sPrivateParam.pParentWnd)
907                 return m_sPrivateParam.pParentWnd->GetRootWnd();
908         else
909                 return this;
910 }
911
912 void CPWL_Wnd::SetVisible(FX_BOOL bVisible)
913 {
914         if (IsValid())
915         {
916                 for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
917                 {
918                         if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
919                         {
920                                 pChild->SetVisible(bVisible);
921                         }
922                 }
923
924                 if (bVisible != m_bVisible)
925                 {
926                         m_bVisible = bVisible;
927                         RePosChildWnd();                
928                         InvalidateRect();
929                 }       
930         }
931 }
932
933 void CPWL_Wnd::SetClipRect(const CPDF_Rect & rect)
934 {
935         m_rcClip = rect;
936         m_rcClip.Normalize();
937 }
938
939 CPDF_Rect CPWL_Wnd::GetClipRect() const
940 {
941         return m_rcClip;
942 }
943
944 FX_BOOL CPWL_Wnd::IsReadOnly() const
945 {
946         return HasFlag(PWS_READONLY);
947 }
948
949 void CPWL_Wnd::RePosChildWnd()
950 {
951         CPDF_Rect rcContent = CPWL_Utils::DeflateRect(GetWindowRect(),(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));
952
953         CPWL_ScrollBar * pVSB = this->GetVScrollBar();
954
955         CPDF_Rect rcVScroll = CPDF_Rect(rcContent.right - PWL_SCROLLBAR_WIDTH,
956                                                         rcContent.bottom,
957                                                         rcContent.right-1.0f,
958                                                         rcContent.top);
959
960         if (pVSB) pVSB->Move(rcVScroll,TRUE,FALSE);
961 }
962
963 void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM & cp)
964 {
965 }
966
967 void CPWL_Wnd::SetCursor()
968 {
969         if (IsValid()) 
970         {
971                 if (IFX_SystemHandler* pSH = GetSystemHandler())
972                 {
973                         FX_INT32 nCursorType = this->GetCreationParam().eCursorType;
974                         pSH->SetCursor(nCursorType);
975                 }
976         }
977 }
978
979 void CPWL_Wnd::CreateMsgControl()
980 {
981         if (!m_sPrivateParam.pMsgControl)
982                 m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
983 }
984
985 void CPWL_Wnd::DestroyMsgControl()
986 {
987         if (CPWL_MsgControl* pMsgControl = GetMsgControl())
988                 if (pMsgControl->IsWndCreated(this))
989                         delete pMsgControl;
990 }
991
992 CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const
993 {
994         return m_sPrivateParam.pMsgControl;
995 }
996
997 FX_BOOL CPWL_Wnd::IsCaptureMouse() const
998 {
999         return IsWndCaptureMouse(this);
1000 }
1001
1002 FX_BOOL CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd * pWnd) const
1003 {
1004         if (CPWL_MsgControl * pCtrl = GetMsgControl())
1005                 return pCtrl->IsWndCaptureMouse(pWnd);
1006
1007         return FALSE;
1008 }
1009
1010 FX_BOOL CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const
1011 {
1012         if (CPWL_MsgControl * pCtrl = GetMsgControl())
1013                 return pCtrl->IsWndCaptureKeyboard(pWnd);
1014
1015         return FALSE;
1016 }
1017
1018 FX_BOOL CPWL_Wnd::IsFocused() const
1019 {
1020         if (CPWL_MsgControl * pCtrl = GetMsgControl())
1021                 return pCtrl->IsMainCaptureKeyboard(this);
1022
1023         return FALSE;
1024 }
1025
1026 CPDF_Rect CPWL_Wnd::GetFocusRect() const
1027 {
1028         return CPWL_Utils::InflateRect(this->GetWindowRect(),1);
1029 }
1030
1031 FX_FLOAT CPWL_Wnd::GetFontSize() const
1032 {
1033         return this->m_sPrivateParam.fFontSize;
1034 }
1035
1036 void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize)
1037 {
1038         this->m_sPrivateParam.fFontSize = fFontSize;
1039 }
1040
1041 IFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const
1042 {
1043         return m_sPrivateParam.pSystemHandler;
1044 }
1045
1046 IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const
1047 {
1048         return m_sPrivateParam.pFocusHandler;
1049 }
1050
1051 IPWL_Provider* CPWL_Wnd::GetProvider() const
1052 {
1053         return m_sPrivateParam.pProvider;
1054 }
1055
1056 IFX_Edit_FontMap* CPWL_Wnd::GetFontMap() const
1057 {
1058         return m_sPrivateParam.pFontMap;
1059 }
1060
1061 CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(FX_INT32 nBorderStyle) const
1062 {
1063         CPWL_Color color;
1064
1065         switch (nBorderStyle)
1066         {
1067                 case PBS_SOLID:
1068                         break;
1069                 case PBS_DASH:
1070                         break;
1071                 case PBS_BEVELED:
1072                         color = CPWL_Color(COLORTYPE_GRAY,1);
1073                         break;
1074                 case PBS_INSET:
1075                         color = CPWL_Color(COLORTYPE_GRAY,0.5f);
1076                         break;
1077                 case PBS_UNDERLINED:
1078                         break;
1079         }
1080
1081         return color;
1082 }
1083
1084 CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(FX_INT32 nBorderStyle) const
1085 {
1086         CPWL_Color color;
1087
1088         switch (nBorderStyle)
1089         {
1090                 case PBS_SOLID:
1091                         break;
1092                 case PBS_DASH:
1093                         break;
1094                 case PBS_BEVELED:
1095                         color = CPWL_Utils::DevideColor(GetBackgroundColor(),2);
1096                         break;
1097                 case PBS_INSET:
1098                         color = CPWL_Color(COLORTYPE_GRAY,0.75f);
1099                         break;
1100                 case PBS_UNDERLINED:
1101                         break;
1102         }
1103
1104         return color;
1105 }
1106
1107 /* ----------------------------------------------------------------- */
1108
1109 FX_INT32 CPWL_Wnd::GetTransparency()
1110 {
1111         return m_sPrivateParam.nTransparency;
1112 }
1113
1114 void CPWL_Wnd::SetTransparency(FX_INT32 nTransparency)
1115 {
1116         for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
1117         {
1118                 if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
1119                 {
1120                         pChild->SetTransparency(nTransparency);
1121                 }
1122         }
1123
1124         m_sPrivateParam.nTransparency = nTransparency;
1125 }
1126
1127 CPDF_Matrix     CPWL_Wnd::GetWindowMatrix() const
1128 {
1129         CPDF_Matrix mt = this->GetChildToRoot();
1130
1131         if (IPWL_Provider* pProvider = GetProvider())
1132         {
1133                 mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
1134                 return mt;
1135         }
1136
1137 /*
1138         if (CReader_App* pApp = CPWL_Module::GetReaderApp())
1139                 if (CReader_Document* pDocument = pApp->GetCurrentDocument())
1140                         if (CReader_DocView* pDocView = pDocument->GetCurrentDocView())
1141                         {
1142                                 CPDF_Matrix mtPageView;
1143                                 pDocView->GetCurrentMatrix(mtPageView);
1144                                 mt.Concat(mtPageView);
1145                                 return mt;
1146                         }               
1147                         
1148 */
1149
1150         return mt;
1151 }
1152
1153 void CPWL_Wnd::PWLtoWnd(const CPDF_Point& point, FX_INT32& x, FX_INT32& y) const
1154 {
1155         CPDF_Matrix mt = GetWindowMatrix();
1156         CPDF_Point pt = point;
1157         mt.Transform(pt.x,pt.y);
1158         x = (FX_INT32)(pt.x+0.5);
1159         y = (FX_INT32)(pt.y+0.5);
1160 }
1161
1162 FX_RECT CPWL_Wnd::PWLtoWnd(const CPDF_Rect & rect) const
1163 {
1164         CPDF_Rect rcTemp = rect;
1165         CPDF_Matrix mt = GetWindowMatrix();
1166         mt.TransformRect(rcTemp);       
1167         return FX_RECT((FX_INT32)(rcTemp.left+0.5), (FX_INT32)(rcTemp.bottom+0.5), (FX_INT32)(rcTemp.right+0.5), (FX_INT32)(rcTemp.top+0.5));
1168 }
1169
1170 FX_HWND CPWL_Wnd::GetAttachedHWnd() const
1171 {
1172         return m_sPrivateParam.hAttachedWnd;
1173 }
1174
1175 CPDF_Point CPWL_Wnd::ChildToParent(const CPDF_Point& point) const
1176 {
1177         CPDF_Matrix mt = GetChildMatrix();
1178         if (mt.IsIdentity())
1179                 return point;
1180         else
1181         {
1182                 CPDF_Point pt = point;
1183                 mt.Transform(pt.x,pt.y);
1184                 return pt;
1185         }
1186 }
1187
1188 CPDF_Rect CPWL_Wnd::ChildToParent(const CPDF_Rect& rect) const
1189 {
1190         CPDF_Matrix mt = GetChildMatrix();
1191         if (mt.IsIdentity())
1192                 return rect;
1193         else
1194         {
1195                 CPDF_Rect rc = rect;
1196                 mt.TransformRect(rc);
1197                 return rc;
1198         }
1199 }
1200
1201 CPDF_Point CPWL_Wnd::ParentToChild(const CPDF_Point& point) const
1202 {
1203         CPDF_Matrix mt = GetChildMatrix();
1204         if (mt.IsIdentity())
1205                 return point;
1206         else
1207         {
1208                 mt.SetReverse(mt);
1209                 CPDF_Point pt = point;
1210                 mt.Transform(pt.x,pt.y);
1211                 return pt;
1212         }
1213 }
1214
1215 CPDF_Rect CPWL_Wnd::ParentToChild(const CPDF_Rect& rect) const
1216 {
1217         CPDF_Matrix mt = GetChildMatrix();
1218         if (mt.IsIdentity())
1219                 return rect;
1220         else
1221         {
1222                 mt.SetReverse(mt);
1223                 CPDF_Rect rc = rect;
1224                 mt.TransformRect(rc);
1225                 return rc;
1226         }
1227 }
1228
1229 CPDF_Matrix CPWL_Wnd::GetChildToRoot() const
1230 {
1231         CPDF_Matrix mt(1,0,0,1,0,0);
1232         
1233         if (HasFlag(PWS_CHILD))
1234         {
1235                 const CPWL_Wnd* pParent = this;
1236                 while (pParent)
1237                 {
1238                         mt.Concat(pParent->GetChildMatrix());
1239                         pParent = pParent->GetParentWindow();
1240                 }
1241         }
1242
1243         return mt;
1244 }
1245
1246 CPDF_Matrix CPWL_Wnd::GetChildMatrix() const
1247 {
1248         if (HasFlag(PWS_CHILD))
1249                 return m_sPrivateParam.mtChild;
1250
1251         return CPDF_Matrix(1,0,0,1,0,0);
1252 }
1253
1254 void CPWL_Wnd::SetChildMatrix(const CPDF_Matrix& mt)
1255 {
1256         m_sPrivateParam.mtChild = mt;
1257 }
1258
1259 const CPWL_Wnd* CPWL_Wnd::GetFocused() const
1260 {
1261         if (CPWL_MsgControl * pMsgCtrl = GetMsgControl())
1262         {
1263                 return pMsgCtrl->m_pMainKeyboardWnd;
1264         }
1265
1266         return NULL;
1267 }
1268
1269 void CPWL_Wnd::EnableWindow(FX_BOOL bEnable)
1270 {
1271         if (m_bEnabled != bEnable)
1272         {
1273                 for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
1274                 {
1275                         if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
1276                         {
1277                                 pChild->EnableWindow(bEnable);
1278                         }
1279                 }
1280
1281                 this->m_bEnabled = bEnable;
1282
1283                 if (bEnable)
1284                         this->OnEnabled();
1285                 else
1286                         this->OnDisabled();
1287         }
1288 }
1289
1290 FX_BOOL CPWL_Wnd::IsEnabled()
1291 {
1292         return m_bEnabled;
1293 }
1294
1295 void CPWL_Wnd::OnEnabled()
1296 {
1297 }
1298
1299 void CPWL_Wnd::OnDisabled()
1300 {
1301 }
1302
1303 FX_BOOL CPWL_Wnd::IsCTRLpressed(FX_DWORD nFlag) const
1304 {
1305         if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
1306         {
1307                 return pSystemHandler->IsCTRLKeyDown(nFlag);
1308         }
1309
1310         return FALSE;
1311 }
1312
1313 FX_BOOL CPWL_Wnd::IsSHIFTpressed(FX_DWORD nFlag) const
1314 {
1315         if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
1316         {
1317                 return pSystemHandler->IsSHIFTKeyDown(nFlag);
1318         }
1319
1320         return FALSE;
1321 }
1322
1323 FX_BOOL CPWL_Wnd::IsALTpressed(FX_DWORD nFlag) const
1324 {
1325         if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
1326         {
1327                 return pSystemHandler->IsALTKeyDown(nFlag);
1328         }
1329
1330         return FALSE;
1331 }
1332
1333 FX_BOOL CPWL_Wnd::IsINSERTpressed(FX_DWORD nFlag) const
1334 {
1335         if (IFX_SystemHandler* pSystemHandler = GetSystemHandler())
1336         {
1337                 return pSystemHandler->IsINSERTKeyDown(nFlag);
1338         }
1339
1340         return FALSE;
1341 }
1342