commit 6971b05226cdce4522b472bcac39eb6c224e3324 Author: Ano-sys Date: Wed Feb 19 01:05:22 2025 +0100 groundlaying functionality diff --git a/App.axaml b/App.axaml new file mode 100644 index 0000000..359ac69 --- /dev/null +++ b/App.axaml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/App.axaml.cs b/App.axaml.cs new file mode 100644 index 0000000..6bf7a0b --- /dev/null +++ b/App.axaml.cs @@ -0,0 +1,33 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Data.Core; +using Avalonia.Data.Core.Plugins; +using Avalonia.Markup.Xaml; +using SimpleDraw.ViewModels; +using SimpleDraw.Views; + +namespace SimpleDraw; + +public partial class App : Application +{ + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + // Line below is needed to remove Avalonia data validation. + // Without this line you will get duplicate validations from both Avalonia and CT + BindingPlugins.DataValidators.RemoveAt(0); + desktop.MainWindow = new MainWindow + { + DataContext = new MainWindowViewModel(), + }; + } + + base.OnFrameworkInitializationCompleted(); + } +} \ No newline at end of file diff --git a/Assets/avalonia-logo.ico b/Assets/avalonia-logo.ico new file mode 100644 index 0000000..da8d49f Binary files /dev/null and b/Assets/avalonia-logo.ico differ diff --git a/Models/ColorPickerButton.cs b/Models/ColorPickerButton.cs new file mode 100644 index 0000000..d9fc5ff --- /dev/null +++ b/Models/ColorPickerButton.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.ComponentModel; +using Avalonia.Media; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; + +namespace SimpleDraw.Models; + +public class ColorPickerButton : ObservableObject +{ + private SolidColorBrush _color; + public RelayCommand SelectColorCommand { get; set; } + + public SolidColorBrush Color + { + get => _color; + set => _color = value; + } + + // public event PropertyChangedEventHandler? PropertyChanged; +} \ No newline at end of file diff --git a/Models/DrawingPoints.cs b/Models/DrawingPoints.cs new file mode 100644 index 0000000..a8479e5 --- /dev/null +++ b/Models/DrawingPoints.cs @@ -0,0 +1,47 @@ +using System.Collections.ObjectModel; +using Avalonia; +using Avalonia.Media; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace SimpleDraw.Models; + +public class DrawingPoints : ObservableObject +{ + private ObservableCollection _drawingPoints = new ObservableCollection(); + // private ObservableCollection> _drawingPointsList = new ObservableCollection>(); + + private Brush _brush; + private double _brushThickness; + + public Brush Brush + { + get => _brush; + set => SetProperty(ref _brush, value); + } + + public double BrushThickness + { + get => _brushThickness; + set => SetProperty(ref _brushThickness, value); + } + + public ObservableCollection CurrentDrawingPoints + { + get => _drawingPoints; + set => SetProperty(ref _drawingPoints, value); + } + + public DrawingPoints(Brush brush, double brushThickness) + { + Brush = brush; + BrushThickness = brushThickness; + } + + /* + public ObservableCollection> DrawingPointsList + { + get => _drawingPointsList; + set => SetProperty(ref _drawingPointsList, value); + } + */ +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..a7ce4fa --- /dev/null +++ b/Program.cs @@ -0,0 +1,21 @@ +using Avalonia; +using System; + +namespace SimpleDraw; + +sealed class Program +{ + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace(); +} diff --git a/SimpleDraw.csproj b/SimpleDraw.csproj new file mode 100644 index 0000000..1aa5d45 --- /dev/null +++ b/SimpleDraw.csproj @@ -0,0 +1,25 @@ + + + WinExe + net9.0 + enable + true + app.manifest + true + + + + + + + + + + + + + + + + + diff --git a/SimpleDraw.sln b/SimpleDraw.sln new file mode 100644 index 0000000..99580a6 --- /dev/null +++ b/SimpleDraw.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleDraw", "SimpleDraw.csproj", "{3BB82696-53EB-4433-BB71-E40A2AC7395D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3BB82696-53EB-4433-BB71-E40A2AC7395D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BB82696-53EB-4433-BB71-E40A2AC7395D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BB82696-53EB-4433-BB71-E40A2AC7395D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BB82696-53EB-4433-BB71-E40A2AC7395D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/ViewLocator.cs b/ViewLocator.cs new file mode 100644 index 0000000..8883119 --- /dev/null +++ b/ViewLocator.cs @@ -0,0 +1,33 @@ +using System; +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using SimpleDraw.ViewModels; + +namespace SimpleDraw; + +public class ViewLocator : IDataTemplate +{ + + public Control? Build(object? data) + { + if (data is null) + return null; + + var name = data.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); + var type = Type.GetType(name); + + if (type != null) + { + var control = (Control)Activator.CreateInstance(type)!; + control.DataContext = data; + return control; + } + + return new TextBlock { Text = "Not Found: " + name }; + } + + public bool Match(object? data) + { + return data is ViewModelBase; + } +} diff --git a/ViewModels/MainWindowViewModel.cs b/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000..5b6a992 --- /dev/null +++ b/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,107 @@ +using Avalonia; +using Avalonia.Input; +using Avalonia.Media; +using CommunityToolkit.Mvvm.Input; +using SimpleDraw.Models; + +namespace SimpleDraw.ViewModels; + +public class MainWindowViewModel : ViewModelBase +{ +#pragma warning disable CA1822 // Mark members as static + public MainWindowViewModel() + { + ColorPalette = + [ + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 255, g: 255, b: 255, a: 255)), + }, + + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 0, g: 0, b: 0, a: 255)), + }, + + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 128, g: 128, b: 128, a: 255)), + }, + + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 255, g: 0, b: 0, a: 255)), + }, + + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 0, g: 255, b: 0, a: 255)), + }, + + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 0, g: 0, b: 255, a: 255)), + }, + + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 128, g: 0, b: 128, a: 255)), + }, + + new ColorPickerButton + { + Color = new SolidColorBrush(new Color(r: 128, g: 128, b: 0, a: 255)), + } + + ]; + + foreach (ColorPickerButton colorPickerButton in ColorPalette) + { + var currentColor = colorPickerButton.Color; + colorPickerButton.SelectColorCommand = new RelayCommand(() => ChangeSelectedColor(currentColor)); + } + + Brush = new SolidColorBrush(Colors.Black); + CanvasPointerPressedCommand = new RelayCommand(OnCanvasPointerPressed); + CanvasPointerMovedCommand = new RelayCommand(OnCanvasPointerMoved); + CanvasPointerReleasedCommand = new RelayCommand(OnCanvasPointerReleased); + } + +#pragma warning restore CA1822 // Mark members as static + + private void ChangeSelectedColor(SolidColorBrush color) + { + Brush = color; + } + + private void OnCanvasPointerPressed(PointerPressedEventArgs? e) + { + if (e == null) return; + + IsDrawing = true; + DrawingPoints.Add(new DrawingPoints(Brush, BrushThickness)); + DrawingPoint = DrawingPoints[^1]; + // DrawingPoints.DrawingPointsList.Add(DrawingPoints.CurrentDrawingPoints); + + if (e.Source is Visual visual) + { + var point = e.GetPosition(visual); + DrawingPoint.CurrentDrawingPoints.Add(point); + } + } + + private void OnCanvasPointerMoved(PointerEventArgs? e) + { + if (e == null || !IsDrawing) return; + if (e.Source is Visual visual) + { + var point = e.GetPosition(visual); + DrawingPoint?.CurrentDrawingPoints.Add(point); + } + } + + private void OnCanvasPointerReleased(PointerReleasedEventArgs? e) + { + IsDrawing = false; + } +} diff --git a/ViewModels/ViewModelBase.cs b/ViewModels/ViewModelBase.cs new file mode 100644 index 0000000..0ac1f1d --- /dev/null +++ b/ViewModels/ViewModelBase.cs @@ -0,0 +1,35 @@ +using System.Collections.ObjectModel; +using Avalonia.Input; +using Avalonia.Media; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using SimpleDraw.Models; + +namespace SimpleDraw.ViewModels; + +public class ViewModelBase : ObservableObject +{ + public ObservableCollection? ColorPalette { get; set; } + public IRelayCommand? CanvasPointerPressedCommand { get; set; } + public IRelayCommand? CanvasPointerMovedCommand { get; set; } + public IRelayCommand? CanvasPointerReleasedCommand { get; set; } + public ObservableCollection DrawingPoints { get; set; } = new(); + public DrawingPoints? DrawingPoint { get; set; } + + protected bool IsDrawing { get; set; } + + private Brush _brush = new SolidColorBrush(new Color(a: 255, r: 0, g: 0, b: 0)); + private double _brushThickness = 2.0; + + protected Brush Brush + { + get => _brush; + set => SetProperty(ref _brush, value); + } + + public double BrushThickness + { + get => _brushThickness; + set => SetProperty(ref _brushThickness, value); + } +} diff --git a/Views/MainWindow.axaml b/Views/MainWindow.axaml new file mode 100644 index 0000000..11855f6 --- /dev/null +++ b/Views/MainWindow.axaml @@ -0,0 +1,111 @@ + + + + + + + + + + + File + + + Edit + + + + + + + + + + + + + + + + + + + + + + + + + + + +