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_widget.h"
8
9 #include <algorithm>
10 #include <utility>
11 #include <vector>
12
13 #include "third_party/base/stl_util.h"
14 #include "xfa/fde/tto/fde_textout.h"
15 #include "xfa/fwl/cfwl_app.h"
16 #include "xfa/fwl/cfwl_combobox.h"
17 #include "xfa/fwl/cfwl_event.h"
18 #include "xfa/fwl/cfwl_eventmouse.h"
19 #include "xfa/fwl/cfwl_form.h"
20 #include "xfa/fwl/cfwl_messagekey.h"
21 #include "xfa/fwl/cfwl_messagekillfocus.h"
22 #include "xfa/fwl/cfwl_messagemouse.h"
23 #include "xfa/fwl/cfwl_messagemousewheel.h"
24 #include "xfa/fwl/cfwl_messagesetfocus.h"
25 #include "xfa/fwl/cfwl_notedriver.h"
26 #include "xfa/fwl/cfwl_themebackground.h"
27 #include "xfa/fwl/cfwl_themepart.h"
28 #include "xfa/fwl/cfwl_themetext.h"
29 #include "xfa/fwl/cfwl_widgetmgr.h"
30 #include "xfa/fwl/ifwl_themeprovider.h"
31 #include "xfa/fxfa/xfa_ffapp.h"
32
33 #define FWL_STYLEEXT_MNU_Vert (1L << 0)
34 #define FWL_WGT_CalcHeight 2048
35 #define FWL_WGT_CalcWidth 2048
36 #define FWL_WGT_CalcMultiLineDefWidth 120.0f
37
CFWL_Widget(const CFWL_App * app,std::unique_ptr<CFWL_WidgetProperties> properties,CFWL_Widget * pOuter)38 CFWL_Widget::CFWL_Widget(const CFWL_App* app,
39 std::unique_ptr<CFWL_WidgetProperties> properties,
40 CFWL_Widget* pOuter)
41 : m_pOwnerApp(app),
42 m_pWidgetMgr(app->GetWidgetMgr()),
43 m_pProperties(std::move(properties)),
44 m_pOuter(pOuter),
45 m_iLock(0),
46 m_pLayoutItem(nullptr),
47 m_nEventKey(0),
48 m_pDelegate(nullptr) {
49 ASSERT(m_pWidgetMgr);
50
51 CFWL_Widget* pParent = m_pProperties->m_pParent;
52 m_pWidgetMgr->InsertWidget(pParent, this);
53 if (IsChild())
54 return;
55
56 CFWL_Widget* pOwner = m_pProperties->m_pOwner;
57 if (pOwner)
58 m_pWidgetMgr->SetOwner(pOwner, this);
59 }
60
~CFWL_Widget()61 CFWL_Widget::~CFWL_Widget() {
62 NotifyDriver();
63 m_pWidgetMgr->RemoveWidget(this);
64 }
65
IsInstance(const CFX_WideStringC & wsClass) const66 bool CFWL_Widget::IsInstance(const CFX_WideStringC& wsClass) const {
67 return false;
68 }
69
GetAutosizedWidgetRect()70 CFX_RectF CFWL_Widget::GetAutosizedWidgetRect() {
71 return CFX_RectF();
72 }
73
GetWidgetRect()74 CFX_RectF CFWL_Widget::GetWidgetRect() {
75 return m_pProperties->m_rtWidget;
76 }
77
InflateWidgetRect(CFX_RectF & rect)78 void CFWL_Widget::InflateWidgetRect(CFX_RectF& rect) {
79 if (HasBorder()) {
80 FX_FLOAT fBorder = GetBorderSize(true);
81 rect.Inflate(fBorder, fBorder);
82 }
83 }
84
SetWidgetRect(const CFX_RectF & rect)85 void CFWL_Widget::SetWidgetRect(const CFX_RectF& rect) {
86 m_pProperties->m_rtWidget = rect;
87 }
88
GetClientRect()89 CFX_RectF CFWL_Widget::GetClientRect() {
90 return GetEdgeRect();
91 }
92
SetParent(CFWL_Widget * pParent)93 void CFWL_Widget::SetParent(CFWL_Widget* pParent) {
94 m_pProperties->m_pParent = pParent;
95 m_pWidgetMgr->SetParent(pParent, this);
96 }
97
GetStyles() const98 uint32_t CFWL_Widget::GetStyles() const {
99 return m_pProperties->m_dwStyles;
100 }
101
ModifyStyles(uint32_t dwStylesAdded,uint32_t dwStylesRemoved)102 void CFWL_Widget::ModifyStyles(uint32_t dwStylesAdded,
103 uint32_t dwStylesRemoved) {
104 m_pProperties->m_dwStyles =
105 (m_pProperties->m_dwStyles & ~dwStylesRemoved) | dwStylesAdded;
106 }
107
GetStylesEx() const108 uint32_t CFWL_Widget::GetStylesEx() const {
109 return m_pProperties->m_dwStyleExes;
110 }
GetStates() const111 uint32_t CFWL_Widget::GetStates() const {
112 return m_pProperties->m_dwStates;
113 }
114
ModifyStylesEx(uint32_t dwStylesExAdded,uint32_t dwStylesExRemoved)115 void CFWL_Widget::ModifyStylesEx(uint32_t dwStylesExAdded,
116 uint32_t dwStylesExRemoved) {
117 m_pProperties->m_dwStyleExes =
118 (m_pProperties->m_dwStyleExes & ~dwStylesExRemoved) | dwStylesExAdded;
119 }
120
NotifyHideChildWidget(CFWL_WidgetMgr * widgetMgr,CFWL_Widget * widget,CFWL_NoteDriver * noteDriver)121 static void NotifyHideChildWidget(CFWL_WidgetMgr* widgetMgr,
122 CFWL_Widget* widget,
123 CFWL_NoteDriver* noteDriver) {
124 CFWL_Widget* child = widgetMgr->GetFirstChildWidget(widget);
125 while (child) {
126 noteDriver->NotifyTargetHide(child);
127 NotifyHideChildWidget(widgetMgr, child, noteDriver);
128 child = widgetMgr->GetNextSiblingWidget(child);
129 }
130 }
131
SetStates(uint32_t dwStates)132 void CFWL_Widget::SetStates(uint32_t dwStates) {
133 m_pProperties->m_dwStates |= dwStates;
134 if (!(dwStates & FWL_WGTSTATE_Invisible))
135 return;
136
137 CFWL_NoteDriver* noteDriver =
138 static_cast<CFWL_NoteDriver*>(GetOwnerApp()->GetNoteDriver());
139 CFWL_WidgetMgr* widgetMgr = GetOwnerApp()->GetWidgetMgr();
140 noteDriver->NotifyTargetHide(this);
141 CFWL_Widget* child = widgetMgr->GetFirstChildWidget(this);
142 while (child) {
143 noteDriver->NotifyTargetHide(child);
144 NotifyHideChildWidget(widgetMgr, child, noteDriver);
145 child = widgetMgr->GetNextSiblingWidget(child);
146 }
147 return;
148 }
149
RemoveStates(uint32_t dwStates)150 void CFWL_Widget::RemoveStates(uint32_t dwStates) {
151 m_pProperties->m_dwStates &= ~dwStates;
152 }
153
HitTest(const CFX_PointF & point)154 FWL_WidgetHit CFWL_Widget::HitTest(const CFX_PointF& point) {
155 if (GetClientRect().Contains(point))
156 return FWL_WidgetHit::Client;
157 if (HasBorder() && GetRelativeRect().Contains(point))
158 return FWL_WidgetHit::Border;
159 return FWL_WidgetHit::Unknown;
160 }
161
TransformTo(CFWL_Widget * pWidget,const CFX_PointF & point)162 CFX_PointF CFWL_Widget::TransformTo(CFWL_Widget* pWidget,
163 const CFX_PointF& point) {
164 if (m_pWidgetMgr->IsFormDisabled()) {
165 CFX_SizeF szOffset;
166 if (IsParent(pWidget)) {
167 szOffset = GetOffsetFromParent(pWidget);
168 } else {
169 szOffset = pWidget->GetOffsetFromParent(this);
170 szOffset.width = -szOffset.width;
171 szOffset.height = -szOffset.height;
172 }
173 return point + CFX_PointF(szOffset.width, szOffset.height);
174 }
175
176 CFX_PointF ret = point;
177 CFWL_Widget* parent = GetParent();
178 if (parent)
179 ret = GetMatrix().Transform(ret + GetWidgetRect().TopLeft());
180
181 CFWL_Widget* form1 = m_pWidgetMgr->GetSystemFormWidget(this);
182 if (!form1)
183 return ret;
184
185 if (!pWidget)
186 return ret + form1->GetWidgetRect().TopLeft();
187
188 CFWL_Widget* form2 = m_pWidgetMgr->GetSystemFormWidget(pWidget);
189 if (!form2)
190 return ret;
191 if (form1 != form2) {
192 ret += form1->GetWidgetRect().TopLeft();
193 ret -= form2->GetWidgetRect().TopLeft();
194 }
195
196 parent = pWidget->GetParent();
197 if (!parent)
198 return ret;
199
200 CFX_Matrix m;
201 m.SetReverse(pWidget->GetMatrix());
202 return m.Transform(ret) - pWidget->GetWidgetRect().TopLeft();
203 }
204
GetMatrix()205 CFX_Matrix CFWL_Widget::GetMatrix() {
206 if (!m_pProperties)
207 return CFX_Matrix();
208
209 CFWL_Widget* parent = GetParent();
210 std::vector<CFWL_Widget*> parents;
211 while (parent) {
212 parents.push_back(parent);
213 parent = parent->GetParent();
214 }
215
216 CFX_Matrix matrix;
217 CFX_Matrix ctmOnParent;
218 CFX_RectF rect;
219 int32_t count = pdfium::CollectionSize<int32_t>(parents);
220 for (int32_t i = count - 2; i >= 0; i--) {
221 parent = parents[i];
222 if (parent->m_pProperties)
223 ctmOnParent.SetIdentity();
224 rect = parent->GetWidgetRect();
225 matrix.Concat(ctmOnParent, true);
226 matrix.Translate(rect.left, rect.top, true);
227 }
228 CFX_Matrix m;
229 m.SetIdentity();
230 matrix.Concat(m, true);
231 parents.clear();
232 return matrix;
233 }
234
GetThemeProvider() const235 IFWL_ThemeProvider* CFWL_Widget::GetThemeProvider() const {
236 return m_pProperties->m_pThemeProvider;
237 }
238
SetThemeProvider(IFWL_ThemeProvider * pThemeProvider)239 void CFWL_Widget::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
240 m_pProperties->m_pThemeProvider = pThemeProvider;
241 }
242
IsEnabled() const243 bool CFWL_Widget::IsEnabled() const {
244 return (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 0;
245 }
246
HasBorder() const247 bool CFWL_Widget::HasBorder() const {
248 return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border);
249 }
250
IsVisible() const251 bool CFWL_Widget::IsVisible() const {
252 return (m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) == 0;
253 }
254
IsOverLapper() const255 bool CFWL_Widget::IsOverLapper() const {
256 return (m_pProperties->m_dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
257 FWL_WGTSTYLE_OverLapper;
258 }
259
IsPopup() const260 bool CFWL_Widget::IsPopup() const {
261 return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Popup);
262 }
263
IsChild() const264 bool CFWL_Widget::IsChild() const {
265 return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Child);
266 }
267
GetEdgeRect()268 CFX_RectF CFWL_Widget::GetEdgeRect() {
269 CFX_RectF rtEdge(0, 0, m_pProperties->m_rtWidget.width,
270 m_pProperties->m_rtWidget.height);
271 if (HasBorder()) {
272 FX_FLOAT fCX = GetBorderSize(true);
273 FX_FLOAT fCY = GetBorderSize(false);
274 rtEdge.Deflate(fCX, fCY);
275 }
276 return rtEdge;
277 }
278
GetBorderSize(bool bCX)279 FX_FLOAT CFWL_Widget::GetBorderSize(bool bCX) {
280 IFWL_ThemeProvider* theme = GetAvailableTheme();
281 if (!theme)
282 return 0.0f;
283 return bCX ? theme->GetCXBorderSize() : theme->GetCYBorderSize();
284 }
285
GetRelativeRect()286 CFX_RectF CFWL_Widget::GetRelativeRect() {
287 return CFX_RectF(0, 0, m_pProperties->m_rtWidget.width,
288 m_pProperties->m_rtWidget.height);
289 }
290
GetAvailableTheme()291 IFWL_ThemeProvider* CFWL_Widget::GetAvailableTheme() {
292 if (m_pProperties->m_pThemeProvider)
293 return m_pProperties->m_pThemeProvider;
294
295 CFWL_Widget* pUp = this;
296 do {
297 pUp = (pUp->GetStyles() & FWL_WGTSTYLE_Popup)
298 ? m_pWidgetMgr->GetOwnerWidget(pUp)
299 : m_pWidgetMgr->GetParentWidget(pUp);
300 if (pUp) {
301 IFWL_ThemeProvider* pRet = pUp->GetThemeProvider();
302 if (pRet)
303 return pRet;
304 }
305 } while (pUp);
306 return nullptr;
307 }
308
GetRootOuter()309 CFWL_Widget* CFWL_Widget::GetRootOuter() {
310 CFWL_Widget* pRet = m_pOuter;
311 if (!pRet)
312 return nullptr;
313
314 while (CFWL_Widget* pOuter = pRet->GetOuter())
315 pRet = pOuter;
316 return pRet;
317 }
318
CalcTextSize(const CFX_WideString & wsText,IFWL_ThemeProvider * pTheme,bool bMultiLine)319 CFX_SizeF CFWL_Widget::CalcTextSize(const CFX_WideString& wsText,
320 IFWL_ThemeProvider* pTheme,
321 bool bMultiLine) {
322 if (!pTheme)
323 return CFX_SizeF();
324
325 CFWL_ThemeText calPart;
326 calPart.m_pWidget = this;
327 calPart.m_wsText = wsText;
328 calPart.m_dwTTOStyles =
329 bMultiLine ? FDE_TTOSTYLE_LineWrap : FDE_TTOSTYLE_SingleLine;
330 calPart.m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
331 FX_FLOAT fWidth =
332 bMultiLine ? FWL_WGT_CalcMultiLineDefWidth : FWL_WGT_CalcWidth;
333 CFX_RectF rect(0, 0, fWidth, FWL_WGT_CalcHeight);
334 pTheme->CalcTextRect(&calPart, rect);
335 return CFX_SizeF(rect.width, rect.height);
336 }
337
CalcTextRect(const CFX_WideString & wsText,IFWL_ThemeProvider * pTheme,uint32_t dwTTOStyles,int32_t iTTOAlign,CFX_RectF & rect)338 void CFWL_Widget::CalcTextRect(const CFX_WideString& wsText,
339 IFWL_ThemeProvider* pTheme,
340 uint32_t dwTTOStyles,
341 int32_t iTTOAlign,
342 CFX_RectF& rect) {
343 CFWL_ThemeText calPart;
344 calPart.m_pWidget = this;
345 calPart.m_wsText = wsText;
346 calPart.m_dwTTOStyles = dwTTOStyles;
347 calPart.m_iTTOAlign = iTTOAlign;
348 pTheme->CalcTextRect(&calPart, rect);
349 }
350
SetFocus(bool bFocus)351 void CFWL_Widget::SetFocus(bool bFocus) {
352 if (m_pWidgetMgr->IsFormDisabled())
353 return;
354
355 const CFWL_App* pApp = GetOwnerApp();
356 if (!pApp)
357 return;
358
359 CFWL_NoteDriver* pDriver =
360 static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
361 if (!pDriver)
362 return;
363
364 CFWL_Widget* curFocus = pDriver->GetFocus();
365 if (bFocus && curFocus != this)
366 pDriver->SetFocus(this);
367 else if (!bFocus && curFocus == this)
368 pDriver->SetFocus(nullptr);
369 }
370
SetGrab(bool bSet)371 void CFWL_Widget::SetGrab(bool bSet) {
372 const CFWL_App* pApp = GetOwnerApp();
373 if (!pApp)
374 return;
375
376 CFWL_NoteDriver* pDriver =
377 static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
378 pDriver->SetGrab(this, bSet);
379 }
380
GetPopupPos(FX_FLOAT fMinHeight,FX_FLOAT fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF & rtPopup)381 void CFWL_Widget::GetPopupPos(FX_FLOAT fMinHeight,
382 FX_FLOAT fMaxHeight,
383 const CFX_RectF& rtAnchor,
384 CFX_RectF& rtPopup) {
385 if (GetClassID() == FWL_Type::ComboBox) {
386 if (m_pWidgetMgr->IsFormDisabled()) {
387 m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
388 rtPopup);
389 return;
390 }
391 GetPopupPosComboBox(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
392 return;
393 }
394 if (GetClassID() == FWL_Type::DateTimePicker &&
395 m_pWidgetMgr->IsFormDisabled()) {
396 m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
397 rtPopup);
398 return;
399 }
400 GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
401 }
402
GetPopupPosMenu(FX_FLOAT fMinHeight,FX_FLOAT fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF & rtPopup)403 bool CFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight,
404 FX_FLOAT fMaxHeight,
405 const CFX_RectF& rtAnchor,
406 CFX_RectF& rtPopup) {
407 if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) {
408 bool bLeft = m_pProperties->m_rtWidget.left < 0;
409 FX_FLOAT fRight = rtAnchor.right() + rtPopup.width;
410 CFX_PointF point = TransformTo(nullptr, CFX_PointF());
411 if (fRight + point.x > 0.0f || bLeft) {
412 rtPopup = CFX_RectF(rtAnchor.left - rtPopup.width, rtAnchor.top,
413 rtPopup.width, rtPopup.height);
414 } else {
415 rtPopup = CFX_RectF(rtAnchor.right(), rtAnchor.top, rtPopup.width,
416 rtPopup.height);
417 }
418 rtPopup.Offset(point.x, point.y);
419 return true;
420 }
421
422 FX_FLOAT fBottom = rtAnchor.bottom() + rtPopup.height;
423 CFX_PointF point = TransformTo(nullptr, point);
424 if (fBottom + point.y > 0.0f) {
425 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height,
426 rtPopup.width, rtPopup.height);
427 } else {
428 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
429 rtPopup.height);
430 }
431 rtPopup.Offset(point.x, point.y);
432 return true;
433 }
434
GetPopupPosComboBox(FX_FLOAT fMinHeight,FX_FLOAT fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF & rtPopup)435 bool CFWL_Widget::GetPopupPosComboBox(FX_FLOAT fMinHeight,
436 FX_FLOAT fMaxHeight,
437 const CFX_RectF& rtAnchor,
438 CFX_RectF& rtPopup) {
439 FX_FLOAT fPopHeight = rtPopup.height;
440 if (rtPopup.height > fMaxHeight)
441 fPopHeight = fMaxHeight;
442 else if (rtPopup.height < fMinHeight)
443 fPopHeight = fMinHeight;
444
445 FX_FLOAT fWidth = std::max(rtAnchor.width, rtPopup.width);
446 FX_FLOAT fBottom = rtAnchor.bottom() + fPopHeight;
447 CFX_PointF point = TransformTo(nullptr, CFX_PointF());
448 if (fBottom + point.y > 0.0f) {
449 rtPopup =
450 CFX_RectF(rtAnchor.left, rtAnchor.top - fPopHeight, fWidth, fPopHeight);
451 } else {
452 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), fWidth, fPopHeight);
453 }
454
455 rtPopup.Offset(point.x, point.y);
456 return true;
457 }
458
GetPopupPosGeneral(FX_FLOAT fMinHeight,FX_FLOAT fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF & rtPopup)459 bool CFWL_Widget::GetPopupPosGeneral(FX_FLOAT fMinHeight,
460 FX_FLOAT fMaxHeight,
461 const CFX_RectF& rtAnchor,
462 CFX_RectF& rtPopup) {
463 CFX_PointF point = TransformTo(nullptr, CFX_PointF());
464 if (rtAnchor.bottom() + point.y > 0.0f) {
465 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height,
466 rtPopup.width, rtPopup.height);
467 } else {
468 rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
469 rtPopup.height);
470 }
471 rtPopup.Offset(point.x, point.y);
472 return true;
473 }
474
RegisterEventTarget(CFWL_Widget * pEventSource)475 void CFWL_Widget::RegisterEventTarget(CFWL_Widget* pEventSource) {
476 const CFWL_App* pApp = GetOwnerApp();
477 if (!pApp)
478 return;
479
480 CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
481 if (!pNoteDriver)
482 return;
483
484 pNoteDriver->RegisterEventTarget(this, pEventSource);
485 }
486
UnregisterEventTarget()487 void CFWL_Widget::UnregisterEventTarget() {
488 const CFWL_App* pApp = GetOwnerApp();
489 if (!pApp)
490 return;
491
492 CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
493 if (!pNoteDriver)
494 return;
495
496 pNoteDriver->UnregisterEventTarget(this);
497 }
498
DispatchEvent(CFWL_Event * pEvent)499 void CFWL_Widget::DispatchEvent(CFWL_Event* pEvent) {
500 if (m_pOuter) {
501 m_pOuter->GetDelegate()->OnProcessEvent(pEvent);
502 return;
503 }
504 const CFWL_App* pApp = GetOwnerApp();
505 if (!pApp)
506 return;
507
508 CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
509 if (!pNoteDriver)
510 return;
511 pNoteDriver->SendEvent(pEvent);
512 }
513
Repaint()514 void CFWL_Widget::Repaint() {
515 RepaintRect(CFX_RectF(0, 0, m_pProperties->m_rtWidget.width,
516 m_pProperties->m_rtWidget.height));
517 }
518
RepaintRect(const CFX_RectF & pRect)519 void CFWL_Widget::RepaintRect(const CFX_RectF& pRect) {
520 m_pWidgetMgr->RepaintWidget(this, pRect);
521 }
522
DrawBackground(CFX_Graphics * pGraphics,CFWL_Part iPartBk,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)523 void CFWL_Widget::DrawBackground(CFX_Graphics* pGraphics,
524 CFWL_Part iPartBk,
525 IFWL_ThemeProvider* pTheme,
526 const CFX_Matrix* pMatrix) {
527 CFWL_ThemeBackground param;
528 param.m_pWidget = this;
529 param.m_iPart = iPartBk;
530 param.m_pGraphics = pGraphics;
531 if (pMatrix)
532 param.m_matrix.Concat(*pMatrix, true);
533 param.m_rtPart = GetRelativeRect();
534 pTheme->DrawBackground(¶m);
535 }
536
DrawBorder(CFX_Graphics * pGraphics,CFWL_Part iPartBorder,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)537 void CFWL_Widget::DrawBorder(CFX_Graphics* pGraphics,
538 CFWL_Part iPartBorder,
539 IFWL_ThemeProvider* pTheme,
540 const CFX_Matrix* pMatrix) {
541 CFWL_ThemeBackground param;
542 param.m_pWidget = this;
543 param.m_iPart = iPartBorder;
544 param.m_pGraphics = pGraphics;
545 if (pMatrix)
546 param.m_matrix.Concat(*pMatrix, true);
547 param.m_rtPart = GetRelativeRect();
548 pTheme->DrawBackground(¶m);
549 }
550
NotifyDriver()551 void CFWL_Widget::NotifyDriver() {
552 const CFWL_App* pApp = GetOwnerApp();
553 if (!pApp)
554 return;
555
556 CFWL_NoteDriver* pDriver =
557 static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
558 if (!pDriver)
559 return;
560
561 pDriver->NotifyTargetDestroy(this);
562 }
563
GetOffsetFromParent(CFWL_Widget * pParent)564 CFX_SizeF CFWL_Widget::GetOffsetFromParent(CFWL_Widget* pParent) {
565 if (pParent == this)
566 return CFX_SizeF();
567
568 CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr();
569 if (!pWidgetMgr)
570 return CFX_SizeF();
571
572 CFX_SizeF szRet(m_pProperties->m_rtWidget.left,
573 m_pProperties->m_rtWidget.top);
574
575 CFWL_Widget* pDstWidget = GetParent();
576 while (pDstWidget && pDstWidget != pParent) {
577 CFX_RectF rtDst = pDstWidget->GetWidgetRect();
578 szRet += CFX_SizeF(rtDst.left, rtDst.top);
579 pDstWidget = pWidgetMgr->GetParentWidget(pDstWidget);
580 }
581 return szRet;
582 }
583
IsParent(CFWL_Widget * pParent)584 bool CFWL_Widget::IsParent(CFWL_Widget* pParent) {
585 CFWL_Widget* pUpWidget = GetParent();
586 while (pUpWidget) {
587 if (pUpWidget == pParent)
588 return true;
589 pUpWidget = pUpWidget->GetParent();
590 }
591 return false;
592 }
593
OnProcessMessage(CFWL_Message * pMessage)594 void CFWL_Widget::OnProcessMessage(CFWL_Message* pMessage) {
595 if (!pMessage->m_pDstTarget)
596 return;
597
598 CFWL_Widget* pWidget = pMessage->m_pDstTarget;
599 switch (pMessage->GetType()) {
600 case CFWL_Message::Type::Mouse: {
601 CFWL_MessageMouse* pMsgMouse = static_cast<CFWL_MessageMouse*>(pMessage);
602
603 CFWL_EventMouse evt(pWidget, pWidget);
604 evt.m_dwCmd = pMsgMouse->m_dwCmd;
605 pWidget->DispatchEvent(&evt);
606 break;
607 }
608 default:
609 break;
610 }
611 }
612
OnProcessEvent(CFWL_Event * pEvent)613 void CFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {}
614
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)615 void CFWL_Widget::OnDrawWidget(CFX_Graphics* pGraphics,
616 const CFX_Matrix* pMatrix) {}
617