Skip to content

Commit

Permalink
(MahAppsGH-3746) Add key processing if Popup is open
Browse files Browse the repository at this point in the history
  • Loading branch information
punker76 committed May 3, 2020
1 parent 4c95279 commit 09b24dc
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 47 deletions.
34 changes: 28 additions & 6 deletions src/MahApps.Metro/Controls/TimePicker/DateTimePicker.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
Expand Down Expand Up @@ -148,8 +149,9 @@ public override void OnApplyTemplate()
{
if (_calendar != null)
{
_calendar.SelectedDatesChanged -= OnCalendarSelectedDateChanged;
_calendar.PreviewMouseUp -= OnCalendarPreviewMouseUp;
_calendar.PreviewKeyDown -= this.CalendarPreviewKeyDown;
_calendar.SelectedDatesChanged -= CalendarSelectedDateChanged;
_calendar.PreviewMouseUp -= CalendarPreviewMouseUp;
}

base.OnApplyTemplate();
Expand All @@ -158,28 +160,48 @@ public override void OnApplyTemplate()

if (_calendar != null)
{
_calendar.PreviewKeyDown += this.CalendarPreviewKeyDown;
_calendar.SelectedDatesChanged += CalendarSelectedDateChanged;
_calendar.PreviewMouseUp += CalendarPreviewMouseUp;

_calendar.SetBinding(Calendar.SelectedDateProperty, GetBinding(SelectedDateTimeProperty));
_calendar.SetBinding(Calendar.DisplayDateProperty, GetBinding(DisplayDateProperty));
_calendar.SetBinding(Calendar.DisplayDateStartProperty, GetBinding(DisplayDateStartProperty));
_calendar.SetBinding(Calendar.DisplayDateEndProperty, GetBinding(DisplayDateEndProperty));
_calendar.SetBinding(Calendar.FirstDayOfWeekProperty, GetBinding(FirstDayOfWeekProperty));
_calendar.SetBinding(Calendar.IsTodayHighlightedProperty, GetBinding(IsTodayHighlightedProperty));
_calendar.SetBinding(FlowDirectionProperty, GetBinding(FlowDirectionProperty));
_calendar.SelectedDatesChanged += OnCalendarSelectedDateChanged;
_calendar.PreviewMouseUp += OnCalendarPreviewMouseUp;
}

SetDatePartValues();
}

private static void OnCalendarPreviewMouseUp(object sender, MouseButtonEventArgs e)
private static void CalendarPreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (Mouse.Captured is CalendarItem)
{
Mouse.Capture(null);
}
}

private void CalendarPreviewKeyDown(object sender, RoutedEventArgs e)
{
var calendar = sender as Calendar;
var keyEventArgs = (KeyEventArgs)e;

Debug.Assert(calendar != null);
Debug.Assert(keyEventArgs != null);

if (keyEventArgs.Key == Key.Escape || ((keyEventArgs.Key == Key.Enter || keyEventArgs.Key == Key.Space) && calendar.DisplayMode == CalendarMode.Month))
{
this.SetCurrentValue(IsDropDownOpenProperty, false);
if (keyEventArgs.Key == Key.Escape)
{
SetCurrentValue(SelectedDateTimeProperty, _originalSelectedDateTime);
}
}
}

protected override void OnPopUpOpened()
{
if (this._calendar != null)
Expand Down Expand Up @@ -279,7 +301,7 @@ private static void OnClockVisibilityChanged(DependencyObject d, DependencyPrope
d.CoerceValue(OrientationProperty);
}

private static void OnCalendarSelectedDateChanged(object sender, SelectionChangedEventArgs e)
private static void CalendarSelectedDateChanged(object sender, SelectionChangedEventArgs e)
{
var dateTimePicker = (DateTimePicker)((Calendar)sender).TemplatedParent;

Expand Down
148 changes: 107 additions & 41 deletions src/MahApps.Metro/Controls/TimePicker/TimePickerBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
Expand Down Expand Up @@ -55,7 +56,7 @@ public abstract class TimePickerBase : Control
private Selector _secondInput;
protected DatePickerTextBox _textBox;
protected bool _deactivateAdjustTimeOnDateChange;
private DateTime? _originalSelectedDateTime;
protected DateTime? _originalSelectedDateTime;

public static readonly DependencyProperty SourceHoursProperty = DependencyProperty.Register(
"SourceHours",
Expand Down Expand Up @@ -547,7 +548,7 @@ protected void SetDefaultTimeOfDayValues()
SetDefaultTimeOfDayValue(_ampmSwitcher);
}

protected virtual void SubscribeEvents()
private void SubscribeEvents()
{
if (_popUp != null)
{
Expand All @@ -561,7 +562,7 @@ protected virtual void SubscribeEvents()
}
}

SubscribeRangeBaseValueChanged(_hourInput, _minuteInput, _secondInput, _ampmSwitcher);
this.SubscribeTimePickerEvents(_hourInput, _minuteInput, _secondInput, _ampmSwitcher);

if (this._dropDownButton != null)
{
Expand All @@ -571,45 +572,47 @@ protected virtual void SubscribeEvents()

if (_textBox != null)
{
_textBox.TextChanged += OnTextChanged;
_textBox.LostFocus += InternalOnTextBoxLostFocus;
_textBox.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown), true);
_textBox.TextChanged += this.TextBox_TextChanged;
_textBox.LostFocus += this.TextBox_LostFocus;
}
}

private void OutsideCapturedElementHandler(object sender, MouseButtonEventArgs e)
{
if (this.IsDropDownOpen)
{
if (!(this._dropDownButton?.InputHitTest(e.GetPosition(this._dropDownButton)) is null))
{
return;
}

this.SetCurrentValue(IsDropDownOpenProperty, false);
}
}

protected virtual void UnSubscribeEvents()
private void UnSubscribeEvents()
{
if (_popUp != null)
{
_popUp.RemoveHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(PopUp_PreviewMouseLeftButtonDown));
_popUp.Opened -= PopUp_Opened;
_popUp.Closed -= PopUp_Closed;
}
UnsubscribeRangeBaseValueChanged(_hourInput, _minuteInput, _secondInput, _ampmSwitcher);

this.UnsubscribeTimePickerEvents(_hourInput, _minuteInput, _secondInput, _ampmSwitcher);

if (this._dropDownButton != null)
{
this._dropDownButton.Click -= this.OnDropDownButtonClicked;
_dropDownButton.RemoveHandler(MouseLeaveEvent, new MouseEventHandler(DropDownButton_MouseLeave));
}

if (_textBox != null)
{
_textBox.TextChanged -= OnTextChanged;
_textBox.LostFocus -= InternalOnTextBoxLostFocus;
_textBox.RemoveHandler(TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown));
_textBox.TextChanged -= this.TextBox_TextChanged;
_textBox.LostFocus -= this.TextBox_LostFocus;
}
}

private void OutsideCapturedElementHandler(object sender, MouseButtonEventArgs e)
{
if (this.IsDropDownOpen)
{
if (!(this._dropDownButton?.InputHitTest(e.GetPosition(this._dropDownButton)) is null))
{
return;
}

this.SetCurrentValue(IsDropDownOpenProperty, false);
}
}

Expand Down Expand Up @@ -709,17 +712,30 @@ private static object CoerceSourceHours(DependencyObject d, object basevalue)
return Enumerable.Empty<int>();
}

private void InternalOnTextBoxLostFocus(object sender, RoutedEventArgs e)
private void TimePickerPreviewKeyDown(object sender, RoutedEventArgs e)
{
if (_textInputChanged)
if (!(e.OriginalSource is Selector))
{
_textInputChanged = false;
return;
}

OnTextBoxLostFocus(sender, e);
var selector = sender as Selector;
var keyEventArgs = (KeyEventArgs)e;

Debug.Assert(selector != null);
Debug.Assert(keyEventArgs != null);

if (keyEventArgs.Key == Key.Escape || keyEventArgs.Key == Key.Enter || keyEventArgs.Key == Key.Space)
{
this.SetCurrentValue(IsDropDownOpenProperty, false);
if (keyEventArgs.Key == Key.Escape)
{
this.SetCurrentValue(SelectedDateTimeProperty, this._originalSelectedDateTime);
}
}
}

private void InternalOnRangeBaseValueChanged(object sender, SelectionChangedEventArgs e)
private void TimePickerSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!_deactivateRangeBaseEvent)
{
Expand Down Expand Up @@ -810,14 +826,6 @@ private static void OnSelectedDateTimeChanged(DependencyObject d, DependencyProp
timePartPickerBase.WriteValueToTextBox();
}

private void OnTextChanged(object sender, TextChangedEventArgs e)
{
if (!_deactivateTextChangedEvent)
{
_textInputChanged = true;
}
}

private static void SetVisibility(UIElement partHours, UIElement partMinutes, UIElement partSeconds, TimePartVisibility visibility)
{
if (partHours != null)
Expand Down Expand Up @@ -1015,19 +1023,77 @@ private void SetPickerVisibility(TimePartVisibility visibility)
SetAmPmVisibility();
}

private void SubscribeRangeBaseValueChanged(params Selector[] selectors)
private void UnsubscribeTimePickerEvents(params Selector[] selectors)
{
foreach (var selector in selectors.Where(i => i != null))
{
selector.SelectionChanged += InternalOnRangeBaseValueChanged;
selector.PreviewKeyDown -= this.TimePickerPreviewKeyDown;
selector.SelectionChanged -= this.TimePickerSelectionChanged;
}
}

private void UnsubscribeRangeBaseValueChanged(params Selector[] selectors)
private void SubscribeTimePickerEvents(params Selector[] selectors)
{
foreach (var selector in selectors.Where(i => i != null))
{
selector.SelectionChanged -= InternalOnRangeBaseValueChanged;
selector.PreviewKeyDown += this.TimePickerPreviewKeyDown;
selector.SelectionChanged += this.TimePickerSelectionChanged;
}
}

private bool ProcessKey(KeyEventArgs e)
{
switch (e.Key)
{
case Key.System:
{
switch (e.SystemKey)
{
case Key.Down:
{
if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)
{
TogglePopUp();
return true;
}

break;
}
}

break;
}

case Key.Enter:
{
// SetSelectedDate();
return true;
}
}

return false;
}

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (_textInputChanged)
{
_textInputChanged = false;

OnTextBoxLostFocus(sender, e);
}
}

private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = ProcessKey(e) || e.Handled;
}

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (!_deactivateTextChangedEvent)
{
_textInputChanged = true;
}
}
}
Expand Down

0 comments on commit 09b24dc

Please sign in to comment.