Browse Source

Add `QuickSettingsDialog` and enhance UI interactions

- Introduced `QuickSettingsDialog` as a pop-up for quick access to settings and actions.
- Added pointer-based handling in `HoverBar`, including right-click for quick settings.
- Updated `DraggableProgressBar` with exposed `UpdateThumbPosition` method and layout refinements.
- Improved theme by introducing chevron icons and updating `NavigationDialog` for better clarity.
- Refined `HoverBar` layout by increasing max width and adding tooltips to buttons.
Ruben 2 months ago
parent
commit
8500d8aa15

+ 1 - 0
src/PicView.Avalonia/CustomControls/DraggableProgressBar.axaml

@@ -8,6 +8,7 @@
             <ControlTemplate>
                 <Border
                     Background="{DynamicResource SecondaryButtonBackgroundColor}"
+                    CornerRadius="{TemplateBinding CornerRadius}"
                     Name="NavigationProgress"
                     Padding="4">
                     <Border

+ 2 - 6
src/PicView.Avalonia/CustomControls/DraggableProgressBar.axaml.cs

@@ -89,6 +89,7 @@ public class DraggableProgressBar : TemplatedControl
                 }
             })
             .AddTo(_disposables);
+        UpdateThumbPosition();
     }
 
     public bool IsDragging { get; private set; }
@@ -122,11 +123,6 @@ public class DraggableProgressBar : TemplatedControl
         base.OnApplyTemplate(e);
         _track = e.NameScope.Find<Border>("PART_Track");
         _thumb = e.NameScope.Find<Ellipse>("PART_Thumb");
-
-        if (_track is not null && _thumb is not null)
-        {
-            UpdateThumbPosition();
-        }
     }
 
     // Recalculate thumb position when CurrentIndex or Maximum changes
@@ -144,7 +140,7 @@ public class DraggableProgressBar : TemplatedControl
         }
     }
 
-    private void UpdateThumbPosition()
+    public void UpdateThumbPosition()
     {
         if (_thumb == null)
         {

+ 50 - 0
src/PicView.Avalonia/PicViewTheme/Icons.axaml

@@ -1201,6 +1201,56 @@
         </DrawingGroup>
     </DrawingImage>
 
+    <DrawingImage x:Key="ChevronsLeftImage">
+        <DrawingGroup>
+            <GeometryDrawing Geometry="F1 M11 17L6 12L11 7">
+                <GeometryDrawing.Pen>
+                    <Pen
+                        Brush="{DynamicResource MainTextColor}"
+                        LineCap="Round"
+                        LineJoin="Round"
+                        MiterLimit="4"
+                        Thickness="2" />
+                </GeometryDrawing.Pen>
+            </GeometryDrawing>
+            <GeometryDrawing Geometry="F1 M18 17L13 12L18 7">
+                <GeometryDrawing.Pen>
+                    <Pen
+                        Brush="{DynamicResource MainTextColor}"
+                        LineCap="Round"
+                        LineJoin="Round"
+                        MiterLimit="4"
+                        Thickness="2" />
+                </GeometryDrawing.Pen>
+            </GeometryDrawing>
+        </DrawingGroup>
+    </DrawingImage>
+
+    <DrawingImage x:Key="ChevronsRightImage">
+        <DrawingGroup>
+            <GeometryDrawing Geometry="F1 M6 17L11 12L6 7">
+                <GeometryDrawing.Pen>
+                    <Pen
+                        Brush="{DynamicResource MainTextColor}"
+                        LineCap="Round"
+                        LineJoin="Round"
+                        MiterLimit="4"
+                        Thickness="2" />
+                </GeometryDrawing.Pen>
+            </GeometryDrawing>
+            <GeometryDrawing Geometry="F1 M13 17L18 12L13 7">
+                <GeometryDrawing.Pen>
+                    <Pen
+                        Brush="{DynamicResource MainTextColor}"
+                        LineCap="Round"
+                        LineJoin="Round"
+                        MiterLimit="4"
+                        Thickness="2" />
+                </GeometryDrawing.Pen>
+            </GeometryDrawing>
+        </DrawingGroup>
+    </DrawingImage>
+
     <DrawingImage x:Key="LastImage">
         <DrawingGroup>
             <GeometryDrawing Geometry="F1 M7 18L13 12L7 6">

+ 1 - 0
src/PicView.Avalonia/StartUp/QuickLoad.cs

@@ -69,6 +69,7 @@ public static class QuickLoad
         }
         
         vm.PicViewer.GetIndex.Value = NavigationManager.GetNonZeroIndex;
+        vm.PicViewer.Index.Value = NavigationManager.GetCurrentIndex;
     }
 
     /// <summary>

+ 23 - 20
src/PicView.Avalonia/Views/UC/HoverBar.axaml

@@ -17,7 +17,7 @@
         CornerRadius="6"
         Height="37"
         Margin="5,65,5,0"
-        MaxWidth="700"
+        MaxWidth="850"
         x:Name="TopBorder">
         <DockPanel LastChildFill="True">
             <customControls:IconButton
@@ -26,12 +26,15 @@
                 BorderThickness="0,0,1,0"
                 Classes="noBorderHover"
                 Command="{CompiledBinding Tools.OpenFileCommand}"
+                CornerRadius="6,0,0,6"
                 Data="{StaticResource AltFolderGeometry}"
                 Foreground="{DynamicResource MainTextColor}"
                 Height="35"
                 IconHeight="17"
                 IconWidth="20"
                 IsTabStop="False"
+                ToolTip.Tip="{CompiledBinding Translation.OpenFileDialog.Value,
+                                              Mode=OneWay}"
                 Width="35"
                 x:Name="FileMenuButton" />
 
@@ -66,7 +69,7 @@
                 x:Name="ZoomInMenuButton" />
 
             <customControls:IconButton
-                Background="{DynamicResource WindowButtonBackgroundColor}"
+                Background="{DynamicResource SecondaryButtonBackgroundColor}"
                 BorderBrush="{DynamicResource MainBorderColor}"
                 BorderThickness="0,0,1,0"
                 Classes="noBorderHover"
@@ -86,7 +89,7 @@
                 x:Name="RotateLeftButton" />
 
             <customControls:IconButton
-                Background="{DynamicResource WindowButtonBackgroundColor}"
+                Background="{DynamicResource SecondaryButtonBackgroundColor}"
                 Classes="noBorderHover"
                 Command="{CompiledBinding Tools.RotateRightCommand}"
                 Data="{StaticResource RotateRightGeometry}"
@@ -105,7 +108,7 @@
                 x:Name="RotateRightButton" />
 
             <customControls:IconButton
-                Background="{DynamicResource WindowButtonBackgroundColor}"
+                Background="{DynamicResource SecondaryButtonBackgroundColor}"
                 BorderBrush="{DynamicResource MainBorderColor}"
                 BorderThickness="1,0,1,0"
                 Classes="noBorderHover"
@@ -129,6 +132,20 @@
                 </Button.RenderTransform>
             </customControls:IconButton>
 
+            <customControls:IconButton
+                Background="{DynamicResource SecondaryButtonBackgroundColor}"
+                BorderBrush="{DynamicResource MainBorderColor}"
+                BorderThickness="0,0,1,0"
+                Classes="noBorderHover"
+                Data="{StaticResource CogGeometry}"
+                Foreground="{DynamicResource MainTextColor}"
+                Height="35"
+                IconHeight="18"
+                IconWidth="18"
+                IsTabStop="False"
+                Width="35"
+                x:Name="SettingsMenuButton" />
+
             <customControls:IconButton
                 Background="{DynamicResource MainButtonBackgroundColor}"
                 BorderBrush="{DynamicResource MainBorderColor}"
@@ -163,23 +180,9 @@
                 Width="80"
                 x:Name="NextButton" />
 
-            <customControls:IconButton
-                Background="{DynamicResource SecondaryButtonBackgroundColor}"
-                BorderBrush="{DynamicResource MainBorderColor}"
-                BorderThickness="0,0,1,0"
-                Classes="noBorderHover"
-                Command="{Binding Window.ShowSettingsWindow}"
-                Data="{StaticResource CogGeometry}"
-                Foreground="{DynamicResource MainTextColor}"
-                Height="35"
-                IconHeight="18"
-                IconWidth="18"
-                IsTabStop="False"
-                Width="35"
-                x:Name="SettingsMenuButton" />
-
             <customControls:DraggableProgressBar
-                CurrentIndex="{CompiledBinding PicViewer.Index}"
+                CornerRadius="0,6,6,0"
+                CurrentIndex="{CompiledBinding PicViewer.Index.Value}"
                 DragSensitivity="1"
                 IsEnabled="{CompiledBinding PicViewer.FileInfo.Value,
                                             Converter={x:Static ObjectConverters.IsNotNull}}"

+ 23 - 0
src/PicView.Avalonia/Views/UC/HoverBar.axaml.cs

@@ -77,6 +77,24 @@ public partial class HoverBar : UserControl
                 await FunctionsMapper.Prev();
             }
         }
+        else if (SettingsMenuButton.IsPointerOver)
+        {
+            if (props.IsRightButtonPressed)
+            {
+                ShowQuickSettingsDialog();
+            }
+            else if (props.IsLeftButtonPressed)
+            {
+                await FunctionsMapper.SettingsWindow();
+            }
+        }
+        else if (ProgressBar.IsPointerOver)
+        {
+            if (props.IsRightButtonPressed)
+            {
+                //TODO: Create popup window to navigate to index
+            }
+        }
         else
         {
             if (props.IsRightButtonPressed)
@@ -97,6 +115,11 @@ public partial class HoverBar : UserControl
         UIHelper.GetMainView.MainGrid.Children.Add(new NavigationDialog());
     }
     
+    private void ShowQuickSettingsDialog()
+    {
+        UIHelper.GetMainView.MainGrid.Children.Add(new QuickSettingsDialog());
+    }
+    
     protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
     {
         base.OnDetachedFromLogicalTree(e);

+ 4 - 4
src/PicView.Avalonia/Views/UC/PopUps/NavigationDialog.axaml

@@ -47,7 +47,7 @@
         <!--  Next 10  -->
         <customControls:TextIconButton
             Classes="altHover"
-            Icon="{StaticResource NextImage}"
+            Icon="{StaticResource ChevronsRightImage}"
             IconHeight="12"
             IconMargin="5,0,10,0"
             IconWidth="12"
@@ -61,7 +61,7 @@
         <!--  Next 100  -->
         <customControls:TextIconButton
             Classes="altHover"
-            Icon="{StaticResource NextImage}"
+            Icon="{StaticResource ChevronsRightImage}"
             IconHeight="12"
             IconMargin="5,0,10,0"
             IconWidth="12"
@@ -75,7 +75,7 @@
         <!--  Prev 10  -->
         <customControls:TextIconButton
             Classes="altHover"
-            Icon="{StaticResource PrevImage}"
+            Icon="{StaticResource ChevronsLeftImage}"
             IconHeight="12"
             IconMargin="5,0,10,0"
             IconWidth="12"
@@ -89,7 +89,7 @@
         <!--  Prev 100  -->
         <customControls:TextIconButton
             Classes="altHover"
-            Icon="{StaticResource PrevImage}"
+            Icon="{StaticResource ChevronsLeftImage}"
             IconHeight="12"
             IconMargin="5,0,10,0"
             IconWidth="12"

+ 185 - 0
src/PicView.Avalonia/Views/UC/PopUps/QuickSettingsDialog.axaml

@@ -0,0 +1,185 @@
+<customControls:AnimatedPopUp
+    ClickingOutsideCloses="True"
+    Padding="20"
+    d:DesignHeight="450"
+    d:DesignWidth="800"
+    mc:Ignorable="d"
+    x:Class="PicView.Avalonia.Views.UC.PopUps.QuickSettingsDialog"
+    x:DataType="viewModels:MainViewModel"
+    xmlns="https://github.com/avaloniaui"
+    xmlns:customControls="clr-namespace:PicView.Avalonia.CustomControls"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:viewModels="clr-namespace:PicView.Avalonia.ViewModels"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+    <StackPanel Background="Transparent">
+
+        <Border
+            Background="{DynamicResource MainBackgroundColor}"
+            BorderBrush="{DynamicResource MainBorderColor}"
+            BorderThickness="1"
+            CornerRadius="4">
+            <StackPanel Orientation="Horizontal">
+                <!--  All settings  -->
+                <customControls:TextIconButton
+                    Background="Transparent"
+                    BorderBrush="{DynamicResource MainBorderColor}"
+                    BorderThickness="0,0,1,0"
+                    Classes="noBorderHover"
+                    CornerRadius="4,0,0,4"
+                    Icon="{StaticResource GeneralSettingsAltImage}"
+                    IconHeight="14"
+                    IconMargin="5,0,10,0"
+                    IconWidth="14"
+                    Padding="15,10"
+                    Text="{CompiledBinding Translation.Settings.Value,
+                                           Mode=OneWay}"
+                    TextMargin="0,0,5,0"
+                    TextMaxWidth="170"
+                    ToolTip.Tip="{CompiledBinding Translation.ShowAllSettingsWindow.Value,
+                                                  Mode=OneWay}"
+                    Width="185"
+                    x:Name="AllSettingsButton" />
+
+                <!--  About  -->
+                <customControls:TextIconButton
+                    Background="Transparent"
+                    Classes="altHover"
+                    CornerRadius="0,4,4,0"
+                    Icon="{StaticResource AboutImage}"
+                    IconHeight="14"
+                    IconMargin="5,0,10,0"
+                    IconWidth="14"
+                    Padding="15,10"
+                    Text="{CompiledBinding Translation.About.Value,
+                                           Mode=OneWay}"
+                    TextMargin="0,0,8,0"
+                    TextMaxWidth="170"
+                    ToolTip.Tip="{CompiledBinding Translation.AboutWindow.Value,
+                                                  Mode=OneWay}"
+                    Width="185"
+                    x:Name="AboutButton" />
+            </StackPanel>
+
+
+        </Border>
+        <WrapPanel
+            Margin="0,15,0,0"
+            MaxWidth="375"
+            Orientation="Horizontal">
+
+            <!--  Toggle scroll  -->
+            <ToggleButton
+                Background="{DynamicResource MenuButtonColor}"
+                Classes="ButtonBorder altHover"
+                Command="{CompiledBinding Tools.ToggleScrollCommand}"
+                Height="42"
+                IsChecked="{CompiledBinding GlobalSettings.IsScrollingEnabled.Value}"
+                Margin="6,0,4,8"
+                ToolTip.Tip="{CompiledBinding Translation.ToggleScroll.Value,
+                                              Mode=OneWay}"
+                Width="175"
+                x:Name="ScrollButton">
+                <TextBlock
+                    Classes="txt"
+                    MaxWidth="155"
+                    Text="{CompiledBinding Translation.IsScrolling.Value,
+                                           Mode=OneWay}" />
+            </ToggleButton>
+
+            <!--  Toggle stretch  -->
+            <ToggleButton
+                Background="{DynamicResource MenuButtonColor}"
+                Classes="ButtonBorder altHover"
+                Command="{CompiledBinding Tools.StretchedCommand}"
+                Height="42"
+                IsChecked="{CompiledBinding GlobalSettings.IsStretched.Value,
+                                            Mode=TwoWay}"
+                Margin="6,0,4,8"
+                ToolTip.Tip="{CompiledBinding Translation.Stretch.Value,
+                                              Mode=OneWay}"
+                Width="175"
+                x:Name="StretchButton">
+                <TextBlock
+                    Classes="txt"
+                    MaxWidth="145"
+                    Text="{CompiledBinding Translation.Stretch.Value,
+                                           Mode=OneWay}" />
+            </ToggleButton>
+
+            <!--  Toggle looping  -->
+            <ToggleButton
+                Background="{DynamicResource MenuButtonColor}"
+                Classes="ButtonBorder altHover"
+                Command="{CompiledBinding Tools.ToggleLoopingCommand}"
+                Height="42"
+                IsChecked="{CompiledBinding GlobalSettings.IsLooping.Value}"
+                Margin="6,0,4,8"
+                ToolTip.Tip="{CompiledBinding Translation.ToggleScroll.Value,
+                                              Mode=OneWay}"
+                Width="175">
+                <TextBlock
+                    Classes="txt"
+                    MaxWidth="155"
+                    Text="{CompiledBinding Translation.IsLooping.Value,
+                                           Mode=OneWay}" />
+            </ToggleButton>
+
+            <!--  Toggle auto fit  -->
+            <ToggleButton
+                Background="{DynamicResource MenuButtonColor}"
+                Classes="ButtonBorder altHover"
+                Command="{CompiledBinding Tools.ChangeAutoFitCommand}"
+                Height="42"
+                IsChecked="{CompiledBinding GlobalSettings.IsAutoFit.Value,
+                                            Mode=TwoWay}"
+                Margin="6,0,4,8"
+                ToolTip.Tip="{CompiledBinding Translation.AutoFitWindow.Value,
+                                              Mode=OneWay}"
+                Width="175">
+                <TextBlock
+                    Classes="txt"
+                    MaxWidth="145"
+                    Text="{CompiledBinding Translation.AutoFitWindow.Value,
+                                           Mode=OneWay}" />
+            </ToggleButton>
+
+            <!--  Toggle topmost  -->
+            <ToggleButton
+                Background="{DynamicResource MenuButtonColor}"
+                Classes="ButtonBorder altHover"
+                Command="{CompiledBinding Tools.ChangeTopMostCommand}"
+                Height="42"
+                IsChecked="{CompiledBinding GlobalSettings.IsTopMost.Value}"
+                Margin="6,0,4,8"
+                ToolTip.Tip="{CompiledBinding Translation.StayTopMost.Value,
+                                              Mode=OneWay}"
+                Width="175">
+                <TextBlock
+                    Classes="txt"
+                    MaxWidth="155"
+                    Text="{CompiledBinding Translation.StayTopMost.Value,
+                                           Mode=OneWay}" />
+            </ToggleButton>
+
+            <!--  Toggle subdirectories  -->
+            <ToggleButton
+                Background="{DynamicResource MenuButtonColor}"
+                Classes="ButtonBorder altHover"
+                Command="{CompiledBinding Tools.ToggleSubdirectoriesCommand}"
+                Height="42"
+                IsChecked="{CompiledBinding GlobalSettings.IsIncludingSubdirectories.Value,
+                                            Mode=TwoWay}"
+                Margin="6,0,4,8"
+                ToolTip.Tip="{CompiledBinding Translation.SearchSubdirectory.Value,
+                                              Mode=OneWay}"
+                Width="175">
+                <TextBlock
+                    Classes="txt"
+                    MaxWidth="145"
+                    Text="{CompiledBinding Translation.SearchSubdirectory.Value,
+                                           Mode=OneWay}" />
+            </ToggleButton>
+        </WrapPanel>
+    </StackPanel>
+</customControls:AnimatedPopUp>

+ 52 - 0
src/PicView.Avalonia/Views/UC/PopUps/QuickSettingsDialog.axaml.cs

@@ -0,0 +1,52 @@
+using Avalonia.Interactivity;
+using Avalonia.LogicalTree;
+using PicView.Avalonia.CustomControls;
+using PicView.Avalonia.Functions;
+using PicView.Avalonia.UI;
+using PicView.Avalonia.ViewModels;
+using R3;
+
+namespace PicView.Avalonia.Views.UC.PopUps;
+
+public partial class QuickSettingsDialog : AnimatedPopUp
+{
+    private readonly CompositeDisposable _subscriptions = new();
+    public QuickSettingsDialog()
+    {
+        DataContext = UIHelper.GetMainView.DataContext as MainViewModel;
+        InitializeComponent();
+        Loaded += OnLoaded;
+    }
+
+    private void OnLoaded(object? sender, RoutedEventArgs e)
+    {
+        // Ensure we don't double-subscribe if Loaded fires multiple times
+        _subscriptions.Clear();
+
+        Observable.FromEventHandler<RoutedEventArgs>(h => AllSettingsButton.Click += h,
+                h => AllSettingsButton.Click -= h)
+            .SubscribeAwait(async (_, _) =>
+            {
+                _ = AnimatedClosing();
+                await FunctionsMapper.SettingsWindow();
+            })
+            .AddTo(_subscriptions);
+        
+        Observable.FromEventHandler<RoutedEventArgs>(h => AboutButton.Click += h,
+                h => AboutButton.Click -= h)
+            .SubscribeAwait(async (_, _) =>
+            {
+                _ = AnimatedClosing();
+                await FunctionsMapper.AboutWindow();
+            })
+            .AddTo(_subscriptions);
+    }
+
+    protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
+    {
+        base.OnDetachedFromLogicalTree(e);
+        Loaded -= OnLoaded;
+        // Dispose current subscriptions but keep the CompositeDisposable reusable
+        _subscriptions.Clear();
+    }
+}