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
36CPWL_Note_Options::CPWL_Note_Options() : m_pText(NULL)
37{
38}
39
40CPWL_Note_Options::~CPWL_Note_Options()
41{
42}
43
44void 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
52void 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
74void 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
83void CPWL_Note_Options::SetText(const CFX_WideString& sText)
84{
85	m_pText->SetText(sText.c_str());
86}
87
88void 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
114CPDF_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
125CPWL_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
133CPWL_Note_Edit::~CPWL_Note_Edit()
134{
135}
136
137void 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
146void 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
154void CPWL_Note_Edit::OnSetFocus()
155{
156	m_bEnableNotify = FALSE;
157	CPWL_Edit::OnSetFocus();
158	m_bEnableNotify = TRUE;
159
160	this->EnableSpellCheck(TRUE);
161}
162
163void 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
182void 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
235FX_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
265FX_FLOAT CPWL_Note_Edit::GetItemLeftMargin()
266{
267	return POPUP_ITEM_TEXT_INDENT;
268}
269
270FX_FLOAT CPWL_Note_Edit::GetItemRightMargin()
271{
272	return POPUP_ITEM_TEXT_INDENT;
273}
274
275/* -------------------------------- CPWL_Note_LBBox --------------------------------*/
276
277CPWL_Note_LBBox::CPWL_Note_LBBox()
278{
279}
280
281CPWL_Note_LBBox::~CPWL_Note_LBBox()
282{
283}
284
285void 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
306CPWL_Note_RBBox::CPWL_Note_RBBox()
307{
308}
309
310CPWL_Note_RBBox::~CPWL_Note_RBBox()
311{
312}
313
314void 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
335CPWL_Note_Icon::CPWL_Note_Icon() : m_nType(0)
336{
337}
338
339CPWL_Note_Icon::~CPWL_Note_Icon()
340{
341}
342
343void CPWL_Note_Icon::SetIconType(FX_INT32 nType)
344{
345	m_nType = nType;
346}
347
348void 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
356CPWL_Note_CloseBox::CPWL_Note_CloseBox() : m_bMouseDown(FALSE)
357{
358}
359
360CPWL_Note_CloseBox::~CPWL_Note_CloseBox()
361{
362}
363
364void 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
394FX_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
404FX_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
416CPWL_Note_Contents::CPWL_Note_Contents() : m_pEdit(NULL)
417{
418}
419
420CPWL_Note_Contents::~CPWL_Note_Contents()
421{
422}
423
424CFX_ByteString CPWL_Note_Contents::GetClassName() const
425{
426	return "CPWL_Note_Contents";
427}
428
429void 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
441void CPWL_Note_Contents::SetText(const CFX_WideString& sText)
442{
443	if (m_pEdit)
444	{
445		m_pEdit->EnableNotify(FALSE);
446		m_pEdit->SetText(sText.c_str());
447		m_pEdit->EnableNotify(TRUE);
448		OnNotify(m_pEdit, PNM_NOTEEDITCHANGED, 0, 0);
449	}
450}
451
452CFX_WideString CPWL_Note_Contents::GetText() const
453{
454	if (m_pEdit)
455		return m_pEdit->GetText();
456
457	return L"";
458}
459
460CPWL_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
484FX_INT32 CPWL_Note_Contents::CountSubItems() const
485{
486	return m_aChildren.GetSize() - 1;
487}
488
489IPWL_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
503void 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
530IPWL_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
549void 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
615FX_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
627void 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
636CPWL_Edit* CPWL_Note_Contents::GetEdit() const
637{
638	return m_pEdit;
639}
640
641void 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
661void 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
683CPWL_NoteItem::CPWL_NoteItem() :
684	m_pSubject(NULL),
685	m_pDateTime(NULL),
686	m_pContents(NULL),
687	m_pPrivateData(NULL),
688	m_sAuthor(L""),
689	m_fOldItemHeight(0.0f),
690	m_bSizeChanged(FALSE),
691	m_bAllowModify(TRUE)
692{
693}
694
695CPWL_NoteItem::~CPWL_NoteItem()
696{
697}
698
699CFX_ByteString CPWL_NoteItem::GetClassName() const
700{
701	return "CPWL_NoteItem";
702}
703
704void 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
739void 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
779void CPWL_NoteItem::SetPrivateData(void* pData)
780{
781	m_pPrivateData = pData;
782}
783
784void 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
810void CPWL_NoteItem::SetSubjectName(const CFX_WideString& sName)
811{
812	if (m_pSubject)
813	{
814		m_pSubject->SetText(sName.c_str());
815	}
816
817	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
818	{
819		pNotify->OnSetSubjectName(this);
820	}
821}
822
823void 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
834void 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().c_str(), nItemIndex);
852
853	if (!m_sAuthor.IsEmpty())
854	{
855		sSubject += L" - ";
856		sSubject += m_sAuthor;
857	}
858	this->SetSubjectName(sSubject);
859	this->RePosChildWnd();
860}
861
862void CPWL_NoteItem::SetDateTime(FX_SYSTEMTIME time)
863{
864	m_dtNote = time;
865
866	CFX_WideString swTime;
867	swTime.Format(L"%04d-%02d-%02d %02d:%02d:%02d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond);
868	if (m_pDateTime)
869	{
870		m_pDateTime->SetText(swTime.c_str());
871	}
872
873	this->RePosChildWnd();
874
875	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
876	{
877		pNotify->OnSetDateTime(this);
878	}
879}
880
881void CPWL_NoteItem::SetContents(const CFX_WideString& sContents)
882{
883	if (m_pContents)
884	{
885		m_pContents->SetText(sContents);
886	}
887
888	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
889	{
890		pNotify->OnSetContents(this);
891	}
892}
893
894CPWL_NoteItem* CPWL_NoteItem::GetParentNoteItem() const
895{
896	if (CPWL_Wnd* pParent = this->GetParentWindow())
897	{
898		if (CPWL_Wnd* pGrand = pParent->GetParentWindow())
899		{
900			ASSERT(pGrand->GetClassName() == "CPWL_NoteItem");
901			return (CPWL_NoteItem*)pGrand;
902		}
903	}
904
905	return NULL;
906}
907
908IPWL_NoteItem* CPWL_NoteItem::GetParentItem() const
909{
910	return GetParentNoteItem();
911}
912
913CPWL_Edit* CPWL_NoteItem::GetEdit() const
914{
915	if (m_pContents)
916		return m_pContents->GetEdit();
917	return NULL;
918}
919
920void* CPWL_NoteItem::GetPrivateData() const
921{
922	return m_pPrivateData;
923}
924
925CFX_WideString CPWL_NoteItem::GetAuthorName() const
926{
927	return m_sAuthor;
928}
929
930CPWL_Color CPWL_NoteItem::GetBkColor() const
931{
932	return this->GetBackgroundColor();
933}
934
935CFX_WideString CPWL_NoteItem::GetContents() const
936{
937	if (m_pContents)
938		return m_pContents->GetText();
939
940	return L"";
941}
942
943FX_SYSTEMTIME CPWL_NoteItem::GetDateTime() const
944{
945	return m_dtNote;
946}
947
948CFX_WideString CPWL_NoteItem::GetSubjectName() const
949{
950	if (m_pSubject)
951		return m_pSubject->GetText();
952
953	return L"";
954}
955
956CPWL_NoteItem* CPWL_NoteItem::CreateNoteItem()
957{
958	if (m_pContents)
959		return m_pContents->CreateSubItem();
960
961	return NULL;
962}
963
964IPWL_NoteItem* CPWL_NoteItem::CreateSubItem()
965{
966	return CreateNoteItem();
967}
968
969FX_INT32 CPWL_NoteItem::CountSubItems() const
970{
971	if (m_pContents)
972		return m_pContents->CountSubItems();
973
974	return 0;
975}
976
977IPWL_NoteItem* CPWL_NoteItem::GetSubItems(FX_INT32 index) const
978{
979	if (m_pContents)
980		return m_pContents->GetSubItems(index);
981
982	return NULL;
983}
984
985void CPWL_NoteItem::DeleteSubItem(IPWL_NoteItem* pNoteItem)
986{
987	this->KillFocus();
988
989	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
990	{
991		pNotify->OnItemDelete(pNoteItem);
992	}
993
994	if (m_pContents)
995		m_pContents->DeleteSubItem(pNoteItem);
996}
997
998IPWL_NoteItem* CPWL_NoteItem::GetHitNoteItem(const CPDF_Point& point)
999{
1000	CPDF_Point pt = this->ParentToChild(point);
1001
1002	if (this->WndHitTest(pt))
1003	{
1004		if (m_pContents)
1005		{
1006			if (IPWL_NoteItem* pNoteItem = m_pContents->GetHitNoteItem(pt))
1007				return pNoteItem;
1008		}
1009
1010		return this;
1011	}
1012
1013	return NULL;
1014}
1015
1016IPWL_NoteItem* CPWL_NoteItem::GetFocusedNoteItem() const
1017{
1018	if (const CPWL_Wnd* pWnd = this->GetFocused())
1019	{
1020		if (pWnd->GetClassName() == "CPWL_Edit")
1021		{
1022			if (CPWL_Wnd* pParent = pWnd->GetParentWindow())
1023			{
1024				ASSERT(pParent->GetClassName() == "CPWL_Note_Contents");
1025
1026				if (CPWL_Wnd* pGrand = pParent->GetParentWindow())
1027				{
1028					ASSERT(pGrand->GetClassName() == "CPWL_NoteItem");
1029					return (CPWL_NoteItem*)pGrand;
1030				}
1031			}
1032		}
1033	}
1034
1035	return NULL;
1036}
1037
1038FX_FLOAT CPWL_NoteItem::GetItemHeight(FX_FLOAT fLimitWidth)
1039{
1040	if (fLimitWidth > 0)
1041	{
1042		if (!m_bSizeChanged)
1043			return m_fOldItemHeight;
1044
1045		m_bSizeChanged = FALSE;
1046
1047		ASSERT(m_pSubject != NULL);
1048		ASSERT(m_pDateTime != NULL);
1049		ASSERT(m_pContents != NULL);
1050
1051		FX_FLOAT fRet = m_pDateTime->GetContentRect().Height();
1052		FX_FLOAT fBorderWidth = (FX_FLOAT)this->GetBorderWidth();
1053		if (fLimitWidth > fBorderWidth * 2)
1054			fRet += m_pContents->GetContentsHeight(fLimitWidth - fBorderWidth * 2);
1055		fRet += POPUP_ITEM_HEAD_BOTTOM + POPUP_ITEM_BOTTOMWIDTH + fBorderWidth * 2;
1056
1057		return m_fOldItemHeight = fRet;
1058	}
1059
1060	return 0;
1061}
1062
1063FX_FLOAT CPWL_NoteItem::GetItemLeftMargin()
1064{
1065	return POPUP_ITEM_SIDEMARGIN;
1066}
1067
1068FX_FLOAT CPWL_NoteItem::GetItemRightMargin()
1069{
1070	return POPUP_ITEM_SIDEMARGIN;
1071}
1072
1073FX_BOOL	CPWL_NoteItem::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag)
1074{
1075	if (!m_pContents->WndHitTest(m_pContents->ParentToChild(point)))
1076	{
1077		SetNoteFocus(FALSE);
1078	}
1079
1080	CPWL_Wnd::OnLButtonDown(point,nFlag);
1081
1082	return TRUE;
1083}
1084
1085FX_BOOL	CPWL_NoteItem::OnRButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
1086{
1087	if (!m_pContents->WndHitTest(m_pContents->ParentToChild(point)))
1088	{
1089		SetNoteFocus(FALSE);
1090		PopupNoteItemMenu(point);
1091
1092		return TRUE;
1093	}
1094
1095	return CPWL_Wnd::OnRButtonUp(point,nFlag);
1096}
1097
1098void CPWL_NoteItem::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam)
1099{
1100	switch (msg)
1101	{
1102	case PNM_NOTEEDITCHANGED:
1103		m_bSizeChanged = TRUE;
1104
1105		if (CPWL_Wnd* pParent = this->GetParentWindow())
1106		{
1107			pParent->OnNotify(this, PNM_NOTEEDITCHANGED, 0, 0);
1108		}
1109		return;
1110	case PNM_SETCARETINFO:
1111		if (PWL_CARET_INFO * pInfo = (PWL_CARET_INFO*)wParam)
1112		{
1113			PWL_CARET_INFO newInfo = *pInfo;
1114			newInfo.bVisible = TRUE;
1115			newInfo.ptHead = this->ChildToParent(pInfo->ptHead);
1116			newInfo.ptFoot = this->ChildToParent(pInfo->ptFoot);
1117
1118			if (CPWL_Wnd * pParent = this->GetParentWindow())
1119			{
1120				pParent->OnNotify(this, PNM_SETCARETINFO, (FX_INTPTR)&newInfo, 0);
1121			}
1122		}
1123		return;
1124	case PNM_NOTERESET:
1125		m_bSizeChanged = TRUE;
1126		m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1127
1128		return;
1129	}
1130
1131	CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
1132}
1133
1134void CPWL_NoteItem::PopupNoteItemMenu(const CPDF_Point& point)
1135{
1136	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
1137	{
1138		FX_INT32 x,y;
1139		PWLtoWnd(point, x, y);
1140		if (IFX_SystemHandler* pSH = GetSystemHandler())
1141			pSH->ClientToScreen(GetAttachedHWnd(), x, y);
1142		pNotify->OnPopupMenu(this, x, y);
1143	}
1144}
1145
1146const CPWL_Note* CPWL_NoteItem::GetNote() const
1147{
1148	if (const CPWL_Wnd* pRoot = this->GetRootWnd())
1149	{
1150		ASSERT(pRoot->GetClassName() == "CPWL_NoteItem");
1151		CPWL_NoteItem* pNoteItem = (CPWL_NoteItem*)pRoot;
1152		if (pNoteItem->IsTopItem())
1153		{
1154			return (CPWL_Note*)pNoteItem;
1155		}
1156	}
1157
1158	return NULL;
1159}
1160
1161IPWL_NoteNotify* CPWL_NoteItem::GetNoteNotify() const
1162{
1163	if (const CPWL_Note* pNote = GetNote())
1164		return pNote->GetNoteNotify();
1165
1166	return NULL;
1167}
1168
1169void CPWL_NoteItem::OnCreateNoteItem()
1170{
1171	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
1172	{
1173		pNotify->OnItemCreate(this);
1174	}
1175}
1176
1177void CPWL_NoteItem::OnContentsValidate()
1178{
1179	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
1180	{
1181		pNotify->OnSetContents(this);
1182	}
1183}
1184
1185void CPWL_NoteItem::SetNoteFocus(FX_BOOL bLast)
1186{
1187	m_pContents->SetEditFocus(bLast);
1188}
1189
1190void CPWL_NoteItem::EnableModify(FX_BOOL bEnabled)
1191{
1192	m_pContents->EnableModify(bEnabled);
1193	m_bAllowModify = bEnabled;
1194}
1195
1196void CPWL_NoteItem::EnableRead(FX_BOOL bEnabled)
1197{
1198	m_pContents->EnableRead(bEnabled);
1199}
1200
1201/* ---------------------------------- CPWL_Note ---------------------------------- */
1202
1203CPWL_Note::CPWL_Note(IPopup_Note* pPopupNote, IPWL_NoteNotify* pNoteNotify, IPWL_NoteHandler* pNoteHandler) :
1204	m_pAuthor(NULL),
1205	m_pIcon(NULL),
1206	m_pCloseBox(NULL),
1207	m_pLBBox(NULL),
1208	m_pRBBox(NULL),
1209	m_pContentsBar(NULL),
1210	m_pOptions(NULL),
1211	m_pNoteNotify(pNoteNotify),
1212	m_bResizing(FALSE),
1213	m_rcCaption(0,0,0,0),
1214	m_bEnalbleNotify(TRUE),
1215	m_pPopupNote(pPopupNote)
1216{
1217}
1218
1219CPWL_Note::~CPWL_Note()
1220{
1221}
1222
1223IPWL_NoteItem* CPWL_Note::Reply()
1224{
1225	return CreateNoteItem();
1226}
1227
1228void CPWL_Note::EnableNotify(FX_BOOL bEnabled)
1229{
1230	m_bEnalbleNotify = bEnabled;
1231}
1232
1233void CPWL_Note::RePosChildWnd()
1234{
1235	RePosNoteChildren();
1236	m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1237	ResetScrollBar();
1238	m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1239	this->OnNotify(this, PNM_NOTEEDITCHANGED, 0, 0);
1240	//ͬ��
1241	if (const CPWL_Wnd* pWnd = this->GetFocused())
1242	{
1243		if (pWnd->GetClassName() == "CPWL_Edit")
1244		{
1245			CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
1246			pEdit->SetCaret(pEdit->GetCaret());
1247		}
1248	}
1249	//CPDF_Point ptNew = m_pContents->GetScrollPos();
1250	//m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptNew.y);
1251}
1252
1253FX_BOOL CPWL_Note::ResetScrollBar()
1254{
1255	FX_BOOL bScrollChanged = FALSE;
1256
1257	if (ScrollBarShouldVisible())
1258	{
1259		if (!m_pContentsBar->IsVisible())
1260		{
1261			m_pContentsBar->SetVisible(TRUE);
1262			if (m_pContentsBar->IsVisible())
1263			{
1264				m_pContentsBar->InvalidateRect(NULL);
1265				bScrollChanged = TRUE;
1266			}
1267		}
1268	}
1269	else
1270	{
1271		if (m_pContentsBar->IsVisible())
1272		{
1273			m_pContentsBar->SetVisible(FALSE);
1274			m_pContentsBar->InvalidateRect(NULL);
1275
1276			bScrollChanged = TRUE;
1277		}
1278	}
1279
1280	if (bScrollChanged)
1281	{
1282		CPDF_Rect rcNote = this->GetClientRect();
1283		CPDF_Rect rcContents = m_pContents->GetWindowRect();
1284		rcContents.right = rcNote.right - 3.0f;
1285		if (m_pContentsBar->IsVisible())
1286			rcContents.right -= PWL_SCROLLBAR_WIDTH;
1287		m_pContents->Move(rcContents, TRUE, TRUE);
1288		m_pContents->SetScrollPos(CPDF_Point(0.0f,0.0f));
1289		m_pContents->InvalidateRect(NULL);
1290	}
1291
1292	return bScrollChanged;
1293}
1294
1295FX_BOOL CPWL_Note::ScrollBarShouldVisible()
1296{
1297	CPDF_Rect rcContentsFact = m_pContents->GetScrollArea();
1298	CPDF_Rect rcContentsClient = m_pContents->GetClientRect();
1299
1300	return rcContentsFact.Height() > rcContentsClient.Height();
1301}
1302
1303void CPWL_Note::SetOptionsText(const CFX_WideString& sText)
1304{
1305	if (m_pOptions)
1306		m_pOptions->SetText(sText);
1307
1308	RePosNoteChildren();
1309}
1310
1311void CPWL_Note::RePosNoteChildren()
1312{
1313	if (m_bResizing) return;
1314
1315	m_bResizing = TRUE;
1316
1317	if (this->IsValid())
1318	{
1319		ASSERT(m_pSubject != NULL);
1320		ASSERT(m_pDateTime != NULL);
1321		ASSERT(m_pContents != NULL);
1322		ASSERT(m_pAuthor != NULL);
1323		ASSERT(m_pCloseBox != NULL);
1324		ASSERT(m_pIcon != NULL);
1325		ASSERT(m_pLBBox != NULL);
1326		ASSERT(m_pRBBox != NULL);
1327		ASSERT(m_pContentsBar != NULL);
1328		ASSERT(m_pOptions != NULL);
1329
1330		CPDF_Rect rcClient = GetClientRect();
1331
1332		CPDF_Rect rcIcon = rcClient;
1333		rcIcon.top -= 2.0f;
1334		rcIcon.right = rcIcon.left + 14.0f;
1335		rcIcon.bottom = rcIcon.top - 14.0f;
1336		rcIcon.Normalize();
1337		m_pIcon->Move(rcIcon, TRUE, FALSE);
1338		m_pIcon->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcIcon));
1339
1340		CPDF_Rect rcCloseBox = rcClient;
1341		rcCloseBox.right -= 1.0f;
1342		rcCloseBox.top -= 1.0f;
1343		rcCloseBox.left = rcCloseBox.right - 14.0f;
1344		rcCloseBox.bottom = rcCloseBox.top - 14.0f;
1345		rcCloseBox.Normalize();
1346		m_pCloseBox->Move(rcCloseBox, TRUE, FALSE);
1347		m_pCloseBox->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcCloseBox));
1348
1349		CPDF_Rect rcDate = rcClient;
1350		rcDate.right = rcCloseBox.left - POPUP_ITEM_TEXT_INDENT;
1351		rcDate.left = PWL_MAX(rcDate.right - m_pDateTime->GetContentRect().Width() - 1.0f, rcIcon.right + 1.0f);
1352		rcDate.top = rcClient.top - 2.0f;
1353		rcDate.bottom = rcDate.top - m_pDateTime->GetContentRect().Height();
1354		rcDate.Normalize();
1355		m_pDateTime->Move(rcDate, TRUE, FALSE);
1356		m_pDateTime->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcDate));
1357
1358		CPDF_Rect rcSubject = rcClient;
1359		rcSubject.top = rcClient.top - 2.0f;
1360		rcSubject.left = rcIcon.right + POPUP_ITEM_TEXT_INDENT;
1361		rcSubject.right = PWL_MIN(rcSubject.left + m_pSubject->GetContentRect().Width() + 1.0f, rcDate.left - 1.0f);
1362		rcSubject.bottom = rcSubject.top - m_pSubject->GetContentRect().Height();
1363		rcSubject.Normalize();
1364		m_pSubject->Move(rcSubject, TRUE, FALSE);
1365		m_pSubject->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcSubject));
1366
1367		CPDF_Rect rcOptions = rcClient;
1368		rcOptions.left = PWL_MAX(rcOptions.right - m_pOptions->GetContentRect().Width(), rcIcon.right + 1.0f);
1369		rcOptions.top = rcSubject.bottom - 4.0f;
1370		rcOptions.bottom = rcOptions.top - m_pOptions->GetContentRect().Height();
1371		rcOptions.Normalize();
1372		m_pOptions->Move(rcOptions, TRUE, FALSE);
1373		m_pOptions->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcOptions));
1374
1375		CPDF_Rect rcAuthor = rcClient;
1376		rcAuthor.top = rcSubject.bottom - 4.0f;
1377		rcAuthor.left = rcSubject.left;
1378		rcAuthor.right = PWL_MIN(rcSubject.left + m_pAuthor->GetContentRect().Width() + 1.0f, rcOptions.left - 1.0f);
1379		rcAuthor.bottom = rcAuthor.top - m_pAuthor->GetContentRect().Height();
1380		rcAuthor.Normalize();
1381		m_pAuthor->Move(rcAuthor, TRUE, FALSE);
1382		m_pAuthor->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcAuthor));
1383
1384		CPDF_Rect rcLBBox = rcClient;
1385		rcLBBox.top = rcLBBox.bottom + 7.0f;
1386		rcLBBox.right = rcLBBox.left + 7.0f;
1387		rcLBBox.Normalize();
1388		m_pLBBox->Move(rcLBBox, TRUE, FALSE);
1389		m_pLBBox->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcLBBox));
1390
1391		CPDF_Rect rcRBBox = rcClient;
1392		rcRBBox.top = rcRBBox.bottom + 7.0f;
1393		rcRBBox.left = rcRBBox.right - 7.0f;
1394		rcRBBox.Normalize();
1395		m_pRBBox->Move(rcRBBox, TRUE, FALSE);
1396		m_pRBBox->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcRBBox));
1397
1398		CPDF_Rect rcContents = rcClient;
1399		rcContents.top = rcAuthor.bottom - POPUP_ITEM_HEAD_BOTTOM;
1400		rcContents.left += 3.0f;
1401		rcContents.right -= 3.0f;
1402		if (m_pContentsBar->IsVisible())
1403			rcContents.right -= PWL_SCROLLBAR_WIDTH;
1404		rcContents.bottom += 14.0f;
1405		rcContents.Normalize();
1406		m_pContents->Move(rcContents, FALSE, FALSE);
1407		m_pContents->SetVisible(CPWL_Utils::ContainsRect(rcClient, rcContents));
1408
1409		CPDF_Rect rcContentsBar = rcContents;
1410		rcContentsBar.right = rcClient.right - 3.0f;
1411		rcContentsBar.left = rcContentsBar.right - PWL_SCROLLBAR_WIDTH;
1412		rcContentsBar.Normalize();
1413		m_pContentsBar->Move(rcContentsBar, TRUE, FALSE);
1414
1415		m_rcCaption = rcClient;
1416		m_rcCaption.bottom = rcContents.top;
1417	}
1418
1419	m_bResizing = FALSE;
1420}
1421
1422//0-normal / 1-caption / 2-leftbottom corner / 3-rightbottom corner / 4-close / 5-options
1423FX_INT32 CPWL_Note::NoteHitTest(const CPDF_Point& point) const
1424{
1425	ASSERT(m_pSubject != NULL);
1426	ASSERT(m_pDateTime != NULL);
1427	ASSERT(m_pContents != NULL);
1428	ASSERT(m_pAuthor != NULL);
1429	ASSERT(m_pIcon != NULL);
1430	ASSERT(m_pContentsBar != NULL);
1431
1432	ASSERT(m_pCloseBox != NULL);
1433	ASSERT(m_pLBBox != NULL);
1434	ASSERT(m_pRBBox != NULL);
1435	ASSERT(m_pOptions != NULL);
1436
1437	GetClientRect();
1438
1439	if (m_pSubject->WndHitTest(m_pSubject->ParentToChild(point))) return 1;
1440	if (m_pDateTime->WndHitTest(m_pDateTime->ParentToChild(point))) return 1;
1441	if (m_pAuthor->WndHitTest(m_pAuthor->ParentToChild(point))) return 1;
1442	if (m_pIcon->WndHitTest(m_pIcon->ParentToChild(point))) return 1;
1443
1444	if (m_pContents->WndHitTest(m_pContents->ParentToChild(point))) return 0;
1445	if (m_pContentsBar->WndHitTest(m_pContentsBar->ParentToChild(point))) return 0;
1446
1447	if (m_pCloseBox->WndHitTest(m_pCloseBox->ParentToChild(point))) return 4;
1448	if (m_pLBBox->WndHitTest(m_pLBBox->ParentToChild(point))) return 2;
1449	if (m_pRBBox->WndHitTest(m_pRBBox->ParentToChild(point))) return 3;
1450	if (m_pOptions->WndHitTest(m_pOptions->ParentToChild(point))) return 5;
1451
1452	return 1;
1453}
1454
1455void CPWL_Note::CreateChildWnd(const PWL_CREATEPARAM & cp)
1456{
1457	CPWL_NoteItem::CreateChildWnd(cp);
1458
1459	CPWL_Color sTextColor;
1460
1461	if (CPWL_Utils::IsBlackOrWhite(this->GetBackgroundColor()))
1462		sTextColor = PWL_DEFAULT_WHITECOLOR;
1463	else
1464		sTextColor = PWL_DEFAULT_BLACKCOLOR;
1465
1466	m_pAuthor = new CPWL_Label;
1467	PWL_CREATEPARAM acp = cp;
1468	acp.pParentWnd = this;
1469	acp.dwFlags = PWS_VISIBLE | PWS_CHILD | PES_LEFT | PES_TOP;
1470	acp.sTextColor = sTextColor;
1471	m_pAuthor->Create(acp);
1472
1473	m_pCloseBox = new CPWL_Note_CloseBox;
1474	PWL_CREATEPARAM ccp = cp;
1475	ccp.pParentWnd = this;
1476	ccp.dwBorderWidth = 2;
1477	ccp.nBorderStyle = PBS_BEVELED;
1478	ccp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER;
1479	ccp.sTextColor = sTextColor;
1480	m_pCloseBox->Create(ccp);
1481
1482	m_pIcon = new CPWL_Note_Icon;
1483	PWL_CREATEPARAM icp = cp;
1484	icp.pParentWnd = this;
1485	icp.dwFlags = PWS_VISIBLE | PWS_CHILD;
1486	m_pIcon->Create(icp);
1487
1488	m_pOptions = new CPWL_Note_Options;
1489	PWL_CREATEPARAM ocp = cp;
1490	ocp.pParentWnd = this;
1491	ocp.dwFlags = PWS_CHILD | PWS_VISIBLE;
1492	ocp.sTextColor = sTextColor;
1493	m_pOptions->Create(ocp);
1494
1495	m_pLBBox = new CPWL_Note_LBBox;
1496	PWL_CREATEPARAM lcp = cp;
1497	lcp.pParentWnd = this;
1498	lcp.dwFlags = PWS_VISIBLE | PWS_CHILD;
1499	lcp.eCursorType = FXCT_NESW;
1500	lcp.sTextColor = sTextColor;
1501	m_pLBBox->Create(lcp);
1502
1503	m_pRBBox = new CPWL_Note_RBBox;
1504	PWL_CREATEPARAM rcp = cp;
1505	rcp.pParentWnd = this;
1506	rcp.dwFlags = PWS_VISIBLE | PWS_CHILD;
1507	rcp.eCursorType = FXCT_NWSE;
1508	rcp.sTextColor = sTextColor;
1509	m_pRBBox->Create(rcp);
1510
1511	m_pContentsBar = new CPWL_ScrollBar(SBT_VSCROLL);
1512	PWL_CREATEPARAM scp = cp;
1513	scp.pParentWnd = this;
1514	scp.sBackgroundColor = CPWL_Color(COLORTYPE_RGB, 240/255.0f, 240/255.0f, 240/255.0f);
1515	scp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_BACKGROUND;
1516	m_pContentsBar->Create(scp);
1517	m_pContentsBar->SetNotifyForever(TRUE);
1518}
1519
1520void CPWL_Note::SetSubjectName(const CFX_WideString& sName)
1521{
1522	CPWL_NoteItem::SetSubjectName(sName);
1523	RePosChildWnd();
1524}
1525
1526void CPWL_Note::SetAuthorName(const CFX_WideString& sName)
1527{
1528	if (m_pAuthor)
1529	{
1530		m_pAuthor->SetText(sName.c_str());
1531		RePosChildWnd();
1532	}
1533
1534	if (IPWL_NoteNotify* pNotify = GetNoteNotify())
1535	{
1536		pNotify->OnSetAuthorName(this);
1537	}
1538}
1539
1540CFX_WideString CPWL_Note::GetAuthorName() const
1541{
1542	if (m_pAuthor)
1543		return m_pAuthor->GetText();
1544
1545	return L"";
1546}
1547
1548FX_BOOL CPWL_Note::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)
1549{
1550	CPDF_Point ptScroll = m_pContents->GetScrollPos();
1551	CPDF_Rect rcScroll = m_pContents->GetScrollArea();
1552	CPDF_Rect rcContents = m_pContents->GetClientRect();
1553
1554	if (rcScroll.top - rcScroll.bottom > rcContents.Height())
1555	{
1556		CPDF_Point ptNew = ptScroll;
1557
1558		if (zDelta > 0)
1559			ptNew.y += 30;
1560		else
1561			ptNew.y -= 30;
1562
1563		if (ptNew.y > rcScroll.top)
1564			ptNew.y = rcScroll.top;
1565		if (ptNew.y < rcScroll.bottom + rcContents.Height())
1566			ptNew.y = rcScroll.bottom + rcContents.Height();
1567		if (ptNew.y < rcScroll.bottom)
1568			ptNew.y = rcScroll.bottom;
1569
1570		if (ptNew.y != ptScroll.y)
1571		{
1572			m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1573			m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL, (FX_INTPTR)&ptNew.y);
1574			m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptNew.y);
1575
1576			return TRUE;
1577		}
1578	}
1579
1580	return FALSE;
1581}
1582
1583void CPWL_Note::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam)
1584{
1585	switch (msg)
1586	{
1587	case PNM_NOTEEDITCHANGED:
1588		{
1589			CPDF_Rect rcScroll = m_pContents->GetScrollArea();
1590
1591
1592			PWL_SCROLL_INFO sInfo;
1593			sInfo.fContentMin = rcScroll.bottom;
1594			sInfo.fContentMax = rcScroll.top;
1595			sInfo.fPlateWidth = m_pContents->GetClientRect().Height();
1596			sInfo.fSmallStep = 13.0f;
1597			sInfo.fBigStep = sInfo.fPlateWidth;
1598
1599			if (FXSYS_memcmp(&m_OldScrollInfo, &sInfo, sizeof(PWL_SCROLL_INFO)) != 0)
1600			{
1601				FX_BOOL bScrollChanged = FALSE;
1602
1603				if (lParam < 3) //��ֹ��ѭ�� mantis:15759
1604				{
1605					bScrollChanged = ResetScrollBar();
1606					if (bScrollChanged)
1607					{
1608						lParam++;
1609						m_pContents->OnNotify(this, PNM_NOTERESET, 0, 0);
1610						this->OnNotify(this, PNM_NOTEEDITCHANGED, 0, lParam);
1611					}
1612				}
1613
1614				if (!bScrollChanged)
1615				{
1616					if (m_pContentsBar->IsVisible())
1617					{
1618						m_pContentsBar->OnNotify(pWnd, PNM_SETSCROLLINFO, SBT_VSCROLL, (FX_INTPTR)&sInfo);
1619						m_OldScrollInfo = sInfo;
1620
1621						CPDF_Point ptScroll = m_pContents->GetScrollPos();
1622						CPDF_Point ptOld = ptScroll;
1623
1624						if (ptScroll.y > sInfo.fContentMax)
1625							ptScroll.y = sInfo.fContentMax;
1626						if (ptScroll.y < sInfo.fContentMin + sInfo.fPlateWidth)
1627							ptScroll.y = sInfo.fContentMin + sInfo.fPlateWidth;
1628						if (ptScroll.y < sInfo.fContentMin)
1629							ptScroll.y = sInfo.fContentMin;
1630
1631						if (ptOld.y != ptScroll.y)
1632						{
1633							m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptScroll.y);
1634							m_pContentsBar->InvalidateRect(NULL);
1635							m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL, (FX_INTPTR)&ptScroll.y);
1636						}
1637					}
1638				}
1639			}
1640		}
1641
1642		m_pContents->InvalidateRect(NULL);
1643
1644		return;
1645	case PNM_SCROLLWINDOW:
1646		if (m_pContents)
1647			m_pContents->OnNotify(pWnd, msg, wParam, lParam);
1648		return;
1649	case PNM_SETSCROLLPOS:
1650		if (m_pContentsBar)
1651			m_pContentsBar->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam);
1652		return;
1653	}
1654
1655	if (msg == PNM_SETCARETINFO && IsValid())
1656	{
1657		if (PWL_CARET_INFO * pInfo = (PWL_CARET_INFO*)wParam)
1658		{
1659			if (m_pContents)
1660			{
1661				CPDF_Rect rcClient = m_pContents->GetClientRect();
1662				if (pInfo->ptHead.y > rcClient.top)
1663				{
1664					CPDF_Point pt = m_pContents->OutToIn(pInfo->ptHead);
1665					m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL, (FX_INTPTR)&pt.y);
1666
1667					CPDF_Point ptScroll = m_pContents->GetScrollPos();
1668					m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptScroll.y);
1669
1670					return;
1671				}
1672
1673				if (pInfo->ptFoot.y < rcClient.bottom)
1674				{
1675					CPDF_Point pt = m_pContents->OutToIn(pInfo->ptFoot);
1676					pt.y += rcClient.Height();
1677					m_pContents->OnNotify(this, PNM_SCROLLWINDOW, SBT_VSCROLL, (FX_INTPTR)&pt.y);
1678
1679					CPDF_Point ptScroll = m_pContents->GetScrollPos();
1680					m_pContentsBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptScroll.y);
1681
1682					return;
1683				}
1684			}
1685		}
1686	}
1687
1688	CPWL_NoteItem::OnNotify(pWnd, msg, wParam, lParam);
1689}
1690
1691void CPWL_Note::SetBkColor(const CPWL_Color& color)
1692{
1693	CPWL_NoteItem::SetBkColor(color);
1694
1695	CPWL_Color sBK = color;
1696	CPWL_Color sTextColor;
1697	if (CPWL_Utils::IsBlackOrWhite(sBK))
1698		sTextColor = PWL_DEFAULT_WHITECOLOR;
1699	else
1700		sTextColor = PWL_DEFAULT_BLACKCOLOR;
1701
1702	if (m_pCloseBox)
1703		m_pCloseBox->SetTextColor(sTextColor);
1704	if (m_pAuthor)
1705		m_pAuthor->SetTextColor(sTextColor);
1706	if (m_pOptions)
1707		m_pOptions->SetTextColor(sTextColor);
1708	if (m_pLBBox)
1709		m_pLBBox->SetTextColor(sTextColor);
1710	if (m_pRBBox)
1711		m_pRBBox->SetTextColor(sTextColor);
1712}
1713
1714FX_BOOL	CPWL_Note::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag)
1715{
1716	if (m_pOptions->WndHitTest(m_pOptions->ParentToChild(point)))
1717	{
1718		if (IPWL_NoteNotify* pNotify = this->GetNoteNotify())
1719		{
1720			FX_INT32 x, y;
1721			PWLtoWnd(point, x, y);
1722			if (IFX_SystemHandler* pSH = GetSystemHandler())
1723				pSH->ClientToScreen(GetAttachedHWnd(), x, y);
1724			this->KillFocus();
1725			pNotify->OnPopupMenu(x, y);
1726
1727			return TRUE;
1728		}
1729	}
1730
1731	return CPWL_Wnd::OnLButtonDown(point,nFlag);
1732}
1733
1734FX_BOOL	CPWL_Note::OnRButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
1735{
1736	return CPWL_Wnd::OnRButtonUp(point,nFlag);
1737}
1738
1739const CPWL_Note* CPWL_Note::GetNote() const
1740{
1741	return this;
1742}
1743
1744IPWL_NoteNotify* CPWL_Note::GetNoteNotify() const
1745{
1746	if (m_bEnalbleNotify)
1747		return m_pNoteNotify;
1748
1749	return NULL;
1750}
1751
1752void CPWL_Note::SetIconType(FX_INT32 nType)
1753{
1754	if (m_pIcon)
1755		m_pIcon->SetIconType(nType);
1756}
1757
1758void CPWL_Note::EnableModify(FX_BOOL bEnabled)
1759{
1760	m_pContents->EnableModify(bEnabled);
1761}
1762
1763void CPWL_Note::EnableRead(FX_BOOL bEnabled)
1764{
1765	m_pContents->EnableRead(bEnabled);
1766}
1767
1768CFX_WideString CPWL_Note::GetReplyString() const
1769{
1770	return m_sReplyString;
1771}
1772
1773void CPWL_Note::SetReplyString(const CFX_WideString& string)
1774{
1775	m_sReplyString = string;
1776}
1777
1778