Browse Source

Add image viewer footer,

pull/165/head
Ionite 1 year ago
parent
commit
5a0bbb8882
No known key found for this signature in database
  1. 34
      StabilityMatrix.Avalonia/Behaviors/ConditionalToolTipBehavior.cs
  2. 11
      StabilityMatrix.Avalonia/Controls/AdvancedImageBox.axaml.cs
  3. 2
      StabilityMatrix.Avalonia/Controls/BetterContentDialog.cs
  4. 7
      StabilityMatrix.Avalonia/Controls/ImageFolderCard.axaml
  5. 1
      StabilityMatrix.Avalonia/Controls/ImageFolderCard.axaml.cs
  6. 176
      StabilityMatrix.Avalonia/Controls/PromptCard.axaml
  7. 3
      StabilityMatrix.Avalonia/DesignData/DesignData.cs
  8. 10
      StabilityMatrix.Avalonia/ViewModels/Dialogs/ImageViewerViewModel.cs
  9. 6
      StabilityMatrix.Avalonia/ViewModels/Inference/ImageFolderCardViewModel.cs
  10. 117
      StabilityMatrix.Avalonia/Views/Dialogs/ImageViewerDialog.axaml

34
StabilityMatrix.Avalonia/Behaviors/ConditionalToolTipBehavior.cs

@ -0,0 +1,34 @@
using System.Diagnostics.CodeAnalysis;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Xaml.Interactivity;
namespace StabilityMatrix.Avalonia.Behaviors;
/// <summary>
/// Behavior that sets tooltip to null if the DisableOn condition is true.
/// </summary>
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
public class ConditionalToolTipBehavior : Behavior<Control>
{
public static readonly StyledProperty<bool> DisableOnProperty = AvaloniaProperty.Register<
ConditionalToolTipBehavior,
bool
>("DisableOn");
public bool DisableOn
{
get => GetValue(DisableOnProperty);
set => SetValue(DisableOnProperty, value);
}
protected override void OnAttached()
{
base.OnAttached();
if (DisableOn)
{
ToolTip.SetTip(AssociatedObject!, null);
}
}
}

11
StabilityMatrix.Avalonia/Controls/AdvancedImageBox.axaml.cs

@ -678,6 +678,15 @@ public class AdvancedImageBox : TemplatedControl
set => SetValue(TrackerImageAutoZoomProperty, value);
}
public static readonly StyledProperty<bool> IsTrackerImageEnabledProperty =
AvaloniaProperty.Register<AdvancedImageBox, bool>("IsTrackerImageEnabled");
public bool IsTrackerImageEnabled
{
get => GetValue(IsTrackerImageEnabledProperty);
set => SetValue(IsTrackerImageEnabledProperty, value);
}
public bool IsHorizontalBarVisible
{
get
@ -1350,7 +1359,7 @@ public class AdvancedImageBox : TemplatedControl
_pointerPosition.X - destSize.Width / 2,
_pointerPosition.Y - destSize.Height / 2
);
context.DrawImage(_trackerImage, new Rect(destPos, destSize));
context.DrawImage(_trackerImage!, new Rect(destPos, destSize));
}
//SkiaContext.SkCanvas.dr

2
StabilityMatrix.Avalonia/Controls/BetterContentDialog.cs

@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Reflection;
using AsyncAwaitBestPractices;
using Avalonia;
@ -11,6 +12,7 @@ using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using Brushes = Avalonia.Media.Brushes;
namespace StabilityMatrix.Avalonia.Controls;

7
StabilityMatrix.Avalonia/Controls/ImageFolderCard.axaml

@ -11,6 +11,7 @@
xmlns:dbModels="clr-namespace:StabilityMatrix.Core.Models.Database;assembly=StabilityMatrix.Core"
xmlns:animations="clr-namespace:StabilityMatrix.Avalonia.Animations"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
xmlns:behaviors="clr-namespace:StabilityMatrix.Avalonia.Behaviors"
x:DataType="vmInference:ImageFolderCardViewModel">
<Design.PreviewWith>
@ -132,7 +133,7 @@
<Interaction.Behaviors>
<BehaviorCollection>
<ContextDragBehavior HorizontalDragThreshold="3" VerticalDragThreshold="3"/>
<ContextDragBehavior HorizontalDragThreshold="6" VerticalDragThreshold="6"/>
</BehaviorCollection>
</Interaction.Behaviors>
@ -168,9 +169,7 @@
</Button.ContextFlyout>
<ToolTip.Tip>
<ToolTip>
<TextBlock Text="{Binding GenerationParameters.PositivePrompt}"/>
</ToolTip>
<TextBlock Text="{Binding GenerationParameters.PositivePrompt}"/>
</ToolTip.Tip>
<Border ClipToBounds="True" CornerRadius="8">

1
StabilityMatrix.Avalonia/Controls/ImageFolderCard.axaml.cs

@ -1,4 +1,5 @@
using AsyncAwaitBestPractices;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Threading;

176
StabilityMatrix.Avalonia/Controls/PromptCard.axaml

@ -1,134 +1,168 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:StabilityMatrix.Avalonia.Controls"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
xmlns:vmInference="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Inference"
xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
xmlns:behaviors="clr-namespace:StabilityMatrix.Avalonia.Behaviors"
xmlns:icons="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
x:DataType="vmInference:PromptCardViewModel">
<Styles
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
xmlns:behaviors="clr-namespace:StabilityMatrix.Avalonia.Behaviors"
xmlns:controls="using:StabilityMatrix.Avalonia.Controls"
xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
xmlns:icons="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:vmInference="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Inference"
x:DataType="vmInference:PromptCardViewModel">
<Design.PreviewWith>
<Grid Height="600" Width="460">
<controls:PromptCard DataContext="{x:Static mocks:DesignData.PromptCardViewModel}"/>
<Grid Width="460" Height="600">
<controls:PromptCard DataContext="{x:Static mocks:DesignData.PromptCardViewModel}" />
</Grid>
</Design.PreviewWith>
<Style Selector="controls|PromptCard">
<!-- Set Defaults -->
<!-- Set Defaults -->
<Setter Property="Template">
<ControlTemplate>
<controls:Card Padding="12" HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
<controls:Card.Resources>
<!--<ui:TextCommandBarFlyout x:Key="EditorFlyout"/>-->
<ui:FAMenuFlyout x:Key="EditorFlyout">
<ui:MenuFlyoutItem
Text="Paste"
IconSource="Paste"
HotKey="Ctrl+V"
Command="{x:Static avaloniaEdit:ApplicationCommands.Paste}">
<ui:MenuFlyoutItem.CommandParameter>
<MultiBinding>
<Binding Source="{x:Null}"/>
<ReflectionBinding Path="$parent[avaloniaEdit:TextEditor].TextArea"/>
</MultiBinding>
</ui:MenuFlyoutItem.CommandParameter>
</ui:MenuFlyoutItem>
<ui:MenuFlyoutItem
Text="Copy"
IconSource="Copy"
HotKey="Ctrl+C"
Command="{x:Static avaloniaEdit:ApplicationCommands.Copy}"
CommandParameter="{Binding $parent[avaloniaEdit:TextEditor;1].TextArea}"/>
<ui:MenuFlyoutItem
Text="Cut"
IconSource="Cut"
HotKey="Ctrl+X"
Command="{x:Static avaloniaEdit:ApplicationCommands.Cut}"
CommandParameter="{Binding $parent[avaloniaEdit:TextEditor;1].TextArea}"/>
</ui:FAMenuFlyout>
</controls:Card.Resources>
<controls:Card.Styles>
<Style Selector="avaloniaEdit|TextEditor">
<Setter Property="Margin" Value="0,8,0,8"/>
<Setter Property="Margin" Value="0,8,0,8" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="4"/>
<Setter Property="LineNumbersForeground" Value="DarkSlateGray"/>
<Setter Property="ShowLineNumbers" Value="True"/>
<Setter Property="WordWrap" Value="True"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="4" />
<Setter Property="LineNumbersForeground" Value="DarkSlateGray" />
<Setter Property="ShowLineNumbers" Value="True" />
<Setter Property="WordWrap" Value="True" />
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ContextFlyout" Value="{StaticResource EditorFlyout}" />
<!--<Setter Property="Background" Value="{DynamicResource ScrollBarTrackStroke}" />-->
</Style>
</controls:Card.Styles>
<Grid RowDefinitions="*,16,*">
<!-- Prompt -->
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,Auto">
<!-- Prompt -->
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,*">
<StackPanel
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="4,0,4,8"
Margin="4,0,4,8"
Orientation="Horizontal">
<TextBlock FontSize="14" Text="Prompt"/>
<icons:Icon Value="fa-solid fa-caret-up" Margin="8,0" FontSize="10" />
<TextBlock FontSize="14" Text="Prompt" />
<icons:Icon
Margin="8,0"
FontSize="10"
Value="fa-solid fa-caret-up" />
</StackPanel>
<StackPanel
Grid.Row="0"
Grid.Column="1"
Margin="0,0,0,4"
Orientation="Horizontal"
HorizontalAlignment="Right">
Margin="0,0,0,4"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button
Classes="transparent-full"
Padding="10,4"
Margin="0,-2,0,0"
Padding="10,4"
VerticalAlignment="Top"
VerticalContentAlignment="Top"
Command="{Binding ShowHelpDialogCommand}"
icons:Attached.Icon="fa-solid fa-question"/>
<Button
Content="Show Tokens"
icons:Attached.Icon="fa-solid fa-question"
Classes="transparent-full"
Command="{Binding ShowHelpDialogCommand}" />
<Button
Padding="8,4"
IsVisible="{Binding SharedState.IsDebugMode}"
Command="{Binding DebugShowTokensCommand}"/>
Command="{Binding DebugShowTokensCommand}"
Content="Show Tokens"
IsVisible="{Binding SharedState.IsDebugMode}" />
</StackPanel>
<ExperimentalAcrylicBorder
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
VerticalAlignment="Stretch"
Material="{StaticResource ThemeDarkAcrylicMaterial}"
CornerRadius="4">
CornerRadius="4"
Material="{StaticResource ThemeDarkAcrylicMaterial}">
<avaloniaEdit:TextEditor
x:Name="PromptEditor"
Document="{Binding PromptDocument}"
FontFamily="Cascadia Code,Consolas,Menlo,Monospace">
<i:Interaction.Behaviors>
<behaviors:TextEditorCompletionBehavior
IsEnabled="{Binding IsAutoCompletionEnabled}"
CompletionProvider="{Binding CompletionProvider}"
TokenizerProvider="{Binding TokenizerProvider}"/>
<behaviors:TextEditorToolTipBehavior
IsEnabled="False"
TokenizerProvider="{Binding TokenizerProvider}"/>
IsEnabled="{Binding IsAutoCompletionEnabled}"
TokenizerProvider="{Binding TokenizerProvider}" />
<behaviors:TextEditorToolTipBehavior IsEnabled="False" TokenizerProvider="{Binding TokenizerProvider}" />
</i:Interaction.Behaviors>
</avaloniaEdit:TextEditor>
</ExperimentalAcrylicBorder>
</Grid>
<GridSplitter
Grid.Row="1"
BorderThickness="1"
VerticalAlignment="Center"
Opacity="0.3"
<GridSplitter
Grid.Row="1"
MaxWidth="45"
CornerRadius="4"/>
<!-- Negative Prompt -->
VerticalAlignment="Center"
BorderThickness="1"
CornerRadius="4"
Opacity="0.3" />
<!-- Negative Prompt -->
<Grid Grid.Row="2" RowDefinitions="Auto,*">
<StackPanel Margin="4,0,4,8" Orientation="Horizontal">
<TextBlock FontSize="14" Text="Negative Prompt"/>
<icons:Icon Value="fa-solid fa-caret-down" Margin="8,0" FontSize="10" />
<TextBlock FontSize="14" Text="Negative Prompt" />
<icons:Icon
Margin="8,0"
FontSize="10"
Value="fa-solid fa-caret-down" />
</StackPanel>
<ExperimentalAcrylicBorder
Grid.Row="1"
VerticalAlignment="Stretch"
Material="{StaticResource ThemeDarkAcrylicMaterial}"
CornerRadius="4">
CornerRadius="4"
Material="{StaticResource ThemeDarkAcrylicMaterial}">
<avaloniaEdit:TextEditor
x:Name="NegativePromptEditor"
Document="{Binding NegativePromptDocument}"
FontFamily="Cascadia Code,Consolas,Menlo,Monospace">
<i:Interaction.Behaviors>
<behaviors:TextEditorCompletionBehavior
IsEnabled="{Binding IsAutoCompletionEnabled}"
CompletionProvider="{Binding CompletionProvider}"
TokenizerProvider="{Binding TokenizerProvider}"/>
<behaviors:TextEditorToolTipBehavior
IsEnabled="False"
TokenizerProvider="{Binding TokenizerProvider}"/>
IsEnabled="{Binding IsAutoCompletionEnabled}"
TokenizerProvider="{Binding TokenizerProvider}" />
<behaviors:TextEditorToolTipBehavior IsEnabled="False" TokenizerProvider="{Binding TokenizerProvider}" />
</i:Interaction.Behaviors>
</avaloniaEdit:TextEditor>

3
StabilityMatrix.Avalonia/DesignData/DesignData.cs

@ -609,6 +609,9 @@ The gallery images are often inpainted, but you will get something very similar
"https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/a318ac1f-3ad0-48ac-98cc-79126febcc17/width=1500"
)
);
vm.FileNameText = "TextToImage_00041.png";
vm.FileSizeText = "2.4 MB";
vm.ImageSizeText = "1280 x 1792";
});
public static SharpenCardViewModel SharpenCardViewModel =>

10
StabilityMatrix.Avalonia/ViewModels/Dialogs/ImageViewerViewModel.cs

@ -31,10 +31,9 @@ public partial class ImageViewerViewModel : ContentDialogViewModelBase
partial void OnLocalImageFileChanged(LocalImageFile? value)
{
ImageSource?.Dispose();
if (value?.GlobalFullPath is { } path)
if (value?.ImageSize is { IsEmpty: false } size)
{
ImageSource = new ImageSource(path);
ImageSizeText = $"{size.Width} x {size.Height}";
}
}
@ -44,11 +43,6 @@ public partial class ImageViewerViewModel : ContentDialogViewModelBase
{
FileNameText = localFile.Name;
FileSizeText = Size.FormatBase10Bytes(localFile.GetSize(true));
if (LocalImageFile?.GenerationParameters is { Width: > 0, Height: > 0 } parameters)
{
ImageSizeText = $"{parameters.Width} x {parameters.Height}";
}
}
}
}

6
StabilityMatrix.Avalonia/ViewModels/Inference/ImageFolderCardViewModel.cs

@ -148,7 +148,11 @@ public partial class ImageFolderCardViewModel : ViewModelBase
{
Width = 1000,
Height = 1000,
DataContext = new ImageViewerViewModel { ImageSource = image }
DataContext = new ImageViewerViewModel
{
ImageSource = image,
LocalImageFile = item
}
}
};

117
StabilityMatrix.Avalonia/Views/Dialogs/ImageViewerDialog.axaml

@ -1,67 +1,94 @@
<controls:UserControlBase xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:vmDialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
xmlns:icons="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
d:DataContext="{x:Static mocks:DesignData.ImageViewerViewModel}"
x:DataType="vmDialogs:ImageViewerViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.ImageViewerDialog">
<Grid RowDefinitions="*,Auto" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<controls:AdvancedImageBox
SizeMode="Fit"
Image="{Binding ImageSource.BitmapAsync^}"/>
<controls:UserControlBase
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.ImageViewerDialog"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:icons="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:vmDialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
d:DataContext="{x:Static mocks:DesignData.ImageViewerViewModel}"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="vmDialogs:ImageViewerViewModel"
mc:Ignorable="d">
<!-- Close button -->
<Grid
<Grid
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
RowDefinitions="*,Auto">
<controls:AdvancedImageBox Image="{Binding ImageSource.BitmapAsync^}" SizeMode="Fit" />
<!-- Close button -->
<Grid
Grid.Row="0"
VerticalAlignment="Top"
HorizontalAlignment="Right">
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Button
Margin="0,8,8,0"
icons:Attached.Icon="fa-solid fa-xmark"
Classes="transparent"
Command="{Binding OnCloseButtonClick}"
icons:Attached.Icon="fa-solid fa-xmark"/>
Command="{Binding OnCloseButtonClick}" />
</Grid>
<!-- Footer -->
<ExperimentalAcrylicBorder
<!-- Footer -->
<Border
Grid.Row="1"
MinHeight="20"
Background="Transparent"
VerticalAlignment="Bottom"
Opacity="0.9">
<UniformGrid Margin="4" Columns="3">
<TextBlock
HorizontalAlignment="Left"
FontSize="13"
Text="{Binding ImageSizeText}" />
<TextBlock
HorizontalAlignment="Center"
FontSize="13"
Text="{Binding FileNameText}"
TextAlignment="Center" />
<TextBlock
HorizontalAlignment="Right"
FontSize="13"
Text="{Binding FileSizeText}" />
</UniformGrid>
</Border>
<!--<ExperimentalAcrylicBorder
Grid.Row="1"
MinHeight="20"
Padding="4,0,0,0"
VerticalAlignment="Bottom"
Material="{StaticResource ThemeDarkAcrylicMaterial}"
Material="{StaticResource ThemeTransparentAcrylicMaterial}"
Opacity="0.9">
<UniformGrid Columns="3">
<TextBlock
FontSize="12"
VerticalAlignment="Center"
<UniformGrid Columns="3" Margin="4">
<TextBlock
FontSize="13"
HorizontalAlignment="Left"
Text="{Binding ImageSizeText}"/>
<TextBlock
FontSize="12"
VerticalAlignment="Center"
<TextBlock
FontSize="13"
HorizontalAlignment="Center"
TextAlignment="Center"
Text="{Binding FileNameText}"/>
<TextBlock
FontSize="12"
VerticalAlignment="Center"
<TextBlock
FontSize="13"
HorizontalAlignment="Right"
Text="{Binding FileSizeText}"/>
</UniformGrid>
</ExperimentalAcrylicBorder>
<!-- The preview tracker -->
<!--<Image
</ExperimentalAcrylicBorder>-->
<!-- The preview tracker -->
<!--<Image
MinHeight="100"
MinWidth="100"
RenderOptions.BitmapInterpolationMode="HighQuality"
Source="{Binding #MainImageBox.TrackerImage}"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"/> -->
VerticalAlignment="Bottom"/>-->
</Grid>
</controls:UserControlBase>

Loading…
Cancel
Save