PWL_Caret.cpp revision ee451cb395940862dad63c85adfe8f2fd55e864c
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_Caret.h"
10#include "../../include/pdfwindow/PWL_Utils.h"
11
12#define PWL_CARET_FLASHINTERVAL		500
13
14//////////////////////////////////////////////////////////////////////
15// Construction/Destruction
16//////////////////////////////////////////////////////////////////////
17
18CPWL_Caret::CPWL_Caret() :
19	m_bFlash(FALSE),
20	m_ptHead(0,0),
21	m_ptFoot(0,0),
22	m_fWidth(0.4f),
23	m_nDelay(0)
24{
25}
26
27CPWL_Caret::~CPWL_Caret()
28{
29}
30
31CFX_ByteString CPWL_Caret::GetClassName() const
32{
33	return "CPWL_Caret";
34}
35
36void CPWL_Caret::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
37{
38	GetCaretApp(sAppStream,CPDF_Point(0.0f,0.0f));
39}
40
41void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
42{
43	if (IsVisible() && m_bFlash)
44	{
45		CPDF_Rect rcRect = GetCaretRect();
46		CPDF_Rect rcClip = GetClipRect();
47
48		CFX_PathData path;
49
50		path.SetPointCount(2);
51
52		FX_FLOAT fCaretX = rcRect.left + m_fWidth * 0.5f;
53		FX_FLOAT fCaretTop = rcRect.top;
54		FX_FLOAT fCaretBottom = rcRect.bottom;
55
56		if (!rcClip.IsEmpty())
57		{
58			rcRect.Intersect(rcClip);
59			if (!rcRect.IsEmpty())
60			{
61				fCaretTop = rcRect.top;
62				fCaretBottom = rcRect.bottom;
63				path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO);
64				path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO);
65			}
66			else
67			{
68				return;
69			}
70		}
71		else
72		{
73			path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO);
74			path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO);
75		}
76
77		CFX_GraphStateData gsd;
78		gsd.m_LineWidth = m_fWidth;
79
80		pDevice->DrawPath(&path, pUser2Device, &gsd,0,  ArgbEncode(255,0,0,0), FXFILL_ALTERNATE);
81	}
82}
83
84void CPWL_Caret::GetCaretApp(CFX_ByteTextBuf & sAppStream,const CPDF_Point & ptOffset)
85{
86	if (IsVisible() && m_bFlash)
87	{
88		CFX_ByteTextBuf sCaret;
89
90		CPDF_Rect rcRect = GetCaretRect();
91		CPDF_Rect rcClip = GetClipRect();
92
93		rcRect = CPWL_Utils::OffsetRect(rcRect,ptOffset.x,ptOffset.y);
94		rcClip = CPWL_Utils::OffsetRect(rcClip,ptOffset.x,ptOffset.y);
95
96		sCaret << "q\n";
97		if (!rcClip.IsEmpty())
98		{
99			sCaret << rcClip.left << " " << rcClip.bottom + 2.5f << " "
100				<< rcClip.right - rcClip.left << " " << rcClip.top - rcClip.bottom - 4.5f << " re W n\n";
101		}
102		sCaret << m_fWidth << " w\n0 G\n";
103		sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.bottom << " m\n";
104		sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.top << " l S\nQ\n";
105
106		sAppStream << sCaret;
107	}
108}
109
110CFX_ByteString CPWL_Caret::GetCaretAppearanceStream(const CPDF_Point & ptOffset)
111{
112	CFX_ByteTextBuf sCaret;
113	GetCaretApp(sCaret,ptOffset);
114	return sCaret.GetByteString();
115}
116
117void CPWL_Caret::TimerProc()
118{
119	if (m_nDelay > 0)
120	{
121		m_nDelay--;
122	}
123	else
124	{
125		m_bFlash = !m_bFlash;
126		InvalidateRect();
127	}
128}
129
130CPDF_Rect CPWL_Caret::GetCaretRect() const
131{
132	return CPDF_Rect(m_ptFoot.x,
133			m_ptFoot.y,
134			m_ptHead.x + this->m_fWidth,
135			m_ptHead.y);
136}
137
138void CPWL_Caret::SetCaret(FX_BOOL bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot)
139{
140	if (bVisible)
141	{
142		if (IsVisible())
143		{
144			if (m_ptHead.x != ptHead.x || m_ptHead.y != ptHead.y ||
145					m_ptFoot.x != ptFoot.x || m_ptFoot.y != ptFoot.y)
146			{
147				this->m_ptHead = ptHead;
148				this->m_ptFoot = ptFoot;
149
150				m_bFlash = TRUE;
151				//Move(GetCaretRect(),FALSE,TRUE);
152				Move(m_rcInvalid, FALSE, TRUE);
153			}
154		}
155		else
156		{
157			this->m_ptHead = ptHead;
158			this->m_ptFoot = ptFoot;
159
160			EndTimer();
161			BeginTimer(PWL_CARET_FLASHINTERVAL);
162
163			CPWL_Wnd::SetVisible(TRUE);
164			m_bFlash = TRUE;
165
166			//Move(GetCaretRect(),FALSE,TRUE);
167			Move(m_rcInvalid, FALSE, TRUE);
168		}
169	}
170	else
171	{
172		this->m_ptHead = CPDF_Point(0,0);
173		this->m_ptFoot = CPDF_Point(0,0);
174
175		m_bFlash = FALSE;
176		if (IsVisible())
177		{
178			EndTimer();
179			CPWL_Wnd::SetVisible(FALSE);
180		}
181	}
182}
183
184void CPWL_Caret::InvalidateRect(CPDF_Rect * pRect)
185{
186	if (pRect)
187	{
188		CPDF_Rect rcRefresh = CPWL_Utils::InflateRect(*pRect,0.5f);
189		rcRefresh.top += 1;
190		rcRefresh.bottom -= 1;
191
192		CPWL_Wnd::InvalidateRect(&rcRefresh);
193	}
194	else
195		CPWL_Wnd::InvalidateRect(pRect);
196}
197
198