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
CFWL_Form(const CFWL_App * app,std::unique_ptr<CFWL_WidgetProperties> properties,CFWL_Widget * pOuter)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
~CFWL_Form()40 CFWL_Form::~CFWL_Form() {
41 UnregisterEventTarget();
42 UnRegisterForm();
43 }
44
GetClassID() const45 FWL_Type CFWL_Form::GetClassID() const {
46 return FWL_Type::Form;
47 }
48
IsInstance(const CFX_WideStringC & wsClass) const49 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
GetClientRect()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
Update()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
HitTest(const CFX_PointF & point)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
DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)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(¶m);
100 }
101 }
102
DoModal()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
EndDoModal()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
DrawBackground(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme)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(¶m);
159 }
160
GetEdgeRect()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
SetWorkAreaRect()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
Layout()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
RegisterForm()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
UnRegisterForm()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
OnProcessMessage(CFWL_Message * pMessage)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
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)241 void CFWL_Form::OnDrawWidget(CFX_Graphics* pGraphics,
242 const CFX_Matrix* pMatrix) {
243 DrawWidget(pGraphics, pMatrix);
244 }
245
OnLButtonDown(CFWL_MessageMouse * pMsg)246 void CFWL_Form::OnLButtonDown(CFWL_MessageMouse* pMsg) {
247 SetGrab(true);
248 }
249
OnLButtonUp(CFWL_MessageMouse * pMsg)250 void CFWL_Form::OnLButtonUp(CFWL_MessageMouse* pMsg) {
251 SetGrab(false);
252 }
253