Fixes #4621. Replace TimeField/DateField with new TimeEditor/DateEditor based on TextValidateField#4622
Conversation
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
…lify logic, extract constants Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
…sWithZero Co-authored-by: tig <585482+tig@users.noreply.github.com>
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Co-authored-by: tig <585482+tig@users.noreply.github.com>
This comment was marked as off-topic.
This comment was marked as off-topic.
tig
left a comment
There was a problem hiding this comment.
Good foundation — the architecture (provider pattern, IValue<TimeSpan>, cultural format support) is sound and the test coverage is a reasonable start. A few issues need to be addressed before merge:
Bugs
- Double-firing
ValueChanged— SettingValueprogrammatically firesValueChangedtwice: once via the setter and again via theTextChanged → RaiseValueChangedEventspath triggered byText = TimeProvider.Text. See inline comment onTimeEditor.cs:55. ValueChangingnot raised for keyboard input — User typing bypasses the cancellable event entirely. SeeTimeEditor.cs:163.
Code quality
3. Bare catch block in TryManualParse — swallows all exceptions including fatal ones.
4. Width management inconsistency — Constructor uses Dim.Auto, Format setter clobbers it with a fixed integer.
5. Redundant 12-hour adjustment in FormatTimeValue() — _isPm may be derivable from _timeValue.Hours rather than tracked as separate state.
Tests
6. Coverage at 61.7% — Below the project's 70% threshold (flagged by CodeCov). The TryManualParse fallback path and much of the cursor navigation code are untested.
7. Missing AI-generated test comment — Project convention requires a comment like // Claude - Sonnet 4.6.
8. Culture-sensitive width test may be non-deterministic.
Minor
_separatorPositions: preferHashSet<int>overList<int>forContainscalls.- Trailing whitespace on blank lines in
TimeAndDate.cs.
Removed the TimeField control, its tests, and documentation. Introduced TimeEditor as the new time input control, based on TextValidateField with culture-aware formatting. Updated all references, scenarios, and docs to use TimeEditor instead of TimeField. TimeField source and tests have been deleted.
Refactored TimeEditor, TimeTextProvider, NetMaskedTextProvider, and TextRegexProvider for clarity and consistency. Removed the VerifyChar method from ITextValidateProvider and all implementations, simplifying the provider interface. Standardized event raising and improved handling of AM/PM, manual parsing, and pattern normalization in TimeTextProvider. Updated TextValidateField drawing and key handling logic for simplicity. Modernized and clarified all related tests to match the new API and style. Made various code style improvements and updated documentation throughout.
Refactored TextValidateField and TimeEditor to fully implement the IValue<T> interface and follow the Cancellable Work Pattern (CWP) for value changes. - TextValidateField now exposes Value, ValueChanging, and ValueChanged events, and synchronizes value changes from both programmatic and user input, with support for cancellation and reversion. - Introduced SuppressValueEvents to prevent unwanted event recursion. - TimeEditor now uses a private _value field, leverages CWPPropertyHelper for value changes, and raises strongly-typed TimeSpan events. - Removed manual event wiring and last-known-value tracking in favor of the new base class pattern. - These changes improve consistency, extensibility, and support for data binding and undo/redo scenarios.
Add DateTextProvider (ITextValidateProvider for dates with culture-aware formatting, pattern normalization, separator handling) and DateEditor (extends TextValidateField, implements IValue<DateTime?> with CWP). Remove legacy DateField and update all usages in DatePicker, scenarios, docs, and indexes. Full test coverage in DateEditorTests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactored event raising in Date, Time, Masked, and Regex text providers by introducing a private RaiseTextChanged method. OnTextChanged is now virtual and serves as a subclass hook, improving extensibility. Updated all event triggers to use RaiseTextChanged. Improved null safety in TextRegexProvider by initializing _text to an empty list. Fixed CleanSeparator logic in DateTextProvider for short separators. Enhanced TryParseDateValue to only fall back to manual parsing if needed. Updated documentation to clarify new event handling pattern.
There was a problem hiding this comment.
Pull request overview
This PR modernizes Terminal.Gui’s date/time input controls by replacing the legacy TimeField/DateField (TextField-based) with TimeEditor/DateEditor built on TextValidateField + new culture-aware ITextValidateProvider implementations, and updates docs/examples/tests accordingly.
Changes:
- Added
TimeEditor/DateEditorplusTimeTextProvider/DateTextProvider, and removed legacyTimeField/DateField. - Updated
TextValidateField/providers to use CWP-style value events and support a “blank cursor cell” past the last editable character for fixed-width providers. - Updated
DatePicker, docs, and UICatalog scenarios to use the new editors; replaced/added unit tests.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| docfx/docs/views.md | Updates view docs to reference DateEditor/TimeEditor. |
| docfx/docs/events.md | Updates IValue table entries to DateEditor/TimeEditor. |
| Tests/UnitTestsParallelizable/Views/TimeFieldTests.cs | Removes legacy TimeField tests. |
| Tests/UnitTestsParallelizable/Views/TimeEditorTests.cs | Adds coverage for TimeEditor/TimeTextProvider. |
| Tests/UnitTestsParallelizable/Views/TextValidateFieldTests.cs | Adjusts tests for new blank-cursor-cell behavior and navigation semantics. |
| Tests/UnitTestsParallelizable/Views/DateFieldTests.cs | Removes legacy DateField tests. |
| Tests/UnitTestsParallelizable/Views/DateEditorTests.cs | Adds coverage for DateEditor/DateTextProvider. |
| Tests/UnitTests/Views/DatePickerTests.cs | Updates focus expectations for DateEditor integration. |
| Terminal.sln.DotSettings | Adds spelling exception entry for “TimeEditor”. |
| Terminal.Gui/Views/TextInput/TimeTextProvider.cs | New culture-aware time provider (12h/24h + AM/PM handling). |
| Terminal.Gui/Views/TextInput/TimeField.cs | Removes legacy time input view. |
| Terminal.Gui/Views/TextInput/TimeEditor.cs | New time editor built on TextValidateField with CWP value events. |
| Terminal.Gui/Views/TextInput/TextValidateField.cs | Adds IValue plumbing, provider change tracking, and blank-cursor-cell support. |
| Terminal.Gui/Views/TextInput/TextRegexProvider.cs | Improves null-safety and aligns event raising pattern with other providers. |
| Terminal.Gui/Views/TextInput/TextEditingLineStatus.cs | Cleans up file header/nullability directive. |
| Terminal.Gui/Views/TextInput/NetMaskedTextProvider.cs | Refactors + aligns event raising pattern with other providers. |
| Terminal.Gui/Views/TextInput/ITextValidateProvider.cs | Removes obsolete OnTextChanged method from the interface. |
| Terminal.Gui/Views/TextInput/DateTextProvider.cs | New culture-aware date provider (normalized fixed-width pattern). |
| Terminal.Gui/Views/TextInput/DateField.cs | Removes legacy date input view. |
| Terminal.Gui/Views/TextInput/DateEditor.cs | New date editor built on TextValidateField with CWP value events. |
| Terminal.Gui/Views/DatePicker.cs | Replaces embedded DateField with DateEditor and uses DateTextProvider.NormalizePattern. |
| Examples/UICatalog/Scenarios/TimeAndDate.cs | Updates scenario to demonstrate TimeEditor/DateEditor and formats. |
| Examples/UICatalog/Scenarios/TextInputControls.cs | Replaces DateField/TimeField usage with editors; updates mirroring labels. |
| AGENTS.md | Updates agent index to new TextInput file set. |
| .tg-docs/INDEX.md | Updates docs index to new TextInput file set. |
BDisp
left a comment
There was a problem hiding this comment.
Good idea to implement them with TextValidateField.
…and Prompt demo - Remove Pos.Center() and center text alignment from all editors and labels - Add inline DatePicker synced bidirectionally with default DateEditor - Add Prompt<DatePicker> button that opens modal date picker dialog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Summary
Replaces the legacy
TimeFieldandDateFieldcontrols with newTimeEditorandDateEditorviews built onTextValidateFieldusing customITextValidateProviderimplementations. This provides cleaner architecture, culture-aware formatting, 12-hour AM/PM support, and proper CWP-compliant events.New Components
TimeTextProvider (
ITextValidateProvider)DateTimeFormatInfo.LongTimePatternto detect 12h/24h format, separators, and AM/PM positionsh→hh)OnTextChanged/TextChangedevent patternDateTextProvider (
ITextValidateProvider)DateTimeFormatInfo.ShortDatePatternfor culture-aware date formattingd→dd,M→MM,yy→yyyy)OnTextChanged/TextChangedevent patternTimeEditor (
TextValidateField,IValue<TimeSpan>,IDesignable)TimeTextProviderValueChanging/ValueChangedevents with full cancellation supportFormatproperty acceptsDateTimeFormatInfofor flexible pattern controlTimeSpanvalue - consistent with other value typesDateEditor (
TextValidateField,IValue<DateTime>,IDesignable)DateTextProviderValueChanging/ValueChangedevents with full cancellation supportFormatproperty acceptsDateTimeFormatInfofor flexible pattern controlDateTimevalue - consistent withTimeEditorandDatePickerOther Changes
DateEditorinstead ofDateField_dateEditornow uses thedateparameter instead ofDateTime.NowCulturesetter now propagatesDateTimeFormatInfoto_dateEditor.FormatValuesetter now propagates to_dateEditor.Valuefor proper synchronizationOnTextChanged/TextChangedon all four providers (TimeTextProvider,DateTextProvider,NetMaskedTextProvider,TextRegexProvider) —OnTextChangedis now a virtual method for subclass override, withRaiseTextChangedhandling event dispatch_textinitialized to[]instead ofnull!to preventNullReferenceExceptioninValidate()during constructionOnHasFocusChanged— preventsNullReferenceExceptionwhen view gains focus before a provider is setTimeEditorandDateEditorTimeField,DateField, and their testsUsage
Architecture
DateTimeFormatInfopattern supportTest Plan
Pull Request checklist:
CTRL-K-Dto automatically reformat your files before committing.dotnet testbefore commit///style comments)🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.