MyCompItem.xaml.vb 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. Public Class MyCompItem
  2. #Region "基础属性"
  3. Public Uuid As Integer = GetUuid()
  4. 'Logo
  5. Private _Logo As String = ""
  6. Public Property Logo As String
  7. Get
  8. Return _Logo
  9. End Get
  10. Set(value As String)
  11. If _Logo = value OrElse value Is Nothing Then Exit Property
  12. _Logo = value
  13. Dim FileAddress = PathTemp & "CompLogo\" & GetHash(_Logo) & ".png"
  14. Try
  15. If _Logo.ToLower.StartsWith("http") Then
  16. '网络图片
  17. If File.Exists(FileAddress) Then
  18. PathLogo.Source = New MyBitmap(FileAddress)
  19. ElseIf _Logo.ToLower.EndsWith(".webp") Then 'Modrinth 林业 Mod 使用了不支持的 WebP 格式 Logo
  20. Log($"[Comp] 发现不支持的 WebP 格式图标,已更改为默认图标:{_Logo}")
  21. PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png")
  22. Else
  23. PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png")
  24. RunInNewThread(Sub() LogoLoader(FileAddress), "Comp Logo Loader " & Uuid & "#", ThreadPriority.BelowNormal)
  25. End If
  26. Else
  27. '位图
  28. PathLogo.Source = New MyBitmap(_Logo)
  29. End If
  30. Catch ex As IOException
  31. Log(ex, "加载资源工程图标时读取失败(" & FileAddress & ")")
  32. Catch ex As ArgumentException
  33. '考虑缓存的图片本身可能有误
  34. Log(ex, "可视化资源工程图标失败(" & FileAddress & ")")
  35. Try
  36. File.Delete(FileAddress)
  37. Log("[Comp] 已清理损坏的资源工程图标:" & FileAddress)
  38. Catch exx As Exception
  39. Log(exx, "清理损坏的资源工程图标缓存失败(" & FileAddress & ")", LogLevel.Hint)
  40. End Try
  41. Catch ex As Exception
  42. Log(ex, "加载资源工程图标失败(" & value & ")")
  43. End Try
  44. End Set
  45. End Property
  46. '后台加载 Logo
  47. Private Sub LogoLoader(Address As String)
  48. Dim Retry As Boolean = False
  49. Dim DownloadEnd As String = GetUuid()
  50. RetryStart:
  51. Try
  52. NetDownload(_Logo, Address & DownloadEnd)
  53. Dim LoadError As Exception = Nothing
  54. RunInUiWait(Sub()
  55. Try
  56. '在地址更换时取消加载
  57. If Not Address = PathTemp & "CompLogo\" & GetHash(_Logo) & ".png" Then Exit Sub
  58. '在完成正常加载后才保存缓存图片
  59. PathLogo.Source = New MyBitmap(Address & DownloadEnd)
  60. Catch ex As Exception
  61. Log(ex, "读取资源工程图标失败(" & Address & ")")
  62. File.Delete(Address & DownloadEnd)
  63. LoadError = ex
  64. End Try
  65. End Sub)
  66. If LoadError IsNot Nothing Then Throw LoadError
  67. If File.Exists(Address) Then
  68. File.Delete(Address & DownloadEnd)
  69. Else
  70. FileIO.FileSystem.MoveFile(Address & DownloadEnd, Address)
  71. End If
  72. Catch ex As Exception
  73. If Not Retry Then
  74. Retry = True
  75. GoTo RetryStart
  76. Else
  77. Log(ex, $"下载资源工程图标失败({_Logo})")
  78. RunInUi(Sub() PathLogo.Source = New MyBitmap(PathImage & "Icons/NoIcon.png"))
  79. End If
  80. End Try
  81. End Sub
  82. '标题
  83. Public Property Title As String
  84. Get
  85. Return LabTitle.Text
  86. End Get
  87. Set(value As String)
  88. If LabTitle.Text = value Then Exit Property
  89. LabTitle.Text = value
  90. End Set
  91. End Property
  92. '副标题
  93. Public Property SubTitle As String
  94. Get
  95. Return If(LabTitleRaw?.Text, "")
  96. End Get
  97. Set(value As String)
  98. If LabTitleRaw.Text = value Then Exit Property
  99. LabTitleRaw.Text = value
  100. LabTitleRaw.Visibility = If(value = "", Visibility.Collapsed, Visibility.Visible)
  101. End Set
  102. End Property
  103. '描述
  104. Public Property Description As String
  105. Get
  106. Return LabInfo.Text
  107. End Get
  108. Set(value As String)
  109. If LabInfo.Text = value Then Exit Property
  110. LabInfo.Text = value
  111. End Set
  112. End Property
  113. '指向时扩展描述
  114. Private Sub LabInfo_MouseEnter(sender As Object, e As MouseEventArgs) Handles LabInfo.MouseEnter
  115. If IsTextTrimmed(LabInfo) Then
  116. ToolTipInfo.Content = LabInfo.Text
  117. ToolTipInfo.Width = LabInfo.ActualWidth + 25
  118. LabInfo.ToolTip = ToolTipInfo
  119. Else
  120. LabInfo.ToolTip = Nothing
  121. End If
  122. End Sub
  123. Private Function IsTextTrimmed(textBlock As TextBlock) As Boolean
  124. Dim typeface As New Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch)
  125. Dim formattedText As New FormattedText(textBlock.Text, Thread.CurrentThread.CurrentCulture, textBlock.FlowDirection, typeface, textBlock.FontSize, textBlock.Foreground, DPI)
  126. Return formattedText.Width > textBlock.ActualWidth
  127. End Function
  128. 'Tag
  129. Public WriteOnly Property Tags As List(Of String)
  130. Set(value As List(Of String))
  131. PanTags.Children.Clear()
  132. PanTags.Visibility = If(value.Any(), Visibility.Visible, Visibility.Collapsed)
  133. For Each TagText In value
  134. Dim NewTag = GetObjectFromXML(
  135. "<Border xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
  136. Background=""#11000000"" Padding=""3,1"" CornerRadius=""3"" Margin=""0,0,3,0""
  137. SnapsToDevicePixels=""True"" UseLayoutRounding=""False"">
  138. <TextBlock Text=""" & TagText & """ Foreground=""#868686"" FontSize=""11"" />
  139. </Border>")
  140. PanTags.Children.Add(NewTag)
  141. Next
  142. End Set
  143. End Property
  144. #End Region
  145. #Region "点击"
  146. '触发点击事件
  147. Public Event Click(sender As Object, e As MouseButtonEventArgs)
  148. Private Sub Button_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonUp
  149. If IsMouseDown Then
  150. RaiseEvent Click(sender, e)
  151. If e.Handled Then Exit Sub
  152. Log("[Control] 按下资源工程列表项:" & LabTitle.Text)
  153. End If
  154. End Sub
  155. Private Sub ProjectClick(sender As MyCompItem, e As EventArgs) Handles Me.Click
  156. '记录当前展开的卡片标题(#2712)
  157. Dim Titles As New List(Of String)
  158. If FrmMain.PageCurrent.Page = FormMain.PageType.CompDetail Then
  159. For Each Card As MyCard In FrmDownloadCompDetail.PanMain.Children
  160. If Card.Title <> "" AndAlso Not Card.IsSwaped Then Titles.Add(Card.Title)
  161. Next
  162. Log("[Comp] 记录当前已展开的卡片:" & String.Join("、", Titles))
  163. FrmMain.PageCurrent.Additional(1) = Titles
  164. End If
  165. '打开详情页
  166. Dim TargetVersion As String
  167. Dim TargetLoader As CompModLoaderType
  168. If FrmMain.PageCurrent.Page = FormMain.PageType.CompDetail Then
  169. TargetVersion = FrmMain.PageCurrent.Additional(2)
  170. TargetLoader = FrmMain.PageCurrent.Additional(3)
  171. Else
  172. Select Case CType(sender.Tag, CompProject).Type
  173. Case CompType.Mod
  174. TargetVersion = If(PageDownloadMod.Loader.Input.GameVersion, "")
  175. TargetLoader = PageDownloadMod.Loader.Input.ModLoader
  176. Case CompType.ModPack
  177. TargetVersion = If(PageDownloadPack.Loader.Input.GameVersion, "")
  178. Case Else 'CompType.ResourcePack
  179. 'FUTURE: Res
  180. TargetVersion = "" 'If(PageDownloadResource.Loader.Input.GameVersion, "")
  181. End Select
  182. End If
  183. If CType(sender.Tag, CompProject).Type <> CompType.Mod Then TargetLoader = CompModLoaderType.Any
  184. FrmMain.PageChange(New FormMain.PageStackData With {.Page = FormMain.PageType.CompDetail,
  185. .Additional = {sender.Tag, New List(Of String), TargetVersion, TargetLoader}})
  186. End Sub
  187. '鼠标点击判定
  188. Private IsMouseDown As Boolean = False
  189. Private Sub Button_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.PreviewMouseLeftButtonDown
  190. If IsMouseOver AndAlso CanInteraction Then IsMouseDown = True
  191. End Sub
  192. Private Sub Button_MouseLeave(sender As Object, e As Object) Handles Me.MouseLeave, Me.PreviewMouseLeftButtonUp
  193. IsMouseDown = False
  194. End Sub
  195. #End Region
  196. #Region "后加载指向背景"
  197. Private _RectBack As Border = Nothing
  198. Public ReadOnly Property RectBack As Border
  199. Get
  200. If _RectBack Is Nothing Then
  201. Dim Rect As New Border With {
  202. .Name = "RectBack",
  203. .CornerRadius = New CornerRadius(3),
  204. .RenderTransform = New ScaleTransform(0.8, 0.8),
  205. .RenderTransformOrigin = New Point(0.5, 0.5),
  206. .BorderThickness = New Thickness(GetWPFSize(1)),
  207. .SnapsToDevicePixels = True,
  208. .IsHitTestVisible = False,
  209. .Opacity = 0
  210. }
  211. Rect.SetResourceReference(Border.BackgroundProperty, "ColorBrush7")
  212. Rect.SetResourceReference(Border.BorderBrushProperty, "ColorBrush6")
  213. SetColumnSpan(Rect, 999)
  214. SetRowSpan(Rect, 999)
  215. Children.Insert(0, Rect)
  216. _RectBack = Rect
  217. '<!--<Border x:Name = "RectBack" CornerRadius="3" RenderTransformOrigin="0.5,0.5" SnapsToDevicePixels="True"
  218. 'IsHitTestVisible = "False" Opacity="0" BorderThickness="1"
  219. 'Grid.ColumnSpan = "4" Background="{DynamicResource ColorBrush7}" BorderBrush="{DynamicResource ColorBrush6}"/>-->
  220. End If
  221. Return _RectBack
  222. End Get
  223. End Property
  224. #End Region
  225. Private StateLast As String
  226. ''' <summary>
  227. ''' 是否允许交互。目前仅用于 PageDownloadCompDetail 的顶部栏展示:若关闭碰撞检测,则无法展开 Tooltip。
  228. ''' </summary>
  229. Public CanInteraction As Boolean = True
  230. Public Sub RefreshColor(sender As Object, e As EventArgs) Handles Me.MouseEnter, Me.MouseLeave, Me.MouseLeftButtonDown, Me.MouseLeftButtonUp
  231. If Not CanInteraction Then Exit Sub
  232. '判断当前颜色
  233. Dim StateNew As String, Time As Integer
  234. If IsMouseOver Then
  235. If IsMouseDown Then
  236. StateNew = "MouseDown"
  237. Time = 120
  238. Else
  239. StateNew = "MouseOver"
  240. Time = 120
  241. End If
  242. Else
  243. StateNew = "Idle"
  244. Time = 180
  245. End If
  246. If StateLast = StateNew Then Exit Sub
  247. StateLast = StateNew
  248. '触发颜色动画
  249. If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
  250. '有动画
  251. Dim Ani As New List(Of AniData)
  252. If IsMouseOver Then
  253. Ani.AddRange({
  254. AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrushBg1"), Time),
  255. AaOpacity(RectBack, 1 - RectBack.Opacity, Time,, New AniEaseOutFluent)
  256. })
  257. If IsMouseDown Then
  258. Ani.Add(AaScaleTransform(RectBack, 0.996 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time * 1.2,, New AniEaseOutFluent))
  259. Else
  260. Ani.Add(AaScaleTransform(RectBack, 1 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time * 1.2,, New AniEaseOutFluent))
  261. End If
  262. Else
  263. Ani.AddRange({
  264. AaOpacity(RectBack, -RectBack.Opacity, Time),
  265. AaColor(RectBack, Border.BackgroundProperty, If(IsMouseDown, "ColorBrush6", "ColorBrush7"), Time),
  266. AaScaleTransform(RectBack, 0.996 - CType(RectBack.RenderTransform, ScaleTransform).ScaleX, Time,, New AniEaseOutFluent),
  267. AaScaleTransform(RectBack, -0.196, 1,,, True)
  268. })
  269. End If
  270. AniStart(Ani, "CompItem Color " & Uuid)
  271. Else
  272. '无动画
  273. AniStop("CompItem Color " & Uuid)
  274. If _RectBack IsNot Nothing Then RectBack.Opacity = 0
  275. End If
  276. End Sub
  277. End Class