| // 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 "core/fxcrt/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<CFWL_DateTimePicker*>(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<CFWL_DateTimePicker>( | |
| GetFWLApp()->GetHeap()->GetAllocationHandle(), GetFWLApp()); | |
| SetNormalWidget(pWidget); | |
| pWidget->SetAdapterIface(this); | |
| CFWL_NoteDriver* pNoteDriver = pWidget->GetFWLApp()->GetNoteDriver(); | |
| pNoteDriver->RegisterEventTarget(pWidget, pWidget); | |
| old_delegate_ = pWidget->GetDelegate(); | |
| pWidget->SetDelegate(this); | |
| { | |
| CFWL_Widget::ScopedUpdateLock update_lock(pWidget); | |
| WideString wsText = node_->GetValue(XFA_ValuePicture::kDisplay); | |
| pWidget->SetEditText(wsText); | |
| CXFA_Value* value = node_->GetFormValueIfExists(); | |
| if (value) { | |
| switch (value->GetChildValueClassID()) { | |
| case XFA_Element::Date: { | |
| if (!wsText.IsEmpty()) { | |
| CXFA_LocaleValue lcValue = XFA_GetLocaleValue(node_.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; | |
| std::optional<int32_t> numCells = node_->GetNumberOfCells(); | |
| if (numCells.has_value() && numCells.value() > 0) { | |
| dwEditStyles |= FWL_STYLEEXT_EDT_CombText; | |
| pPicker->SetEditLimit(numCells.value()); | |
| } | |
| if (!node_->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive()) { | |
| dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly; | |
| } | |
| if (!node_->IsHorizontalScrollPolicyOff()) { | |
| dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll; | |
| } | |
| pPicker->ModifyEditStyleExts(dwEditStyles, 0xFFFFFFFF); | |
| } | |
| uint32_t CXFA_FFDateTimeEdit::GetAlignment() { | |
| CXFA_Para* para = node_->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 (!node_->SetValue(XFA_ValuePicture::kEdit, pPicker->GetEditText())) { | |
| return false; | |
| } | |
| GetDoc()->GetDocView()->UpdateUIDisplay(node_.Get(), this); | |
| return true; | |
| } | |
| void CXFA_FFDateTimeEdit::UpdateFWLData() { | |
| if (!GetNormalWidget()) { | |
| return; | |
| } | |
| XFA_ValuePicture eType = XFA_ValuePicture::kDisplay; | |
| if (IsFocused()) { | |
| eType = XFA_ValuePicture::kEdit; | |
| } | |
| WideString wsText = node_->GetValue(eType); | |
| CFWL_DateTimePicker* pPicker = GetPickerWidget(); | |
| pPicker->SetEditText(wsText); | |
| if (IsFocused() && !wsText.IsEmpty()) { | |
| CXFA_LocaleValue lcValue = XFA_GetLocaleValue(node_.Get()); | |
| CFX_DateTime date = lcValue.GetDate(); | |
| if (lcValue.IsValid()) { | |
| if (date.IsSet()) { | |
| pPicker->SetCurSel(date.GetYear(), date.GetMonth(), date.GetDay()); | |
| } | |
| } | |
| } | |
| GetNormalWidget()->Update(); | |
| } | |
| bool CXFA_FFDateTimeEdit::IsDataChanged() { | |
| if (GetLayoutItem()->TestStatusBits( | |
| XFA_WidgetStatus::kTextEditValueChanged)) { | |
| return true; | |
| } | |
| WideString wsText = GetPickerWidget()->GetEditText(); | |
| return node_->GetValue(XFA_ValuePicture::kEdit) != wsText; | |
| } | |
| void CXFA_FFDateTimeEdit::OnSelectChanged(CFWL_Widget* pWidget, | |
| int32_t iYear, | |
| int32_t iMonth, | |
| int32_t iDay) { | |
| WideString wsPicture = node_->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, node_->GetLocale(), | |
| XFA_ValuePicture::kEdit); | |
| CFWL_DateTimePicker* pPicker = GetPickerWidget(); | |
| pPicker->SetEditText(wsDate); | |
| pPicker->Update(); | |
| GetDoc()->SetFocusWidget(nullptr); | |
| CXFA_EventParam eParam(XFA_EVENT_Unknown); | |
| eParam.type_ = XFA_EVENT_Change; | |
| eParam.prev_text_ = node_->GetValue(XFA_ValuePicture::kRaw); | |
| node_->ProcessEvent(GetDocView(), XFA_AttributeValue::Change, &eParam); | |
| } | |
| void CXFA_FFDateTimeEdit::OnProcessEvent(CFWL_Event* pEvent) { | |
| if (pEvent->GetType() == CFWL_Event::Type::SelectChanged) { | |
| auto* event = static_cast<CFWL_EventSelectChanged*>(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; | |
| } | |
| std::optional<WideString> CXFA_FFDateTimeEdit::Copy() { | |
| return GetPickerWidget()->Copy(); | |
| } | |
| bool CXFA_FFDateTimeEdit::Undo() { | |
| return GetPickerWidget()->Undo(); | |
| } | |
| bool CXFA_FFDateTimeEdit::Redo() { | |
| return GetPickerWidget()->Redo(); | |
| } | |
| std::optional<WideString> 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(); | |
| } |