Skip to content

Commit de7ed18

Browse files
Fixed auto complete bug and some of the scroll issues with the tag list.
1 parent 9e8e849 commit de7ed18

File tree

4 files changed

+84
-85
lines changed

4 files changed

+84
-85
lines changed

src/ImageDataSetTagEditor/App.axaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public override void Initialize()
1616
public override void OnFrameworkInitializationCompleted()
1717
{
1818
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
19-
desktop.MainWindow = new MainWindow(new MainWindowViewModel());
19+
desktop.MainWindow = new MainWindow();
2020

2121
base.OnFrameworkInitializationCompleted();
2222
}

src/ImageDataSetTagEditor/ViewModels/MainWindowViewModel.cs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@
88
using DynamicData.Alias;
99
using DynamicData.Binding;
1010
using DynamicData.PLinq;
11+
using ImageDataSetTagEditor.Views;
1112
using ReactiveUI;
1213

1314
namespace ImageDataSetTagEditor.ViewModels;
1415

1516
public class MainWindowViewModel : ViewModelBase
1617
{
18+
private readonly MainWindow _window;
1719
private static readonly string[] ValidImageExtensions = { ".jpg", ".jpeg", ".png", ".gif" };
1820

1921
private readonly SourceCache<ImageViewModel, string> _images = new(x => x.ImagePath);
20-
private readonly SourceCache<GlobalTagViewModel, string> _globalTags = new(x => x.Tag);
22+
private readonly SourceCache<GlobalTagViewModel, string> _globalTags = new(x => x.Tag.ToLowerInvariant());
2123

2224
private ImageViewModel? _currentSelectedImage;
2325
private TagViewModel? _currentSelectedTag;
@@ -107,8 +109,9 @@ public bool IsSaving
107109
public ReactiveCommand<Unit, Unit> MoveTagUpCommand { get; set; }
108110
public ReactiveCommand<Unit, Unit> MoveTagDownCommand { get; set; }
109111

110-
public MainWindowViewModel()
112+
public MainWindowViewModel(MainWindow window)
111113
{
114+
_window = window;
112115
SelectedPreviousImageCommand = ReactiveCommand.Create(SelectedPreviousImage);
113116
SelectedNextImageCommand = ReactiveCommand.Create(SelectedNextImage);
114117
SaveAllCommand = ReactiveCommand.CreateFromTask(SaveAllAsync);
@@ -245,7 +248,7 @@ public void MoveTagUp(TagViewModel tag)
245248
var temp = CurrentSelectedImage.Tags[index - 1];
246249
CurrentSelectedImage.Tags[index - 1] = tag;
247250
CurrentSelectedImage.Tags[index] = temp;
248-
251+
249252
CurrentSelectedTag = CurrentSelectedImage.Tags[index - 1];
250253
}
251254

@@ -416,15 +419,11 @@ public void RebuildGlobalTags()
416419
.ToList();
417420

418421
_globalTags.Clear();
419-
foreach (var tag in tags)
422+
423+
_globalTags.AddOrUpdate(tags.Select(tag => new GlobalTagViewModel(tag.Key, 0)
420424
{
421-
var global = _globalTags.Items.SingleOrDefault(globalTag =>
422-
string.Equals(globalTag.Tag, tag.Key,
423-
StringComparison.InvariantCultureIgnoreCase)) ??
424-
new GlobalTagViewModel(tag.Key, 0);
425-
global.ImageCount += tag.Count();
426-
_globalTags.AddOrUpdate(global);
427-
}
425+
ImageCount = tag.Count()
426+
}));
428427

429428
_globalTags.Refresh();
430429
this.RaisePropertyChanged(nameof(TagCountText));
@@ -443,16 +442,20 @@ private void AddTag()
443442
if (CurrentSelectedImage is null) return;
444443

445444
var newTag = new TagViewModel("New Tag");
445+
newTag.OnValueChanged += RefreshSuggestions;
446446
CurrentSelectedImage.Tags.Add(newTag);
447447
CurrentSelectedTag = newTag;
448-
448+
449+
_window.ScrollViewer.ScrollToEnd();
450+
449451
RebuildGlobalTags();
450452
}
451453

452454
private void RemoveTag()
453455
{
454456
if (CurrentSelectedImage is null || CurrentSelectedTag is null) return;
455457

458+
CurrentSelectedTag.ShowAutocomplete = false;
456459
var image = CurrentSelectedImage;
457460
var index = image.Tags.IndexOf(CurrentSelectedTag);
458461

src/ImageDataSetTagEditor/Views/MainWindow.axaml

Lines changed: 66 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
</Window.KeyBindings>
2525
<Window.Resources>
2626
<local:BitmapAssetValueConverter x:Key="VariableImage" />
27+
<Styles x:Key="CustomVirtualizingStackPanelStyle">
28+
<Style Selector="VirtualizingStackPanel">
29+
<Setter Property="Margin" Value="0 0 0 100" />
30+
</Style>
31+
</Styles>
2732
</Window.Resources>
2833
<Design.DataContext>
2934
<!-- This only sets the DataContext for the previewer in an IDE,
@@ -84,59 +89,67 @@
8489
Source="{Binding CurrentSelectedImage.ImagePath, Converter={StaticResource VariableImage}, ConverterParameter=500}" />
8590
</Border>
8691
<Grid Grid.Row="2" ColumnDefinitions="8*, Auto" RowDefinitions="*">
87-
<ListBox Grid.Column="0" Items="{Binding CurrentSelectedImage.Tags}"
88-
SelectedItem="{Binding CurrentSelectedTag}"
89-
SelectionMode="Single"
90-
SelectedIndex="0"
91-
SelectionChanged="TagListBox_OnSelectionChanged">
92-
<ListBox.KeyBindings>
93-
<KeyBinding Gesture="Down" Command="{Binding SelectNextTagCommand}" />
94-
<KeyBinding Gesture="Up" Command="{Binding SelectPreviousTagCommand}" />
95-
<KeyBinding Gesture="Enter"
96-
Command="{Binding DataContext.SetSuggestionCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
97-
<KeyBinding Gesture="Escape"
98-
Command="{Binding DataContext.CloseSuggestionsCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
99-
<KeyBinding Gesture="Alt+Down"
100-
Command="{Binding DataContext.MoveTagDownCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
101-
<KeyBinding Gesture="Alt+Up"
102-
Command="{Binding DataContext.MoveTagUpCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
103-
</ListBox.KeyBindings>
104-
<ListBox.ItemTemplate>
105-
<DataTemplate>
106-
<Grid RowDefinitions="Auto, Auto" ColumnDefinitions="Auto, *">
107-
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal"
108-
Margin="0 0 5 0">
109-
<Button Height="25" Width="25" Click="TagMoveUp_OnClick">
110-
<Image Height="20" Width="20" HorizontalAlignment="Stretch"
111-
VerticalAlignment="Stretch"
112-
Source="{SvgImage /Assets/arrow-up.svg}" />
113-
</Button>
114-
<Button Height="25" Width="25" Click="TagMoveDown_OnClick">
115-
<Image Height="20" Width="20" HorizontalAlignment="Stretch"
116-
VerticalAlignment="Stretch"
117-
Source="{SvgImage /Assets/arrow-down.svg}" />
118-
</Button>
119-
</StackPanel>
120-
<TextBox Grid.Row="0" Grid.Column="1" GotFocus="Tag_OnGotFocus"
121-
LostFocus="Tag_OnLostFocus"
122-
Text="{Binding Value}"
123-
HorizontalContentAlignment="Left" />
124-
<ListBox Grid.Row="1" Grid.Column="1" Name="SuggestionListBox"
125-
Items="{Binding DataContext.TagSuggestions, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
126-
SelectedItem="{Binding DataContext.CurrentSelectedSuggestion, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
127-
SelectionMode="Single"
128-
IsVisible="{Binding ShowAutocomplete}">
129-
<ListBox.ItemTemplate>
130-
<DataTemplate>
131-
<TextBlock Text="{Binding}" Tapped="Suggestion_OnTapped"
132-
PointerPressed="Suggestion_OnPointerPressed" />
133-
</DataTemplate>
134-
</ListBox.ItemTemplate>
135-
</ListBox>
136-
</Grid>
137-
</DataTemplate>
138-
</ListBox.ItemTemplate>
139-
</ListBox>
92+
<ScrollViewer Grid.Column="0" VerticalScrollBarVisibility="Auto" Name="ScrollViewer">
93+
<ListBox Items="{Binding CurrentSelectedImage.Tags}"
94+
SelectedItem="{Binding CurrentSelectedTag}"
95+
SelectionMode="Single"
96+
SelectedIndex="0"
97+
SelectionChanged="TagListBox_OnSelectionChanged">
98+
<ListBox.KeyBindings>
99+
<KeyBinding Gesture="Down" Command="{Binding SelectNextTagCommand}" />
100+
<KeyBinding Gesture="Up" Command="{Binding SelectPreviousTagCommand}" />
101+
<KeyBinding Gesture="Enter"
102+
Command="{Binding DataContext.SetSuggestionCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
103+
<KeyBinding Gesture="Escape"
104+
Command="{Binding DataContext.CloseSuggestionsCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
105+
<KeyBinding Gesture="Alt+Down"
106+
Command="{Binding DataContext.MoveTagDownCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
107+
<KeyBinding Gesture="Alt+Up"
108+
Command="{Binding DataContext.MoveTagUpCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
109+
</ListBox.KeyBindings>
110+
<ListBox.ItemsPanel>
111+
<ItemsPanelTemplate>
112+
<VirtualizingStackPanel
113+
Styles="{StaticResource CustomVirtualizingStackPanelStyle}" />
114+
</ItemsPanelTemplate>
115+
</ListBox.ItemsPanel>
116+
<ListBox.ItemTemplate>
117+
<DataTemplate>
118+
<Grid RowDefinitions="Auto, Auto" ColumnDefinitions="Auto, *">
119+
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal"
120+
Margin="0 0 5 0">
121+
<Button Height="25" Width="25" Click="TagMoveUp_OnClick">
122+
<Image Height="20" Width="20" HorizontalAlignment="Stretch"
123+
VerticalAlignment="Stretch"
124+
Source="{SvgImage /Assets/arrow-up.svg}" />
125+
</Button>
126+
<Button Height="25" Width="25" Click="TagMoveDown_OnClick">
127+
<Image Height="20" Width="20" HorizontalAlignment="Stretch"
128+
VerticalAlignment="Stretch"
129+
Source="{SvgImage /Assets/arrow-down.svg}" />
130+
</Button>
131+
</StackPanel>
132+
<TextBox Grid.Row="0" Grid.Column="1" GotFocus="Tag_OnGotFocus"
133+
LostFocus="Tag_OnLostFocus"
134+
Text="{Binding Value}"
135+
HorizontalContentAlignment="Left" />
136+
<ListBox Grid.Row="1" Grid.Column="1" Name="SuggestionListBox"
137+
Items="{Binding DataContext.TagSuggestions, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
138+
SelectedItem="{Binding DataContext.CurrentSelectedSuggestion, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
139+
SelectionMode="Single"
140+
IsVisible="{Binding ShowAutocomplete}">
141+
<ListBox.ItemTemplate>
142+
<DataTemplate>
143+
<TextBlock Text="{Binding}" Tapped="Suggestion_OnTapped"
144+
PointerPressed="Suggestion_OnPointerPressed" />
145+
</DataTemplate>
146+
</ListBox.ItemTemplate>
147+
</ListBox>
148+
</Grid>
149+
</DataTemplate>
150+
</ListBox.ItemTemplate>
151+
</ListBox>
152+
</ScrollViewer>
140153

141154
<StackPanel Grid.Column="1" Orientation="Vertical">
142155
<Button Height="50" Width="50" Command="{Binding AddTagCommand}">

src/ImageDataSetTagEditor/Views/MainWindow.axaml.cs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Avalonia.Interactivity;
99
using Avalonia.VisualTree;
1010
using ImageDataSetTagEditor.ViewModels;
11-
using ReactiveUI;
1211

1312
namespace ImageDataSetTagEditor.Views;
1413

@@ -17,24 +16,10 @@ public partial class MainWindow : Window
1716
public MainWindow()
1817
{
1918
InitializeComponent();
20-
}
21-
22-
public MainWindow(object? dataContest) : this()
23-
{
24-
DataContext = dataContest;
19+
DataContext = new MainWindowViewModel(this);
2520

2621
ViewModel.FocusSearchBoxCommand.Subscribe(new AnonymousObserver<Unit>(_ => ImageSearchTextBox.Focus()));
2722
ViewModel.FocusTagSearchBoxCommand.Subscribe(new AnonymousObserver<Unit>(_ => GlobalTagSearchBox.Focus()));
28-
29-
ViewModel.PropertyChanged += (sender, args) =>
30-
{
31-
// if (args.PropertyName == nameof(MainWindowViewModel.CurrentSelectedTag))
32-
// {
33-
// var textBox = this.GetVisualChildren().SingleOrDefault(x =>
34-
// x is TextBox { DataContext: TagViewModel tag } && tag == ViewModel.CurrentSelectedTag) as TextBox;
35-
// textBox?.Focus();
36-
// }
37-
};
3823
}
3924

4025
private MainWindowViewModel ViewModel => (MainWindowViewModel)DataContext!;
@@ -83,9 +68,7 @@ private void Tag_OnLostFocus(object? sender, RoutedEventArgs e)
8368
{
8469
if (sender is not TextBox { DataContext: TagViewModel tag }) return;
8570

86-
if (tag.ShowAutocomplete)
87-
ViewModel.RebuildGlobalTags();
88-
71+
ViewModel.RebuildGlobalTags();
8972
tag.ShowAutocomplete = false;
9073
}
9174

0 commit comments

Comments
 (0)