Skip to content

Commit 58a618e

Browse files
committed
🐛 Temporary solution for #15
1 parent b510c8f commit 58a618e

File tree

3 files changed

+131
-6
lines changed

3 files changed

+131
-6
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Avalonia.Controls;
4+
using Avalonia.Interactivity;
5+
using Avalonia.Xaml.Interactivity;
6+
7+
//https://github.com/AvaloniaUI/Avalonia/discussions/13301
8+
namespace CloudlogHelper.Behaviours
9+
{
10+
public class AutoCompleteZeroMinimumPrefixLengthDropdownBehaviour : Behavior<AutoCompleteBox>
11+
{
12+
static AutoCompleteZeroMinimumPrefixLengthDropdownBehaviour()
13+
{
14+
}
15+
16+
protected override void OnAttached()
17+
{
18+
if (AssociatedObject is not null)
19+
{
20+
AssociatedObject.KeyUp += OnKeyUp;
21+
AssociatedObject.DropDownOpening += DropDownOpening;
22+
AssociatedObject.GotFocus += OnGotFocus;
23+
24+
Task.Delay(500).ContinueWith(_ => Avalonia.Threading.Dispatcher.UIThread.Invoke(() => { CreateDropdownButton(); }));
25+
}
26+
27+
base.OnAttached();
28+
}
29+
30+
protected override void OnDetaching()
31+
{
32+
if (AssociatedObject is not null)
33+
{
34+
AssociatedObject.KeyUp -= OnKeyUp;
35+
AssociatedObject.DropDownOpening -= DropDownOpening;
36+
AssociatedObject.GotFocus -= OnGotFocus;
37+
}
38+
39+
base.OnDetaching();
40+
}
41+
42+
//have to use KeyUp as AutoCompleteBox eats some of the KeyDown events
43+
private void OnKeyUp(object? sender, Avalonia.Input.KeyEventArgs e)
44+
{
45+
if ((e.Key == Avalonia.Input.Key.Down || e.Key == Avalonia.Input.Key.F4))
46+
{
47+
if (string.IsNullOrEmpty(AssociatedObject?.Text))
48+
{
49+
ShowDropdown();
50+
}
51+
}
52+
}
53+
54+
private void DropDownOpening(object? sender, System.ComponentModel.CancelEventArgs e)
55+
{
56+
var prop = AssociatedObject?.GetType().GetProperty("TextBox", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
57+
var tb = (TextBox?)prop?.GetValue(AssociatedObject);
58+
if (tb is not null && tb.IsReadOnly)
59+
{
60+
e.Cancel = true;
61+
return;
62+
}
63+
}
64+
65+
private void ShowDropdown()
66+
{
67+
if (AssociatedObject is not null && !AssociatedObject.IsDropDownOpen)
68+
{
69+
typeof(AutoCompleteBox).GetMethod("PopulateDropDown", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.Invoke(AssociatedObject, new object[] { AssociatedObject, EventArgs.Empty });
70+
typeof(AutoCompleteBox).GetMethod("OpeningDropDown", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.Invoke(AssociatedObject, new object[] { false });
71+
72+
if (!AssociatedObject.IsDropDownOpen)
73+
{
74+
//We *must* set the field and not the property as we need to avoid the changed event being raised (which prevents the dropdown opening).
75+
var ipc = typeof(AutoCompleteBox).GetField("_ignorePropertyChange", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
76+
if ((bool)ipc?.GetValue(AssociatedObject) == false)
77+
ipc?.SetValue(AssociatedObject, true);
78+
79+
AssociatedObject.SetCurrentValue<bool>(AutoCompleteBox.IsDropDownOpenProperty, true);
80+
}
81+
}
82+
}
83+
84+
private void CreateDropdownButton()
85+
{
86+
if (AssociatedObject != null)
87+
{
88+
var prop = AssociatedObject.GetType().GetProperty("TextBox", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
89+
var tb = (TextBox?)prop?.GetValue(AssociatedObject);
90+
if (tb is not null && tb.InnerRightContent is not Button)
91+
{
92+
var btn = new Button()
93+
{
94+
/* grab symbol from https://www.amp-what.com/unicode/search/down */
95+
Content = "⯆",
96+
Margin = new(3),
97+
ClickMode = ClickMode.Press
98+
};
99+
btn.Click += (s, e) =>
100+
{
101+
AssociatedObject.Text = string.Empty;
102+
ShowDropdown();
103+
};
104+
105+
tb.InnerRightContent = btn;
106+
}
107+
}
108+
}
109+
110+
private void OnGotFocus(object? sender, RoutedEventArgs e)
111+
{
112+
if (AssociatedObject != null)
113+
{
114+
CreateDropdownButton();
115+
}
116+
}
117+
}
118+
}

src/CloudlogHelper/ViewModels/SettingsWindowViewModel.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ public SettingsWindowViewModel(CommandLineOptions cmd,
175175
}).DisposeWith(disposables);
176176

177177
// refresh hamlib lib after fully inited
178-
Observable.Return(Unit.Default)
179-
.InvokeCommand(RefreshPort)
180-
.DisposeWith(disposables);
178+
// Observable.Return(Unit.Default)
179+
// .InvokeCommand(RefreshPort)
180+
// .DisposeWith(disposables);
181181
});
182182

183183
FullyInitialized = false;

src/CloudlogHelper/Views/SettingsWindow.axaml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
xmlns:userControls1="clr-namespace:CloudlogHelper.Views.UserControls"
99
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
1010
xmlns:avaloniaProgressRing="clr-namespace:AvaloniaProgressRing;assembly=AvaloniaProgressRing"
11+
xmlns:behaviours="clr-namespace:CloudlogHelper.Behaviours"
1112
mc:Ignorable="d"
1213
d:DesignWidth="700" d:DesignHeight="700"
1314
x:DataType="viewModels:SettingsWindowViewModel"
@@ -311,9 +312,15 @@
311312
IsEnabled="{Binding !#externalRigctld.IsChecked}" />
312313
<StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="1" Spacing="8"
313314
IsEnabled="{Binding !#externalRigctld.IsChecked}">
314-
<ComboBox Classes="setting-control"
315-
SelectedItem="{Binding DraftSettings.HamlibSettings.SelectedPort}"
316-
ItemsSource="{Binding Ports}" />
315+
<AutoCompleteBox Classes="setting-control"
316+
IsTextCompletionEnabled="False"
317+
MinWidth="200"
318+
Text="{Binding DraftSettings.HamlibSettings.SelectedPort}"
319+
ItemsSource="{Binding Ports}" >
320+
<Interaction.Behaviors>
321+
<behaviours:AutoCompleteZeroMinimumPrefixLengthDropdownBehaviour/>
322+
</Interaction.Behaviors>
323+
</AutoCompleteBox>
317324
<Button Command="{Binding RefreshPort}" CornerRadius="4"
318325
Content="{avalonia:MaterialIconExt Kind=Refresh}"
319326
Width="32" Height="32" />

0 commit comments

Comments
 (0)