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
* Added "mod", "rem", "round", "round-up", "round-down", and "round-to-zero" SizeFunc functions
* Added ModSize, RemSize, RoundSize, RoundUpSize, RoundDownSize, and RoundToZeroSize functions
* Added Start, Stop, Pause, and Resume methods to Animation interface
# v0.16.0
* Can use ListAdapter as "content" property value of ListLayout

View File

@ -121,6 +121,10 @@ type animationData struct {
propertyList
keyFramesName string
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:
@ -128,6 +132,17 @@ type animationData struct {
type Animation interface {
Properties
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)
animationCSS(session Session) string
transitionCSS(buffer *strings.Builder, session Session)
@ -163,19 +178,29 @@ func NewAnimation(params Params) Animation {
return animation
}
func (animation *animationData) hasAnimatedProperty() bool {
props := animation.getRaw(PropertyTag)
if props == nil {
func (animation *animationData) animatedProperties() []AnimatedProperty {
value := animation.getRaw(PropertyTag)
if value == nil {
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.")
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 {
@ -394,19 +419,11 @@ func (animation *animationData) String() string {
func (animation *animationData) animationCSS(session Session) string {
if animation.keyFramesName == "" {
props := animation.getRaw(PropertyTag)
if props == nil {
ErrorLog("There are no animated properties.")
if props := animation.animatedProperties(); props != nil {
animation.keyFramesName = session.registerAnimation(props)
} else {
return ""
}
animatedProps, ok := props.([]AnimatedProperty)
if !ok || len(animatedProps) == 0 {
ErrorLog("Invalid animated properties.")
return ""
}
animation.keyFramesName = session.registerAnimation(animatedProps)
}
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 {
session := view.Session()
if !session.canvasStart(view.htmlID()) {
return nil
}
canvas := new(canvasData)
canvas.view = view
canvas.session = view.Session()
canvas.session.canvasStart(view.htmlID())
canvas.session = session
return canvas
}

View File

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