WindowViewModel.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using System.Collections.ObjectModel;
  2. using System.Drawing;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using Avalonia.Input;
  6. using CommunityToolkit.Mvvm.Input;
  7. using PixiDocks.Core.Docking;
  8. using PixiEditor.AvaloniaUI.Models.Commands;
  9. using PixiEditor.AvaloniaUI.ViewModels.Document;
  10. using PixiEditor.AvaloniaUI.Views;
  11. using PixiEditor.AvaloniaUI.Views.Dialogs;
  12. using PixiEditor.AvaloniaUI.Views.Windows;
  13. using PixiEditor.UI.Common.Fonts;
  14. using Command = PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands.Command;
  15. using SettingsWindow = PixiEditor.AvaloniaUI.Views.Windows.Settings.SettingsWindow;
  16. namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
  17. #nullable enable
  18. [Command.Group("PixiEditor.Window", "WINDOWS")]
  19. internal class WindowViewModel : SubViewModel<ViewModelMain>
  20. {
  21. private CommandController commandController;
  22. private ShortcutsPopup? shortcutPopup;
  23. private ShortcutsPopup ShortcutsPopup => shortcutPopup ??= new(commandController);
  24. public RelayCommand<string> ShowAvalonDockWindowCommand { get; set; }
  25. public ObservableCollection<ViewportWindowViewModel> Viewports { get; } = new();
  26. public event EventHandler<ViewportWindowViewModel>? ActiveViewportChanged;
  27. public event Action<ViewportWindowViewModel> ViewportAdded;
  28. public event Action<ViewportWindowViewModel> ViewportClosed;
  29. private object? activeWindow;
  30. public object? ActiveWindow
  31. {
  32. get => activeWindow;
  33. set
  34. {
  35. if (activeWindow == value)
  36. return;
  37. activeWindow = value;
  38. OnPropertyChanged(nameof(ActiveWindow));
  39. if (activeWindow is ViewportWindowViewModel viewport)
  40. ActiveViewportChanged?.Invoke(this, viewport);
  41. }
  42. }
  43. public WindowViewModel(ViewModelMain owner, CommandController commandController)
  44. : base(owner)
  45. {
  46. ShowAvalonDockWindowCommand = new(ShowDockWindow);
  47. this.commandController = commandController;
  48. }
  49. [Command.Basic("PixiEditor.Window.CreateNewViewport", "NEW_WINDOW_FOR_IMG", "NEW_WINDOW_FOR_IMG",
  50. Icon = PixiPerfectIcons.PlusSquare, CanExecute = "PixiEditor.HasDocument",
  51. MenuItemPath = "VIEW/NEW_WINDOW_FOR_IMG", MenuItemOrder = 0)]
  52. public void CreateNewViewport()
  53. {
  54. var doc = ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument;
  55. if (doc is null)
  56. return;
  57. CreateNewViewport(doc);
  58. }
  59. [Command.Basic("PixiEditor.Window.CenterActiveViewport", "CENTER_ACTIVE_VIEWPORT", "CENTER_ACTIVE_VIEWPORT", CanExecute = "PixiEditor.HasDocument",
  60. Icon = PixiPerfectIcons.Center)]
  61. public void CenterCurrentViewport()
  62. {
  63. if (ActiveWindow is ViewportWindowViewModel viewport)
  64. viewport.CenterViewportTrigger.Execute(this, viewport.Document.SizeBindable);
  65. }
  66. [Command.Basic("PixiEditor.Window.FlipHorizontally", "FLIP_VIEWPORT_HORIZONTALLY", "FLIP_VIEWPORT_HORIZONTALLY", CanExecute = "PixiEditor.HasDocument",
  67. Icon = PixiPerfectIcons.YFlip)]
  68. public void FlipViewportHorizontally()
  69. {
  70. if (ActiveWindow is ViewportWindowViewModel viewport)
  71. {
  72. viewport.FlipX = !viewport.FlipX;
  73. }
  74. }
  75. [Command.Basic("PixiEditor.Window.FlipVertically", "FLIP_VIEWPORT_VERTICALLY", "FLIP_VIEWPORT_VERTICALLY", CanExecute = "PixiEditor.HasDocument",
  76. Icon = PixiPerfectIcons.XFlip)]
  77. public void FlipViewportVertically()
  78. {
  79. if (ActiveWindow is ViewportWindowViewModel viewport)
  80. {
  81. viewport.FlipY = !viewport.FlipY;
  82. }
  83. }
  84. public void CreateNewViewport(DocumentViewModel doc)
  85. {
  86. ViewportWindowViewModel newViewport = new ViewportWindowViewModel(this, doc);
  87. Viewports.Add(newViewport);
  88. foreach (var viewport in Viewports.Where(vp => vp.Document == doc))
  89. {
  90. viewport.IndexChanged();
  91. }
  92. ViewportAdded?.Invoke(newViewport);
  93. }
  94. public void MakeDocumentViewportActive(DocumentViewModel? doc)
  95. {
  96. if (doc is null)
  97. {
  98. ActiveWindow = null;
  99. Owner.DocumentManagerSubViewModel.MakeActiveDocumentNull();
  100. return;
  101. }
  102. ActiveWindow = Viewports.FirstOrDefault(viewport => viewport.Document == doc);
  103. }
  104. public string CalculateViewportIndex(ViewportWindowViewModel viewport)
  105. {
  106. ViewportWindowViewModel[] viewports = Viewports.Where(a => a.Document == viewport.Document).ToArray();
  107. if (viewports.Length < 2)
  108. return "";
  109. return $"[{Array.IndexOf(viewports, viewport) + 1}]";
  110. }
  111. public async Task<bool> OnViewportWindowCloseButtonPressed(ViewportWindowViewModel viewport)
  112. {
  113. var viewports = Viewports.Where(vp => vp.Document == viewport.Document).ToArray();
  114. if (viewports.Length == 1)
  115. {
  116. return await Owner.DisposeDocumentWithSaveConfirmation(viewport.Document);
  117. }
  118. Viewports.Remove(viewport);
  119. foreach (var sibling in viewports)
  120. {
  121. sibling.IndexChanged();
  122. }
  123. ViewportClosed?.Invoke(viewport);
  124. return true;
  125. }
  126. public void CloseViewportsForDocument(DocumentViewModel document)
  127. {
  128. var viewports = Viewports.Where(vp => vp.Document == document).ToArray();
  129. foreach (ViewportWindowViewModel viewport in viewports)
  130. {
  131. Viewports.Remove(viewport);
  132. ViewportClosed?.Invoke(viewport);
  133. }
  134. }
  135. [Command.Basic("PixiEditor.Window.OpenSettingsWindow", "OPEN_SETTINGS", "OPEN_SETTINGS_DESCRIPTIVE", Key = Key.OemComma, Modifiers = KeyModifiers.Control,
  136. MenuItemPath = "EDIT/SETTINGS", MenuItemOrder = 16, Icon = PixiPerfectIcons.Settings)]
  137. public static void OpenSettingsWindow(int page)
  138. {
  139. if (page < 0)
  140. {
  141. page = 0;
  142. }
  143. var settings = new SettingsWindow(page);
  144. settings.Show();
  145. }
  146. [Command.Basic("PixiEditor.Window.OpenStartupWindow", "OPEN_STARTUP_WINDOW", "OPEN_STARTUP_WINDOW",
  147. Icon = PixiPerfectIcons.Home, MenuItemPath = "VIEW/OPEN_STARTUP_WINDOW", MenuItemOrder = 1)]
  148. public void OpenHelloThereWindow()
  149. {
  150. new HelloTherePopup(Owner.FileSubViewModel).Show(MainWindow.Current);
  151. }
  152. [Command.Basic("PixiEditor.Window.OpenShortcutWindow", "OPEN_SHORTCUT_WINDOW", "OPEN_SHORTCUT_WINDOW", Key = Key.F1,
  153. Icon = PixiPerfectIcons.Book, MenuItemPath = "VIEW/OPEN_SHORTCUT_WINDOW", MenuItemOrder = 2)]
  154. public void ShowShortcutWindow()
  155. {
  156. ShortcutsPopup.Show();
  157. ShortcutsPopup.Activate();
  158. }
  159. [Command.Basic("PixiEditor.Window.OpenAboutWindow", "OPEN_ABOUT_WINDOW", "OPEN_ABOUT_WINDOW",
  160. Icon = PixiPerfectIcons.Info, MenuItemPath = "HELP/ABOUT", MenuItemOrder = 5)]
  161. public void OpenAboutWindow()
  162. {
  163. new AboutPopup().Show();
  164. }
  165. [Command.Internal("PixiEditor.Window.ShowDockWindow")]
  166. [Command.Basic("PixiEditor.Window.OpenNavigationWindow", "Navigator", "OPEN_NAVIGATION_WINDOW", "OPEN_NAVIGATION_WINDOW")]
  167. public void ShowDockWindow(string id)
  168. {
  169. Owner.LayoutSubViewModel.LayoutManager.ShowDockable(id);
  170. }
  171. }