rui_orig/viewsContainer.go

371 lines
8.7 KiB
Go

package rui
import "strings"
type ParentView interface {
// Views return a list of child views
Views() []View
}
// ViewsContainer - mutable list-container of Views
type ViewsContainer interface {
View
ParentView
// 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 int)
// Remove removes a view from the list of a view children and return it
RemoveView(index int) View
// ViewIndex returns the index of view, -1 overwise
ViewIndex(view View) int
}
type viewsContainerData struct {
viewData
views []View
}
// Init initialize fields of ViewsContainer by default values
func (container *viewsContainerData) init(session Session) {
container.viewData.init(session)
container.tag = "ViewsContainer"
container.views = []View{}
}
func (container *viewsContainerData) String() string {
return getViewString(container, nil)
}
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{}
} else if count := len(container.views); count > 0 {
views := make([]View, count)
copy(views, container.views)
return views
}
return []View{}
}
// 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 container.views == nil || len(container.views) == 0 {
container.views = []View{view}
} else {
container.views = append(container.views, view)
}
updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
}
}
// Insert inserts a view to the "index" position in the list of a view children
func (container *viewsContainerData) Insert(view View, index int) {
if view != nil {
htmlID := container.htmlID()
if container.views == nil || index < 0 || index >= len(container.views) {
container.Append(view)
} else if index > 0 {
view.setParentID(htmlID)
container.views = append(container.views[:index], append([]View{view}, container.views[index:]...)...)
updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
} else {
view.setParentID(htmlID)
container.views = append([]View{view}, container.views...)
updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
}
}
}
// Remove removes view from list and return it
func (container *viewsContainerData) RemoveView(index int) View {
if container.views == nil {
container.views = []View{}
return nil
}
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 == count-1 {
container.views = container.views[:index]
} else {
container.views = append(container.views[:index], container.views[index+1:]...)
}
view.setParentID("")
updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
return view
}
func (container *viewsContainerData) ViewIndex(view View) int {
for index, v := range container.views {
if v == view {
return index
}
}
return -1
}
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 {
viewHTML(view, buffer)
}
}
}
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) Remove(tag string) {
container.remove(strings.ToLower(tag))
}
func (container *viewsContainerData) remove(tag string) {
switch tag {
case Content:
if container.views == nil || len(container.views) > 0 {
container.views = []View{}
updateInnerHTML(container.htmlID(), container.Session())
}
container.propertyChangedEvent(Content)
case Disabled:
if _, ok := container.properties[Disabled]; ok {
delete(container.properties, Disabled)
if container.views != nil {
for _, view := range container.views {
view.Remove(Disabled)
}
}
container.propertyChangedEvent(tag)
}
default:
container.viewData.remove(tag)
}
}
func (container *viewsContainerData) Set(tag string, value any) bool {
return container.set(strings.ToLower(tag), value)
}
func (container *viewsContainerData) set(tag string, value any) bool {
if value == nil {
container.remove(tag)
return true
}
switch tag {
case Content:
// do nothing
case Disabled:
oldDisabled := IsDisabled(container)
if container.viewData.Set(Disabled, value) {
disabled := IsDisabled(container)
if oldDisabled != disabled {
if container.views != nil {
for _, view := range container.views {
view.Set(Disabled, disabled)
}
}
}
container.propertyChangedEvent(tag)
return true
}
return false
default:
return container.viewData.set(tag, value)
}
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
case []any:
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(tag, value)
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(tag, value)
return false
}
htmlID := container.htmlID()
for _, view := range container.views {
view.setParentID(htmlID)
}
if container.created {
updateInnerHTML(htmlID, container.session)
}
container.propertyChangedEvent(Content)
return true
}
func (container *viewsContainerData) Get(tag string) any {
return container.get(strings.ToLower(tag))
}
func (container *viewsContainerData) get(tag string) any {
switch tag {
case Content:
return container.views
default:
return container.viewData.get(tag)
}
}
// 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 {
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 {
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
}