forked from mbk-lab/rui_orig
2
0
Fork 0

Add a listener for changing a property value

This commit is contained in:
anoshenko 2021-11-20 11:15:28 +03:00
parent 584983b818
commit 7e2804f002
30 changed files with 1024 additions and 555 deletions

View File

@ -53,6 +53,7 @@ func (canvasView *canvasViewData) remove(tag string) {
if tag == DrawFunction { if tag == DrawFunction {
canvasView.drawer = nil canvasView.drawer = nil
canvasView.Redraw() canvasView.Redraw()
canvasView.propertyChangedEvent(tag)
} else { } else {
canvasView.viewData.remove(tag) canvasView.viewData.remove(tag)
} }
@ -73,6 +74,7 @@ func (canvasView *canvasViewData) set(tag string, value interface{}) bool {
return false return false
} }
canvasView.Redraw() canvasView.Redraw()
canvasView.propertyChangedEvent(tag)
return true return true
} }

View File

@ -57,13 +57,16 @@ func (button *checkboxData) Get(tag string) interface{} {
} }
func (button *checkboxData) Set(tag string, value interface{}) bool { func (button *checkboxData) Set(tag string, value interface{}) bool {
switch strings.ToLower(tag) { return button.set(tag, value)
case CheckboxChangedEvent: }
ok := button.setChangedListener(value)
if !ok { func (button *checkboxData) set(tag string, value interface{}) bool {
notCompatibleType(tag, value) switch tag {
case CheckboxChangedEvent:
if !button.setChangedListener(value) {
notCompatibleType(tag, value)
return false
} }
return ok
case Checked: case Checked:
oldChecked := button.checked() oldChecked := button.checked()
@ -76,46 +79,60 @@ func (button *checkboxData) Set(tag string, value interface{}) bool {
button.changedCheckboxState(checked) button.changedCheckboxState(checked)
} }
} }
return true
case CheckboxHorizontalAlign, CheckboxVerticalAlign: case CheckboxHorizontalAlign, CheckboxVerticalAlign:
if button.setEnumProperty(tag, value, enumProperties[tag].values) { if !button.setEnumProperty(tag, value, enumProperties[tag].values) {
return false
}
if button.created { if button.created {
htmlID := button.htmlID() htmlID := button.htmlID()
updateCSSStyle(htmlID, button.session) updateCSSStyle(htmlID, button.session)
updateInnerHTML(htmlID, button.session) updateInnerHTML(htmlID, button.session)
} }
return true
}
return false
case VerticalAlign: case VerticalAlign:
if button.setEnumProperty(tag, value, enumProperties[tag].values) { if !button.setEnumProperty(tag, value, enumProperties[tag].values) {
return false
}
if button.created { if button.created {
updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session) updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session)
} }
return true
}
return false
case HorizontalAlign: case HorizontalAlign:
if button.setEnumProperty(tag, value, enumProperties[tag].values) { if !button.setEnumProperty(tag, value, enumProperties[tag].values) {
return false
}
if button.created { if button.created {
updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session) updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session)
} }
return true
}
return false
case CellVerticalAlign, CellHorizontalAlign, CellWidth, CellHeight: case CellVerticalAlign, CellHorizontalAlign, CellWidth, CellHeight:
return false return false
default:
return button.viewsContainerData.set(tag, value)
} }
return button.viewsContainerData.Set(tag, value) button.propertyChangedEvent(tag)
return true
} }
func (button *checkboxData) Remove(tag string) { func (button *checkboxData) Remove(tag string) {
switch strings.ToLower(tag) { button.remove(strings.ToLower(tag))
}
func (button *checkboxData) remove(tag string) {
switch tag {
case ClickEvent:
if !button.viewsContainerData.set(ClickEvent, checkboxClickListener) {
delete(button.properties, tag)
}
case KeyDownEvent:
if !button.viewsContainerData.set(KeyDownEvent, checkboxKeyListener) {
delete(button.properties, tag)
}
case CheckboxChangedEvent: case CheckboxChangedEvent:
if len(button.checkedListeners) > 0 { if len(button.checkedListeners) > 0 {
button.checkedListeners = []func(Checkbox, bool){} button.checkedListeners = []func(Checkbox, bool){}
@ -124,27 +141,35 @@ func (button *checkboxData) Remove(tag string) {
case Checked: case Checked:
oldChecked := button.checked() oldChecked := button.checked()
delete(button.properties, tag) delete(button.properties, tag)
if oldChecked { if button.created && oldChecked {
button.changedCheckboxState(false) button.changedCheckboxState(false)
} }
case CheckboxHorizontalAlign, CheckboxVerticalAlign: case CheckboxHorizontalAlign, CheckboxVerticalAlign:
delete(button.properties, tag) delete(button.properties, tag)
if button.created {
htmlID := button.htmlID() htmlID := button.htmlID()
updateCSSStyle(htmlID, button.session) updateCSSStyle(htmlID, button.session)
updateInnerHTML(htmlID, button.session) updateInnerHTML(htmlID, button.session)
}
case VerticalAlign: case VerticalAlign:
delete(button.properties, tag) delete(button.properties, tag)
if button.created {
updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session) updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session)
}
case HorizontalAlign: case HorizontalAlign:
delete(button.properties, tag) delete(button.properties, tag)
if button.created {
updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session) updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session)
}
default: default:
button.viewsContainerData.Remove(tag) button.viewsContainerData.remove(tag)
return
} }
button.propertyChangedEvent(tag)
} }
func (button *checkboxData) checked() bool { func (button *checkboxData) checked() bool {

View File

@ -56,7 +56,10 @@ func (picker *colorPickerData) Remove(tag string) {
func (picker *colorPickerData) remove(tag string) { func (picker *colorPickerData) remove(tag string) {
switch tag { switch tag {
case ColorChangedEvent: case ColorChangedEvent:
if len(picker.colorChangedListeners) > 0 {
picker.colorChangedListeners = []func(ColorPicker, Color){} picker.colorChangedListeners = []func(ColorPicker, Color){}
picker.propertyChangedEvent(tag)
}
case ColorPickerValue: case ColorPickerValue:
oldColor := GetColorPickerValue(picker, "") oldColor := GetColorPickerValue(picker, "")
@ -131,15 +134,13 @@ func (picker *colorPickerData) set(tag string, value interface{}) bool {
} }
picker.colorChangedListeners = listeners picker.colorChangedListeners = listeners
} }
picker.propertyChangedEvent(tag)
return true return true
case ColorPickerValue: case ColorPickerValue:
oldColor := GetColorPickerValue(picker, "") oldColor := GetColorPickerValue(picker, "")
if picker.setColorProperty(ColorPickerValue, value) { if picker.setColorProperty(ColorPickerValue, value) {
newValue := GetColorPickerValue(picker, "")
if oldColor != newValue {
picker.colorChanged(oldColor) picker.colorChanged(oldColor)
}
return true return true
} }
@ -150,12 +151,14 @@ func (picker *colorPickerData) set(tag string, value interface{}) bool {
} }
func (picker *colorPickerData) colorChanged(oldColor Color) { func (picker *colorPickerData) colorChanged(oldColor Color) {
newColor := GetColorPickerValue(picker, "") if newColor := GetColorPickerValue(picker, ""); oldColor != newColor {
if oldColor != newColor { if picker.created {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newColor.rgbString())) picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newColor.rgbString()))
}
for _, listener := range picker.colorChangedListeners { for _, listener := range picker.colorChangedListeners {
listener(picker, newColor) listener(picker, newColor)
} }
picker.propertyChangedEvent(ColorTag)
} }
} }
@ -188,7 +191,7 @@ func (picker *colorPickerData) htmlProperties(self View, buffer *strings.Builder
} }
func (picker *colorPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (picker *colorPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
if IsDisabled(self) { if IsDisabled(self, "") {
buffer.WriteString(` disabled`) buffer.WriteString(` disabled`)
} }
picker.viewData.htmlDisabledProperties(self, buffer) picker.viewData.htmlDisabledProperties(self, buffer)

View File

@ -82,6 +82,7 @@ func (columnLayout *columnLayoutData) Remove(tag string) {
func (columnLayout *columnLayoutData) remove(tag string) { func (columnLayout *columnLayoutData) remove(tag string) {
columnLayout.viewsContainerData.remove(tag) columnLayout.viewsContainerData.remove(tag)
if columnLayout.created {
switch tag { switch tag {
case ColumnCount, ColumnWidth, ColumnGap: case ColumnCount, ColumnWidth, ColumnGap:
updateCSSProperty(columnLayout.htmlID(), tag, "", columnLayout.Session()) updateCSSProperty(columnLayout.htmlID(), tag, "", columnLayout.Session())
@ -90,6 +91,7 @@ func (columnLayout *columnLayoutData) remove(tag string) {
updateCSSProperty(columnLayout.htmlID(), "column-rule", "", columnLayout.Session()) updateCSSProperty(columnLayout.htmlID(), "column-rule", "", columnLayout.Session())
} }
} }
}
func (columnLayout *columnLayoutData) Set(tag string, value interface{}) bool { func (columnLayout *columnLayoutData) Set(tag string, value interface{}) bool {
return columnLayout.set(columnLayout.normalizeTag(tag), value) return columnLayout.set(columnLayout.normalizeTag(tag), value)
@ -101,22 +103,11 @@ func (columnLayout *columnLayoutData) set(tag string, value interface{}) bool {
return true return true
} }
switch tag { if !columnLayout.viewsContainerData.set(tag, value) {
case ColumnCount:
if columnLayout.setIntProperty(tag, value) {
session := columnLayout.Session()
if count, ok := intProperty(columnLayout, tag, session, 0); ok && count > 0 {
updateCSSProperty(columnLayout.htmlID(), tag, strconv.Itoa(count), session)
} else {
updateCSSProperty(columnLayout.htmlID(), tag, "auto", session)
}
return true
}
return false return false
} }
ok := columnLayout.viewsContainerData.set(tag, value) if columnLayout.created {
if ok {
switch tag { switch tag {
case ColumnSeparator: case ColumnSeparator:
css := "" css := ""
@ -126,9 +117,17 @@ func (columnLayout *columnLayoutData) set(tag string, value interface{}) bool {
css = separator.cssValue(columnLayout.Session()) css = separator.cssValue(columnLayout.Session())
} }
updateCSSProperty(columnLayout.htmlID(), "column-rule", css, session) updateCSSProperty(columnLayout.htmlID(), "column-rule", css, session)
case ColumnCount:
session := columnLayout.Session()
if count, ok := intProperty(columnLayout, tag, session, 0); ok && count > 0 {
updateCSSProperty(columnLayout.htmlID(), tag, strconv.Itoa(count), session)
} else {
updateCSSProperty(columnLayout.htmlID(), tag, "auto", session)
} }
} }
return ok }
return true
} }
// GetColumnCount returns int value which specifies number of columns into which the content of // GetColumnCount returns int value which specifies number of columns into which the content of

View File

@ -68,6 +68,10 @@ func (customView *CustomViewData) SetAnimated(tag string, value interface{}, ani
return customView.superView.SetAnimated(tag, value, animation) return customView.superView.SetAnimated(tag, value, animation)
} }
func (customView *CustomViewData) SetChangeListener(tag string, listener func(View, string)) {
customView.superView.SetChangeListener(tag, listener)
}
// Remove removes the property with name defined by the argument // Remove removes the property with name defined by the argument
func (customView *CustomViewData) Remove(tag string) { func (customView *CustomViewData) Remove(tag string) {
customView.superView.Remove(tag) customView.superView.Remove(tag)

View File

@ -63,28 +63,47 @@ func (picker *datePickerData) remove(tag string) {
case DateChangedEvent: case DateChangedEvent:
if len(picker.dateChangedListeners) > 0 { if len(picker.dateChangedListeners) > 0 {
picker.dateChangedListeners = []func(DatePicker, time.Time){} picker.dateChangedListeners = []func(DatePicker, time.Time){}
picker.propertyChangedEvent(tag)
} }
return
case DatePickerMin: case DatePickerMin:
delete(picker.properties, DatePickerMin) delete(picker.properties, DatePickerMin)
if picker.created {
removeProperty(picker.htmlID(), Min, picker.session) removeProperty(picker.htmlID(), Min, picker.session)
}
case DatePickerMax: case DatePickerMax:
delete(picker.properties, DatePickerMax) delete(picker.properties, DatePickerMax)
if picker.created {
removeProperty(picker.htmlID(), Max, picker.session) removeProperty(picker.htmlID(), Max, picker.session)
}
case DatePickerStep: case DatePickerStep:
delete(picker.properties, DatePickerMax) delete(picker.properties, DatePickerMax)
if picker.created {
removeProperty(picker.htmlID(), Step, picker.session) removeProperty(picker.htmlID(), Step, picker.session)
}
case DatePickerValue: case DatePickerValue:
if _, ok := picker.properties[DatePickerValue]; ok {
delete(picker.properties, DatePickerValue) delete(picker.properties, DatePickerValue)
updateProperty(picker.htmlID(), Value, time.Now().Format(dateFormat), picker.session) date := GetDatePickerValue(picker, "")
if picker.created {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat)))
}
for _, listener := range picker.dateChangedListeners {
listener(picker, date)
}
} else {
return
}
default: default:
picker.viewData.remove(tag) picker.viewData.remove(tag)
picker.propertyChanged(tag) return
} }
picker.propertyChangedEvent(tag)
} }
func (picker *datePickerData) Set(tag string, value interface{}) bool { func (picker *datePickerData) Set(tag string, value interface{}) bool {
@ -98,7 +117,6 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
} }
setTimeValue := func(tag string) (time.Time, bool) { setTimeValue := func(tag string) (time.Time, bool) {
//old, oldOK := getDateProperty(picker, tag, shortTag)
switch value := value.(type) { switch value := value.(type) {
case time.Time: case time.Time:
picker.properties[tag] = value picker.properties[tag] = value
@ -122,8 +140,11 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
old, oldOK := getDateProperty(picker, DatePickerMin, Min) old, oldOK := getDateProperty(picker, DatePickerMin, Min)
if date, ok := setTimeValue(DatePickerMin); ok { if date, ok := setTimeValue(DatePickerMin); ok {
if !oldOK || date != old { if !oldOK || date != old {
if picker.created {
updateProperty(picker.htmlID(), Min, date.Format(dateFormat), picker.session) updateProperty(picker.htmlID(), Min, date.Format(dateFormat), picker.session)
} }
picker.propertyChangedEvent(tag)
}
return true return true
} }
@ -131,33 +152,41 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
old, oldOK := getDateProperty(picker, DatePickerMax, Max) old, oldOK := getDateProperty(picker, DatePickerMax, Max)
if date, ok := setTimeValue(DatePickerMax); ok { if date, ok := setTimeValue(DatePickerMax); ok {
if !oldOK || date != old { if !oldOK || date != old {
if picker.created {
updateProperty(picker.htmlID(), Max, date.Format(dateFormat), picker.session) updateProperty(picker.htmlID(), Max, date.Format(dateFormat), picker.session)
} }
picker.propertyChangedEvent(tag)
}
return true return true
} }
case DatePickerStep: case DatePickerStep:
oldStep := GetDatePickerStep(picker, "") oldStep := GetDatePickerStep(picker, "")
if picker.setIntProperty(DatePickerStep, value) { if picker.setIntProperty(DatePickerStep, value) {
step := GetDatePickerStep(picker, "") if step := GetDatePickerStep(picker, ""); oldStep != step {
if oldStep != step { if picker.created {
if step > 0 { if step > 0 {
updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session) updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session)
} else { } else {
removeProperty(picker.htmlID(), Step, picker.session) removeProperty(picker.htmlID(), Step, picker.session)
} }
} }
picker.propertyChangedEvent(tag)
}
return true return true
} }
case DatePickerValue: case DatePickerValue:
oldDate := GetDatePickerValue(picker, "") oldDate := GetDatePickerValue(picker, "")
if date, ok := setTimeValue(DatePickerMax); ok { if date, ok := setTimeValue(DatePickerMax); ok {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat)))
if date != oldDate { if date != oldDate {
if picker.created {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat)))
}
for _, listener := range picker.dateChangedListeners { for _, listener := range picker.dateChangedListeners {
listener(picker, date) listener(picker, date)
} }
picker.propertyChangedEvent(tag)
} }
return true return true
} }
@ -214,13 +243,11 @@ func (picker *datePickerData) set(tag string, value interface{}) bool {
} }
picker.dateChangedListeners = listeners picker.dateChangedListeners = listeners
} }
picker.propertyChangedEvent(tag)
return true return true
default: default:
if picker.viewData.set(tag, value) { return picker.viewData.set(tag, value)
picker.propertyChanged(tag)
return true
}
} }
return false return false
} }
@ -274,7 +301,7 @@ func (picker *datePickerData) htmlProperties(self View, buffer *strings.Builder)
} }
func (picker *datePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (picker *datePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
if IsDisabled(self) { if IsDisabled(self, "") {
buffer.WriteString(` disabled`) buffer.WriteString(` disabled`)
} }
picker.viewData.htmlDisabledProperties(self, buffer) picker.viewData.htmlDisabledProperties(self, buffer)

View File

@ -57,6 +57,15 @@ func createTextStyleDemo(session rui.Session) rui.View {
return nil return nil
} }
rui.SetChangeListener(view, "textStyleFont", rui.Current, func(v rui.View, tag string) {
fonts := []string{"", "serif", "sans-serif", "\"Courier new\", monospace", "cursive", "fantasy"}
if number := rui.GetDropDownCurrent(v, ""); number > 0 && number < len(fonts) {
rui.Set(view, "textStyleText", rui.FontName, fonts[number])
} else {
rui.Set(view, "textStyleText", rui.FontName, nil)
}
})
/*
rui.Set(view, "textStyleFont", rui.DropDownEvent, func(number int) { rui.Set(view, "textStyleFont", rui.DropDownEvent, func(number int) {
fonts := []string{"", "serif", "sans-serif", "\"Courier new\", monospace", "cursive", "fantasy"} fonts := []string{"", "serif", "sans-serif", "\"Courier new\", monospace", "cursive", "fantasy"}
if number > 0 && number < len(fonts) { if number > 0 && number < len(fonts) {
@ -65,6 +74,7 @@ func createTextStyleDemo(session rui.Session) rui.View {
rui.Set(view, "textStyleText", rui.FontName, nil) rui.Set(view, "textStyleText", rui.FontName, nil)
} }
}) })
*/
rui.Set(view, "textStyleSize", rui.DropDownEvent, func(number int) { rui.Set(view, "textStyleSize", rui.DropDownEvent, func(number int) {
sizes := []string{"1em", "14pt", "12px", "1.5em"} sizes := []string{"1em", "14pt", "12px", "1.5em"}

View File

@ -2,6 +2,8 @@ package rui
import "strings" import "strings"
// TODO Expanded event
const ( const (
// Summary is the constant for the "summary" property tag. // Summary is the constant for the "summary" property tag.
// The contents of the "summary" property are used as the label for the disclosure widget. // The contents of the "summary" property are used as the label for the disclosure widget.
@ -45,18 +47,14 @@ func (detailsView *detailsViewData) Remove(tag string) {
} }
func (detailsView *detailsViewData) remove(tag string) { func (detailsView *detailsViewData) remove(tag string) {
if _, ok := detailsView.properties[tag]; ok { detailsView.viewsContainerData.remove(tag)
if detailsView.created {
switch tag { switch tag {
case Summary: case Summary:
delete(detailsView.properties, tag)
updateInnerHTML(detailsView.htmlID(), detailsView.Session()) updateInnerHTML(detailsView.htmlID(), detailsView.Session())
case Expanded: case Expanded:
delete(detailsView.properties, tag)
removeProperty(detailsView.htmlID(), "open", detailsView.Session()) removeProperty(detailsView.htmlID(), "open", detailsView.Session())
default:
detailsView.viewsContainerData.remove(tag)
} }
} }
} }
@ -66,6 +64,11 @@ func (detailsView *detailsViewData) Set(tag string, value interface{}) bool {
} }
func (detailsView *detailsViewData) set(tag string, value interface{}) bool { func (detailsView *detailsViewData) set(tag string, value interface{}) bool {
if value == nil {
detailsView.remove(tag)
return true
}
switch tag { switch tag {
case Summary: case Summary:
switch value := value.(type) { switch value := value.(type) {
@ -86,25 +89,31 @@ func (detailsView *detailsViewData) set(tag string, value interface{}) bool {
notCompatibleType(tag, value) notCompatibleType(tag, value)
return false return false
} }
if detailsView.created {
updateInnerHTML(detailsView.htmlID(), detailsView.Session()) updateInnerHTML(detailsView.htmlID(), detailsView.Session())
return true }
case Expanded: case Expanded:
if detailsView.setBoolProperty(tag, value) { if !detailsView.setBoolProperty(tag, value) {
notCompatibleType(tag, value)
return false
}
if detailsView.created {
if IsDetailsExpanded(detailsView, "") { if IsDetailsExpanded(detailsView, "") {
updateProperty(detailsView.htmlID(), "open", "", detailsView.Session()) updateProperty(detailsView.htmlID(), "open", "", detailsView.Session())
} else { } else {
removeProperty(detailsView.htmlID(), "open", detailsView.Session()) removeProperty(detailsView.htmlID(), "open", detailsView.Session())
} }
return true
}
notCompatibleType(tag, value)
return false
} }
default:
return detailsView.viewsContainerData.Set(tag, value) return detailsView.viewsContainerData.Set(tag, value)
} }
detailsView.propertyChangedEvent(tag)
return true
}
func (detailsView *detailsViewData) Get(tag string) interface{} { func (detailsView *detailsViewData) Get(tag string) interface{} {
return detailsView.get(strings.ToLower(tag)) return detailsView.get(strings.ToLower(tag))
} }

View File

@ -48,19 +48,31 @@ func (list *dropDownListData) remove(tag string) {
case Items: case Items:
if len(list.items) > 0 { if len(list.items) > 0 {
list.items = []string{} list.items = []string{}
if list.created {
updateInnerHTML(list.htmlID(), list.session) updateInnerHTML(list.htmlID(), list.session)
} }
list.propertyChangedEvent(tag)
case Current: }
list.set(Current, 0)
case DropDownEvent: case DropDownEvent:
if len(list.dropDownListener) > 0 { if len(list.dropDownListener) > 0 {
list.dropDownListener = []func(DropDownList, int){} list.dropDownListener = []func(DropDownList, int){}
list.propertyChangedEvent(tag)
}
case Current:
oldCurrent := GetDropDownCurrent(list, "")
delete(list.properties, Current)
if oldCurrent != 0 {
if list.created {
list.session.runScript(fmt.Sprintf(`selectDropDownListItem('%s', %d)`, list.htmlID(), 0))
}
list.onSelectedItemChanged(0)
} }
default: default:
list.viewData.remove(tag) list.viewData.remove(tag)
return
} }
} }
@ -73,23 +85,22 @@ func (list *dropDownListData) set(tag string, value interface{}) bool {
case Items: case Items:
return list.setItems(value) return list.setItems(value)
case DropDownEvent:
return list.setDropDownListener(value)
case Current: case Current:
oldCurrent := GetDropDownCurrent(list, "") oldCurrent := GetDropDownCurrent(list, "")
if !list.setIntProperty(Current, value) { if !list.setIntProperty(Current, value) {
return false return false
} }
if !list.session.ignoreViewUpdates() { if current := GetDropDownCurrent(list, ""); oldCurrent != current {
current := GetDropDownCurrent(list, "") if list.created {
if oldCurrent != current {
list.session.runScript(fmt.Sprintf(`selectDropDownListItem('%s', %d)`, list.htmlID(), current)) list.session.runScript(fmt.Sprintf(`selectDropDownListItem('%s', %d)`, list.htmlID(), current))
}
list.onSelectedItemChanged(current) list.onSelectedItemChanged(current)
} }
}
return true return true
case DropDownEvent:
return list.setDropDownListener(value)
} }
return list.viewData.set(tag, value) return list.viewData.set(tag, value)
@ -160,9 +171,11 @@ func (list *dropDownListData) setItems(value interface{}) bool {
return false return false
} }
if !list.session.ignoreViewUpdates() { if list.created {
updateInnerHTML(list.htmlID(), list.session) updateInnerHTML(list.htmlID(), list.session)
} }
list.propertyChangedEvent(Items)
return true return true
} }
@ -170,17 +183,14 @@ func (list *dropDownListData) setDropDownListener(value interface{}) bool {
switch value := value.(type) { switch value := value.(type) {
case func(DropDownList, int): case func(DropDownList, int):
list.dropDownListener = []func(DropDownList, int){value} list.dropDownListener = []func(DropDownList, int){value}
return true
case func(int): case func(int):
list.dropDownListener = []func(DropDownList, int){func(list DropDownList, index int) { list.dropDownListener = []func(DropDownList, int){func(list DropDownList, index int) {
value(index) value(index)
}} }}
return true
case []func(DropDownList, int): case []func(DropDownList, int):
list.dropDownListener = value list.dropDownListener = value
return true
case []func(int): case []func(int):
listeners := make([]func(DropDownList, int), len(value)) listeners := make([]func(DropDownList, int), len(value))
@ -194,7 +204,6 @@ func (list *dropDownListData) setDropDownListener(value interface{}) bool {
} }
} }
list.dropDownListener = listeners list.dropDownListener = listeners
return true
case []interface{}: case []interface{}:
listeners := make([]func(DropDownList, int), len(value)) listeners := make([]func(DropDownList, int), len(value))
@ -216,15 +225,18 @@ func (list *dropDownListData) setDropDownListener(value interface{}) bool {
notCompatibleType(DropDownEvent, value) notCompatibleType(DropDownEvent, value)
return false return false
} }
}
list.dropDownListener = listeners list.dropDownListener = listeners
}
return true
}
default:
notCompatibleType(DropDownEvent, value) notCompatibleType(DropDownEvent, value)
return false return false
} }
list.propertyChangedEvent(DropDownEvent)
return true
}
func (list *dropDownListData) Get(tag string) interface{} { func (list *dropDownListData) Get(tag string) interface{} {
return list.get(strings.ToLower(tag)) return list.get(strings.ToLower(tag))
} }
@ -280,7 +292,7 @@ func (list *dropDownListData) htmlProperties(self View, buffer *strings.Builder)
func (list *dropDownListData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (list *dropDownListData) htmlDisabledProperties(self View, buffer *strings.Builder) {
list.viewData.htmlDisabledProperties(self, buffer) list.viewData.htmlDisabledProperties(self, buffer)
if IsDisabled(list) { if IsDisabled(list, "") {
buffer.WriteString(`disabled`) buffer.WriteString(`disabled`)
} }
} }
@ -289,6 +301,7 @@ func (list *dropDownListData) onSelectedItemChanged(number int) {
for _, listener := range list.dropDownListener { for _, listener := range list.dropDownListener {
listener(list, number) listener(list, number)
} }
list.propertyChangedEvent(Current)
} }
func (list *dropDownListData) handleCommand(self View, command string, data DataObject) bool { func (list *dropDownListData) handleCommand(self View, command string, data DataObject) bool {

View File

@ -84,63 +84,98 @@ func (edit *editViewData) Remove(tag string) {
} }
func (edit *editViewData) remove(tag string) { func (edit *editViewData) remove(tag string) {
if _, ok := edit.properties[tag]; ok { _, exists := edit.properties[tag]
switch tag { switch tag {
case Hint: case Hint:
if exists {
delete(edit.properties, Hint) delete(edit.properties, Hint)
if edit.created {
removeProperty(edit.htmlID(), "placeholder", edit.session) removeProperty(edit.htmlID(), "placeholder", edit.session)
}
edit.propertyChangedEvent(tag)
}
case MaxLength: case MaxLength:
if exists {
delete(edit.properties, MaxLength) delete(edit.properties, MaxLength)
if edit.created {
removeProperty(edit.htmlID(), "maxlength", edit.session) removeProperty(edit.htmlID(), "maxlength", edit.session)
}
edit.propertyChangedEvent(tag)
}
case ReadOnly, Spellcheck: case ReadOnly, Spellcheck:
if exists {
delete(edit.properties, tag) delete(edit.properties, tag)
if edit.created {
updateBoolProperty(edit.htmlID(), tag, false, edit.session) updateBoolProperty(edit.htmlID(), tag, false, edit.session)
}
edit.propertyChangedEvent(tag)
}
case EditTextChangedEvent: case EditTextChangedEvent:
if len(edit.textChangeListeners) > 0 { if len(edit.textChangeListeners) > 0 {
edit.textChangeListeners = []func(EditView, string){} edit.textChangeListeners = []func(EditView, string){}
edit.propertyChangedEvent(tag)
} }
case Text: case Text:
if exists {
oldText := GetText(edit, "") oldText := GetText(edit, "")
delete(edit.properties, tag) delete(edit.properties, tag)
if oldText != "" { if oldText != "" {
edit.textChanged("") edit.textChanged("")
if edit.created {
edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), "")) edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), ""))
} }
}
}
case EditViewPattern: case EditViewPattern:
if exists {
oldText := GetEditViewPattern(edit, "") oldText := GetEditViewPattern(edit, "")
delete(edit.properties, tag) delete(edit.properties, tag)
if oldText != "" { if oldText != "" {
if edit.created {
removeProperty(edit.htmlID(), Pattern, edit.session) removeProperty(edit.htmlID(), Pattern, edit.session)
} }
edit.propertyChangedEvent(tag)
}
}
case EditViewType: case EditViewType:
if exists {
oldType := GetEditViewType(edit, "") oldType := GetEditViewType(edit, "")
delete(edit.properties, tag) delete(edit.properties, tag)
if oldType != 0 { if oldType != 0 {
if edit.created {
updateInnerHTML(edit.parentHTMLID(), edit.session) updateInnerHTML(edit.parentHTMLID(), edit.session)
} }
edit.propertyChangedEvent(tag)
}
}
case Wrap: case Wrap:
if exists {
oldWrap := IsEditViewWrap(edit, "") oldWrap := IsEditViewWrap(edit, "")
delete(edit.properties, tag) delete(edit.properties, tag)
if GetEditViewType(edit, "") == MultiLineText { if GetEditViewType(edit, "") == MultiLineText {
if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap { if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap {
if edit.created {
if wrap { if wrap {
updateProperty(edit.htmlID(), "wrap", "soft", edit.session) updateProperty(edit.htmlID(), "wrap", "soft", edit.session)
} else { } else {
updateProperty(edit.htmlID(), "wrap", "off", edit.session) updateProperty(edit.htmlID(), "wrap", "off", edit.session)
} }
} }
edit.propertyChangedEvent(tag)
}
}
} }
default: default:
edit.viewData.remove(tag) edit.viewData.remove(tag)
} return
} }
} }
@ -161,6 +196,7 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
edit.properties[Text] = text edit.properties[Text] = text
if text = GetText(edit, ""); oldText != text { if text = GetText(edit, ""); oldText != text {
edit.textChanged(text) edit.textChanged(text)
if edit.created {
if GetEditViewType(edit, "") == MultiLineText { if GetEditViewType(edit, "") == MultiLineText {
updateInnerHTML(edit.htmlID(), edit.Session()) updateInnerHTML(edit.htmlID(), edit.Session())
} else { } else {
@ -171,6 +207,7 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), text)) edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), text))
} }
} }
}
return true return true
} }
return false return false
@ -180,12 +217,15 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
if text, ok := value.(string); ok { if text, ok := value.(string); ok {
edit.properties[Hint] = text edit.properties[Hint] = text
if text = GetHint(edit, ""); oldText != text { if text = GetHint(edit, ""); oldText != text {
if edit.created {
if text != "" { if text != "" {
updateProperty(edit.htmlID(), "placeholder", text, edit.session) updateProperty(edit.htmlID(), "placeholder", text, edit.session)
} else { } else {
removeProperty(edit.htmlID(), "placeholder", edit.session) removeProperty(edit.htmlID(), "placeholder", edit.session)
} }
} }
edit.propertyChangedEvent(tag)
}
return true return true
} }
return false return false
@ -194,30 +234,39 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
oldMaxLength := GetMaxLength(edit, "") oldMaxLength := GetMaxLength(edit, "")
if edit.setIntProperty(MaxLength, value) { if edit.setIntProperty(MaxLength, value) {
if maxLength := GetMaxLength(edit, ""); maxLength != oldMaxLength { if maxLength := GetMaxLength(edit, ""); maxLength != oldMaxLength {
if edit.created {
if maxLength > 0 { if maxLength > 0 {
updateProperty(edit.htmlID(), "maxlength", strconv.Itoa(maxLength), edit.session) updateProperty(edit.htmlID(), "maxlength", strconv.Itoa(maxLength), edit.session)
} else { } else {
removeProperty(edit.htmlID(), "maxlength", edit.session) removeProperty(edit.htmlID(), "maxlength", edit.session)
} }
} }
edit.propertyChangedEvent(tag)
}
return true return true
} }
return false return false
case ReadOnly: case ReadOnly:
if edit.setBoolProperty(ReadOnly, value) { if edit.setBoolProperty(ReadOnly, value) {
if edit.created {
if IsReadOnly(edit, "") { if IsReadOnly(edit, "") {
updateProperty(edit.htmlID(), ReadOnly, "", edit.session) updateProperty(edit.htmlID(), ReadOnly, "", edit.session)
} else { } else {
removeProperty(edit.htmlID(), ReadOnly, edit.session) removeProperty(edit.htmlID(), ReadOnly, edit.session)
} }
}
edit.propertyChangedEvent(tag)
return true return true
} }
return false return false
case Spellcheck: case Spellcheck:
if edit.setBoolProperty(Spellcheck, value) { if edit.setBoolProperty(Spellcheck, value) {
if edit.created {
updateBoolProperty(edit.htmlID(), Spellcheck, IsSpellcheck(edit, ""), edit.session) updateBoolProperty(edit.htmlID(), Spellcheck, IsSpellcheck(edit, ""), edit.session)
}
edit.propertyChangedEvent(tag)
return true return true
} }
return false return false
@ -227,12 +276,15 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
if text, ok := value.(string); ok { if text, ok := value.(string); ok {
edit.properties[Pattern] = text edit.properties[Pattern] = text
if text = GetEditViewPattern(edit, ""); oldText != text { if text = GetEditViewPattern(edit, ""); oldText != text {
if edit.created {
if text != "" { if text != "" {
updateProperty(edit.htmlID(), Pattern, text, edit.session) updateProperty(edit.htmlID(), Pattern, text, edit.session)
} else { } else {
removeProperty(edit.htmlID(), Pattern, edit.session) removeProperty(edit.htmlID(), Pattern, edit.session)
} }
} }
edit.propertyChangedEvent(tag)
}
return true return true
} }
return false return false
@ -241,8 +293,11 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
oldType := GetEditViewType(edit, "") oldType := GetEditViewType(edit, "")
if edit.setEnumProperty(EditViewType, value, enumProperties[EditViewType].values) { if edit.setEnumProperty(EditViewType, value, enumProperties[EditViewType].values) {
if GetEditViewType(edit, "") != oldType { if GetEditViewType(edit, "") != oldType {
if edit.created {
updateInnerHTML(edit.parentHTMLID(), edit.session) updateInnerHTML(edit.parentHTMLID(), edit.session)
} }
edit.propertyChangedEvent(tag)
}
return true return true
} }
return false return false
@ -252,12 +307,15 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
if edit.setBoolProperty(Wrap, value) { if edit.setBoolProperty(Wrap, value) {
if GetEditViewType(edit, "") == MultiLineText { if GetEditViewType(edit, "") == MultiLineText {
if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap { if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap {
if edit.created {
if wrap { if wrap {
updateProperty(edit.htmlID(), "wrap", "soft", edit.session) updateProperty(edit.htmlID(), "wrap", "soft", edit.session)
} else { } else {
updateProperty(edit.htmlID(), "wrap", "off", edit.session) updateProperty(edit.htmlID(), "wrap", "off", edit.session)
} }
} }
edit.propertyChangedEvent(tag)
}
} }
return true return true
} }
@ -268,6 +326,7 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
if !ok { if !ok {
notCompatibleType(tag, value) notCompatibleType(tag, value)
} }
edit.propertyChangedEvent(tag)
return ok return ok
} }
@ -363,6 +422,7 @@ func (edit *editViewData) textChanged(newText string) {
for _, listener := range edit.textChangeListeners { for _, listener := range edit.textChangeListeners {
listener(edit, newText) listener(edit, newText)
} }
edit.propertyChangedEvent(Text)
} }
func (edit *editViewData) htmlTag() string { func (edit *editViewData) htmlTag() string {
@ -446,7 +506,7 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
} }
func (edit *editViewData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (edit *editViewData) htmlDisabledProperties(self View, buffer *strings.Builder) {
if IsDisabled(self) { if IsDisabled(self, "") {
buffer.WriteString(` disabled`) buffer.WriteString(` disabled`)
} }
edit.viewData.htmlDisabledProperties(self, buffer) edit.viewData.htmlDisabledProperties(self, buffer)

View File

@ -114,7 +114,17 @@ func (picker *filePickerData) Remove(tag string) {
func (picker *filePickerData) remove(tag string) { func (picker *filePickerData) remove(tag string) {
switch tag { switch tag {
case FileSelectedEvent: case FileSelectedEvent:
if len(picker.fileSelectedListeners) > 0 {
picker.fileSelectedListeners = []func(FilePicker, []FileInfo){} picker.fileSelectedListeners = []func(FilePicker, []FileInfo){}
picker.propertyChangedEvent(tag)
}
case Accept:
delete(picker.properties, tag)
if picker.created {
removeProperty(picker.htmlID(), "accept", picker.Session())
}
picker.propertyChangedEvent(tag)
default: default:
picker.viewData.remove(tag) picker.viewData.remove(tag)
@ -184,6 +194,7 @@ func (picker *filePickerData) set(tag string, value interface{}) bool {
} }
picker.fileSelectedListeners = listeners picker.fileSelectedListeners = listeners
} }
picker.propertyChangedEvent(tag)
return true return true
case Accept: case Accept:
@ -218,6 +229,15 @@ func (picker *filePickerData) set(tag string, value interface{}) bool {
notCompatibleType(tag, value) notCompatibleType(tag, value)
return false return false
} }
if picker.created {
if css := picker.acceptCSS(); css != "" {
updateProperty(picker.htmlID(), "accept", css, picker.Session())
} else {
removeProperty(picker.htmlID(), "accept", picker.Session())
}
}
picker.propertyChangedEvent(tag)
return true return true
default: default:
@ -271,7 +291,7 @@ func (picker *filePickerData) htmlProperties(self View, buffer *strings.Builder)
} }
func (picker *filePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (picker *filePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
if IsDisabled(self) { if IsDisabled(self, "") {
buffer.WriteString(` disabled`) buffer.WriteString(` disabled`)
} }
picker.viewData.htmlDisabledProperties(self, buffer) picker.viewData.htmlDisabledProperties(self, buffer)

View File

@ -216,10 +216,12 @@ func (gridLayout *gridLayoutData) remove(tag string) {
if tag == Gap { if tag == Gap {
gridLayout.remove(GridRowGap) gridLayout.remove(GridRowGap)
gridLayout.remove(GridColumnGap) gridLayout.remove(GridColumnGap)
gridLayout.propertyChangedEvent(Gap)
return return
} }
gridLayout.viewsContainerData.remove(tag) gridLayout.viewsContainerData.remove(tag)
if gridLayout.created {
switch tag { switch tag {
case CellWidth: case CellWidth:
updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`, updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`,
@ -231,6 +233,7 @@ func (gridLayout *gridLayoutData) remove(tag string) {
} }
} }
}
func (gridLayout *gridLayoutData) Set(tag string, value interface{}) bool { func (gridLayout *gridLayoutData) Set(tag string, value interface{}) bool {
return gridLayout.set(gridLayout.normalizeTag(tag), value) return gridLayout.set(gridLayout.normalizeTag(tag), value)
@ -243,10 +246,15 @@ func (gridLayout *gridLayoutData) set(tag string, value interface{}) bool {
} }
if tag == Gap { if tag == Gap {
return gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) if gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) {
gridLayout.propertyChangedEvent(Gap)
return true
}
return false
} }
if gridLayout.viewsContainerData.set(tag, value) { if gridLayout.viewsContainerData.set(tag, value) {
if gridLayout.created {
switch tag { switch tag {
case CellWidth: case CellWidth:
updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`, updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`,
@ -257,6 +265,7 @@ func (gridLayout *gridLayoutData) set(tag string, value interface{}) bool {
gridLayout.gridCellSizesCSS(CellHeight, gridLayout.session), gridLayout.session) gridLayout.gridCellSizesCSS(CellHeight, gridLayout.session), gridLayout.session)
} }
}
return true return true
} }

View File

@ -67,7 +67,7 @@ func (imageView *imageViewData) normalizeTag(tag string) string {
case HorizontalAlign: case HorizontalAlign:
tag = ImageHorizontalAlign tag = ImageHorizontalAlign
case altProperty: case altTag:
tag = AltText tag = AltText
} }
return tag return tag
@ -79,6 +79,7 @@ func (imageView *imageViewData) Remove(tag string) {
func (imageView *imageViewData) remove(tag string) { func (imageView *imageViewData) remove(tag string) {
imageView.viewData.remove(tag) imageView.viewData.remove(tag)
if imageView.created {
switch tag { switch tag {
case Source: case Source:
updateProperty(imageView.htmlID(), "src", "", imageView.session) updateProperty(imageView.htmlID(), "src", "", imageView.session)
@ -91,6 +92,7 @@ func (imageView *imageViewData) remove(tag string) {
updateCSSStyle(imageView.htmlID(), imageView.session) updateCSSStyle(imageView.htmlID(), imageView.session)
} }
} }
}
func (imageView *imageViewData) Set(tag string, value interface{}) bool { func (imageView *imageViewData) Set(tag string, value interface{}) bool {
return imageView.set(imageView.normalizeTag(tag), value) return imageView.set(imageView.normalizeTag(tag), value)
@ -106,30 +108,38 @@ func (imageView *imageViewData) set(tag string, value interface{}) bool {
case Source: case Source:
if text, ok := value.(string); ok { if text, ok := value.(string); ok {
imageView.properties[Source] = text imageView.properties[Source] = text
if imageView.created {
updateProperty(imageView.htmlID(), "src", text, imageView.session) updateProperty(imageView.htmlID(), "src", text, imageView.session)
if srcset := imageView.srcSet(text); srcset != "" { if srcset := imageView.srcSet(text); srcset != "" {
updateProperty(imageView.htmlID(), "srcset", srcset, imageView.session) updateProperty(imageView.htmlID(), "srcset", srcset, imageView.session)
} else { } else {
removeProperty(imageView.htmlID(), "srcset", imageView.session) removeProperty(imageView.htmlID(), "srcset", imageView.session)
} }
}
imageView.propertyChangedEvent(Source)
return true return true
} }
notCompatibleType(tag, value) notCompatibleType(Source, value)
case AltText: case AltText:
if text, ok := value.(string); ok { if text, ok := value.(string); ok {
imageView.properties[AltText] = text imageView.properties[AltText] = text
if imageView.created {
updateInnerHTML(imageView.htmlID(), imageView.session) updateInnerHTML(imageView.htmlID(), imageView.session)
}
imageView.propertyChangedEvent(Source)
return true return true
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
default: default:
if imageView.viewData.set(tag, value) { if imageView.viewData.set(tag, value) {
if imageView.created {
switch tag { switch tag {
case ImageVerticalAlign, ImageHorizontalAlign: case ImageVerticalAlign, ImageHorizontalAlign:
updateCSSStyle(imageView.htmlID(), imageView.session) updateCSSStyle(imageView.htmlID(), imageView.session)
} }
}
return true return true
} }
} }

View File

@ -77,7 +77,7 @@ func (adapter *viewListAdapter) ListItem(index int, session Session) View {
func (adapter *viewListAdapter) IsListItemEnabled(index int) bool { func (adapter *viewListAdapter) IsListItemEnabled(index int) bool {
if index >= 0 && index < len(adapter.items) { if index >= 0 && index < len(adapter.items) {
return !IsDisabled(adapter.items[index]) return !IsDisabled(adapter.items[index], "")
} }
return true return true
} }

View File

@ -55,11 +55,13 @@ func (listLayout *listLayoutData) Remove(tag string) {
func (listLayout *listLayoutData) remove(tag string) { func (listLayout *listLayoutData) remove(tag string) {
listLayout.viewsContainerData.remove(tag) listLayout.viewsContainerData.remove(tag)
if listLayout.created {
switch tag { switch tag {
case Orientation, Wrap, HorizontalAlign, VerticalAlign: case Orientation, Wrap, HorizontalAlign, VerticalAlign:
updateCSSStyle(listLayout.htmlID(), listLayout.session) updateCSSStyle(listLayout.htmlID(), listLayout.session)
} }
} }
}
func (listLayout *listLayoutData) Set(tag string, value interface{}) bool { func (listLayout *listLayoutData) Set(tag string, value interface{}) bool {
return listLayout.set(strings.ToLower(tag), value) return listLayout.set(strings.ToLower(tag), value)
@ -72,10 +74,12 @@ func (listLayout *listLayoutData) set(tag string, value interface{}) bool {
} }
if listLayout.viewsContainerData.set(tag, value) { if listLayout.viewsContainerData.set(tag, value) {
if listLayout.created {
switch tag { switch tag {
case Orientation, Wrap, HorizontalAlign, VerticalAlign: case Orientation, Wrap, HorizontalAlign, VerticalAlign:
updateCSSStyle(listLayout.htmlID(), listLayout.session) updateCSSStyle(listLayout.htmlID(), listLayout.session)
} }
}
return true return true
} }
return false return false

View File

@ -114,46 +114,71 @@ func (listView *listViewData) Remove(tag string) {
func (listView *listViewData) remove(tag string) { func (listView *listViewData) remove(tag string) {
switch tag { switch tag {
case Checked: case Checked:
if len(listView.checkedItem) > 0 {
listView.checkedItem = []int{} listView.checkedItem = []int{}
if listView.created {
updateInnerHTML(listView.htmlID(), listView.session) updateInnerHTML(listView.htmlID(), listView.session)
}
listView.propertyChangedEvent(tag)
}
case Items: case Items:
if listView.adapter != nil {
listView.adapter = nil listView.adapter = nil
if listView.created {
updateInnerHTML(listView.htmlID(), listView.session) updateInnerHTML(listView.htmlID(), listView.session)
}
listView.propertyChangedEvent(tag)
}
case Orientation, Wrap: case Orientation, Wrap:
if _, ok := listView.properties[tag]; ok {
delete(listView.properties, tag) delete(listView.properties, tag)
if listView.created {
updateCSSStyle(listView.htmlID(), listView.session) updateCSSStyle(listView.htmlID(), listView.session)
}
listView.propertyChangedEvent(tag)
}
case Current: case Current:
current := GetListViewCurrent(listView, "") current := GetListViewCurrent(listView, "")
delete(listView.properties, tag) delete(listView.properties, tag)
if listView.created {
updateInnerHTML(listView.htmlID(), listView.session) updateInnerHTML(listView.htmlID(), listView.session)
}
if current != -1 { if current != -1 {
for _, listener := range listView.selectedListeners { for _, listener := range listView.selectedListeners {
listener(listView, -1) listener(listView, -1)
} }
listView.propertyChangedEvent(tag)
} }
case ItemWidth, ItemHeight, ItemHorizontalAlign, ItemVerticalAlign, ItemCheckbox, case ItemWidth, ItemHeight, ItemHorizontalAlign, ItemVerticalAlign, ItemCheckbox,
CheckboxHorizontalAlign, CheckboxVerticalAlign, ListItemStyle, CurrentStyle, CurrentInactiveStyle: CheckboxHorizontalAlign, CheckboxVerticalAlign, ListItemStyle, CurrentStyle, CurrentInactiveStyle:
if _, ok := listView.properties[tag]; ok {
delete(listView.properties, tag) delete(listView.properties, tag)
if listView.created {
updateInnerHTML(listView.htmlID(), listView.session) updateInnerHTML(listView.htmlID(), listView.session)
}
listView.propertyChangedEvent(tag)
}
case ListItemClickedEvent: case ListItemClickedEvent:
if len(listView.clickedListeners) > 0 { if len(listView.clickedListeners) > 0 {
listView.clickedListeners = []func(ListView, int){} listView.clickedListeners = []func(ListView, int){}
listView.propertyChangedEvent(tag)
} }
case ListItemSelectedEvent: case ListItemSelectedEvent:
if len(listView.selectedListeners) > 0 { if len(listView.selectedListeners) > 0 {
listView.selectedListeners = []func(ListView, int){} listView.selectedListeners = []func(ListView, int){}
listView.propertyChangedEvent(tag)
} }
case ListItemCheckedEvent: case ListItemCheckedEvent:
if len(listView.checkedListeners) > 0 { if len(listView.checkedListeners) > 0 {
listView.checkedListeners = []func(ListView, []int){} listView.checkedListeners = []func(ListView, []int){}
listView.propertyChangedEvent(tag)
} }
default: default:
@ -171,10 +196,7 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
return true return true
} }
result := false
switch tag { switch tag {
case ListItemClickedEvent: case ListItemClickedEvent:
listeners := listView.valueToItemListeners(value) listeners := listView.valueToItemListeners(value)
if listeners == nil { if listeners == nil {
@ -182,6 +204,7 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
return false return false
} }
listView.clickedListeners = listeners listView.clickedListeners = listeners
listView.propertyChangedEvent(tag)
return true return true
case ListItemSelectedEvent: case ListItemSelectedEvent:
@ -191,44 +214,56 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
return false return false
} }
listView.selectedListeners = listeners listView.selectedListeners = listeners
listView.propertyChangedEvent(tag)
return true return true
case ListItemCheckedEvent: case ListItemCheckedEvent:
return listView.setItemCheckedEvent(value) if !listView.setItemCheckedEvent(value) {
return false
}
listView.propertyChangedEvent(tag)
return true
case Checked: case Checked:
return listView.setChecked(value) if !listView.setChecked(value) {
return false
}
case Items: case Items:
result = listView.setItems(value) if !listView.setItems(value) {
return false
}
case Current: case Current:
oldCurrent := GetListViewCurrent(listView, "") oldCurrent := GetListViewCurrent(listView, "")
if listView.setIntProperty(Current, value) { if !listView.setIntProperty(Current, value) {
return false
}
current := GetListViewCurrent(listView, "") current := GetListViewCurrent(listView, "")
if oldCurrent != current { if oldCurrent == current {
updateInnerHTML(listView.htmlID(), listView.session)
for _, listener := range listView.selectedListeners {
listener(listView, current)
}
}
return true return true
} }
case Orientation, Wrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled: for _, listener := range listView.selectedListeners {
result = listView.viewData.set(tag, value) listener(listView, current)
}
case ItemWidth, ItemHeight: case Orientation, Wrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight:
result = listView.setSizeProperty(tag, value) result := listView.viewData.set(tag, value)
if result && listView.created {
updateInnerHTML(listView.htmlID(), listView.session)
}
return result
case ItemHorizontalAlign, ItemVerticalAlign, ItemCheckbox, CheckboxHorizontalAlign, CheckboxVerticalAlign: case ItemHorizontalAlign, ItemVerticalAlign, ItemCheckbox, CheckboxHorizontalAlign, CheckboxVerticalAlign:
result = listView.setEnumProperty(tag, value, enumProperties[tag].values) if !listView.setEnumProperty(tag, value, enumProperties[tag].values) {
return false
}
case ListItemStyle, CurrentStyle, CurrentInactiveStyle: case ListItemStyle, CurrentStyle, CurrentInactiveStyle:
switch value := value.(type) { switch value := value.(type) {
case string: case string:
listView.properties[tag] = value listView.properties[tag] = value
result = true
default: default:
notCompatibleType(tag, value) notCompatibleType(tag, value)
@ -239,11 +274,11 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
return listView.viewData.set(tag, value) return listView.viewData.set(tag, value)
} }
if result { if listView.created {
updateInnerHTML(listView.htmlID(), listView.session) updateInnerHTML(listView.htmlID(), listView.session)
} }
listView.propertyChangedEvent(tag)
return result return true
} }
func (listView *listViewData) setItemCheckedEvent(value interface{}) bool { func (listView *listViewData) setItemCheckedEvent(value interface{}) bool {
@ -1054,14 +1089,18 @@ func (listView *listViewData) handleCommand(self View, command string, data Data
for _, listener := range listView.selectedListeners { for _, listener := range listView.selectedListeners {
listener(listView, number) listener(listView, number)
} }
listView.propertyChangedEvent(Current)
} }
} }
case "itemUnselected": case "itemUnselected":
if _, ok := listView.properties[Current]; ok {
delete(listView.properties, Current) delete(listView.properties, Current)
for _, listener := range listView.selectedListeners { for _, listener := range listView.selectedListeners {
listener(listView, -1) listener(listView, -1)
} }
listView.propertyChangedEvent(Current)
}
case "itemClick": case "itemClick":
listView.onItemClick() listView.onItemClick()
@ -1075,7 +1114,7 @@ func (listView *listViewData) handleCommand(self View, command string, data Data
func (listView *listViewData) onItemClick() { func (listView *listViewData) onItemClick() {
current := GetListViewCurrent(listView, "") current := GetListViewCurrent(listView, "")
if current >= 0 && !IsDisabled(listView) { if current >= 0 && !IsDisabled(listView, "") {
checkbox := GetListViewCheckbox(listView, "") checkbox := GetListViewCheckbox(listView, "")
m: m:
switch checkbox { switch checkbox {
@ -1115,6 +1154,7 @@ func (listView *listViewData) onItemClick() {
for _, listener := range listView.checkedListeners { for _, listener := range listView.checkedListeners {
listener(listView, listView.checkedItem) listener(listView, listView.checkedItem)
} }
listView.propertyChangedEvent(Checked)
} }
for _, listener := range listView.clickedListeners { for _, listener := range listView.clickedListeners {
listener(listView, current) listener(listView, current)

View File

@ -173,20 +173,8 @@ func (player *mediaPlayerData) Remove(tag string) {
} }
func (player *mediaPlayerData) remove(tag string) { func (player *mediaPlayerData) remove(tag string) {
switch tag {
case Controls, Loop, Muted, Preload, AbortEvent, LoadStartEvent, PlayerErrorEvent,
CanPlayEvent, CanPlayThroughEvent, CompleteEvent, DurationChangedEvent,
EmptiedEvent, EndedEvent, LoadedDataEvent, LoadedMetadataEvent, PauseEvent, PlayEvent,
PlayingEvent, RateChangedEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent,
ProgressEvent, TimeUpdateEvent, VolumeChangedEvent, WaitingEvent:
player.viewData.remove(tag) player.viewData.remove(tag)
player.propertyChanged(tag) player.propertyChanged(tag)
default:
player.viewData.remove(tag)
}
} }
func (player *mediaPlayerData) Set(tag string, value interface{}) bool { func (player *mediaPlayerData) Set(tag string, value interface{}) bool {
@ -216,6 +204,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool {
player.properties[tag] = listeners player.properties[tag] = listeners
} }
player.propertyChanged(tag) player.propertyChanged(tag)
player.propertyChangedEvent(tag)
return true return true
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
@ -228,6 +217,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool {
player.properties[tag] = listeners player.properties[tag] = listeners
} }
player.propertyChanged(tag) player.propertyChanged(tag)
player.propertyChangedEvent(tag)
return true return true
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
@ -240,6 +230,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool {
player.properties[tag] = listeners player.properties[tag] = listeners
} }
player.propertyChanged(tag) player.propertyChanged(tag)
player.propertyChangedEvent(tag)
return true return true
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
@ -247,14 +238,14 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool {
case Source: case Source:
if player.setSource(value) { if player.setSource(value) {
player.propertyChanged(tag) player.propertyChanged(tag)
player.propertyChangedEvent(tag)
return true return true
} }
default: default:
if player.viewData.set(tag, value) { return player.viewData.set(tag, value)
return true
}
} }
return false return false
} }
@ -657,6 +648,7 @@ func playerEvents() []struct{ tag, cssTag string } {
} }
func (player *mediaPlayerData) propertyChanged(tag string) { func (player *mediaPlayerData) propertyChanged(tag string) {
if player.created {
switch tag { switch tag {
case Controls, Loop: case Controls, Loop:
value, _ := boolProperty(player, tag, player.Session()) value, _ := boolProperty(player, tag, player.Session())
@ -737,9 +729,7 @@ func (player *mediaPlayerData) propertyChanged(tag string) {
case Source: case Source:
updateInnerHTML(player.htmlID(), player.Session()) updateInnerHTML(player.htmlID(), player.Session())
}
default:
player.viewData.propertyChanged(tag)
} }
} }

View File

@ -69,6 +69,7 @@ func (picker *numberPickerData) remove(tag string) {
case NumberChangedEvent: case NumberChangedEvent:
if len(picker.numberChangedListeners) > 0 { if len(picker.numberChangedListeners) > 0 {
picker.numberChangedListeners = []func(NumberPicker, float64){} picker.numberChangedListeners = []func(NumberPicker, float64){}
picker.propertyChangedEvent(tag)
} }
default: default:
@ -135,18 +136,21 @@ func (picker *numberPickerData) set(tag string, value interface{}) bool {
} }
picker.numberChangedListeners = listeners picker.numberChangedListeners = listeners
} }
picker.propertyChangedEvent(tag)
return true return true
case NumberPickerValue: case NumberPickerValue:
oldValue := GetNumberPickerValue(picker, "") oldValue := GetNumberPickerValue(picker, "")
min, max := GetNumberPickerMinMax(picker, "") min, max := GetNumberPickerMinMax(picker, "")
if picker.setFloatProperty(NumberPickerValue, value, min, max) { if picker.setFloatProperty(NumberPickerValue, value, min, max) {
newValue := GetNumberPickerValue(picker, "") if newValue := GetNumberPickerValue(picker, ""); oldValue != newValue {
if oldValue != newValue { if picker.created {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), newValue)) picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), newValue))
}
for _, listener := range picker.numberChangedListeners { for _, listener := range picker.numberChangedListeners {
listener(picker, newValue) listener(picker, newValue)
} }
picker.propertyChangedEvent(tag)
} }
return true return true
} }
@ -161,6 +165,7 @@ func (picker *numberPickerData) set(tag string, value interface{}) bool {
} }
func (picker *numberPickerData) propertyChanged(tag string) { func (picker *numberPickerData) propertyChanged(tag string) {
if picker.created {
switch tag { switch tag {
case NumberPickerType: case NumberPickerType:
if GetNumberPickerType(picker, "") == NumberSlider { if GetNumberPickerType(picker, "") == NumberSlider {
@ -192,6 +197,7 @@ func (picker *numberPickerData) propertyChanged(tag string) {
} }
} }
} }
}
func (picker *numberPickerData) Get(tag string) interface{} { func (picker *numberPickerData) Get(tag string) interface{} {
return picker.get(picker.normalizeTag(tag)) return picker.get(picker.normalizeTag(tag))
@ -246,7 +252,7 @@ func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builde
} }
func (picker *numberPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (picker *numberPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
if IsDisabled(self) { if IsDisabled(self, "") {
buffer.WriteString(` disabled`) buffer.WriteString(` disabled`)
} }
picker.viewData.htmlDisabledProperties(self, buffer) picker.viewData.htmlDisabledProperties(self, buffer)

View File

@ -58,6 +58,7 @@ func (progress *progressBarData) remove(tag string) {
} }
func (progress *progressBarData) propertyChanged(tag string) { func (progress *progressBarData) propertyChanged(tag string) {
if progress.created {
switch tag { switch tag {
case ProgressBarMax: case ProgressBarMax:
updateProperty(progress.htmlID(), Max, strconv.FormatFloat(GetProgressBarMax(progress, ""), 'f', -1, 32), progress.session) updateProperty(progress.htmlID(), Max, strconv.FormatFloat(GetProgressBarMax(progress, ""), 'f', -1, 32), progress.session)
@ -66,6 +67,7 @@ func (progress *progressBarData) propertyChanged(tag string) {
updateProperty(progress.htmlID(), Value, strconv.FormatFloat(GetProgressBarValue(progress, ""), 'f', -1, 32), progress.session) updateProperty(progress.htmlID(), Value, strconv.FormatFloat(GetProgressBarValue(progress, ""), 'f', -1, 32), progress.session)
} }
} }
}
func (progress *progressBarData) Set(tag string, value interface{}) bool { func (progress *progressBarData) Set(tag string, value interface{}) bool {
return progress.set(progress.normalizeTag(tag), value) return progress.set(progress.normalizeTag(tag), value)

View File

@ -368,7 +368,7 @@ const (
CenterY = "center-y" CenterY = "center-y"
// AltText is the constant for the "alt-text" property tag. // AltText is the constant for the "alt-text" property tag.
AltText = "alt-text" AltText = "alt-text"
altProperty = "alt" altTag = "alt"
// AvoidBreak is the constant for the "avoid-break" property tag. // AvoidBreak is the constant for the "avoid-break" property tag.
// The "avoid-break" bool property sets how region breaks should behave inside a generated box. // The "avoid-break" bool property sets how region breaks should behave inside a generated box.
// If the property value is "true" then fvoids any break from being inserted within the principal box. // If the property value is "true" then fvoids any break from being inserted within the principal box.

View File

@ -65,6 +65,7 @@ var intProperties = []string{
FootHeight, FootHeight,
RowSpan, RowSpan,
ColumnSpan, ColumnSpan,
ColumnCount,
} }
var floatProperties = map[string]struct{ min, max float64 }{ var floatProperties = map[string]struct{ min, max float64 }{

View File

@ -75,22 +75,29 @@ func (resizable *resizableData) remove(tag string) {
oldSide := resizable.getSide() oldSide := resizable.getSide()
delete(resizable.properties, Side) delete(resizable.properties, Side)
if oldSide != resizable.getSide() { if oldSide != resizable.getSide() {
if resizable.created {
updateInnerHTML(resizable.htmlID(), resizable.Session()) updateInnerHTML(resizable.htmlID(), resizable.Session())
resizable.updateResizeBorderWidth() resizable.updateResizeBorderWidth()
} }
resizable.propertyChangedEvent(tag)
}
case ResizeBorderWidth: case ResizeBorderWidth:
w := resizable.resizeBorderWidth() w := resizable.resizeBorderWidth()
delete(resizable.properties, ResizeBorderWidth) delete(resizable.properties, ResizeBorderWidth)
if !w.Equal(resizable.resizeBorderWidth()) { if !w.Equal(resizable.resizeBorderWidth()) {
resizable.updateResizeBorderWidth() resizable.updateResizeBorderWidth()
resizable.propertyChangedEvent(tag)
} }
case Content: case Content:
if len(resizable.content) > 0 { if len(resizable.content) > 0 {
resizable.content = []View{} resizable.content = []View{}
if resizable.created {
updateInnerHTML(resizable.htmlID(), resizable.Session()) updateInnerHTML(resizable.htmlID(), resizable.Session())
} }
resizable.propertyChangedEvent(tag)
}
default: default:
resizable.viewData.remove(tag) resizable.viewData.remove(tag)
@ -110,20 +117,25 @@ func (resizable *resizableData) set(tag string, value interface{}) bool {
switch tag { switch tag {
case Side: case Side:
oldSide := resizable.getSide() oldSide := resizable.getSide()
ok := resizable.setSide(value) if !resizable.setSide(value) {
if ok && oldSide != resizable.getSide() { notCompatibleType(tag, value)
return false
}
if oldSide != resizable.getSide() {
if resizable.created {
updateInnerHTML(resizable.htmlID(), resizable.Session()) updateInnerHTML(resizable.htmlID(), resizable.Session())
resizable.updateResizeBorderWidth() resizable.updateResizeBorderWidth()
} else {
notCompatibleType(tag, value)
} }
return ok resizable.propertyChangedEvent(tag)
}
return true
case ResizeBorderWidth: case ResizeBorderWidth:
w := resizable.resizeBorderWidth() w := resizable.resizeBorderWidth()
ok := resizable.setSizeProperty(tag, value) ok := resizable.setSizeProperty(tag, value)
if ok && !w.Equal(resizable.resizeBorderWidth()) { if ok && !w.Equal(resizable.resizeBorderWidth()) {
resizable.updateResizeBorderWidth() resizable.updateResizeBorderWidth()
resizable.propertyChangedEvent(tag)
} }
return ok return ok
@ -139,18 +151,25 @@ func (resizable *resizableData) set(tag string, value interface{}) bool {
case DataObject: case DataObject:
if view := CreateViewFromObject(resizable.Session(), value); view != nil { if view := CreateViewFromObject(resizable.Session(), value); view != nil {
newContent = view newContent = view
} } else {
return false
}
default:
notCompatibleType(tag, value)
return false
} }
if newContent != nil {
if len(resizable.content) == 0 { if len(resizable.content) == 0 {
resizable.content = []View{newContent} resizable.content = []View{newContent}
} else { } else {
resizable.content[0] = newContent resizable.content[0] = newContent
} }
if resizable.created {
updateInnerHTML(resizable.htmlID(), resizable.Session()) updateInnerHTML(resizable.htmlID(), resizable.Session())
return true
} }
resizable.propertyChangedEvent(tag)
return true
case CellWidth, CellHeight, GridRowGap, GridColumnGap, CellVerticalAlign, CellHorizontalAlign: case CellWidth, CellHeight, GridRowGap, GridColumnGap, CellVerticalAlign, CellHorizontalAlign:
ErrorLogF(`Not supported "%s" property`, tag) ErrorLogF(`Not supported "%s" property`, tag)
@ -306,6 +325,7 @@ func (resizable *resizableData) resizeBorderWidth() SizeUnit {
} }
func (resizable *resizableData) updateResizeBorderWidth() { func (resizable *resizableData) updateResizeBorderWidth() {
if resizable.created {
htmlID := resizable.htmlID() htmlID := resizable.htmlID()
session := resizable.Session() session := resizable.Session()
column, row := resizable.cellSizeCSS() column, row := resizable.cellSizeCSS()
@ -313,6 +333,7 @@ func (resizable *resizableData) updateResizeBorderWidth() {
updateCSSProperty(htmlID, "grid-template-columns", column, session) updateCSSProperty(htmlID, "grid-template-columns", column, session)
updateCSSProperty(htmlID, "grid-template-rows", row, session) updateCSSProperty(htmlID, "grid-template-rows", row, session)
} }
}
func (resizable *resizableData) cellSizeCSS() (string, string) { func (resizable *resizableData) cellSizeCSS() (string, string) {
w := resizable.resizeBorderWidth().cssString("4px") w := resizable.resizeBorderWidth().cssString("4px")

View File

@ -6,6 +6,8 @@ import (
"strings" "strings"
) )
// TODO PeekChangedEvent
const ( const (
// DefaultAnimation - default animation of StackLayout push // DefaultAnimation - default animation of StackLayout push
DefaultAnimation = 0 DefaultAnimation = 0
@ -93,23 +95,33 @@ func (layout *stackLayoutData) popFinished(view View, tag string) {
} }
func (layout *stackLayoutData) Set(tag string, value interface{}) bool { func (layout *stackLayoutData) Set(tag string, value interface{}) bool {
if strings.ToLower(tag) == TransitionEndEvent { return layout.set(strings.ToLower(tag), value)
}
func (layout *stackLayoutData) set(tag string, value interface{}) bool {
if tag == TransitionEndEvent {
listeners, ok := valueToAnimationListeners(value) listeners, ok := valueToAnimationListeners(value)
if ok { if ok {
listeners = append(listeners, layout.pushFinished) listeners = append(listeners, layout.pushFinished)
listeners = append(listeners, layout.popFinished) listeners = append(listeners, layout.popFinished)
layout.properties[TransitionEndEvent] = listeners layout.properties[TransitionEndEvent] = listeners
layout.propertyChangedEvent(TransitionEndEvent)
} }
return ok return ok
} }
return layout.viewsContainerData.Set(tag, value) return layout.viewsContainerData.set(tag, value)
} }
func (layout *stackLayoutData) Remove(tag string) { func (layout *stackLayoutData) Remove(tag string) {
if strings.ToLower(tag) == TransitionEndEvent { layout.remove(strings.ToLower(tag))
}
func (layout *stackLayoutData) remove(tag string) {
if tag == TransitionEndEvent {
layout.properties[TransitionEndEvent] = []func(View, string){layout.pushFinished, layout.popFinished} layout.properties[TransitionEndEvent] = []func(View, string){layout.pushFinished, layout.popFinished}
layout.propertyChangedEvent(TransitionEndEvent)
} else { } else {
layout.viewsContainerData.Remove(tag) layout.viewsContainerData.remove(tag)
} }
} }
@ -238,6 +250,7 @@ func (layout *stackLayoutData) Push(view View, animation int, onPushFinished fun
layout.views = append(layout.views, view) layout.views = append(layout.views, view)
view.setParentID(htmlID) view.setParentID(htmlID)
layout.propertyChangedEvent(Content)
} }
func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool { func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool {
@ -286,6 +299,7 @@ func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool
} }
updateCSSProperty(htmlID+"pop", "transform", value, layout.session) updateCSSProperty(htmlID+"pop", "transform", value, layout.session)
layout.propertyChangedEvent(Content)
return true return true
} }

View File

@ -168,35 +168,51 @@ func (table *tableViewData) Init(session Session) {
table.tag = "TableView" table.tag = "TableView"
} }
func (table *tableViewData) normalizeTag(tag string) string {
switch tag = strings.ToLower(tag); tag {
case "top-cell-padding":
tag = CellPaddingTop
case "right-cell-padding":
tag = CellPaddingRight
case "bottom-cell-padding":
tag = CellPaddingBottom
case "left-cell-padding":
tag = CellPaddingLeft
}
return tag
}
func (table *tableViewData) Get(tag string) interface{} { func (table *tableViewData) Get(tag string) interface{} {
return table.get(strings.ToLower(tag)) return table.get(table.normalizeTag(tag))
} }
func (table *tableViewData) Remove(tag string) { func (table *tableViewData) Remove(tag string) {
table.remove(strings.ToLower(tag)) table.remove(table.normalizeTag(tag))
} }
func (table *tableViewData) remove(tag string) { func (table *tableViewData) remove(tag string) {
switch tag { switch tag {
case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft:
case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft,
"top-cell-padding", "right-cell-padding", "bottom-cell-padding", "left-cell-padding":
table.removeBoundsSide(CellPadding, tag) table.removeBoundsSide(CellPadding, tag)
table.propertyChanged(tag)
case Gap, CellBorder, CellPadding, RowStyle, ColumnStyle, CellStyle, case Gap, CellBorder, CellPadding, RowStyle, ColumnStyle, CellStyle,
HeadHeight, HeadStyle, FootHeight, FootStyle: HeadHeight, HeadStyle, FootHeight, FootStyle:
if _, ok := table.properties[tag]; ok {
delete(table.properties, tag) delete(table.properties, tag)
default:
table.viewData.remove(tag)
return
}
table.propertyChanged(tag) table.propertyChanged(tag)
} }
default:
table.viewData.remove(tag)
}
}
func (table *tableViewData) Set(tag string, value interface{}) bool { func (table *tableViewData) Set(tag string, value interface{}) bool {
return table.set(strings.ToLower(tag), value) return table.set(table.normalizeTag(tag), value)
} }
func (table *tableViewData) set(tag string, value interface{}) bool { func (table *tableViewData) set(tag string, value interface{}) bool {
@ -307,8 +323,7 @@ func (table *tableViewData) set(tag string, value interface{}) bool {
return false return false
} }
case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft, case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft:
"top-cell-padding", "right-cell-padding", "bottom-cell-padding", "left-cell-padding":
if !table.setBoundsSide(CellPadding, tag, value) { if !table.setBoundsSide(CellPadding, tag, value) {
return false return false
} }
@ -336,11 +351,11 @@ func (table *tableViewData) set(tag string, value interface{}) bool {
} }
func (table *tableViewData) propertyChanged(tag string) { func (table *tableViewData) propertyChanged(tag string) {
if table.created {
switch tag { switch tag {
case Content, RowStyle, ColumnStyle, CellStyle, CellPadding, CellBorder, case Content, RowStyle, ColumnStyle, CellStyle, CellPadding, CellBorder,
HeadHeight, HeadStyle, FootHeight, FootStyle, HeadHeight, HeadStyle, FootHeight, FootStyle,
CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft, CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft:
"top-cell-padding", "right-cell-padding", "bottom-cell-padding", "left-cell-padding":
table.ReloadTableData() table.ReloadTableData()
case Gap: case Gap:
@ -354,9 +369,10 @@ func (table *tableViewData) propertyChanged(tag string) {
updateCSSProperty(htmlID, "border-spacing", gap.cssString("0"), session) updateCSSProperty(htmlID, "border-spacing", gap.cssString("0"), session)
updateCSSProperty(htmlID, "border-collapse", "separate", session) updateCSSProperty(htmlID, "border-collapse", "separate", session)
} }
} }
} }
table.propertyChangedEvent(tag)
}
func (table *tableViewData) htmlTag() string { func (table *tableViewData) htmlTag() string {
return "table" return "table"

View File

@ -123,15 +123,26 @@ func (tabsLayout *tabsLayoutData) Remove(tag string) {
func (tabsLayout *tabsLayoutData) remove(tag string) { func (tabsLayout *tabsLayoutData) remove(tag string) {
switch tag { switch tag {
case CurrentTabChangedEvent: case CurrentTabChangedEvent:
if len(tabsLayout.tabListener) > 0 {
tabsLayout.tabListener = []func(TabsLayout, int, int){} tabsLayout.tabListener = []func(TabsLayout, int, int){}
tabsLayout.propertyChangedEvent(tag)
}
return
case TabCloseEvent: case TabCloseEvent:
if len(tabsLayout.tabCloseListener) > 0 {
tabsLayout.tabCloseListener = []func(TabsLayout, int){} tabsLayout.tabCloseListener = []func(TabsLayout, int){}
tabsLayout.propertyChangedEvent(tag)
}
return
case Current: case Current:
oldCurrent := tabsLayout.currentItem() oldCurrent := tabsLayout.currentItem()
delete(tabsLayout.properties, Current) delete(tabsLayout.properties, Current)
if !tabsLayout.session.ignoreViewUpdates() && oldCurrent != 0 { if oldCurrent == 0 {
return
}
if tabsLayout.created {
tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), 0)) tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), 0))
for _, listener := range tabsLayout.tabListener { for _, listener := range tabsLayout.tabListener {
listener(tabsLayout, 0, oldCurrent) listener(tabsLayout, 0, oldCurrent)
@ -140,7 +151,7 @@ func (tabsLayout *tabsLayoutData) remove(tag string) {
case Tabs: case Tabs:
delete(tabsLayout.properties, Tabs) delete(tabsLayout.properties, Tabs)
if !tabsLayout.session.ignoreViewUpdates() { if tabsLayout.created {
htmlID := tabsLayout.htmlID() htmlID := tabsLayout.htmlID()
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
@ -150,7 +161,7 @@ func (tabsLayout *tabsLayoutData) remove(tag string) {
case TabStyle, CurrentTabStyle: case TabStyle, CurrentTabStyle:
delete(tabsLayout.properties, tag) delete(tabsLayout.properties, tag)
if !tabsLayout.session.ignoreViewUpdates() { if tabsLayout.created {
htmlID := tabsLayout.htmlID() htmlID := tabsLayout.htmlID()
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
@ -159,13 +170,16 @@ func (tabsLayout *tabsLayoutData) remove(tag string) {
case TabCloseButton: case TabCloseButton:
delete(tabsLayout.properties, tag) delete(tabsLayout.properties, tag)
if !tabsLayout.session.ignoreViewUpdates() { if tabsLayout.created {
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session) updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session)
} }
default: default:
tabsLayout.viewsContainerData.remove(tag) tabsLayout.viewsContainerData.remove(tag)
return
} }
tabsLayout.propertyChangedEvent(tag)
} }
func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool { func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool {
@ -201,21 +215,22 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
return false return false
} }
if !tabsLayout.session.ignoreViewUpdates() {
current := tabsLayout.currentItem() current := tabsLayout.currentItem()
if oldCurrent != current { if oldCurrent == current {
return true
}
if tabsLayout.created {
tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), current)) tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), current))
for _, listener := range tabsLayout.tabListener { for _, listener := range tabsLayout.tabListener {
listener(tabsLayout, current, oldCurrent) listener(tabsLayout, current, oldCurrent)
} }
} }
}
case Tabs: case Tabs:
if !tabsLayout.setEnumProperty(Tabs, value, enumProperties[Tabs].values) { if !tabsLayout.setEnumProperty(Tabs, value, enumProperties[Tabs].values) {
return false return false
} }
if !tabsLayout.session.ignoreViewUpdates() { if tabsLayout.created {
htmlID := tabsLayout.htmlID() htmlID := tabsLayout.htmlID()
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
@ -235,7 +250,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
return false return false
} }
if !tabsLayout.session.ignoreViewUpdates() { if tabsLayout.created {
htmlID := tabsLayout.htmlID() htmlID := tabsLayout.htmlID()
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
@ -246,7 +261,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
if !tabsLayout.setBoolProperty(tag, value) { if !tabsLayout.setBoolProperty(tag, value) {
return false return false
} }
if !tabsLayout.session.ignoreViewUpdates() { if tabsLayout.created {
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session) updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session)
} }
@ -254,6 +269,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
return tabsLayout.viewsContainerData.set(tag, value) return tabsLayout.viewsContainerData.set(tag, value)
} }
tabsLayout.propertyChangedEvent(tag)
return true return true
} }
@ -905,6 +921,7 @@ func (tabsLayout *tabsLayoutData) handleCommand(self View, command string, data
for _, listener := range tabsLayout.tabListener { for _, listener := range tabsLayout.tabListener {
listener(tabsLayout, number, current) listener(tabsLayout, number, current)
} }
tabsLayout.propertyChangedEvent(Current)
} }
} }
} }

View File

@ -43,6 +43,7 @@ func (textView *textViewData) Remove(tag string) {
func (textView *textViewData) remove(tag string) { func (textView *textViewData) remove(tag string) {
textView.viewData.remove(tag) textView.viewData.remove(tag)
if textView.created {
switch tag { switch tag {
case Text: case Text:
updateInnerHTML(textView.htmlID(), textView.session) updateInnerHTML(textView.htmlID(), textView.session)
@ -51,6 +52,7 @@ func (textView *textViewData) remove(tag string) {
textView.textOverflowUpdated() textView.textOverflowUpdated()
} }
} }
}
func (textView *textViewData) Set(tag string, value interface{}) bool { func (textView *textViewData) Set(tag string, value interface{}) bool {
return textView.set(strings.ToLower(tag), value) return textView.set(strings.ToLower(tag), value)
@ -90,16 +92,24 @@ func (textView *textViewData) set(tag string, value interface{}) bool {
return false return false
} }
} }
if textView.created {
updateInnerHTML(textView.htmlID(), textView.session) updateInnerHTML(textView.htmlID(), textView.session)
return true }
case TextOverflow: case TextOverflow:
if textView.viewData.set(tag, value) { if !textView.viewData.set(tag, value) {
return false
}
if textView.created {
textView.textOverflowUpdated() textView.textOverflowUpdated()
} }
default:
return textView.viewData.set(tag, value)
} }
return textView.viewData.set(tag, value) textView.propertyChangedEvent(tag)
return true
} }
func (textView *textViewData) textOverflowUpdated() { func (textView *textViewData) textOverflowUpdated() {

View File

@ -63,28 +63,47 @@ func (picker *timePickerData) remove(tag string) {
case TimeChangedEvent: case TimeChangedEvent:
if len(picker.timeChangedListeners) > 0 { if len(picker.timeChangedListeners) > 0 {
picker.timeChangedListeners = []func(TimePicker, time.Time){} picker.timeChangedListeners = []func(TimePicker, time.Time){}
picker.propertyChangedEvent(tag)
} }
return
case TimePickerMin: case TimePickerMin:
delete(picker.properties, TimePickerMin) delete(picker.properties, TimePickerMin)
if picker.created {
removeProperty(picker.htmlID(), Min, picker.session) removeProperty(picker.htmlID(), Min, picker.session)
}
case TimePickerMax: case TimePickerMax:
delete(picker.properties, TimePickerMax) delete(picker.properties, TimePickerMax)
if picker.created {
removeProperty(picker.htmlID(), Max, picker.session) removeProperty(picker.htmlID(), Max, picker.session)
}
case TimePickerStep: case TimePickerStep:
delete(picker.properties, TimePickerMax) delete(picker.properties, TimePickerMax)
if picker.created {
removeProperty(picker.htmlID(), Step, picker.session) removeProperty(picker.htmlID(), Step, picker.session)
}
case TimePickerValue: case TimePickerValue:
if _, ok := picker.properties[TimePickerValue]; ok {
delete(picker.properties, TimePickerValue) delete(picker.properties, TimePickerValue)
updateProperty(picker.htmlID(), Value, time.Now().Format(timeFormat), picker.session) time := GetTimePickerValue(picker, "")
if picker.created {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat)))
}
for _, listener := range picker.timeChangedListeners {
listener(picker, time)
}
} else {
return
}
default: default:
picker.viewData.remove(tag) picker.viewData.remove(tag)
picker.propertyChanged(tag) return
} }
picker.propertyChangedEvent(tag)
} }
func (picker *timePickerData) Set(tag string, value interface{}) bool { func (picker *timePickerData) Set(tag string, value interface{}) bool {
@ -121,8 +140,11 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
old, oldOK := getTimeProperty(picker, TimePickerMin, Min) old, oldOK := getTimeProperty(picker, TimePickerMin, Min)
if time, ok := setTimeValue(TimePickerMin); ok { if time, ok := setTimeValue(TimePickerMin); ok {
if !oldOK || time != old { if !oldOK || time != old {
if picker.created {
updateProperty(picker.htmlID(), Min, time.Format(timeFormat), picker.session) updateProperty(picker.htmlID(), Min, time.Format(timeFormat), picker.session)
} }
picker.propertyChangedEvent(tag)
}
return true return true
} }
@ -130,33 +152,41 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
old, oldOK := getTimeProperty(picker, TimePickerMax, Max) old, oldOK := getTimeProperty(picker, TimePickerMax, Max)
if time, ok := setTimeValue(TimePickerMax); ok { if time, ok := setTimeValue(TimePickerMax); ok {
if !oldOK || time != old { if !oldOK || time != old {
if picker.created {
updateProperty(picker.htmlID(), Max, time.Format(timeFormat), picker.session) updateProperty(picker.htmlID(), Max, time.Format(timeFormat), picker.session)
} }
picker.propertyChangedEvent(tag)
}
return true return true
} }
case TimePickerStep: case TimePickerStep:
oldStep := GetTimePickerStep(picker, "") oldStep := GetTimePickerStep(picker, "")
if picker.setIntProperty(TimePickerStep, value) { if picker.setIntProperty(TimePickerStep, value) {
step := GetTimePickerStep(picker, "") if step := GetTimePickerStep(picker, ""); oldStep != step {
if oldStep != step { if picker.created {
if step > 0 { if step > 0 {
updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session) updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session)
} else { } else {
removeProperty(picker.htmlID(), Step, picker.session) removeProperty(picker.htmlID(), Step, picker.session)
} }
} }
picker.propertyChangedEvent(tag)
}
return true return true
} }
case TimePickerValue: case TimePickerValue:
oldTime := GetTimePickerValue(picker, "") oldTime := GetTimePickerValue(picker, "")
if time, ok := setTimeValue(TimePickerMax); ok { if time, ok := setTimeValue(TimePickerMax); ok {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat)))
if time != oldTime { if time != oldTime {
if picker.created {
picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat)))
}
for _, listener := range picker.timeChangedListeners { for _, listener := range picker.timeChangedListeners {
listener(picker, time) listener(picker, time)
} }
picker.propertyChangedEvent(tag)
} }
return true return true
} }
@ -167,8 +197,8 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
picker.timeChangedListeners = []func(TimePicker, time.Time){value} picker.timeChangedListeners = []func(TimePicker, time.Time){value}
case func(time.Time): case func(time.Time):
fn := func(view TimePicker, date time.Time) { fn := func(view TimePicker, time time.Time) {
value(date) value(time)
} }
picker.timeChangedListeners = []func(TimePicker, time.Time){fn} picker.timeChangedListeners = []func(TimePicker, time.Time){fn}
@ -183,8 +213,8 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
return false return false
} }
listeners[i] = func(view TimePicker, date time.Time) { listeners[i] = func(view TimePicker, time time.Time) {
val(date) val(time)
} }
} }
picker.timeChangedListeners = listeners picker.timeChangedListeners = listeners
@ -202,8 +232,8 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
listeners[i] = val listeners[i] = val
case func(time.Time): case func(time.Time):
listeners[i] = func(view TimePicker, date time.Time) { listeners[i] = func(view TimePicker, time time.Time) {
val(date) val(time)
} }
default: default:
@ -213,13 +243,11 @@ func (picker *timePickerData) set(tag string, value interface{}) bool {
} }
picker.timeChangedListeners = listeners picker.timeChangedListeners = listeners
} }
picker.propertyChangedEvent(tag)
return true return true
default: default:
if picker.viewData.set(tag, value) { return picker.viewData.set(tag, value)
picker.propertyChanged(tag)
return true
}
} }
return false return false
} }
@ -273,7 +301,7 @@ func (picker *timePickerData) htmlProperties(self View, buffer *strings.Builder)
} }
func (picker *timePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (picker *timePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) {
if IsDisabled(self) { if IsDisabled(self, "") {
buffer.WriteString(` disabled`) buffer.WriteString(` disabled`)
} }
picker.viewData.htmlDisabledProperties(self, buffer) picker.viewData.htmlDisabledProperties(self, buffer)

148
view.go
View File

@ -57,6 +57,8 @@ type View interface {
// a description of the error is written to the log // a description of the error is written to the log
SetAnimated(tag string, value interface{}, animation Animation) bool SetAnimated(tag string, value interface{}, animation Animation) bool
SetChangeListener(tag string, listener func(View, string))
handleCommand(self View, command string, data DataObject) bool handleCommand(self View, command string, data DataObject) bool
//updateEventHandlers() //updateEventHandlers()
htmlClass(disabled bool) string htmlClass(disabled bool) string
@ -87,6 +89,7 @@ type viewData struct {
_htmlID string _htmlID string
parentID string parentID string
systemClass string systemClass string
changeListener map[string]func(View, string)
singleTransition map[string]Animation singleTransition map[string]Animation
addCSS map[string]string addCSS map[string]string
frame Frame frame Frame
@ -129,6 +132,7 @@ func (view *viewData) Init(session Session) {
view.viewStyle.init() view.viewStyle.init()
view.tag = "View" view.tag = "View"
view.session = session view.session = session
view.changeListener = map[string]func(View, string){}
view.addCSS = map[string]string{} view.addCSS = map[string]string{}
//view.animation = map[string]AnimationEndListener{} //view.animation = map[string]AnimationEndListener{}
view.singleTransition = map[string]Animation{} view.singleTransition = map[string]Animation{}
@ -186,7 +190,7 @@ func (view *viewData) remove(tag string) {
case Style, StyleDisabled: case Style, StyleDisabled:
if _, ok := view.properties[tag]; ok { if _, ok := view.properties[tag]; ok {
delete(view.properties, tag) delete(view.properties, tag)
updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view)), view.session) updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view, "")), view.session)
} }
case FocusEvent, LostFocusEvent: case FocusEvent, LostFocusEvent:
@ -221,8 +225,62 @@ func (view *viewData) remove(tag string) {
default: default:
view.viewStyle.remove(tag) view.viewStyle.remove(tag)
view.propertyChanged(tag) viewPropertyChanged(view, tag)
} }
view.propertyChangedEvent(tag)
}
func (view *viewData) propertyChangedEvent(tag string) {
if listener, ok := view.changeListener[tag]; ok {
listener(view, tag)
}
switch tag {
case BorderLeft, BorderRight, BorderTop, BorderBottom,
BorderStyle, BorderLeftStyle, BorderRightStyle, BorderTopStyle, BorderBottomStyle,
BorderColor, BorderLeftColor, BorderRightColor, BorderTopColor, BorderBottomColor,
BorderWidth, BorderLeftWidth, BorderRightWidth, BorderTopWidth, BorderBottomWidth:
tag = Border
case CellBorderStyle, CellBorderColor, CellBorderWidth,
CellBorderLeft, CellBorderLeftStyle, CellBorderLeftColor, CellBorderLeftWidth,
CellBorderRight, CellBorderRightStyle, CellBorderRightColor, CellBorderRightWidth,
CellBorderTop, CellBorderTopStyle, CellBorderTopColor, CellBorderTopWidth,
CellBorderBottom, CellBorderBottomStyle, CellBorderBottomColor, CellBorderBottomWidth:
tag = CellBorder
case OutlineColor, OutlineStyle, OutlineWidth:
tag = Outline
case RadiusX, RadiusY, RadiusTopLeft, RadiusTopLeftX, RadiusTopLeftY,
RadiusTopRight, RadiusTopRightX, RadiusTopRightY,
RadiusBottomLeft, RadiusBottomLeftX, RadiusBottomLeftY,
RadiusBottomRight, RadiusBottomRightX, RadiusBottomRightY:
tag = Radius
case MarginTop, MarginRight, MarginBottom, MarginLeft,
"top-margin", "right-margin", "bottom-margin", "left-margin":
tag = Margin
case PaddingTop, PaddingRight, PaddingBottom, PaddingLeft,
"top-padding", "right-padding", "bottom-padding", "left-padding":
tag = Padding
case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft:
tag = CellPadding
case ColumnSeparatorStyle, ColumnSeparatorWidth, ColumnSeparatorColor:
tag = ColumnSeparator
default:
return
}
if listener, ok := view.changeListener[tag]; ok {
listener(view, tag)
}
} }
func (view *viewData) Set(tag string, value interface{}) bool { func (view *viewData) Set(tag string, value interface{}) bool {
@ -235,64 +293,71 @@ func (view *viewData) set(tag string, value interface{}) bool {
return true return true
} }
result := func(res bool) bool {
if res {
view.propertyChangedEvent(tag)
}
return res
}
switch tag { switch tag {
case ID: case ID:
if text, ok := value.(string); ok { text, ok := value.(string)
view.viewID = text if !ok {
return true
}
notCompatibleType(ID, value) notCompatibleType(ID, value)
return false return false
}
view.viewID = text
case Style, StyleDisabled: case Style, StyleDisabled:
if text, ok := value.(string); ok { text, ok := value.(string)
view.properties[tag] = text if !ok {
//updateInnerHTML(view.parentID, view.session)
if view.created {
updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view)), view.session)
}
return true
}
notCompatibleType(ID, value) notCompatibleType(ID, value)
return false return false
}
view.properties[tag] = text
if view.created {
updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view, "")), view.session)
}
case FocusEvent, LostFocusEvent: case FocusEvent, LostFocusEvent:
return view.setFocusListener(tag, value) return result(view.setFocusListener(tag, value))
case KeyDownEvent, KeyUpEvent: case KeyDownEvent, KeyUpEvent:
return view.setKeyListener(tag, value) return result(view.setKeyListener(tag, value))
case ClickEvent, DoubleClickEvent, MouseDown, MouseUp, MouseMove, MouseOut, MouseOver, ContextMenuEvent: case ClickEvent, DoubleClickEvent, MouseDown, MouseUp, MouseMove, MouseOut, MouseOver, ContextMenuEvent:
return view.setMouseListener(tag, value) return result(view.setMouseListener(tag, value))
case PointerDown, PointerUp, PointerMove, PointerOut, PointerOver, PointerCancel: case PointerDown, PointerUp, PointerMove, PointerOut, PointerOver, PointerCancel:
return view.setPointerListener(tag, value) return result(view.setPointerListener(tag, value))
case TouchStart, TouchEnd, TouchMove, TouchCancel: case TouchStart, TouchEnd, TouchMove, TouchCancel:
return view.setTouchListener(tag, value) return result(view.setTouchListener(tag, value))
case TransitionRunEvent, TransitionStartEvent, TransitionEndEvent, TransitionCancelEvent: case TransitionRunEvent, TransitionStartEvent, TransitionEndEvent, TransitionCancelEvent:
return view.setTransitionListener(tag, value) return result(view.setTransitionListener(tag, value))
case AnimationStartEvent, AnimationEndEvent, AnimationIterationEvent, AnimationCancelEvent: case AnimationStartEvent, AnimationEndEvent, AnimationIterationEvent, AnimationCancelEvent:
return view.setAnimationListener(tag, value) return result(view.setAnimationListener(tag, value))
case ResizeEvent, ScrollEvent: case ResizeEvent, ScrollEvent:
return view.setFrameListener(tag, value) return result(view.setFrameListener(tag, value))
default:
if !view.viewStyle.set(tag, value) {
return false
}
if view.created {
viewPropertyChanged(view, tag)
}
} }
if view.viewStyle.set(tag, value) { view.propertyChangedEvent(tag)
if view.created {
view.propertyChanged(tag)
}
return true return true
} }
return false func viewPropertyChanged(view *viewData, tag string) {
}
func (view *viewData) propertyChanged(tag string) {
if view.updateTransformProperty(tag) { if view.updateTransformProperty(tag) {
return return
} }
@ -446,7 +511,7 @@ func (view *viewData) propertyChanged(tag string) {
case Strikethrough, Overline, Underline: case Strikethrough, Overline, Underline:
updateCSSProperty(htmlID, "text-decoration", view.cssTextDecoration(session), session) updateCSSProperty(htmlID, "text-decoration", view.cssTextDecoration(session), session)
for _, tag2 := range []string{TextLineColor, TextLineStyle, TextLineThickness} { for _, tag2 := range []string{TextLineColor, TextLineStyle, TextLineThickness} {
view.propertyChanged(tag2) viewPropertyChanged(view, tag2)
} }
return return
@ -568,7 +633,7 @@ func (view *viewData) htmlProperties(self View, buffer *strings.Builder) {
} }
func (view *viewData) htmlDisabledProperties(self View, buffer *strings.Builder) { func (view *viewData) htmlDisabledProperties(self View, buffer *strings.Builder) {
if IsDisabled(self) { if IsDisabled(self, "") {
buffer.WriteString(` data-disabled="1"`) buffer.WriteString(` data-disabled="1"`)
} else { } else {
buffer.WriteString(` data-disabled="0"`) buffer.WriteString(` data-disabled="0"`)
@ -583,7 +648,7 @@ func viewHTML(view View, buffer *strings.Builder) {
buffer.WriteString(view.htmlID()) buffer.WriteString(view.htmlID())
buffer.WriteRune('"') buffer.WriteRune('"')
disabled := IsDisabled(view) disabled := IsDisabled(view, "")
if cls := view.htmlClass(disabled); cls != "" { if cls := view.htmlClass(disabled); cls != "" {
buffer.WriteString(` class="`) buffer.WriteString(` class="`)
@ -660,7 +725,7 @@ func (view *viewData) handleCommand(self View, command string, data DataObject)
switch command { switch command {
case KeyDownEvent, KeyUpEvent: case KeyDownEvent, KeyUpEvent:
if !IsDisabled(self) { if !IsDisabled(self, "") {
handleKeyEvents(self, command, data) handleKeyEvents(self, command, data)
} }
@ -767,13 +832,10 @@ func (view *viewData) String() string {
return writer.finish() return writer.finish()
} }
// IsDisabled returns "true" if the view is disabled func (view *viewData) SetChangeListener(tag string, listener func(View, string)) {
func IsDisabled(view View) bool { if listener == nil {
if disabled, _ := boolProperty(view, Disabled, view.Session()); disabled { delete(view.changeListener, tag)
return true } else {
view.changeListener[tag] = listener
} }
if parent := view.Parent(); parent != nil {
return IsDisabled(parent)
}
return false
} }

View File

@ -4,7 +4,13 @@ package rui
// The type of return value depends on the property. // The type of return value depends on the property.
// If the subview don't exists or the property is not set then nil is returned. // If the subview don't exists or the property is not set then nil is returned.
func Get(rootView View, viewID, tag string) interface{} { func Get(rootView View, viewID, tag string) interface{} {
if view := ViewByID(rootView, viewID); view != nil { var view View
if viewID != "" {
view = ViewByID(rootView, viewID)
} else {
view = rootView
}
if view != nil {
return view.Get(tag) return view.Get(tag)
} }
return nil return nil
@ -14,12 +20,29 @@ func Get(rootView View, viewID, tag string) interface{} {
// true - success, // true - success,
// false - error (incompatible type or invalid format of a string value, see AppLog). // false - error (incompatible type or invalid format of a string value, see AppLog).
func Set(rootView View, viewID, tag string, value interface{}) bool { func Set(rootView View, viewID, tag string, value interface{}) bool {
if view := ViewByID(rootView, viewID); view != nil { var view View
if viewID != "" {
view = ViewByID(rootView, viewID)
} else {
view = rootView
}
if view != nil {
return view.Set(tag, value) return view.Set(tag, value)
} }
return false return false
} }
// SetChangeListener sets a listener for changing a subview property value.
// If the second argument (subviewID) is "" then a listener for the first argument (view) is set
func SetChangeListener(view View, viewID, tag string, listener func(View, string)) {
if viewID != "" {
view = ViewByID(view, viewID)
}
if view != nil {
view.SetChangeListener(tag, listener)
}
}
// SetParams sets properties with name "tag" of the "rootView" subview. Result: // SetParams sets properties with name "tag" of the "rootView" subview. Result:
// true - all properties were set successful, // true - all properties were set successful,
// false - error (incompatible type or invalid format of a string value, see AppLog). // false - error (incompatible type or invalid format of a string value, see AppLog).
@ -36,6 +59,22 @@ func SetParams(rootView View, viewID string, params Params) bool {
return result return result
} }
// IsDisabled returns "true" if the subview is disabled
// If the second argument (subviewID) is "" then a state of the first argument (view) is returned
func IsDisabled(view View, subviewID string) bool {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if disabled, _ := boolProperty(view, Disabled, view.Session()); disabled {
return true
}
if parent := view.Parent(); parent != nil {
return IsDisabled(parent, "")
}
return false
}
// GetSemantics returns the subview semantics. Valid semantics values are // GetSemantics returns the subview semantics. Valid semantics values are
// DefaultSemantics (0), ArticleSemantics (1), SectionSemantics (2), AsideSemantics (3), // DefaultSemantics (0), ArticleSemantics (1), SectionSemantics (2), AsideSemantics (3),
// HeaderSemantics (4), MainSemantics (5), FooterSemantics (6), NavigationSemantics (7), // HeaderSemantics (4), MainSemantics (5), FooterSemantics (6), NavigationSemantics (7),
@ -926,7 +965,7 @@ func valueFromStyle(view View, tag string) (string, bool) {
return "", false return "", false
} }
if IsDisabled(view) { if IsDisabled(view, "") {
if value, ok := getValue(StyleDisabled); ok { if value, ok := getValue(StyleDisabled); ok {
return value, true return value, true
} }

View File

@ -39,16 +39,6 @@ func (container *viewsContainerData) setParentID(parentID string) {
} }
} }
// SetDisabled set the View disabled state
func (container *viewsContainerData) SetDisabled(disabled bool) {
container.viewData.Set(Disabled, disabled)
if container.views != nil {
for _, view := range container.views {
view.Set(Disabled, disabled)
}
}
}
// Views return a list of child views // Views return a list of child views
func (container *viewsContainerData) Views() []View { func (container *viewsContainerData) Views() []View {
if container.views == nil { if container.views == nil {
@ -68,6 +58,7 @@ func (container *viewsContainerData) Append(view View) {
container.views = append(container.views, view) container.views = append(container.views, view)
} }
updateInnerHTML(container.htmlID(), container.session) updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
} }
} }
@ -81,10 +72,12 @@ func (container *viewsContainerData) Insert(view View, index uint) {
view.setParentID(htmlID) view.setParentID(htmlID)
container.views = append(container.views[:index], append([]View{view}, container.views[index:]...)...) container.views = append(container.views[:index], append([]View{view}, container.views[index:]...)...)
updateInnerHTML(container.htmlID(), container.session) updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
} else { } else {
view.setParentID(htmlID) view.setParentID(htmlID)
container.views = append([]View{view}, container.views...) container.views = append([]View{view}, container.views...)
updateInnerHTML(container.htmlID(), container.session) updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
} }
} }
} }
@ -112,6 +105,7 @@ func (container *viewsContainerData) RemoveView(index uint) View {
view.setParentID("") view.setParentID("")
updateInnerHTML(container.htmlID(), container.session) updateInnerHTML(container.htmlID(), container.session)
container.propertyChangedEvent(Content)
return view return view
} }
@ -151,6 +145,18 @@ func (container *viewsContainerData) remove(tag string) {
container.views = []View{} container.views = []View{}
updateInnerHTML(container.htmlID(), container.Session()) 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: default:
container.viewData.remove(tag) container.viewData.remove(tag)
@ -167,7 +173,27 @@ func (container *viewsContainerData) set(tag string, value interface{}) bool {
return true return true
} }
if tag != Content { 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) return container.viewData.set(tag, value)
} }
@ -239,6 +265,8 @@ func (container *viewsContainerData) set(tag string, value interface{}) bool {
if container.created { if container.created {
updateInnerHTML(htmlID, container.session) updateInnerHTML(htmlID, container.session)
} }
container.propertyChangedEvent(Content)
return true return true
} }