Home | History | Annotate | Download | only in pwl
      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 "fpdfsdk/pwl/cpwl_caret.h"
      8 
      9 #include <sstream>
     10 
     11 #include "core/fxge/cfx_graphstatedata.h"
     12 #include "core/fxge/cfx_pathdata.h"
     13 #include "core/fxge/cfx_renderdevice.h"
     14 #include "fpdfsdk/pwl/cpwl_wnd.h"
     15 
     16 #define PWL_CARET_FLASHINTERVAL 500
     17 
     18 CPWL_Caret::CPWL_Caret() : m_bFlash(false), m_fWidth(0.4f), m_nDelay(0) {}
     19 
     20 CPWL_Caret::~CPWL_Caret() {}
     21 
     22 ByteString CPWL_Caret::GetClassName() const {
     23   return "CPWL_Caret";
     24 }
     25 
     26 void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice,
     27                                     const CFX_Matrix& mtUser2Device) {
     28   if (!IsVisible() || !m_bFlash)
     29     return;
     30 
     31   CFX_FloatRect rcRect = GetCaretRect();
     32   CFX_FloatRect rcClip = GetClipRect();
     33   CFX_PathData path;
     34 
     35   float fCaretX = rcRect.left + m_fWidth * 0.5f;
     36   float fCaretTop = rcRect.top;
     37   float fCaretBottom = rcRect.bottom;
     38   if (!rcClip.IsEmpty()) {
     39     rcRect.Intersect(rcClip);
     40     if (rcRect.IsEmpty())
     41       return;
     42 
     43     fCaretTop = rcRect.top;
     44     fCaretBottom = rcRect.bottom;
     45   }
     46 
     47   path.AppendPoint(CFX_PointF(fCaretX, fCaretBottom), FXPT_TYPE::MoveTo, false);
     48   path.AppendPoint(CFX_PointF(fCaretX, fCaretTop), FXPT_TYPE::LineTo, false);
     49 
     50   CFX_GraphStateData gsd;
     51   gsd.m_LineWidth = m_fWidth;
     52   pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0),
     53                     FXFILL_ALTERNATE);
     54 }
     55 
     56 void CPWL_Caret::TimerProc() {
     57   if (m_nDelay > 0) {
     58     --m_nDelay;
     59     return;
     60   }
     61 
     62   m_bFlash = !m_bFlash;
     63   InvalidateRect(nullptr);
     64   // Note, |this| may no longer be viable at this point. If more work needs
     65   // to be done, add an observer.
     66 }
     67 
     68 CFX_FloatRect CPWL_Caret::GetCaretRect() const {
     69   return CFX_FloatRect(m_ptFoot.x, m_ptFoot.y, m_ptHead.x + m_fWidth,
     70                        m_ptHead.y);
     71 }
     72 
     73 void CPWL_Caret::SetCaret(bool bVisible,
     74                           const CFX_PointF& ptHead,
     75                           const CFX_PointF& ptFoot) {
     76   if (!bVisible) {
     77     m_ptHead = CFX_PointF();
     78     m_ptFoot = CFX_PointF();
     79     m_bFlash = false;
     80     if (!IsVisible())
     81       return;
     82 
     83     EndTimer();
     84     CPWL_Wnd::SetVisible(false);
     85     // Note, |this| may no longer be viable at this point. If more work needs
     86     // to be done, check the return value of SetVisible().
     87     return;
     88   }
     89 
     90   if (!IsVisible()) {
     91     m_ptHead = ptHead;
     92     m_ptFoot = ptFoot;
     93     EndTimer();
     94     BeginTimer(PWL_CARET_FLASHINTERVAL);
     95 
     96     if (!CPWL_Wnd::SetVisible(true))
     97       return;
     98 
     99     m_bFlash = true;
    100     Move(m_rcInvalid, false, true);
    101     // Note, |this| may no longer be viable at this point. If more work needs
    102     // to be done, check the return value of Move().
    103     return;
    104   }
    105 
    106   if (m_ptHead == ptHead && m_ptFoot == ptFoot)
    107     return;
    108 
    109   m_ptHead = ptHead;
    110   m_ptFoot = ptFoot;
    111   m_bFlash = true;
    112   Move(m_rcInvalid, false, true);
    113   // Note, |this| may no longer be viable at this point. If more work
    114   // needs to be done, check the return value of Move().
    115 }
    116 
    117 bool CPWL_Caret::InvalidateRect(CFX_FloatRect* pRect) {
    118   if (!pRect) {
    119     return CPWL_Wnd::InvalidateRect(nullptr);
    120   }
    121 
    122   CFX_FloatRect rcRefresh = *pRect;
    123   if (!rcRefresh.IsEmpty()) {
    124     rcRefresh.Inflate(0.5f, 0.5f);
    125     rcRefresh.Normalize();
    126   }
    127   rcRefresh.top += 1;
    128   rcRefresh.bottom -= 1;
    129   return CPWL_Wnd::InvalidateRect(&rcRefresh);
    130 }
    131 
    132 bool CPWL_Caret::SetVisible(bool bVisible) {
    133   return true;
    134 }
    135