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