Skip to content

Commit cb72531

Browse files
authored
Merge pull request #23 from ButchersBoy/master
update from original repo
2 parents 55d8d11 + bc7307f commit cb72531

16 files changed

+111
-52
lines changed

MainDemo.Wpf/Snackbars.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
88
mc:Ignorable="d"
99
d:DesignHeight="300" d:DesignWidth="300">
10+
1011
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden">
1112
<Grid Margin="0 0 0 4">
1213
<Grid.ColumnDefinitions>

MainDemo.Wpf/TextFields.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
</TextBox>
7979
<TextBlock Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" Margin="16 0 8 0">OS</TextBlock>
8080
<ComboBox Grid.Row="1" Grid.Column="3" materialDesign:HintAssist.Hint="OS">
81-
<ComboBoxItem>Andoid</ComboBoxItem>
81+
<ComboBoxItem>Android</ComboBoxItem>
8282
<ComboBoxItem>iOS</ComboBoxItem>
8383
<ComboBoxItem>Linux</ComboBoxItem>
8484
<ComboBoxItem>Windows</ComboBoxItem>
@@ -115,7 +115,7 @@
115115
<TextBox Grid.Row="4" Grid.Column="1" materialDesign:HintAssist.Hint="Floating Hint"
116116
Style="{StaticResource MaterialDesignFloatingHintTextBox}" />
117117
<ComboBox Grid.Row="4" Grid.Column="3" materialDesign:HintAssist.Hint="OS" Style="{StaticResource MaterialDesignFloatingHintComboBox}">
118-
<ComboBoxItem>Andoid</ComboBoxItem>
118+
<ComboBoxItem>Android</ComboBoxItem>
119119
<ComboBoxItem>iOS</ComboBoxItem>
120120
<ComboBoxItem>Linux</ComboBoxItem>
121121
<ComboBoxItem>Windows</ComboBoxItem>

MaterialDesignThemes.Wpf/ComboBoxAssist.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ namespace MaterialDesignThemes.Wpf
99
{
1010
public static class ComboBoxAssist
1111
{
12-
#region ShowSelectedItem
13-
1412
/// <summary>
1513
/// By default the selected item his hidden from the drop down list, as per Material Design specifications.
1614
/// To revert to a more classic Windows desktop behaviour, and show the currently selected item again in the drop
@@ -32,7 +30,5 @@ public static void SetShowSelectedItem(DependencyObject element, object value)
3230
{
3331
element.SetValue(ShowSelectedItemProperty, value);
3432
}
35-
36-
#endregion
3733
}
3834
}

MaterialDesignThemes.Wpf/HintProxyFabric.ComboBox.cs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,52 @@ private sealed class ComboBoxHintProxy : IHintProxy
1616
private readonly ComboBox _comboBox;
1717
private readonly TextChangedEventHandler _comboBoxTextChangedEventHandler;
1818

19-
public object Content => _comboBox.IsEditable
20-
? _comboBox.Text
21-
: _comboBox.SelectedItem != null ? " " : null;
22-
23-
public bool IsLoaded => _comboBox.IsLoaded;
24-
public bool IsVisible => _comboBox.IsVisible;
25-
26-
public event EventHandler ContentChanged;
27-
public event EventHandler IsVisibleChanged;
28-
public event EventHandler Loaded;
29-
3019
public ComboBoxHintProxy(ComboBox comboBox)
3120
{
3221
if (comboBox == null) throw new ArgumentNullException(nameof(comboBox));
3322

3423
_comboBox = comboBox;
35-
_comboBoxTextChangedEventHandler = new TextChangedEventHandler(ComboBoxTextChanged);
24+
_comboBoxTextChangedEventHandler = ComboBoxTextChanged;
3625
_comboBox.AddHandler(TextBoxBase.TextChangedEvent, _comboBoxTextChangedEventHandler);
3726
_comboBox.SelectionChanged += ComboBoxSelectionChanged;
3827
_comboBox.Loaded += ComboBoxLoaded;
3928
_comboBox.IsVisibleChanged += ComboBoxIsVisibleChanged;
4029
}
4130

31+
public object Content
32+
{
33+
get
34+
{
35+
if (_comboBox.IsEditable)
36+
{
37+
return _comboBox.Text;
38+
}
39+
40+
var comboBoxItem = _comboBox.SelectedItem as ComboBoxItem;
41+
return comboBoxItem != null
42+
? comboBoxItem.Content
43+
: _comboBox.SelectedItem;
44+
}
45+
}
46+
47+
public bool IsLoaded => _comboBox.IsLoaded;
48+
49+
public bool IsVisible => _comboBox.IsVisible;
50+
51+
public bool IsEmpty()
52+
{
53+
return string.IsNullOrWhiteSpace(_comboBox.Text);
54+
}
55+
56+
public event EventHandler ContentChanged;
57+
58+
public event EventHandler IsVisibleChanged;
59+
60+
public event EventHandler Loaded;
61+
4262
private void ComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
4363
{
44-
ContentChanged?.Invoke(sender, EventArgs.Empty);
64+
_comboBox.Dispatcher.InvokeAsync(() => ContentChanged?.Invoke(sender, EventArgs.Empty));
4565
}
4666

4767
private void ComboBoxIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)

MaterialDesignThemes.Wpf/HintProxyFabric.PasswordBox.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ private sealed class PasswordBoxHintProxy : IHintProxy
99
{
1010
private readonly PasswordBox _passwordBox;
1111

12+
public bool IsEmpty() => string.IsNullOrWhiteSpace(_passwordBox.Password);
13+
1214
public object Content => _passwordBox.Password;
15+
1316
public bool IsLoaded => _passwordBox.IsLoaded;
17+
1418
public bool IsVisible => _passwordBox.IsVisible;
1519

1620
public event EventHandler ContentChanged;

MaterialDesignThemes.Wpf/HintProxyFabric.TextBox.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ private sealed class TextBoxHintProxy : IHintProxy
1111
private readonly TextBox _textBox;
1212

1313
public object Content => _textBox.Text;
14+
1415
public bool IsLoaded => _textBox.IsLoaded;
16+
1517
public bool IsVisible => _textBox.IsVisible;
1618

19+
public bool IsEmpty() => string.IsNullOrWhiteSpace(_textBox.Text);
20+
1721
public event EventHandler ContentChanged;
1822
public event EventHandler IsVisibleChanged;
1923
public event EventHandler Loaded;

MaterialDesignThemes.Wpf/IHintProxy.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ namespace MaterialDesignThemes.Wpf
1414
/// </summary>
1515
public interface IHintProxy : IDisposable
1616
{
17+
/// <summary>
18+
/// Checks to see if the targetted control can be deemed as logically
19+
/// empty, even if not null, affecting the current hint display.
20+
/// </summary>
21+
/// <returns></returns>
22+
bool IsEmpty();
23+
24+
[Obsolete]
1725
object Content { get; }
1826

1927
bool IsLoaded { get; }

MaterialDesignThemes.Wpf/ISnackbarMessageQueue.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ public interface ISnackbarMessageQueue
4141
/// <param name="content">Message.</param>
4242
/// <param name="actionContent">Content for the action button.</param>
4343
/// <param name="actionHandler">Call back to be executed if user clicks the action button.</param>
44-
/// <param name="neverConsiderToBeDuplicate">Subsequent, duplicate messages queued within a short time span will
45-
/// be discarded. To override this behaviour and ensure the message always gets displayed set to <c>true</c>.</param>
46-
void Enqueue(object content, object actionContent, Action actionHandler, bool neverConsiderToBeDuplicate);
44+
/// <param name="promote">The message will promoted to the front ot the queue and never considered to be a duplicate.</param>
45+
void Enqueue(object content, object actionContent, Action actionHandler, bool promote);
4746

4847
/// <summary>
4948
/// Queues a notificaton message for display in a snackbar.
@@ -52,11 +51,7 @@ public interface ISnackbarMessageQueue
5251
/// <param name="actionContent">Content for the action button.</param>
5352
/// <param name="actionHandler">Call back to be executed if user clicks the action button.</param>
5453
/// <param name="actionArgument">Argument to pass to <paramref name="actionHandler"/>.</param>
55-
/// <param name="neverConsiderToBeDuplicate">Subsequent, duplicate messages queued within a short time span will
56-
/// be discarded. To override this behaviour and ensure the message always gets displayed set to <c>true</c>.</param>
57-
void Enqueue<TArgument>(object content, object actionContent, Action<TArgument> actionHandler, TArgument actionArgument, bool neverConsiderToBeDuplicate);
58-
59-
//TODO consider additional variants of Enqueue:
60-
// ShowAsync(. . .)
54+
/// <param name="promote">The message will promoted to the front ot the queue and never considered to be a duplicate.</param>
55+
void Enqueue<TArgument>(object content, object actionContent, Action<TArgument> actionHandler, TArgument actionArgument, bool promote);
6156
}
6257
}

MaterialDesignThemes.Wpf/SmartHint.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,18 @@ public object Hint
5252

5353
#region IsContentNullOrEmpty
5454

55-
public static readonly DependencyProperty IsContentNullOrEmptyProperty = DependencyProperty.Register(
56-
nameof(IsContentNullOrEmpty), typeof(bool), typeof(SmartHint), new PropertyMetadata(default(bool)));
55+
private static readonly DependencyPropertyKey IsContentNullOrEmptyPropertyKey =
56+
DependencyProperty.RegisterReadOnly(
57+
"IsContentNullOrEmpty", typeof(bool), typeof(SmartHint),
58+
new PropertyMetadata(default(bool)));
59+
60+
public static readonly DependencyProperty IsContentNullOrEmptyProperty =
61+
IsContentNullOrEmptyPropertyKey.DependencyProperty;
5762

5863
public bool IsContentNullOrEmpty
5964
{
60-
get { return (bool)GetValue(IsContentNullOrEmptyProperty); }
61-
set { SetValue(IsContentNullOrEmptyProperty, value); }
65+
get { return (bool) GetValue(IsContentNullOrEmptyProperty); }
66+
private set { SetValue(IsContentNullOrEmptyPropertyKey, value); }
6267
}
6368

6469
#endregion
@@ -150,7 +155,7 @@ private static void HintProxyPropertyChangedCallback(DependencyObject dependency
150155

151156
protected virtual void OnHintProxyContentChanged(object sender, EventArgs e)
152157
{
153-
IsContentNullOrEmpty = string.IsNullOrEmpty((HintProxy.Content ?? "").ToString());
158+
IsContentNullOrEmpty = HintProxy.IsEmpty();
154159

155160
if (HintProxy.IsLoaded)
156161
{
@@ -182,7 +187,7 @@ private void RefreshState(bool useTransitions)
182187

183188
var action = new Action(() =>
184189
{
185-
var state = String.IsNullOrEmpty((proxy.Content ?? String.Empty).ToString())
190+
var state = proxy.IsEmpty()
186191
? ContentEmptyName
187192
: ContentNotEmptyName;
188193

@@ -198,5 +203,7 @@ private void RefreshState(bool useTransitions)
198203
Dispatcher.BeginInvoke(action);
199204
}
200205
}
206+
207+
201208
}
202209
}

MaterialDesignThemes.Wpf/SnackbarMessageQueue.cs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class SnackbarMessageQueue : ISnackbarMessageQueue, IDisposable
1313
{
1414
private readonly TimeSpan _messageDuration;
1515
private readonly HashSet<Snackbar> _pairedSnackbars = new HashSet<Snackbar>();
16-
private readonly Queue<SnackbarMessageQueueItem> _snackbarMessages = new Queue<SnackbarMessageQueueItem>();
16+
private readonly LinkedList<SnackbarMessageQueueItem> _snackbarMessages = new LinkedList<SnackbarMessageQueueItem>();
1717
private readonly ManualResetEvent _disposedEvent = new ManualResetEvent(false);
1818
private readonly ManualResetEvent _pausedEvent = new ManualResetEvent(false);
1919
private readonly ManualResetEvent _messageWaitingEvent = new ManualResetEvent(false);
@@ -193,7 +193,7 @@ public void Enqueue(object content, bool neverConsiderToBeDuplicate)
193193
{
194194
if (content == null) throw new ArgumentNullException(nameof(content));
195195

196-
_snackbarMessages.Enqueue(new SnackbarMessageQueueItem(content));
196+
_snackbarMessages.AddLast(new SnackbarMessageQueueItem(content));
197197
_messageWaitingEvent.Set();
198198
}
199199

@@ -202,11 +202,11 @@ public void Enqueue(object content, object actionContent, Action actionHandler)
202202
Enqueue(content, actionContent, actionHandler, false);
203203
}
204204

205-
public void Enqueue(object content, object actionContent, Action actionHandler, bool neverConsiderToBeDuplicate)
205+
public void Enqueue(object content, object actionContent, Action actionHandler, bool promote)
206206
{
207207
if (content == null) throw new ArgumentNullException(nameof(content));
208208

209-
_snackbarMessages.Enqueue(new SnackbarMessageQueueItem(content, actionContent, actionHandler));
209+
_snackbarMessages.AddLast(new SnackbarMessageQueueItem(content, actionContent, actionHandler));
210210
_messageWaitingEvent.Set();
211211
}
212212

@@ -217,7 +217,7 @@ public void Enqueue<TArgument>(object content, object actionContent, Action<TArg
217217
}
218218

219219
public void Enqueue<TArgument>(object content, object actionContent, Action<TArgument> actionHandler,
220-
TArgument actionArgument, bool neverConsiderToBeDuplicate)
220+
TArgument actionArgument, bool promote)
221221
{
222222
if (content == null) throw new ArgumentNullException(nameof(content));
223223

@@ -230,11 +230,32 @@ public void Enqueue<TArgument>(object content, object actionContent, Action<TArg
230230
}
231231

232232
var argumentType = actionArgument != null ? typeof(TArgument) : null;
233-
_snackbarMessages.Enqueue(new SnackbarMessageQueueItem(content, actionContent, actionHandler,
234-
actionArgument, argumentType, neverConsiderToBeDuplicate));
233+
234+
var snackbarMessageQueueItem = new SnackbarMessageQueueItem(content, actionContent, actionHandler,
235+
actionArgument, argumentType, promote);
236+
if (promote)
237+
InsertAsLastNotPromotedNode(snackbarMessageQueueItem);
238+
else
239+
_snackbarMessages.AddLast(snackbarMessageQueueItem);
240+
235241
_messageWaitingEvent.Set();
236242
}
237243

244+
private void InsertAsLastNotPromotedNode(SnackbarMessageQueueItem snackbarMessageQueueItem)
245+
{
246+
var node = _snackbarMessages.First;
247+
while (node != null)
248+
{
249+
if (!node.Value.IsPromoted)
250+
{
251+
_snackbarMessages.AddBefore(node, snackbarMessageQueueItem);
252+
return;
253+
}
254+
node = node.Next;
255+
}
256+
_snackbarMessages.AddLast(snackbarMessageQueueItem);
257+
}
258+
238259
private async void PumpAsync()
239260
{
240261
while (!_isDisposed)
@@ -264,9 +285,10 @@ private async void PumpAsync()
264285
//show message
265286
if (snackbar != null)
266287
{
267-
var message = _snackbarMessages.Dequeue();
288+
var message = _snackbarMessages.First.Value;
289+
_snackbarMessages.RemoveFirst();
268290
if (_latestShownItem == null
269-
|| message.NeverConsiderToBeDuplicate
291+
|| message.IsPromoted
270292
|| !Equals(_latestShownItem.Item1.Content, message.Content)
271293
|| !Equals(_latestShownItem.Item1.ActionContent, message.ActionContent)
272294
|| _latestShownItem.Item2 <= DateTime.Now.Subtract(_messageDuration))
@@ -359,7 +381,7 @@ await Task.WhenAny(
359381
durationPassedWaitHandle
360382
});
361383
}),
362-
Task.Factory.StartNew(() => actionClickWaitHandle.WaitOne()));
384+
Task.Factory.StartNew(actionClickWaitHandle.WaitOne));
363385
}
364386

365387
private static void DoActionCallback(SnackbarMessageQueueItem messageQueueItem)
@@ -403,7 +425,7 @@ public void Dispose()
403425
_isDisposed = true;
404426
_disposedEvent.Set();
405427
_disposedEvent.Dispose();
406-
_pausedEvent.Dispose();
428+
_pausedEvent.Dispose();
407429
}
408430
}
409431
}

0 commit comments

Comments
 (0)