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