From 36e6d0a389557fd0b6be5832391840ff81e1d8a6 Mon Sep 17 00:00:00 2001 From: anoshenko Date: Sat, 20 Nov 2021 14:22:00 +0300 Subject: [PATCH] Added the "current" property to StackLayout --- CHANGELOG.md | 8 ++++ customView.go | 4 +- stackLayout.go | 101 ++++++++++++++++++++++++++++++++++++++-------- tabsLayout.go | 17 ++++---- viewsContainer.go | 20 ++++----- 5 files changed, 115 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bba9840..abc2459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# v0.4.0 + +* Added SetTitle and SetTitleColor function to the Session interface +* Added a listener for changing a view property value +* Added the "current" property to StackLayout +* Updated TabsLayout +* Bug fixing + # v0.3.0 * Added FilePicker diff --git a/customView.go b/customView.go index 15beadb..aed1499 100644 --- a/customView.go +++ b/customView.go @@ -224,7 +224,7 @@ func (customView *CustomViewData) Append(view View) { } // Insert inserts a view to the "index" position in the list of a view children -func (customView *CustomViewData) Insert(view View, index uint) { +func (customView *CustomViewData) Insert(view View, index int) { if customView.superView != nil { if container, ok := customView.superView.(ViewsContainer); ok { container.Insert(view, index) @@ -233,7 +233,7 @@ func (customView *CustomViewData) Insert(view View, index uint) { } // Remove removes a view from the list of a view children and return it -func (customView *CustomViewData) RemoveView(index uint) View { +func (customView *CustomViewData) RemoveView(index int) View { if customView.superView != nil { if container, ok := customView.superView.(ViewsContainer); ok { return container.RemoveView(index) diff --git a/stackLayout.go b/stackLayout.go index 9f1c7c5..81e5ed6 100644 --- a/stackLayout.go +++ b/stackLayout.go @@ -6,8 +6,6 @@ import ( "strings" ) -// TODO PeekChangedEvent - const ( // DefaultAnimation - default animation of StackLayout push DefaultAnimation = 0 @@ -33,7 +31,7 @@ type StackLayout interface { type stackLayoutData struct { viewsContainerData - peek uint + peek int pushView, popView View animationType int onPushFinished func() @@ -66,11 +64,12 @@ func (layout *stackLayoutData) pushFinished(view View, tag string) { layout.pushView = nil count := len(layout.views) if count > 0 { - layout.peek = uint(count - 1) + layout.peek = count - 1 } else { layout.peek = 0 } updateInnerHTML(layout.htmlID(), layout.session) + layout.propertyChangedEvent(Current) } if layout.onPushFinished != nil { @@ -99,7 +98,13 @@ func (layout *stackLayoutData) Set(tag string, value interface{}) bool { } func (layout *stackLayoutData) set(tag string, value interface{}) bool { - if tag == TransitionEndEvent { + if value == nil { + layout.remove(tag) + return true + } + + switch tag { + case TransitionEndEvent: listeners, ok := valueToAnimationListeners(value) if ok { listeners = append(listeners, layout.pushFinished) @@ -108,6 +113,46 @@ func (layout *stackLayoutData) set(tag string, value interface{}) bool { layout.propertyChangedEvent(TransitionEndEvent) } return ok + + case Current: + setCurrent := func(index int) { + if index != layout.peek { + if layout.peek < len(layout.views) { + updateCSSProperty(layout.htmlID()+"page"+strconv.Itoa(layout.peek), "visibility", "hidden", layout.Session()) + } + + layout.peek = index + updateCSSProperty(layout.htmlID()+"page"+strconv.Itoa(index), "visibility", "visible", layout.Session()) + layout.propertyChangedEvent(Current) + } + } + switch value := value.(type) { + case string: + text, ok := layout.session.resolveConstants(value) + if !ok { + invalidPropertyValue(tag, value) + return false + } + n, err := strconv.Atoi(strings.Trim(text, " \t")) + if err != nil { + invalidPropertyValue(tag, value) + ErrorLog(err.Error()) + return false + } + setCurrent(n) + + default: + n, ok := isInt(value) + if !ok { + notCompatibleType(tag, value) + return false + } else if n < 0 || n >= len(layout.views) { + ErrorLogF(`The view index "%d" of "%s" property is out of range`, n, tag) + return false + } + setCurrent(n) + } + return true } return layout.viewsContainerData.set(tag, value) } @@ -117,14 +162,30 @@ func (layout *stackLayoutData) Remove(tag string) { } func (layout *stackLayoutData) remove(tag string) { - if tag == TransitionEndEvent { + switch tag { + case TransitionEndEvent: layout.properties[TransitionEndEvent] = []func(View, string){layout.pushFinished, layout.popFinished} layout.propertyChangedEvent(TransitionEndEvent) - } else { + + case Current: + layout.set(Current, 0) + + default: layout.viewsContainerData.remove(tag) } } +func (layout *stackLayoutData) Get(tag string) interface{} { + return layout.get(strings.ToLower(tag)) +} + +func (layout *stackLayoutData) get(tag string) interface{} { + if tag == Current { + return layout.peek + } + return layout.viewsContainerData.get(tag) +} + func (layout *stackLayoutData) Peek() View { if int(layout.peek) < len(layout.views) { return layout.views[layout.peek] @@ -142,8 +203,9 @@ func (layout *stackLayoutData) MoveToFront(view View) bool { updateCSSProperty(layout.htmlID()+"page"+strconv.Itoa(peek), "visibility", "hidden", layout.Session()) } - layout.peek = uint(i) + layout.peek = i updateCSSProperty(layout.htmlID()+"page"+strconv.Itoa(i), "visibility", "visible", layout.Session()) + layout.propertyChangedEvent(Current) } return true } @@ -162,8 +224,9 @@ func (layout *stackLayoutData) MoveToFrontByID(viewID string) bool { updateCSSProperty(layout.htmlID()+"page"+strconv.Itoa(peek), "visibility", "hidden", layout.Session()) } - layout.peek = uint(i) + layout.peek = i updateCSSProperty(layout.htmlID()+"page"+strconv.Itoa(i), "visibility", "visible", layout.Session()) + layout.propertyChangedEvent(Current) } return true } @@ -175,31 +238,38 @@ func (layout *stackLayoutData) MoveToFrontByID(viewID string) bool { func (layout *stackLayoutData) Append(view View) { if view != nil { - layout.peek = uint(len(layout.views)) + layout.peek = len(layout.views) layout.viewsContainerData.Append(view) + layout.propertyChangedEvent(Current) } else { ErrorLog("StackLayout.Append(nil, ....) is forbidden") } } -func (layout *stackLayoutData) Insert(view View, index uint) { +func (layout *stackLayoutData) Insert(view View, index int) { if view != nil { - count := uint(len(layout.views)) + count := len(layout.views) if index < count { - layout.peek = index + layout.peek = int(index) } else { layout.peek = count } layout.viewsContainerData.Insert(view, index) + layout.propertyChangedEvent(Current) } else { ErrorLog("StackLayout.Insert(nil, ....) is forbidden") } } -func (layout *stackLayoutData) RemoveView(index uint) View { +func (layout *stackLayoutData) RemoveView(index int) View { + if index < 0 || index >= len(layout.views) { + return nil + } + if layout.peek > 0 { layout.peek-- } + defer layout.propertyChangedEvent(Current) return layout.viewsContainerData.RemoveView(index) } @@ -254,7 +324,7 @@ func (layout *stackLayoutData) Push(view View, animation int, onPushFinished fun } func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool { - count := uint(len(layout.views)) + count := len(layout.views) if count == 0 || layout.peek >= count { ErrorLog("StackLayout is empty") return false @@ -299,7 +369,6 @@ func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool } updateCSSProperty(htmlID+"pop", "transform", value, layout.session) - layout.propertyChangedEvent(Content) return true } diff --git a/tabsLayout.go b/tabsLayout.go index 967bc98..3ac2a4c 100644 --- a/tabsLayout.go +++ b/tabsLayout.go @@ -588,31 +588,32 @@ func (tabsLayout *tabsLayoutData) Append(view View) { if view != nil { tabsLayout.viewsContainerData.Append(view) if len(tabsLayout.views) == 1 { - tabsLayout.setIntProperty(Current, 0) + tabsLayout.properties[Current] = 0 for _, listener := range tabsLayout.tabListener { listener(tabsLayout, 0, -1) } + defer tabsLayout.propertyChangedEvent(Current) } updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session) } } // Insert inserts view to the "index" position in view list -func (tabsLayout *tabsLayoutData) Insert(view View, index uint) { +func (tabsLayout *tabsLayoutData) Insert(view View, index int) { if tabsLayout.views == nil { tabsLayout.views = []View{} } if view != nil { - tabsLayout.viewsContainerData.Insert(view, index) - current := tabsLayout.currentItem() - if current >= int(index) { - tabsLayout.Set(Current, current+1) + if current := tabsLayout.currentItem(); current >= int(index) { + tabsLayout.properties[Current] = current + 1 + defer tabsLayout.propertyChangedEvent(Current) } + tabsLayout.viewsContainerData.Insert(view, index) } } // Remove removes view from list and return it -func (tabsLayout *tabsLayoutData) RemoveView(index uint) View { +func (tabsLayout *tabsLayoutData) RemoveView(index int) View { if tabsLayout.views == nil { tabsLayout.views = []View{} return nil @@ -629,6 +630,7 @@ func (tabsLayout *tabsLayoutData) RemoveView(index uint) View { for _, listener := range tabsLayout.tabListener { listener(tabsLayout, 0, 0) } + tabsLayout.propertyChangedEvent(Current) return view } @@ -639,6 +641,7 @@ func (tabsLayout *tabsLayoutData) RemoveView(index uint) View { for _, listener := range tabsLayout.tabListener { listener(tabsLayout, current-1, current) } + defer tabsLayout.propertyChangedEvent(Current) } return tabsLayout.viewsContainerData.RemoveView(index) diff --git a/viewsContainer.go b/viewsContainer.go index efcddbe..0730238 100644 --- a/viewsContainer.go +++ b/viewsContainer.go @@ -14,9 +14,9 @@ type ViewsContainer interface { // Append appends a view to the end of the list of a view children Append(view View) // Insert inserts a view to the "index" position in the list of a view children - Insert(view View, index uint) + Insert(view View, index int) // Remove removes a view from the list of a view children and return it - RemoveView(index uint) View + RemoveView(index int) View } type viewsContainerData struct { @@ -63,10 +63,10 @@ func (container *viewsContainerData) Append(view View) { } // Insert inserts a view to the "index" position in the list of a view children -func (container *viewsContainerData) Insert(view View, index uint) { +func (container *viewsContainerData) Insert(view View, index int) { if view != nil { htmlID := container.htmlID() - if container.views == nil || index >= uint(len(container.views)) { + if container.views == nil || index < 0 || index >= len(container.views) { container.Append(view) } else if index > 0 { view.setParentID(htmlID) @@ -83,21 +83,21 @@ func (container *viewsContainerData) Insert(view View, index uint) { } // Remove removes view from list and return it -func (container *viewsContainerData) RemoveView(index uint) View { +func (container *viewsContainerData) RemoveView(index int) View { if container.views == nil { container.views = []View{} return nil } - viewsLen := uint(len(container.views)) - if index >= viewsLen { + count := len(container.views) + if index < 0 || index >= count { return nil } view := container.views[index] if index == 0 { container.views = container.views[1:] - } else if index == viewsLen-1 { + } else if index == count-1 { container.views = container.views[:index] } else { container.views = append(container.views[:index], container.views[index+1:]...) @@ -306,7 +306,7 @@ func AppendView(rootView View, containerID string, view View) bool { } // Insert inserts a view to the "index" position in the list of a view children -func InsertView(rootView View, containerID string, view View, index uint) bool { +func InsertView(rootView View, containerID string, view View, index int) bool { var container ViewsContainer = nil if containerID != "" { container = ViewsContainerByID(rootView, containerID) @@ -327,7 +327,7 @@ func InsertView(rootView View, containerID string, view View, index uint) bool { } // Remove removes a view from the list of a view children and return it -func RemoveView(rootView View, containerID string, index uint) View { +func RemoveView(rootView View, containerID string, index int) View { var container ViewsContainer = nil if containerID != "" { container = ViewsContainerByID(rootView, containerID)