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/fxfa/app/xfa_ffpushbutton.h"
8
9 #include "xfa/fwl/cfwl_notedriver.h"
10 #include "xfa/fwl/cfwl_pushbutton.h"
11 #include "xfa/fwl/cfwl_widgetmgr.h"
12 #include "xfa/fxfa/app/cxfa_textlayout.h"
13 #include "xfa/fxfa/app/xfa_fffield.h"
14 #include "xfa/fxfa/app/xfa_ffwidgetacc.h"
15 #include "xfa/fxfa/xfa_ffapp.h"
16 #include "xfa/fxfa/xfa_ffpageview.h"
17 #include "xfa/fxfa/xfa_ffwidget.h"
18 #include "xfa/fxgraphics/cfx_color.h"
19 #include "xfa/fxgraphics/cfx_path.h"
20
CXFA_FFPushButton(CXFA_WidgetAcc * pDataAcc)21 CXFA_FFPushButton::CXFA_FFPushButton(CXFA_WidgetAcc* pDataAcc)
22 : CXFA_FFField(pDataAcc),
23 m_pRolloverTextLayout(nullptr),
24 m_pDownTextLayout(nullptr),
25 m_pDownProvider(nullptr),
26 m_pRollProvider(nullptr),
27 m_pOldDelegate(nullptr) {}
28
~CXFA_FFPushButton()29 CXFA_FFPushButton::~CXFA_FFPushButton() {
30 CXFA_FFPushButton::UnloadWidget();
31 }
32
RenderWidget(CFX_Graphics * pGS,CFX_Matrix * pMatrix,uint32_t dwStatus)33 void CXFA_FFPushButton::RenderWidget(CFX_Graphics* pGS,
34 CFX_Matrix* pMatrix,
35 uint32_t dwStatus) {
36 if (!IsMatchVisibleStatus(dwStatus))
37 return;
38
39 CFX_Matrix mtRotate = GetRotateMatrix();
40 if (pMatrix)
41 mtRotate.Concat(*pMatrix);
42
43 CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus);
44 RenderHighlightCaption(pGS, &mtRotate);
45
46 CFX_RectF rtWidget = GetRectWithoutRotate();
47 CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top);
48 mt.Concat(mtRotate);
49 GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt);
50 }
51
LoadWidget()52 bool CXFA_FFPushButton::LoadWidget() {
53 ASSERT(!m_pNormalWidget);
54 CFWL_PushButton* pPushButton = new CFWL_PushButton(GetFWLApp());
55 m_pOldDelegate = pPushButton->GetDelegate();
56 pPushButton->SetDelegate(this);
57
58 m_pNormalWidget = pPushButton;
59 m_pNormalWidget->SetLayoutItem(this);
60
61 CFWL_NoteDriver* pNoteDriver =
62 m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
63 pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
64 m_pNormalWidget->LockUpdate();
65 UpdateWidgetProperty();
66 LoadHighlightCaption();
67 m_pNormalWidget->UnlockUpdate();
68 return CXFA_FFField::LoadWidget();
69 }
UpdateWidgetProperty()70 void CXFA_FFPushButton::UpdateWidgetProperty() {
71 uint32_t dwStyleEx = 0;
72 switch (m_pDataAcc->GetButtonHighlight()) {
73 case XFA_ATTRIBUTEENUM_Inverted:
74 dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteInverted;
75 break;
76 case XFA_ATTRIBUTEENUM_Outline:
77 dwStyleEx = XFA_FWL_PSBSTYLEEXT_HiliteOutLine;
78 break;
79 case XFA_ATTRIBUTEENUM_Push:
80 dwStyleEx = XFA_FWL_PSBSTYLEEXT_HilitePush;
81 break;
82 default:
83 break;
84 }
85 m_pNormalWidget->ModifyStylesEx(dwStyleEx, 0xFFFFFFFF);
86 }
87
UnloadWidget()88 void CXFA_FFPushButton::UnloadWidget() {
89 delete m_pRolloverTextLayout;
90 m_pRolloverTextLayout = nullptr;
91 delete m_pDownTextLayout;
92 m_pDownTextLayout = nullptr;
93 delete m_pDownProvider;
94 m_pDownProvider = nullptr;
95 delete m_pRollProvider;
96 m_pRollProvider = nullptr;
97 CXFA_FFField::UnloadWidget();
98 }
99
PerformLayout()100 bool CXFA_FFPushButton::PerformLayout() {
101 CXFA_FFWidget::PerformLayout();
102 CFX_RectF rtWidget = GetRectWithoutRotate();
103
104 m_rtUI = rtWidget;
105 if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin())
106 XFA_RectWidthoutMargin(rtWidget, mgWidget);
107
108 CXFA_Caption caption = m_pDataAcc->GetCaption();
109 m_rtCaption = rtWidget;
110 if (CXFA_Margin mgCap = caption.GetMargin())
111 XFA_RectWidthoutMargin(m_rtCaption, mgCap);
112
113 LayoutHighlightCaption();
114 SetFWLRect();
115 if (m_pNormalWidget)
116 m_pNormalWidget->Update();
117
118 return true;
119 }
GetLineWidth()120 FX_FLOAT CXFA_FFPushButton::GetLineWidth() {
121 CXFA_Border border = m_pDataAcc->GetBorder();
122 if (border && border.GetPresence() == XFA_ATTRIBUTEENUM_Visible) {
123 CXFA_Edge edge = border.GetEdge(0);
124 return edge.GetThickness();
125 }
126 return 0;
127 }
GetLineColor()128 FX_ARGB CXFA_FFPushButton::GetLineColor() {
129 return 0xFF000000;
130 }
GetFillColor()131 FX_ARGB CXFA_FFPushButton::GetFillColor() {
132 return 0xFFFFFFFF;
133 }
LoadHighlightCaption()134 void CXFA_FFPushButton::LoadHighlightCaption() {
135 CXFA_Caption caption = m_pDataAcc->GetCaption();
136 if (caption && caption.GetPresence() != XFA_ATTRIBUTEENUM_Hidden) {
137 {
138 CFX_WideString wsRollover;
139 bool bRichText;
140 if (m_pDataAcc->GetButtonRollover(wsRollover, bRichText)) {
141 if (!m_pRollProvider) {
142 m_pRollProvider =
143 new CXFA_TextProvider(m_pDataAcc, XFA_TEXTPROVIDERTYPE_Rollover);
144 }
145 m_pRolloverTextLayout = new CXFA_TextLayout(m_pRollProvider);
146 }
147 CFX_WideString wsDown;
148 if (m_pDataAcc->GetButtonDown(wsDown, bRichText)) {
149 if (!m_pDownProvider) {
150 m_pDownProvider =
151 new CXFA_TextProvider(m_pDataAcc, XFA_TEXTPROVIDERTYPE_Down);
152 }
153 m_pDownTextLayout = new CXFA_TextLayout(m_pDownProvider);
154 }
155 }
156 }
157 }
LayoutHighlightCaption()158 void CXFA_FFPushButton::LayoutHighlightCaption() {
159 CFX_SizeF sz(m_rtCaption.width, m_rtCaption.height);
160 LayoutCaption();
161 if (m_pRolloverTextLayout) {
162 m_pRolloverTextLayout->Layout(sz);
163 }
164 if (m_pDownTextLayout) {
165 m_pDownTextLayout->Layout(sz);
166 }
167 }
RenderHighlightCaption(CFX_Graphics * pGS,CFX_Matrix * pMatrix)168 void CXFA_FFPushButton::RenderHighlightCaption(CFX_Graphics* pGS,
169 CFX_Matrix* pMatrix) {
170 CXFA_TextLayout* pCapTextLayout = m_pDataAcc->GetCaptionTextLayout();
171 CXFA_Caption caption = m_pDataAcc->GetCaption();
172 if (!caption || caption.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
173 return;
174
175 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
176 CFX_RectF rtClip = m_rtCaption;
177 rtClip.Intersect(GetRectWithoutRotate());
178 CFX_Matrix mt(1, 0, 0, 1, m_rtCaption.left, m_rtCaption.top);
179 if (pMatrix) {
180 pMatrix->TransformRect(rtClip);
181 mt.Concat(*pMatrix);
182 }
183
184 uint32_t dwState = m_pNormalWidget->GetStates();
185 if (m_pDownTextLayout && (dwState & FWL_STATE_PSB_Pressed) &&
186 (dwState & FWL_STATE_PSB_Hovered)) {
187 if (m_pDownTextLayout->DrawString(pRenderDevice, mt, rtClip))
188 return;
189 } else if (m_pRolloverTextLayout && (dwState & FWL_STATE_PSB_Hovered)) {
190 if (m_pRolloverTextLayout->DrawString(pRenderDevice, mt, rtClip))
191 return;
192 }
193
194 if (pCapTextLayout)
195 pCapTextLayout->DrawString(pRenderDevice, mt, rtClip);
196 }
197
OnProcessMessage(CFWL_Message * pMessage)198 void CXFA_FFPushButton::OnProcessMessage(CFWL_Message* pMessage) {
199 m_pOldDelegate->OnProcessMessage(pMessage);
200 }
201
OnProcessEvent(CFWL_Event * pEvent)202 void CXFA_FFPushButton::OnProcessEvent(CFWL_Event* pEvent) {
203 m_pOldDelegate->OnProcessEvent(pEvent);
204 CXFA_FFField::OnProcessEvent(pEvent);
205 }
206
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)207 void CXFA_FFPushButton::OnDrawWidget(CFX_Graphics* pGraphics,
208 const CFX_Matrix* pMatrix) {
209 if (m_pNormalWidget->GetStylesEx() & XFA_FWL_PSBSTYLEEXT_HiliteInverted) {
210 if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) &&
211 (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) {
212 CFX_RectF rtFill(0, 0, m_pNormalWidget->GetWidgetRect().Size());
213 FX_FLOAT fLineWith = GetLineWidth();
214 rtFill.Deflate(fLineWith, fLineWith);
215 CFX_Color cr(FXARGB_MAKE(128, 128, 255, 255));
216 pGraphics->SetFillColor(&cr);
217
218 CFX_Path path;
219 path.AddRectangle(rtFill.left, rtFill.top, rtFill.width, rtFill.height);
220 pGraphics->FillPath(&path, FXFILL_WINDING, (CFX_Matrix*)pMatrix);
221 }
222 } else if (m_pNormalWidget->GetStylesEx() &
223 XFA_FWL_PSBSTYLEEXT_HiliteOutLine) {
224 if ((m_pNormalWidget->GetStates() & FWL_STATE_PSB_Pressed) &&
225 (m_pNormalWidget->GetStates() & FWL_STATE_PSB_Hovered)) {
226 FX_FLOAT fLineWidth = GetLineWidth();
227 CFX_Color cr(FXARGB_MAKE(255, 128, 255, 255));
228 pGraphics->SetStrokeColor(&cr);
229 pGraphics->SetLineWidth(fLineWidth);
230
231 CFX_Path path;
232 CFX_RectF rect = m_pNormalWidget->GetWidgetRect();
233 path.AddRectangle(0, 0, rect.width, rect.height);
234 pGraphics->StrokePath(&path, (CFX_Matrix*)pMatrix);
235 }
236 }
237 }
238