using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; using Avalonia.Platform; using Avalonia.Threading; using InABox.Core; using Microsoft.Maui.Graphics.Platform; using System.Timers; using System.Windows.Input; using Timer = System.Timers.Timer; namespace InABox.Avalonia.Platform.Barcodes; public interface ICameraViewControl : ILoggable { IPlatformHandle CreateControl(CameraView view, IPlatformHandle parent); } public class DefaultCameraViewControl : ICameraViewControl { public Logger? Logger { get; set; } public IPlatformHandle CreateControl(CameraView view, IPlatformHandle parent) { return null; } } public partial class CameraView : UserControl { public static readonly StyledProperty OnDetectionFinishedCommandProperty = AvaloniaProperty.Register(nameof(OnDetectionFinishedCommand)); public ICommand OnDetectionFinishedCommand { get => GetValue(OnDetectionFinishedCommandProperty); set => SetValue(OnDetectionFinishedCommandProperty, value); } public static readonly StyledProperty OnImageCapturedCommandProperty = AvaloniaProperty.Register(nameof(OnImageCapturedCommand)); public ICommand OnImageCapturedCommand { get => GetValue(OnImageCapturedCommandProperty); set => SetValue(OnImageCapturedCommandProperty, value); } public static readonly StyledProperty VibrationOnDetectedProperty = AvaloniaProperty.Register(nameof(VibrationOnDetected), false); public bool VibrationOnDetected { get => GetValue(VibrationOnDetectedProperty); set => SetValue(VibrationOnDetectedProperty, value); } public static readonly StyledProperty CameraEnabledProperty = AvaloniaProperty.Register(nameof(CameraEnabled), false); public bool CameraEnabled { get => GetValue(CameraEnabledProperty); set => SetValue(CameraEnabledProperty, value); } public static readonly StyledProperty PauseScanningProperty = AvaloniaProperty.Register(nameof(PauseScanning), false); public bool PauseScanning { get => GetValue(PauseScanningProperty); set => SetValue(PauseScanningProperty, value); } public static readonly StyledProperty ForceInvertedProperty = AvaloniaProperty.Register(nameof(ForceInverted), false); public bool ForceInverted { get => GetValue(ForceInvertedProperty); set => SetValue(ForceInvertedProperty, value); } public static readonly StyledProperty TorchOnProperty = AvaloniaProperty.Register(nameof(TorchOn), false); public bool TorchOn { get => GetValue(TorchOnProperty); set => SetValue(TorchOnProperty, value); } public static readonly StyledProperty TapToFocusEnabledProperty = AvaloniaProperty.Register(nameof(TapToFocusEnabled), false); public bool TapToFocusEnabled { get => GetValue(TapToFocusEnabledProperty); set => SetValue(TapToFocusEnabledProperty, value); } public static readonly StyledProperty CameraFacingProperty = AvaloniaProperty.Register(nameof(CameraFacing), CameraFacing.Back); public CameraFacing CameraFacing { get => GetValue(CameraFacingProperty); set => SetValue(CameraFacingProperty, value); } public static readonly StyledProperty CaptureQualityProperty = AvaloniaProperty.Register(nameof(CaptureQuality), CaptureQuality.Medium); public CaptureQuality CaptureQuality { get => GetValue(CaptureQualityProperty); set => SetValue(CaptureQualityProperty, value); } public static readonly StyledProperty BarcodeSymbologiesProperty = AvaloniaProperty.Register(nameof(BarcodeSymbologies), BarcodeFormats.All); public BarcodeFormats BarcodeSymbologies { get => GetValue(BarcodeSymbologiesProperty); set => SetValue(BarcodeSymbologiesProperty, value); } public static readonly StyledProperty AimModeProperty = AvaloniaProperty.Register(nameof(AimMode), false); public bool AimMode { get => GetValue(AimModeProperty); set => SetValue(AimModeProperty, value); } public static readonly StyledProperty ViewfinderModeProperty = AvaloniaProperty.Register(nameof(ViewfinderMode), false); public bool ViewfinderMode { get => GetValue(ViewfinderModeProperty); set => SetValue(ViewfinderModeProperty, value); } public static readonly StyledProperty CaptureNextFrameProperty = AvaloniaProperty.Register(nameof(CaptureNextFrame), false); public bool CaptureNextFrame { get => GetValue(CaptureNextFrameProperty); set => SetValue(CaptureNextFrameProperty, value); } public static readonly StyledProperty ForceFrameCaptureProperty = AvaloniaProperty.Register(nameof(ForceFrameCapture), false); public bool ForceFrameCapture { get => GetValue(ForceFrameCaptureProperty); set => SetValue(ForceFrameCaptureProperty, value); } public static readonly StyledProperty RequestZoomFactorProperty = AvaloniaProperty.Register(nameof(RequestZoomFactor), -1f); public float RequestZoomFactor { get => GetValue(RequestZoomFactorProperty); set => SetValue(RequestZoomFactorProperty, value); } public static readonly StyledProperty CurrentZoomFactorProperty = AvaloniaProperty.Register(nameof(CurrentZoomFactor), -1f); public float CurrentZoomFactor { get => GetValue(CurrentZoomFactorProperty); set => SetValue(CurrentZoomFactorProperty, value); } public static readonly StyledProperty MinZoomFactorProperty = AvaloniaProperty.Register(nameof(MinZoomFactor), -1f); public float MinZoomFactor { get => GetValue(MinZoomFactorProperty); set => SetValue(MinZoomFactorProperty, value); } public static readonly StyledProperty MaxZoomFactorProperty = AvaloniaProperty.Register(nameof(MaxZoomFactor), -1f); public float MaxZoomFactor { get => GetValue(MaxZoomFactorProperty); set => SetValue(MaxZoomFactorProperty, value); } public static readonly StyledProperty DeviceSwitchZoomFactorProperty = AvaloniaProperty.Register(nameof(DeviceSwitchZoomFactor), []); public float[] DeviceSwitchZoomFactor { get => GetValue(DeviceSwitchZoomFactorProperty); set => SetValue(DeviceSwitchZoomFactorProperty, value); } public CameraView() { InitializeComponent(); LayoutUpdated += CameraView_LayoutUpdated; } private void CameraView_LayoutUpdated(object? sender, EventArgs e) { Host.TryUpdateNativeControlPosition(); } public void DetectionFinished(HashSet barCodeResults) { // if (_poolingTimer.Enabled) // { // _poolingTimer.Stop(); // } TriggerOnDetectionFinished(barCodeResults); } private void TriggerOnDetectionFinished(HashSet barCodeResults) { Dispatcher.UIThread.InvokeAsync(() => { if(OnDetectionFinishedCommand?.CanExecute(barCodeResults) ?? false) { OnDetectionFinishedCommand?.Execute(barCodeResults); } }); } public void TriggerOnImageCaptured(PlatformImage image) { Dispatcher.UIThread.InvokeAsync(() => { CaptureNextFrame = false; if (PauseScanning) return; // OnImageCaptured?.Invoke(this, new OnImageCapturedEventArg { Image = image }); if (OnImageCapturedCommand?.CanExecute(image) ?? false) OnImageCapturedCommand?.Execute(image); }); } } internal class CameraViewControlHost : NativeControlHost { protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent) { if(Parent is CameraView cameraView) { return PlatformTools.CameraViewControl.CreateControl(cameraView, parent) ?? base.CreateNativeControlCore(parent); } else { return base.CreateNativeControlCore(parent); } } }