TitleManager.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. using ImageMagick;
  2. using PicView.Avalonia.ImageHandling;
  3. using PicView.Avalonia.Navigation;
  4. using PicView.Avalonia.ViewModels;
  5. using PicView.Core.FileHandling;
  6. using PicView.Core.ImageDecoding;
  7. using PicView.Core.Localization;
  8. using PicView.Core.Navigation;
  9. namespace PicView.Avalonia.UI;
  10. public static class TitleManager
  11. {
  12. /// <summary>
  13. /// Sets the title of the window and the title displayed in the UI to the appropriate
  14. /// value based on the current state of the application.
  15. /// </summary>
  16. /// <param name="vm">The main view model instance.</param>
  17. /// <remarks>Can be used to refresh the title when files are added or removed.</remarks>
  18. public static void SetTitle(MainViewModel vm)
  19. {
  20. if (!NavigationManager.CanNavigate(vm))
  21. {
  22. string title;
  23. var s = vm.Title;
  24. if (!string.IsNullOrWhiteSpace(s.GetURL()))
  25. {
  26. title = vm.Title.GetURL();
  27. }
  28. else if (s.Contains(TranslationManager.Translation.Base64Image))
  29. {
  30. title = TranslationManager.Translation.Base64Image;
  31. }
  32. else
  33. {
  34. title = TranslationManager.Translation.ClipboardImage!;
  35. }
  36. var singleImageWindowTitles =
  37. ImageTitleFormatter.GenerateTitleForSingleImage(vm.PicViewer.PixelWidth, vm.PicViewer.PixelWidth, title, vm.ZoomValue);
  38. vm.WindowTitle = singleImageWindowTitles.BaseTitle;
  39. vm.Title = singleImageWindowTitles.TitleWithAppName;
  40. vm.TitleTooltip = singleImageWindowTitles.TitleWithAppName;
  41. return;
  42. }
  43. if (NavigationManager.TiffNavigationInfo is not null)
  44. {
  45. SetTiffTitle(NavigationManager.TiffNavigationInfo, vm.PicViewer.PixelWidth, vm.PicViewer.PixelHeight,
  46. NavigationManager.GetCurrentIndex, vm.PicViewer.FileInfo, vm);
  47. return;
  48. }
  49. if (Settings.ImageScaling.ShowImageSideBySide)
  50. {
  51. var imageModel1 = new ImageModel
  52. {
  53. FileInfo = vm.PicViewer.FileInfo,
  54. PixelWidth = vm.PicViewer.PixelWidth,
  55. PixelHeight = vm.PicViewer.PixelHeight
  56. };
  57. var nextFileName = NavigationManager.GetNextFileName;
  58. using var magickImage = new MagickImage();
  59. magickImage.Ping(nextFileName);
  60. var imageModel2 = new ImageModel
  61. {
  62. FileInfo = new FileInfo(nextFileName),
  63. PixelWidth = (int)magickImage.Width,
  64. PixelHeight = (int)magickImage.Height
  65. };
  66. SetSideBySideTitle(vm, imageModel1, imageModel2);
  67. return;
  68. }
  69. var windowTitles = ImageTitleFormatter.GenerateTitleStrings(vm.PicViewer.PixelWidth, vm.PicViewer.PixelHeight,
  70. NavigationManager.GetCurrentIndex,
  71. vm.PicViewer.FileInfo, vm.ZoomValue, NavigationManager.GetCollection);
  72. vm.WindowTitle = windowTitles.TitleWithAppName;
  73. vm.Title = windowTitles.BaseTitle;
  74. vm.TitleTooltip = windowTitles.FilePathTitle;
  75. }
  76. /// <summary>
  77. /// Sets the title of the window and the title displayed in the UI
  78. /// to a temporary "Loading..." title while the application is loading current image.
  79. /// </summary>
  80. /// <param name="vm">The main view model instance.</param>
  81. public static void SetLoadingTitle(MainViewModel vm)
  82. {
  83. vm.WindowTitle = $"{TranslationManager.Translation.Loading} - PicView";
  84. vm.Title = TranslationManager.Translation.Loading;
  85. vm.TitleTooltip = vm.Title;
  86. }
  87. /// <summary>
  88. /// Sets the window title and UI title based on the provided image model.
  89. /// </summary>
  90. /// <param name="vm">The main view model instance.</param>
  91. /// <param name="imageModel">The image model containing information about the current image.</param>
  92. /// <remarks>If the image model or its file info is null, an error message is set as the title.</remarks>
  93. public static void SetTitle(MainViewModel vm, ImageModel? imageModel)
  94. {
  95. if (!ValidateImageModel(imageModel, vm))
  96. {
  97. if (vm.PicViewer.FileInfo is null)
  98. {
  99. ReturnError(vm);
  100. return;
  101. }
  102. imageModel = new ImageModel
  103. {
  104. FileInfo = vm.PicViewer.FileInfo,
  105. PixelWidth = vm.PicViewer.PixelWidth,
  106. PixelHeight = vm.PicViewer.PixelHeight
  107. };
  108. }
  109. var windowTitles = ImageTitleFormatter.GenerateTitleStrings(imageModel.PixelWidth, imageModel.PixelHeight,
  110. NavigationManager.GetCurrentIndex,
  111. imageModel.FileInfo, vm.ZoomValue, NavigationManager.GetCollection);
  112. vm.WindowTitle = windowTitles.TitleWithAppName;
  113. vm.Title = windowTitles.BaseTitle;
  114. vm.TitleTooltip = windowTitles.FilePathTitle;
  115. }
  116. /// <summary>
  117. /// Sets the title of the window and the title displayed in the UI
  118. /// based on the provided TIFF navigation info and image model.
  119. /// </summary>
  120. /// <param name="tiffNavigationInfo">The TIFF navigation info object.</param>
  121. /// <param name="width">The width of the image in pixels.</param>
  122. /// <param name="height">The height of the image in pixels.</param>
  123. /// <param name="index">The index of the image in the list.</param>
  124. /// <param name="fileInfo">The FileInfo object representing the image file.</param>
  125. /// <param name="vm">The main view model instance.</param>
  126. /// <remarks>
  127. /// This method is used to set the title of the window and the title displayed in the UI
  128. /// for TIFF images. The image title is generated using the TIFF navigation info and image model.
  129. /// </remarks>
  130. public static void SetTiffTitle(TiffManager.TiffNavigationInfo tiffNavigationInfo, int width, int height, int index,
  131. FileInfo fileInfo, MainViewModel vm)
  132. {
  133. var singeImageWindowTitles = ImageTitleFormatter.GenerateTiffTitleStrings(width, height, index, fileInfo,
  134. tiffNavigationInfo, 1, NavigationManager.GetCollection);
  135. vm.WindowTitle = singeImageWindowTitles.TitleWithAppName;
  136. vm.Title = singeImageWindowTitles.BaseTitle;
  137. vm.TitleTooltip = singeImageWindowTitles.BaseTitle;
  138. }
  139. /// <summary>
  140. /// Sets the title of the window and the title displayed in the UI
  141. /// based on the provided image model and main view model instance.
  142. /// If the image is a TIFF with multiple pages, the title is generated
  143. /// using the TIFF navigation info and image model. Otherwise, the single
  144. /// image title is generated using the image model.
  145. /// </summary>
  146. /// <param name="imageModel">The image model containing the image information.</param>
  147. /// <param name="vm">The main view model instance.</param>
  148. /// <remarks>
  149. /// This method is used to set the title of the window and the title displayed in the UI
  150. /// for TIFF images with multiple pages. If the image is not a TIFF with multiple pages,
  151. /// the single image title is generated using the image model.
  152. /// </remarks>
  153. public static void TrySetTiffTitle(ImageModel? imageModel, MainViewModel vm)
  154. {
  155. if (!ValidateImageModel(imageModel, vm))
  156. {
  157. return;
  158. }
  159. if (TiffManager.GetTiffPageCount(imageModel.FileInfo.FullName) is { } pageCount and > 1)
  160. {
  161. var tiffNavigationInfo = new TiffManager.TiffNavigationInfo
  162. {
  163. CurrentPage = 0,
  164. PageCount = pageCount,
  165. Pages = TiffManager.LoadTiffPages(imageModel.FileInfo.FullName)
  166. };
  167. SetTiffTitle(tiffNavigationInfo, imageModel.PixelWidth, imageModel.PixelHeight,
  168. NavigationManager.GetCurrentIndex, imageModel.FileInfo, vm);
  169. }
  170. else
  171. {
  172. SetTitle(vm, imageModel);
  173. }
  174. }
  175. /// <summary>
  176. /// Sets the title of the window and the title displayed in the UI when showing two images side by side.
  177. /// </summary>
  178. /// <param name="vm">The main view model instance.</param>
  179. /// <param name="imageModel1">The first image model containing the image information.</param>
  180. /// <param name="imageModel2">The second image model containing the image information.</param>
  181. /// <remarks>
  182. /// This method is used to set the title of the window and the title displayed in the UI.
  183. /// The title is a combination of the titles of the two images.
  184. /// </remarks>
  185. public static void SetSideBySideTitle(MainViewModel vm, ImageModel? imageModel1, ImageModel? imageModel2)
  186. {
  187. // Fix image models, which can be null caused by race conditions?
  188. if (!ValidateImageModel(imageModel1, vm))
  189. {
  190. if (vm.PicViewer.FileInfo is null)
  191. {
  192. return;
  193. }
  194. imageModel1 = new ImageModel
  195. {
  196. FileInfo = vm.PicViewer.FileInfo,
  197. PixelWidth = vm.PicViewer.PixelWidth,
  198. PixelHeight = vm.PicViewer.PixelHeight
  199. };
  200. }
  201. if (!ValidateImageModel(imageModel2, vm))
  202. {
  203. if (!NavigationManager.CanNavigate(vm))
  204. {
  205. return;
  206. }
  207. var nextFileName = NavigationManager.GetNextFileName;
  208. if (string.IsNullOrWhiteSpace(nextFileName))
  209. {
  210. return;
  211. }
  212. using var magickImage = new MagickImage();
  213. magickImage.Ping(nextFileName);
  214. imageModel2 = new ImageModel
  215. {
  216. FileInfo = new FileInfo(nextFileName),
  217. PixelWidth = (int)magickImage.Width,
  218. PixelHeight = (int)magickImage.Height
  219. };
  220. }
  221. var firstWindowTitles = ImageTitleFormatter.GenerateTitleStrings(imageModel1.PixelWidth,
  222. imageModel1.PixelHeight, NavigationManager.GetCurrentIndex,
  223. imageModel1.FileInfo, vm.ZoomValue, NavigationManager.GetCollection);
  224. var secondWindowTitles = ImageTitleFormatter.GenerateTitleStrings(imageModel2.PixelWidth,
  225. imageModel2.PixelHeight, NavigationManager.GetNextIndex,
  226. imageModel2.FileInfo, vm.ZoomValue, NavigationManager.GetCollection);
  227. var windowTitle = $"{firstWindowTitles.BaseTitle} \u21dc || \u21dd {secondWindowTitles.BaseTitle} - PicView";
  228. var title = $"{firstWindowTitles.BaseTitle} \u21dc || \u21dd {secondWindowTitles.BaseTitle}";
  229. var titleTooltip = $"{firstWindowTitles.FilePathTitle} \u21dc || \u21dd {secondWindowTitles.FilePathTitle}";
  230. vm.WindowTitle = windowTitle;
  231. vm.Title = title;
  232. vm.TitleTooltip = titleTooltip;
  233. }
  234. /// <summary>
  235. /// Sets the window title and UI title to indicate no image is available.
  236. /// </summary>
  237. /// <param name="vm">The main view model instance.</param>
  238. /// <remarks>
  239. /// This method sets the title, window title, and tooltip to a default message
  240. /// indicating that no image is currently loaded or available.
  241. /// </remarks>
  242. public static void SetNoImageTitle(MainViewModel vm)
  243. {
  244. vm.Title = TranslationManager.Translation.NoImage;
  245. vm.WindowTitle = TranslationManager.Translation.NoImage + " - PicView";
  246. vm.TitleTooltip = TranslationManager.Translation.NoImage;
  247. }
  248. private static void ReturnError(MainViewModel vm)
  249. {
  250. vm.WindowTitle =
  251. vm.Title =
  252. vm.TitleTooltip = TranslationManager.GetTranslation("UnableToRender");
  253. }
  254. private static bool ValidateImageModel(ImageModel? imageModel, MainViewModel vm)
  255. {
  256. if (imageModel?.FileInfo is not null)
  257. {
  258. return true;
  259. }
  260. ReturnError(vm);
  261. return false;
  262. }
  263. }