| OLD | NEW |
| (Empty) |
| 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 "xfa/src/fwl/basewidget/fwl_tooltipctrlimp.h" | |
| 8 | |
| 9 #include "xfa/include/fwl/basewidget/fwl_tooltipctrl.h" | |
| 10 #include "xfa/include/fwl/core/fwl_theme.h" | |
| 11 #include "xfa/src/fde/tto/fde_textout.h" | |
| 12 #include "xfa/src/fwl/core/fwl_formimp.h" | |
| 13 #include "xfa/src/fwl/core/fwl_noteimp.h" | |
| 14 #include "xfa/src/fwl/core/fwl_panelimp.h" | |
| 15 #include "xfa/src/fwl/core/fwl_targetimp.h" | |
| 16 #include "xfa/src/fwl/core/fwl_widgetimp.h" | |
| 17 | |
| 18 // static | |
| 19 IFWL_ToolTip* IFWL_ToolTip::Create(const CFWL_WidgetImpProperties& properties, | |
| 20 IFWL_Widget* pOuter) { | |
| 21 IFWL_ToolTip* pToolTip = new IFWL_ToolTip; | |
| 22 CFWL_ToolTipImp* pToolTipImpl = new CFWL_ToolTipImp(properties, pOuter); | |
| 23 pToolTip->SetImpl(pToolTipImpl); | |
| 24 pToolTipImpl->SetInterface(pToolTip); | |
| 25 return pToolTip; | |
| 26 } | |
| 27 FWL_ERR IFWL_ToolTip::SetAnchor(const CFX_RectF& rtAnchor) { | |
| 28 return static_cast<CFWL_ToolTipImp*>(GetImpl())->SetAnchor(rtAnchor); | |
| 29 } | |
| 30 FWL_ERR IFWL_ToolTip::Show() { | |
| 31 return static_cast<CFWL_ToolTipImp*>(GetImpl())->Show(); | |
| 32 } | |
| 33 FWL_ERR IFWL_ToolTip::Hide() { | |
| 34 return static_cast<CFWL_ToolTipImp*>(GetImpl())->Hide(); | |
| 35 } | |
| 36 IFWL_ToolTip::IFWL_ToolTip() {} | |
| 37 CFWL_ToolTipImp::CFWL_ToolTipImp(const CFWL_WidgetImpProperties& properties, | |
| 38 IFWL_Widget* pOuter) | |
| 39 : CFWL_FormImp(properties, pOuter), | |
| 40 m_bBtnDown(FALSE), | |
| 41 m_dwTTOStyles(FDE_TTOSTYLE_SingleLine), | |
| 42 m_iTTOAlign(FDE_TTOALIGNMENT_Center), | |
| 43 m_hTimerShow(NULL), | |
| 44 m_hTimerHide(NULL), | |
| 45 m_pTimer(NULL) { | |
| 46 m_rtClient.Set(0, 0, 0, 0); | |
| 47 m_rtCaption.Set(0, 0, 0, 0); | |
| 48 m_rtAnchor.Set(0, 0, 0, 0); | |
| 49 m_TimerShow.m_pToolTip = this; | |
| 50 m_TimerHide.m_pToolTip = this; | |
| 51 } | |
| 52 CFWL_ToolTipImp::~CFWL_ToolTipImp() { | |
| 53 if (m_pTimer) { | |
| 54 delete m_pTimer; | |
| 55 m_pTimer = NULL; | |
| 56 } | |
| 57 } | |
| 58 FWL_ERR CFWL_ToolTipImp::GetClassName(CFX_WideString& wsClass) const { | |
| 59 wsClass = FWL_CLASS_ToolTip; | |
| 60 return FWL_ERR_Succeeded; | |
| 61 } | |
| 62 FX_DWORD CFWL_ToolTipImp::GetClassID() const { | |
| 63 return FWL_CLASSHASH_ToolTip; | |
| 64 } | |
| 65 FWL_ERR CFWL_ToolTipImp::Initialize() { | |
| 66 m_pProperties->m_dwStyles |= FWL_WGTSTYLE_Popup; | |
| 67 m_pProperties->m_dwStyles &= ~FWL_WGTSTYLE_Child; | |
| 68 if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) | |
| 69 return FWL_ERR_Indefinite; | |
| 70 m_pDelegate = new CFWL_ToolTipImpDelegate(this); | |
| 71 return FWL_ERR_Succeeded; | |
| 72 } | |
| 73 FWL_ERR CFWL_ToolTipImp::Finalize() { | |
| 74 delete m_pDelegate; | |
| 75 m_pDelegate = nullptr; | |
| 76 return CFWL_WidgetImp::Finalize(); | |
| 77 } | |
| 78 FWL_ERR CFWL_ToolTipImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { | |
| 79 if (bAutoSize) { | |
| 80 rect.Set(0, 0, 0, 0); | |
| 81 if (m_pProperties->m_pThemeProvider == NULL) { | |
| 82 m_pProperties->m_pThemeProvider = GetAvailableTheme(); | |
| 83 } | |
| 84 CFX_WideString wsCaption; | |
| 85 IFWL_ToolTipDP* pData = | |
| 86 static_cast<IFWL_ToolTipDP*>(m_pProperties->m_pDataProvider); | |
| 87 if (pData) { | |
| 88 pData->GetCaption(m_pInterface, wsCaption); | |
| 89 } | |
| 90 int32_t iLen = wsCaption.GetLength(); | |
| 91 if (iLen > 0) { | |
| 92 CFX_SizeF sz = CalcTextSize(wsCaption, m_pProperties->m_pThemeProvider); | |
| 93 rect.Set(0, 0, sz.x, sz.y); | |
| 94 rect.width += FWL_WGTCAPACITY_CXBorder * 25; | |
| 95 rect.height += FWL_WGTCAPACITY_CYBorder * 8; | |
| 96 } | |
| 97 CFWL_WidgetImp::GetWidgetRect(rect, TRUE); | |
| 98 } else { | |
| 99 rect = m_pProperties->m_rtWidget; | |
| 100 } | |
| 101 return FWL_ERR_Succeeded; | |
| 102 } | |
| 103 FWL_ERR CFWL_ToolTipImp::Update() { | |
| 104 if (IsLocked()) { | |
| 105 return FWL_ERR_Indefinite; | |
| 106 } | |
| 107 if (!m_pProperties->m_pThemeProvider) { | |
| 108 m_pProperties->m_pThemeProvider = GetAvailableTheme(); | |
| 109 } | |
| 110 UpdateTextOutStyles(); | |
| 111 GetClientRect(m_rtClient); | |
| 112 m_rtCaption = m_rtClient; | |
| 113 return FWL_ERR_Succeeded; | |
| 114 } | |
| 115 FWL_ERR CFWL_ToolTipImp::GetClientRect(CFX_RectF& rect) { | |
| 116 FX_FLOAT x = 0; | |
| 117 FX_FLOAT y = 0; | |
| 118 FX_FLOAT t = 0; | |
| 119 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; | |
| 120 if (pTheme) { | |
| 121 CFWL_ThemePart part; | |
| 122 part.m_pWidget = m_pInterface; | |
| 123 x = *static_cast<FX_FLOAT*>( | |
| 124 pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CXBorder)); | |
| 125 y = *static_cast<FX_FLOAT*>( | |
| 126 pTheme->GetCapacity(&part, FWL_WGTCAPACITY_CYBorder)); | |
| 127 } | |
| 128 rect = m_pProperties->m_rtWidget; | |
| 129 rect.Offset(-rect.left, -rect.top); | |
| 130 rect.Deflate(x, t, x, y); | |
| 131 return FWL_ERR_Succeeded; | |
| 132 } | |
| 133 FWL_ERR CFWL_ToolTipImp::DrawWidget(CFX_Graphics* pGraphics, | |
| 134 const CFX_Matrix* pMatrix) { | |
| 135 IFWL_ToolTipTarget* toolTipTarget = | |
| 136 CFWL_ToolTipContainer::getInstance()->GetCurrentToolTipTarget(); | |
| 137 if (toolTipTarget && !toolTipTarget->UseDefaultTheme()) { | |
| 138 return toolTipTarget->DrawToolTip(pGraphics, pMatrix, m_pInterface); | |
| 139 } | |
| 140 if (!pGraphics) | |
| 141 return FWL_ERR_Indefinite; | |
| 142 if (!m_pProperties->m_pThemeProvider) | |
| 143 return FWL_ERR_Indefinite; | |
| 144 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; | |
| 145 DrawBkground(pGraphics, pTheme, pMatrix); | |
| 146 DrawText(pGraphics, pTheme, pMatrix); | |
| 147 return FWL_ERR_Succeeded; | |
| 148 } | |
| 149 void CFWL_ToolTipImp::DrawBkground(CFX_Graphics* pGraphics, | |
| 150 IFWL_ThemeProvider* pTheme, | |
| 151 const CFX_Matrix* pMatrix) { | |
| 152 CFWL_ThemeBackground param; | |
| 153 param.m_pWidget = m_pInterface; | |
| 154 param.m_iPart = FWL_PART_TTP_Background; | |
| 155 param.m_dwStates = m_pProperties->m_dwStates; | |
| 156 param.m_pGraphics = pGraphics; | |
| 157 if (pMatrix) { | |
| 158 param.m_matrix.Concat(*pMatrix); | |
| 159 } | |
| 160 param.m_rtPart = m_rtClient; | |
| 161 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { | |
| 162 param.m_pData = &m_rtCaption; | |
| 163 } | |
| 164 pTheme->DrawBackground(¶m); | |
| 165 } | |
| 166 void CFWL_ToolTipImp::DrawText(CFX_Graphics* pGraphics, | |
| 167 IFWL_ThemeProvider* pTheme, | |
| 168 const CFX_Matrix* pMatrix) { | |
| 169 if (!m_pProperties->m_pDataProvider) | |
| 170 return; | |
| 171 CFX_WideString wsCaption; | |
| 172 m_pProperties->m_pDataProvider->GetCaption(m_pInterface, wsCaption); | |
| 173 if (wsCaption.IsEmpty()) { | |
| 174 return; | |
| 175 } | |
| 176 CFWL_ThemeText param; | |
| 177 param.m_pWidget = m_pInterface; | |
| 178 param.m_iPart = FWL_PART_TTP_Caption; | |
| 179 param.m_dwStates = m_pProperties->m_dwStates; | |
| 180 param.m_pGraphics = pGraphics; | |
| 181 if (pMatrix) { | |
| 182 param.m_matrix.Concat(*pMatrix); | |
| 183 } | |
| 184 param.m_rtPart = m_rtCaption; | |
| 185 param.m_wsText = wsCaption; | |
| 186 param.m_dwTTOStyles = m_dwTTOStyles; | |
| 187 param.m_iTTOAlign = m_iTTOAlign; | |
| 188 pTheme->DrawText(¶m); | |
| 189 } | |
| 190 void CFWL_ToolTipImp::UpdateTextOutStyles() { | |
| 191 m_iTTOAlign = FDE_TTOALIGNMENT_Center; | |
| 192 m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; | |
| 193 if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) { | |
| 194 m_dwTTOStyles |= FDE_TTOSTYLE_RTL; | |
| 195 } | |
| 196 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_TTP_Multiline) { | |
| 197 m_dwTTOStyles &= ~FDE_TTOSTYLE_SingleLine; | |
| 198 } | |
| 199 } | |
| 200 FWL_ERR CFWL_ToolTipImp::SetAnchor(const CFX_RectF& rtAnchor) { | |
| 201 m_rtAnchor = rtAnchor; | |
| 202 return TRUE; | |
| 203 } | |
| 204 FWL_ERR CFWL_ToolTipImp::Show() { | |
| 205 IFWL_ToolTipDP* pData = | |
| 206 static_cast<IFWL_ToolTipDP*>(m_pProperties->m_pDataProvider); | |
| 207 int32_t nInitDelay = pData->GetInitialDelay(m_pInterface); | |
| 208 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible)) { | |
| 209 m_hTimerShow = FWL_StartTimer(&m_TimerShow, nInitDelay, FALSE); | |
| 210 } | |
| 211 return TRUE; | |
| 212 } | |
| 213 FWL_ERR CFWL_ToolTipImp::Hide() { | |
| 214 SetStates(FWL_WGTSTATE_Invisible, TRUE); | |
| 215 if (m_hTimerHide) { | |
| 216 FWL_StopTimer(m_hTimerHide); | |
| 217 m_hTimerHide = NULL; | |
| 218 } | |
| 219 if (m_hTimerShow) { | |
| 220 FWL_StopTimer(m_hTimerShow); | |
| 221 m_hTimerShow = NULL; | |
| 222 } | |
| 223 return TRUE; | |
| 224 } | |
| 225 FWL_ERR CFWL_ToolTipImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) { | |
| 226 if ((dwStates & FWL_WGTSTATE_Invisible) && !bSet) { | |
| 227 IFWL_ToolTipDP* pData = | |
| 228 static_cast<IFWL_ToolTipDP*>(m_pProperties->m_pDataProvider); | |
| 229 int32_t nAutoPopDelay = pData->GetAutoPopDelay(m_pInterface); | |
| 230 m_hTimerHide = FWL_StartTimer(&m_TimerHide, nAutoPopDelay, FALSE); | |
| 231 } | |
| 232 return CFWL_WidgetImp::SetStates(dwStates, bSet); | |
| 233 } | |
| 234 void CFWL_ToolTipImp::RefreshToolTipPos() { | |
| 235 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_TTP_NoAnchor) == 0) { | |
| 236 CFX_RectF rtPopup; | |
| 237 CFX_RectF rtWidget(m_pProperties->m_rtWidget); | |
| 238 CFX_RectF rtAnchor(m_rtAnchor); | |
| 239 rtPopup.Set(0, 0, 0, 0); | |
| 240 FX_FLOAT fx = rtAnchor.Center().x + 20; | |
| 241 FX_FLOAT fy = rtAnchor.Center().y + 20; | |
| 242 rtPopup.Set(fx, fy, rtWidget.Width(), rtWidget.Height()); | |
| 243 FX_FLOAT fScreenWidth = 0; | |
| 244 FX_FLOAT fScreenHeight = 0; | |
| 245 GetScreenSize(fScreenWidth, fScreenHeight); | |
| 246 if (rtPopup.bottom() > fScreenHeight) { | |
| 247 rtPopup.Offset(0, fScreenHeight - rtPopup.bottom()); | |
| 248 } | |
| 249 if (rtPopup.right() > fScreenWidth) { | |
| 250 rtPopup.Offset(fScreenWidth - rtPopup.right(), 0); | |
| 251 } | |
| 252 if (rtPopup.left < 0) { | |
| 253 rtPopup.Offset(0 - rtPopup.left, 0); | |
| 254 } | |
| 255 if (rtPopup.top < 0) { | |
| 256 rtPopup.Offset(0, 0 - rtPopup.top); | |
| 257 } | |
| 258 SetWidgetRect(rtPopup); | |
| 259 Update(); | |
| 260 } | |
| 261 } | |
| 262 CFWL_ToolTipImp::CFWL_ToolTipTimer::CFWL_ToolTipTimer(CFWL_ToolTipImp* pToolTip) | |
| 263 : m_pToolTip(pToolTip) {} | |
| 264 int32_t CFWL_ToolTipImp::CFWL_ToolTipTimer::Run(FWL_HTIMER hTimer) { | |
| 265 if (m_pToolTip->m_hTimerShow == hTimer && m_pToolTip->m_hTimerShow) { | |
| 266 if (m_pToolTip->GetStates() & FWL_WGTSTATE_Invisible) { | |
| 267 m_pToolTip->SetStates(FWL_WGTSTATE_Invisible, FALSE); | |
| 268 m_pToolTip->RefreshToolTipPos(); | |
| 269 FWL_StopTimer(m_pToolTip->m_hTimerShow); | |
| 270 m_pToolTip->m_hTimerShow = NULL; | |
| 271 return TRUE; | |
| 272 } | |
| 273 } | |
| 274 if (m_pToolTip->m_hTimerHide == hTimer && m_pToolTip->m_hTimerHide) { | |
| 275 m_pToolTip->SetStates(FWL_WGTSTATE_Invisible, TRUE); | |
| 276 FWL_StopTimer(m_pToolTip->m_hTimerHide); | |
| 277 m_pToolTip->m_hTimerHide = NULL; | |
| 278 return TRUE; | |
| 279 } | |
| 280 return TRUE; | |
| 281 } | |
| 282 CFWL_ToolTipImpDelegate::CFWL_ToolTipImpDelegate(CFWL_ToolTipImp* pOwner) | |
| 283 : m_pOwner(pOwner) {} | |
| 284 int32_t CFWL_ToolTipImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { | |
| 285 return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); | |
| 286 } | |
| 287 FWL_ERR CFWL_ToolTipImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { | |
| 288 return FWL_ERR_Succeeded; | |
| 289 } | |
| 290 FWL_ERR CFWL_ToolTipImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, | |
| 291 const CFX_Matrix* pMatrix) { | |
| 292 return m_pOwner->DrawWidget(pGraphics, pMatrix); | |
| 293 } | |
| OLD | NEW |