// Copyright 2017 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "xfa/fxfa/cxfa_ffdatetimeedit.h" #include "core/fxcrt/cfx_datetime.h" #include "third_party/base/check.h" #include "xfa/fwl/cfwl_datetimepicker.h" #include "xfa/fwl/cfwl_eventselectchanged.h" #include "xfa/fwl/cfwl_notedriver.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/cxfa_ffdoc.h" #include "xfa/fxfa/cxfa_ffdocview.h" #include "xfa/fxfa/parser/cxfa_localevalue.h" #include "xfa/fxfa/parser/cxfa_para.h" #include "xfa/fxfa/parser/cxfa_value.h" #include "xfa/fxfa/parser/xfa_utils.h" CXFA_FFDateTimeEdit::CXFA_FFDateTimeEdit(CXFA_Node* pNode) : CXFA_FFTextEdit(pNode) {} CXFA_FFDateTimeEdit::~CXFA_FFDateTimeEdit() = default; CFWL_DateTimePicker* CXFA_FFDateTimeEdit::GetPickerWidget() { return static_cast(GetNormalWidget()); } CFX_RectF CXFA_FFDateTimeEdit::GetBBox(FocusOption focus) { if (focus == kDrawFocus) return CFX_RectF(); return CXFA_FFWidget::GetBBox(kDoNotDrawFocus); } bool CXFA_FFDateTimeEdit::PtInActiveRect(const CFX_PointF& point) { CFWL_DateTimePicker* pPicker = GetPickerWidget(); return pPicker && pPicker->GetBBox().Contains(point); } bool CXFA_FFDateTimeEdit::LoadWidget() { DCHECK(!IsLoaded()); CFWL_DateTimePicker* pWidget = cppgc::MakeGarbageCollected( GetFWLApp()->GetHeap()->GetAllocationHandle(), GetFWLApp()); SetNormalWidget(pWidget); pWidget->SetAdapterIface(this); CFWL_NoteDriver* pNoteDriver = pWidget->GetFWLApp()->GetNoteDriver(); pNoteDriver->RegisterEventTarget(pWidget, pWidget); m_pOldDelegate = pWidget->GetDelegate(); pWidget->SetDelegate(this); { CFWL_Widget::ScopedUpdateLock update_lock(pWidget); WideString wsText = m_pNode->GetValue(XFA_ValuePicture::kDisplay); pWidget->SetEditText(wsText); CXFA_Value* value = m_pNode->GetFormValueIfExists(); if (value) { switch (value->GetChildValueClassID()) { case XFA_Element::Date: { if (!wsText.IsEmpty()) { CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pNode.Get()); CFX_DateTime date = lcValue.GetDate(); if (date.IsSet()) pWidget->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay()); } } break; default: break; } } UpdateWidgetProperty(); } return CXFA_FFField::LoadWidget(); } void CXFA_FFDateTimeEdit::UpdateWidgetProperty() { CFWL_DateTimePicker* pPicker = GetPickerWidget(); if (!pPicker) return; uint32_t dwExtendedStyle = FWL_STYLEEXT_DTP_ShortDateFormat; dwExtendedStyle |= UpdateUIProperty(); dwExtendedStyle |= GetAlignment(); GetNormalWidget()->ModifyStyleExts(dwExtendedStyle, 0xFFFFFFFF); uint32_t dwEditStyles = 0; absl::optional numCells = m_pNode->GetNumberOfCells(); if (numCells.has_value() && numCells.value() > 0) { dwEditStyles |= FWL_STYLEEXT_EDT_CombText; pPicker->SetEditLimit(numCells.value()); } if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly; if (!m_pNode->IsHorizontalScrollPolicyOff()) dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll; pPicker->ModifyEditStyleExts(dwEditStyles, 0xFFFFFFFF); } uint32_t CXFA_FFDateTimeEdit::GetAlignment() { CXFA_Para* para = m_pNode->GetParaIfExists(); if (!para) return 0; uint32_t dwExtendedStyle = 0; switch (para->GetHorizontalAlign()) { case XFA_AttributeValue::Center: dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHCenter; break; case XFA_AttributeValue::Justify: dwExtendedStyle |= FWL_STYLEEXT_DTP_EditJustified; break; case XFA_AttributeValue::JustifyAll: case XFA_AttributeValue::Radix: break; case XFA_AttributeValue::Right: dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHFar; break; default: dwExtendedStyle |= FWL_STYLEEXT_DTP_EditHNear; break; } switch (para->GetVerticalAlign()) { case XFA_AttributeValue::Middle: dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVCenter; break; case XFA_AttributeValue::Bottom: dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVFar; break; default: dwExtendedStyle |= FWL_STYLEEXT_DTP_EditVNear; break; } return dwExtendedStyle; } bool CXFA_FFDateTimeEdit::CommitData() { CFWL_DateTimePicker* pPicker = GetPickerWidget(); if (!m_pNode->SetValue(XFA_ValuePicture::kEdit, pPicker->GetEditText())) return false; GetDoc()->GetDocView()->UpdateUIDisplay(m_pNode.Get(), this); return true; } bool CXFA_FFDateTimeEdit::UpdateFWLData() { if (!GetNormalWidget()) return false; XFA_ValuePicture eType = XFA_ValuePicture::kDisplay; if (IsFocused()) eType = XFA_ValuePicture::kEdit; WideString wsText = m_pNode->GetValue(eType); CFWL_DateTimePicker* pPicker = GetPickerWidget(); pPicker->SetEditText(wsText); if (IsFocused() && !wsText.IsEmpty()) { CXFA_LocaleValue lcValue = XFA_GetLocaleValue(m_pNode.Get()); CFX_DateTime date = lcValue.GetDate(); if (lcValue.IsValid()) { if (date.IsSet()) pPicker->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay()); } } GetNormalWidget()->Update(); return true; } bool CXFA_FFDateTimeEdit::IsDataChanged() { if (GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kTextEditValueChanged)) return true; WideString wsText = GetPickerWidget()->GetEditText(); return m_pNode->GetValue(XFA_ValuePicture::kEdit) != wsText; } void CXFA_FFDateTimeEdit::OnSelectChanged(CFWL_Widget* pWidget, int32_t iYear, int32_t iMonth, int32_t iDay) { WideString wsPicture = m_pNode->GetPictureContent(XFA_ValuePicture::kEdit); CXFA_LocaleValue date(CXFA_LocaleValue::ValueType::kDate, GetDoc()->GetXFADoc()->GetLocaleMgr()); date.SetDate(CFX_DateTime(iYear, iMonth, iDay, 0, 0, 0, 0)); WideString wsDate; date.FormatPatterns(wsDate, wsPicture, m_pNode->GetLocale(), XFA_ValuePicture::kEdit); CFWL_DateTimePicker* pPicker = GetPickerWidget(); pPicker->SetEditText(wsDate); pPicker->Update(); GetDoc()->SetFocusWidget(nullptr); CXFA_EventParam eParam; eParam.m_eType = XFA_EVENT_Change; eParam.m_wsPrevText = m_pNode->GetValue(XFA_ValuePicture::kRaw); m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Change, &eParam); } void CXFA_FFDateTimeEdit::OnProcessEvent(CFWL_Event* pEvent) { if (pEvent->GetType() == CFWL_Event::Type::SelectChanged) { auto* event = static_cast(pEvent); OnSelectChanged(GetNormalWidget(), event->GetYear(), event->GetMonth(), event->GetDay()); return; } CXFA_FFTextEdit::OnProcessEvent(pEvent); } bool CXFA_FFDateTimeEdit::CanUndo() { return GetPickerWidget()->CanUndo(); } bool CXFA_FFDateTimeEdit::CanRedo() { return GetPickerWidget()->CanRedo(); } bool CXFA_FFDateTimeEdit::CanCopy() { return GetPickerWidget()->HasSelection(); } bool CXFA_FFDateTimeEdit::CanCut() { if (GetPickerWidget()->GetStyleExts() & FWL_STYLEEXT_EDT_ReadOnly) return false; return GetPickerWidget()->HasSelection(); } bool CXFA_FFDateTimeEdit::CanPaste() { return !(GetPickerWidget()->GetStyleExts() & FWL_STYLEEXT_EDT_ReadOnly); } bool CXFA_FFDateTimeEdit::CanSelectAll() { return GetPickerWidget()->GetEditTextLength() > 0; } absl::optional CXFA_FFDateTimeEdit::Copy() { return GetPickerWidget()->Copy(); } bool CXFA_FFDateTimeEdit::Undo() { return GetPickerWidget()->Undo(); } bool CXFA_FFDateTimeEdit::Redo() { return GetPickerWidget()->Redo(); } absl::optional CXFA_FFDateTimeEdit::Cut() { return GetPickerWidget()->Cut(); } bool CXFA_FFDateTimeEdit::Paste(const WideString& wsPaste) { return GetPickerWidget()->Paste(wsPaste); } void CXFA_FFDateTimeEdit::SelectAll() { GetPickerWidget()->SelectAll(); } void CXFA_FFDateTimeEdit::Delete() { GetPickerWidget()->ClearText(); } void CXFA_FFDateTimeEdit::DeSelect() { GetPickerWidget()->ClearSelection(); } WideString CXFA_FFDateTimeEdit::GetText() { return GetPickerWidget()->GetEditText(); }