| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- 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 Return
- _ShowProgress = value
- RefreshText()
- End Set
- End Property
- Private _Text As String = "加载中"
- Public Property Text As String
- Get
- Return _Text
- End Get
- Set(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(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, _State.ProgressChanged
- RunInUi(
- Sub()
- 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
- LabText.Text = Ex.GetDisplay(False)
- 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 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 Return
- 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 Return
- 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 Return
- IsLooping = True
- ErrorAnimationWaiting = True
- 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 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)
- Event ProgressChanged(NewProgress As Double, OldProgress As Double)
- 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 Return
- 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
- Public Event ProgressChanged(NewProgress As Double, OldProgress As Double) Implements ILoadingTrigger.ProgressChanged
- End Class
|