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 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 29 CXFA_FFPushButton::~CXFA_FFPushButton() { 30 CXFA_FFPushButton::UnloadWidget(); 31 } 32 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 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 } 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 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 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 } 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 } 128 FX_ARGB CXFA_FFPushButton::GetLineColor() { 129 return 0xFF000000; 130 } 131 FX_ARGB CXFA_FFPushButton::GetFillColor() { 132 return 0xFFFFFFFF; 133 } 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 } 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 } 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 198 void CXFA_FFPushButton::OnProcessMessage(CFWL_Message* pMessage) { 199 m_pOldDelegate->OnProcessMessage(pMessage); 200 } 201 202 void CXFA_FFPushButton::OnProcessEvent(CFWL_Event* pEvent) { 203 m_pOldDelegate->OnProcessEvent(pEvent); 204 CXFA_FFField::OnProcessEvent(pEvent); 205 } 206 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