From 73cc26b54ee93af4cc17ba8c1a0ea87685a767e7 Mon Sep 17 00:00:00 2001 From: Alexei Anoshenko <2277098+anoshenko@users.noreply.github.com> Date: Sun, 6 Jul 2025 11:20:37 +0300 Subject: [PATCH] Optimisation --- angleUnit.go | 5 ++++ backgroundConicGradient.go | 49 +++++++++++++------------------------ backgroundLinearGradient.go | 37 ++++++++++++---------------- clipShape.go | 6 ++--- colorPicker.go | 4 +-- datePicker.go | 6 ++--- detailsView.go | 4 +-- dragAndDrop.go | 4 +-- dropDownList.go | 12 ++++----- editView.go | 4 +-- gridLayout.go | 8 +++--- image.go | 4 +-- imageView.go | 6 ++--- listLayout.go | 2 +- listView.go | 8 ++---- numberPicker.go | 4 +-- popup.go | 8 +++--- propertyGet.go | 8 +++--- propertySet.go | 13 ++++++---- resizable.go | 4 +-- sizeFunc.go | 2 +- stackLayout.go | 14 +++++------ tableView.go | 11 +++------ tabsLayout.go | 6 ++--- timePicker.go | 7 ++---- view.go | 18 ++++++++------ viewsContainer.go | 17 ++++++------- 27 files changed, 117 insertions(+), 154 deletions(-) diff --git a/angleUnit.go b/angleUnit.go index 422aa0f..b70f5c5 100644 --- a/angleUnit.go +++ b/angleUnit.go @@ -1,6 +1,7 @@ package rui import ( + "errors" "fmt" "math" "strconv" @@ -86,6 +87,10 @@ func StringToAngleUnit(value string) (AngleUnit, bool) { func stringToAngleUnit(value string) (AngleUnit, error) { value = strings.ToLower(strings.Trim(value, " \t\n\r")) + if value == "" { + return AngleUnit{}, errors.New(`invalid AngleUnit value: ""`) + } + setValue := func(suffix string, unitType AngleUnitType) (AngleUnit, error) { val, err := strconv.ParseFloat(value[:len(value)-len(suffix)], 64) if err != nil { diff --git a/backgroundConicGradient.go b/backgroundConicGradient.go index f44524f..48e56e4 100644 --- a/backgroundConicGradient.go +++ b/backgroundConicGradient.go @@ -65,16 +65,12 @@ func (point *BackgroundGradientAngle) color(session Session) (Color, bool) { if point.Color != nil { switch color := point.Color.(type) { case string: - if color != "" { - if color[0] == '@' { - if clr, ok := session.Color(color[1:]); ok { - return clr, true - } - } else { - if clr, ok := StringToColor(color); ok { - return clr, true - } + if ok, constName := isConstantName(color); ok { + if clr, ok := session.Color(constName); ok { + return clr, true } + } else if clr, ok := StringToColor(color); ok { + return clr, true } case Color: @@ -104,19 +100,15 @@ func (point *BackgroundGradientAngle) cssString(session Session, buffer *strings if point.Angle != nil { switch value := point.Angle.(type) { case string: - if value != "" { - if value[0] == '@' { - if val, ok := session.Constant(value[1:]); ok { - value = val - } else { - return - } + if ok, constName := isConstantName(value); ok { + if value, ok = session.Constant(constName); !ok { + return } + } - if angle, ok := StringToAngleUnit(value); ok { - buffer.WriteRune(' ') - buffer.WriteString(angle.cssString()) - } + if angle, ok := StringToAngleUnit(value); ok { + buffer.WriteRune(' ') + buffer.WriteString(angle.cssString()) } case AngleUnit: @@ -174,7 +166,7 @@ func backgroundConicGradientSet(properties Properties, tag PropertyName, value a properties.setRaw(Gradient, vector) return []PropertyName{tag} } - } else if isConstantName(value) { + } else if ok, _ := isConstantName(value); ok { properties.setRaw(Gradient, value) return []PropertyName{tag} } @@ -206,15 +198,6 @@ func backgroundConicGradientSet(properties Properties, tag PropertyName, value a return propertiesSet(properties, tag, value) } -func (gradient *backgroundConicGradient) stringToAngle(text string) (any, bool) { - if text == "" { - return nil, false - } else if text[0] == '@' { - return text, true - } - return StringToAngleUnit(text) -} - func (gradient *backgroundConicGradient) stringToGradientPoint(text string) (BackgroundGradientAngle, bool) { var result BackgroundGradientAngle colorText := "" @@ -231,7 +214,7 @@ func (gradient *backgroundConicGradient) stringToGradientPoint(text string) (Bac return result, false } - if colorText[0] == '@' { + if ok, _ := isConstantName(colorText); ok { result.Color = colorText } else if color, ok := StringToColor(colorText); ok { result.Color = color @@ -240,7 +223,9 @@ func (gradient *backgroundConicGradient) stringToGradientPoint(text string) (Bac } if pointText != "" { - if angle, ok := gradient.stringToAngle(pointText); ok { + if ok, _ := isConstantName(pointText); ok { + result.Angle = pointText + } else if angle, ok := StringToAngleUnit(text); ok { result.Angle = angle } else { return result, false diff --git a/backgroundLinearGradient.go b/backgroundLinearGradient.go index 4eb7ec7..ca0ef8b 100644 --- a/backgroundLinearGradient.go +++ b/backgroundLinearGradient.go @@ -103,14 +103,14 @@ func backgroundGradientSet(properties Properties, tag PropertyName, value any) [ case Gradient: switch value := value.(type) { case string: - if value != "" { - if strings.Contains(value, " ") || strings.Contains(value, ",") { - if points := parseGradientText(value); len(points) >= 2 { - properties.setRaw(Gradient, points) - return []PropertyName{tag} - } - } else if value[0] == '@' { - properties.setRaw(Gradient, value) + if ok, _ := isConstantName(value); ok { + properties.setRaw(Gradient, value) + return []PropertyName{tag} + } + + if strings.ContainsAny(value, " ,") { + if points := parseGradientText(value); len(points) >= 2 { + properties.setRaw(Gradient, points) return []PropertyName{tag} } } @@ -168,7 +168,7 @@ func (point *BackgroundGradientPoint) setValue(text string) bool { return false } - if colorText[0] == '@' { + if ok, _ := isConstantName(colorText); ok { point.Color = colorText } else if color, ok := StringToColor(colorText); ok { point.Color = color @@ -178,7 +178,7 @@ func (point *BackgroundGradientPoint) setValue(text string) bool { if pointText == "" { point.Pos = nil - } else if pointText[0] == '@' { + } else if ok, _ := isConstantName(pointText); ok { point.Pos = pointText } else if pos, ok := StringToSizeUnit(pointText); ok { point.Pos = pos @@ -193,17 +193,10 @@ func (point *BackgroundGradientPoint) color(session Session) (Color, bool) { if point.Color != nil { switch color := point.Color.(type) { case string: - if color != "" { - if color[0] == '@' { - if clr, ok := session.Color(color[1:]); ok { - return clr, true - } - } else { - if clr, ok := StringToColor(color); ok { - return clr, true - } - } + if ok, constName := isConstantName(color); ok { + return session.Color(constName) } + return StringToColor(color) case Color: return color, true @@ -256,8 +249,8 @@ func (gradient *backgroundGradient) writeGradient(session Session, buffer *strin switch value := value.(type) { case string: - if value != "" && value[0] == '@' { - if text, ok := session.Constant(value[1:]); ok { + if ok, constName := isConstantName(value); ok { + if text, ok := session.Constant(constName); ok { points = parseGradientText(text) } } diff --git a/clipShape.go b/clipShape.go index 5d1322e..a43d99a 100644 --- a/clipShape.go +++ b/clipShape.go @@ -450,7 +450,7 @@ func polygonClipDataSet(properties Properties, tag PropertyName, value any) []Pr for i, val := range value { switch val := val.(type) { case string: - if isConstantName(val) { + if ok, _ := isConstantName(val); ok { points[i] = val } else if size, ok := StringToSizeUnit(val); ok { points[i] = size @@ -484,7 +484,7 @@ func polygonClipDataSet(properties Properties, tag PropertyName, value any) []Pr points := make([]any, len(values)) for i, val := range values { val = strings.Trim(val, " \t\n\r") - if isConstantName(val) { + if ok, _ := isConstantName(val); ok { points[i] = val } else if size, ok := StringToSizeUnit(val); ok { points[i] = size @@ -634,7 +634,7 @@ func setClipShapePropertyProperty(properties Properties, tag PropertyName, value return []PropertyName{tag} case string: - if isConstantName(value) { + if ok, _ := isConstantName(value); ok { properties.setRaw(tag, value) return []PropertyName{tag} } diff --git a/colorPicker.go b/colorPicker.go index eddd1fa..38335d2 100644 --- a/colorPicker.go +++ b/colorPicker.go @@ -159,9 +159,7 @@ func (picker *colorPickerData) handleCommand(self View, command PropertyName, da for _, listener := range getTwoArgEventListeners[ColorPicker, Color](picker, nil, ColorChangedEvent) { listener.Run(picker, color, oldColor) } - if listener, ok := picker.changeListener[ColorPickerValue]; ok { - listener.Run(picker, ColorPickerValue) - } + picker.runChangeListener(ColorPickerValue) } } } diff --git a/datePicker.go b/datePicker.go index f923686..212beba 100644 --- a/datePicker.go +++ b/datePicker.go @@ -207,7 +207,7 @@ func (picker *datePickerData) setFunc(tag PropertyName, value any) []PropertyNam return []PropertyName{tag} case string: - if isConstantName(value) { + if ok, _ := isConstantName(value); ok { picker.setRaw(tag, value) return []PropertyName{tag} } @@ -351,9 +351,7 @@ func (picker *datePickerData) handleCommand(self View, command PropertyName, dat for _, listener := range getTwoArgEventListeners[DatePicker, time.Time](picker, nil, DateChangedEvent) { listener.Run(picker, value, oldValue) } - if listener, ok := picker.changeListener[DatePickerValue]; ok { - listener.Run(picker, DatePickerValue) - } + picker.runChangeListener(DatePickerValue) } } } diff --git a/detailsView.go b/detailsView.go index 5d4417e..1320420 100644 --- a/detailsView.go +++ b/detailsView.go @@ -192,9 +192,7 @@ func (detailsView *detailsViewData) handleCommand(self View, command PropertyNam if command == "details-open" { if n, ok := dataIntProperty(data, "open"); ok { detailsView.properties[Expanded] = (n != 0) - if listener, ok := detailsView.changeListener[Expanded]; ok { - listener.Run(detailsView, Expanded) - } + detailsView.runChangeListener(Expanded) } return true } diff --git a/dragAndDrop.go b/dragAndDrop.go index 243a4c1..6e9d751 100644 --- a/dragAndDrop.go +++ b/dragAndDrop.go @@ -608,8 +608,8 @@ func GetDragImage(view View, subviewID ...string) string { if value != nil { if img, ok := value.(string); ok { img = strings.Trim(img, " \t") - if img != "" && img[0] == '@' { - if img, ok = view.Session().ImageConstant(img[1:]); ok { + if ok, constName := isConstantName(img); ok { + if img, ok = view.Session().ImageConstant(constName); ok { return img } } else { diff --git a/dropDownList.go b/dropDownList.go index a639bf2..cc4474c 100644 --- a/dropDownList.go +++ b/dropDownList.go @@ -139,7 +139,7 @@ func parseIndicesArray(value any) ([]any, bool) { if val != nil { switch val := val.(type) { case string: - if isConstantName(val) { + if ok, _ := isConstantName(val); ok { items = append(items, val) } else if n, err := strconv.Atoi(val); err == nil { items = append(items, n) @@ -162,7 +162,7 @@ func parseIndicesArray(value any) ([]any, bool) { items := make([]any, 0, len(value)) for _, str := range value { if str = strings.Trim(str, " \t"); str != "" { - if isConstantName(str) { + if ok, _ := isConstantName(str); ok { items = append(items, str) } else if n, err := strconv.Atoi(str); err == nil { items = append(items, n) @@ -248,9 +248,7 @@ func (list *dropDownListData) handleCommand(self View, command PropertyName, dat for _, listener := range getTwoArgEventListeners[DropDownList, int](list, nil, DropDownEvent) { listener.Run(list, number, old) } - if listener, ok := list.changeListener[Current]; ok { - listener.Run(list, Current) - } + list.runChangeListener(Current) } } else { ErrorLog(err.Error()) @@ -308,8 +306,8 @@ func getIndicesArray(view View, tag PropertyName) []int { result = append(result, value) case string: - if value != "" && value[0] == '@' { - if val, ok := view.Session().Constant(value[1:]); ok { + if ok, constName := isConstantName(value); ok { + if val, ok := view.Session().Constant(constName); ok { if n, err := strconv.Atoi(val); err == nil { result = append(result, n) } diff --git a/editView.go b/editView.go index d318a44..0fa171a 100644 --- a/editView.go +++ b/editView.go @@ -271,9 +271,7 @@ func (edit *editViewData) textChanged(newText, oldText string) { for _, listener := range getTwoArgEventListeners[EditView, string](edit, nil, EditTextChangedEvent) { listener.Run(edit, newText, oldText) } - if listener, ok := edit.changeListener[Text]; ok { - listener.Run(edit, Text) - } + edit.runChangeListener(Text) } func (edit *editViewData) htmlTag() string { diff --git a/gridLayout.go b/gridLayout.go index 88f4573..13f4742 100644 --- a/gridLayout.go +++ b/gridLayout.go @@ -150,7 +150,7 @@ func setGridCellSize(properties Properties, tag PropertyName, value any) []Prope sizes := make([]any, count) for i, val := range values { val = strings.Trim(val, " \t\n\r") - if isConstantName(val) { + if ok, _ := isConstantName(val); ok { sizes[i] = val } else if fn := parseSizeFunc(val); fn != nil { sizes[i] = SizeUnit{Type: SizeFunction, Function: fn} @@ -162,7 +162,7 @@ func setGridCellSize(properties Properties, tag PropertyName, value any) []Prope } } properties.setRaw(tag, sizes) - } else if isConstantName(values[0]) { + } else if ok, _ := isConstantName(values[0]); ok { properties.setRaw(tag, values[0]) } else if size, err := stringToSizeUnit(values[0]); err == nil { properties.setRaw(tag, size) @@ -220,7 +220,7 @@ func setGridCellSize(properties Properties, tag PropertyName, value any) []Prope sizes[i] = val case string: - if isConstantName(val) { + if ok, _ := isConstantName(val); ok { sizes[i] = val } else if size, err := stringToSizeUnit(val); err == nil { sizes[i] = size @@ -458,7 +458,7 @@ func (gridLayout *gridLayoutData) UpdateGridContent() { if gridLayout.created { updateInnerHTML(gridLayout.htmlID(), gridLayout.session) } - gridLayout.contentChanged() + gridLayout.runChangeListener(Content) } } diff --git a/image.go b/image.go index bb17a52..44b80d8 100644 --- a/image.go +++ b/image.go @@ -143,8 +143,8 @@ func (manager *imageManager) imageLoadError(obj DataObject) { // LoadImage starts the async image loading by url func LoadImage(url string, onLoaded func(Image), session Session) Image { - if url != "" && url[0] == '@' { - if image, ok := session.ImageConstant(url[1:]); ok { + if ok, constName := isConstantName(url); ok { + if image, ok := session.ImageConstant(constName); ok { url = image } } diff --git a/imageView.go b/imageView.go index 9411d89..fb5df6d 100644 --- a/imageView.go +++ b/imageView.go @@ -217,11 +217,11 @@ func (imageView *imageViewData) htmlTag() string { } func imageViewSrc(view View, src string) (string, string) { - if src != "" && src[0] == '@' { - if image, ok := view.Session().ImageConstant(src[1:]); ok { + if ok, constName := isConstantName(src); ok { + if image, ok := view.Session().ImageConstant(constName); ok { src = image } else { - src = "" + return "", "" } } diff --git a/listLayout.go b/listLayout.go index 1503029..72c1e80 100644 --- a/listLayout.go +++ b/listLayout.go @@ -196,7 +196,7 @@ func (listLayout *listLayoutData) UpdateContent() { if listLayout.created { updateInnerHTML(listLayout.htmlID(), listLayout.session) } - listLayout.contentChanged() + listLayout.runChangeListener(Content) } } diff --git a/listView.go b/listView.go index 376ebd7..46ab44e 100644 --- a/listView.go +++ b/listView.go @@ -962,9 +962,7 @@ func (listView *listViewData) handleCurrent(number int) { for _, listener := range getOneArgEventListeners[ListView, int](listView, nil, ListItemSelectedEvent) { listener.Run(listView, number) } - if listener, ok := listView.changeListener[Current]; ok { - listener.Run(listView, Current) - } + listView.runChangeListener(Current) } func (listView *listViewData) onItemClick(number int) { @@ -1021,9 +1019,7 @@ func (listView *listViewData) onItemClick(number int) { } setArrayPropertyValue(listView, Checked, checkedItem) - if listener, ok := listView.changeListener[Checked]; ok { - listener.Run(listView, Checked) - } + listView.runChangeListener(Checked) for _, listener := range getOneArgEventListeners[ListView, []int](listView, nil, ListItemCheckedEvent) { listener.Run(listView, checkedItem) diff --git a/numberPicker.go b/numberPicker.go index e6a7594..33f6705 100644 --- a/numberPicker.go +++ b/numberPicker.go @@ -283,9 +283,7 @@ func (picker *numberPickerData) handleCommand(self View, command PropertyName, d for _, listener := range getTwoArgEventListeners[NumberPicker, float64](picker, nil, NumberChangedEvent) { listener.Run(picker, value, oldValue) } - if listener, ok := picker.changeListener[NumberPickerValue]; ok { - listener.Run(picker, NumberPickerValue) - } + picker.runChangeListener(NumberPickerValue) } } } diff --git a/popup.go b/popup.go index 192d3f4..759f7e3 100644 --- a/popup.go +++ b/popup.go @@ -615,8 +615,8 @@ func (popup *popupData) Set(tag PropertyName, value any) bool { popup.setRaw(Content, popup.contentView) case string: - if len(value) > 0 && value[0] == '@' { - view := CreateViewFromResources(popup.session, value[1:]) + if ok, constName := isConstantName(value); ok { + view := CreateViewFromResources(popup.session, constName) if view != nil { popup.contentView = view break @@ -1107,8 +1107,8 @@ func (popup *popupData) createTitleView() GridLayout { if value := popup.getRaw(Title); value != nil { switch value := value.(type) { case string: - if len(value) > 0 && value[0] == '@' { - title = CreateViewFromResources(session, value[1:]) + if ok, constName := isConstantName(value); ok { + title = CreateViewFromResources(session, constName) if title != nil { break } diff --git a/propertyGet.go b/propertyGet.go index 7928db9..f7475b9 100644 --- a/propertyGet.go +++ b/propertyGet.go @@ -18,8 +18,8 @@ func stringProperty(properties Properties, tag PropertyName, session Session) (s func imageProperty(properties Properties, tag PropertyName, session Session) (string, bool) { if value := properties.getRaw(tag); value != nil { if text, ok := value.(string); ok { - if text != "" && text[0] == '@' { - if image, ok := session.ImageConstant(text[1:]); ok { + if ok, constName := isConstantName(text); ok { + if image, ok := session.ImageConstant(constName); ok { return image, true } else { return "", false @@ -88,8 +88,8 @@ func valueToColor(value any, session Session) (Color, bool) { return value, true case string: - if len(value) > 1 && value[0] == '@' { - return session.Color(value[1:]) + if ok, constName := isConstantName(value); ok { + return session.Color(constName) } return StringToColor(value) } diff --git a/propertySet.go b/propertySet.go index 6291f99..4cb8115 100644 --- a/propertySet.go +++ b/propertySet.go @@ -511,10 +511,10 @@ func invalidPropertyValue(tag PropertyName, value any) { ErrorLogF(`Invalid value "%v" of "%s" property`, value, string(tag)) } -func isConstantName(text string) bool { +func isConstantName(text string) (bool, string) { len := len(text) if len <= 1 || text[0] != '@' { - return false + return false, "" } if len > 2 { @@ -522,11 +522,14 @@ func isConstantName(text string) bool { if (text[1] == '`' && text[last] == '`') || (text[1] == '"' && text[last] == '"') || (text[1] == '\'' && text[last] == '\'') { - return true + return true, text[2:last] } } - return !strings.ContainsAny(text, ",;|\"'`+(){}[]<>/\\*&%! \t\n\r") + if strings.ContainsAny(text, ",;|\"'`+(){}[]<>/\\*&%! \t\n\r") { + return false, "" + } + return true, text[1:] } func isInt(value any) (int, bool) { @@ -579,7 +582,7 @@ func setSimpleProperty(properties Properties, tag PropertyName, value any) bool properties.setRaw(tag, nil) return true } - if isConstantName(text) { + if ok, _ := isConstantName(text); ok { properties.setRaw(tag, text) return true } diff --git a/resizable.go b/resizable.go index 96297b0..69d9497 100644 --- a/resizable.go +++ b/resizable.go @@ -234,7 +234,7 @@ func resizableSetSide(properties Properties, value any) []PropertyName { val := strings.Trim(val, " \t\r\n") values[i] = val - if val[0] == '@' { + if ok, _ := isConstantName(val); ok { hasConst = true } else if n, err := strconv.Atoi(val); err == nil { if n < 1 || n > AllSides { @@ -262,7 +262,7 @@ func resizableSetSide(properties Properties, value any) []PropertyName { return []PropertyName{Side} } - } else if value[0] == '@' { + } else if ok, _ := isConstantName(value); ok { properties.setRaw(Side, value) return []PropertyName{Side} } else if n, ok := validValues[value]; ok { diff --git a/sizeFunc.go b/sizeFunc.go index b5996cf..d6e180d 100644 --- a/sizeFunc.go +++ b/sizeFunc.go @@ -130,7 +130,7 @@ func (data *sizeFuncData) parseArgs(args []any, allowNumber bool) bool { return false } - if arg[0] == '@' { + if ok, _ := isConstantName(arg); ok { data.args = append(data.args, arg) } else if val, err := strconv.ParseFloat(arg, 64); err == nil { return numberArg(i, val) diff --git a/stackLayout.go b/stackLayout.go index ed9caef..89de384 100644 --- a/stackLayout.go +++ b/stackLayout.go @@ -377,7 +377,7 @@ func (layout *stackLayoutData) transitionFinished(view View, tag PropertyName) { } } delete(layout.onPushFinished, viewID) - layout.contentChanged() + layout.runChangeListener(Content) } case "pop": @@ -416,7 +416,7 @@ func (layout *stackLayoutData) transitionFinished(view View, tag PropertyName) { session.removeProperty(pageID, "ontransitionend") session.removeProperty(pageID, "ontransitioncancel") session.finishUpdateScript(pageID) - layout.contentChanged() + layout.runChangeListener(Content) if finished, ok := layout.onMoveFinished[viewID]; ok { for _, listener := range finished.listener { @@ -566,7 +566,7 @@ func (layout *stackLayoutData) moveToFrontByIndex(index int, onShow []func(View) if transform == nil { session.updateCSSProperty(peekPageID, "visibility", "hidden") session.updateCSSProperty(pageID, "visibility", "visible") - layout.contentChanged() + layout.runChangeListener(Content) for _, listener := range onShow { if listener != nil { listener(view) @@ -677,7 +677,7 @@ func (layout *stackLayoutData) Append(view View) { } session.appendToInnerHTML(stackID, buffer.String()) - layout.contentChanged() + layout.runChangeListener(Content) } } @@ -713,7 +713,7 @@ func (layout *stackLayoutData) Insert(view View, index int) { session := layout.Session() session.appendToInnerHTML(stackID, buffer.String()) - layout.contentChanged() + layout.runChangeListener(Content) } // Remove removes view from list and return it @@ -744,7 +744,7 @@ func (layout *stackLayoutData) RemoveView(index int) View { } layout.Session().callFunc("removeView", view.htmlID()+"page") - layout.contentChanged() + layout.runChangeListener(Content) return view } @@ -839,7 +839,7 @@ func (layout *stackLayoutData) Pop(onPopFinished ...func(View)) bool { view.setParentID("") layout.views = layout.views[:peek] - layout.contentChanged() + layout.runChangeListener(Content) layout.onPopFinished[view.htmlID()] = popFinished{ view: view, diff --git a/tableView.go b/tableView.go index 6dfdc69..b67a7c4 100644 --- a/tableView.go +++ b/tableView.go @@ -695,7 +695,7 @@ func (table *tableViewData) setFunc(tag PropertyName, value any) []PropertyName case HeadHeight, FootHeight: switch value := value.(type) { case string: - if isConstantName(value) { + if ok, _ := isConstantName(value); ok { table.setRaw(tag, value) } else if n, err := strconv.Atoi(value); err == nil { table.setRaw(tag, n) @@ -1675,13 +1675,10 @@ func (table *tableViewData) handleCommand(self View, command PropertyName, data if row, ok := dataIntProperty(data, "row"); ok && row != current.Row { current.Row = row table.setRaw(Current, current.Row) - if listener, ok := table.changeListener[Current]; ok { - listener.Run(table, Current) - } - for _, listener := range getOneArgEventListeners[TableView, int](table, nil, TableRowSelectedEvent) { listener.Run(table, row) } + table.runChangeListener(Current) } case "currentCell": @@ -1692,13 +1689,11 @@ func (table *tableViewData) handleCommand(self View, command PropertyName, data current.Row = row current.Column = column table.setRaw(Current, current.Row) - if listener, ok := table.changeListener[Current]; ok { - listener.Run(table, Current) - } for _, listener := range getTwoArgEventListeners[TableView, int](table, nil, TableCellSelectedEvent) { listener.Run(table, row, column) } + table.runChangeListener(Current) } } } diff --git a/tabsLayout.go b/tabsLayout.go index c11eb97..b14efb8 100644 --- a/tabsLayout.go +++ b/tabsLayout.go @@ -403,7 +403,7 @@ func (tabsLayout *tabsLayoutData) Append(view View) { view.SetChangeListener(TabCloseButton, tabsLayout.updateTabCloseButton) if tabsLayout.created { updateInnerHTML(tabsLayout.htmlID(), tabsLayout.Session()) - tabsLayout.contentChanged() + tabsLayout.runChangeListener(Content) tabsLayout.Set(Current, len(tabsLayout.views)-1) } } @@ -427,7 +427,7 @@ func (tabsLayout *tabsLayoutData) currentChanged(newCurrent, oldCurrent int) { for _, listener := range getTwoArgEventListeners[TabsLayout, int](tabsLayout, nil, CurrentTabChangedEvent) { listener.Run(tabsLayout, newCurrent, oldCurrent) } - tabsLayout.contentChanged() + tabsLayout.runChangeListener(Current) } // Remove removes view from list and return it @@ -453,7 +453,7 @@ func (tabsLayout *tabsLayoutData) RemoveView(index int) View { tabsLayout.Set(Current, newCurrent) } updateInnerHTML(tabsLayout.htmlID(), tabsLayout.Session()) - tabsLayout.contentChanged() + tabsLayout.runChangeListener(Content) } else if newCurrent != oldCurrent { tabsLayout.setRaw(Current, newCurrent) } diff --git a/timePicker.go b/timePicker.go index db7261e..0579e5a 100644 --- a/timePicker.go +++ b/timePicker.go @@ -176,7 +176,7 @@ func (picker *timePickerData) setFunc(tag PropertyName, value any) []PropertyNam return []PropertyName{tag} case string: - if isConstantName(value) { + if ok, _ := isConstantName(value); ok { picker.setRaw(tag, value) return []PropertyName{tag} } @@ -323,10 +323,7 @@ func (picker *timePickerData) handleCommand(self View, command PropertyName, dat for _, listener := range getTwoArgEventListeners[TimePicker, time.Time](picker, nil, TimeChangedEvent) { listener.Run(picker, value, oldValue) } - if listener, ok := picker.changeListener[TimePickerValue]; ok { - listener.Run(picker, TimePickerValue) - } - + picker.runChangeListener(TimePickerValue) } } } diff --git a/view.go b/view.go index ff9fc19..d4735dc 100644 --- a/view.go +++ b/view.go @@ -246,15 +246,19 @@ func (view *viewData) Focusable() bool { return false } +func (view *viewData) runChangeListener(tag PropertyName) { + if listener, ok := view.changeListener[tag]; ok { + listener.Run(view, tag) + } +} + func (view *viewData) Remove(tag PropertyName) { changedTags := view.removeFunc(view.normalize(tag)) if view.created && len(changedTags) > 0 { for _, tag := range changedTags { view.changed(tag) - if listener, ok := view.changeListener[tag]; ok { - listener.Run(view, tag) - } + view.runChangeListener(tag) } } } @@ -280,9 +284,7 @@ func (view *viewData) Set(tag PropertyName, value any) bool { if view.created && len(changedTags) > 0 { for _, tag := range changedTags { view.changed(tag) - if listener, ok := view.changeListener[tag]; ok { - listener.Run(view, tag) - } + view.runChangeListener(tag) } } @@ -910,8 +912,8 @@ func (view *viewData) propertyChanged(tag PropertyName) { case DragImage: if img, ok := stringProperty(view, DragImage, session); ok && img != "" { img = strings.Trim(img, " \t") - if img[0] == '@' { - img, ok = session.ImageConstant(img[1:]) + if ok, constName := isConstantName(img); ok { + img, ok = session.ImageConstant(constName) if !ok { session.removeProperty(htmlID, "data-drag-image") return diff --git a/viewsContainer.go b/viewsContainer.go index 68a3811..d925653 100644 --- a/viewsContainer.go +++ b/viewsContainer.go @@ -88,13 +88,7 @@ func (container *viewsContainerData) Append(view View) { viewHTML(view, buffer, "") container.Session().appendToInnerHTML(container.htmlID(), buffer.String()) - container.contentChanged() - } -} - -func (container *viewsContainerData) contentChanged() { - if listener, ok := container.changeListener[Content]; ok { - listener.Run(container, Content) + container.runChangeListener(Content) } } @@ -119,7 +113,7 @@ func (container *viewsContainerData) insert(view View, index int) bool { func (container *viewsContainerData) Insert(view View, index int) { if container.insert(view, index) && container.created { updateInnerHTML(container.htmlID(), container.Session()) - container.contentChanged() + container.runChangeListener(Content) } } @@ -153,7 +147,7 @@ func (container *viewsContainerData) RemoveView(index int) View { view := container.removeView(index) if view != nil && container.created { container.Session().callFunc("removeView", view.htmlID()) - container.contentChanged() + container.runChangeListener(Content) } return view } @@ -190,6 +184,11 @@ func viewFromTextValue(text string, session Session) View { return view } } + if ok, constName := isConstantName(text); ok { + if view := CreateViewFromResources(session, constName); view != nil { + return view + } + } return NewTextView(session, Params{Text: text}) }