1 // Copyright 2014 The PDFium Authors
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 "fpdfsdk/formfiller/cffl_radiobutton.h"
8
9 #include <utility>
10
11 #include "constants/ascii.h"
12 #include "core/fpdfdoc/cpdf_formcontrol.h"
13 #include "fpdfsdk/cpdfsdk_widget.h"
14 #include "fpdfsdk/formfiller/cffl_formfield.h"
15 #include "fpdfsdk/pwl/cpwl_special_button.h"
16 #include "public/fpdf_fwlevent.h"
17 #include "third_party/base/check.h"
18
CFFL_RadioButton(CFFL_InteractiveFormFiller * pFormFiller,CPDFSDK_Widget * pWidget)19 CFFL_RadioButton::CFFL_RadioButton(CFFL_InteractiveFormFiller* pFormFiller,
20 CPDFSDK_Widget* pWidget)
21 : CFFL_Button(pFormFiller, pWidget) {}
22
23 CFFL_RadioButton::~CFFL_RadioButton() = default;
24
NewPWLWindow(const CPWL_Wnd::CreateParams & cp,std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData)25 std::unique_ptr<CPWL_Wnd> CFFL_RadioButton::NewPWLWindow(
26 const CPWL_Wnd::CreateParams& cp,
27 std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData) {
28 auto pWnd = std::make_unique<CPWL_RadioButton>(cp, std::move(pAttachedData));
29 pWnd->Realize();
30 pWnd->SetCheck(m_pWidget->IsChecked());
31 return std::move(pWnd);
32 }
33
OnKeyDown(FWL_VKEYCODE nKeyCode,Mask<FWL_EVENTFLAG> nFlags)34 bool CFFL_RadioButton::OnKeyDown(FWL_VKEYCODE nKeyCode,
35 Mask<FWL_EVENTFLAG> nFlags) {
36 switch (nKeyCode) {
37 case FWL_VKEY_Return:
38 case FWL_VKEY_Space:
39 return true;
40 default:
41 return CFFL_FormField::OnKeyDown(nKeyCode, nFlags);
42 }
43 }
44
OnChar(CPDFSDK_Widget * pWidget,uint32_t nChar,Mask<FWL_EVENTFLAG> nFlags)45 bool CFFL_RadioButton::OnChar(CPDFSDK_Widget* pWidget,
46 uint32_t nChar,
47 Mask<FWL_EVENTFLAG> nFlags) {
48 switch (nChar) {
49 case pdfium::ascii::kReturn:
50 case pdfium::ascii::kSpace: {
51 CPDFSDK_PageView* pPageView = pWidget->GetPageView();
52 DCHECK(pPageView);
53
54 ObservedPtr<CPDFSDK_Widget> pObserved(m_pWidget);
55 if (m_pFormFiller->OnButtonUp(pObserved, pPageView, nFlags) ||
56 !pObserved) {
57 return true;
58 }
59
60 CFFL_FormField::OnChar(pWidget, nChar, nFlags);
61 CPWL_RadioButton* pWnd = CreateOrUpdatePWLRadioButton(pPageView);
62 if (pWnd && !pWnd->IsReadOnly())
63 pWnd->SetCheck(true);
64 return CommitData(pPageView, nFlags);
65 }
66 default:
67 return CFFL_FormField::OnChar(pWidget, nChar, nFlags);
68 }
69 }
70
OnLButtonUp(CPDFSDK_PageView * pPageView,CPDFSDK_Widget * pWidget,Mask<FWL_EVENTFLAG> nFlags,const CFX_PointF & point)71 bool CFFL_RadioButton::OnLButtonUp(CPDFSDK_PageView* pPageView,
72 CPDFSDK_Widget* pWidget,
73 Mask<FWL_EVENTFLAG> nFlags,
74 const CFX_PointF& point) {
75 CFFL_Button::OnLButtonUp(pPageView, pWidget, nFlags, point);
76
77 if (!IsValid())
78 return true;
79
80 CPWL_RadioButton* pWnd = CreateOrUpdatePWLRadioButton(pPageView);
81 if (pWnd)
82 pWnd->SetCheck(true);
83
84 return CommitData(pPageView, nFlags);
85 }
86
IsDataChanged(const CPDFSDK_PageView * pPageView)87 bool CFFL_RadioButton::IsDataChanged(const CPDFSDK_PageView* pPageView) {
88 CPWL_RadioButton* pWnd = GetPWLRadioButton(pPageView);
89 return pWnd && pWnd->IsChecked() != m_pWidget->IsChecked();
90 }
91
SaveData(const CPDFSDK_PageView * pPageView)92 void CFFL_RadioButton::SaveData(const CPDFSDK_PageView* pPageView) {
93 CPWL_RadioButton* pWnd = GetPWLRadioButton(pPageView);
94 if (!pWnd)
95 return;
96
97 bool bNewChecked = pWnd->IsChecked();
98 ObservedPtr<CPDFSDK_Widget> observed_widget(m_pWidget);
99 ObservedPtr<CFFL_RadioButton> observed_this(this);
100 m_pWidget->SetCheck(bNewChecked);
101 if (!observed_widget)
102 return;
103
104 m_pWidget->UpdateField();
105 if (!observed_widget || !observed_this)
106 return;
107
108 SetChangeMark();
109 }
110
GetPWLRadioButton(const CPDFSDK_PageView * pPageView) const111 CPWL_RadioButton* CFFL_RadioButton::GetPWLRadioButton(
112 const CPDFSDK_PageView* pPageView) const {
113 return static_cast<CPWL_RadioButton*>(GetPWLWindow(pPageView));
114 }
115
CreateOrUpdatePWLRadioButton(const CPDFSDK_PageView * pPageView)116 CPWL_RadioButton* CFFL_RadioButton::CreateOrUpdatePWLRadioButton(
117 const CPDFSDK_PageView* pPageView) {
118 return static_cast<CPWL_RadioButton*>(CreateOrUpdatePWLWindow(pPageView));
119 }
120