diff --git a/Directory.Build.props b/Directory.Build.props
index 0e7b282a..a1fcc387 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -54,7 +54,7 @@
-
+
diff --git a/src/CrissCross.MAUI/CrissCross.MAUI.csproj b/src/CrissCross.MAUI/CrissCross.MAUI.csproj
index b4c9188e..bb8eb4a2 100644
--- a/src/CrissCross.MAUI/CrissCross.MAUI.csproj
+++ b/src/CrissCross.MAUI/CrissCross.MAUI.csproj
@@ -16,6 +16,7 @@
6.5
+
diff --git a/src/CrissCross.WPF.Plot/CrissCross.WPF.Plot.csproj b/src/CrissCross.WPF.Plot/CrissCross.WPF.Plot.csproj
index 8f42de72..b4a9f0cb 100644
--- a/src/CrissCross.WPF.Plot/CrissCross.WPF.Plot.csproj
+++ b/src/CrissCross.WPF.Plot/CrissCross.WPF.Plot.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/src/CrissCross.WPF.Plot/Live/StreamerUI.cs b/src/CrissCross.WPF.Plot/Live/StreamerUI.cs
index e1ac1cf0..3c503035 100644
--- a/src/CrissCross.WPF.Plot/Live/StreamerUI.cs
+++ b/src/CrissCross.WPF.Plot/Live/StreamerUI.cs
@@ -263,13 +263,16 @@ public void UpdateStream(IObservable<(string? Name, IList? Value, IList<
var datetime = new List(data.DateTime.ToList().ConvertAll(x => new DateTime(Convert.ToInt64(x)).ToOADate()));
var coord = datetime.Zip(values, (d, v) => new Coordinates(d, v));
ItemName = data.Name;
- Streamer!.Data.Clear();
- Streamer.Add(coord);
+ Streamer?.Data.Coordinates.Clear();
+ foreach (var co in coord)
+ {
+ Streamer?.Data.Add(co);
+ }
// UPDATE X AXIS
if (ManualScale || AutoScale)
{
- Plot.Plot.Axes.SetLimitsX(doublelimits, doublenow, Streamer.Axes.XAxis);
+ Plot.Plot.Axes.SetLimitsX(doublelimits, doublenow, Streamer!.Axes.XAxis);
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/Border/Border.cs b/src/CrissCross.WPF.UI/Controls/Border/Border.cs
index 13ed59d3..d7f145d2 100644
--- a/src/CrissCross.WPF.UI/Controls/Border/Border.cs
+++ b/src/CrissCross.WPF.UI/Controls/Border/Border.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class Border : System.Windows.Controls.Border;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class Border : System.Windows.Controls.Border;
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Button.cs b/src/CrissCross.WPF.UI/Controls/Button/Button.cs
index d4f242c0..74070672 100644
--- a/src/CrissCross.WPF.UI/Controls/Button/Button.cs
+++ b/src/CrissCross.WPF.UI/Controls/Button/Button.cs
@@ -2,7 +2,6 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System.Windows.Controls;
using CrissCross.WPF.UI.Converters;
namespace CrissCross.WPF.UI.Controls;
diff --git a/src/CrissCross.WPF.UI/Controls/Calendar/Calendar.cs b/src/CrissCross.WPF.UI/Controls/Calendar/Calendar.cs
index 9b30f9c6..0f5603e4 100644
--- a/src/CrissCross.WPF.UI/Controls/Calendar/Calendar.cs
+++ b/src/CrissCross.WPF.UI/Controls/Calendar/Calendar.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class Calendar : System.Windows.Controls.Calendar;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class Calendar : System.Windows.Controls.Calendar;
diff --git a/src/CrissCross.WPF.UI/Controls/CheckBox/CheckBox.cs b/src/CrissCross.WPF.UI/Controls/CheckBox/CheckBox.cs
index 5d6c7dbf..2afeadbd 100644
--- a/src/CrissCross.WPF.UI/Controls/CheckBox/CheckBox.cs
+++ b/src/CrissCross.WPF.UI/Controls/CheckBox/CheckBox.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class CheckBox : System.Windows.Controls.CheckBox;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class CheckBox : System.Windows.Controls.CheckBox;
diff --git a/src/CrissCross.WPF.UI/Controls/ComboBox/ComboBox.cs b/src/CrissCross.WPF.UI/Controls/ComboBox/ComboBox.cs
index 3c7962e4..6e15281d 100644
--- a/src/CrissCross.WPF.UI/Controls/ComboBox/ComboBox.cs
+++ b/src/CrissCross.WPF.UI/Controls/ComboBox/ComboBox.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class ComboBox : System.Windows.Controls.ComboBox;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class ComboBox : System.Windows.Controls.ComboBox;
diff --git a/src/CrissCross.WPF.UI/Controls/DateTimePicker/DateTimePicker.xaml.cs b/src/CrissCross.WPF.UI/Controls/DateTimePicker/DateTimePicker.xaml.cs
index fd5ea6c2..16ed71ab 100644
--- a/src/CrissCross.WPF.UI/Controls/DateTimePicker/DateTimePicker.xaml.cs
+++ b/src/CrissCross.WPF.UI/Controls/DateTimePicker/DateTimePicker.xaml.cs
@@ -6,146 +6,145 @@
using System.Windows.Controls.Primitives;
using System.Windows.Input;
-namespace CrissCross.WPF.UI
+namespace CrissCross.WPF.UI;
+
+///
+/// Interaction logic for DateTimePicker.xaml.
+///
+public partial class DateTimePicker : UserControl
{
///
- /// Interaction logic for DateTimePicker.xaml.
+ /// The selected date property.
///
- public partial class DateTimePicker : UserControl
- {
- ///
- /// The selected date property.
- ///
- public static readonly DependencyProperty SelectedDateProperty = DependencyProperty.Register(
- nameof(SelectedDate),
+ public static readonly DependencyProperty SelectedDateProperty = DependencyProperty.Register(
+ nameof(SelectedDate),
+ typeof(DateTime),
+ typeof(DateTimePicker),
+ new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+
+ ///
+ /// The display date start property.
+ ///
+ public static readonly DependencyProperty DisplayDateStartProperty =
+ DependencyProperty.Register(
+ nameof(DisplayDateStart),
typeof(DateTime),
typeof(DateTimePicker),
- new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
-
- ///
- /// The display date start property.
- ///
- public static readonly DependencyProperty DisplayDateStartProperty =
- DependencyProperty.Register(
- nameof(DisplayDateStart),
- typeof(DateTime),
- typeof(DateTimePicker),
- new PropertyMetadata(DateTime.MinValue, DateChanged));
-
- ///
- /// The display date end property.
- ///
- public static readonly DependencyProperty DisplayDateEndProperty =
- DependencyProperty.Register(
- nameof(DisplayDateEnd),
- typeof(DateTime),
- typeof(DateTimePicker),
- new PropertyMetadata(DateTime.Now, DateChanged));
-
- private const string DateTimeFormat = "dd.MM.yyyy HH:mm";
-
- ///
- /// Initializes a new instance of the class.
- ///
- public DateTimePicker()
- {
- InitializeComponent();
- CalDisplay.SelectedDatesChanged += CalDisplay_SelectedDatesChanged;
- CalDisplay.SelectedDate = DateTime.Now;
- }
+ new PropertyMetadata(DateTime.MinValue, DateChanged));
- ///
- /// Gets or sets the selected date.
- ///
- ///
- /// The selected date.
- ///
- public DateTime SelectedDate
- {
- get => (DateTime)GetValue(SelectedDateProperty);
- set => SetValue(SelectedDateProperty, value);
- }
+ ///
+ /// The display date end property.
+ ///
+ public static readonly DependencyProperty DisplayDateEndProperty =
+ DependencyProperty.Register(
+ nameof(DisplayDateEnd),
+ typeof(DateTime),
+ typeof(DateTimePicker),
+ new PropertyMetadata(DateTime.Now, DateChanged));
- ///
- /// Gets or sets the display date start.
- ///
- ///
- /// The display date start.
- ///
- public DateTime DisplayDateStart
- {
- get => (DateTime)GetValue(DisplayDateStartProperty);
- set => SetValue(DisplayDateStartProperty, value);
- }
+ private const string DateTimeFormat = "dd.MM.yyyy HH:mm";
- ///
- /// Gets or sets the display date end.
- ///
- ///
- /// The display date end.
- ///
- public DateTime DisplayDateEnd
- {
- get => (DateTime)GetValue(DisplayDateEndProperty);
- set => SetValue(DisplayDateEndProperty, value);
- }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DateTimePicker()
+ {
+ InitializeComponent();
+ CalDisplay.SelectedDatesChanged += CalDisplay_SelectedDatesChanged;
+ CalDisplay.SelectedDate = DateTime.Now;
+ }
+
+ ///
+ /// Gets or sets the selected date.
+ ///
+ ///
+ /// The selected date.
+ ///
+ public DateTime SelectedDate
+ {
+ get => (DateTime)GetValue(SelectedDateProperty);
+ set => SetValue(SelectedDateProperty, value);
+ }
+
+ ///
+ /// Gets or sets the display date start.
+ ///
+ ///
+ /// The display date start.
+ ///
+ public DateTime DisplayDateStart
+ {
+ get => (DateTime)GetValue(DisplayDateStartProperty);
+ set => SetValue(DisplayDateStartProperty, value);
+ }
+
+ ///
+ /// Gets or sets the display date end.
+ ///
+ ///
+ /// The display date end.
+ ///
+ public DateTime DisplayDateEnd
+ {
+ get => (DateTime)GetValue(DisplayDateEndProperty);
+ set => SetValue(DisplayDateEndProperty, value);
+ }
- private static void DateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ private static void DateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is DateTimePicker dateTimePicker)
{
- if (d is DateTimePicker dateTimePicker)
+ if (dateTimePicker.DisplayDateStart > dateTimePicker.DisplayDateEnd)
{
- if (dateTimePicker.DisplayDateStart > dateTimePicker.DisplayDateEnd)
- {
- dateTimePicker.DisplayDateEnd = dateTimePicker.DisplayDateStart;
- }
-
- if (dateTimePicker.DisplayDateStart > dateTimePicker.SelectedDate)
- {
- dateTimePicker.SelectedDate = dateTimePicker.DisplayDateStart;
- }
-
- if (dateTimePicker.DisplayDateEnd < dateTimePicker.SelectedDate)
- {
- dateTimePicker.SelectedDate = dateTimePicker.DisplayDateEnd;
- }
-
- dateTimePicker.CalDisplay_SelectedDatesChanged(null, EventArgs.Empty);
+ dateTimePicker.DisplayDateEnd = dateTimePicker.DisplayDateStart;
}
- }
- private void CalDisplay_SelectedDatesChanged(object? sender, EventArgs e)
- {
- var hours = (Hours?.SelectedItem as ComboBoxItem)?.Content?.ToString() ?? "0";
- var minutes = (Min?.SelectedItem as ComboBoxItem)?.Content?.ToString() ?? "0";
- var timeSpan = TimeSpan.Parse(hours + ":" + minutes);
- if (CalDisplay.SelectedDate.Value.Date == DateTime.Today.Date && timeSpan.CompareTo(DateTime.Now.TimeOfDay) < 0)
+ if (dateTimePicker.DisplayDateStart > dateTimePicker.SelectedDate)
{
- timeSpan = TimeSpan.FromHours(DateTime.Now.Hour + 1);
+ dateTimePicker.SelectedDate = dateTimePicker.DisplayDateStart;
}
- var date = CalDisplay.SelectedDate.Value.Date + timeSpan;
- DateDisplay.Text = date.ToString(DateTimeFormat);
- SelectedDate = date;
- }
+ if (dateTimePicker.DisplayDateEnd < dateTimePicker.SelectedDate)
+ {
+ dateTimePicker.SelectedDate = dateTimePicker.DisplayDateEnd;
+ }
- private void SaveTime_Click(object sender, RoutedEventArgs e)
- {
- CalDisplay_SelectedDatesChanged(SaveTime, EventArgs.Empty);
- PopUpCalendarButton.IsChecked = false;
+ dateTimePicker.CalDisplay_SelectedDatesChanged(null, EventArgs.Empty);
}
+ }
- private void Time_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ private void CalDisplay_SelectedDatesChanged(object? sender, EventArgs e)
+ {
+ var hours = (Hours?.SelectedItem as ComboBoxItem)?.Content?.ToString() ?? "0";
+ var minutes = (Min?.SelectedItem as ComboBoxItem)?.Content?.ToString() ?? "0";
+ var timeSpan = TimeSpan.Parse(hours + ":" + minutes);
+ if (CalDisplay.SelectedDate.Value.Date == DateTime.Today.Date && timeSpan.CompareTo(DateTime.Now.TimeOfDay) < 0)
{
- CalDisplay_SelectedDatesChanged(sender, e);
+ timeSpan = TimeSpan.FromHours(DateTime.Now.Hour + 1);
}
- private void CalDisplay_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ var date = CalDisplay.SelectedDate.Value.Date + timeSpan;
+ DateDisplay.Text = date.ToString(DateTimeFormat);
+ SelectedDate = date;
+ }
+
+ private void SaveTime_Click(object sender, RoutedEventArgs e)
+ {
+ CalDisplay_SelectedDatesChanged(SaveTime, EventArgs.Empty);
+ PopUpCalendarButton.IsChecked = false;
+ }
+
+ private void Time_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ CalDisplay_SelectedDatesChanged(sender, e);
+ }
+
+ private void CalDisplay_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ // that it's not necessary to click twice after opening the calendar https://stackoverflow.com/q/6024372
+ if (Mouse.Captured is CalendarItem)
{
- // that it's not necessary to click twice after opening the calendar https://stackoverflow.com/q/6024372
- if (Mouse.Captured is CalendarItem)
- {
- Mouse.Capture(null);
- }
+ Mouse.Capture(null);
}
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCache.cs b/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCache.cs
index e02b8015..c805344c 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCache.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCache.cs
@@ -4,154 +4,153 @@
using System.Windows.Media.Imaging;
-namespace CrissCross.WPF.UI.Controls
+namespace CrissCross.WPF.UI.Controls;
+
+internal static class AnimationCache
{
- internal static class AnimationCache
+ private static readonly Dictionary _animationCache = new Dictionary();
+ private static readonly Dictionary> _imageControls = new Dictionary>();
+
+ public static void AddControlForSource(ImageSource source, Image imageControl)
+ {
+ var cacheKey = new CacheKey(source);
+ if (!_imageControls.TryGetValue(cacheKey, out var controls))
+ {
+ _imageControls[cacheKey] = controls = new HashSet();
+ }
+
+ controls.Add(imageControl);
+ }
+
+ public static void RemoveControlForSource(ImageSource source, Image imageControl)
+ {
+ var cacheKey = new CacheKey(source);
+ if (_imageControls.TryGetValue(cacheKey, out var controls) && controls.Remove(imageControl) && controls.Count == 0)
+ {
+ _animationCache.Remove(cacheKey);
+ _imageControls.Remove(cacheKey);
+ }
+ }
+
+ public static void Add(ImageSource source, AnimationCacheEntry entry)
+ {
+ var key = new CacheKey(source);
+ _animationCache[key] = entry;
+ }
+
+ public static void Remove(ImageSource source)
{
- private static readonly Dictionary _animationCache = new Dictionary();
- private static readonly Dictionary> _imageControls = new Dictionary>();
+ var key = new CacheKey(source);
+ _animationCache.Remove(key);
+ }
+
+ public static AnimationCacheEntry? Get(ImageSource source)
+ {
+ var key = new CacheKey(source);
+ _animationCache.TryGetValue(key, out var entry);
+ return entry;
+ }
- public static void AddControlForSource(ImageSource source, Image imageControl)
+ private readonly struct CacheKey(ImageSource source) : IEquatable
+ {
+ private readonly ImageSource _source = source;
+
+ public override bool Equals(object? obj)
{
- var cacheKey = new CacheKey(source);
- if (!_imageControls.TryGetValue(cacheKey, out var controls))
+ if (ReferenceEquals(null, obj))
{
- _imageControls[cacheKey] = controls = new HashSet();
+ return false;
}
- controls.Add(imageControl);
- }
+ if (Equals(obj))
+ {
+ return true;
+ }
- public static void RemoveControlForSource(ImageSource source, Image imageControl)
- {
- var cacheKey = new CacheKey(source);
- if (_imageControls.TryGetValue(cacheKey, out var controls) && controls.Remove(imageControl) && controls.Count == 0)
+ if (obj.GetType() != GetType())
{
- _animationCache.Remove(cacheKey);
- _imageControls.Remove(cacheKey);
+ return false;
}
- }
- public static void Add(ImageSource source, AnimationCacheEntry entry)
- {
- var key = new CacheKey(source);
- _animationCache[key] = entry;
+ return Equals((CacheKey)obj);
}
- public static void Remove(ImageSource source)
- {
- var key = new CacheKey(source);
- _animationCache.Remove(key);
- }
+ public bool Equals(CacheKey other) => ImageEquals(_source, other._source);
- public static AnimationCacheEntry? Get(ImageSource source)
- {
- var key = new CacheKey(source);
- _animationCache.TryGetValue(key, out var entry);
- return entry;
- }
+ public override int GetHashCode() => ImageGetHashCode(_source);
- private readonly struct CacheKey(ImageSource source) : IEquatable
+ private static int ImageGetHashCode(ImageSource image)
{
- private readonly ImageSource _source = source;
-
- public override bool Equals(object? obj)
+ if (image != null)
{
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- if (Equals(obj))
+ var uri = GetUri(image);
+ if (uri != null)
{
- return true;
+ return uri.GetHashCode();
}
-
- if (obj.GetType() != GetType())
- {
- return false;
- }
-
- return Equals((CacheKey)obj);
}
- public bool Equals(CacheKey other) => ImageEquals(_source, other._source);
-
- public override int GetHashCode() => ImageGetHashCode(_source);
+ return 0;
+ }
- private static int ImageGetHashCode(ImageSource image)
+ private static bool ImageEquals(ImageSource x, ImageSource y)
+ {
+ if (Equals(x, y))
{
- if (image != null)
- {
- var uri = GetUri(image);
- if (uri != null)
- {
- return uri.GetHashCode();
- }
- }
+ return true;
+ }
- return 0;
+ if ((x == null) != (y == null))
+ {
+ return false;
}
- private static bool ImageEquals(ImageSource x, ImageSource y)
+ // They can't both be null or Equals would have returned true
+ // and if any is null, the previous would have detected it
+ // ReSharper disable PossibleNullReferenceException
+ if (x?.GetType() != y?.GetType())
{
- if (Equals(x, y))
- {
- return true;
- }
+ return false;
+ }
- if ((x == null) != (y == null))
+ var xUri = GetUri(x);
+ var yUri = GetUri(y);
+ return xUri != null && xUri == yUri;
+ }
+
+ private static Uri? GetUri(ImageSource? image)
+ {
+ if (image is BitmapImage bmp && bmp.UriSource != null)
+ {
+ if (bmp.UriSource.IsAbsoluteUri)
{
- return false;
+ return bmp.UriSource;
}
- // They can't both be null or Equals would have returned true
- // and if any is null, the previous would have detected it
- // ReSharper disable PossibleNullReferenceException
- if (x?.GetType() != y?.GetType())
+ if (bmp.BaseUri != null)
{
- return false;
+ return new Uri(bmp.BaseUri, bmp.UriSource);
}
-
- var xUri = GetUri(x);
- var yUri = GetUri(y);
- return xUri != null && xUri == yUri;
}
- private static Uri? GetUri(ImageSource? image)
+ if (image is BitmapFrame frame)
{
- if (image is BitmapImage bmp && bmp.UriSource != null)
+ var s = frame.ToString();
+ if (s != frame.GetType().FullName && Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out var fUri))
{
- if (bmp.UriSource.IsAbsoluteUri)
- {
- return bmp.UriSource;
- }
-
- if (bmp.BaseUri != null)
+ if (fUri.IsAbsoluteUri)
{
- return new Uri(bmp.BaseUri, bmp.UriSource);
+ return fUri;
}
- }
- if (image is BitmapFrame frame)
- {
- var s = frame.ToString();
- if (s != frame.GetType().FullName && Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out var fUri))
+ if (frame.BaseUri != null)
{
- if (fUri.IsAbsoluteUri)
- {
- return fUri;
- }
-
- if (frame.BaseUri != null)
- {
- return new Uri(frame.BaseUri, fUri);
- }
+ return new Uri(frame.BaseUri, fUri);
}
}
-
- return null;
}
+
+ return null;
}
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCacheEntry.cs b/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCacheEntry.cs
index 257bb29c..04b9c377 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCacheEntry.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/AnimationCacheEntry.cs
@@ -4,14 +4,13 @@
using System.Windows.Media.Animation;
-namespace CrissCross.WPF.UI.Controls
+namespace CrissCross.WPF.UI.Controls;
+
+internal class AnimationCacheEntry(ObjectKeyFrameCollection keyFrames, Duration duration, int repeatCountFromMetadata)
{
- internal class AnimationCacheEntry(ObjectKeyFrameCollection keyFrames, Duration duration, int repeatCountFromMetadata)
- {
- public ObjectKeyFrameCollection KeyFrames { get; } = keyFrames;
+ public ObjectKeyFrameCollection KeyFrames { get; } = keyFrames;
- public Duration Duration { get; } = duration;
+ public Duration Duration { get; } = duration;
- public int RepeatCountFromMetadata { get; } = repeatCountFromMetadata;
- }
+ public int RepeatCountFromMetadata { get; } = repeatCountFromMetadata;
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifApplicationExtension.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifApplicationExtension.cs
index 49354868..48db2b06 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifApplicationExtension.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifApplicationExtension.cs
@@ -5,50 +5,49 @@
using System.IO;
using System.Text;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+// label 0xFF
+internal sealed class GifApplicationExtension : GifExtension
{
- // label 0xFF
- internal sealed class GifApplicationExtension : GifExtension
+ internal const int ExtensionLabel = 0xFF;
+
+ private GifApplicationExtension()
{
- internal const int ExtensionLabel = 0xFF;
+ }
- private GifApplicationExtension()
- {
- }
+ public int BlockSize { get; private set; }
- public int BlockSize { get; private set; }
+ public string? ApplicationIdentifier { get; private set; }
- public string? ApplicationIdentifier { get; private set; }
+ public byte[]? AuthenticationCode { get; private set; }
- public byte[]? AuthenticationCode { get; private set; }
+ public byte[]? Data { get; private set; }
- public byte[]? Data { get; private set; }
+ internal override GifBlockKind Kind => GifBlockKind.SpecialPurpose;
- internal override GifBlockKind Kind => GifBlockKind.SpecialPurpose;
+ internal static GifApplicationExtension ReadApplication(Stream stream)
+ {
+ var ext = new GifApplicationExtension();
+ ext.Read(stream);
+ return ext;
+ }
- internal static GifApplicationExtension ReadApplication(Stream stream)
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xFF) has already been read
+ var bytes = new byte[12];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ BlockSize = bytes[0]; // should always be 11
+ if (BlockSize != 11)
{
- var ext = new GifApplicationExtension();
- ext.Read(stream);
- return ext;
+ throw GifHelpers.InvalidBlockSizeException("Application Extension", 11, BlockSize);
}
- private void Read(Stream stream)
- {
- // Note: at this point, the label (0xFF) has already been read
- var bytes = new byte[12];
- stream.ReadAll(bytes, 0, bytes.Length);
- BlockSize = bytes[0]; // should always be 11
- if (BlockSize != 11)
- {
- throw GifHelpers.InvalidBlockSizeException("Application Extension", 11, BlockSize);
- }
-
- ApplicationIdentifier = Encoding.ASCII.GetString(bytes, 1, 8);
- var authCode = new byte[3];
- Array.Copy(bytes, 9, authCode, 0, 3);
- AuthenticationCode = authCode;
- Data = GifHelpers.ReadDataBlocks(stream, false);
- }
+ ApplicationIdentifier = Encoding.ASCII.GetString(bytes, 1, 8);
+ var authCode = new byte[3];
+ Array.Copy(bytes, 9, authCode, 0, 3);
+ AuthenticationCode = authCode;
+ Data = GifHelpers.ReadDataBlocks(stream, false);
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlock.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlock.cs
index 7ff9ec32..5dd2c354 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlock.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlock.cs
@@ -4,27 +4,26 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal abstract class GifBlock
{
- internal abstract class GifBlock
- {
- internal abstract GifBlockKind Kind { get; }
+ internal abstract GifBlockKind Kind { get; }
- internal static GifBlock ReadBlock(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ internal static GifBlock ReadBlock(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ {
+ var blockId = stream.ReadByte();
+ if (blockId < 0)
{
- var blockId = stream.ReadByte();
- if (blockId < 0)
- {
- throw GifHelpers.UnexpectedEndOfStreamException();
- }
-
- return blockId switch
- {
- GifExtension.ExtensionIntroducer => GifExtension.ReadExtension(stream, controlExtensions, metadataOnly),
- GifFrame.ImageSeparator => GifFrame.ReadFrame(stream, controlExtensions, metadataOnly),
- GifTrailer.TrailerByte => GifTrailer.ReadTrailer(),
- _ => throw GifHelpers.UnknownBlockTypeException(blockId),
- };
+ throw GifHelpers.UnexpectedEndOfStreamException();
}
+
+ return blockId switch
+ {
+ GifExtension.ExtensionIntroducer => GifExtension.ReadExtension(stream, controlExtensions, metadataOnly),
+ GifFrame.ImageSeparator => GifFrame.ReadFrame(stream, controlExtensions, metadataOnly),
+ GifTrailer.TrailerByte => GifTrailer.ReadTrailer(),
+ _ => throw GifHelpers.UnknownBlockTypeException(blockId),
+ };
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlockKind.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlockKind.cs
index 2bf4c912..f0a3e5f2 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlockKind.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifBlockKind.cs
@@ -2,13 +2,12 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal enum GifBlockKind
{
- internal enum GifBlockKind
- {
- Control,
- GraphicRendering,
- SpecialPurpose,
- Other
- }
+ Control,
+ GraphicRendering,
+ SpecialPurpose,
+ Other
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifColor.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifColor.cs
index c6c5a44c..9bcb7f01 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifColor.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifColor.cs
@@ -2,16 +2,15 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal readonly record struct GifColor(byte R, byte G, byte B)
{
- internal readonly record struct GifColor(byte R, byte G, byte B)
- {
- public byte R { get; } = R;
+ public byte R { get; } = R;
- public byte G { get; } = G;
+ public byte G { get; } = G;
- public byte B { get; } = B;
+ public byte B { get; } = B;
- public override readonly string ToString() => string.Format("#{0:x2}{1:x2}{2:x2}", R, G, B);
- }
+ public override readonly string ToString() => string.Format("#{0:x2}{1:x2}{2:x2}", R, G, B);
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifCommentExtension.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifCommentExtension.cs
index 57d30aaa..5c0ee9b8 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifCommentExtension.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifCommentExtension.cs
@@ -5,35 +5,34 @@
using System.IO;
using System.Text;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal sealed class GifCommentExtension : GifExtension
{
- internal sealed class GifCommentExtension : GifExtension
- {
- internal const int ExtensionLabel = 0xFE;
+ internal const int ExtensionLabel = 0xFE;
- private GifCommentExtension()
- {
- }
+ private GifCommentExtension()
+ {
+ }
- public string? Text { get; private set; }
+ public string? Text { get; private set; }
- internal override GifBlockKind Kind => GifBlockKind.SpecialPurpose;
+ internal override GifBlockKind Kind => GifBlockKind.SpecialPurpose;
- internal static GifCommentExtension ReadComment(Stream stream)
- {
- var comment = new GifCommentExtension();
- comment.Read(stream);
- return comment;
- }
+ internal static GifCommentExtension ReadComment(Stream stream)
+ {
+ var comment = new GifCommentExtension();
+ comment.Read(stream);
+ return comment;
+ }
- private void Read(Stream stream)
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xFE) has already been read
+ var bytes = GifHelpers.ReadDataBlocks(stream, false);
+ if (bytes != null)
{
- // Note: at this point, the label (0xFE) has already been read
- var bytes = GifHelpers.ReadDataBlocks(stream, false);
- if (bytes != null)
- {
- Text = Encoding.ASCII.GetString(bytes);
- }
+ Text = Encoding.ASCII.GetString(bytes);
}
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifDecoderException.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifDecoderException.cs
index 07efcfa7..2a0721d2 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifDecoderException.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifDecoderException.cs
@@ -2,27 +2,26 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+///
+/// Gif Decoder Exception.
+///
+///
+[Serializable]
+public class GifDecoderException : Exception
{
- ///
- /// Gif Decoder Exception.
- ///
- ///
- [Serializable]
- public class GifDecoderException : Exception
+ internal GifDecoderException()
{
- internal GifDecoderException()
- {
- }
+ }
- internal GifDecoderException(string message)
- : base(message)
- {
- }
+ internal GifDecoderException(string message)
+ : base(message)
+ {
+ }
- internal GifDecoderException(string message, Exception inner)
- : base(message, inner)
- {
- }
+ internal GifDecoderException(string message, Exception inner)
+ : base(message, inner)
+ {
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifExtension.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifExtension.cs
index a4ecdbf3..e038ab58 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifExtension.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifExtension.cs
@@ -4,29 +4,28 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal abstract class GifExtension : GifBlock
{
- internal abstract class GifExtension : GifBlock
- {
- internal const int ExtensionIntroducer = 0x21;
+ internal const int ExtensionIntroducer = 0x21;
- internal static GifExtension ReadExtension(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ internal static GifExtension ReadExtension(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the Extension Introducer (0x21) has already been read
+ var label = stream.ReadByte();
+ if (label < 0)
{
- // Note: at this point, the Extension Introducer (0x21) has already been read
- var label = stream.ReadByte();
- if (label < 0)
- {
- throw GifHelpers.UnexpectedEndOfStreamException();
- }
-
- return label switch
- {
- GifGraphicControlExtension.ExtensionLabel => GifGraphicControlExtension.ReadGraphicsControl(stream),
- GifCommentExtension.ExtensionLabel => GifCommentExtension.ReadComment(stream),
- GifPlainTextExtension.ExtensionLabel => GifPlainTextExtension.ReadPlainText(stream, controlExtensions, metadataOnly),
- GifApplicationExtension.ExtensionLabel => GifApplicationExtension.ReadApplication(stream),
- _ => throw GifHelpers.UnknownExtensionTypeException(label),
- };
+ throw GifHelpers.UnexpectedEndOfStreamException();
}
+
+ return label switch
+ {
+ GifGraphicControlExtension.ExtensionLabel => GifGraphicControlExtension.ReadGraphicsControl(stream),
+ GifCommentExtension.ExtensionLabel => GifCommentExtension.ReadComment(stream),
+ GifPlainTextExtension.ExtensionLabel => GifPlainTextExtension.ReadPlainText(stream, controlExtensions, metadataOnly),
+ GifApplicationExtension.ExtensionLabel => GifApplicationExtension.ReadApplication(stream),
+ _ => throw GifHelpers.UnknownExtensionTypeException(label),
+ };
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFile.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFile.cs
index 4bb12fa6..1c829cb5 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFile.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFile.cs
@@ -4,96 +4,95 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal sealed class GifFile
{
- internal sealed class GifFile
+ private GifFile()
{
- private GifFile()
- {
- }
+ }
+
+ public GifHeader? Header { get; private set; }
- public GifHeader? Header { get; private set; }
+ public GifColor[]? GlobalColorTable { get; set; }
- public GifColor[]? GlobalColorTable { get; set; }
+ public IList? Frames { get; set; }
- public IList? Frames { get; set; }
+ public IList? Extensions { get; set; }
- public IList? Extensions { get; set; }
+ public ushort RepeatCount { get; set; }
- public ushort RepeatCount { get; set; }
+ internal static GifFile ReadGifFile(Stream stream, bool metadataOnly)
+ {
+ var file = new GifFile();
+ file.Read(stream, metadataOnly);
+ return file;
+ }
+
+ private void Read(Stream stream, bool metadataOnly)
+ {
+ Header = GifHeader.ReadHeader(stream);
- internal static GifFile ReadGifFile(Stream stream, bool metadataOnly)
+ if (Header.LogicalScreenDescriptor?.HasGlobalColorTable == true)
{
- var file = new GifFile();
- file.Read(stream, metadataOnly);
- return file;
+ GlobalColorTable = GifHelpers.ReadColorTable(stream, Header.LogicalScreenDescriptor.GlobalColorTableSize);
}
- private void Read(Stream stream, bool metadataOnly)
- {
- Header = GifHeader.ReadHeader(stream);
+ ReadFrames(stream, metadataOnly);
- if (Header.LogicalScreenDescriptor?.HasGlobalColorTable == true)
- {
- GlobalColorTable = GifHelpers.ReadColorTable(stream, Header.LogicalScreenDescriptor.GlobalColorTableSize);
- }
+ var netscapeExtension =
+ Extensions?
+ .OfType()
+ .FirstOrDefault(GifHelpers.IsNetscapeExtension);
- ReadFrames(stream, metadataOnly);
+ if (netscapeExtension != null)
+ {
+ RepeatCount = GifHelpers.GetRepeatCount(netscapeExtension);
+ }
+ else
+ {
+ RepeatCount = 1;
+ }
+ }
- var netscapeExtension =
- Extensions?
- .OfType()
- .FirstOrDefault(GifHelpers.IsNetscapeExtension);
+ private void ReadFrames(Stream stream, bool metadataOnly)
+ {
+ List frames = [];
+ List controlExtensions = [];
+ List specialExtensions = [];
+ while (true)
+ {
+ var block = GifBlock.ReadBlock(stream, controlExtensions, metadataOnly);
- if (netscapeExtension != null)
+ if (block.Kind == GifBlockKind.GraphicRendering)
{
- RepeatCount = GifHelpers.GetRepeatCount(netscapeExtension);
+ controlExtensions = [];
}
- else
+
+ if (block is GifFrame gifFrame)
{
- RepeatCount = 1;
+ frames.Add(gifFrame);
}
- }
-
- private void ReadFrames(Stream stream, bool metadataOnly)
- {
- List frames = [];
- List controlExtensions = [];
- List specialExtensions = [];
- while (true)
+ else if (block is GifExtension gifExtension)
{
- var block = GifBlock.ReadBlock(stream, controlExtensions, metadataOnly);
-
- if (block.Kind == GifBlockKind.GraphicRendering)
- {
- controlExtensions = [];
- }
-
- if (block is GifFrame gifFrame)
+ var extension = gifExtension;
+ switch (extension.Kind)
{
- frames.Add(gifFrame);
- }
- else if (block is GifExtension gifExtension)
- {
- var extension = gifExtension;
- switch (extension.Kind)
- {
- case GifBlockKind.Control:
- controlExtensions.Add(extension);
- break;
- case GifBlockKind.SpecialPurpose:
- specialExtensions.Add(extension);
- break;
- }
- }
- else if (block is GifTrailer)
- {
- break;
+ case GifBlockKind.Control:
+ controlExtensions.Add(extension);
+ break;
+ case GifBlockKind.SpecialPurpose:
+ specialExtensions.Add(extension);
+ break;
}
}
-
- Frames = frames.AsReadOnly();
- Extensions = specialExtensions.AsReadOnly();
+ else if (block is GifTrailer)
+ {
+ break;
+ }
}
+
+ Frames = frames.AsReadOnly();
+ Extensions = specialExtensions.AsReadOnly();
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFrame.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFrame.cs
index 3e2c8e1c..edd899af 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFrame.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifFrame.cs
@@ -4,46 +4,45 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal sealed class GifFrame : GifBlock
{
- internal sealed class GifFrame : GifBlock
- {
- internal const int ImageSeparator = 0x2C;
+ internal const int ImageSeparator = 0x2C;
- private GifFrame()
- {
- }
+ private GifFrame()
+ {
+ }
- public GifImageDescriptor? Descriptor { get; private set; }
+ public GifImageDescriptor? Descriptor { get; private set; }
- public GifColor[]? LocalColorTable { get; private set; }
+ public GifColor[]? LocalColorTable { get; private set; }
- public IList? Extensions { get; private set; }
+ public IList? Extensions { get; private set; }
- public GifImageData? ImageData { get; private set; }
+ public GifImageData? ImageData { get; private set; }
- internal override GifBlockKind Kind => GifBlockKind.GraphicRendering;
+ internal override GifBlockKind Kind => GifBlockKind.GraphicRendering;
- internal static GifFrame ReadFrame(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
- {
- var frame = new GifFrame();
+ internal static GifFrame ReadFrame(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ {
+ var frame = new GifFrame();
- frame.Read(stream, controlExtensions, metadataOnly);
+ frame.Read(stream, controlExtensions, metadataOnly);
- return frame;
- }
+ return frame;
+ }
- private void Read(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ private void Read(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the Image Separator (0x2C) has already been read
+ Descriptor = GifImageDescriptor.ReadImageDescriptor(stream);
+ if (Descriptor.HasLocalColorTable)
{
- // Note: at this point, the Image Separator (0x2C) has already been read
- Descriptor = GifImageDescriptor.ReadImageDescriptor(stream);
- if (Descriptor.HasLocalColorTable)
- {
- LocalColorTable = GifHelpers.ReadColorTable(stream, Descriptor.LocalColorTableSize);
- }
-
- ImageData = GifImageData.ReadImageData(stream, metadataOnly);
- Extensions = controlExtensions.ToList().AsReadOnly();
+ LocalColorTable = GifHelpers.ReadColorTable(stream, Descriptor.LocalColorTableSize);
}
+
+ ImageData = GifImageData.ReadImageData(stream, metadataOnly);
+ Extensions = controlExtensions.ToList().AsReadOnly();
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifGraphicControlExtension.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifGraphicControlExtension.cs
index 0f39912f..ada23095 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifGraphicControlExtension.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifGraphicControlExtension.cs
@@ -4,55 +4,54 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+// label 0xF9
+internal sealed class GifGraphicControlExtension : GifExtension
{
- // label 0xF9
- internal sealed class GifGraphicControlExtension : GifExtension
+ internal const int ExtensionLabel = 0xF9;
+
+ private GifGraphicControlExtension()
{
- internal const int ExtensionLabel = 0xF9;
+ }
- private GifGraphicControlExtension()
- {
- }
+ public int BlockSize { get; private set; }
- public int BlockSize { get; private set; }
+ public int DisposalMethod { get; private set; }
- public int DisposalMethod { get; private set; }
+ public bool UserInput { get; private set; }
- public bool UserInput { get; private set; }
+ public bool HasTransparency { get; private set; }
- public bool HasTransparency { get; private set; }
+ public int Delay { get; private set; }
- public int Delay { get; private set; }
+ public int TransparencyIndex { get; private set; }
- public int TransparencyIndex { get; private set; }
+ internal override GifBlockKind Kind => GifBlockKind.Control;
- internal override GifBlockKind Kind => GifBlockKind.Control;
+ internal static GifGraphicControlExtension ReadGraphicsControl(Stream stream)
+ {
+ var ext = new GifGraphicControlExtension();
+ ext.Read(stream);
+ return ext;
+ }
- internal static GifGraphicControlExtension ReadGraphicsControl(Stream stream)
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xF9) has already been read
+ var bytes = new byte[6];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ BlockSize = bytes[0]; // should always be 4
+ if (BlockSize != 4)
{
- var ext = new GifGraphicControlExtension();
- ext.Read(stream);
- return ext;
+ throw GifHelpers.InvalidBlockSizeException("Graphic Control Extension", 4, BlockSize);
}
- private void Read(Stream stream)
- {
- // Note: at this point, the label (0xF9) has already been read
- var bytes = new byte[6];
- stream.ReadAll(bytes, 0, bytes.Length);
- BlockSize = bytes[0]; // should always be 4
- if (BlockSize != 4)
- {
- throw GifHelpers.InvalidBlockSizeException("Graphic Control Extension", 4, BlockSize);
- }
-
- var packedFields = bytes[1];
- DisposalMethod = (packedFields & 0x1C) >> 2;
- UserInput = (packedFields & 0x02) != 0;
- HasTransparency = (packedFields & 0x01) != 0;
- Delay = BitConverter.ToUInt16(bytes, 2) * 10; // milliseconds
- TransparencyIndex = bytes[4];
- }
+ var packedFields = bytes[1];
+ DisposalMethod = (packedFields & 0x1C) >> 2;
+ UserInput = (packedFields & 0x02) != 0;
+ HasTransparency = (packedFields & 0x01) != 0;
+ Delay = BitConverter.ToUInt16(bytes, 2) * 10; // milliseconds
+ TransparencyIndex = bytes[4];
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHeader.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHeader.cs
index 808b9203..c827a605 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHeader.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHeader.cs
@@ -4,44 +4,43 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal sealed class GifHeader : GifBlock
{
- internal sealed class GifHeader : GifBlock
+ private GifHeader()
{
- private GifHeader()
- {
- }
+ }
- public string? Signature { get; private set; }
+ public string? Signature { get; private set; }
- public string? Version { get; private set; }
+ public string? Version { get; private set; }
- public GifLogicalScreenDescriptor? LogicalScreenDescriptor { get; private set; }
+ public GifLogicalScreenDescriptor? LogicalScreenDescriptor { get; private set; }
- internal override GifBlockKind Kind => GifBlockKind.Other;
+ internal override GifBlockKind Kind => GifBlockKind.Other;
- internal static GifHeader ReadHeader(Stream stream)
+ internal static GifHeader ReadHeader(Stream stream)
+ {
+ var header = new GifHeader();
+ header.Read(stream);
+ return header;
+ }
+
+ private void Read(Stream stream)
+ {
+ Signature = GifHelpers.ReadString(stream, 3);
+ if (Signature != "GIF")
{
- var header = new GifHeader();
- header.Read(stream);
- return header;
+ throw GifHelpers.InvalidSignatureException(Signature);
}
- private void Read(Stream stream)
+ Version = GifHelpers.ReadString(stream, 3);
+ if (Version != "87a" && Version != "89a")
{
- Signature = GifHelpers.ReadString(stream, 3);
- if (Signature != "GIF")
- {
- throw GifHelpers.InvalidSignatureException(Signature);
- }
-
- Version = GifHelpers.ReadString(stream, 3);
- if (Version != "87a" && Version != "89a")
- {
- throw GifHelpers.UnsupportedVersionException(Version);
- }
-
- LogicalScreenDescriptor = GifLogicalScreenDescriptor.ReadLogicalScreenDescriptor(stream);
+ throw GifHelpers.UnsupportedVersionException(Version);
}
+
+ LogicalScreenDescriptor = GifLogicalScreenDescriptor.ReadLogicalScreenDescriptor(stream);
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHelpers.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHelpers.cs
index f7ac0c22..df90379d 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHelpers.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifHelpers.cs
@@ -5,94 +5,93 @@
using System.IO;
using System.Text;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal static class GifHelpers
{
- internal static class GifHelpers
+ public static string ReadString(Stream stream, int length)
{
- public static string ReadString(Stream stream, int length)
- {
- var bytes = new byte[length];
- stream.ReadAll(bytes, 0, length);
- return Encoding.ASCII.GetString(bytes);
- }
+ var bytes = new byte[length];
+ stream.ReadAll(bytes, 0, length);
+ return Encoding.ASCII.GetString(bytes);
+ }
- public static byte[]? ReadDataBlocks(Stream stream, bool discard)
+ public static byte[]? ReadDataBlocks(Stream stream, bool discard)
+ {
+ var ms = discard ? null : new MemoryStream();
+ using (ms)
{
- var ms = discard ? null : new MemoryStream();
- using (ms)
+ int len;
+ while ((len = stream.ReadByte()) > 0)
{
- int len;
- while ((len = stream.ReadByte()) > 0)
- {
- var bytes = new byte[len];
- stream.ReadAll(bytes, 0, len);
- ms?.Write(bytes, 0, len);
- }
-
- if (ms != null)
- {
- return ms.ToArray();
- }
-
- return null;
+ var bytes = new byte[len];
+ stream.ReadAll(bytes, 0, len);
+ ms?.Write(bytes, 0, len);
}
- }
- public static GifColor[] ReadColorTable(Stream stream, int size)
- {
- var length = 3 * size;
- var bytes = new byte[length];
- stream.ReadAll(bytes, 0, length);
- var colorTable = new GifColor[size];
- for (var i = 0; i < size; i++)
+ if (ms != null)
{
- var r = bytes[3 * i];
- var g = bytes[(3 * i) + 1];
- var b = bytes[(3 * i) + 2];
- colorTable[i] = new GifColor(r, g, b);
+ return ms.ToArray();
}
- return colorTable;
+ return null;
}
+ }
- public static bool IsNetscapeExtension(GifApplicationExtension ext) =>
- ext.ApplicationIdentifier == "NETSCAPE"
- && Encoding.ASCII.GetString(ext.AuthenticationCode ?? []) == "2.0";
-
- public static ushort GetRepeatCount(GifApplicationExtension ext)
+ public static GifColor[] ReadColorTable(Stream stream, int size)
+ {
+ var length = 3 * size;
+ var bytes = new byte[length];
+ stream.ReadAll(bytes, 0, length);
+ var colorTable = new GifColor[size];
+ for (var i = 0; i < size; i++)
{
- if (ext.Data?.Length >= 3)
- {
- return BitConverter.ToUInt16(ext.Data, 1);
- }
+ var r = bytes[3 * i];
+ var g = bytes[(3 * i) + 1];
+ var b = bytes[(3 * i) + 2];
+ colorTable[i] = new GifColor(r, g, b);
+ }
+
+ return colorTable;
+ }
- return 1;
+ public static bool IsNetscapeExtension(GifApplicationExtension ext) =>
+ ext.ApplicationIdentifier == "NETSCAPE"
+ && Encoding.ASCII.GetString(ext.AuthenticationCode ?? []) == "2.0";
+
+ public static ushort GetRepeatCount(GifApplicationExtension ext)
+ {
+ if (ext.Data?.Length >= 3)
+ {
+ return BitConverter.ToUInt16(ext.Data, 1);
}
- public static Exception UnexpectedEndOfStreamException() => new GifDecoderException("Unexpected end of stream before trailer was encountered");
+ return 1;
+ }
+
+ public static Exception UnexpectedEndOfStreamException() => new GifDecoderException("Unexpected end of stream before trailer was encountered");
- public static Exception UnknownBlockTypeException(int blockId) => new GifDecoderException("Unknown block type: 0x" + blockId.ToString("x2"));
+ public static Exception UnknownBlockTypeException(int blockId) => new GifDecoderException("Unknown block type: 0x" + blockId.ToString("x2"));
- public static Exception UnknownExtensionTypeException(int extensionLabel) => new GifDecoderException("Unknown extension type: 0x" + extensionLabel.ToString("x2"));
+ public static Exception UnknownExtensionTypeException(int extensionLabel) => new GifDecoderException("Unknown extension type: 0x" + extensionLabel.ToString("x2"));
- public static Exception InvalidBlockSizeException(string blockName, int expectedBlockSize, int actualBlockSize) => new GifDecoderException(
- string.Format(
- "Invalid block size for {0}. Expected {1}, but was {2}",
- blockName,
- expectedBlockSize,
- actualBlockSize));
+ public static Exception InvalidBlockSizeException(string blockName, int expectedBlockSize, int actualBlockSize) => new GifDecoderException(
+ string.Format(
+ "Invalid block size for {0}. Expected {1}, but was {2}",
+ blockName,
+ expectedBlockSize,
+ actualBlockSize));
- public static Exception InvalidSignatureException(string signature) => new GifDecoderException("Invalid file signature: " + signature);
+ public static Exception InvalidSignatureException(string signature) => new GifDecoderException("Invalid file signature: " + signature);
- public static Exception UnsupportedVersionException(string version) => new GifDecoderException("Unsupported version: " + version);
+ public static Exception UnsupportedVersionException(string version) => new GifDecoderException("Unsupported version: " + version);
- public static void ReadAll(this Stream stream, byte[] buffer, int offset, int count)
+ public static void ReadAll(this Stream stream, byte[] buffer, int offset, int count)
+ {
+ var totalRead = 0;
+ while (totalRead < count)
{
- var totalRead = 0;
- while (totalRead < count)
- {
- totalRead += stream.Read(buffer, offset + totalRead, count - totalRead);
- }
+ totalRead += stream.Read(buffer, offset + totalRead, count - totalRead);
}
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageData.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageData.cs
index 48e6b496..f4b96882 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageData.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageData.cs
@@ -4,29 +4,28 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal sealed class GifImageData
{
- internal sealed class GifImageData
+ private GifImageData()
{
- private GifImageData()
- {
- }
+ }
- public byte LzwMinimumCodeSize { get; set; }
+ public byte LzwMinimumCodeSize { get; set; }
- public byte[]? CompressedData { get; set; }
+ public byte[]? CompressedData { get; set; }
- internal static GifImageData ReadImageData(Stream stream, bool metadataOnly)
- {
- var imgData = new GifImageData();
- imgData.Read(stream, metadataOnly);
- return imgData;
- }
+ internal static GifImageData ReadImageData(Stream stream, bool metadataOnly)
+ {
+ var imgData = new GifImageData();
+ imgData.Read(stream, metadataOnly);
+ return imgData;
+ }
- private void Read(Stream stream, bool metadataOnly)
- {
- LzwMinimumCodeSize = (byte)stream.ReadByte();
- CompressedData = GifHelpers.ReadDataBlocks(stream, metadataOnly);
- }
+ private void Read(Stream stream, bool metadataOnly)
+ {
+ LzwMinimumCodeSize = (byte)stream.ReadByte();
+ CompressedData = GifHelpers.ReadDataBlocks(stream, metadataOnly);
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageDescriptor.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageDescriptor.cs
index 550e7bf8..34b8aadf 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageDescriptor.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifImageDescriptor.cs
@@ -4,50 +4,49 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal sealed class GifImageDescriptor
{
- internal sealed class GifImageDescriptor
+ private GifImageDescriptor()
{
- private GifImageDescriptor()
- {
- }
+ }
- public int Left { get; private set; }
+ public int Left { get; private set; }
- public int Top { get; private set; }
+ public int Top { get; private set; }
- public int Width { get; private set; }
+ public int Width { get; private set; }
- public int Height { get; private set; }
+ public int Height { get; private set; }
- public bool HasLocalColorTable { get; private set; }
+ public bool HasLocalColorTable { get; private set; }
- public bool Interlace { get; private set; }
+ public bool Interlace { get; private set; }
- public bool IsLocalColorTableSorted { get; private set; }
+ public bool IsLocalColorTableSorted { get; private set; }
- public int LocalColorTableSize { get; private set; }
+ public int LocalColorTableSize { get; private set; }
- internal static GifImageDescriptor ReadImageDescriptor(Stream stream)
- {
- var descriptor = new GifImageDescriptor();
- descriptor.Read(stream);
- return descriptor;
- }
+ internal static GifImageDescriptor ReadImageDescriptor(Stream stream)
+ {
+ var descriptor = new GifImageDescriptor();
+ descriptor.Read(stream);
+ return descriptor;
+ }
- private void Read(Stream stream)
- {
- var bytes = new byte[9];
- stream.ReadAll(bytes, 0, bytes.Length);
- Left = BitConverter.ToUInt16(bytes, 0);
- Top = BitConverter.ToUInt16(bytes, 2);
- Width = BitConverter.ToUInt16(bytes, 4);
- Height = BitConverter.ToUInt16(bytes, 6);
- var packedFields = bytes[8];
- HasLocalColorTable = (packedFields & 0x80) != 0;
- Interlace = (packedFields & 0x40) != 0;
- IsLocalColorTableSorted = (packedFields & 0x20) != 0;
- LocalColorTableSize = 1 << ((packedFields & 0x07) + 1);
- }
+ private void Read(Stream stream)
+ {
+ var bytes = new byte[9];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ Left = BitConverter.ToUInt16(bytes, 0);
+ Top = BitConverter.ToUInt16(bytes, 2);
+ Width = BitConverter.ToUInt16(bytes, 4);
+ Height = BitConverter.ToUInt16(bytes, 6);
+ var packedFields = bytes[8];
+ HasLocalColorTable = (packedFields & 0x80) != 0;
+ Interlace = (packedFields & 0x40) != 0;
+ IsLocalColorTableSorted = (packedFields & 0x20) != 0;
+ LocalColorTableSize = 1 << ((packedFields & 0x07) + 1);
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifLogicalScreenDescriptor.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifLogicalScreenDescriptor.cs
index 7a54320d..3bcae53a 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifLogicalScreenDescriptor.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifLogicalScreenDescriptor.cs
@@ -4,50 +4,49 @@
using System.IO;
-namespace CrissCross.WPF.UI.Controls.Decoding
-{
- internal class GifLogicalScreenDescriptor
- {
- public int Width { get; private set; }
+namespace CrissCross.WPF.UI.Controls.Decoding;
- public int Height { get; private set; }
+internal class GifLogicalScreenDescriptor
+{
+ public int Width { get; private set; }
- public bool HasGlobalColorTable { get; private set; }
+ public int Height { get; private set; }
- public int ColorResolution { get; private set; }
+ public bool HasGlobalColorTable { get; private set; }
- public bool IsGlobalColorTableSorted { get; private set; }
+ public int ColorResolution { get; private set; }
- public int GlobalColorTableSize { get; private set; }
+ public bool IsGlobalColorTableSorted { get; private set; }
- public int BackgroundColorIndex { get; private set; }
+ public int GlobalColorTableSize { get; private set; }
- public double PixelAspectRatio { get; private set; }
+ public int BackgroundColorIndex { get; private set; }
- internal static GifLogicalScreenDescriptor ReadLogicalScreenDescriptor(Stream stream)
- {
- var descriptor = new GifLogicalScreenDescriptor();
- descriptor.Read(stream);
- return descriptor;
- }
+ public double PixelAspectRatio { get; private set; }
- private void Read(Stream stream)
- {
- var bytes = new byte[7];
- stream.ReadAll(bytes, 0, bytes.Length);
+ internal static GifLogicalScreenDescriptor ReadLogicalScreenDescriptor(Stream stream)
+ {
+ var descriptor = new GifLogicalScreenDescriptor();
+ descriptor.Read(stream);
+ return descriptor;
+ }
- Width = BitConverter.ToUInt16(bytes, 0);
- Height = BitConverter.ToUInt16(bytes, 2);
- var packedFields = bytes[4];
- HasGlobalColorTable = (packedFields & 0x80) != 0;
- ColorResolution = ((packedFields & 0x70) >> 4) + 1;
- IsGlobalColorTableSorted = (packedFields & 0x08) != 0;
- GlobalColorTableSize = 1 << ((packedFields & 0x07) + 1);
- BackgroundColorIndex = bytes[5];
- PixelAspectRatio =
- bytes[5] == 0
- ? 0.0
- : (15 + bytes[5]) / 64.0;
- }
+ private void Read(Stream stream)
+ {
+ var bytes = new byte[7];
+ stream.ReadAll(bytes, 0, bytes.Length);
+
+ Width = BitConverter.ToUInt16(bytes, 0);
+ Height = BitConverter.ToUInt16(bytes, 2);
+ var packedFields = bytes[4];
+ HasGlobalColorTable = (packedFields & 0x80) != 0;
+ ColorResolution = ((packedFields & 0x70) >> 4) + 1;
+ IsGlobalColorTableSorted = (packedFields & 0x08) != 0;
+ GlobalColorTableSize = 1 << ((packedFields & 0x07) + 1);
+ BackgroundColorIndex = bytes[5];
+ PixelAspectRatio =
+ bytes[5] == 0
+ ? 0.0
+ : (15 + bytes[5]) / 64.0;
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifPlainTextExtension.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifPlainTextExtension.cs
index a9475634..3ee7a0e2 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifPlainTextExtension.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifPlainTextExtension.cs
@@ -5,72 +5,71 @@
using System.IO;
using System.Text;
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+// label 0x01
+internal sealed class GifPlainTextExtension : GifExtension
{
- // label 0x01
- internal sealed class GifPlainTextExtension : GifExtension
+ internal const int ExtensionLabel = 0x01;
+
+ private GifPlainTextExtension()
{
- internal const int ExtensionLabel = 0x01;
+ }
- private GifPlainTextExtension()
- {
- }
+ public int BlockSize { get; private set; }
- public int BlockSize { get; private set; }
+ public int Left { get; private set; }
- public int Left { get; private set; }
+ public int Top { get; private set; }
- public int Top { get; private set; }
+ public int Width { get; private set; }
- public int Width { get; private set; }
+ public int Height { get; private set; }
- public int Height { get; private set; }
+ public int CellWidth { get; private set; }
- public int CellWidth { get; private set; }
+ public int CellHeight { get; private set; }
- public int CellHeight { get; private set; }
+ public int ForegroundColorIndex { get; private set; }
- public int ForegroundColorIndex { get; private set; }
+ public int BackgroundColorIndex { get; private set; }
- public int BackgroundColorIndex { get; private set; }
+ public string? Text { get; private set; }
- public string? Text { get; private set; }
+ public IList? Extensions { get; private set; }
- public IList? Extensions { get; private set; }
+ internal override GifBlockKind Kind => GifBlockKind.GraphicRendering;
- internal override GifBlockKind Kind => GifBlockKind.GraphicRendering;
+ internal static GifPlainTextExtension ReadPlainText(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ {
+ var plainText = new GifPlainTextExtension();
+ plainText.Read(stream, controlExtensions, metadataOnly);
+ return plainText;
+ }
- internal static GifPlainTextExtension ReadPlainText(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
- {
- var plainText = new GifPlainTextExtension();
- plainText.Read(stream, controlExtensions, metadataOnly);
- return plainText;
- }
+ private void Read(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the label (0x01) has already been read
+ var bytes = new byte[13];
+ stream.ReadAll(bytes, 0, bytes.Length);
- private void Read(Stream stream, IEnumerable controlExtensions, bool metadataOnly)
+ BlockSize = bytes[0];
+ if (BlockSize != 12)
{
- // Note: at this point, the label (0x01) has already been read
- var bytes = new byte[13];
- stream.ReadAll(bytes, 0, bytes.Length);
-
- BlockSize = bytes[0];
- if (BlockSize != 12)
- {
- throw GifHelpers.InvalidBlockSizeException("Plain Text Extension", 12, BlockSize);
- }
-
- Left = BitConverter.ToUInt16(bytes, 1);
- Top = BitConverter.ToUInt16(bytes, 3);
- Width = BitConverter.ToUInt16(bytes, 5);
- Height = BitConverter.ToUInt16(bytes, 7);
- CellWidth = bytes[9];
- CellHeight = bytes[10];
- ForegroundColorIndex = bytes[11];
- BackgroundColorIndex = bytes[12];
-
- var dataBytes = GifHelpers.ReadDataBlocks(stream, metadataOnly);
- Text = Encoding.ASCII.GetString(dataBytes ?? []);
- Extensions = controlExtensions.ToList().AsReadOnly();
+ throw GifHelpers.InvalidBlockSizeException("Plain Text Extension", 12, BlockSize);
}
+
+ Left = BitConverter.ToUInt16(bytes, 1);
+ Top = BitConverter.ToUInt16(bytes, 3);
+ Width = BitConverter.ToUInt16(bytes, 5);
+ Height = BitConverter.ToUInt16(bytes, 7);
+ CellWidth = bytes[9];
+ CellHeight = bytes[10];
+ ForegroundColorIndex = bytes[11];
+ BackgroundColorIndex = bytes[12];
+
+ var dataBytes = GifHelpers.ReadDataBlocks(stream, metadataOnly);
+ Text = Encoding.ASCII.GetString(dataBytes ?? []);
+ Extensions = controlExtensions.ToList().AsReadOnly();
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifTrailer.cs b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifTrailer.cs
index 926fba3e..1b48d882 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifTrailer.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/Decoding/GifTrailer.cs
@@ -2,18 +2,17 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls.Decoding
+namespace CrissCross.WPF.UI.Controls.Decoding;
+
+internal sealed class GifTrailer : GifBlock
{
- internal sealed class GifTrailer : GifBlock
- {
- internal const int TrailerByte = 0x3B;
+ internal const int TrailerByte = 0x3B;
- private GifTrailer()
- {
- }
+ private GifTrailer()
+ {
+ }
- internal override GifBlockKind Kind => GifBlockKind.Other;
+ internal override GifBlockKind Kind => GifBlockKind.Other;
- internal static GifTrailer ReadTrailer() => new();
- }
+ internal static GifTrailer ReadTrailer() => new();
}
diff --git a/src/CrissCross.WPF.UI/Controls/GifImage/ImageAnimationController.cs b/src/CrissCross.WPF.UI/Controls/GifImage/ImageAnimationController.cs
index 2875ea5a..f7bdfc4d 100644
--- a/src/CrissCross.WPF.UI/Controls/GifImage/ImageAnimationController.cs
+++ b/src/CrissCross.WPF.UI/Controls/GifImage/ImageAnimationController.cs
@@ -4,183 +4,182 @@
using System.Windows.Media.Animation;
-namespace CrissCross.WPF.UI.Controls
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Provides a way to pause, resume or seek a GIF animation.
+///
+internal class ImageAnimationController : IDisposable
{
- ///
- /// Provides a way to pause, resume or seek a GIF animation.
- ///
- internal class ImageAnimationController : IDisposable
- {
- private static readonly DependencyPropertyDescriptor _sourceDescriptor;
+ private static readonly DependencyPropertyDescriptor _sourceDescriptor;
- private readonly Image _image;
- private readonly ObjectAnimationUsingKeyFrames _animation;
- private readonly AnimationClock _clock;
- private readonly ClockController _clockController;
+ private readonly Image _image;
+ private readonly ObjectAnimationUsingKeyFrames _animation;
+ private readonly AnimationClock _clock;
+ private readonly ClockController _clockController;
- private bool _isSuspended;
+ private bool _isSuspended;
- static ImageAnimationController() => _sourceDescriptor = DependencyPropertyDescriptor.FromProperty(Image.SourceProperty, typeof(Image));
+ static ImageAnimationController() => _sourceDescriptor = DependencyPropertyDescriptor.FromProperty(Image.SourceProperty, typeof(Image));
- internal ImageAnimationController(Image image, ObjectAnimationUsingKeyFrames animation, bool autoStart)
- {
- _image = image;
- _animation = animation;
- _animation.Completed += AnimationCompleted;
- _clock = _animation.CreateClock();
- _clockController = _clock.Controller;
- _sourceDescriptor.AddValueChanged(image, ImageSourceChanged);
-
- // ReSharper disable once PossibleNullReferenceException
- _clockController.Pause();
+ internal ImageAnimationController(Image image, ObjectAnimationUsingKeyFrames animation, bool autoStart)
+ {
+ _image = image;
+ _animation = animation;
+ _animation.Completed += AnimationCompleted;
+ _clock = _animation.CreateClock();
+ _clockController = _clock.Controller;
+ _sourceDescriptor.AddValueChanged(image, ImageSourceChanged);
- _image.ApplyAnimationClock(Image.SourceProperty, _clock);
+ // ReSharper disable once PossibleNullReferenceException
+ _clockController.Pause();
- IsPaused = !autoStart;
- if (autoStart)
- {
- _clockController.Resume();
- }
- }
+ _image.ApplyAnimationClock(Image.SourceProperty, _clock);
- ///
- /// Finalizes an instance of the class.
- ///
- ~ImageAnimationController()
+ IsPaused = !autoStart;
+ if (autoStart)
{
- Dispose(false);
+ _clockController.Resume();
}
+ }
+
+ ///
+ /// Finalizes an instance of the class.
+ ///
+ ~ImageAnimationController()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Raised when the current frame changes.
+ ///
+ public event EventHandler? CurrentFrameChanged;
- ///
- /// Raised when the current frame changes.
- ///
- public event EventHandler? CurrentFrameChanged;
-
- ///
- /// Gets the number of frames in the image.
- ///
- public int FrameCount => _animation.KeyFrames.Count;
-
- ///
- /// Gets the duration of the animation.
- ///
- public TimeSpan Duration => _animation.Duration.HasTimeSpan
- ? _animation.Duration.TimeSpan
- : TimeSpan.Zero;
-
- ///
- /// Gets a value indicating whether returns a value that indicates whether the animation is paused.
- ///
- public bool IsPaused { get; private set; }
-
- ///
- /// Gets a value indicating whether returns a value that indicates whether the animation is complete.
- ///
- public bool IsComplete => _clock.CurrentState == ClockState.Filling;
-
- ///
- /// Gets the current frame index.
- ///
- public int CurrentFrame
+ ///
+ /// Gets the number of frames in the image.
+ ///
+ public int FrameCount => _animation.KeyFrames.Count;
+
+ ///
+ /// Gets the duration of the animation.
+ ///
+ public TimeSpan Duration => _animation.Duration.HasTimeSpan
+ ? _animation.Duration.TimeSpan
+ : TimeSpan.Zero;
+
+ ///
+ /// Gets a value indicating whether returns a value that indicates whether the animation is paused.
+ ///
+ public bool IsPaused { get; private set; }
+
+ ///
+ /// Gets a value indicating whether returns a value that indicates whether the animation is complete.
+ ///
+ public bool IsComplete => _clock.CurrentState == ClockState.Filling;
+
+ ///
+ /// Gets the current frame index.
+ ///
+ public int CurrentFrame
+ {
+ get
{
- get
+ var time = _clock.CurrentTime;
+ var frameAndIndex =
+ _animation.KeyFrames
+ .Cast()
+ .Select((f, i) => new { Time = f.KeyTime.TimeSpan, Index = i })
+ .FirstOrDefault(fi => fi.Time >= time);
+ if (frameAndIndex != null)
{
- var time = _clock.CurrentTime;
- var frameAndIndex =
- _animation.KeyFrames
- .Cast()
- .Select((f, i) => new { Time = f.KeyTime.TimeSpan, Index = i })
- .FirstOrDefault(fi => fi.Time >= time);
- if (frameAndIndex != null)
- {
- return frameAndIndex.Index;
- }
-
- return -1;
+ return frameAndIndex.Index;
}
+
+ return -1;
}
+ }
+
+ ///
+ /// Seeks the animation to the specified frame index.
+ ///
+ /// The index of the frame to seek to.
+ public void GotoFrame(int index)
+ {
+ var frame = _animation.KeyFrames[index];
+ _clockController.Seek(frame.KeyTime.TimeSpan, TimeSeekOrigin.BeginTime);
+ }
+
+ ///
+ /// Pauses the animation.
+ ///
+ public void Pause()
+ {
+ IsPaused = true;
+ _clockController.Pause();
+ }
- ///
- /// Seeks the animation to the specified frame index.
- ///
- /// The index of the frame to seek to.
- public void GotoFrame(int index)
+ ///
+ /// Starts or resumes the animation. If the animation is complete, it restarts from the beginning.
+ ///
+ public void Play()
+ {
+ IsPaused = false;
+ if (!_isSuspended)
{
- var frame = _animation.KeyFrames[index];
- _clockController.Seek(frame.KeyTime.TimeSpan, TimeSeekOrigin.BeginTime);
+ _clockController.Resume();
}
+ }
+
+ ///
+ /// Disposes the current object.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
- ///
- /// Pauses the animation.
- ///
- public void Pause()
+ internal void SetSuspended(bool isSuspended)
+ {
+ if (isSuspended == _isSuspended)
{
- IsPaused = true;
- _clockController.Pause();
+ return;
}
- ///
- /// Starts or resumes the animation. If the animation is complete, it restarts from the beginning.
- ///
- public void Play()
+ var wasSuspended = _isSuspended;
+ _isSuspended = isSuspended;
+ if (wasSuspended)
{
- IsPaused = false;
- if (!_isSuspended)
+ if (!IsPaused)
{
_clockController.Resume();
}
}
-
- ///
- /// Disposes the current object.
- ///
- public void Dispose()
+ else
{
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- internal void SetSuspended(bool isSuspended)
- {
- if (isSuspended == _isSuspended)
- {
- return;
- }
-
- var wasSuspended = _isSuspended;
- _isSuspended = isSuspended;
- if (wasSuspended)
- {
- if (!IsPaused)
- {
- _clockController.Resume();
- }
- }
- else
- {
- _clockController.Pause();
- }
+ _clockController.Pause();
}
+ }
- ///
- /// Disposes the current object.
- ///
- /// true to dispose both managed an unmanaged resources, false to dispose only managed resources.
- protected virtual void Dispose(bool disposing)
+ ///
+ /// Disposes the current object.
+ ///
+ /// true to dispose both managed an unmanaged resources, false to dispose only managed resources.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
{
- if (disposing)
- {
- _image.BeginAnimation(Image.SourceProperty, null);
- _animation.Completed -= AnimationCompleted;
- _sourceDescriptor.RemoveValueChanged(_image, ImageSourceChanged);
- _image.Source = null!;
- }
+ _image.BeginAnimation(Image.SourceProperty, null);
+ _animation.Completed -= AnimationCompleted;
+ _sourceDescriptor.RemoveValueChanged(_image, ImageSourceChanged);
+ _image.Source = null!;
}
+ }
- private void AnimationCompleted(object? sender, EventArgs e) => _image.RaiseEvent(new System.Windows.RoutedEventArgs(ImageBehavior.AnimationCompletedEvent, _image));
+ private void AnimationCompleted(object? sender, EventArgs e) => _image.RaiseEvent(new System.Windows.RoutedEventArgs(ImageBehavior.AnimationCompletedEvent, _image));
- private void ImageSourceChanged(object? sender, EventArgs e) => OnCurrentFrameChanged();
+ private void ImageSourceChanged(object? sender, EventArgs e) => OnCurrentFrameChanged();
- private void OnCurrentFrameChanged() => CurrentFrameChanged?.Invoke(this, EventArgs.Empty);
- }
+ private void OnCurrentFrameChanged() => CurrentFrameChanged?.Invoke(this, EventArgs.Empty);
}
diff --git a/src/CrissCross.WPF.UI/Controls/Grid/Grid.cs b/src/CrissCross.WPF.UI/Controls/Grid/Grid.cs
index 4fce2360..75224ba5 100644
--- a/src/CrissCross.WPF.UI/Controls/Grid/Grid.cs
+++ b/src/CrissCross.WPF.UI/Controls/Grid/Grid.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class Grid : System.Windows.Controls.Grid;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class Grid : System.Windows.Controls.Grid;
diff --git a/src/CrissCross.WPF.UI/Controls/GroupBox/GroupBox.cs b/src/CrissCross.WPF.UI/Controls/GroupBox/GroupBox.cs
index cd39a23e..a58396db 100644
--- a/src/CrissCross.WPF.UI/Controls/GroupBox/GroupBox.cs
+++ b/src/CrissCross.WPF.UI/Controls/GroupBox/GroupBox.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class GroupBox : System.Windows.Controls.GroupBox;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class GroupBox : System.Windows.Controls.GroupBox;
diff --git a/src/CrissCross.WPF.UI/Controls/Label/Label.cs b/src/CrissCross.WPF.UI/Controls/Label/Label.cs
index ae760ad0..795d80c1 100644
--- a/src/CrissCross.WPF.UI/Controls/Label/Label.cs
+++ b/src/CrissCross.WPF.UI/Controls/Label/Label.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class Label : System.Windows.Controls.Label;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class Label : System.Windows.Controls.Label;
diff --git a/src/CrissCross.WPF.UI/Controls/Page/Page.cs b/src/CrissCross.WPF.UI/Controls/Page/Page.cs
index a8f4a6a0..30dd1254 100644
--- a/src/CrissCross.WPF.UI/Controls/Page/Page.cs
+++ b/src/CrissCross.WPF.UI/Controls/Page/Page.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class Page : System.Windows.Controls.Page;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class Page : System.Windows.Controls.Page;
diff --git a/src/CrissCross.WPF.UI/Controls/StackPanel/StackPanel.cs b/src/CrissCross.WPF.UI/Controls/StackPanel/StackPanel.cs
index 84d2943d..21390e62 100644
--- a/src/CrissCross.WPF.UI/Controls/StackPanel/StackPanel.cs
+++ b/src/CrissCross.WPF.UI/Controls/StackPanel/StackPanel.cs
@@ -2,11 +2,10 @@
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-namespace CrissCross.WPF.UI.Controls
-{
- ///
- /// Extended .
- ///
- ///
- public class StackPanel : System.Windows.Controls.StackPanel;
-}
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// Extended .
+///
+///
+public class StackPanel : System.Windows.Controls.StackPanel;
diff --git a/src/CrissCross.WPF/CrissCross.WPF.csproj b/src/CrissCross.WPF/CrissCross.WPF.csproj
index 253399b3..6b6e3b1a 100644
--- a/src/CrissCross.WPF/CrissCross.WPF.csproj
+++ b/src/CrissCross.WPF/CrissCross.WPF.csproj
@@ -1,21 +1,26 @@
-
- $(CrissCrossWinTargetFrameworks)
- true
- enable
- True
- True
- true
-
+
+ $(CrissCrossWinTargetFrameworks)
+ true
+ enable
+ True
+ True
+ true
+
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
diff --git a/src/CrissCross.XamForms/CrissCross.XamForms.csproj b/src/CrissCross.XamForms/CrissCross.XamForms.csproj
index 3ef02090..74678040 100644
--- a/src/CrissCross.XamForms/CrissCross.XamForms.csproj
+++ b/src/CrissCross.XamForms/CrissCross.XamForms.csproj
@@ -7,9 +7,14 @@
+
+
+
+
+