Przeglądaj źródła

Navigator window done

Equbuxu 3 lat temu
rodzic
commit
39beef6058

+ 28 - 0
src/PixiEditor/Views/UserControls/FixedViewport.xaml

@@ -0,0 +1,28 @@
+<UserControl x:Class="PixiEditor.Views.UserControls.FixedViewport"
+             x:ClassModifier="internal"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
+             xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             mc:Ignorable="d"
+             x:Name="uc"
+             HorizontalAlignment="Center"
+             VerticalAlignment="Center"
+             d:DesignHeight="450" d:DesignWidth="800">
+    <Image
+        x:Name="mainImage"
+        Focusable="True"
+        Source="{Binding TargetBitmap, ElementName=uc}"
+        HorizontalAlignment="Stretch"
+        Stretch="Uniform"
+        SizeChanged="OnImageSizeChanged">
+        <RenderOptions.BitmapScalingMode>
+            <MultiBinding Converter="{converters:WidthToBitmapScalingModeConverter}">
+                <Binding ElementName="uc" Path="TargetBitmap.PixelWidth"/>
+                <Binding ElementName="mainImage" Path="ActualWidth"/>
+            </MultiBinding>
+        </RenderOptions.BitmapScalingMode>
+    </Image>
+</UserControl>

+ 127 - 0
src/PixiEditor/Views/UserControls/FixedViewport.xaml.cs

@@ -0,0 +1,127 @@
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Media.Imaging;
+using ChunkyImageLib.DataHolders;
+using PixiEditor.Models.Position;
+using PixiEditor.ViewModels.SubViewModels.Document;
+
+namespace PixiEditor.Views.UserControls;
+#nullable enable
+internal partial class FixedViewport : UserControl, INotifyPropertyChanged
+{
+    public static readonly DependencyProperty DocumentProperty =
+        DependencyProperty.Register(nameof(Document), typeof(DocumentViewModel), typeof(FixedViewport), new(null, OnDocumentChange));
+
+    private static readonly DependencyProperty BitmapsProperty =
+        DependencyProperty.Register(nameof(Bitmaps), typeof(Dictionary<ChunkResolution, WriteableBitmap>), typeof(FixedViewport), new(null, OnBitmapsChange));
+
+    public static readonly DependencyProperty DelayedProperty = DependencyProperty.Register(
+        nameof(Delayed), typeof(bool), typeof(FixedViewport), new PropertyMetadata(false));
+
+    public event PropertyChangedEventHandler? PropertyChanged;
+
+    public bool Delayed
+    {
+        get => (bool)GetValue(DelayedProperty);
+        set => SetValue(DelayedProperty, value);
+    }
+
+    public Dictionary<ChunkResolution, WriteableBitmap>? Bitmaps
+    {
+        get => (Dictionary<ChunkResolution, WriteableBitmap>?)GetValue(BitmapsProperty);
+        set => SetValue(BitmapsProperty, value);
+    }
+
+    public DocumentViewModel? Document
+    {
+        get => (DocumentViewModel)GetValue(DocumentProperty);
+        set => SetValue(DocumentProperty, value);
+    }
+
+    public WriteableBitmap? TargetBitmap
+    {
+        get => Document?.Bitmaps.TryGetValue(CalculateResolution(), out WriteableBitmap? value) == true ? value : null;
+    }
+
+    public Guid GuidValue { get; } = Guid.NewGuid();
+
+    public FixedViewport()
+    {
+        InitializeComponent();
+        Binding binding = new Binding { Source = this, Path = new PropertyPath("Document.Bitmaps") };
+        SetBinding(BitmapsProperty, binding);
+
+        Loaded += OnLoad;
+        Unloaded += OnUnload;
+    }
+
+    private void OnUnload(object sender, RoutedEventArgs e)
+    {
+        Document?.RemoveViewport(GuidValue);
+    }
+
+    private void OnLoad(object sender, RoutedEventArgs e)
+    {
+        Document?.AddOrUpdateViewport(GetLocation());
+    }
+
+    private ChunkResolution CalculateResolution()
+    {
+        if (Document is null)
+            return ChunkResolution.Full;
+        double density = Document.Width / mainImage.ActualWidth;
+        if (density > 8.01)
+            return ChunkResolution.Eighth;
+        else if (density > 4.01)
+            return ChunkResolution.Quarter;
+        else if (density > 2.01)
+            return ChunkResolution.Half;
+        return ChunkResolution.Full;
+    }
+
+    private void ForceRefreshFinalImage()
+    {
+        mainImage.InvalidateVisual();
+    }
+
+    private ViewportInfo GetLocation()
+    {
+        VecD docSize = new VecD(1);
+        if (Document is not null)
+            docSize = Document.SizeBindable;
+
+        return new ViewportInfo(
+            0,
+            docSize / 2,
+            new VecD(mainImage.ActualWidth, mainImage.ActualHeight),
+            docSize,
+            CalculateResolution(),
+            GuidValue,
+            Delayed,
+            ForceRefreshFinalImage);
+    }
+
+    private static void OnDocumentChange(DependencyObject viewportObj, DependencyPropertyChangedEventArgs args)
+    {
+        DocumentViewModel? oldDoc = (DocumentViewModel?)args.OldValue;
+        DocumentViewModel? newDoc = (DocumentViewModel?)args.NewValue;
+        FixedViewport? viewport = (FixedViewport)viewportObj;
+        oldDoc?.RemoveViewport(viewport.GuidValue);
+        newDoc?.AddOrUpdateViewport(viewport.GetLocation());
+    }
+
+    private static void OnBitmapsChange(DependencyObject viewportObj, DependencyPropertyChangedEventArgs args)
+    {
+        FixedViewport? viewport = ((FixedViewport)viewportObj);
+        viewport.PropertyChanged?.Invoke(viewportObj, new(nameof(TargetBitmap)));
+        viewport.Document!.AddOrUpdateViewport(viewport.GetLocation());
+    }
+
+    private void OnImageSizeChanged(object sender, SizeChangedEventArgs e)
+    {
+        PropertyChanged?.Invoke(this, new(nameof(TargetBitmap)));
+        Document?.AddOrUpdateViewport(GetLocation());
+    }
+}

+ 12 - 17
src/PixiEditor/Views/UserControls/PreviewWindow.xaml

@@ -21,29 +21,24 @@
             <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
 
-        <Viewbox Margin="30" VerticalAlignment="Center" x:Name="previewWindowViewbox">
-            <Grid x:Name="imageGrid" RenderOptions.BitmapScalingMode="NearestNeighbor"
+        <Grid x:Name="imageGrid" RenderOptions.BitmapScalingMode="NearestNeighbor"
               Visibility="{Binding Document, Converter={converters:NotNullToVisibilityConverter}, ElementName=uc}"
-              Height="{Binding Document.Height, ElementName=uc}" Width="{Binding Document.Width, ElementName=uc}"
+              Margin="10" Background="Transparent"
               d:Width="8" d:Height="8">
-                <Grid Background="{Binding ActiveItem.Value, ElementName=backgroundButton}">
-                    <Grid.LayoutTransform>
-                        <MultiBinding Converter="{converters:ViewboxInverseTransformConverter}">
-                            <Binding ElementName="previewWindowViewbox" Path="." />
-                            <Binding ElementName="imageGrid" Path="ActualWidth" />
-                            <Binding ElementName="imageGrid" Path="ActualHeight" />
-                        </MultiBinding>
-                    </Grid.LayoutTransform>
-                </Grid>
-                <Border x:Name="colorCursor" Width="1" Height="1"
+            <local:FixedViewport
+                Delayed="True"
+                x:Name="viewport"
+                Document="{Binding Document, ElementName=uc}"
+                Background="{Binding ActiveItem.Value, ElementName=backgroundButton}"/>
+            <Border 
+                    x:Name="colorCursor" Width="1" Height="1"
                     Margin="{Binding ColorCursorPosition, ElementName=uc}"
                     HorizontalAlignment="Left" VerticalAlignment="Top"
                     BorderBrush="Black" BorderThickness=".1"
                     Visibility="{Binding IsMouseOver, ElementName=imageGrid, Converter={StaticResource BoolToVisibilityConverter}}">
-                    <Border BorderThickness=".1" BorderBrush="White"/>
-                </Border>
-            </Grid>
-        </Viewbox>
+                <Border BorderThickness=".1" BorderBrush="White"/>
+            </Border>
+        </Grid>
 
         <Grid Grid.Row="1">
             <Grid.Background>

+ 8 - 6
src/PixiEditor/Views/UserControls/PreviewWindow.xaml.cs

@@ -2,13 +2,11 @@
 using System.Windows.Controls;
 using System.Windows.Input;
 using System.Windows.Media;
+using ChunkyImageLib.DataHolders;
 using PixiEditor.ViewModels.SubViewModels.Document;
 
 namespace PixiEditor.Views.UserControls;
 
-/// <summary>
-/// Interaction logic for PreviewWindow.xaml
-/// </summary>
 internal partial class PreviewWindow : UserControl
 {
     public static readonly DependencyProperty DocumentProperty =
@@ -119,10 +117,14 @@ internal partial class PreviewWindow : UserControl
             return;
         }
 
-        Point mousePos = e.GetPosition(imageGrid);
+        Point mousePos = e.GetPosition(viewport);
+        VecD mousePosConverted =
+            new VecD(mousePos.X, mousePos.Y)
+                .Divide(new VecD(viewport.ActualWidth, viewport.ActualHeight))
+                .Multiply(Document.SizeBindable);
 
-        int x = (int)mousePos.X;
-        int y = (int)mousePos.Y;
+        int x = (int)mousePosConverted.X;
+        int y = (int)mousePosConverted.Y;
 
         Thickness newPos = new Thickness(x, y, 0, 0);
 

+ 1 - 1
src/PixiEditor/Views/UserControls/Viewport.xaml.cs

@@ -234,7 +234,7 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         Binding binding = new Binding { Source = this, Path = new PropertyPath("Document.Bitmaps") };
         SetBinding(BitmapsProperty, binding);
 
-        GetImage().Loaded += OnImageLoaded;
+        GetImage()!.Loaded += OnImageLoaded;
         Loaded += OnLoad;
         Unloaded += OnUnload;
     }