Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fwl / src / basewidget / fwl_tooltipctrlimp.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../foxitlib.h"\r
8 #include "../core/include/fwl_targetimp.h"\r
9 #include "../core/include/fwl_noteimp.h"\r
10 #include "../core/include/fwl_widgetimp.h"\r
11 #include "../core/include/fwl_panelimp.h"\r
12 #include "../core/include/fwl_formimp.h"\r
13 #include "include/fwl_tooltipctrlimp.h"\r
14 IFWL_ToolTip *IFWL_ToolTip::Create()\r
15 {\r
16     return new IFWL_ToolTip;\r
17 }\r
18 FWL_ERR IFWL_ToolTip::Initialize(IFWL_Widget *pOuter)\r
19 {\r
20     m_pData = FX_NEW CFWL_ToolTipImp(pOuter);\r
21     ((CFWL_ToolTipImp*)m_pData)->SetInterface(this);\r
22     return ((CFWL_ToolTipImp*)m_pData)->Initialize();\r
23 }\r
24 FWL_ERR IFWL_ToolTip::Initialize(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter)\r
25 {\r
26     m_pData = FX_NEW CFWL_ToolTipImp(properties, pOuter);\r
27     ((CFWL_ToolTipImp*)m_pData)->SetInterface(this);\r
28     return ((CFWL_ToolTipImp*)m_pData)->Initialize();\r
29 }\r
30 FWL_ERR IFWL_ToolTip::SetAnchor(const CFX_RectF &rtAnchor)\r
31 {\r
32     return ((CFWL_ToolTipImp*)m_pData)->SetAnchor( rtAnchor);\r
33 }\r
34 FWL_ERR IFWL_ToolTip::Show()\r
35 {\r
36     return ((CFWL_ToolTipImp*)m_pData)->Show();\r
37 }\r
38 FWL_ERR IFWL_ToolTip::Hide()\r
39 {\r
40     return ((CFWL_ToolTipImp*)m_pData)->Hide();\r
41 }\r
42 IFWL_ToolTip::IFWL_ToolTip()\r
43 {\r
44     m_pData = NULL;\r
45 }\r
46 IFWL_ToolTip::~IFWL_ToolTip()\r
47 {\r
48     if (m_pData) {\r
49         delete (CFWL_ToolTipImp*)m_pData;\r
50         m_pData = NULL;\r
51     }\r
52 }\r
53 CFWL_ToolTipImp::CFWL_ToolTipImp(IFWL_Widget *pOuter )\r
54     : CFWL_FormImp(pOuter)\r
55     , m_bBtnDown(FALSE)\r
56     , m_dwTTOStyles(FDE_TTOSTYLE_SingleLine)\r
57     , m_iTTOAlign(FDE_TTOALIGNMENT_Center)\r
58     , m_hTimerShow(NULL)\r
59     , m_hTimerHide(NULL)\r
60     , m_pTimer(NULL)\r
61 {\r
62     m_rtClient.Set(0, 0, 0, 0);\r
63     m_rtCaption.Set(0, 0, 0, 0);\r
64     m_pTimer = NULL;\r
65     m_TimerShow.m_pToolTip = this;\r
66     m_TimerHide.m_pToolTip = this;\r
67 }\r
68 CFWL_ToolTipImp::CFWL_ToolTipImp(const CFWL_WidgetImpProperties &properties, IFWL_Widget *pOuter )\r
69     : CFWL_FormImp(properties, pOuter)\r
70     , m_bBtnDown(FALSE)\r
71     , m_dwTTOStyles(FDE_TTOSTYLE_SingleLine)\r
72     , m_iTTOAlign(FDE_TTOALIGNMENT_Center)\r
73     , m_hTimerShow(NULL)\r
74     , m_hTimerHide(NULL)\r
75     , m_pTimer(NULL)\r
76 {\r
77     m_rtClient.Set(0, 0, 0, 0);\r
78     m_rtCaption.Set(0, 0, 0, 0);\r
79     m_rtAnchor.Set(0, 0, 0, 0);\r
80     m_TimerShow.m_pToolTip = this;\r
81     m_TimerHide.m_pToolTip = this;\r
82 }\r
83 CFWL_ToolTipImp::~CFWL_ToolTipImp()\r
84 {\r
85     if (m_pTimer) {\r
86         delete m_pTimer;\r
87         m_pTimer = NULL;\r
88     }\r
89 }\r
90 FWL_ERR CFWL_ToolTipImp::GetClassName(CFX_WideString &wsClass) const\r
91 {\r
92     wsClass = FWL_CLASS_ToolTip;\r
93     return FWL_ERR_Succeeded;\r
94 }\r
95 FX_DWORD CFWL_ToolTipImp::GetClassID() const\r
96 {\r
97     return FWL_CLASSHASH_ToolTip;\r
98 }\r
99 FWL_ERR CFWL_ToolTipImp::Initialize()\r
100 {\r
101     m_pProperties->m_dwStyles |= FWL_WGTSTYLE_Popup;\r
102     m_pProperties->m_dwStyles &= ~FWL_WGTSTYLE_Child;\r
103     _FWL_ERR_CHECK_RETURN_VALUE_IF_FAIL(CFWL_WidgetImp::Initialize(), FWL_ERR_Indefinite);\r
104     m_pDelegate = (IFWL_WidgetDelegate*) FX_NEW CFWL_ToolTipImpDelegate(this);\r
105     return FWL_ERR_Succeeded;\r
106 }\r
107 FWL_ERR CFWL_ToolTipImp::Finalize()\r
108 {\r
109     if ( m_pDelegate) {\r
110         delete (CFWL_ToolTipImpDelegate*)m_pDelegate;\r
111         m_pDelegate = NULL;\r
112     }\r
113     return CFWL_WidgetImp::Finalize();\r
114 }\r
115 FWL_ERR CFWL_ToolTipImp::GetWidgetRect(CFX_RectF &rect, FX_BOOL bAutoSize )\r
116 {\r
117     if (bAutoSize) {\r
118         rect.Set(0, 0, 0, 0);\r
119         if (m_pProperties->m_pThemeProvider == NULL) {\r
120             m_pProperties->m_pThemeProvider = GetAvailableTheme();\r
121         }\r
122         CFX_WideString wsCaption;\r
123         IFWL_ToolTipDP *pData = (IFWL_ToolTipDP*)m_pProperties->m_pDataProvider;\r
124         if (pData) {\r
125             pData->GetCaption(m_pInterface, wsCaption);\r
126         }\r
127         FX_INT32 iLen = wsCaption.GetLength();\r
128         if (iLen > 0) {\r
129             CFX_SizeF sz = CalcTextSize(wsCaption, m_pProperties->m_pThemeProvider);\r
130             rect.Set(0, 0, sz.x, sz.y);\r
131             rect.width += FWL_WGTCAPACITY_CXBorder * 25;\r
132             rect.height += FWL_WGTCAPACITY_CYBorder * 8;\r
133         }\r
134         CFWL_WidgetImp::GetWidgetRect(rect, TRUE);\r
135     } else {\r
136         rect = m_pProperties->m_rtWidget;\r
137     }\r
138     return FWL_ERR_Succeeded;\r
139 }\r
140 FWL_ERR CFWL_ToolTipImp::Update()\r
141 {\r
142     if (IsLocked()) {\r
143         return FWL_ERR_Indefinite;\r
144     }\r
145     if (!m_pProperties->m_pThemeProvider) {\r
146         m_pProperties->m_pThemeProvider = GetAvailableTheme();\r
147     }\r
148     UpdateTextOutStyles();\r
149     GetClientRect(m_rtClient);\r
150     m_rtCaption = m_rtClient;\r
151     return FWL_ERR_Succeeded;\r
152 }\r
153 FWL_ERR CFWL_ToolTipImp::GetClientRect(CFX_RectF &rect)\r
154 {\r
155     FX_FLOAT x = 0;\r
156     FX_FLOAT y = 0;\r
157     FX_FLOAT t = 0;\r
158     IFWL_ThemeProvider *pTheme = m_pProperties->m_pThemeProvider;\r
159     if (pTheme) {\r
160         CFWL_ThemePart part;\r
161         part.m_pWidget = m_pInterface;\r
162         FX_FLOAT * value = NULL;\r
163         value = (FX_FLOAT *) pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CXBorder);\r
164         x = *value;\r
165         value = (FX_FLOAT *) pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CYBorder);\r
166         y = *value;\r
167     }\r
168     rect = m_pProperties->m_rtWidget;\r
169     rect.Offset(-rect.left, -rect.top);\r
170     rect.Deflate(x, t, x, y);\r
171     return FWL_ERR_Succeeded;\r
172 }\r
173 FWL_ERR CFWL_ToolTipImp::DrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix )\r
174 {\r
175     IFWL_ToolTipTarget * toolTipTarget = CFWL_ToolTipContainer::getInstance()->GetCurrentToolTipTarget();\r
176     if (toolTipTarget && !toolTipTarget->UseDefaultTheme()) {\r
177         return toolTipTarget->DrawToolTip(pGraphics, pMatrix, m_pInterface);\r
178     }\r
179     _FWL_RETURN_VALUE_IF_FAIL(pGraphics, FWL_ERR_Indefinite);\r
180     _FWL_RETURN_VALUE_IF_FAIL(m_pProperties->m_pThemeProvider, FWL_ERR_Indefinite);\r
181     IFWL_ThemeProvider *pTheme = m_pProperties->m_pThemeProvider;\r
182     DrawBkground(pGraphics, pTheme, pMatrix);\r
183     DrawText(pGraphics, pTheme, pMatrix);\r
184     return FWL_ERR_Succeeded;\r
185 }\r
186 void CFWL_ToolTipImp::DrawBkground(CFX_Graphics *pGraphics, IFWL_ThemeProvider *pTheme, const CFX_Matrix *pMatrix)\r
187 {\r
188     CFWL_ThemeBackground param;\r
189     param.m_pWidget = m_pInterface;\r
190     param.m_iPart = FWL_PART_TTP_Background;\r
191     param.m_dwStates = m_pProperties->m_dwStates;\r
192     param.m_pGraphics = pGraphics;\r
193     if (pMatrix) {\r
194         param.m_matrix.Concat(*pMatrix);\r
195     }\r
196     param.m_rtPart = m_rtClient;\r
197     if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {\r
198         param.m_pData = &m_rtCaption;\r
199     }\r
200     pTheme->DrawBackground(&param);\r
201 }\r
202 void CFWL_ToolTipImp::DrawText(CFX_Graphics *pGraphics, IFWL_ThemeProvider *pTheme, const CFX_Matrix *pMatrix)\r
203 {\r
204     _FWL_RETURN_IF_FAIL(m_pProperties->m_pDataProvider);\r
205     CFX_WideString wsCaption;\r
206     m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption);\r
207     if (wsCaption.IsEmpty()) {\r
208         return;\r
209     }\r
210     CFWL_ThemeText param;\r
211     param.m_pWidget = m_pInterface;\r
212     param.m_iPart = FWL_PART_TTP_Caption;\r
213     param.m_dwStates = m_pProperties->m_dwStates;\r
214     param.m_pGraphics = pGraphics;\r
215     if (pMatrix) {\r
216         param.m_matrix.Concat(*pMatrix);\r
217     }\r
218     param.m_rtPart = m_rtCaption;\r
219     param.m_wsText = wsCaption;\r
220     param.m_dwTTOStyles = m_dwTTOStyles;\r
221     param.m_iTTOAlign = m_iTTOAlign;\r
222     pTheme->DrawText(&param);\r
223 }\r
224 void CFWL_ToolTipImp::UpdateTextOutStyles()\r
225 {\r
226     m_iTTOAlign = FDE_TTOALIGNMENT_Center;\r
227     m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;\r
228     if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) {\r
229         m_dwTTOStyles |= FDE_TTOSTYLE_RTL;\r
230     }\r
231     if ( m_pProperties->m_dwStyleExes & FWL_STYLEEXT_TTP_Multiline) {\r
232         m_dwTTOStyles &= ~FDE_TTOSTYLE_SingleLine;\r
233     }\r
234 }\r
235 FWL_ERR CFWL_ToolTipImp::SetAnchor(const CFX_RectF &rtAnchor)\r
236 {\r
237     m_rtAnchor = rtAnchor;\r
238     return TRUE;\r
239 }\r
240 FWL_ERR CFWL_ToolTipImp::Show()\r
241 {\r
242     IFWL_ToolTipDP *pData = (IFWL_ToolTipDP*)m_pProperties->m_pDataProvider;\r
243     FX_INT32 nInitDelay = pData->GetInitialDelay(m_pInterface);\r
244     if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible)) {\r
245         m_hTimerShow = FWL_StartTimer( &m_TimerShow, nInitDelay, FALSE);\r
246     }\r
247     return TRUE;\r
248 }\r
249 FWL_ERR CFWL_ToolTipImp::Hide()\r
250 {\r
251     SetStates( FWL_WGTSTATE_Invisible, TRUE);\r
252     if ( m_hTimerHide) {\r
253         FWL_StopTimer(m_hTimerHide);\r
254         m_hTimerHide = NULL;\r
255     }\r
256     if ( m_hTimerShow) {\r
257         FWL_StopTimer(m_hTimerShow);\r
258         m_hTimerShow = NULL;\r
259     }\r
260     return TRUE;\r
261 }\r
262 FWL_ERR CFWL_ToolTipImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet )\r
263 {\r
264     if ( (dwStates & FWL_WGTSTATE_Invisible) && !bSet) {\r
265         IFWL_ToolTipDP *pData = (IFWL_ToolTipDP*)m_pProperties->m_pDataProvider;\r
266         FX_INT32 nAutoPopDelay = pData->GetAutoPopDelay(m_pInterface);\r
267         m_hTimerHide = FWL_StartTimer( &m_TimerHide, nAutoPopDelay, FALSE);\r
268     }\r
269     return CFWL_WidgetImp::SetStates(dwStates, bSet);\r
270 }\r
271 void CFWL_ToolTipImp::RefreshToolTipPos()\r
272 {\r
273     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_TTP_NoAnchor) == 0) {\r
274         CFX_RectF rtPopup;\r
275         CFX_RectF rtWidget(m_pProperties->m_rtWidget);\r
276         CFX_RectF rtAnchor(m_rtAnchor);\r
277         rtPopup.Set( 0, 0, 0, 0);\r
278         FX_FLOAT fx = rtAnchor.Center().x + 20;\r
279         FX_FLOAT fy = rtAnchor.Center().y + 20;\r
280         rtPopup.Set( fx, fy, rtWidget.Width(), rtWidget.Height());\r
281         FX_FLOAT fScreenWidth = 0;\r
282         FX_FLOAT fScreenHeight = 0;\r
283         GetScreenSize(fScreenWidth, fScreenHeight);\r
284         if (rtPopup.bottom() > fScreenHeight) {\r
285             rtPopup.Offset( 0, fScreenHeight - rtPopup.bottom());\r
286         }\r
287         if ( rtPopup.right() > fScreenWidth) {\r
288             rtPopup.Offset( fScreenWidth - rtPopup.right(), 0);\r
289         }\r
290         if ( rtPopup.left < 0) {\r
291             rtPopup.Offset(0 - rtPopup.left, 0);\r
292         }\r
293         if ( rtPopup.top < 0) {\r
294             rtPopup.Offset( 0, 0 - rtPopup.top);\r
295         }\r
296         SetWidgetRect(rtPopup);\r
297         Update();\r
298     }\r
299 }\r
300 CFWL_ToolTipImp::CFWL_ToolTipTimer::CFWL_ToolTipTimer(CFWL_ToolTipImp * pToolTip)\r
301     : m_pToolTip(pToolTip)\r
302 {\r
303 }\r
304 FX_INT32 CFWL_ToolTipImp::CFWL_ToolTipTimer::Run(FWL_HTIMER hTimer)\r
305 {\r
306     if (m_pToolTip->m_hTimerShow == hTimer && m_pToolTip->m_hTimerShow) {\r
307         if (m_pToolTip->GetStates() & FWL_WGTSTATE_Invisible) {\r
308             m_pToolTip->SetStates(FWL_WGTSTATE_Invisible, FALSE);\r
309             m_pToolTip->RefreshToolTipPos();\r
310             FWL_StopTimer(m_pToolTip->m_hTimerShow);\r
311             m_pToolTip->m_hTimerShow = NULL;\r
312             return TRUE;\r
313         }\r
314     }\r
315     if (m_pToolTip->m_hTimerHide == hTimer && m_pToolTip->m_hTimerHide) {\r
316         m_pToolTip->SetStates(FWL_WGTSTATE_Invisible, TRUE);\r
317         FWL_StopTimer(m_pToolTip->m_hTimerHide);\r
318         m_pToolTip->m_hTimerHide = NULL;\r
319         return TRUE;\r
320     }\r
321     return TRUE;\r
322 }\r
323 CFWL_ToolTipImpDelegate::CFWL_ToolTipImpDelegate(CFWL_ToolTipImp *pOwner)\r
324     : m_pOwner(pOwner)\r
325 {\r
326 }\r
327 FX_INT32 CFWL_ToolTipImpDelegate::OnProcessMessage(CFWL_Message *pMessage)\r
328 {\r
329     return      CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);\r
330 }\r
331 FWL_ERR CFWL_ToolTipImpDelegate::OnProcessEvent(CFWL_Event *pEvent)\r
332 {\r
333     return FWL_ERR_Succeeded;\r
334 }\r
335 FWL_ERR CFWL_ToolTipImpDelegate::OnDrawWidget(CFX_Graphics *pGraphics, const CFX_Matrix *pMatrix )\r
336 {\r
337     return m_pOwner->DrawWidget(pGraphics, pMatrix);\r
338 }\r