Added Start, Stop, Pause, and Resume methods to Animation interface

This commit is contained in:
anoshenko 2024-07-05 16:41:07 +03:00
parent 2f3de8fce3
commit 5e3d37a6a0
5 changed files with 188 additions and 29 deletions

View File

@ -1,6 +1,7 @@
# v0.17.0 # v0.17.0
* Added "mod", "rem", "round", "round-up", "round-down", and "round-to-zero" SizeFunc functions * Added "mod", "rem", "round", "round-up", "round-down", and "round-to-zero" SizeFunc functions
* Added ModSize, RemSize, RoundSize, RoundUpSize, RoundDownSize, and RoundToZeroSize functions * Added ModSize, RemSize, RoundSize, RoundUpSize, RoundDownSize, and RoundToZeroSize functions
* Added Start, Stop, Pause, and Resume methods to Animation interface
# v0.16.0 # v0.16.0
* Can use ListAdapter as "content" property value of ListLayout * Can use ListAdapter as "content" property value of ListLayout

View File

@ -121,6 +121,10 @@ type animationData struct {
propertyList propertyList
keyFramesName string keyFramesName string
usageCounter int usageCounter int
view View
listener func(view View, animation Animation, event string)
oldListeners map[string][]func(View, string)
oldAnimation []Animation
} }
// Animation interface is used to set animation parameters. Used properties: // Animation interface is used to set animation parameters. Used properties:
@ -128,6 +132,17 @@ type animationData struct {
type Animation interface { type Animation interface {
Properties Properties
fmt.Stringer fmt.Stringer
// Start starts the animation for the view specified by the first argument.
// The second argument specifies the animation event listener (can be nil)
Start(view View, listener func(view View, animation Animation, event string)) bool
// Stop stops the animation
Stop()
// Pause pauses the animation
Pause()
// Resume resumes an animation that was stopped using the Pause method
Resume()
writeTransitionString(tag string, buffer *strings.Builder) writeTransitionString(tag string, buffer *strings.Builder)
animationCSS(session Session) string animationCSS(session Session) string
transitionCSS(buffer *strings.Builder, session Session) transitionCSS(buffer *strings.Builder, session Session)
@ -163,19 +178,29 @@ func NewAnimation(params Params) Animation {
return animation return animation
} }
func (animation *animationData) hasAnimatedProperty() bool { func (animation *animationData) animatedProperties() []AnimatedProperty {
props := animation.getRaw(PropertyTag) value := animation.getRaw(PropertyTag)
if props == nil { if value == nil {
ErrorLog("There are no animated properties.") ErrorLog("There are no animated properties.")
return false return nil
} }
if _, ok := props.([]AnimatedProperty); !ok { props, ok := value.([]AnimatedProperty)
if !ok {
ErrorLog("Invalid animated properties.") ErrorLog("Invalid animated properties.")
return false return nil
} }
return true if len(props) == 0 {
ErrorLog("There are no animated properties.")
return nil
}
return props
}
func (animation *animationData) hasAnimatedProperty() bool {
return animation.animatedProperties() != nil
} }
func (animation *animationData) animationName() string { func (animation *animationData) animationName() string {
@ -394,19 +419,11 @@ func (animation *animationData) String() string {
func (animation *animationData) animationCSS(session Session) string { func (animation *animationData) animationCSS(session Session) string {
if animation.keyFramesName == "" { if animation.keyFramesName == "" {
props := animation.getRaw(PropertyTag) if props := animation.animatedProperties(); props != nil {
if props == nil { animation.keyFramesName = session.registerAnimation(props)
ErrorLog("There are no animated properties.") } else {
return "" return ""
} }
animatedProps, ok := props.([]AnimatedProperty)
if !ok || len(animatedProps) == 0 {
ErrorLog("Invalid animated properties.")
return ""
}
animation.keyFramesName = session.registerAnimation(animatedProps)
} }
buffer := allocStringBuilder() buffer := allocStringBuilder()

109
animationRun.go Normal file
View File

@ -0,0 +1,109 @@
package rui
func (animation *animationData) Start(view View, listener func(view View, animation Animation, event string)) bool {
if view == nil {
ErrorLog("nil View in animation.Start() function")
return false
}
if !animation.hasAnimatedProperty() {
return false
}
animation.view = view
animation.listener = listener
animation.oldAnimation = nil
if value := view.Get(AnimationTag); value != nil {
if oldAnimation, ok := value.([]Animation); ok && len(oldAnimation) > 0 {
animation.oldAnimation = oldAnimation
}
}
animation.oldListeners = map[string][]func(View, string){}
setListeners := func(event string, listener func(View, string)) {
var listeners []func(View, string) = nil
if value := view.Get(event); value != nil {
if oldListeners, ok := value.([]func(View, string)); ok && len(oldListeners) > 0 {
listeners = oldListeners
}
}
if listeners == nil {
view.Set(event, listener)
} else {
animation.oldListeners[event] = listeners
view.Set(event, append(listeners, listener))
}
}
setListeners(AnimationStartEvent, animation.onAnimationStart)
setListeners(AnimationEndEvent, animation.onAnimationEnd)
setListeners(AnimationCancelEvent, animation.onAnimationCancel)
setListeners(AnimationIterationEvent, animation.onAnimationIteration)
view.Set(AnimationTag, animation)
return true
}
func (animation *animationData) finish() {
if animation.view != nil {
for _, event := range []string{AnimationStartEvent, AnimationEndEvent, AnimationCancelEvent, AnimationIterationEvent} {
if listeners, ok := animation.oldListeners[event]; ok {
animation.view.Set(event, listeners)
} else {
animation.view.Remove(event)
}
}
animation.view.Set(AnimationTag, animation.oldAnimation)
animation.oldListeners = map[string][]func(View, string){}
animation.oldAnimation = nil
animation.view = nil
animation.listener = nil
}
}
func (animation *animationData) Stop() {
animation.finish()
}
func (animation *animationData) Pause() {
if animation.view != nil {
animation.view.Set(AnimationPaused, true)
}
}
func (animation *animationData) Resume() {
if animation.view != nil {
animation.view.Remove(AnimationPaused)
}
}
func (animation *animationData) onAnimationStart(view View, _ string) {
if animation.view != nil && animation.listener != nil {
animation.listener(animation.view, animation, AnimationStartEvent)
}
}
func (animation *animationData) onAnimationEnd(view View, _ string) {
if animation.view != nil {
if animation.listener != nil {
animation.listener(animation.view, animation, AnimationEndEvent)
}
animation.finish()
}
}
func (animation *animationData) onAnimationIteration(view View, _ string) {
if animation.view != nil && animation.listener != nil {
animation.listener(animation.view, animation, AnimationIterationEvent)
}
}
func (animation *animationData) onAnimationCancel(view View, _ string) {
if animation.view != nil && animation.listener != nil {
animation.listener(animation.view, animation, AnimationCancelEvent)
}
}

View File

@ -299,10 +299,13 @@ type canvasData struct {
} }
func newCanvas(view CanvasView) Canvas { func newCanvas(view CanvasView) Canvas {
session := view.Session()
if !session.canvasStart(view.htmlID()) {
return nil
}
canvas := new(canvasData) canvas := new(canvasData)
canvas.view = view canvas.view = view
canvas.session = view.Session() canvas.session = session
canvas.session.canvasStart(view.htmlID())
return canvas return canvas
} }

View File

@ -144,7 +144,9 @@ type Session interface {
sendResponse() sendResponse()
addAnimationCSS(css string) addAnimationCSS(css string)
removeAnimation(keyframe string) removeAnimation(keyframe string)
canvasStart(htmlID string) htmlPropertyValue(htmlID, name string) string
canvasStart(htmlID string) bool
callCanvasFunc(funcName string, args ...any) callCanvasFunc(funcName string, args ...any)
createCanvasVar(funcName string, args ...any) any createCanvasVar(funcName string, args ...any) any
callCanvasVarFunc(v any, funcName string, args ...any) callCanvasVarFunc(v any, funcName string, args ...any)
@ -152,7 +154,7 @@ type Session interface {
updateCanvasProperty(property string, value any) updateCanvasProperty(property string, value any)
canvasFinish() canvasFinish()
canvasTextMetrics(htmlID, font, text string) TextMetrics canvasTextMetrics(htmlID, font, text string) TextMetrics
htmlPropertyValue(htmlID, name string) string
addToEventsQueue(data DataObject) addToEventsQueue(data DataObject)
handleAnswer(command string, data DataObject) bool handleAnswer(command string, data DataObject) bool
handleRootSize(data DataObject) handleRootSize(data DataObject)
@ -427,20 +429,32 @@ func (session *sessionData) appendToInnerHTML(htmlID, html string) {
} }
func (session *sessionData) updateCSSProperty(htmlID, property, value string) { func (session *sessionData) updateCSSProperty(htmlID, property, value string) {
if !session.ignoreViewUpdates() && session.bridge != nil { if !session.ignoreViewUpdates() {
session.bridge.updateCSSProperty(htmlID, property, value) if session.bridge != nil {
session.bridge.updateCSSProperty(htmlID, property, value)
} else {
ErrorLog("No connection")
}
} }
} }
func (session *sessionData) updateProperty(htmlID, property string, value any) { func (session *sessionData) updateProperty(htmlID, property string, value any) {
if !session.ignoreViewUpdates() && session.bridge != nil { if !session.ignoreViewUpdates() {
session.bridge.updateProperty(htmlID, property, value) if session.bridge != nil {
session.bridge.updateProperty(htmlID, property, value)
} else {
ErrorLog("No connection")
}
} }
} }
func (session *sessionData) removeProperty(htmlID, property string) { func (session *sessionData) removeProperty(htmlID, property string) {
if !session.ignoreViewUpdates() && session.bridge != nil { if !session.ignoreViewUpdates() {
session.bridge.removeProperty(htmlID, property) if session.bridge != nil {
session.bridge.removeProperty(htmlID, property)
} else {
ErrorLog("No connection")
}
} }
} }
@ -448,18 +462,23 @@ func (session *sessionData) startUpdateScript(htmlID string) bool {
if session.bridge != nil { if session.bridge != nil {
return session.bridge.startUpdateScript(htmlID) return session.bridge.startUpdateScript(htmlID)
} }
ErrorLog("No connection")
return false return false
} }
func (session *sessionData) finishUpdateScript(htmlID string) { func (session *sessionData) finishUpdateScript(htmlID string) {
if session.bridge != nil { if session.bridge != nil {
session.bridge.finishUpdateScript(htmlID) session.bridge.finishUpdateScript(htmlID)
} else {
ErrorLog("No connection")
} }
} }
func (session *sessionData) sendResponse() { func (session *sessionData) sendResponse() {
if session.bridge != nil { if session.bridge != nil {
session.bridge.sendResponse() session.bridge.sendResponse()
} else {
ErrorLog("No connection")
} }
} }
@ -467,6 +486,8 @@ func (session *sessionData) addAnimationCSS(css string) {
session.animationCSS += css session.animationCSS += css
if session.bridge != nil { if session.bridge != nil {
session.bridge.appendAnimationCSS(css) session.bridge.appendAnimationCSS(css)
} else {
ErrorLog("No connection")
} }
} }
@ -503,14 +524,20 @@ func (session *sessionData) removeAnimation(keyframe string) {
session.animationCSS = css[:index] + css[end:] session.animationCSS = css[:index] + css[end:]
if session.bridge != nil { if session.bridge != nil {
session.bridge.setAnimationCSS(session.animationCSS) session.bridge.setAnimationCSS(session.animationCSS)
} else {
ErrorLog("No connection")
} }
} }
} }
func (session *sessionData) canvasStart(htmlID string) { func (session *sessionData) canvasStart(htmlID string) bool {
if session.bridge != nil { if session.bridge != nil {
session.bridge.canvasStart(htmlID) session.bridge.canvasStart(htmlID)
return true
} }
ErrorLog("No connection")
return false
} }
func (session *sessionData) callCanvasFunc(funcName string, args ...any) { func (session *sessionData) callCanvasFunc(funcName string, args ...any) {
@ -587,6 +614,8 @@ func (session *sessionData) handleAnswer(command string, data DataObject) bool {
if session.bridge != nil { if session.bridge != nil {
session.bridge.sendResponse() session.bridge.sendResponse()
} else {
ErrorLog("No connection")
} }
return true return true
} }