rui_orig/viewsContainer.go

383 lines
8.9 KiB
Go
Raw Normal View History

2021-09-07 17:36:50 +03:00
package rui
import "strings"
// ParentView describe a view which can have a child views
2022-11-23 15:10:29 +03:00
type ParentView interface {
2021-09-07 17:36:50 +03:00
// Views return a list of child views
Views() []View
}
// ViewsContainer represent a mutable list-container of views
2021-09-07 17:36:50 +03:00
type ViewsContainer interface {
View
2022-11-23 15:10:29 +03:00
ParentView
2024-04-23 19:34:36 +03:00
2021-09-07 17:36:50 +03:00
// Append appends a view to the end of the list of a view children
Append(view View)
2024-04-23 19:34:36 +03:00
2021-09-07 17:36:50 +03:00
// Insert inserts a view to the "index" position in the list of a view children
Insert(view View, index int)
2024-04-23 19:34:36 +03:00
2021-09-07 17:36:50 +03:00
// Remove removes a view from the list of a view children and return it
RemoveView(index int) View
2024-04-23 19:34:36 +03:00
// ViewIndex returns the index of view, -1 overwise
ViewIndex(view View) int
2024-11-13 12:56:39 +03:00
setContent(value any) bool
2021-09-07 17:36:50 +03:00
}
type viewsContainerData struct {
viewData
views []View
}
// Init initialize fields of ViewsContainer by default values
func (container *viewsContainerData) init(session Session) {
container.viewData.init(session)
2021-09-07 17:36:50 +03:00
container.tag = "ViewsContainer"
container.views = []View{}
container.get = container.getFunc
2024-11-13 12:56:39 +03:00
container.set = container.setFunc
container.remove = container.removeFunc
container.changed = container.propertyChanged
2022-05-22 12:54:02 +03:00
}
2021-09-07 17:36:50 +03:00
func (container *viewsContainerData) setParentID(parentID string) {
container.viewData.setParentID(parentID)
htmlID := container.htmlID()
for _, view := range container.views {
view.setParentID(htmlID)
}
}
// Views return a list of child views
func (container *viewsContainerData) Views() []View {
if container.views == nil {
container.views = []View{}
2022-08-10 15:36:38 +03:00
} else if count := len(container.views); count > 0 {
2022-05-17 10:46:00 +03:00
views := make([]View, count)
copy(views, container.views)
return views
}
return []View{}
2021-09-07 17:36:50 +03:00
}
// Append appends a view to the end of the list of a view children
func (container *viewsContainerData) Append(view View) {
if view != nil {
htmlID := container.htmlID()
view.setParentID(htmlID)
if len(container.views) == 0 {
2021-09-07 17:36:50 +03:00
container.views = []View{view}
} else {
container.views = append(container.views, view)
}
2024-11-24 18:23:24 +03:00
2024-11-25 23:13:29 +03:00
if container.created {
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
2024-11-24 18:23:24 +03:00
2024-11-25 23:13:29 +03:00
viewHTML(view, buffer, "")
container.Session().appendToInnerHTML(htmlID, buffer.String())
2024-11-24 18:23:24 +03:00
2024-11-25 23:13:29 +03:00
if listener, ok := container.changeListener[Content]; ok {
listener(container, Content)
}
2024-11-24 18:23:24 +03:00
}
2021-09-07 17:36:50 +03:00
}
}
// Insert inserts a view to the "index" position in the list of a view children
func (container *viewsContainerData) Insert(view View, index int) {
2021-09-07 17:36:50 +03:00
if view != nil {
if container.views == nil || index < 0 || index >= len(container.views) {
2021-09-07 17:36:50 +03:00
container.Append(view)
2024-11-24 18:23:24 +03:00
return
}
htmlID := container.htmlID()
view.setParentID(htmlID)
if index > 0 {
2021-09-07 17:36:50 +03:00
container.views = append(container.views[:index], append([]View{view}, container.views[index:]...)...)
} else {
container.views = append([]View{view}, container.views...)
2024-11-24 18:23:24 +03:00
}
2024-11-25 23:13:29 +03:00
if container.created {
updateInnerHTML(htmlID, container.Session())
if listener, ok := container.changeListener[Content]; ok {
listener(container, Content)
}
2021-09-07 17:36:50 +03:00
}
}
}
// Remove removes view from list and return it
func (container *viewsContainerData) RemoveView(index int) View {
2021-09-07 17:36:50 +03:00
if container.views == nil {
container.views = []View{}
return nil
}
count := len(container.views)
if index < 0 || index >= count {
2021-09-07 17:36:50 +03:00
return nil
}
view := container.views[index]
if index == 0 {
container.views = container.views[1:]
} else if index == count-1 {
2021-09-07 17:36:50 +03:00
container.views = container.views[:index]
} else {
container.views = append(container.views[:index], container.views[index+1:]...)
}
view.setParentID("")
2024-11-24 18:23:24 +03:00
2024-11-25 23:13:29 +03:00
if container.created {
container.Session().callFunc("removeView", view.htmlID())
if listener, ok := container.changeListener[Content]; ok {
listener(container, Content)
}
2024-11-24 18:23:24 +03:00
}
2021-09-07 17:36:50 +03:00
return view
}
func (container *viewsContainerData) ViewIndex(view View) int {
for index, v := range container.views {
if v == view {
return index
}
}
return -1
}
2021-09-07 17:36:50 +03:00
func (container *viewsContainerData) cssStyle(self View, builder cssBuilder) {
container.viewData.cssStyle(self, builder)
builder.add(`overflow`, `auto`)
}
func (container *viewsContainerData) htmlSubviews(self View, buffer *strings.Builder) {
if container.views != nil {
for _, view := range container.views {
2024-11-21 09:25:46 +03:00
viewHTML(view, buffer, "")
2021-09-07 17:36:50 +03:00
}
}
}
func viewFromTextValue(text string, session Session) View {
if strings.Contains(text, "{") && strings.Contains(text, "}") {
data := ParseDataText(text)
if data != nil {
if view := CreateViewFromObject(session, data); view != nil {
return view
}
}
}
return NewTextView(session, Params{Text: text})
}
func (container *viewsContainerData) removeFunc(tag PropertyName) []PropertyName {
2021-09-07 17:36:50 +03:00
switch tag {
case Content:
2024-11-13 12:56:39 +03:00
if len(container.views) > 0 {
2021-09-07 17:36:50 +03:00
container.views = []View{}
2024-11-13 12:56:39 +03:00
return []PropertyName{tag}
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
return []PropertyName{}
case Disabled:
if container.getRaw(Disabled) != nil {
container.setRaw(Disabled, nil)
2024-11-13 12:56:39 +03:00
for _, view := range container.views {
view.Remove(Disabled)
}
2024-11-13 12:56:39 +03:00
return []PropertyName{tag}
}
2021-09-07 17:36:50 +03:00
}
return container.viewData.removeFunc(tag)
2021-09-07 17:36:50 +03:00
}
func (container *viewsContainerData) setFunc(tag PropertyName, value any) []PropertyName {
switch tag {
case Content:
2024-11-13 12:56:39 +03:00
if container.setContent(value) {
return []PropertyName{tag}
}
return nil
case Disabled:
oldDisabled := IsDisabled(container)
result := container.viewData.setFunc(Disabled, value)
2024-11-13 12:56:39 +03:00
if result != nil {
disabled := IsDisabled(container)
if oldDisabled != disabled {
2024-11-13 12:56:39 +03:00
for _, view := range container.views {
view.Set(Disabled, disabled)
}
}
}
2024-11-13 12:56:39 +03:00
return result
2021-09-07 17:36:50 +03:00
}
return container.viewData.setFunc(tag, value)
2024-11-13 12:56:39 +03:00
}
func (container *viewsContainerData) propertyChanged(tag PropertyName) {
2024-11-13 12:56:39 +03:00
switch tag {
case Content:
updateInnerHTML(container.htmlID(), container.Session())
2024-11-13 12:56:39 +03:00
default:
container.viewData.propertyChanged(tag)
2024-11-13 12:56:39 +03:00
}
}
func (container *viewsContainerData) setContent(value any) bool {
2021-09-07 17:36:50 +03:00
session := container.Session()
switch value := value.(type) {
case View:
container.views = []View{value}
case []View:
container.views = value
case string:
container.views = []View{viewFromTextValue(value, session)}
case []string:
views := []View{}
for _, text := range value {
views = append(views, viewFromTextValue(text, session))
}
container.views = views
2022-07-26 18:36:00 +03:00
case []any:
2021-09-07 17:36:50 +03:00
views := []View{}
for _, v := range value {
switch v := v.(type) {
case View:
views = append(views, v)
case string:
views = append(views, viewFromTextValue(v, session))
default:
notCompatibleType(Content, value)
2021-09-07 17:36:50 +03:00
return false
}
}
container.views = views
case DataObject:
if view := CreateViewFromObject(session, value); view != nil {
container.views = []View{view}
} else {
return false
}
case []DataValue:
views := []View{}
for _, data := range value {
if data.IsObject() {
if view := CreateViewFromObject(session, data.Object()); view != nil {
views = append(views, view)
}
} else {
views = append(views, viewFromTextValue(data.Value(), session))
}
}
container.views = views
default:
notCompatibleType(Content, value)
2021-09-07 17:36:50 +03:00
return false
}
htmlID := container.htmlID()
isDisabled := IsDisabled(container)
2021-09-07 17:36:50 +03:00
for _, view := range container.views {
view.setParentID(htmlID)
if isDisabled {
view.Set(Disabled, true)
}
2021-09-07 17:36:50 +03:00
}
return true
}
func (container *viewsContainerData) getFunc(tag PropertyName) any {
2021-09-07 17:36:50 +03:00
switch tag {
case Content:
return container.views
default:
return container.viewData.getFunc(tag)
2021-09-07 17:36:50 +03:00
}
}
// AppendView appends a view to the end of the list of a view children
func AppendView(rootView View, containerID string, view View) bool {
var container ViewsContainer = nil
if containerID != "" {
container = ViewsContainerByID(rootView, containerID)
} else {
if cont, ok := rootView.(ViewsContainer); ok {
container = cont
} else {
ErrorLogF(`Unable to add a view to "%s"`, rootView.Tag())
}
}
if container != nil {
container.Append(view)
return true
}
return false
}
// Insert inserts a view to the "index" position in the list of a view children
func InsertView(rootView View, containerID string, view View, index int) bool {
2021-09-07 17:36:50 +03:00
var container ViewsContainer = nil
if containerID != "" {
container = ViewsContainerByID(rootView, containerID)
} else {
if cont, ok := rootView.(ViewsContainer); ok {
container = cont
} else {
ErrorLogF(`Unable to add a view to "%s"`, rootView.Tag())
}
}
if container != nil {
container.Insert(view, index)
return true
}
return false
}
// Remove removes a view from the list of a view children and return it
func RemoveView(rootView View, containerID string, index int) View {
2021-09-07 17:36:50 +03:00
var container ViewsContainer = nil
if containerID != "" {
container = ViewsContainerByID(rootView, containerID)
} else {
if cont, ok := rootView.(ViewsContainer); ok {
container = cont
} else {
ErrorLogF(`Unable to add a view to "%s"`, rootView.Tag())
}
}
if container != nil {
return container.RemoveView(index)
}
return nil
}