MyCompItem.xaml.vb 13 KB

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