上传公开代码
This commit is contained in:
@@ -0,0 +1,313 @@
|
||||
Imports PCL.MyLoading
|
||||
|
||||
Public Class MyLoading
|
||||
|
||||
Public Event IsErrorChanged(sender As Object, isError As Boolean)
|
||||
Public Event StateChanged(sender As Object, newState As MyLoadingState, oldState As MyLoadingState)
|
||||
Public Event Click(sender As Object, e As MouseButtonEventArgs)
|
||||
|
||||
Public Property AutoRun As Boolean = True
|
||||
Private Uuid As Integer = GetUuid()
|
||||
|
||||
#Region "颜色"
|
||||
|
||||
Public Property Foreground As SolidColorBrush
|
||||
Get
|
||||
Return GetValue(ForegroundProperty)
|
||||
End Get
|
||||
Set(value As SolidColorBrush)
|
||||
SetValue(ForegroundProperty, value)
|
||||
End Set
|
||||
End Property
|
||||
Public Shared ReadOnly ForegroundProperty As DependencyProperty = DependencyProperty.Register("Foreground", GetType(SolidColorBrush), GetType(MyLoading))
|
||||
Public Sub New()
|
||||
InitializeComponent()
|
||||
SetResourceReference(ForegroundProperty, "ColorBrush3")
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "文本"
|
||||
|
||||
Private Property _ShowProgress As Boolean = False
|
||||
Public Property ShowProgress As Boolean
|
||||
Get
|
||||
Return _ShowProgress
|
||||
End Get
|
||||
Set(value As Boolean)
|
||||
If _ShowProgress = value Then Exit Property
|
||||
_ShowProgress = value
|
||||
RefreshText()
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Private _Text As String = "加载中"
|
||||
Public Property Text As String
|
||||
Get
|
||||
Return _Text
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
_Text = value
|
||||
RefreshText()
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Private _TextError As String = "加载失败"
|
||||
Public Property TextError As String
|
||||
Get
|
||||
Return _TextError
|
||||
End Get
|
||||
Set(ByVal value As String)
|
||||
_TextError = value
|
||||
RefreshText()
|
||||
End Set
|
||||
End Property
|
||||
''' <summary>
|
||||
''' 是否在使用 Loader 时使用 Loader 的错误输出来替换默认的错误文本显示。
|
||||
''' </summary>
|
||||
Public Property TextErrorInherit As Boolean = True
|
||||
|
||||
Private Sub RefreshText() Handles Me.IsErrorChanged, Me.Loaded
|
||||
If InnerState = MyLoadingState.Error Then
|
||||
If TextErrorInherit AndAlso State.IsLoader Then
|
||||
Dim Ex As Exception = CType(State, Object).Error
|
||||
If Ex Is Nothing Then
|
||||
LabText.Text = "未知错误"
|
||||
Else
|
||||
Do While Ex.InnerException IsNot Nothing
|
||||
Ex = Ex.InnerException
|
||||
Loop
|
||||
LabText.Text = StrTrim(Ex.Message)
|
||||
If LabText.Text.Contains("远程主机强迫关闭了一个现有的连接") OrElse LabText.Text.Contains("操作已超时") OrElse LabText.Text.Contains("操作超时") OrElse LabText.Text.Contains("服务器超时") OrElse LabText.Text.Contains("连接超时") Then LabText.Text = "网络环境不佳,请重试或尝试使用 VPN"
|
||||
End If
|
||||
Else
|
||||
LabText.Text = TextError
|
||||
End If
|
||||
Else
|
||||
If ShowProgress AndAlso State.IsLoader Then
|
||||
LabText.Text = Text & " - " & Math.Floor(CType(State, Object).Progress * 100) & "%"
|
||||
Else
|
||||
LabText.Text = Text
|
||||
End If
|
||||
End If
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "状态改变"
|
||||
|
||||
'状态枚举
|
||||
Public Enum MyLoadingState
|
||||
Unloaded = -1
|
||||
Run = 0
|
||||
[Stop] = 1
|
||||
[Error] = 2
|
||||
End Enum
|
||||
|
||||
'用于外部改变的公开状态
|
||||
Private WithEvents _State As ILoadingTrigger
|
||||
Public Property State As ILoadingTrigger
|
||||
Get
|
||||
InitState()
|
||||
Return _State
|
||||
End Get
|
||||
Set(value As ILoadingTrigger)
|
||||
_State = value
|
||||
RefreshState()
|
||||
End Set
|
||||
End Property
|
||||
Private Sub InitState() Handles Me.Loaded
|
||||
If _State Is Nothing Then
|
||||
_State = New MyLoadingStateSimulator
|
||||
If AutoRun Then _State.LoadingState = MyLoadingState.Run
|
||||
End If
|
||||
End Sub
|
||||
Private Sub RefreshState() Handles _State.LoadingStateChanged, Me.Loaded, Me.Unloaded
|
||||
If _State.LoadingState = MyLoadingState.Run AndAlso Not IsLoaded Then InnerState = MyLoadingState.Stop
|
||||
InnerState = _State.LoadingState
|
||||
OuterState = _State.LoadingState
|
||||
AniLoop()
|
||||
End Sub
|
||||
|
||||
'用于引发外部事件的状态
|
||||
Private Property _OuterState As MyLoadingState = MyLoadingState.Unloaded
|
||||
Private Property OuterState As MyLoadingState
|
||||
Get
|
||||
Return _OuterState
|
||||
End Get
|
||||
Set(value As MyLoadingState)
|
||||
If _OuterState = value Then Exit Property
|
||||
Dim OldValue = _OuterState
|
||||
_OuterState = value
|
||||
'引发事件
|
||||
RaiseEvent StateChanged(Me, value, OldValue)
|
||||
If (OldValue = MyLoadingState.Error) <> (value = MyLoadingState.Error) Then RaiseEvent IsErrorChanged(Me, value = MyLoadingState.Error)
|
||||
End Set
|
||||
End Property
|
||||
|
||||
|
||||
'用于引发内部动画事件的状态
|
||||
Private Property _InnerState As MyLoadingState = MyLoadingState.Unloaded
|
||||
Private Property InnerState As MyLoadingState
|
||||
Get
|
||||
Return _InnerState
|
||||
End Get
|
||||
Set(value As MyLoadingState)
|
||||
If _InnerState = value Then Exit Property
|
||||
Dim OldValue = _InnerState
|
||||
_InnerState = value
|
||||
'引发事件
|
||||
AniLoop()
|
||||
If (OldValue = MyLoadingState.Error) <> (value = MyLoadingState.Error) Then ErrorAnimation(Me, value = MyLoadingState.Error)
|
||||
End Set
|
||||
End Property
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "动画"
|
||||
|
||||
''' <summary>
|
||||
''' 是否需要动画。
|
||||
''' </summary>
|
||||
Public Property HasAnimation As Boolean = True
|
||||
|
||||
''' <summary>
|
||||
''' 主动画循环是否正在运行中。
|
||||
''' </summary>
|
||||
Private IsLooping As Boolean = False
|
||||
Private Sub AniLoop()
|
||||
'这坨循环代码也是老屎坑了,救救.jpg
|
||||
If Not HasAnimation OrElse IsLooping OrElse Not InnerState = MyLoadingState.Run OrElse AniSpeed > 10 OrElse Not IsLoaded Then Exit Sub
|
||||
IsLooping = True
|
||||
ErrorAnimationWaiting = True
|
||||
If ShowProgress Then
|
||||
RefreshText()
|
||||
AniStart({
|
||||
AaRotateTransform(PathPickaxe, -20 - CType(PathPickaxe.RenderTransform, RotateTransform).Angle, 350, 250, New AniEaseInBack(AniEasePower.Weak)),
|
||||
AaCode(AddressOf RefreshText, 100), '这是为了省下一个 Timer 线程……
|
||||
AaCode(AddressOf RefreshText, 200),
|
||||
AaCode(AddressOf RefreshText, 300),
|
||||
AaCode(AddressOf RefreshText, 400),
|
||||
AaCode(AddressOf RefreshText, 500),
|
||||
AaRotateTransform(PathPickaxe, 50, 900,, New AniEaseOutFluent, True),
|
||||
AaRotateTransform(PathPickaxe, 25, 900,, New AniEaseOutElastic(AniEasePower.Weak)),
|
||||
AaCode(Sub()
|
||||
PathLeft.Opacity = 1
|
||||
PathLeft.Margin = New Thickness(7, 41, 0, 0)
|
||||
PathRight.Opacity = 1
|
||||
PathRight.Margin = New Thickness(14, 41, 0, 0)
|
||||
ErrorAnimationWaiting = False
|
||||
RefreshText()
|
||||
End Sub),
|
||||
AaCode(AddressOf RefreshText, 100),
|
||||
AaCode(AddressOf RefreshText, 200),
|
||||
AaCode(AddressOf RefreshText, 300),
|
||||
AaCode(AddressOf RefreshText, 400),
|
||||
AaCode(AddressOf RefreshText, 500),
|
||||
AaCode(AddressOf RefreshText, 600),
|
||||
AaCode(AddressOf RefreshText, 700),
|
||||
AaCode(AddressOf RefreshText, 800),
|
||||
AaOpacity(PathLeft, -1, 100, 70),
|
||||
AaX(PathLeft, -5, 180, 20, New AniEaseOutFluent),
|
||||
AaY(PathLeft, -6, 180, 20, New AniEaseOutFluent),
|
||||
AaOpacity(PathRight, -1, 100, 70),
|
||||
AaX(PathRight, 5, 180, 20, New AniEaseOutFluent),
|
||||
AaY(PathRight, -6, 180, 20, New AniEaseOutFluent),
|
||||
AaCode(Sub()
|
||||
IsLooping = False
|
||||
AniLoop()
|
||||
End Sub,, True)
|
||||
}, "MyLoader Loop " & Uuid & "/" & GetUuid())
|
||||
Else
|
||||
AniStart({
|
||||
AaRotateTransform(PathPickaxe, -20 - CType(PathPickaxe.RenderTransform, RotateTransform).Angle, 350, 250, New AniEaseInBack(AniEasePower.Weak)),
|
||||
AaRotateTransform(PathPickaxe, 50, 900,, New AniEaseOutFluent, True),
|
||||
AaRotateTransform(PathPickaxe, 25, 900,, New AniEaseOutElastic(AniEasePower.Weak)),
|
||||
AaCode(Sub()
|
||||
PathLeft.Opacity = 1
|
||||
PathLeft.Margin = New Thickness(7, 41, 0, 0)
|
||||
PathRight.Opacity = 1
|
||||
PathRight.Margin = New Thickness(14, 41, 0, 0)
|
||||
ErrorAnimationWaiting = False
|
||||
End Sub),
|
||||
AaOpacity(PathLeft, -1, 100, 50),
|
||||
AaX(PathLeft, -5, 180,, New AniEaseOutFluent),
|
||||
AaY(PathLeft, -6, 180,, New AniEaseOutFluent),
|
||||
AaOpacity(PathRight, -1, 100, 50),
|
||||
AaX(PathRight, 5, 180,, New AniEaseOutFluent),
|
||||
AaY(PathRight, -6, 180,, New AniEaseOutFluent),
|
||||
AaCode(Sub()
|
||||
IsLooping = False
|
||||
AniLoop()
|
||||
End Sub,, True)
|
||||
}, "MyLoader Loop " & Uuid & "/" & GetUuid())
|
||||
End If
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 镐子是否还没挥下去,要求错误动画等待。
|
||||
''' </summary>
|
||||
Private ErrorAnimationWaiting As Boolean = False
|
||||
Private Sub ErrorAnimation(sender As Object, isError As Boolean)
|
||||
If isError Then
|
||||
'非错误变为错误
|
||||
Dim Wait As Integer = If(ErrorAnimationWaiting, 400, 0)
|
||||
AniStart({
|
||||
AaColor(PanBack, ForegroundProperty, "ColorBrushRedLight", 300),
|
||||
AaOpacity(PathError, 1 - PathError.Opacity, 100, 300 + Wait),
|
||||
AaScaleTransform(PathError, 1 - CType(PathError.RenderTransform, ScaleTransform).ScaleX, 400, 300 + Wait, New AniEaseOutBack)
|
||||
}, "MyLoader Error " & Uuid)
|
||||
Else
|
||||
'错误变为非错误
|
||||
AniStart({
|
||||
AaOpacity(PathError, -PathError.Opacity, 100),
|
||||
AaScaleTransform(PathError, 0.5 - CType(PathError.RenderTransform, ScaleTransform).ScaleX, 200),
|
||||
AaColor(PanBack, ForegroundProperty, "ColorBrush3", 300)
|
||||
}, "MyLoader Error " & Uuid)
|
||||
End If
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
#Region "点击事件"
|
||||
|
||||
Private Sub Button_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonUp
|
||||
RaiseEvent Click(sender, e)
|
||||
End Sub
|
||||
Private IsMouseDown As Boolean = False
|
||||
Private Sub Button_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
|
||||
'鼠标点击判定(务必放在点击事件之后,以使得 Button_MouseUp 先于 Button_MouseLeave 执行)
|
||||
IsMouseDown = True
|
||||
End Sub
|
||||
Private Sub Button_MouseLeave(sender As Object, e As Object) Handles Me.MouseLeave, Me.MouseLeftButtonUp
|
||||
IsMouseDown = False
|
||||
End Sub
|
||||
|
||||
#End Region
|
||||
|
||||
End Class
|
||||
|
||||
Public Interface ILoadingTrigger
|
||||
ReadOnly Property IsLoader As Boolean
|
||||
Property LoadingState As MyLoadingState
|
||||
Event LoadingStateChanged(NewState As MyLoadingState, OldState As MyLoadingState)
|
||||
End Interface
|
||||
|
||||
Public Class MyLoadingStateSimulator
|
||||
Implements ILoadingTrigger
|
||||
Private Property _LoadingState As MyLoadingState = MyLoadingState.Unloaded
|
||||
Public Property LoadingState As MyLoadingState Implements ILoadingTrigger.LoadingState
|
||||
Get
|
||||
Return _LoadingState
|
||||
End Get
|
||||
Set(value As MyLoadingState)
|
||||
If _LoadingState = value Then Exit Property
|
||||
Dim OldState = _LoadingState
|
||||
_LoadingState = value
|
||||
RaiseEvent LoadingStateChanged(value, OldState)
|
||||
End Set
|
||||
End Property
|
||||
Public ReadOnly Property IsLoader As Boolean = False Implements ILoadingTrigger.IsLoader
|
||||
|
||||
Public Event LoadingStateChanged(NewState As MyLoadingState, OldState As MyLoadingState) Implements ILoadingTrigger.LoadingStateChanged
|
||||
End Class
|
||||
Reference in New Issue
Block a user