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 
CPWL_Note_Options()32 CPWL_Note_Options::CPWL_Note_Options() : m_pText(NULL) {}
33 
~CPWL_Note_Options()34 CPWL_Note_Options::~CPWL_Note_Options() {}
35 
SetTextColor(const CPWL_Color & color)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 
RePosChildWnd()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 
CreateChildWnd(const PWL_CREATEPARAM & cp)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 
SetText(const CFX_WideString & sText)66 void CPWL_Note_Options::SetText(const CFX_WideString& sText) {
67   m_pText->SetText(sText.c_str());
68 }
69 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
GetContentRect() const98 CPDF_Rect CPWL_Note_Options::GetContentRect() const {
99   CPDF_Rect rcText = m_pText->GetContentRect();
100   rcText.right += 15.0f;
101   return rcText;
102 }
103 
CPWL_Note_Edit()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 
~CPWL_Note_Edit()111 CPWL_Note_Edit::~CPWL_Note_Edit() {}
112 
RePosChildWnd()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 
SetText(const FX_WCHAR * csText)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 
OnSetFocus()128 void CPWL_Note_Edit::OnSetFocus() {
129   m_bEnableNotify = FALSE;
130   CPWL_Edit::OnSetFocus();
131   m_bEnableNotify = TRUE;
132 
133   EnableSpellCheck(TRUE);
134 }
135 
OnKillFocus()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 
OnNotify(CPWL_Wnd * pWnd,FX_DWORD msg,intptr_t wParam,intptr_t lParam)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 
GetItemHeight(FX_FLOAT fLimitWidth)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 
GetItemLeftMargin()221 FX_FLOAT CPWL_Note_Edit::GetItemLeftMargin() {
222   return POPUP_ITEM_TEXT_INDENT;
223 }
224 
GetItemRightMargin()225 FX_FLOAT CPWL_Note_Edit::GetItemRightMargin() {
226   return POPUP_ITEM_TEXT_INDENT;
227 }
228 
CPWL_Note_LBBox()229 CPWL_Note_LBBox::CPWL_Note_LBBox() {}
230 
~CPWL_Note_LBBox()231 CPWL_Note_LBBox::~CPWL_Note_LBBox() {}
232 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
CPWL_Note_RBBox()256 CPWL_Note_RBBox::CPWL_Note_RBBox() {}
257 
~CPWL_Note_RBBox()258 CPWL_Note_RBBox::~CPWL_Note_RBBox() {}
259 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
CPWL_Note_Icon()283 CPWL_Note_Icon::CPWL_Note_Icon() : m_nType(0) {}
284 
~CPWL_Note_Icon()285 CPWL_Note_Icon::~CPWL_Note_Icon() {}
286 
SetIconType(int32_t nType)287 void CPWL_Note_Icon::SetIconType(int32_t nType) {
288   m_nType = nType;
289 }
290 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
CPWL_Note_CloseBox()298 CPWL_Note_CloseBox::CPWL_Note_CloseBox() : m_bMouseDown(FALSE) {}
299 
~CPWL_Note_CloseBox()300 CPWL_Note_CloseBox::~CPWL_Note_CloseBox() {}
301 
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)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 
OnLButtonDown(const CPDF_Point & point,FX_DWORD nFlag)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 
OnLButtonUp(const CPDF_Point & point,FX_DWORD nFlag)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 
CPWL_Note_Contents()353 CPWL_Note_Contents::CPWL_Note_Contents() : m_pEdit(NULL) {}
354 
~CPWL_Note_Contents()355 CPWL_Note_Contents::~CPWL_Note_Contents() {}
356 
GetClassName() const357 CFX_ByteString CPWL_Note_Contents::GetClassName() const {
358   return "CPWL_Note_Contents";
359 }
360 
CreateChildWnd(const PWL_CREATEPARAM & cp)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 
SetText(const CFX_WideString & sText)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 
GetText() const382 CFX_WideString CPWL_Note_Contents::GetText() const {
383   if (m_pEdit)
384     return m_pEdit->GetText();
385 
386   return L"";
387 }
388 
CreateSubItem()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 
CountSubItems() const412 int32_t CPWL_Note_Contents::CountSubItems() const {
413   return m_aChildren.GetSize() - 1;
414 }
415 
GetSubItems(int32_t index) const416 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 
DeleteSubItem(IPWL_NoteItem * pNoteItem)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 
GetHitNoteItem(const CPDF_Point & point)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 
OnNotify(CPWL_Wnd * pWnd,FX_DWORD msg,intptr_t wParam,intptr_t lParam)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 
OnLButtonDown(const CPDF_Point & point,FX_DWORD nFlag)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 
SetEditFocus(FX_BOOL bLast)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 
GetEdit() const546 CPWL_Edit* CPWL_Note_Contents::GetEdit() const {
547   return m_pEdit;
548 }
549 
EnableModify(FX_BOOL bEnabled)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 
EnableRead(FX_BOOL bEnabled)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 
CPWL_NoteItem()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 
~CPWL_NoteItem()592 CPWL_NoteItem::~CPWL_NoteItem() {}
593 
GetClassName() const594 CFX_ByteString CPWL_NoteItem::GetClassName() const {
595   return "CPWL_NoteItem";
596 }
597 
CreateChildWnd(const PWL_CREATEPARAM & cp)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 
RePosChildWnd()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 
SetPrivateData(void * pData)670 void CPWL_NoteItem::SetPrivateData(void* pData) {
671   m_pPrivateData = pData;
672 }
673 
SetBkColor(const CPWL_Color & color)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 
SetSubjectName(const CFX_WideString & sName)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 
SetAuthorName(const CFX_WideString & sName)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 
ResetSubjectName(int32_t nItemIndex)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 
SetDateTime(FX_SYSTEMTIME time)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 
SetContents(const CFX_WideString & sContents)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 
GetParentNoteItem() const766 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 
GetParentItem() const777 IPWL_NoteItem* CPWL_NoteItem::GetParentItem() const {
778   return GetParentNoteItem();
779 }
780 
GetEdit() const781 CPWL_Edit* CPWL_NoteItem::GetEdit() const {
782   if (m_pContents)
783     return m_pContents->GetEdit();
784   return NULL;
785 }
786 
GetPrivateData() const787 void* CPWL_NoteItem::GetPrivateData() const {
788   return m_pPrivateData;
789 }
790 
GetAuthorName() const791 CFX_WideString CPWL_NoteItem::GetAuthorName() const {
792   return m_sAuthor;
793 }
794 
GetBkColor() const795 CPWL_Color CPWL_NoteItem::GetBkColor() const {
796   return GetBackgroundColor();
797 }
798 
GetContents() const799 CFX_WideString CPWL_NoteItem::GetContents() const {
800   if (m_pContents)
801     return m_pContents->GetText();
802 
803   return L"";
804 }
805 
GetDateTime() const806 FX_SYSTEMTIME CPWL_NoteItem::GetDateTime() const {
807   return m_dtNote;
808 }
809 
GetSubjectName() const810 CFX_WideString CPWL_NoteItem::GetSubjectName() const {
811   if (m_pSubject)
812     return m_pSubject->GetText();
813 
814   return L"";
815 }
816 
CreateNoteItem()817 CPWL_NoteItem* CPWL_NoteItem::CreateNoteItem() {
818   if (m_pContents)
819     return m_pContents->CreateSubItem();
820 
821   return NULL;
822 }
823 
CreateSubItem()824 IPWL_NoteItem* CPWL_NoteItem::CreateSubItem() {
825   return CreateNoteItem();
826 }
827 
CountSubItems() const828 int32_t CPWL_NoteItem::CountSubItems() const {
829   if (m_pContents)
830     return m_pContents->CountSubItems();
831 
832   return 0;
833 }
834 
GetSubItems(int32_t index) const835 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 
DeleteSubItem(IPWL_NoteItem * pNoteItem)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 
GetHitNoteItem(const CPDF_Point & point)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 
GetFocusedNoteItem() const868 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 
GetItemHeight(FX_FLOAT fLimitWidth)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 
GetItemLeftMargin()904 FX_FLOAT CPWL_NoteItem::GetItemLeftMargin() {
905   return POPUP_ITEM_SIDEMARGIN;
906 }
907 
GetItemRightMargin()908 FX_FLOAT CPWL_NoteItem::GetItemRightMargin() {
909   return POPUP_ITEM_SIDEMARGIN;
910 }
911 
OnLButtonDown(const CPDF_Point & point,FX_DWORD nFlag)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 
OnRButtonUp(const CPDF_Point & point,FX_DWORD nFlag)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 
OnNotify(CPWL_Wnd * pWnd,FX_DWORD msg,intptr_t wParam,intptr_t lParam)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 
PopupNoteItemMenu(const CPDF_Point & point)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 
GetNote() const977 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 
GetNoteNotify() const989 IPWL_NoteNotify* CPWL_NoteItem::GetNoteNotify() const {
990   if (const CPWL_Note* pNote = GetNote())
991     return pNote->GetNoteNotify();
992 
993   return NULL;
994 }
995 
OnCreateNoteItem()996 void CPWL_NoteItem::OnCreateNoteItem() {
997   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
998     pNotify->OnItemCreate(this);
999   }
1000 }
1001 
OnContentsValidate()1002 void CPWL_NoteItem::OnContentsValidate() {
1003   if (IPWL_NoteNotify* pNotify = GetNoteNotify()) {
1004     pNotify->OnSetContents(this);
1005   }
1006 }
1007 
SetNoteFocus(FX_BOOL bLast)1008 void CPWL_NoteItem::SetNoteFocus(FX_BOOL bLast) {
1009   m_pContents->SetEditFocus(bLast);
1010 }
1011 
EnableModify(FX_BOOL bEnabled)1012 void CPWL_NoteItem::EnableModify(FX_BOOL bEnabled) {
1013   m_pContents->EnableModify(bEnabled);
1014   m_bAllowModify = bEnabled;
1015 }
1016 
EnableRead(FX_BOOL bEnabled)1017 void CPWL_NoteItem::EnableRead(FX_BOOL bEnabled) {
1018   m_pContents->EnableRead(bEnabled);
1019 }
1020 
CPWL_Note(IPopup_Note * pPopupNote,IPWL_NoteNotify * pNoteNotify,IPWL_NoteHandler * pNoteHandler)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 
~CPWL_Note()1035 CPWL_Note::~CPWL_Note() {}
1036 
Reply()1037 IPWL_NoteItem* CPWL_Note::Reply() {
1038   return CreateNoteItem();
1039 }
1040 
EnableNotify(FX_BOOL bEnabled)1041 void CPWL_Note::EnableNotify(FX_BOOL bEnabled) {
1042   m_bEnableNotify = bEnabled;
1043 }
1044 
RePosChildWnd()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 
ResetScrollBar()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 
ScrollBarShouldVisible()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 
SetOptionsText(const CFX_WideString & sText)1100 void CPWL_Note::SetOptionsText(const CFX_WideString& sText) {
1101   if (m_pOptions)
1102     m_pOptions->SetText(sText);
1103 
1104   RePosNoteChildren();
1105 }
1106 
RePosNoteChildren()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 
CreateChildWnd(const PWL_CREATEPARAM & cp)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 
SetSubjectName(const CFX_WideString & sName)1276 void CPWL_Note::SetSubjectName(const CFX_WideString& sName) {
1277   CPWL_NoteItem::SetSubjectName(sName);
1278   RePosChildWnd();
1279 }
1280 
SetAuthorName(const CFX_WideString & sName)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 
GetAuthorName() const1292 CFX_WideString CPWL_Note::GetAuthorName() const {
1293   if (m_pAuthor)
1294     return m_pAuthor->GetText();
1295 
1296   return L"";
1297 }
1298 
OnMouseWheel(short zDelta,const CPDF_Point & point,FX_DWORD nFlag)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 
OnNotify(CPWL_Wnd * pWnd,FX_DWORD msg,intptr_t wParam,intptr_t lParam)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 
SetBkColor(const CPWL_Color & color)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 
OnLButtonDown(const CPDF_Point & point,FX_DWORD nFlag)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 
OnRButtonUp(const CPDF_Point & point,FX_DWORD nFlag)1478 FX_BOOL CPWL_Note::OnRButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
1479   return CPWL_Wnd::OnRButtonUp(point, nFlag);
1480 }
1481 
GetNote() const1482 const CPWL_Note* CPWL_Note::GetNote() const {
1483   return this;
1484 }
1485 
GetNoteNotify() const1486 IPWL_NoteNotify* CPWL_Note::GetNoteNotify() const {
1487   return m_bEnableNotify ? m_pNoteNotify : nullptr;
1488 }
1489 
SetIconType(int32_t nType)1490 void CPWL_Note::SetIconType(int32_t nType) {
1491   if (m_pIcon)
1492     m_pIcon->SetIconType(nType);
1493 }
1494 
EnableModify(FX_BOOL bEnabled)1495 void CPWL_Note::EnableModify(FX_BOOL bEnabled) {
1496   m_pContents->EnableModify(bEnabled);
1497 }
1498 
EnableRead(FX_BOOL bEnabled)1499 void CPWL_Note::EnableRead(FX_BOOL bEnabled) {
1500   m_pContents->EnableRead(bEnabled);
1501 }
1502 
GetReplyString() const1503 CFX_WideString CPWL_Note::GetReplyString() const {
1504   return m_sReplyString;
1505 }
1506 
SetReplyString(const CFX_WideString & string)1507 void CPWL_Note::SetReplyString(const CFX_WideString& string) {
1508   m_sReplyString = string;
1509 }
1510