Skip to content

Commit a969b09

Browse files
added reordering to context menu of unity projects
1 parent 14756b0 commit a969b09

File tree

5 files changed

+169
-59
lines changed

5 files changed

+169
-59
lines changed

UnityHubNative.Net/ControlsExtensions.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Avalonia.Controls.Primitives;
33
using Avalonia.Input;
44
using Avalonia.Interactivity;
5+
using FluentAvalonia.UI.Controls;
56

67
namespace UnityHubNative.Net;
78

@@ -110,6 +111,23 @@ public static MenuItem OnClick(this MenuItem menuItem, Action callback)
110111
return menuItem;
111112
}
112113

114+
public static MenuFlyoutItem OnClick(this MenuFlyoutItem menuItem, params Action[] callbacks)
115+
{
116+
for (int i = 0; i < callbacks.Length; i++)
117+
{
118+
int index = 0;
119+
menuItem.Click += (obj, args) => callbacks[index]();
120+
}
121+
122+
return menuItem;
123+
}
124+
125+
public static MenuFlyoutItem OnClick(this MenuFlyoutItem menuItem, Action callback)
126+
{
127+
menuItem.Click += (obj, args) => callback();
128+
return menuItem;
129+
}
130+
113131
public static T AddChildren<T>(this T control, params Control[] children) where T : Panel
114132
{
115133
control.Children.AddRange(children);
@@ -130,6 +148,13 @@ public static MenuItem AddItems(this MenuItem menu, params MenuItem[] menuItems)
130148
return menu;
131149
}
132150

151+
public static MenuFlyout AddItems(this MenuFlyout menu, params MenuItem[] menuItems)
152+
{
153+
for (int i = 0; i < menuItems.Length; i++)
154+
menu.Items.Add(menuItems[i]);
155+
return menu;
156+
}
157+
133158
public static T1 AddItems<T1, T2>(this T1 menu, T2[] items) where T1 : NativeMenu where T2 : NativeMenuItemBase
134159
{
135160
for (int i = 0; i < items.Length; i++)
@@ -204,4 +229,11 @@ public static T OnTextChanged<T>(this T control, Action action) where T : Contro
204229
control.SizeChanged += (_, e) => action();
205230
return control;
206231
}
232+
233+
public static T OnOpening<T>(this T menu, Action<object, T> action) where T : MenuFlyout
234+
{
235+
menu.Opened += (src, args) => action?.Invoke((object)args, (T)src);
236+
menu.Opening += (src, args) => action?.Invoke((object)args, (T)src);
237+
return menu;
238+
}
207239
}

UnityHubNative.Net/MainWindow.cs

Lines changed: 94 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -86,34 +86,88 @@ protected override void OnOpened(EventArgs e)
8686
s_unityProjectsParent.ContainerFromIndex(0)!.Focus();
8787
}
8888

89-
void SetupBackground()
89+
public static void ReloadEverything()
9090
{
91-
if (UnityHubNativeNetApp.Config.transparent)
92-
{
93-
TransparencyLevelHint =
94-
[
95-
UnityHubNativeNetApp.Config.acrylic ? WindowTransparencyLevel.AcrylicBlur : WindowTransparencyLevel.Mica,
96-
WindowTransparencyLevel.Blur,
97-
];
98-
#if Windows
91+
UnityHubUtils.LoadAll();
92+
UpdateUnityVersionViews();
93+
UpdateUnitySearchPathViews();
94+
UpdateUnityProjectViews();
95+
}
9996

100-
Background = UnityHubNativeNetApp.Config.acrylic
101-
? new SolidColorBrush(
102-
ActualThemeVariant == Avalonia.Styling.ThemeVariant.Dark ? Colors.Black : Colors.White,
103-
1 - UnityHubNativeNetApp.Config.blurIntensity)
104-
: Brushes.Transparent;
105-
#endif
106-
}
97+
public static void OnOpenWithClicked()
98+
{
99+
var dialogue = new OpenWithDialogue(UnityHubUtils.UnityProjects[GetUnityProjectSelectedIndex()]);
100+
dialogue.ShowDialog(Instance);
107101
}
108102

109-
static void ReloadEverything()
103+
public static void OnRemoveProjectFromListClicked()
110104
{
111-
UnityHubUtils.LoadAll();
112-
UpdateUnityVersionViews();
113-
UpdateUnitySearchPathViews();
105+
UnityHubUtils.UnityProjects.RemoveAt(GetUnityProjectSelectedIndex());
106+
UnityHubUtils.SaveUnityProjects();
107+
UnityHubUtils.LoadUnityProjects();
114108
UpdateUnityProjectViews();
115109
}
116110

111+
public static void UpdateUnityVersionViews()
112+
{
113+
SyncListBoxWithView<UnityInstallation, UnityInstallationView>(s_unityInstallationsParent, UnityHubUtils.UnityInstallations);
114+
115+
for (int i = 0; i < UnityHubUtils.UnityInstallations.Count; i++)
116+
((UnityInstallationView)s_unityInstallationsParent.Items[i]!).Update(UnityHubUtils.UnityInstallations[i]);
117+
}
118+
119+
public static void UpdateUnitySearchPathViews()
120+
{
121+
SyncListBoxWithView<string, UnityInstallationSearchPathView>(s_unityInstalltionSearchPathsParent, UnityHubUtils.UnityInstallationSearchPaths);
122+
123+
for (int i = 0; i < UnityHubUtils.UnityInstallationSearchPaths.Count; i++)
124+
((UnityInstallationSearchPathView)s_unityInstalltionSearchPathsParent.Items[i]!).Update(UnityHubUtils.UnityInstallationSearchPaths[i]);
125+
}
126+
127+
public static void UpdateUnityProjectViews()
128+
{
129+
SyncListBoxWithView<UnityProject, UnityProjectView>(s_unityProjectsParent, UnityHubUtils.UnityProjects);
130+
131+
for (int i = 0; i < UnityHubUtils.UnityProjects.Count; i++)
132+
((UnityProjectView)s_unityProjectsParent.Items[i]!).Update(UnityHubUtils.UnityProjects[i]);
133+
}
134+
135+
public static void MoveUnityProjectUp(UnityProject unityProject)
136+
{
137+
if (unityProject is null)
138+
return;
139+
var ind = UnityHubUtils.UnityProjects.IndexOf(unityProject);
140+
if (ind == -1)
141+
return;
142+
if (ind == UnityHubUtils.UnityProjects.Count - 1)
143+
return;
144+
UnityHubUtils.UnityProjects.RemoveAt(ind);
145+
UnityHubUtils.UnityProjects.Insert(ind + 1, unityProject);
146+
UnityHubUtils.SaveUnityProjects();
147+
(s_unityProjectsParent.Items[ind], s_unityProjectsParent.Items[ind + 1]) = (s_unityProjectsParent.Items[ind + 1], s_unityProjectsParent.Items[ind]);
148+
s_unityProjectsParent.SelectedIndex = ind + 1;
149+
((UnityProjectView)s_unityProjectsParent.Items[ind]).Update(UnityHubUtils.UnityProjects[ind]);
150+
((UnityProjectView)s_unityProjectsParent.Items[ind + 1]).Update(UnityHubUtils.UnityProjects[ind + 1]);
151+
}
152+
153+
public static void MoveUnityProjectDown(UnityProject unityProject)
154+
{
155+
if (unityProject is null)
156+
return;
157+
var ind = UnityHubUtils.UnityProjects.IndexOf(unityProject);
158+
if (ind == -1)
159+
return;
160+
if (ind == 0)
161+
return;
162+
UnityHubUtils.UnityProjects.RemoveAt(ind);
163+
UnityHubUtils.UnityProjects.Insert(ind - 1, unityProject);
164+
UnityHubUtils.SaveUnityProjects();
165+
(s_unityProjectsParent.Items[ind], s_unityProjectsParent.Items[ind - 1]) = (s_unityProjectsParent.Items[ind - 1], s_unityProjectsParent.Items[ind]);
166+
s_unityProjectsParent.SelectedIndex = ind - 1;
167+
((UnityProjectView)s_unityProjectsParent.Items[ind]).Update(UnityHubUtils.UnityProjects[ind]);
168+
((UnityProjectView)s_unityProjectsParent.Items[ind - 1]).Update(UnityHubUtils.UnityProjects[ind - 1]);
169+
}
170+
117171
static Control CreateContent() => new DockPanel
118172
{
119173
LastChildFill = true,
@@ -655,50 +709,12 @@ static async void OnAddExistingProjectClicked()
655709
}
656710
}
657711

658-
static void OnOpenWithClicked()
659-
{
660-
var dialogue = new OpenWithDialogue(UnityHubUtils.UnityProjects[GetUnityProjectSelectedIndex()]);
661-
dialogue.ShowDialog(Instance);
662-
}
663-
664712
static void OnCreateNewProjectClicked() => new CreateNewProjectDialogue().ShowDialog(Instance);
665713

666-
static void OnRemoveProjectFromListClicked()
667-
{
668-
UnityHubUtils.UnityProjects.RemoveAt(GetUnityProjectSelectedIndex());
669-
UnityHubUtils.SaveUnityProjects();
670-
UnityHubUtils.LoadUnityProjects();
671-
UpdateUnityProjectViews();
672-
}
673-
674714
static void OnRevealProjectClicked() => OsUtils.OpenExplorer(UnityHubUtils.UnityProjects[GetUnityProjectSelectedIndex()].path);
675715

676716
static void OnAboutClicked(MenuItem item, RoutedEventArgs args) => new AboutDialogue().ShowDialog(Instance);
677717

678-
static void UpdateUnityVersionViews()
679-
{
680-
SyncListBoxWithView<UnityInstallation, UnityInstallationView>(s_unityInstallationsParent, UnityHubUtils.UnityInstallations);
681-
682-
for (int i = 0; i < UnityHubUtils.UnityInstallations.Count; i++)
683-
((UnityInstallationView)s_unityInstallationsParent.Items[i]!).Update(UnityHubUtils.UnityInstallations[i]);
684-
}
685-
686-
static void UpdateUnitySearchPathViews()
687-
{
688-
SyncListBoxWithView<string, UnityInstallationSearchPathView>(s_unityInstalltionSearchPathsParent, UnityHubUtils.UnityInstallationSearchPaths);
689-
690-
for (int i = 0; i < UnityHubUtils.UnityInstallationSearchPaths.Count; i++)
691-
((UnityInstallationSearchPathView)s_unityInstalltionSearchPathsParent.Items[i]!).Update(UnityHubUtils.UnityInstallationSearchPaths[i]);
692-
}
693-
694-
static void UpdateUnityProjectViews()
695-
{
696-
SyncListBoxWithView<UnityProject, UnityProjectView>(s_unityProjectsParent, UnityHubUtils.UnityProjects);
697-
698-
for (int i = 0; i < UnityHubUtils.UnityProjects.Count; i++)
699-
((UnityProjectView)s_unityProjectsParent.Items[i]!).Update(UnityHubUtils.UnityProjects[i]);
700-
}
701-
702718
static void SyncListBoxWithView<TItem, TView>(ListBox parent, List<TItem> items) where TView : new()
703719
{
704720
// update
@@ -720,5 +736,25 @@ static void ShowTbiDialogue()
720736
{
721737
_ = MessageBoxManager.GetMessageBoxStandard("To be implemented", "Not implemented yet", MsBox.Avalonia.Enums.ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Warning).ShowWindowDialogAsync(Instance);
722738
}
739+
740+
void SetupBackground()
741+
{
742+
if (UnityHubNativeNetApp.Config.transparent)
743+
{
744+
TransparencyLevelHint =
745+
[
746+
UnityHubNativeNetApp.Config.acrylic ? WindowTransparencyLevel.AcrylicBlur : WindowTransparencyLevel.Mica,
747+
WindowTransparencyLevel.Blur,
748+
];
749+
#if Windows
750+
751+
Background = UnityHubNativeNetApp.Config.acrylic
752+
? new SolidColorBrush(
753+
ActualThemeVariant == Avalonia.Styling.ThemeVariant.Dark ? Colors.Black : Colors.White,
754+
1 - UnityHubNativeNetApp.Config.blurIntensity)
755+
: Brushes.Transparent;
756+
#endif
757+
}
758+
}
723759
}
724760

UnityHubNative.Net/SubmitableListBox.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ class SubmitableListBox : ListBox
2626
protected override void OnPointerReleased(PointerReleasedEventArgs e)
2727
{
2828
base.OnPointerReleased(e);
29-
OnSubmit?.Invoke();
29+
if (e.InitialPressMouseButton == MouseButton.Left)
30+
{
31+
OnSubmit?.Invoke();
32+
e.Handled = true;
33+
}
3034
}
3135

3236
protected override void OnKeyDown(KeyEventArgs e)

UnityHubNative.Net/UnityHubUtils.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ class UnityProject(string path, DateTime lastModifiedDate, UnityInstallation? un
238238

239239
public override string ToString() => $"{{\"{path}\", \"{name}\", {unity}}}";
240240

241+
public override bool Equals(object? obj) => obj is UnityProject project && project.path == path;
242+
241243
public static bool TryLoadUnityProject(string path, out UnityProject result)
242244
{
243245
try

UnityHubNative.Net/UnityProjectView.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
using Avalonia.Controls;
33
using Avalonia.Layout;
44
using Avalonia.Media;
5+
using FluentAvalonia.UI.Controls;
56

67
namespace UnityHubNative.Net;
78

89
internal sealed class UnityProjectView : Panel
910
{
1011
public UnityProject unityProject;
12+
private MenuItem _moveUpMenuItem;
13+
private MenuItem _moveDownMenuItem;
1114
readonly ComboBox _unityVersionComboBox;
1215
readonly TextBlock _titleTextBlock;
1316
readonly TextBlock _pathTextBlock;
@@ -22,6 +25,32 @@ public UnityProjectView() : base()
2225
([
2326
new Border
2427
{
28+
Background = Brushes.Transparent,
29+
ContextFlyout = new MenuFlyout
30+
{
31+
}.AddItems
32+
([
33+
new MenuItem
34+
{
35+
Header = "Open"
36+
}.OnClick(OpenProject),
37+
new MenuItem
38+
{
39+
Header = "Open With",
40+
}.OnClick(MainWindow.OnOpenWithClicked),
41+
new MenuItem
42+
{
43+
Header = "Remove From List",
44+
}.OnClick(MainWindow.OnRemoveProjectFromListClicked),
45+
_moveUpMenuItem = new MenuItem
46+
{
47+
Header = "Move Up In List",
48+
}.OnClick(OnMoveUpClicked),
49+
_moveDownMenuItem = new MenuItem
50+
{
51+
Header = "Move Down In List",
52+
}.OnClick(OnMoveDownClicked),
53+
]),
2554
ClipToBounds = false,
2655
Child = new DockPanel
2756
{
@@ -62,6 +91,10 @@ public UnityProjectView() : base()
6291
ActualThemeVariantChanged += (_, _) => UpdateUnityVersionWarning();
6392
}
6493

94+
private void OnMoveDownClicked() => MainWindow.MoveUnityProjectUp(unityProject);
95+
96+
private void OnMoveUpClicked() => MainWindow.MoveUnityProjectDown(unityProject);
97+
6598
private void OnPathLinkClicked()
6699
{
67100
OsUtils.OpenExplorer(unityProject.path);
@@ -93,6 +126,9 @@ void DropDownClosed(object? sender, EventArgs e)
93126
public void Update(UnityProject unityProject)
94127
{
95128
this.unityProject = unityProject;
129+
var index = UnityHubUtils.UnityProjects.IndexOf(unityProject);
130+
_moveDownMenuItem.IsEnabled = index >= 0 && index < UnityHubUtils.UnityProjects.Count - 1;
131+
_moveUpMenuItem.IsEnabled = index > 0 && index < UnityHubUtils.UnityProjects.Count;
96132
_titleTextBlock.Text = unityProject.name;
97133
_pathTextBlock.Text = unityProject.path;
98134
_unityVersionComboBox.SelectedIndex = unityProject.unity.HasValue

0 commit comments

Comments
 (0)