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 
CFWL_Form(const CFWL_App * app,std::unique_ptr<CFWL_WidgetProperties> properties,CFWL_Widget * pOuter)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 
~CFWL_Form()39 CFWL_Form::~CFWL_Form() {
40   UnregisterEventTarget();
41   UnRegisterForm();
42 }
43 
GetClassID() const44 FWL_Type CFWL_Form::GetClassID() const {
45   return FWL_Type::Form;
46 }
47 
IsInstance(const WideStringView & wsClass) const48 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 
GetClientRect()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 
Update()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 
HitTest(const CFX_PointF & point)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 
DrawWidget(CXFA_Graphics * pGraphics,const CFX_Matrix & matrix)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 
DoModal()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 
EndDoModal()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 
DrawBackground(CXFA_Graphics * pGraphics,IFWL_ThemeProvider * pTheme)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 
GetEdgeRect()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 
SetWorkAreaRect()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 
Layout()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 
RegisterForm()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 
UnRegisterForm()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 
OnProcessMessage(CFWL_Message * pMessage)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 
OnDrawWidget(CXFA_Graphics * pGraphics,const CFX_Matrix & matrix)239 void CFWL_Form::OnDrawWidget(CXFA_Graphics* pGraphics,
240                              const CFX_Matrix& matrix) {
241   DrawWidget(pGraphics, matrix);
242 }
243 
OnLButtonDown(CFWL_MessageMouse * pMsg)244 void CFWL_Form::OnLButtonDown(CFWL_MessageMouse* pMsg) {
245   SetGrab(true);
246 }
247 
OnLButtonUp(CFWL_MessageMouse * pMsg)248 void CFWL_Form::OnLButtonUp(CFWL_MessageMouse* pMsg) {
249   SetGrab(false);
250 }
251