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