Use override in more classes in core/
[pdfium.git] / fpdfsdk / src / pdfwindow / PWL_Note.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_Button.h"
10 #include "../../include/pdfwindow/PWL_EditCtrl.h"
11 #include "../../include/pdfwindow/PWL_Edit.h"
12 #include "../../include/pdfwindow/PWL_ListCtrl.h"
13 #include "../../include/pdfwindow/PWL_ScrollBar.h"
14 #include "../../include/pdfwindow/PWL_Note.h"
15 #include "../../include/pdfwindow/PWL_Label.h"
16 #include "../../include/pdfwindow/PWL_Edit.h"
17 #include "../../include/pdfwindow/PWL_ScrollBar.h"
18 #include "../../include/pdfwindow/PWL_Utils.h"
19 #include "../../include/pdfwindow/PWL_Caret.h"
20
21 #define POPUP_ITEM_HEAD_BOTTOM 3.0f
22 #define POPUP_ITEM_BOTTOMWIDTH 1.0f
23 #define POPUP_ITEM_SIDEMARGIN 3.0f
24 #define POPUP_ITEM_SPACE 4.0f
25 #define POPUP_ITEM_TEXT_INDENT 2.0f
26 #define POPUP_ITEM_BORDERCOLOR \
27   CPWL_Color(COLORTYPE_RGB, 80 / 255.0f, 80 / 255.0f, 80 / 255.0f)
28
29 #define IsFloatZero(f) ((f) < 0.0001 && (f) > -0.0001)
30 #define IsFloatBigger(fa, fb) ((fa) > (fb) && !IsFloatZero((fa) - (fb)))
31 #define IsFloatSmaller(fa, fb) ((fa) < (fb) && !IsFloatZero((fa) - (fb)))
32 #define IsFloatEqual(fa, fb) IsFloatZero((fa) - (fb))
33
34 /* ------------------------------- CPWL_Note_Options
35  * ------------------------------- */
36
37 CPWL_Note_Options::CPWL_Note_Options() : m_pText(NULL) {}
38
39 CPWL_Note_Options::~CPWL_Note_Options() {}
40
41 void CPWL_Note_Options::SetTextColor(const CPWL_Color& color) {
42   CPWL_Wnd::SetTextColor(color);
43
44   if (m_pText)
45     m_pText->SetTextColor(color);
46 }
47
48 void CPWL_Note_Options::RePosChildWnd() {
49   if (IsValid()) {
50     ASSERT(m_pText != NULL);
51
52     CPDF_Rect rcClient = GetClientRect();
53
54     if (rcClient.Width() > 15.0f) {
55       rcClient.right -= 15.0f;
56       m_pText->Move(rcClient, TRUE, FALSE);
57       m_pText->SetVisible(TRUE);
58     } else {
59       m_pText->Move(CPDF_Rect(0, 0, 0, 0), TRUE, FALSE);
60       m_pText->SetVisible(FALSE);
61     }
62   }
63 }
64
65 void CPWL_Note_Options::CreateChildWnd(const PWL_CREATEPARAM& cp) {
66   m_pText = new CPWL_Label;
67   PWL_CREATEPARAM tcp = cp;
68   tcp.pParentWnd = this;
69   tcp.dwFlags = PWS_CHILD | PWS_VISIBLE;
70   m_pText->Create(tcp);
71 }
72
73 void CPWL_Note_Options::SetText(const CFX_WideString& sText) {
74   m_pText->SetText(sText.c_str());
75 }
76
77 void CPWL_Note_Options::DrawThisAppearance(CFX_RenderDevice* pDevice,
78                                            CPDF_Matrix* pUser2Device) {
79   CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
80
81   CPDF_Rect rcClient = GetClientRect();
82   rcClient.left = rcClient.right - 15.0f;
83
84   CPDF_Point ptCenter = CPDF_Point((rcClient.left + rcClient.right) * 0.5f,
85                                    (rcClient.top + rcClient.bottom) * 0.5f);
86
87   CPDF_Point pt1(ptCenter.x - 2.0f, ptCenter.y + 2.0f * 0.5f);
88   CPDF_Point pt2(ptCenter.x + 2.0f, ptCenter.y + 2.0f * 0.5f);
89   CPDF_Point pt3(ptCenter.x, ptCenter.y - 3.0f * 0.5f);
90
91   CFX_PathData path;
92
93   path.SetPointCount(4);
94   path.SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO);
95   path.SetPoint(1, pt2.x, pt2.y, FXPT_LINETO);
96   path.SetPoint(2, pt3.x, pt3.y, FXPT_LINETO);
97   path.SetPoint(3, pt1.x, pt1.y, FXPT_LINETO);
98
99   pDevice->DrawPath(
100       &path, pUser2Device, NULL,
101       CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()), 0,
102       FXFILL_ALTERNATE);
103 }
104
105 CPDF_Rect CPWL_Note_Options::GetContentRect() const {
106   ASSERT(m_pText != NULL);
107
108   CPDF_Rect rcText = m_pText->GetContentRect();
109   rcText.right += 15.0f;
110   return rcText;
111 }
112
113 /* ------------------------------- CPWL_Note_Edit ------------------------------
114  */
115
116 CPWL_Note_Edit::CPWL_Note_Edit()
117     : m_bEnableNotify(TRUE),
118       m_fOldItemHeight(0.0f),
119       m_bSizeChanged(FALSE),
120       m_fOldMin(0.0f),
121       m_fOldMax(0.0f) {}
122
123 CPWL_Note_Edit::~CPWL_Note_Edit() {}
124
125 void CPWL_Note_Edit::RePosChildWnd() {
126   m_bEnableNotify = FALSE;
127   CPWL_Edit::RePosChildWnd();
128   m_bEnableNotify = TRUE;
129
130   m_fOldItemHeight = GetContentRect().Height();
131 }
132
133 void CPWL_Note_Edit::SetText(const FX_WCHAR* csText) {
134   m_bEnableNotify = FALSE;
135   CPWL_Edit::SetText(csText);
136   m_bEnableNotify = TRUE;
137   m_fOldItemHeight = GetContentRect().Height();
138 }
139
140 void CPWL_Note_Edit::OnSetFocus() {
141   m_bEnableNotify = FALSE;
142   CPWL_Edit::OnSetFocus();
143   m_bEnableNotify = TRUE;
144
145   EnableSpellCheck(TRUE);
146 }
147
148 void CPWL_Note_Edit::OnKillFocus() {
149   EnableSpellCheck(FALSE);
150
151   if (CPWL_Wnd* pParent = GetParentWindow()) {
152     if (CPWL_Wnd* pGrand = pParent->GetParentWindow()) {
153       ASSERT(pGrand->GetClassName() == "CPWL_NoteItem");
154
155       CPWL_NoteItem* pNoteItem = (CPWL_NoteItem*)pGrand;
156
157       pNoteItem->OnContentsValidate();
158     }
159   }
160
161   CPWL_Edit::OnKillFocus();
162 }
163
164 void CPWL_Note_Edit::OnNotify(CPWL_Wnd* pWnd,
165                               FX_DWORD msg,
166                               intptr_t wParam,
167                               intptr_t lParam) {
168   if (m_bEnableNotify) {
169     if (wParam == SBT_VSCROLL) {
170       switch (msg) {
171         case PNM_SETSCROLLINFO:
172           if (PWL_SCROLL_INFO* pInfo = (PWL_SCROLL_INFO*)lParam) {
173             if (!IsFloatEqual(pInfo->fContentMax, m_fOldMax) ||
174                 !IsFloatEqual(pInfo->fContentMin, m_fOldMin)) {
175               m_bSizeChanged = TRUE;
176               if (CPWL_Wnd* pParent = GetParentWindow()) {
177                 pParent->OnNotify(this, PNM_NOTEEDITCHANGED, 0, 0);
178               }
179
180               m_fOldMax = pInfo->fContentMax;
181               m_fOldMin = pInfo->fContentMin;
182               return;
183             }
184           }
185       }
186     }
187   }
188
189   CPWL_Edit::OnNotify(pWnd, msg, wParam, lParam);
190
191   if (m_bEnableNotify) {
192     switch (msg) {
193       case PNM_SETCARETINFO:
194         if (PWL_CARET_INFO* pInfo = (PWL_CARET_INFO*)wParam) {
195           PWL_CARET_INFO newInfo = *pInfo;
196           newInfo.bVisible = TRUE;
197           newInfo.ptHead = ChildToParent(pInfo->ptHead);
198           newInfo.ptFoot = ChildToParent(pInfo->ptFoot);
199
200           if (CPWL_Wnd* pParent = GetParentWindow()) {
201             pParent->OnNotify(this, PNM_SETCARETINFO, (intptr_t)&newInfo, 0);
202           }
203         }
204         break;
205     }
206   }
207 }
208
209 FX_FLOAT CPWL_Note_Edit::GetItemHeight(FX_FLOAT fLimitWidth) {
210   if (fLimitWidth > 0) {
211     if (!m_bSizeChanged)
212       return m_fOldItemHeight;
213
214     m_bSizeChanged = FALSE;
215
216     EnableNotify(FALSE);
217     EnableRefresh(FALSE);
218     m_pEdit->EnableNotify(FALSE);
219
220     Move(CPDF_Rect(0, 0, fLimitWidth, 0), TRUE, FALSE);
221     FX_FLOAT fRet = GetContentRect().Height();
222
223     m_pEdit->EnableNotify(TRUE);
224     EnableNotify(TRUE);
225     EnableRefresh(TRUE);
226
227     return fRet;
228   }
229
230   return 0;
231 }
232
233 FX_FLOAT CPWL_Note_Edit::GetItemLeftMargin() {
234   return POPUP_ITEM_TEXT_INDENT;
235 }
236
237 FX_FLOAT CPWL_Note_Edit::GetItemRightMargin() {
238   return POPUP_ITEM_TEXT_INDENT;
239 }
240
241 /* -------------------------------- CPWL_Note_LBBox
242  * --------------------------------*/
243
244 CPWL_Note_LBBox::CPWL_Note_LBBox() {}
245
246 CPWL_Note_LBBox::~CPWL_Note_LBBox() {}
247
248 void CPWL_Note_LBBox::DrawThisAppearance(CFX_RenderDevice* pDevice,
249                                          CPDF_Matrix* pUser2Device) {
250   CPDF_Rect rcClient = GetClientRect();
251
252   CFX_GraphStateData gsd;
253   gsd.m_LineWidth = 1.0f;
254
255   CFX_PathData pathCross;
256
257   pathCross.SetPointCount(4);
258   pathCross.SetPoint(0, rcClient.left, rcClient.top, FXPT_MOVETO);
259   pathCross.SetPoint(1, rcClient.right, rcClient.bottom, FXPT_LINETO);
260   pathCross.SetPoint(2, rcClient.left,
261                      rcClient.bottom + rcClient.Height() * 0.5f, FXPT_MOVETO);
262   pathCross.SetPoint(3, rcClient.left + rcClient.Width() * 0.5f,
263                      rcClient.bottom, FXPT_LINETO);
264
265   pDevice->DrawPath(
266       &pathCross, pUser2Device, &gsd, 0,
267       CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
268       FXFILL_ALTERNATE);
269 }
270
271 /* -------------------------------- CPWL_Note_RBBox
272  * --------------------------------*/
273
274 CPWL_Note_RBBox::CPWL_Note_RBBox() {}
275
276 CPWL_Note_RBBox::~CPWL_Note_RBBox() {}
277
278 void CPWL_Note_RBBox::DrawThisAppearance(CFX_RenderDevice* pDevice,
279                                          CPDF_Matrix* pUser2Device) {
280   CPDF_Rect rcClient = GetClientRect();
281
282   CFX_GraphStateData gsd;
283   gsd.m_LineWidth = 1.0f;
284
285   CFX_PathData pathCross;
286
287   pathCross.SetPointCount(4);
288   pathCross.SetPoint(0, rcClient.right, rcClient.top, FXPT_MOVETO);
289   pathCross.SetPoint(1, rcClient.left, rcClient.bottom, FXPT_LINETO);
290   pathCross.SetPoint(2, rcClient.right,
291                      rcClient.bottom + rcClient.Height() * 0.5f, FXPT_MOVETO);
292   pathCross.SetPoint(3, rcClient.left + rcClient.Width() * 0.5f,
293                      rcClient.bottom, FXPT_LINETO);
294
295   pDevice->DrawPath(
296       &pathCross, pUser2Device, &gsd, 0,
297       CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
298       FXFILL_ALTERNATE);
299 }
300
301 /* --------------------------------- CPWL_Note_Icon
302  * ---------------------------------- */
303
304 CPWL_Note_Icon::CPWL_Note_Icon() : m_nType(0) {}
305
306 CPWL_Note_Icon::~CPWL_Note_Icon() {}
307
308 void CPWL_Note_Icon::SetIconType(int32_t nType) {
309   m_nType = nType;
310 }
311
312 void CPWL_Note_Icon::DrawThisAppearance(CFX_RenderDevice* pDevice,
313                                         CPDF_Matrix* pUser2Device) {
314   CPWL_Utils::DrawIconAppStream(pDevice, pUser2Device, m_nType, GetClientRect(),
315                                 GetBackgroundColor(), PWL_DEFAULT_BLACKCOLOR,
316                                 GetTransparency());
317 }
318
319 /* --------------------------------- CPWL_Note_CloseBox
320  * ---------------------------------- */
321
322 CPWL_Note_CloseBox::CPWL_Note_CloseBox() : m_bMouseDown(FALSE) {}
323
324 CPWL_Note_CloseBox::~CPWL_Note_CloseBox() {}
325
326 void CPWL_Note_CloseBox::DrawThisAppearance(CFX_RenderDevice* pDevice,
327                                             CPDF_Matrix* pUser2Device) {
328   CPWL_Button::DrawThisAppearance(pDevice, pUser2Device);
329
330   CPDF_Rect rcClient = GetClientRect();
331   rcClient = CPWL_Utils::DeflateRect(rcClient, 2.0f);
332
333   CFX_GraphStateData gsd;
334   gsd.m_LineWidth = 1.0f;
335
336   CFX_PathData pathCross;
337
338   if (m_bMouseDown) {
339     rcClient.left += 0.5f;
340     rcClient.right += 0.5f;
341     rcClient.top -= 0.5f;
342     rcClient.bottom -= 0.5f;
343   }
344
345   pathCross.SetPointCount(4);
346   pathCross.SetPoint(0, rcClient.left, rcClient.bottom, FXPT_MOVETO);
347   pathCross.SetPoint(1, rcClient.right, rcClient.top, FXPT_LINETO);
348   pathCross.SetPoint(2, rcClient.left, rcClient.top, FXPT_MOVETO);
349   pathCross.SetPoint(3, rcClient.right, rcClient.bottom, FXPT_LINETO);
350
351   pDevice->DrawPath(
352       &pathCross, pUser2Device, &gsd, 0,
353       CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
354       FXFILL_ALTERNATE);
355 }
356
357 FX_BOOL CPWL_Note_CloseBox::OnLButtonDown(const CPDF_Point& point,
358                                           FX_DWORD nFlag) {
359   SetBorderStyle(PBS_INSET);
360   InvalidateRect(NULL);
361
362   m_bMouseDown = TRUE;
363
364   return CPWL_Button::OnLButtonDown(point, nFlag);
365 }
366
367 FX_BOOL CPWL_Note_CloseBox::OnLButtonUp(const CPDF_Point& point,
368                                         FX_DWORD nFlag) {
369   m_bMouseDown = FALSE;
370
371   SetBorderStyle(PBS_BEVELED);
372   InvalidateRect(NULL);
373
374   return CPWL_Button::OnLButtonUp(point, nFlag);
375 }
376
377 /* ------------------------------ CPWL_Note_Contents
378  * ------------------------------- */
379
380 CPWL_Note_Contents::CPWL_Note_Contents() : m_pEdit(NULL) {}
381
382 CPWL_Note_Contents::~CPWL_Note_Contents() {}
383
384 CFX_ByteString CPWL_Note_Contents::GetClassName() const {
385   return "CPWL_Note_Contents";
386 }
387
388 void CPWL_Note_Contents::CreateChildWnd(const PWL_CREATEPARAM& cp) {
389   m_pEdit = new CPWL_Note_Edit;
390   PWL_CREATEPARAM ecp = cp;
391   ecp.pParentWnd = this;
392   ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PES_MULTILINE | PES_AUTORETURN |
393                 PES_TEXTOVERFLOW | PES_UNDO | PES_SPELLCHECK;
394
395   m_pEdit->EnableNotify(FALSE);
396   m_pEdit->Create(ecp);
397   m_pEdit->EnableNotify(TRUE);
398 }
399
400 void CPWL_Note_Contents::SetText(const CFX_WideString& sText) {
401   if (m_pEdit) {
402     m_pEdit->EnableNotify(FALSE);
403     m_pEdit->SetText(sText.c_str());
404     m_pEdit->EnableNotify(TRUE);
405     OnNotify(m_pEdit, PNM_NOTEEDITCHANGED, 0, 0);
406   }
407 }
408
409 CFX_WideString CPWL_Note_Contents::GetText() const {
410   if (m_pEdit)
411     return m_pEdit->GetText();
412
413   return L"";
414 }
415
416 CPWL_NoteItem* CPWL_Note_Contents::CreateSubItem() {
417   CPWL_NoteItem* pNoteItem = new CPWL_NoteItem;
418   PWL_CREATEPARAM icp = GetCreationParam();
419   icp.pParentWnd = this;
420   icp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_BACKGROUND;
421   pNoteItem->Create(icp);
422
423   pNoteItem->OnCreateNoteItem();
424
425   pNoteItem->ResetSubjectName(m_aChildren.GetSize() - 1);
426
427   FX_SYSTEMTIME st;
428   if (IFX_SystemHandler* pSH = GetSystemHandler())
429     st = pSH->GetLocalTime();
430   pNoteItem->SetDateTime(st);
431
432   pNoteItem->SetContents(L"");
433
434   OnNotify(pNoteItem, PNM_NOTEEDITCHANGED, 0, 0);
435
436   return pNoteItem;
437 }
438
439 int32_t CPWL_Note_Contents::CountSubItems() const {
440   return m_aChildren.GetSize() - 1;
441 }
442
443 IPWL_NoteItem* CPWL_Note_Contents::GetSubItems(int32_t index) const {
444   int32_t nIndex = index + 1;
445
446   if (nIndex > 0 && nIndex < m_aChildren.GetSize())
447     if (CPWL_Wnd* pChild = m_aChildren.GetAt(nIndex)) {
448       ASSERT(pChild->GetClassName() == "CPWL_NoteItem");
449       CPWL_NoteItem* pItem = (CPWL_NoteItem*)pChild;
450       return pItem;
451     }
452   return NULL;
453 }
454
455 void CPWL_Note_Contents::DeleteSubItem(IPWL_NoteItem* pNoteItem) {
456   int32_t nIndex = GetItemIndex((CPWL_NoteItem*)pNoteItem);
457
458   if (nIndex > 0) {
459     if (CPWL_NoteItem* pPWLNoteItem = (CPWL_NoteItem*)pNoteItem) {
460       pPWLNoteItem->KillFocus();
461       pPWLNoteItem->Destroy();
462       delete pPWLNoteItem;
463     }
464
465     for (int32_t i = nIndex, sz = m_aChildren.GetSize(); i < sz; i++) {
466       if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
467         ASSERT(pChild->GetClassName() == "CPWL_NoteItem");
468         CPWL_NoteItem* pItem = (CPWL_NoteItem*)pChild;
469         pItem->ResetSubjectName(i);
470       }
471     }
472
473     OnNotify(this, PNM_NOTEEDITCHANGED, 0, 0);
474   }
475 }
476
477 IPWL_NoteItem* CPWL_Note_Contents::GetHitNoteItem(const CPDF_Point& point) {
478   CPDF_Point pt = ParentToChild(point);
479
480   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
481     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
482       if (pChild->GetClassName() == "CPWL_NoteItem") {
483         CPWL_NoteItem* pNoteItem = (CPWL_NoteItem*)pChild;
484         if (IPWL_NoteItem* pRet = pNoteItem->GetHitNoteItem(pt))
485           return pRet;
486       }
487     }
488   }
489   return NULL;
490 }
491
492 void CPWL_Note_Contents::OnNotify(CPWL_Wnd* pWnd,
493                                   FX_DWORD msg,
494                                   intptr_t wParam,
495                                   intptr_t lParam) {
496   switch (msg) {
497     case PNM_NOTEEDITCHANGED: {
498       int32_t nIndex = GetItemIndex(pWnd);
499       if (nIndex < 0)
500         nIndex = 0;
501
502       m_pEdit->EnableNotify(FALSE);
503       ResetContent(nIndex);
504       m_pEdit->EnableNotify(TRUE);
505
506       for (int32_t i = nIndex + 1, sz = m_aChildren.GetSize(); i < sz; i++) {
507         if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
508           pChild->OnNotify(this, PNM_NOTERESET, 0, 0);
509       }
510
511       if (CPWL_Wnd* pParent = GetParentWindow()) {
512         pParent->OnNotify(this, PNM_NOTEEDITCHANGED, 0, 0);
513       }
514     }
515       return;
516     case PNM_SCROLLWINDOW:
517       SetScrollPos(CPDF_Point(0.0f, *(FX_FLOAT*)lParam));
518       ResetFace();
519       InvalidateRect(NULL);
520       return;
521     case PNM_SETCARETINFO:
522       if (PWL_CARET_INFO* pInfo = (PWL_CARET_INFO*)wParam) {
523         PWL_CARET_INFO newInfo = *pInfo;
524         newInfo.bVisible = TRUE;
525         newInfo.ptHead = ChildToParent(pInfo->ptHead);
526         newInfo.ptFoot = ChildToParent(pInfo->ptFoot);
527
528         if (CPWL_Wnd* pParent = GetParentWindow()) {
529           pParent->OnNotify(this, PNM_SETCARETINFO, (intptr_t)&newInfo, 0);
530         }
531       }
532       return;
533     case PNM_NOTERESET: {
534       m_pEdit->EnableNotify(FALSE);
535       ResetContent(0);
536       m_pEdit->EnableNotify(TRUE);
537
538       for (int32_t i = 1, sz = m_aChildren.GetSize(); i < sz; i++) {
539         if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
540           pChild->OnNotify(this, PNM_NOTERESET, 0, 0);
541       }
542
543       m_pEdit->EnableNotify(FALSE);
544       ResetContent(0);
545       m_pEdit->EnableNotify(TRUE);
546     }
547       return;
548   }
549
550   CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
551 }
552
553 FX_BOOL CPWL_Note_Contents::OnLButtonDown(const CPDF_Point& point,
554                                           FX_DWORD nFlag) {
555   if (CPWL_Wnd::OnLButtonDown(point, nFlag))
556     return TRUE;
557
558   if (!m_pEdit->IsFocused()) {
559     m_pEdit->SetFocus();
560   }
561
562   return TRUE;
563 }
564
565 void CPWL_Note_Contents::SetEditFocus(FX_BOOL bLast) {
566   if (!m_pEdit->IsFocused()) {
567     m_pEdit->SetFocus();
568     m_pEdit->SetCaret(bLast ? m_pEdit->GetTotalWords() : 0);
569   }
570 }
571
572 CPWL_Edit* CPWL_Note_Contents::GetEdit() const {
573   return m_pEdit;
574 }
575
576 void CPWL_Note_Contents::EnableModify(FX_BOOL bEnabled) {
577   if (!bEnabled)
578     m_pEdit->AddFlag(PWS_READONLY);
579   else
580     m_pEdit->RemoveFlag(PWS_READONLY);
581
582   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
583     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
584       if (pChild->GetClassName() == "CPWL_NoteItem") {
585         CPWL_NoteItem* pNoteItem = (CPWL_NoteItem*)pChild;
586         pNoteItem->EnableModify(bEnabled);
587       }
588     }
589   }
590 }
591
592 void CPWL_Note_Contents::EnableRead(FX_BOOL bEnabled) {
593   if (!bEnabled)
594     m_pEdit->AddFlag(PES_NOREAD);
595   else
596     m_pEdit->RemoveFlag(PES_NOREAD);
597
598   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
599     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
600       if (pChild->GetClassName() == "CPWL_NoteItem") {
601         CPWL_NoteItem* pNoteItem = (CPWL_NoteItem*)pChild;
602         pNoteItem->EnableRead(bEnabled);
603       }
604     }
605   }
606 }
607
608 /* ---------------------------------- CPWL_NoteItem
609  * ---------------------------------- */
610
611 CPWL_NoteItem::CPWL_NoteItem()
612     : m_pSubject(NULL),
613       m_pDateTime(NULL),
614       m_pContents(NULL),
615       m_pPrivateData(NULL),
616       m_sAuthor(L""),
617       m_fOldItemHeight(0.0f),
618       m_bSizeChanged(FALSE),
619       m_bAllowModify(TRUE) {}
620
621 CPWL_NoteItem::~CPWL_NoteItem() {}
622
623 CFX_ByteString CPWL_NoteItem::GetClassName() const {
624   return "CPWL_NoteItem";
625 }
626
627 void CPWL_NoteItem::CreateChildWnd(const PWL_CREATEPARAM& cp) {
628   CPWL_Color sTextColor;
629
630   if (CPWL_Utils::IsBlackOrWhite(GetBackgroundColor()))
631     sTextColor = PWL_DEFAULT_WHITECOLOR;
632   else
633     sTextColor = PWL_DEFAULT_BLACKCOLOR;
634
635   m_pSubject = new CPWL_Label;
636   PWL_CREATEPARAM scp = cp;
637   scp.pParentWnd = this;
638   scp.dwFlags = PWS_VISIBLE | PWS_CHILD | PES_LEFT | PES_TOP;
639   scp.sTextColor = sTextColor;
640   m_pSubject->Create(scp);
641
642   m_pDateTime = new CPWL_Label;
643   PWL_CREATEPARAM dcp = cp;
644   dcp.pParentWnd = this;
645   dcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PES_RIGHT | PES_TOP;
646   dcp.sTextColor = sTextColor;
647   m_pDateTime->Create(dcp);
648
649   m_pContents = new CPWL_Note_Contents;
650   PWL_CREATEPARAM ccp = cp;
651   ccp.pParentWnd = this;
652   // ccp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
653   ccp.sBackgroundColor =
654       CPWL_Color(COLORTYPE_RGB, 240 / 255.0f, 240 / 255.0f, 240 / 255.0f);
655   ccp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BACKGROUND;
656   m_pContents->Create(ccp);
657   m_pContents->SetItemSpace(POPUP_ITEM_SPACE);
658   m_pContents->SetTopSpace(POPUP_ITEM_SPACE);
659   m_pContents->SetBottomSpace(POPUP_ITEM_SPACE);
660 }
661
662 void CPWL_NoteItem::RePosChildWnd() {
663   if (IsValid()) {
664     ASSERT(m_pSubject != NULL);
665     ASSERT(m_pDateTime != NULL);
666     ASSERT(m_pContents != NULL);
667
668     CPDF_Rect rcClient = GetClientRect();
669
670     CPDF_Rect rcSubject = rcClient;
671     rcSubject.left += POPUP_ITEM_TEXT_INDENT;
672     rcSubject.top = rcClient.top;
673     rcSubject.right =
674         PWL_MIN(rcSubject.left + m_pSubject->GetContentRect().Width() + 1.0f,
675                 rcClient.right);
676     rcSubject.bottom = rcSubject.top - m_pSubject->GetContentRect().Height();
677     rcSubject.Normalize();
678     m_pSubject->Move(rcSubject, TRUE, FALSE);
679     m_pSubject->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcSubject));
680
681     CPDF_Rect rcDate = rcClient;
682     rcDate.right -= POPUP_ITEM_TEXT_INDENT;
683     rcDate.left =
684         PWL_MAX(rcDate.right - m_pDateTime->GetContentRect().Width() - 1.0f,
685                 rcSubject.right);
686     rcDate.bottom = rcDate.top - m_pDateTime->GetContentRect().Height();
687     rcDate.Normalize();
688     m_pDateTime->Move(rcDate, TRUE, FALSE);
689     m_pDateTime->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcDate));
690
691     CPDF_Rect rcContents = rcClient;
692     rcContents.left += 1.0f;
693     rcContents.right -= 1.0f;
694     rcContents.top = rcDate.bottom - POPUP_ITEM_HEAD_BOTTOM;
695     rcContents.bottom += POPUP_ITEM_BOTTOMWIDTH;
696     rcContents.Normalize();
697     m_pContents->Move(rcContents, TRUE, FALSE);
698     m_pContents->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcContents));
699   }
700
701   SetClipRect(CPWL_Utils::InflateRect(GetWindowRect(), 1.0f));
702 }
703
704 void CPWL_NoteItem::SetPrivateData(void* pData) {
705   m_pPrivateData = pData;
706 }
707
708 void CPWL_NoteItem::SetBkColor(const CPWL_Color& color) {
709   CPWL_Color sBK = color;
710   SetBackgroundColor(sBK);
711
712   CPWL_Color sTextColor;
713
714   if (CPWL_Utils::IsBlackOrWhite(sBK))
715     sTextColor = PWL_DEFAULT_WHITECOLOR;
716   else
717     sTextColor = PWL_DEFAULT_BLACKCOLOR;
718
719   SetTextColor(sTextColor);
720   if (m_pSubject)
721     m_pSubject->SetTextColor(sTextColor);
722   if (m_pDateTime)
723     m_pDateTime->SetTextColor(sTextColor);
724
725   InvalidateRect(nullptr);
726
727   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
728     pNotify->OnSetBkColor(this);
729   }
730 }
731
732 void CPWL_NoteItem::SetSubjectName(const CFX_WideString& sName) {
733   if (m_pSubject) {
734     m_pSubject->SetText(sName.c_str());
735   }
736
737   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
738     pNotify->OnSetSubjectName(this);
739   }
740 }
741
742 void CPWL_NoteItem::SetAuthorName(const CFX_WideString& sName) {
743   m_sAuthor = sName;
744   ResetSubjectName(-1);
745
746   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
747     pNotify->OnSetAuthorName(this);
748   }
749 }
750
751 void CPWL_NoteItem::ResetSubjectName(int32_t nItemIndex) {
752   if (nItemIndex < 0) {
753     if (CPWL_Wnd* pParent = GetParentWindow()) {
754       ASSERT(pParent->GetClassName() == "CPWL_Note_Contents");
755
756       CPWL_Note_Contents* pContents = (CPWL_Note_Contents*)pParent;
757       nItemIndex = pContents->GetItemIndex(this);
758     }
759   }
760
761   const CPWL_Note* pNote = GetNote();
762   ASSERT(pNote != NULL);
763
764   CFX_WideString sSubject;
765   sSubject.Format(pNote->GetReplyString().c_str(), nItemIndex);
766
767   if (!m_sAuthor.IsEmpty()) {
768     sSubject += L" - ";
769     sSubject += m_sAuthor;
770   }
771   SetSubjectName(sSubject);
772   RePosChildWnd();
773 }
774
775 void CPWL_NoteItem::SetDateTime(FX_SYSTEMTIME time) {
776   m_dtNote = time;
777
778   CFX_WideString swTime;
779   swTime.Format(L"%04d-%02d-%02d %02d:%02d:%02d", time.wYear, time.wMonth,
780                 time.wDay, time.wHour, time.wMinute, time.wSecond);
781   if (m_pDateTime) {
782     m_pDateTime->SetText(swTime.c_str());
783   }
784
785   RePosChildWnd();
786
787   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
788     pNotify->OnSetDateTime(this);
789   }
790 }
791
792 void CPWL_NoteItem::SetContents(const CFX_WideString& sContents) {
793   if (m_pContents) {
794     m_pContents->SetText(sContents);
795   }
796
797   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
798     pNotify->OnSetContents(this);
799   }
800 }
801
802 CPWL_NoteItem* CPWL_NoteItem::GetParentNoteItem() const {
803   if (CPWL_Wnd* pParent = GetParentWindow()) {
804     if (CPWL_Wnd* pGrand = pParent->GetParentWindow()) {
805       ASSERT(pGrand->GetClassName() == "CPWL_NoteItem");
806       return (CPWL_NoteItem*)pGrand;
807     }
808   }
809
810   return NULL;
811 }
812
813 IPWL_NoteItem* CPWL_NoteItem::GetParentItem() const {
814   return GetParentNoteItem();
815 }
816
817 CPWL_Edit* CPWL_NoteItem::GetEdit() const {
818   if (m_pContents)
819     return m_pContents->GetEdit();
820   return NULL;
821 }
822
823 void* CPWL_NoteItem::GetPrivateData() const {
824   return m_pPrivateData;
825 }
826
827 CFX_WideString CPWL_NoteItem::GetAuthorName() const {
828   return m_sAuthor;
829 }
830
831 CPWL_Color CPWL_NoteItem::GetBkColor() const {
832   return GetBackgroundColor();
833 }
834
835 CFX_WideString CPWL_NoteItem::GetContents() const {
836   if (m_pContents)
837     return m_pContents->GetText();
838
839   return L"";
840 }
841
842 FX_SYSTEMTIME CPWL_NoteItem::GetDateTime() const {
843   return m_dtNote;
844 }
845
846 CFX_WideString CPWL_NoteItem::GetSubjectName() const {
847   if (m_pSubject)
848     return m_pSubject->GetText();
849
850   return L"";
851 }
852
853 CPWL_NoteItem* CPWL_NoteItem::CreateNoteItem() {
854   if (m_pContents)
855     return m_pContents->CreateSubItem();
856
857   return NULL;
858 }
859
860 IPWL_NoteItem* CPWL_NoteItem::CreateSubItem() {
861   return CreateNoteItem();
862 }
863
864 int32_t CPWL_NoteItem::CountSubItems() const {
865   if (m_pContents)
866     return m_pContents->CountSubItems();
867
868   return 0;
869 }
870
871 IPWL_NoteItem* CPWL_NoteItem::GetSubItems(int32_t index) const {
872   if (m_pContents)
873     return m_pContents->GetSubItems(index);
874
875   return NULL;
876 }
877
878 void CPWL_NoteItem::DeleteSubItem(IPWL_NoteItem* pNoteItem) {
879   KillFocus();
880
881   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
882     pNotify->OnItemDelete(pNoteItem);
883   }
884
885   if (m_pContents)
886     m_pContents->DeleteSubItem(pNoteItem);
887 }
888
889 IPWL_NoteItem* CPWL_NoteItem::GetHitNoteItem(const CPDF_Point& point) {
890   CPDF_Point pt = ParentToChild(point);
891
892   if (WndHitTest(pt)) {
893     if (m_pContents) {
894       if (IPWL_NoteItem* pNoteItem = m_pContents->GetHitNoteItem(pt))
895         return pNoteItem;
896     }
897
898     return this;
899   }
900
901   return NULL;
902 }
903
904 IPWL_NoteItem* CPWL_NoteItem::GetFocusedNoteItem() const {
905   if (const CPWL_Wnd* pWnd = GetFocused()) {
906     if (pWnd->GetClassName() == "CPWL_Edit") {
907       if (CPWL_Wnd* pParent = pWnd->GetParentWindow()) {
908         ASSERT(pParent->GetClassName() == "CPWL_Note_Contents");
909
910         if (CPWL_Wnd* pGrand = pParent->GetParentWindow()) {
911           ASSERT(pGrand->GetClassName() == "CPWL_NoteItem");
912           return (CPWL_NoteItem*)pGrand;
913         }
914       }
915     }
916   }
917
918   return NULL;
919 }
920
921 FX_FLOAT CPWL_NoteItem::GetItemHeight(FX_FLOAT fLimitWidth) {
922   if (fLimitWidth > 0) {
923     if (!m_bSizeChanged)
924       return m_fOldItemHeight;
925
926     m_bSizeChanged = FALSE;
927
928     ASSERT(m_pSubject != NULL);
929     ASSERT(m_pDateTime != NULL);
930     ASSERT(m_pContents != NULL);
931
932     FX_FLOAT fRet = m_pDateTime->GetContentRect().Height();
933     FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
934     if (fLimitWidth > fBorderWidth * 2)
935       fRet += m_pContents->GetContentsHeight(fLimitWidth - fBorderWidth * 2);
936     fRet += POPUP_ITEM_HEAD_BOTTOM + POPUP_ITEM_BOTTOMWIDTH + fBorderWidth * 2;
937
938     return m_fOldItemHeight = fRet;
939   }
940
941   return 0;
942 }
943
944 FX_FLOAT CPWL_NoteItem::GetItemLeftMargin() {
945   return POPUP_ITEM_SIDEMARGIN;
946 }
947
948 FX_FLOAT CPWL_NoteItem::GetItemRightMargin() {
949   return POPUP_ITEM_SIDEMARGIN;
950 }
951
952 FX_BOOL CPWL_NoteItem::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag) {
953   if (!m_pContents->WndHitTest(m_pContents->ParentToChild(point))) {
954     SetNoteFocus(FALSE);
955   }
956
957   CPWL_Wnd::OnLButtonDown(point, nFlag);
958
959   return TRUE;
960 }
961
962 FX_BOOL CPWL_NoteItem::OnRButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
963   if (!m_pContents->WndHitTest(m_pContents->ParentToChild(point))) {
964     SetNoteFocus(FALSE);
965     PopupNoteItemMenu(point);
966
967     return TRUE;
968   }
969
970   return CPWL_Wnd::OnRButtonUp(point, nFlag);
971 }
972
973 void CPWL_NoteItem::OnNotify(CPWL_Wnd* pWnd,
974                              FX_DWORD msg,
975                              intptr_t wParam,
976                              intptr_t lParam) {
977   switch (msg) {
978     case PNM_NOTEEDITCHANGED:
979       m_bSizeChanged = TRUE;
980
981       if (CPWL_Wnd* pParent = GetParentWindow()) {
982         pParent->OnNotify(this, PNM_NOTEEDITCHANGED, 0, 0);
983       }
984       return;
985     case PNM_SETCARETINFO:
986       if (PWL_CARET_INFO* pInfo = (PWL_CARET_INFO*)wParam) {
987         PWL_CARET_INFO newInfo = *pInfo;
988         newInfo.bVisible = TRUE;
989         newInfo.ptHead = ChildToParent(pInfo->ptHead);
990         newInfo.ptFoot = ChildToParent(pInfo->ptFoot);
991
992         if (CPWL_Wnd* pParent = GetParentWindow()) {
993           pParent->OnNotify(this, PNM_SETCARETINFO, (intptr_t)&newInfo, 0);
994         }
995       }
996       return;
997     case PNM_NOTERESET:
998       m_bSizeChanged = TRUE;
999       m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1000
1001       return;
1002   }
1003
1004   CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
1005 }
1006
1007 void CPWL_NoteItem::PopupNoteItemMenu(const CPDF_Point& point) {
1008   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
1009     int32_t x, y;
1010     PWLtoWnd(point, x, y);
1011     if (IFX_SystemHandler* pSH = GetSystemHandler())
1012       pSH->ClientToScreen(GetAttachedHWnd(), x, y);
1013     pNotify->OnPopupMenu(this, x, y);
1014   }
1015 }
1016
1017 const CPWL_Note* CPWL_NoteItem::GetNote() const {
1018   if (const CPWL_Wnd* pRoot = GetRootWnd()) {
1019     ASSERT(pRoot->GetClassName() == "CPWL_NoteItem");
1020     CPWL_NoteItem* pNoteItem = (CPWL_NoteItem*)pRoot;
1021     if (pNoteItem->IsTopItem()) {
1022       return (CPWL_Note*)pNoteItem;
1023     }
1024   }
1025
1026   return NULL;
1027 }
1028
1029 IPWL_NoteNotify* CPWL_NoteItem::GetNoteNotify() const {
1030   if (const CPWL_Note* pNote = GetNote())
1031     return pNote->GetNoteNotify();
1032
1033   return NULL;
1034 }
1035
1036 void CPWL_NoteItem::OnCreateNoteItem() {
1037   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
1038     pNotify->OnItemCreate(this);
1039   }
1040 }
1041
1042 void CPWL_NoteItem::OnContentsValidate() {
1043   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
1044     pNotify->OnSetContents(this);
1045   }
1046 }
1047
1048 void CPWL_NoteItem::SetNoteFocus(FX_BOOL bLast) {
1049   m_pContents->SetEditFocus(bLast);
1050 }
1051
1052 void CPWL_NoteItem::EnableModify(FX_BOOL bEnabled) {
1053   m_pContents->EnableModify(bEnabled);
1054   m_bAllowModify = bEnabled;
1055 }
1056
1057 void CPWL_NoteItem::EnableRead(FX_BOOL bEnabled) {
1058   m_pContents->EnableRead(bEnabled);
1059 }
1060
1061 /* ---------------------------------- CPWL_Note
1062  * ---------------------------------- */
1063
1064 CPWL_Note::CPWL_Note(IPopup_Note* pPopupNote,
1065                      IPWL_NoteNotify* pNoteNotify,
1066                      IPWL_NoteHandler* pNoteHandler)
1067     : m_pAuthor(NULL),
1068       m_pIcon(NULL),
1069       m_pCloseBox(NULL),
1070       m_pLBBox(NULL),
1071       m_pRBBox(NULL),
1072       m_pContentsBar(NULL),
1073       m_pOptions(NULL),
1074       m_pNoteNotify(pNoteNotify),
1075       m_bResizing(FALSE),
1076       m_rcCaption(0, 0, 0, 0),
1077       m_bEnalbleNotify(TRUE),
1078       m_pPopupNote(pPopupNote) {}
1079
1080 CPWL_Note::~CPWL_Note() {}
1081
1082 IPWL_NoteItem* CPWL_Note::Reply() {
1083   return CreateNoteItem();
1084 }
1085
1086 void CPWL_Note::EnableNotify(FX_BOOL bEnabled) {
1087   m_bEnalbleNotify = bEnabled;
1088 }
1089
1090 void CPWL_Note::RePosChildWnd() {
1091   RePosNoteChildren();
1092   m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1093   ResetScrollBar();
1094   m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1095   OnNotify(this, PNM_NOTEEDITCHANGED, 0, 0);
1096   if (const CPWL_Wnd* pWnd = GetFocused()) {
1097     if (pWnd->GetClassName() == "CPWL_Edit") {
1098       CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
1099       pEdit->SetCaret(pEdit->GetCaret());
1100     }
1101   }
1102 }
1103
1104 FX_BOOL CPWL_Note::ResetScrollBar() {
1105   FX_BOOL bScrollChanged = FALSE;
1106
1107   if (ScrollBarShouldVisible()) {
1108     if (!m_pContentsBar->IsVisible()) {
1109       m_pContentsBar->SetVisible(TRUE);
1110       if (m_pContentsBar->IsVisible()) {
1111         m_pContentsBar->InvalidateRect(NULL);
1112         bScrollChanged = TRUE;
1113       }
1114     }
1115   } else {
1116     if (m_pContentsBar->IsVisible()) {
1117       m_pContentsBar->SetVisible(FALSE);
1118       m_pContentsBar->InvalidateRect(NULL);
1119
1120       bScrollChanged = TRUE;
1121     }
1122   }
1123
1124   if (bScrollChanged) {
1125     CPDF_Rect rcNote = GetClientRect();
1126     CPDF_Rect rcContents = m_pContents->GetWindowRect();
1127     rcContents.right = rcNote.right - 3.0f;
1128     if (m_pContentsBar->IsVisible())
1129       rcContents.right -= PWL_SCROLLBAR_WIDTH;
1130     m_pContents->Move(rcContents, TRUE, TRUE);
1131     m_pContents->SetScrollPos(CPDF_Point(0.0f, 0.0f));
1132     m_pContents->InvalidateRect(NULL);
1133   }
1134
1135   return bScrollChanged;
1136 }
1137
1138 FX_BOOL CPWL_Note::ScrollBarShouldVisible() {
1139   CPDF_Rect rcContentsFact = m_pContents->GetScrollArea();
1140   CPDF_Rect rcContentsClient = m_pContents->GetClientRect();
1141
1142   return rcContentsFact.Height() > rcContentsClient.Height();
1143 }
1144
1145 void CPWL_Note::SetOptionsText(const CFX_WideString& sText) {
1146   if (m_pOptions)
1147     m_pOptions->SetText(sText);
1148
1149   RePosNoteChildren();
1150 }
1151
1152 void CPWL_Note::RePosNoteChildren() {
1153   if (m_bResizing)
1154     return;
1155
1156   m_bResizing = TRUE;
1157
1158   if (IsValid()) {
1159     ASSERT(m_pSubject != NULL);
1160     ASSERT(m_pDateTime != NULL);
1161     ASSERT(m_pContents != NULL);
1162     ASSERT(m_pAuthor != NULL);
1163     ASSERT(m_pCloseBox != NULL);
1164     ASSERT(m_pIcon != NULL);
1165     ASSERT(m_pLBBox != NULL);
1166     ASSERT(m_pRBBox != NULL);
1167     ASSERT(m_pContentsBar != NULL);
1168     ASSERT(m_pOptions != NULL);
1169
1170     CPDF_Rect rcClient = GetClientRect();
1171
1172     CPDF_Rect rcIcon = rcClient;
1173     rcIcon.top -= 2.0f;
1174     rcIcon.right = rcIcon.left + 14.0f;
1175     rcIcon.bottom = rcIcon.top - 14.0f;
1176     rcIcon.Normalize();
1177     m_pIcon->Move(rcIcon, TRUE, FALSE);
1178     m_pIcon->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcIcon));
1179
1180     CPDF_Rect rcCloseBox = rcClient;
1181     rcCloseBox.right -= 1.0f;
1182     rcCloseBox.top -= 1.0f;
1183     rcCloseBox.left = rcCloseBox.right - 14.0f;
1184     rcCloseBox.bottom = rcCloseBox.top - 14.0f;
1185     rcCloseBox.Normalize();
1186     m_pCloseBox->Move(rcCloseBox, TRUE, FALSE);
1187     m_pCloseBox->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcCloseBox));
1188
1189     CPDF_Rect rcDate = rcClient;
1190     rcDate.right = rcCloseBox.left - POPUP_ITEM_TEXT_INDENT;
1191     rcDate.left =
1192         PWL_MAX(rcDate.right - m_pDateTime->GetContentRect().Width() - 1.0f,
1193                 rcIcon.right + 1.0f);
1194     rcDate.top = rcClient.top - 2.0f;
1195     rcDate.bottom = rcDate.top - m_pDateTime->GetContentRect().Height();
1196     rcDate.Normalize();
1197     m_pDateTime->Move(rcDate, TRUE, FALSE);
1198     m_pDateTime->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcDate));
1199
1200     CPDF_Rect rcSubject = rcClient;
1201     rcSubject.top = rcClient.top - 2.0f;
1202     rcSubject.left = rcIcon.right + POPUP_ITEM_TEXT_INDENT;
1203     rcSubject.right =
1204         PWL_MIN(rcSubject.left + m_pSubject->GetContentRect().Width() + 1.0f,
1205                 rcDate.left - 1.0f);
1206     rcSubject.bottom = rcSubject.top - m_pSubject->GetContentRect().Height();
1207     rcSubject.Normalize();
1208     m_pSubject->Move(rcSubject, TRUE, FALSE);
1209     m_pSubject->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcSubject));
1210
1211     CPDF_Rect rcOptions = rcClient;
1212     rcOptions.left =
1213         PWL_MAX(rcOptions.right - m_pOptions->GetContentRect().Width(),
1214                 rcIcon.right + 1.0f);
1215     rcOptions.top = rcSubject.bottom - 4.0f;
1216     rcOptions.bottom = rcOptions.top - m_pOptions->GetContentRect().Height();
1217     rcOptions.Normalize();
1218     m_pOptions->Move(rcOptions, TRUE, FALSE);
1219     m_pOptions->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcOptions));
1220
1221     CPDF_Rect rcAuthor = rcClient;
1222     rcAuthor.top = rcSubject.bottom - 4.0f;
1223     rcAuthor.left = rcSubject.left;
1224     rcAuthor.right =
1225         PWL_MIN(rcSubject.left + m_pAuthor->GetContentRect().Width() + 1.0f,
1226                 rcOptions.left - 1.0f);
1227     rcAuthor.bottom = rcAuthor.top - m_pAuthor->GetContentRect().Height();
1228     rcAuthor.Normalize();
1229     m_pAuthor->Move(rcAuthor, TRUE, FALSE);
1230     m_pAuthor->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcAuthor));
1231
1232     CPDF_Rect rcLBBox = rcClient;
1233     rcLBBox.top = rcLBBox.bottom + 7.0f;
1234     rcLBBox.right = rcLBBox.left + 7.0f;
1235     rcLBBox.Normalize();
1236     m_pLBBox->Move(rcLBBox, TRUE, FALSE);
1237     m_pLBBox->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcLBBox));
1238
1239     CPDF_Rect rcRBBox = rcClient;
1240     rcRBBox.top = rcRBBox.bottom + 7.0f;
1241     rcRBBox.left = rcRBBox.right - 7.0f;
1242     rcRBBox.Normalize();
1243     m_pRBBox->Move(rcRBBox, TRUE, FALSE);
1244     m_pRBBox->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcRBBox));
1245
1246     CPDF_Rect rcContents = rcClient;
1247     rcContents.top = rcAuthor.bottom - POPUP_ITEM_HEAD_BOTTOM;
1248     rcContents.left += 3.0f;
1249     rcContents.right -= 3.0f;
1250     if (m_pContentsBar->IsVisible())
1251       rcContents.right -= PWL_SCROLLBAR_WIDTH;
1252     rcContents.bottom += 14.0f;
1253     rcContents.Normalize();
1254     m_pContents->Move(rcContents, FALSE, FALSE);
1255     m_pContents->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcContents));
1256
1257     CPDF_Rect rcContentsBar = rcContents;
1258     rcContentsBar.right = rcClient.right - 3.0f;
1259     rcContentsBar.left = rcContentsBar.right - PWL_SCROLLBAR_WIDTH;
1260     rcContentsBar.Normalize();
1261     m_pContentsBar->Move(rcContentsBar, TRUE, FALSE);
1262
1263     m_rcCaption = rcClient;
1264     m_rcCaption.bottom = rcContents.top;
1265   }
1266
1267   m_bResizing = FALSE;
1268 }
1269
1270 // 0-normal / 1-caption / 2-leftbottom corner / 3-rightbottom corner / 4-close /
1271 // 5-options
1272 int32_t CPWL_Note::NoteHitTest(const CPDF_Point& point) const {
1273   ASSERT(m_pSubject != NULL);
1274   ASSERT(m_pDateTime != NULL);
1275   ASSERT(m_pContents != NULL);
1276   ASSERT(m_pAuthor != NULL);
1277   ASSERT(m_pIcon != NULL);
1278   ASSERT(m_pContentsBar != NULL);
1279
1280   ASSERT(m_pCloseBox != NULL);
1281   ASSERT(m_pLBBox != NULL);
1282   ASSERT(m_pRBBox != NULL);
1283   ASSERT(m_pOptions != NULL);
1284
1285   GetClientRect();
1286
1287   if (m_pSubject->WndHitTest(m_pSubject->ParentToChild(point)))
1288     return 1;
1289   if (m_pDateTime->WndHitTest(m_pDateTime->ParentToChild(point)))
1290     return 1;
1291   if (m_pAuthor->WndHitTest(m_pAuthor->ParentToChild(point)))
1292     return 1;
1293   if (m_pIcon->WndHitTest(m_pIcon->ParentToChild(point)))
1294     return 1;
1295
1296   if (m_pContents->WndHitTest(m_pContents->ParentToChild(point)))
1297     return 0;
1298   if (m_pContentsBar->WndHitTest(m_pContentsBar->ParentToChild(point)))
1299     return 0;
1300
1301   if (m_pCloseBox->WndHitTest(m_pCloseBox->ParentToChild(point)))
1302     return 4;
1303   if (m_pLBBox->WndHitTest(m_pLBBox->ParentToChild(point)))
1304     return 2;
1305   if (m_pRBBox->WndHitTest(m_pRBBox->ParentToChild(point)))
1306     return 3;
1307   if (m_pOptions->WndHitTest(m_pOptions->ParentToChild(point)))
1308     return 5;
1309
1310   return 1;
1311 }
1312
1313 void CPWL_Note::CreateChildWnd(const PWL_CREATEPARAM& cp) {
1314   CPWL_NoteItem::CreateChildWnd(cp);
1315
1316   CPWL_Color sTextColor;
1317
1318   if (CPWL_Utils::IsBlackOrWhite(GetBackgroundColor()))
1319     sTextColor = PWL_DEFAULT_WHITECOLOR;
1320   else
1321     sTextColor = PWL_DEFAULT_BLACKCOLOR;
1322
1323   m_pAuthor = new CPWL_Label;
1324   PWL_CREATEPARAM acp = cp;
1325   acp.pParentWnd = this;
1326   acp.dwFlags = PWS_VISIBLE | PWS_CHILD | PES_LEFT | PES_TOP;
1327   acp.sTextColor = sTextColor;
1328   m_pAuthor->Create(acp);
1329
1330   m_pCloseBox = new CPWL_Note_CloseBox;
1331   PWL_CREATEPARAM ccp = cp;
1332   ccp.pParentWnd = this;
1333   ccp.dwBorderWidth = 2;
1334   ccp.nBorderStyle = PBS_BEVELED;
1335   ccp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER;
1336   ccp.sTextColor = sTextColor;
1337   m_pCloseBox->Create(ccp);
1338
1339   m_pIcon = new CPWL_Note_Icon;
1340   PWL_CREATEPARAM icp = cp;
1341   icp.pParentWnd = this;
1342   icp.dwFlags = PWS_VISIBLE | PWS_CHILD;
1343   m_pIcon->Create(icp);
1344
1345   m_pOptions = new CPWL_Note_Options;
1346   PWL_CREATEPARAM ocp = cp;
1347   ocp.pParentWnd = this;
1348   ocp.dwFlags = PWS_CHILD | PWS_VISIBLE;
1349   ocp.sTextColor = sTextColor;
1350   m_pOptions->Create(ocp);
1351
1352   m_pLBBox = new CPWL_Note_LBBox;
1353   PWL_CREATEPARAM lcp = cp;
1354   lcp.pParentWnd = this;
1355   lcp.dwFlags = PWS_VISIBLE | PWS_CHILD;
1356   lcp.eCursorType = FXCT_NESW;
1357   lcp.sTextColor = sTextColor;
1358   m_pLBBox->Create(lcp);
1359
1360   m_pRBBox = new CPWL_Note_RBBox;
1361   PWL_CREATEPARAM rcp = cp;
1362   rcp.pParentWnd = this;
1363   rcp.dwFlags = PWS_VISIBLE | PWS_CHILD;
1364   rcp.eCursorType = FXCT_NWSE;
1365   rcp.sTextColor = sTextColor;
1366   m_pRBBox->Create(rcp);
1367
1368   m_pContentsBar = new CPWL_ScrollBar(SBT_VSCROLL);
1369   PWL_CREATEPARAM scp = cp;
1370   scp.pParentWnd = this;
1371   scp.sBackgroundColor =
1372       CPWL_Color(COLORTYPE_RGB, 240 / 255.0f, 240 / 255.0f, 240 / 255.0f);
1373   scp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_BACKGROUND;
1374   m_pContentsBar->Create(scp);
1375   m_pContentsBar->SetNotifyForever(TRUE);
1376 }
1377
1378 void CPWL_Note::SetSubjectName(const CFX_WideString& sName) {
1379   CPWL_NoteItem::SetSubjectName(sName);
1380   RePosChildWnd();
1381 }
1382
1383 void CPWL_Note::SetAuthorName(const CFX_WideString& sName) {
1384   if (m_pAuthor) {
1385     m_pAuthor->SetText(sName.c_str());
1386     RePosChildWnd();
1387   }
1388
1389   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
1390     pNotify->OnSetAuthorName(this);
1391   }
1392 }
1393
1394 CFX_WideString CPWL_Note::GetAuthorName() const {
1395   if (m_pAuthor)
1396     return m_pAuthor->GetText();
1397
1398   return L"";
1399 }
1400
1401 FX_BOOL CPWL_Note::OnMouseWheel(short zDelta,
1402                                 const CPDF_Point& point,
1403                                 FX_DWORD nFlag) {
1404   CPDF_Point ptScroll = m_pContents->GetScrollPos();
1405   CPDF_Rect rcScroll = m_pContents->GetScrollArea();
1406   CPDF_Rect rcContents = m_pContents->GetClientRect();
1407
1408   if (rcScroll.top - rcScroll.bottom > rcContents.Height()) {
1409     CPDF_Point ptNew = ptScroll;
1410
1411     if (zDelta > 0)
1412       ptNew.y += 30;
1413     else
1414       ptNew.y -= 30;
1415
1416     if (ptNew.y > rcScroll.top)
1417       ptNew.y = rcScroll.top;
1418     if (ptNew.y < rcScroll.bottom + rcContents.Height())
1419       ptNew.y = rcScroll.bottom + rcContents.Height();
1420     if (ptNew.y < rcScroll.bottom)
1421       ptNew.y = rcScroll.bottom;
1422
1423     if (ptNew.y != ptScroll.y) {
1424       m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1425       m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL,
1426                             (intptr_t)&ptNew.y);
1427       m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL,
1428                                (intptr_t)&ptNew.y);
1429
1430       return TRUE;
1431     }
1432   }
1433
1434   return FALSE;
1435 }
1436
1437 void CPWL_Note::OnNotify(CPWL_Wnd* pWnd,
1438                          FX_DWORD msg,
1439                          intptr_t wParam,
1440                          intptr_t lParam) {
1441   switch (msg) {
1442     case PNM_NOTEEDITCHANGED: {
1443       CPDF_Rect rcScroll = m_pContents->GetScrollArea();
1444
1445       PWL_SCROLL_INFO sInfo;
1446       sInfo.fContentMin = rcScroll.bottom;
1447       sInfo.fContentMax = rcScroll.top;
1448       sInfo.fPlateWidth = m_pContents->GetClientRect().Height();
1449       sInfo.fSmallStep = 13.0f;
1450       sInfo.fBigStep = sInfo.fPlateWidth;
1451
1452       if (FXSYS_memcmp(&m_OldScrollInfo, &sInfo, sizeof(PWL_SCROLL_INFO)) !=
1453           0) {
1454         FX_BOOL bScrollChanged = FALSE;
1455
1456         if (lParam < 3)  //·ÀÖ¹ËÀÑ­»· mantis:15759
1457         {
1458           bScrollChanged = ResetScrollBar();
1459           if (bScrollChanged) {
1460             lParam++;
1461             m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1462             OnNotify(this, PNM_NOTEEDITCHANGED, 0, lParam);
1463           }
1464         }
1465
1466         if (!bScrollChanged) {
1467           if (m_pContentsBar->IsVisible()) {
1468             m_pContentsBar->OnNotify(pWnd, PNM_SETSCROLLINFO, SBT_VSCROLL,
1469                                      (intptr_t)&sInfo);
1470             m_OldScrollInfo = sInfo;
1471
1472             CPDF_Point ptScroll = m_pContents->GetScrollPos();
1473             CPDF_Point ptOld = ptScroll;
1474
1475             if (ptScroll.y > sInfo.fContentMax)
1476               ptScroll.y = sInfo.fContentMax;
1477             if (ptScroll.y < sInfo.fContentMin + sInfo.fPlateWidth)
1478               ptScroll.y = sInfo.fContentMin + sInfo.fPlateWidth;
1479             if (ptScroll.y < sInfo.fContentMin)
1480               ptScroll.y = sInfo.fContentMin;
1481
1482             if (ptOld.y != ptScroll.y) {
1483               m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL,
1484                                        (intptr_t)&ptScroll.y);
1485               m_pContentsBar->InvalidateRect(NULL);
1486               m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL,
1487                                     (intptr_t)&ptScroll.y);
1488             }
1489           }
1490         }
1491       }
1492     }
1493
1494       m_pContents->InvalidateRect(NULL);
1495
1496       return;
1497     case PNM_SCROLLWINDOW:
1498       if (m_pContents)
1499         m_pContents->OnNotify(pWnd, msg, wParam, lParam);
1500       return;
1501     case PNM_SETSCROLLPOS:
1502       if (m_pContentsBar)
1503         m_pContentsBar->OnNotify(pWnd, PNM_SETSCROLLPOS, wParam, lParam);
1504       return;
1505   }
1506
1507   if (msg == PNM_SETCARETINFO && IsValid()) {
1508     if (PWL_CARET_INFO* pInfo = (PWL_CARET_INFO*)wParam) {
1509       if (m_pContents) {
1510         CPDF_Rect rcClient = m_pContents->GetClientRect();
1511         if (pInfo->ptHead.y > rcClient.top) {
1512           CPDF_Point pt = m_pContents->OutToIn(pInfo->ptHead);
1513           m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL,
1514                                 (intptr_t)&pt.y);
1515
1516           CPDF_Point ptScroll = m_pContents->GetScrollPos();
1517           m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL,
1518                                    (intptr_t)&ptScroll.y);
1519
1520           return;
1521         }
1522
1523         if (pInfo->ptFoot.y < rcClient.bottom) {
1524           CPDF_Point pt = m_pContents->OutToIn(pInfo->ptFoot);
1525           pt.y += rcClient.Height();
1526           m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL,
1527                                 (intptr_t)&pt.y);
1528
1529           CPDF_Point ptScroll = m_pContents->GetScrollPos();
1530           m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL,
1531                                    (intptr_t)&ptScroll.y);
1532
1533           return;
1534         }
1535       }
1536     }
1537   }
1538
1539   CPWL_NoteItem::OnNotify(pWnd, msg, wParam, lParam);
1540 }
1541
1542 void CPWL_Note::SetBkColor(const CPWL_Color& color) {
1543   CPWL_NoteItem::SetBkColor(color);
1544
1545   CPWL_Color sBK = color;
1546   CPWL_Color sTextColor;
1547   if (CPWL_Utils::IsBlackOrWhite(sBK))
1548     sTextColor = PWL_DEFAULT_WHITECOLOR;
1549   else
1550     sTextColor = PWL_DEFAULT_BLACKCOLOR;
1551
1552   if (m_pCloseBox)
1553     m_pCloseBox->SetTextColor(sTextColor);
1554   if (m_pAuthor)
1555     m_pAuthor->SetTextColor(sTextColor);
1556   if (m_pOptions)
1557     m_pOptions->SetTextColor(sTextColor);
1558   if (m_pLBBox)
1559     m_pLBBox->SetTextColor(sTextColor);
1560   if (m_pRBBox)
1561     m_pRBBox->SetTextColor(sTextColor);
1562 }
1563
1564 FX_BOOL CPWL_Note::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag) {
1565   if (m_pOptions->WndHitTest(m_pOptions->ParentToChild(point))) {
1566     if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
1567       int32_t x, y;
1568       PWLtoWnd(point, x, y);
1569       if (IFX_SystemHandler* pSH = GetSystemHandler())
1570         pSH->ClientToScreen(GetAttachedHWnd(), x, y);
1571       KillFocus();
1572       pNotify->OnPopupMenu(x, y);
1573
1574       return TRUE;
1575     }
1576   }
1577
1578   return CPWL_Wnd::OnLButtonDown(point, nFlag);
1579 }
1580
1581 FX_BOOL CPWL_Note::OnRButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
1582   return CPWL_Wnd::OnRButtonUp(point, nFlag);
1583 }
1584
1585 const CPWL_Note* CPWL_Note::GetNote() const {
1586   return this;
1587 }
1588
1589 IPWL_NoteNotify* CPWL_Note::GetNoteNotify() const {
1590   if (m_bEnalbleNotify)
1591     return m_pNoteNotify;
1592
1593   return NULL;
1594 }
1595
1596 void CPWL_Note::SetIconType(int32_t nType) {
1597   if (m_pIcon)
1598     m_pIcon->SetIconType(nType);
1599 }
1600
1601 void CPWL_Note::EnableModify(FX_BOOL bEnabled) {
1602   m_pContents->EnableModify(bEnabled);
1603 }
1604
1605 void CPWL_Note::EnableRead(FX_BOOL bEnabled) {
1606   m_pContents->EnableRead(bEnabled);
1607 }
1608
1609 CFX_WideString CPWL_Note::GetReplyString() const {
1610   return m_sReplyString;
1611 }
1612
1613 void CPWL_Note::SetReplyString(const CFX_WideString& string) {
1614   m_sReplyString = string;
1615 }