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