Skip to content

Commit

Permalink
Merge pull request AvaloniaUI#7634 from AvaloniaUI/fixes/7633-date-ti…
Browse files Browse the repository at this point in the history
…me-picker-popup

Fix Date/Time picker popups
# Conflicts:
#	src/Avalonia.Controls/DateTimePickers/DatePicker.cs
#	src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  • Loading branch information
maxkatz6 authored and danwalmsley committed Feb 21, 2022
1 parent 0419426 commit 4b6d122
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 7 deletions.
18 changes: 14 additions & 4 deletions src/Avalonia.Controls/DateTimePickers/DatePicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Layout;
using System;
using System.Collections.Generic;
using System.Globalization;
Expand Down Expand Up @@ -398,18 +399,27 @@ private void SetSelectedDateText()
private void OnFlyoutButtonClicked(object sender, RoutedEventArgs e)
{
if (_presenter == null)
throw new InvalidOperationException("No DatePickerPresenter found");
throw new InvalidOperationException("No DatePickerPresenter found.");
if (_popup == null)
throw new InvalidOperationException("No Popup found.");

_presenter.Date = SelectedDate ?? DateTimeOffset.Now;

_popup.PlacementMode = PlacementMode.AnchorAndGravity;
_popup.PlacementAnchor = Primitives.PopupPositioning.PopupAnchor.Bottom;
_popup.PlacementGravity = Primitives.PopupPositioning.PopupGravity.Bottom;
_popup.PlacementConstraintAdjustment = Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY;
_popup.IsOpen = true;

// Overlay popup hosts won't get measured until the next layout pass, but we need the
// template to be applied to `_presenter` now. Detect this case and force a layout pass.
if (!_presenter.IsMeasureValid)
(VisualRoot as ILayoutRoot)?.LayoutManager?.ExecuteInitialLayoutPass();

var deltaY = _presenter.GetOffsetForPopup();

// The extra 5 px I think is related to default popup placement behavior
_popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
_popup.VerticalOffset = deltaY + 5;
}

protected virtual void OnSelectedDateChanged(object sender, DatePickerSelectedValueChangedEventArgs e)
Expand Down
3 changes: 3 additions & 0 deletions src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,9 @@ private void OnMonthChanged(object sender, EventArgs e)

internal double GetOffsetForPopup()
{
if (_monthSelector is null)
return 0;

var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_monthSelector.ItemHeight / 2);
}
Expand Down
19 changes: 16 additions & 3 deletions src/Avalonia.Controls/DateTimePickers/TimePicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Layout;
using System;
using System.Globalization;

Expand Down Expand Up @@ -254,16 +255,28 @@ protected virtual void OnSelectedTimeChanged(TimeSpan? oldTime, TimeSpan? newTim

private void OnFlyoutButtonClicked(object sender, Interactivity.RoutedEventArgs e)
{
if (_presenter == null)
throw new InvalidOperationException("No DatePickerPresenter found.");
if (_popup == null)
throw new InvalidOperationException("No Popup found.");

_presenter.Time = SelectedTime ?? DateTime.Now.TimeOfDay;

_popup.PlacementMode = PlacementMode.AnchorAndGravity;
_popup.PlacementAnchor = Primitives.PopupPositioning.PopupAnchor.Bottom;
_popup.PlacementGravity = Primitives.PopupPositioning.PopupGravity.Bottom;
_popup.PlacementConstraintAdjustment = Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY;
_popup.IsOpen = true;

// Overlay popup hosts won't get measured until the next layout pass, but we need the
// template to be applied to `_presenter` now. Detect this case and force a layout pass.
if (!_presenter.IsMeasureValid)
(VisualRoot as ILayoutRoot)?.LayoutManager?.ExecuteInitialLayoutPass();

var deltaY = _presenter.GetOffsetForPopup();

// The extra 5 px I think is related to default popup placement behavior
_popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
_popup.VerticalOffset = deltaY + 5;
}

private void OnDismissPicker(object sender, EventArgs e)
Expand Down
3 changes: 3 additions & 0 deletions src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ private void OnSelectorButtonClick(object sender, RoutedEventArgs e)

internal double GetOffsetForPopup()
{
if (_hourSelector is null)
return 0;

var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_hourSelector.ItemHeight / 2);
}
Expand Down

0 comments on commit 4b6d122

Please sign in to comment.