rui_orig/listView.go

1208 lines
35 KiB
Go
Raw Permalink Normal View History

2021-09-07 17:36:50 +03:00
package rui
import (
"fmt"
"strconv"
"strings"
)
// Constants which represent [ListView] specific properties and events
2021-09-07 17:36:50 +03:00
const (
// ListItemClickedEvent is the constant for "list-item-clicked" property tag.
//
// Used by `ListView`.
// Occur when the user clicks on an item in the list.
//
// General listener format:
// `func(list rui.ListView, item int)`.
//
// where:
// list - Interface of a list which generated this event,
// item - An index of an item clicked.
//
// Allowed listener formats:
// `func(item int)`,
// `func(list rui.ListView)`,
// `func()`.
2024-11-13 12:56:39 +03:00
ListItemClickedEvent PropertyName = "list-item-clicked"
2024-04-23 19:34:36 +03:00
2021-09-07 17:36:50 +03:00
// ListItemSelectedEvent is the constant for "list-item-selected" property tag.
//
// Used by `ListView`.
// Occur when a list item becomes selected.
//
// General listener format:
// `func(list rui.ListView, item int)`.
//
// where:
// list - Interface of a list which generated this event,
// item - An index of an item selected.
//
// Allowed listener formats:
2024-11-13 12:56:39 +03:00
ListItemSelectedEvent PropertyName = "list-item-selected"
2024-04-23 19:34:36 +03:00
2021-09-07 17:36:50 +03:00
// ListItemCheckedEvent is the constant for "list-item-checked" property tag.
//
// Used by `ListView`.
// Occur when a list item checkbox becomes checked or unchecked.
//
// General listener format:
// `func(list rui.ListView, checkedItems []int)`.
//
// where:
// list - Interface of a list which generated this event,
// checkedItems - Array of indices of marked elements.
//
// Allowed listener formats:
// `func(checkedItems []int)`,
// `func(list rui.ListView)`,
// `func()`.
2024-11-13 12:56:39 +03:00
ListItemCheckedEvent PropertyName = "list-item-checked"
2024-04-23 19:34:36 +03:00
2021-11-04 21:13:34 +03:00
// ListItemStyle is the constant for "list-item-style" property tag.
//
// Used by `ListView`.
// Defines the style of an unselected item.
//
// Supported types: `string`.
2024-11-13 12:56:39 +03:00
ListItemStyle PropertyName = "list-item-style"
2024-04-23 19:34:36 +03:00
2021-11-04 21:13:34 +03:00
// CurrentStyle is the constant for "current-style" property tag.
//
// Used by `ListView`.
// Defines the style of the selected item when the `ListView` is focused.
//
// Supported types: `string`.
2024-11-13 12:56:39 +03:00
CurrentStyle PropertyName = "current-style"
2024-04-23 19:34:36 +03:00
2021-11-04 21:13:34 +03:00
// CurrentInactiveStyle is the constant for "current-inactive-style" property tag.
//
// Used by `ListView`.
// Defines the style of the selected item when the `ListView` is unfocused.
//
// Supported types: `string`.
2024-11-13 12:56:39 +03:00
CurrentInactiveStyle PropertyName = "current-inactive-style"
2021-09-07 17:36:50 +03:00
)
// Constants which represent values of the "orientation" property of the [ListView]. These are aliases for values used in
// [ListLayout] "orientation" property like TopDownOrientation and StartToEndOrientation
2021-09-07 17:36:50 +03:00
const (
// VerticalOrientation is the vertical ListView orientation
VerticalOrientation = 0
2021-09-07 17:36:50 +03:00
// HorizontalOrientation is the horizontal ListView orientation
HorizontalOrientation = 1
)
2021-09-07 17:36:50 +03:00
// Constants which represent values of a "checkbox" property of [ListView]
const (
2021-09-07 17:36:50 +03:00
// NoneCheckbox is value of "checkbox" property: no checkbox
NoneCheckbox = 0
2021-09-07 17:36:50 +03:00
// SingleCheckbox is value of "checkbox" property: only one item can be checked
SingleCheckbox = 1
2021-09-07 17:36:50 +03:00
// MultipleCheckbox is value of "checkbox" property: several items can be checked
MultipleCheckbox = 2
)
// ListView represents a ListView view
2021-09-07 17:36:50 +03:00
type ListView interface {
View
2022-11-23 15:10:29 +03:00
ParentView
2021-09-07 17:36:50 +03:00
// ReloadListViewData updates ListView content
ReloadListViewData()
2024-11-13 12:56:39 +03:00
//getCheckedItems() []int
2021-09-07 17:36:50 +03:00
getItemFrames() []Frame
}
type listViewData struct {
viewData
2024-11-13 12:56:39 +03:00
//adapter ListAdapter
//clickedListeners []func(ListView, int)
//selectedListeners []func(ListView, int)
//checkedListeners []func(ListView, []int)
items []View
itemFrame []Frame
//checkedItem []int
2021-09-07 17:36:50 +03:00
}
// NewListView creates the new list view
func NewListView(session Session, params Params) ListView {
view := new(listViewData)
view.init(session)
2021-09-07 17:36:50 +03:00
setInitParams(view, params)
return view
}
func newListView(session Session) View {
2024-11-13 12:56:39 +03:00
return new(listViewData) // NewListView(session, nil)
2021-09-07 17:36:50 +03:00
}
// Init initialize fields of ViewsContainer by default values
func (listView *listViewData) init(session Session) {
listView.viewData.init(session)
2021-09-07 17:36:50 +03:00
listView.tag = "ListView"
listView.systemClass = "ruiListView"
listView.items = []View{}
listView.itemFrame = []Frame{}
2024-11-13 12:56:39 +03:00
listView.normalize = normalizeListViewTag
listView.get = listView.getFunc
listView.set = listView.setFunc
listView.remove = listView.removeFunc
listView.changed = listView.propertyChanged
2022-05-22 12:54:02 +03:00
}
2021-09-07 17:36:50 +03:00
func (listView *listViewData) Views() []View {
return listView.items
}
2024-11-13 12:56:39 +03:00
func normalizeListViewTag(tag PropertyName) PropertyName {
tag = defaultNormalize(tag)
2021-09-07 17:36:50 +03:00
switch tag {
2024-11-13 12:56:39 +03:00
case Content:
tag = Items
2021-09-07 17:36:50 +03:00
case HorizontalAlign:
tag = ItemHorizontalAlign
case VerticalAlign:
tag = ItemVerticalAlign
case "wrap":
tag = ListWrap
case "row-gap":
return ListRowGap
case ColumnGap:
return ListColumnGap
2021-09-07 17:36:50 +03:00
}
return tag
}
func (listView *listViewData) removeFunc(tag PropertyName) []PropertyName {
2021-09-07 17:36:50 +03:00
switch tag {
case Gap:
result := listView.removeFunc(ListRowGap)
2024-11-13 12:56:39 +03:00
if result != nil {
if result2 := listView.removeFunc(ListColumnGap); result2 != nil {
2024-11-13 12:56:39 +03:00
result = append(result, result2...)
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
return result
2021-09-07 17:36:50 +03:00
}
return listView.viewData.removeFunc(tag)
2021-09-07 17:36:50 +03:00
}
func (listView *listViewData) setFunc(tag PropertyName, value any) []PropertyName {
2021-09-07 17:36:50 +03:00
switch tag {
case Gap:
result := listView.setFunc(ListRowGap, value)
2024-11-13 12:56:39 +03:00
if result != nil {
if result2 := listView.setFunc(ListColumnGap, value); result2 != nil {
2024-11-13 12:56:39 +03:00
result = append(result, result2...)
}
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
return result
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
case ListItemClickedEvent, ListItemSelectedEvent:
return setOneArgEventListener[ListView, int](listView, tag, value)
2021-09-07 17:36:50 +03:00
case ListItemCheckedEvent:
return setOneArgEventListener[ListView, []int](listView, tag, value)
2021-09-07 17:36:50 +03:00
case Checked:
2024-11-13 12:56:39 +03:00
var checked []int
switch value := value.(type) {
case string:
elements := strings.Split(value, ",")
checked = make([]int, 0, len(elements))
for _, val := range elements {
if val = strings.Trim(val, " \t"); val != "" {
n, err := strconv.Atoi(val)
if err != nil {
invalidPropertyValue(Checked, value)
ErrorLog(err.Error())
return nil
}
checked = append(checked, n)
}
}
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
case int:
checked = []int{value}
2023-05-18 12:26:54 +03:00
2024-11-13 12:56:39 +03:00
case []int:
checked = value
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
default:
notCompatibleType(tag, value)
return nil
}
2021-09-07 17:36:50 +03:00
return setArrayPropertyValue(listView, Checked, checked)
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
case Items:
return listView.setItems(value)
2021-09-07 17:36:50 +03:00
case ListItemStyle, CurrentStyle, CurrentInactiveStyle:
2024-11-13 12:56:39 +03:00
if text, ok := value.(string); ok {
return setStringPropertyValue(listView, tag, text)
}
2024-11-13 12:56:39 +03:00
notCompatibleType(tag, value)
return nil
2024-11-13 12:56:39 +03:00
case Current:
return setIntProperty(listView, Current, value)
2021-09-07 17:36:50 +03:00
}
return listView.viewData.setFunc(tag, value)
2024-11-13 12:56:39 +03:00
2021-09-07 17:36:50 +03:00
}
func (listView *listViewData) propertyChanged(tag PropertyName) {
2024-11-13 12:56:39 +03:00
switch tag {
case Current:
updateInnerHTML(listView.htmlID(), listView.Session())
if listeners := getOneArgEventListeners[ListView, int](listView, nil, ListItemSelectedEvent); len(listeners) > 0 {
current := GetCurrent(listView)
for _, listener := range listeners {
listener(listView, current)
2024-11-13 12:56:39 +03:00
}
2023-05-18 12:26:54 +03:00
}
2024-11-13 12:56:39 +03:00
case Checked:
updateInnerHTML(listView.htmlID(), listView.Session())
if listeners := getOneArgEventListeners[ListView, []int](listView, nil, ListItemCheckedEvent); len(listeners) > 0 {
checked := GetListViewCheckedItems(listView)
for _, listener := range listeners {
listener(listView, checked)
2024-11-13 12:56:39 +03:00
}
}
2023-05-18 12:26:54 +03:00
2024-11-13 12:56:39 +03:00
case Items, Orientation, ListWrap, ListRowGap, ListColumnGap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight,
ItemHorizontalAlign, ItemVerticalAlign, ItemCheckbox, CheckboxHorizontalAlign, CheckboxVerticalAlign, ListItemStyle, AccentColor:
updateInnerHTML(listView.htmlID(), listView.Session())
2023-05-18 12:26:54 +03:00
2024-11-13 12:56:39 +03:00
case CurrentStyle:
listView.Session().updateProperty(listView.htmlID(), "data-focusitemstyle", listViewCurrentStyle(listView))
updateInnerHTML(listView.htmlID(), listView.Session())
2023-05-18 12:26:54 +03:00
2024-11-13 12:56:39 +03:00
case CurrentInactiveStyle:
listView.Session().updateProperty(listView.htmlID(), "data-bluritemstyle", listViewCurrentInactiveStyle(listView))
updateInnerHTML(listView.htmlID(), listView.Session())
2023-05-18 12:26:54 +03:00
2024-11-13 12:56:39 +03:00
default:
listView.viewData.propertyChanged(tag)
2024-11-13 12:56:39 +03:00
}
2021-09-07 17:36:50 +03:00
}
func (listView *listViewData) getFunc(tag PropertyName) any {
2021-09-07 17:36:50 +03:00
switch tag {
case Gap:
if rowGap := GetListRowGap(listView); rowGap.Equal(GetListColumnGap(listView)) {
return rowGap
}
return AutoSize()
2024-11-13 12:56:39 +03:00
}
return listView.viewData.getFunc(tag)
2024-11-13 12:56:39 +03:00
}
func (listView *listViewData) setItems(value any) []PropertyName {
2024-11-13 12:56:39 +03:00
var adapter ListAdapter = nil
2021-09-07 17:36:50 +03:00
session := listView.session
2021-09-07 17:36:50 +03:00
switch value := value.(type) {
case []string:
2024-11-13 12:56:39 +03:00
adapter = NewTextListAdapter(value, nil)
2021-09-07 17:36:50 +03:00
case []DataValue:
hasObject := false
for _, val := range value {
if val.IsObject() {
hasObject = true
break
}
}
if hasObject {
items := make([]View, len(value))
for i, val := range value {
if val.IsObject() {
2024-11-13 12:56:39 +03:00
if view := CreateViewFromObject(session, val.Object()); view != nil {
2021-09-07 17:36:50 +03:00
items[i] = view
} else {
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
} else {
2024-11-13 12:56:39 +03:00
items[i] = NewTextView(session, Params{Text: val.Value()})
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
adapter = NewViewListAdapter(items)
2021-09-07 17:36:50 +03:00
} else {
items := make([]string, len(value))
for i, val := range value {
items[i] = val.Value()
}
2024-11-13 12:56:39 +03:00
adapter = NewTextListAdapter(items, nil)
2021-09-07 17:36:50 +03:00
}
2022-07-26 18:36:00 +03:00
case []any:
2021-09-07 17:36:50 +03:00
items := make([]View, len(value))
for i, val := range value {
switch value := val.(type) {
case View:
items[i] = value
case string:
2024-11-13 12:56:39 +03:00
items[i] = NewTextView(session, Params{Text: value})
2021-09-07 17:36:50 +03:00
case fmt.Stringer:
2024-11-13 12:56:39 +03:00
items[i] = NewTextView(session, Params{Text: value.String()})
2021-09-07 17:36:50 +03:00
case float32:
2024-11-13 12:56:39 +03:00
items[i] = NewTextView(session, Params{Text: fmt.Sprintf("%g", float64(value))})
2021-09-07 17:36:50 +03:00
case float64:
2024-11-13 12:56:39 +03:00
items[i] = NewTextView(session, Params{Text: fmt.Sprintf("%g", value)})
2021-09-07 17:36:50 +03:00
default:
if n, ok := isInt(val); ok {
2024-11-13 12:56:39 +03:00
items[i] = NewTextView(session, Params{Text: strconv.Itoa(n)})
2021-09-07 17:36:50 +03:00
} else {
notCompatibleType(Items, value)
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
}
}
2024-11-13 12:56:39 +03:00
adapter = NewViewListAdapter(items)
2021-09-07 17:36:50 +03:00
case []View:
2024-11-13 12:56:39 +03:00
adapter = NewViewListAdapter(value)
2021-09-07 17:36:50 +03:00
case ListAdapter:
2024-11-13 12:56:39 +03:00
adapter = value
2021-09-07 17:36:50 +03:00
default:
notCompatibleType(Items, value)
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
listView.setRaw(Items, adapter)
2024-11-13 12:56:39 +03:00
return []PropertyName{Items}
}
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
func (listView *listViewData) Focusable() bool {
2021-09-07 17:36:50 +03:00
return true
}
2024-11-13 12:56:39 +03:00
func (listView *listViewData) getAdapter() ListAdapter {
if value := listView.getRaw(Items); value != nil {
if adapter, ok := value.(ListAdapter); ok {
return adapter
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
func (listView *listViewData) ReloadListViewData() {
itemCount := 0
2024-11-13 12:56:39 +03:00
if adapter := listView.getAdapter(); adapter != nil {
itemCount = adapter.ListSize()
2021-09-07 17:36:50 +03:00
if itemCount != len(listView.items) {
listView.items = make([]View, itemCount)
listView.itemFrame = make([]Frame, itemCount)
}
for i := 0; i < itemCount; i++ {
2024-11-13 12:56:39 +03:00
listView.items[i] = adapter.ListItem(i, listView.Session())
2021-09-07 17:36:50 +03:00
}
} else if len(listView.items) > 0 {
listView.items = []View{}
listView.itemFrame = []Frame{}
}
updateInnerHTML(listView.htmlID(), listView.session)
}
func (listView *listViewData) getItemFrames() []Frame {
return listView.itemFrame
}
2024-02-27 17:08:05 +03:00
func (listView *listViewData) itemAlign(buffer *strings.Builder) {
2021-09-07 17:36:50 +03:00
values := enumProperties[ItemHorizontalAlign].cssValues
if hAlign := GetListItemHorizontalAlign(listView); hAlign >= 0 && hAlign < len(values) {
2021-09-07 17:36:50 +03:00
buffer.WriteString(" justify-items: ")
buffer.WriteString(values[hAlign])
buffer.WriteRune(';')
}
values = enumProperties[ItemVerticalAlign].cssValues
if vAlign := GetListItemVerticalAlign(listView); vAlign >= 0 && vAlign < len(values) {
2021-09-07 17:36:50 +03:00
buffer.WriteString(" align-items: ")
buffer.WriteString(values[vAlign])
buffer.WriteRune(';')
}
}
2024-02-27 17:08:05 +03:00
func (listView *listViewData) itemSize(buffer *strings.Builder) {
if itemWidth := GetListItemWidth(listView); itemWidth.Type != Auto {
2021-09-07 17:36:50 +03:00
buffer.WriteString(` min-width: `)
buffer.WriteString(itemWidth.cssString("", listView.Session()))
2021-09-07 17:36:50 +03:00
buffer.WriteRune(';')
}
if itemHeight := GetListItemHeight(listView); itemHeight.Type != Auto {
2021-09-07 17:36:50 +03:00
buffer.WriteString(` min-height: `)
buffer.WriteString(itemHeight.cssString("", listView.Session()))
2021-09-07 17:36:50 +03:00
buffer.WriteRune(';')
}
}
2024-02-27 17:08:05 +03:00
func (listView *listViewData) getDivs(checkbox, hCheckboxAlign, vCheckboxAlign int) (string, string, string) {
2021-09-07 17:36:50 +03:00
session := listView.Session()
contentBuilder := allocStringBuilder()
defer freeStringBuilder(contentBuilder)
contentBuilder.WriteString(`<div style="display: grid;`)
2024-02-27 17:08:05 +03:00
listView.itemAlign(contentBuilder)
2021-09-07 17:36:50 +03:00
onDivBuilder := allocStringBuilder()
defer freeStringBuilder(onDivBuilder)
if hCheckboxAlign == CenterAlign {
if vCheckboxAlign == BottomAlign {
onDivBuilder.WriteString(`<div style="grid-row: 2 / 3; grid-column: 1 / 2; display: grid; justify-items: center;`)
contentBuilder.WriteString(` grid-row: 1 / 2; grid-column: 1 / 2;">`)
} else {
vCheckboxAlign = TopAlign
onDivBuilder.WriteString(`<div style="grid-row: 1 / 2; grid-column: 1 / 2; display: grid; justify-items: center;`)
contentBuilder.WriteString(` grid-row: 2 / 3; grid-column: 1 / 2;">`)
}
} else {
if hCheckboxAlign == RightAlign {
onDivBuilder.WriteString(`<div style="grid-row: 1 / 2; grid-column: 2 / 3; display: grid;`)
contentBuilder.WriteString(` grid-row: 1 / 2; grid-column: 1 / 2;">`)
} else {
onDivBuilder.WriteString(`<div style="grid-row: 1 / 2; grid-column: 1 / 2; display: grid;`)
contentBuilder.WriteString(` grid-row: 1 / 2; grid-column: 2 / 3;">`)
}
switch vCheckboxAlign {
case BottomAlign:
onDivBuilder.WriteString(` align-items: end;`)
case CenterAlign:
onDivBuilder.WriteString(` align-items: center;`)
default:
onDivBuilder.WriteString(` align-items: start;`)
}
}
onDivBuilder.WriteString(`">`)
offDivBuilder := allocStringBuilder()
defer freeStringBuilder(offDivBuilder)
offDivBuilder.WriteString(onDivBuilder.String())
accentColor := Color(0)
if color := GetAccentColor(listView, ""); color != 0 {
accentColor = color
}
2021-09-07 17:36:50 +03:00
if checkbox == SingleCheckbox {
offDivBuilder.WriteString(session.radiobuttonOffImage())
onDivBuilder.WriteString(session.radiobuttonOnImage(accentColor))
2021-09-07 17:36:50 +03:00
} else {
offDivBuilder.WriteString(session.checkboxOffImage(accentColor))
onDivBuilder.WriteString(session.checkboxOnImage(accentColor))
2021-09-07 17:36:50 +03:00
}
onDivBuilder.WriteString("</div>")
offDivBuilder.WriteString("</div>")
return onDivBuilder.String(), offDivBuilder.String(), contentBuilder.String()
}
2024-02-27 17:08:05 +03:00
func (listView *listViewData) checkboxItemDiv(checkbox, hCheckboxAlign, vCheckboxAlign int) string {
2021-09-07 17:36:50 +03:00
itemStyleBuilder := allocStringBuilder()
defer freeStringBuilder(itemStyleBuilder)
itemStyleBuilder.WriteString(`<div style="display: grid; justify-items: stretch; align-items: stretch;`)
if hCheckboxAlign == CenterAlign {
if vCheckboxAlign == BottomAlign {
itemStyleBuilder.WriteString(` grid-template-columns: 1fr; grid-template-rows: 1fr auto;`)
} else {
vCheckboxAlign = TopAlign
itemStyleBuilder.WriteString(` grid-template-columns: 1fr; grid-template-rows: auto 1fr;`)
}
} else {
if hCheckboxAlign == RightAlign {
itemStyleBuilder.WriteString(` grid-template-columns: 1fr auto; grid-template-rows: 1fr;`)
} else {
itemStyleBuilder.WriteString(` grid-template-columns: auto 1fr; grid-template-rows: 1fr;`)
}
}
if gap, ok := sizeConstant(listView.session, "ruiCheckboxGap"); ok && gap.Type != Auto {
itemStyleBuilder.WriteString(` grid-gap: `)
itemStyleBuilder.WriteString(gap.cssString("auto", listView.Session()))
2021-09-07 17:36:50 +03:00
itemStyleBuilder.WriteRune(';')
}
itemStyleBuilder.WriteString(`">`)
return itemStyleBuilder.String()
}
2024-11-13 12:56:39 +03:00
func (listView *listViewData) getItemView(adapter ListAdapter, index int) View {
if adapter == nil || index < 0 || index >= adapter.ListSize() {
2021-09-07 17:36:50 +03:00
return nil
}
2024-11-13 12:56:39 +03:00
if size := adapter.ListSize(); size != len(listView.items) {
2021-09-07 17:36:50 +03:00
listView.items = make([]View, size)
2024-11-13 12:56:39 +03:00
listView.itemFrame = make([]Frame, size)
2021-09-07 17:36:50 +03:00
}
if listView.items[index] == nil {
2024-11-13 12:56:39 +03:00
listView.items[index] = adapter.ListItem(index, listView.Session())
2021-09-07 17:36:50 +03:00
}
return listView.items[index]
}
2024-11-13 12:56:39 +03:00
func listViewItemStyle(view View, tag PropertyName, defaultStyle string) string {
session := view.Session()
if value := view.getRaw(tag); value != nil {
2021-09-07 17:36:50 +03:00
if style, ok := value.(string); ok {
2024-11-13 12:56:39 +03:00
if style, ok = session.resolveConstants(style); ok {
2021-09-07 17:36:50 +03:00
return style
}
}
}
2024-11-13 12:56:39 +03:00
if value := valueFromStyle(view, tag); value != nil {
2021-09-07 17:36:50 +03:00
if style, ok := value.(string); ok {
2024-11-13 12:56:39 +03:00
if style, ok = session.resolveConstants(style); ok {
2021-09-07 17:36:50 +03:00
return style
}
}
}
return defaultStyle
}
func (listView *listViewData) listItemStyle() string {
2024-11-13 12:56:39 +03:00
return listViewItemStyle(listView, ListItemStyle, "ruiListItem")
}
2024-11-13 12:56:39 +03:00
func listViewCurrentStyle(view View) string {
return listViewItemStyle(view, CurrentStyle, "ruiListItemFocused")
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func listViewCurrentInactiveStyle(view View) string {
return listViewItemStyle(view, CurrentInactiveStyle, "ruiListItemSelected")
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func (listView *listViewData) checkboxSubviews(adapter ListAdapter, buffer *strings.Builder, checkbox int) {
count := adapter.ListSize()
2021-09-07 17:36:50 +03:00
listViewID := listView.htmlID()
hCheckboxAlign := GetListViewCheckboxHorizontalAlign(listView)
vCheckboxAlign := GetListViewCheckboxVerticalAlign(listView)
2021-09-07 17:36:50 +03:00
2024-02-27 17:08:05 +03:00
itemDiv := listView.checkboxItemDiv(checkbox, hCheckboxAlign, vCheckboxAlign)
onDiv, offDiv, contentDiv := listView.getDivs(checkbox, hCheckboxAlign, vCheckboxAlign)
2021-09-07 17:36:50 +03:00
current := GetCurrent(listView)
checkedItems := GetListViewCheckedItems(listView)
2021-09-07 17:36:50 +03:00
for i := 0; i < count; i++ {
buffer.WriteString(`<div id="`)
buffer.WriteString(listViewID)
buffer.WriteRune('-')
buffer.WriteString(strconv.Itoa(i))
buffer.WriteString(`" class="ruiView `)
buffer.WriteString(listView.listItemStyle())
if i == current {
buffer.WriteRune(' ')
2024-11-13 12:56:39 +03:00
buffer.WriteString(listViewCurrentInactiveStyle(listView))
2021-09-07 17:36:50 +03:00
}
buffer.WriteString(`" onclick="listItemClickEvent(this, event)" data-left="0" data-top="0" data-width="0" data-height="0" style="display: grid; justify-items: stretch; align-items: stretch;`)
2024-02-27 17:08:05 +03:00
listView.itemSize(buffer)
2024-11-13 12:56:39 +03:00
if ext, ok := adapter.(ListItemEnabled); ok {
if !ext.IsListItemEnabled(i) {
buffer.WriteString(`" data-disabled="1`)
}
2023-05-03 15:16:03 +03:00
}
2021-09-07 17:36:50 +03:00
buffer.WriteString(`">`)
buffer.WriteString(itemDiv)
checked := false
for _, index := range checkedItems {
if index == i {
buffer.WriteString(onDiv)
checked = true
break
}
}
if !checked {
buffer.WriteString(offDiv)
}
buffer.WriteString(contentDiv)
2024-11-13 12:56:39 +03:00
if view := listView.getItemView(adapter, i); view != nil {
2021-09-07 17:36:50 +03:00
//view.setNoResizeEvent()
2024-11-21 09:25:46 +03:00
viewHTML(view, buffer, "")
2021-09-07 17:36:50 +03:00
} else {
buffer.WriteString("ERROR: invalid item view")
}
buffer.WriteString(`</div></div></div>`)
}
}
2024-11-13 12:56:39 +03:00
func (listView *listViewData) noneCheckboxSubviews(adapter ListAdapter, buffer *strings.Builder) {
count := adapter.ListSize()
2021-09-07 17:36:50 +03:00
listViewID := listView.htmlID()
itemStyleBuilder := allocStringBuilder()
defer freeStringBuilder(itemStyleBuilder)
itemStyleBuilder.WriteString(`data-left="0" data-top="0" data-width="0" data-height="0" style="max-width: 100%; max-height: 100%; display: grid;`)
2024-02-27 17:08:05 +03:00
listView.itemAlign(itemStyleBuilder)
listView.itemSize(itemStyleBuilder)
2021-09-07 17:36:50 +03:00
itemStyleBuilder.WriteString(`" onclick="listItemClickEvent(this, event)"`)
itemStyle := itemStyleBuilder.String()
current := GetCurrent(listView)
2021-09-07 17:36:50 +03:00
for i := 0; i < count; i++ {
buffer.WriteString(`<div id="`)
buffer.WriteString(listViewID)
buffer.WriteRune('-')
buffer.WriteString(strconv.Itoa(i))
buffer.WriteString(`" class="ruiView `)
buffer.WriteString(listView.listItemStyle())
if i == current {
buffer.WriteRune(' ')
2024-11-13 12:56:39 +03:00
buffer.WriteString(listViewCurrentInactiveStyle(listView))
2021-09-07 17:36:50 +03:00
}
buffer.WriteString(`" `)
buffer.WriteString(itemStyle)
2024-11-13 12:56:39 +03:00
if ext, ok := adapter.(ListItemEnabled); ok {
if !ext.IsListItemEnabled(i) {
buffer.WriteString(` data-disabled="1"`)
}
2023-05-03 15:16:03 +03:00
}
2021-09-07 17:36:50 +03:00
buffer.WriteString(`>`)
2024-11-13 12:56:39 +03:00
if view := listView.getItemView(adapter, i); view != nil {
2021-09-07 17:36:50 +03:00
//view.setNoResizeEvent()
2024-11-21 09:25:46 +03:00
viewHTML(view, buffer, "")
2021-09-07 17:36:50 +03:00
} else {
buffer.WriteString("ERROR: invalid item view")
}
buffer.WriteString(`</div>`)
}
}
func (listView *listViewData) updateCheckboxItem(index int, checked bool) {
checkbox := GetListViewCheckbox(listView)
hCheckboxAlign := GetListViewCheckboxHorizontalAlign(listView)
vCheckboxAlign := GetListViewCheckboxVerticalAlign(listView)
2024-02-27 17:08:05 +03:00
onDiv, offDiv, contentDiv := listView.getDivs(checkbox, hCheckboxAlign, vCheckboxAlign)
2021-09-07 17:36:50 +03:00
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
2024-02-27 17:08:05 +03:00
buffer.WriteString(listView.checkboxItemDiv(checkbox, hCheckboxAlign, vCheckboxAlign))
2021-09-07 17:36:50 +03:00
if checked {
buffer.WriteString(onDiv)
} else {
buffer.WriteString(offDiv)
}
buffer.WriteString(contentDiv)
session := listView.Session()
2024-11-13 12:56:39 +03:00
if adapter := listView.getAdapter(); adapter != nil {
if view := listView.getItemView(adapter, index); view != nil {
2021-09-07 17:36:50 +03:00
view.setNoResizeEvent()
2024-11-21 09:25:46 +03:00
viewHTML(view, buffer, "")
2021-09-07 17:36:50 +03:00
} else {
buffer.WriteString("ERROR: invalid item view")
}
}
2022-10-29 20:16:40 +03:00
buffer.WriteString(`</div></div>`)
2022-10-30 17:22:33 +03:00
session.updateInnerHTML(listView.htmlID()+"-"+strconv.Itoa(index), buffer.String())
2021-09-07 17:36:50 +03:00
}
2021-11-11 13:23:41 +03:00
func (listView *listViewData) htmlProperties(self View, buffer *strings.Builder) {
2021-11-22 15:20:53 +03:00
listView.viewData.htmlProperties(self, buffer)
2021-11-11 13:23:41 +03:00
buffer.WriteString(`onfocus="listViewFocusEvent(this, event)" onblur="listViewBlurEvent(this, event)"`)
buffer.WriteString(` onkeydown="listViewKeyDownEvent(this, event)" data-focusitemstyle="`)
2024-11-13 12:56:39 +03:00
buffer.WriteString(listViewCurrentStyle(listView))
2021-11-11 13:23:41 +03:00
buffer.WriteString(`" data-bluritemstyle="`)
2024-11-13 12:56:39 +03:00
buffer.WriteString(listViewCurrentInactiveStyle(listView))
2021-11-11 13:23:41 +03:00
buffer.WriteString(`"`)
2024-11-13 12:56:39 +03:00
if adapter := listView.getAdapter(); adapter != nil {
if current := GetCurrent(listView); current >= 0 && current < adapter.ListSize() {
buffer.WriteString(` data-current="`)
buffer.WriteString(listView.htmlID())
buffer.WriteRune('-')
buffer.WriteString(strconv.Itoa(current))
buffer.WriteRune('"')
}
}
listView.viewData.htmlProperties(self, buffer)
2021-11-11 13:23:41 +03:00
}
/*
func (listView *listViewData) cssStyle(self View, builder cssBuilder) {
listView.viewData.cssStyle(self, builder)
if GetListWrap(listView) != WrapOff {
switch GetListOrientation(listView) {
2021-11-11 13:23:41 +03:00
case TopDownOrientation, BottomUpOrientation:
builder.add(`max-height`, `100%`)
default:
builder.add(`max-width`, `100%`)
}
2021-09-07 17:36:50 +03:00
}
2021-11-11 13:23:41 +03:00
}
*/
func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
2024-11-13 12:56:39 +03:00
adapter := listView.getAdapter()
if adapter == nil {
return
}
if listSize := adapter.ListSize(); listSize == 0 {
2021-09-07 17:36:50 +03:00
return
}
if !listView.session.ignoreViewUpdates() {
listView.session.setIgnoreViewUpdates(true)
defer listView.session.setIgnoreViewUpdates(false)
}
2021-11-11 13:23:41 +03:00
buffer.WriteString(`<div style="display: flex; align-content: stretch;`)
if gap := GetListRowGap(listView); gap.Type != Auto {
buffer.WriteString(` row-gap: `)
buffer.WriteString(gap.cssString("0", listView.Session()))
buffer.WriteRune(';')
}
if gap := GetListColumnGap(listView); gap.Type != Auto {
buffer.WriteString(` column-gap: `)
buffer.WriteString(gap.cssString("0", listView.Session()))
buffer.WriteRune(';')
}
wrap := GetListWrap(listView)
orientation := GetListOrientation(listView)
2021-11-11 13:23:41 +03:00
rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation)
if rows {
if wrap == ListWrapOff {
2021-11-11 13:23:41 +03:00
buffer.WriteString(` min-width: 100%; height: 100%;`)
} else {
buffer.WriteString(` width: 100%; min-height: 100%;`)
}
} else {
if wrap == ListWrapOff {
2021-11-11 13:23:41 +03:00
buffer.WriteString(` width: 100%; min-height: 100%;`)
} else {
buffer.WriteString(` min-width: 100%; height: 100%;`)
}
}
buffer.WriteString(` flex-flow: `)
buffer.WriteString(enumProperties[Orientation].cssValues[orientation])
switch wrap {
case ListWrapOn:
2021-11-11 13:23:41 +03:00
buffer.WriteString(` wrap;`)
case ListWrapReverse:
2021-11-11 13:23:41 +03:00
buffer.WriteString(` wrap-reverse;`)
default:
buffer.WriteString(`;`)
}
var hAlignTag, vAlignTag string
if rows {
hAlignTag = `justify-content`
vAlignTag = `align-items`
} else {
hAlignTag = `align-items`
vAlignTag = `justify-content`
}
value := ""
switch GetListHorizontalAlign(listView) {
2022-07-28 12:41:50 +03:00
case LeftAlign:
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
value = `flex-end`
} else {
value = `flex-start`
}
case RightAlign:
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
value = `flex-start`
} else {
value = `flex-end`
}
case CenterAlign:
value = `center`
2021-11-11 13:23:41 +03:00
2022-07-28 12:41:50 +03:00
case StretchAlign:
if rows {
value = `space-between`
} else {
value = `stretch`
2021-11-11 13:23:41 +03:00
}
}
if value != "" {
buffer.WriteRune(' ')
buffer.WriteString(hAlignTag)
buffer.WriteString(`: `)
buffer.WriteString(value)
buffer.WriteRune(';')
}
value = ""
switch GetListVerticalAlign(listView) {
2022-07-28 12:41:50 +03:00
case TopAlign:
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
value = `flex-end`
} else {
value = `flex-start`
}
case BottomAlign:
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
value = `flex-start`
} else {
value = `flex-end`
}
case CenterAlign:
value = `center`
2021-11-11 13:23:41 +03:00
2022-07-28 12:41:50 +03:00
case StretchAlign:
if rows {
value = `stretch`
} else {
value = `space-between`
2021-11-11 13:23:41 +03:00
}
}
if value != "" {
buffer.WriteRune(' ')
buffer.WriteString(vAlignTag)
buffer.WriteString(`: `)
buffer.WriteString(value)
buffer.WriteRune(';')
}
buffer.WriteString(`">`)
checkbox := GetListViewCheckbox(listView)
2021-09-07 17:36:50 +03:00
if checkbox == NoneCheckbox {
2024-11-13 12:56:39 +03:00
listView.noneCheckboxSubviews(adapter, buffer)
2021-09-07 17:36:50 +03:00
} else {
2024-11-13 12:56:39 +03:00
listView.checkboxSubviews(adapter, buffer, checkbox)
2021-09-07 17:36:50 +03:00
}
2021-11-11 13:23:41 +03:00
buffer.WriteString(`</div>`)
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func (listView *listViewData) handleCommand(self View, command PropertyName, data DataObject) bool {
2021-09-07 17:36:50 +03:00
switch command {
case "itemSelected":
if number, ok := dataIntProperty(data, `number`); ok {
2024-11-13 12:56:39 +03:00
listView.handleCurrent(number)
2021-09-07 17:36:50 +03:00
}
case "itemUnselected":
if _, ok := listView.properties[Current]; ok {
2024-11-13 12:56:39 +03:00
listView.handleCurrent(-1)
2021-09-07 17:36:50 +03:00
}
case "itemClick":
if number, ok := dataIntProperty(data, `number`); ok {
listView.onItemClick(number)
}
2021-09-07 17:36:50 +03:00
default:
return listView.viewData.handleCommand(self, command, data)
}
return true
}
2024-11-13 12:56:39 +03:00
func (listView *listViewData) handleCurrent(number int) {
listView.properties[Current] = number
for _, listener := range getOneArgEventListeners[ListView, int](listView, nil, ListItemSelectedEvent) {
2024-11-13 12:56:39 +03:00
listener(listView, number)
}
if listener, ok := listView.changeListener[Current]; ok {
listener(listView, Current)
}
}
func (listView *listViewData) onItemClick(number int) {
if IsDisabled(listView) {
2024-11-13 12:56:39 +03:00
return
}
if current := GetCurrent(listView); current != number {
listView.Set(Current, number)
}
if checkbox := GetListViewCheckbox(listView); checkbox != NoneCheckbox {
2024-11-13 12:56:39 +03:00
checkedItem := GetListViewCheckedItems(listView)
2021-09-07 17:36:50 +03:00
switch checkbox {
case SingleCheckbox:
2024-11-13 12:56:39 +03:00
if len(checkedItem) == 0 {
checkedItem = []int{number}
listView.updateCheckboxItem(number, true)
} else if checkedItem[0] != number {
2024-11-13 12:56:39 +03:00
listView.updateCheckboxItem(checkedItem[0], false)
checkedItem = []int{number}
listView.updateCheckboxItem(number, true)
2024-11-13 12:56:39 +03:00
} else {
checkedItem = []int{}
listView.updateCheckboxItem(number, false)
2021-09-07 17:36:50 +03:00
}
case MultipleCheckbox:
2024-11-13 12:56:39 +03:00
uncheck := false
for i, index := range checkedItem {
if index == number {
2024-11-13 12:56:39 +03:00
uncheck = true
2021-09-07 17:36:50 +03:00
listView.updateCheckboxItem(index, false)
2024-11-13 12:56:39 +03:00
count := len(checkedItem)
2021-09-07 17:36:50 +03:00
if count == 1 {
2024-11-13 12:56:39 +03:00
checkedItem = []int{}
2021-09-07 17:36:50 +03:00
} else if i == 0 {
2024-11-13 12:56:39 +03:00
checkedItem = checkedItem[1:]
2021-09-07 17:36:50 +03:00
} else if i == count-1 {
2024-11-13 12:56:39 +03:00
checkedItem = checkedItem[:i]
2021-09-07 17:36:50 +03:00
} else {
2024-11-13 12:56:39 +03:00
checkedItem = append(checkedItem[:i], checkedItem[i+1:]...)
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
break
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
if !uncheck {
listView.updateCheckboxItem(number, true)
checkedItem = append(checkedItem, number)
2024-11-13 12:56:39 +03:00
}
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
setArrayPropertyValue(listView, Checked, checkedItem)
if listener, ok := listView.changeListener[Checked]; ok {
listener(listView, Checked)
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
for _, listener := range getOneArgEventListeners[ListView, []int](listView, nil, ListItemCheckedEvent) {
2024-11-13 12:56:39 +03:00
listener(listView, checkedItem)
2021-09-07 17:36:50 +03:00
}
}
for _, listener := range getOneArgEventListeners[ListView, int](listView, nil, ListItemClickedEvent) {
listener(listView, number)
}
2021-09-07 17:36:50 +03:00
}
func (listView *listViewData) onItemResize(self View, index string, x, y, width, height float64) {
n, err := strconv.Atoi(index)
if err != nil {
ErrorLog(err.Error())
} else if n >= 0 && n < len(listView.itemFrame) {
listView.itemFrame[n] = Frame{Left: x, Top: y, Width: width, Height: height}
} else {
ErrorLogF(`Invalid ListView item index: %d`, n)
2021-09-07 17:36:50 +03:00
}
}
// GetVerticalAlign return the vertical align of a list: TopAlign (0), BottomAlign (1), CenterAlign (2), StretchAlign (3)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetVerticalAlign(view View, subviewID ...string) int {
2022-08-24 15:00:25 +03:00
return enumStyledProperty(view, subviewID, VerticalAlign, TopAlign, false)
2021-09-07 17:36:50 +03:00
}
2022-08-24 15:00:25 +03:00
// GetHorizontalAlign return the vertical align of a list/checkbox: LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetHorizontalAlign(view View, subviewID ...string) int {
2022-08-24 15:00:25 +03:00
return enumStyledProperty(view, subviewID, HorizontalAlign, LeftAlign, false)
2021-09-07 17:36:50 +03:00
}
// GetListItemClickedListeners returns a ListItemClickedListener of the ListView.
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListItemClickedListeners(view View, subviewID ...string) []func(ListView, int) {
return getOneArgEventListeners[ListView, int](view, subviewID, ListItemClickedEvent)
2021-09-07 17:36:50 +03:00
}
// GetListItemSelectedListeners returns a ListItemSelectedListener of the ListView.
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListItemSelectedListeners(view View, subviewID ...string) []func(ListView, int) {
return getOneArgEventListeners[ListView, int](view, subviewID, ListItemSelectedEvent)
2021-09-07 17:36:50 +03:00
}
// GetListItemCheckedListeners returns a ListItemCheckedListener of the ListView.
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListItemCheckedListeners(view View, subviewID ...string) []func(ListView, []int) {
return getOneArgEventListeners[ListView, []int](view, subviewID, ListItemCheckedEvent)
2021-09-07 17:36:50 +03:00
}
// GetListItemWidth returns the width of a ListView item.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListItemWidth(view View, subviewID ...string) SizeUnit {
return sizeStyledProperty(view, subviewID, ItemWidth, false)
2021-09-07 17:36:50 +03:00
}
// GetListItemHeight returns the height of a ListView item.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListItemHeight(view View, subviewID ...string) SizeUnit {
return sizeStyledProperty(view, subviewID, ItemHeight, false)
2021-09-07 17:36:50 +03:00
}
// GetListViewCheckbox returns the ListView checkbox type: NoneCheckbox (0), SingleCheckbox (1), or MultipleCheckbox (2).
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListViewCheckbox(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, ItemCheckbox, 0, false)
2021-09-07 17:36:50 +03:00
}
// GetListViewCheckedItems returns the array of ListView checked items.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListViewCheckedItems(view View, subviewID ...string) []int {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])
2021-09-07 17:36:50 +03:00
}
2021-09-07 17:36:50 +03:00
if view != nil {
2024-11-13 12:56:39 +03:00
if value := view.getRaw(Checked); value != nil {
if checkedItems, ok := value.([]int); ok {
switch GetListViewCheckbox(view) {
case MultipleCheckbox:
return checkedItems
case SingleCheckbox:
if len(checkedItems) > 1 {
return []int{checkedItems[0]}
}
2021-09-07 17:36:50 +03:00
}
}
}
}
return []int{}
}
// IsListViewCheckedItem returns true if the ListView item with index is checked, false otherwise.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func IsListViewCheckedItem(view View, subviewID string, index int) bool {
for _, n := range GetListViewCheckedItems(view, subviewID) {
if n == index {
return true
}
}
return false
}
// GetListViewCheckboxVerticalAlign returns the vertical align of the ListView checkbox:
// TopAlign (0), BottomAlign (1), CenterAlign (2)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListViewCheckboxVerticalAlign(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, CheckboxVerticalAlign, TopAlign, false)
2021-09-07 17:36:50 +03:00
}
// GetListViewCheckboxHorizontalAlign returns the horizontal align of the ListView checkbox:
// LeftAlign (0), RightAlign (1), CenterAlign (2)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListViewCheckboxHorizontalAlign(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, CheckboxHorizontalAlign, LeftAlign, false)
2021-09-07 17:36:50 +03:00
}
// GetListItemVerticalAlign returns the vertical align of the ListView item content:
// TopAlign (0), BottomAlign (1), CenterAlign (2)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListItemVerticalAlign(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, ItemVerticalAlign, TopAlign, false)
2021-09-07 17:36:50 +03:00
}
// ItemHorizontalAlign returns the horizontal align of the ListView item content:
// LeftAlign (0), RightAlign (1), CenterAlign (2), StretchAlign (3)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListItemHorizontalAlign(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, ItemHorizontalAlign, LeftAlign, false)
2021-09-07 17:36:50 +03:00
}
// GetListItemFrame - returns the location and size of the ListView item in pixels.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
2021-09-07 17:36:50 +03:00
func GetListItemFrame(view View, subviewID string, index int) Frame {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if listView, ok := view.(ListView); ok {
itemFrames := listView.getItemFrames()
if index >= 0 && index < len(itemFrames) {
return itemFrames[index]
}
}
}
return Frame{Left: 0, Top: 0, Width: 0, Height: 0}
}
// GetListViewAdapter - returns the ListView adapter.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetListViewAdapter(view View, subviewID ...string) ListAdapter {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])
2021-09-07 17:36:50 +03:00
}
if view != nil {
if value := view.Get(Items); value != nil {
if adapter, ok := value.(ListAdapter); ok {
return adapter
}
}
}
return nil
}
// ReloadListViewData updates ListView content
// If the second argument (subviewID) is not specified or it is "" then content the first argument (view) is updated.
func ReloadListViewData(view View, subviewID ...string) {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])
2021-09-07 17:36:50 +03:00
}
2021-09-07 17:36:50 +03:00
if view != nil {
if listView, ok := view.(ListView); ok {
listView.ReloadListViewData()
}
}
}