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