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