forked from LykosAI/StabilityMatrix
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFADownloadableComboBox.cs
More file actions
133 lines (111 loc) · 4.2 KB
/
FADownloadableComboBox.cs
File metadata and controls
133 lines (111 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
using CommunityToolkit.Mvvm.Input;
using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.DependencyInjection;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Models;
namespace StabilityMatrix.Avalonia.Controls;
// ReSharper disable once InconsistentNaming
public partial class FADownloadableComboBox : FAComboBox
{
protected override Type StyleKeyOverride => typeof(FAComboBox);
private Popup? dropDownPopup;
private IDisposable? openSubscription;
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
CleanupSubscription();
DropDownOpened -= OnDropDownOpenedHandler;
DropDownClosed -= OnDropDownClosedHandler;
// Template part name is "Popup" per FAComboBox.properties.cs (s_tpPopup = "Popup")
dropDownPopup = e.NameScope.Find<Popup>("Popup");
DropDownOpened += OnDropDownOpenedHandler;
DropDownClosed += OnDropDownClosedHandler;
}
private void OnDropDownOpenedHandler(object? sender, EventArgs e)
{
CleanupSubscription();
if (dropDownPopup?.Child is not Control popupChild)
return;
var scrollViewer = popupChild.GetVisualDescendants().OfType<ScrollViewer>().FirstOrDefault();
if (scrollViewer == null)
return;
// On Unix-like systems, overlay popups share the same TopLevel visual root as the main window.
// FAComboBox.OnPopupOpened adds a TopLevel tunnel handler that marks all wheel eventsas handled while the dropdown is open,
// which inadvertently blocks scroll-wheelevents in popup menus in Inference model cards.
// Resetting e.Handled on the ScrollViewer's tunnel phase counters this.
if (!Compat.IsUnix)
return;
openSubscription = scrollViewer.AddDisposableHandler(
PointerWheelChangedEvent,
static (_, ev) =>
{
if (ev.Handled)
ev.Handled = false;
},
RoutingStrategies.Tunnel,
handledEventsToo: true
);
}
private void OnDropDownClosedHandler(object? sender, EventArgs e)
{
CleanupSubscription();
}
private void CleanupSubscription()
{
openSubscription?.Dispose();
openSubscription = null;
}
static FADownloadableComboBox()
{
SelectionChangedEvent.AddClassHandler<FADownloadableComboBox>(
(comboBox, args) => comboBox.OnSelectionChanged(args)
);
}
protected virtual void OnSelectionChanged(SelectionChangedEventArgs e)
{
// On downloadable added
if (e.AddedItems.Count > 0 && e.AddedItems[0] is IDownloadableResource { IsDownloadable: true } item)
{
// Reset the selection
e.Handled = true;
if (
e.RemovedItems.Count > 0
&& e.RemovedItems[0] is IDownloadableResource { IsDownloadable: false } removedItem
)
{
SelectedItem = removedItem;
}
else
{
SelectedItem = null;
}
// Show dialog to download the model
PromptDownloadCommand.ExecuteAsync(item).SafeFireAndForget();
}
}
[RelayCommand]
private static async Task PromptDownloadAsync(IDownloadableResource downloadable)
{
if (downloadable.DownloadableResource is not { } resource)
return;
var vmFactory = App.Services.GetRequiredService<IServiceManager<ViewModelBase>>();
var confirmDialog = vmFactory.Get<DownloadResourceViewModel>();
confirmDialog.Resource = resource;
confirmDialog.FileName = resource.FileName;
if (await confirmDialog.GetDialog().ShowAsync() == ContentDialogResult.Primary)
{
confirmDialog.StartDownload();
}
}
}