Home | History | Annotate | Download | only in fwl
      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/fwl/cfwl_form.h"
      8 
      9 #include <utility>
     10 
     11 #include "third_party/base/ptr_util.h"
     12 #include "xfa/fde/cfde_textout.h"
     13 #include "xfa/fwl/cfwl_app.h"
     14 #include "xfa/fwl/cfwl_event.h"
     15 #include "xfa/fwl/cfwl_formproxy.h"
     16 #include "xfa/fwl/cfwl_messagemouse.h"
     17 #include "xfa/fwl/cfwl_notedriver.h"
     18 #include "xfa/fwl/cfwl_noteloop.h"
     19 #include "xfa/fwl/cfwl_themebackground.h"
     20 #include "xfa/fwl/cfwl_themepart.h"
     21 #include "xfa/fwl/cfwl_themetext.h"
     22 #include "xfa/fwl/cfwl_widgetmgr.h"
     23 #include "xfa/fwl/ifwl_themeprovider.h"
     24 
     25 CFWL_Form::CFWL_Form(const CFWL_App* app,
     26                      std::unique_ptr<CFWL_WidgetProperties> properties,
     27                      CFWL_Widget* pOuter)
     28     : CFWL_Widget(app, std::move(properties), pOuter),
     29       m_pSubFocus(nullptr),
     30       m_fCXBorder(0),
     31       m_fCYBorder(0) {
     32   m_rtRelative.Reset();
     33   m_rtRestore.Reset();
     34 
     35   RegisterForm();
     36   RegisterEventTarget(nullptr);
     37 }
     38 
     39 CFWL_Form::~CFWL_Form() {
     40   UnregisterEventTarget();
     41   UnRegisterForm();
     42 }
     43 
     44 FWL_Type CFWL_Form::GetClassID() const {
     45   return FWL_Type::Form;
     46 }
     47 
     48 bool CFWL_Form::IsInstance(const WideStringView& wsClass) const {
     49   if (wsClass == WideStringView(FWL_CLASS_Form))
     50     return true;
     51   return CFWL_Widget::IsInstance(wsClass);
     52 }
     53 
     54 CFX_RectF CFWL_Form::GetClientRect() {
     55   CFX_RectF rect = m_pProperties->m_rtWidget;
     56   rect.Offset(-rect.left, -rect.top);
     57   return rect;
     58 }
     59 
     60 void CFWL_Form::Update() {
     61   if (m_iLock > 0)
     62     return;
     63   if (!m_pProperties->m_pThemeProvider)
     64     m_pProperties->m_pThemeProvider = GetAvailableTheme();
     65 
     66   Layout();
     67 }
     68 
     69 FWL_WidgetHit CFWL_Form::HitTest(const CFX_PointF& point) {
     70   GetAvailableTheme();
     71 
     72   CFX_RectF rtCap(m_fCYBorder, m_fCXBorder, -2 * m_fCYBorder, 0 - m_fCXBorder);
     73   return rtCap.Contains(point) ? FWL_WidgetHit::Titlebar
     74                                : FWL_WidgetHit::Client;
     75 }
     76 
     77 void CFWL_Form::DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) {
     78   if (!pGraphics)
     79     return;
     80   if (!m_pProperties->m_pThemeProvider)
     81     return;
     82 
     83   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
     84   DrawBackground(pGraphics, pTheme);
     85 
     86 #if _FX_OS_ == _FX_OS_MACOSX_
     87   return;
     88 #endif
     89   CFWL_ThemeBackground param;
     90   param.m_pWidget = this;
     91   param.m_dwStates = CFWL_PartState_Normal;
     92   param.m_pGraphics = pGraphics;
     93   param.m_rtPart = m_rtRelative;
     94   param.m_matrix.Concat(matrix);
     95   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) {
     96     param.m_iPart = CFWL_Part::Border;
     97     pTheme->DrawBackground(&param);
     98   }
     99 }
    100 
    101 CFWL_Widget* CFWL_Form::DoModal() {
    102   const CFWL_App* pApp = GetOwnerApp();
    103   if (!pApp)
    104     return nullptr;
    105 
    106   CFWL_NoteDriver* pDriver = pApp->GetNoteDriver();
    107   if (!pDriver)
    108     return nullptr;
    109 
    110   m_pNoteLoop = pdfium::MakeUnique<CFWL_NoteLoop>();
    111   m_pNoteLoop->SetMainForm(this);
    112 
    113   pDriver->PushNoteLoop(m_pNoteLoop.get());
    114   RemoveStates(FWL_WGTSTATE_Invisible);
    115   pDriver->Run();
    116 
    117 #if _FX_OS_ != _FX_OS_MACOSX_
    118   pDriver->PopNoteLoop();
    119 #endif
    120 
    121   m_pNoteLoop.reset();
    122   return nullptr;
    123 }
    124 
    125 void CFWL_Form::EndDoModal() {
    126   if (!m_pNoteLoop)
    127     return;
    128 
    129 #if (_FX_OS_ == _FX_OS_MACOSX_)
    130   m_pNoteLoop->EndModalLoop();
    131   const CFWL_App* pApp = GetOwnerApp();
    132   if (!pApp)
    133     return;
    134 
    135   CFWL_NoteDriver* pDriver =
    136       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
    137   if (!pDriver)
    138     return;
    139 
    140   pDriver->PopNoteLoop();
    141   SetStates(FWL_WGTSTATE_Invisible);
    142 #else
    143   SetStates(FWL_WGTSTATE_Invisible);
    144   m_pNoteLoop->EndModalLoop();
    145 #endif
    146 }
    147 
    148 void CFWL_Form::DrawBackground(CXFA_Graphics* pGraphics,
    149                                IFWL_ThemeProvider* pTheme) {
    150   CFWL_ThemeBackground param;
    151   param.m_pWidget = this;
    152   param.m_iPart = CFWL_Part::Background;
    153   param.m_pGraphics = pGraphics;
    154   param.m_rtPart = m_rtRelative;
    155   param.m_rtPart.Deflate(m_fCYBorder, m_fCXBorder, m_fCYBorder, m_fCXBorder);
    156   pTheme->DrawBackground(&param);
    157 }
    158 
    159 CFX_RectF CFWL_Form::GetEdgeRect() {
    160   CFX_RectF rtEdge = m_rtRelative;
    161   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border) {
    162     float fCX = GetBorderSize(true);
    163     float fCY = GetBorderSize(false);
    164     rtEdge.Deflate(fCX, fCY, fCX, fCY);
    165   }
    166   return rtEdge;
    167 }
    168 
    169 void CFWL_Form::SetWorkAreaRect() {
    170   m_rtRestore = m_pProperties->m_rtWidget;
    171   CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr();
    172   if (!pWidgetMgr)
    173     return;
    174   RepaintRect(m_rtRelative);
    175 }
    176 
    177 void CFWL_Form::Layout() {
    178   m_rtRelative = GetRelativeRect();
    179 
    180 #if _FX_OS_ == _FX_OS_MACOSX_
    181   IFWL_ThemeProvider* theme = GetAvailableTheme();
    182   m_fCXBorder = theme ? theme->GetCXBorderSize() : 0.0f;
    183   m_fCYBorder = theme ? theme->GetCYBorderSize() : 0.0f;
    184 #endif
    185 }
    186 
    187 void CFWL_Form::RegisterForm() {
    188   const CFWL_App* pApp = GetOwnerApp();
    189   if (!pApp)
    190     return;
    191 
    192   CFWL_NoteDriver* pDriver =
    193       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
    194   if (!pDriver)
    195     return;
    196 
    197   pDriver->RegisterForm(this);
    198 }
    199 
    200 void CFWL_Form::UnRegisterForm() {
    201   const CFWL_App* pApp = GetOwnerApp();
    202   if (!pApp)
    203     return;
    204 
    205   CFWL_NoteDriver* pDriver =
    206       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
    207   if (!pDriver)
    208     return;
    209 
    210   pDriver->UnRegisterForm(this);
    211 }
    212 
    213 void CFWL_Form::OnProcessMessage(CFWL_Message* pMessage) {
    214 #if _FX_OS_ == _FX_OS_MACOSX_
    215   if (!pMessage)
    216     return;
    217 
    218   switch (pMessage->GetType()) {
    219     case CFWL_Message::Type::Mouse: {
    220       CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
    221       switch (pMsg->m_dwCmd) {
    222         case FWL_MouseCommand::LeftButtonDown:
    223           OnLButtonDown(pMsg);
    224           break;
    225         case FWL_MouseCommand::LeftButtonUp:
    226           OnLButtonUp(pMsg);
    227           break;
    228         default:
    229           break;
    230       }
    231       break;
    232     }
    233     default:
    234       break;
    235   }
    236 #endif  // _FX_OS_ == _FX_OS_MACOSX_
    237 }
    238 
    239 void CFWL_Form::OnDrawWidget(CXFA_Graphics* pGraphics,
    240                              const CFX_Matrix& matrix) {
    241   DrawWidget(pGraphics, matrix);
    242 }
    243 
    244 void CFWL_Form::OnLButtonDown(CFWL_MessageMouse* pMsg) {
    245   SetGrab(true);
    246 }
    247 
    248 void CFWL_Form::OnLButtonUp(CFWL_MessageMouse* pMsg) {
    249   SetGrab(false);
    250 }
    251