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