From 73b14ed78a97ac518197b900210e856fc8eda021 Mon Sep 17 00:00:00 2001 From: Alexei Anoshenko <2277098+anoshenko@users.noreply.github.com> Date: Tue, 24 Jun 2025 13:53:36 +0300 Subject: [PATCH] Adde binding parameter to CreateView functions --- detailsView.go | 2 +- listView.go | 2 +- resizable.go | 2 +- viewFactory.go | 138 ++++++++++++++++++++++++++-------------------- viewsContainer.go | 9 ++- 5 files changed, 86 insertions(+), 67 deletions(-) diff --git a/detailsView.go b/detailsView.go index 48701d5..5d4417e 100644 --- a/detailsView.go +++ b/detailsView.go @@ -92,7 +92,7 @@ func (detailsView *detailsViewData) setFunc(tag PropertyName, value any) []Prope value.setParentID(detailsView.htmlID()) case DataObject: - if view := CreateViewFromObject(detailsView.Session(), value); view != nil { + if view := CreateViewFromObject(detailsView.Session(), value, nil); view != nil { detailsView.setRaw(Summary, view) view.setParentID(detailsView.htmlID()) } else { diff --git a/listView.go b/listView.go index f685114..5103631 100644 --- a/listView.go +++ b/listView.go @@ -336,7 +336,7 @@ func (listView *listViewData) setItems(value any) []PropertyName { items := make([]View, len(value)) for i, val := range value { if val.IsObject() { - if view := CreateViewFromObject(session, val.Object()); view != nil { + if view := CreateViewFromObject(session, val.Object(), nil); view != nil { items[i] = view } else { return nil diff --git a/resizable.go b/resizable.go index 183c22c..96297b0 100644 --- a/resizable.go +++ b/resizable.go @@ -118,7 +118,7 @@ func (resizable *resizableData) setFunc(tag PropertyName, value any) []PropertyN newContent = value case DataObject: - if newContent = CreateViewFromObject(resizable.Session(), value); newContent == nil { + if newContent = CreateViewFromObject(resizable.Session(), value, nil); newContent == nil { return nil } diff --git a/viewFactory.go b/viewFactory.go index 2fa553c..dbd70d6 100644 --- a/viewFactory.go +++ b/viewFactory.go @@ -6,7 +6,7 @@ import ( "strings" ) -var viewCreators = map[string]func(Session) View{ +var systemViewCreators = map[string]func(Session) View{ "View": newView, "ColumnLayout": newColumnLayout, "ListLayout": newListLayout, @@ -36,84 +36,104 @@ var viewCreators = map[string]func(Session) View{ "VideoPlayer": newVideoPlayer, } +var viewCreate map[string]func(Session) View = nil + +func viewCreators() map[string]func(Session) View { + if viewCreate == nil { + viewCreate = map[string]func(Session) View{} + for tag, fn := range systemViewCreators { + viewCreate[strings.ToLower(tag)] = fn + } + } + return viewCreate +} + // RegisterViewCreator register function of creating view func RegisterViewCreator(tag string, creator func(Session) View) bool { - builtinViews := []string{ - "View", - "ViewsContainer", - "ColumnLayout", - "ListLayout", - "GridLayout", - "StackLayout", - "TabsLayout", - "AbsoluteLayout", - "Resizable", - "DetailsView", - "TextView", - "Button", - "Checkbox", - "DropDownList", - "ProgressBar", - "NumberPicker", - "ColorPicker", - "DatePicker", - "TimePicker", - "EditView", - "ListView", - "CanvasView", - "ImageView", - "TableView", - } - - for _, name := range builtinViews { - if name == tag { + loTag := strings.ToLower(tag) + for name := range systemViewCreators { + if name == loTag { + ErrorLog(`It is forbidden to override the function of ` + tag + ` creating`) return false } } - viewCreators[tag] = creator + viewCreators()[loTag] = creator return true } -// CreateViewFromObject create new View and initialize it by Node data -func CreateViewFromObject(session Session, object DataObject) View { - tag := object.Tag() - - if creator, ok := viewCreators[tag]; ok { - if !session.ignoreViewUpdates() { - session.setIgnoreViewUpdates(true) - defer session.setIgnoreViewUpdates(false) - } - view := creator(session) - view.init(session) - if customView, ok := view.(CustomView); ok { - if !InitCustomView(customView, tag, session, nil) { - return nil - } - } - parseProperties(view, object) - return view +// CreateViewFromObject create new View and initialize it by DataObject data. Parameters: +// - session - the session to which the view will be attached (should not be nil); +// - object - datas describing View; +// - binding - object assigned to the Binding property (may be nil). +// +// If the function fails, it returns nil and an error message is written to the log. +func CreateViewFromObject(session Session, object DataObject, binding any) View { + if session == nil { + ErrorLog(`Session must not be nil`) + return nil } - ErrorLog(`Unknown view type "` + object.Tag() + `"`) - return nil + tag := object.Tag() + creator, ok := viewCreators()[strings.ToLower(tag)] + if !ok { + ErrorLog(`Unknown view type "` + tag + `"`) + return nil + } + + if !session.ignoreViewUpdates() { + session.setIgnoreViewUpdates(true) + defer session.setIgnoreViewUpdates(false) + } + + view := creator(session) + view.init(session) + if customView, ok := view.(CustomView); ok { + if !InitCustomView(customView, tag, session, nil) { + return nil + } + } + parseProperties(view, object) + if binding != nil { + view.setRaw(Binding, binding) + } + return view } -// CreateViewFromText create new View and initialize it by content of text -func CreateViewFromText(session Session, text string) View { +// CreateViewFromText create new View and initialize it by content of text. Parameters: +// - session - the session to which the view will be attached (should not be nil); +// - text - text describing View; +// - binding - object assigned to the Binding property (optional parameter). +// +// If the function fails, it returns nil and an error message is written to the log. +func CreateViewFromText(session Session, text string, binding ...any) View { if data := ParseDataText(text); data != nil { - return CreateViewFromObject(session, data) + var b any = nil + if len(binding) > 0 { + b = binding[0] + } + return CreateViewFromObject(session, data, b) } return nil } // CreateViewFromResources create new View and initialize it by the content of -// the resource file from "views" directory -func CreateViewFromResources(session Session, name string) View { +// the resource file from "views" directory. Parameters: +// - session - the session to which the view will be attached (should not be nil); +// - name - file name in the views folder of the application resources (it is not necessary to specify the .rui extension, it is added automatically); +// - binding - object assigned to the Binding property (optional parameter). +// +// If the function fails, it returns nil and an error message is written to the log. +func CreateViewFromResources(session Session, name string, binding ...any) View { if strings.ToLower(filepath.Ext(name)) != ".rui" { name += ".rui" } + var b any = nil + if len(binding) > 0 { + b = binding[0] + } + for _, fs := range resources.embedFS { rootDirs := resources.embedRootDirs(fs) for _, dir := range rootDirs { @@ -124,14 +144,14 @@ func CreateViewFromResources(session Session, name string) View { case viewDir: if data, err := fs.ReadFile(dir + "/" + name); err == nil { if data := ParseDataText(string(data)); data != nil { - return CreateViewFromObject(session, data) + return CreateViewFromObject(session, data, b) } } default: if data, err := fs.ReadFile(dir + "/" + viewDir + "/" + name); err == nil { if data := ParseDataText(string(data)); data != nil { - return CreateViewFromObject(session, data) + return CreateViewFromObject(session, data, b) } } } @@ -141,7 +161,7 @@ func CreateViewFromResources(session Session, name string) View { if resources.path != "" { if data, err := os.ReadFile(resources.path + viewDir + "/" + name); err == nil { if data := ParseDataText(string(data)); data != nil { - return CreateViewFromObject(session, data) + return CreateViewFromObject(session, data, b) } } } diff --git a/viewsContainer.go b/viewsContainer.go index c004b42..3d6d870 100644 --- a/viewsContainer.go +++ b/viewsContainer.go @@ -174,9 +174,8 @@ func (container *viewsContainerData) htmlSubviews(self View, buffer *strings.Bui 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 { + if data := ParseDataText(text); data != nil { + if view := CreateViewFromObject(session, data, nil); view != nil { return view } } @@ -277,7 +276,7 @@ func (container *viewsContainerData) setContent(value any) bool { container.views = views case DataObject: - if view := CreateViewFromObject(session, value); view != nil { + if view := CreateViewFromObject(session, value, nil); view != nil { container.views = []View{view} } else { return false @@ -287,7 +286,7 @@ func (container *viewsContainerData) setContent(value any) bool { views := []View{} for _, data := range value { if data.IsObject() { - if view := CreateViewFromObject(session, data.Object()); view != nil { + if view := CreateViewFromObject(session, data.Object(), nil); view != nil { views = append(views, view) } } else {