diff --git a/CHANGELOG.md b/CHANGELOG.md index 0181114..1912ce0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,11 @@ * Requires go 1.18 or higher * The "interface{}" type replaced by "any" -* Added "accent-color", "tab-size", "overflow", "arrow", "arrow-align", "arrow-size", "arrow-width", and "arrow-offset" properties +* Added "list-row-gap", "list-column-gap", "accent-color", "tab-size", "overflow", +"arrow", "arrow-align", "arrow-size", "arrow-width", and "arrow-offset" properties * Added "@ruiArrowSize" and "@ruiArrowWidth" constants to the default theme * Added Transition, Transitions, and SetTransition functions to the ViewStyle interface -* Added GetAccentColor, GetTabSize, GetOverflow, IsTimingFunctionValid, and GetTransitions functions +* Added GetListRowGap, GetListColumnGap, GetAccentColor, GetTabSize, GetOverflow, IsTimingFunctionValid, and GetTransitions functions * Changed GetTransition functions * Added the OpenURL function to the Session interface diff --git a/README-ru.md b/README-ru.md index f6335e1..6b87ffb 100644 --- a/README-ru.md +++ b/README-ru.md @@ -30,7 +30,7 @@ В функции main вызывается функция StartApp. Она создает rui приложение и запускает его основной цикл. Функция StartApp имеет 3 параметра: 1) IP адрес по которому будет доступно приложение (в нашем примере это "localhost:8000") -2) Фуекция создает структуру реализующую интерфейс SessionContent +2) Функция создает структуру реализующую интерфейс SessionContent 3) Дополнительные опциональные параметры (в нашем примере это заголовок и имя файла иконки) Интерфейс SessionContent объявлен как: @@ -2205,6 +2205,11 @@ ListLayout является контейнером, реализующим ин | 2 | CenterAlign | "center" | Выравнивание по центру | | 3 | StretchAlign | "stretch" | Выравнивание по ширине | +### "list-row-gap" и "list-column-gap" + +Свойства "list-row-gap" и "list-column-gap" (константы ListRowGap и ListColumnGap) типа SizeUnit позволяют +установить соответственно расстояния между строками и столбцами контейнера. Значение по умолчанию 0. + ## GridLayout GridLayout является контейнером, реализующим интерфейс ViewsContainer. Для его создания используется функция @@ -3226,6 +3231,11 @@ int8…int64, uint, uint8…uint64 func NewListView(session Session, params Params) ListView +ListView реализован на основе ListLayout и поэтому он поддерживает все свойства ListLayout: +"orientation", "list-wrap", "vertical-align", "horizontal-align", "list-row-gap" и "list-column-gap". + +Помимо эти свойств ListView имеет ещё следующие: + ### Свойство "items" Элементы списка задаются с помощью свойства "items" (константа Items). Основным значением diff --git a/README.md b/README.md index 173ed91..caa8057 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[Russian](https://github.com/anoshenko/rui/blob/main/README-ru.md) + # RUI library The RUI (Remote User Interface) library is designed to create web applications in the go language. @@ -2183,6 +2185,11 @@ alignment of items in the list. Valid values: | 2 | CenterAlign | "center" | Center alignment | | 3 | StretchAlign | "stretch" | Width alignment | +### "list-row-gap" and "list-column-gap" properties + +The "list-row-gap" and "list-column-gap" SizeUnit properties (ListRowGap and ListColumnGap constants) +allow you to set the distance between the rows and columns of the container, respectively. The default is 0px. + ## GridLayout GridLayout is a container that implements the ViewsContainer interface. To create it, use the function @@ -3193,6 +3200,11 @@ The ListView is created using the function: func NewListView(session Session, params Params) ListView +ListView is implemented on top of ListLayout and therefore supports all ListLayout properties: +"orientation", "list-wrap", "vertical-align", "horizontal-align", "list-row-gap", and "list-column-gap". + +In addition to these properties ListView has the following: + ### The "items" property List items are set using the "items" property (Items constant). diff --git a/gridLayout.go b/gridLayout.go index 9b9c577..4c8e443 100644 --- a/gridLayout.go +++ b/gridLayout.go @@ -250,11 +250,7 @@ func (gridLayout *gridLayoutData) set(tag string, value any) bool { } if tag == Gap { - if gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) { - gridLayout.propertyChangedEvent(Gap) - return true - } - return false + return gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) } if gridLayout.viewsContainerData.set(tag, value) { diff --git a/listLayout.go b/listLayout.go index 0ffa9bc..d1d9cd2 100644 --- a/listLayout.go +++ b/listLayout.go @@ -58,6 +58,12 @@ func (listLayout *listLayoutData) normalizeTag(tag string) string { switch tag { case "wrap": tag = ListWrap + + case "row-gap": + return ListRowGap + + case ColumnGap: + return ListColumnGap } return tag } @@ -66,11 +72,27 @@ func (listLayout *listLayoutData) Get(tag string) any { return listLayout.get(listLayout.normalizeTag(tag)) } +func (listLayout *listLayoutData) get(tag string) any { + if tag == Gap { + if rowGap := GetListRowGap(listLayout, ""); rowGap.Equal(GetListColumnGap(listLayout, "")) { + return rowGap + } + return AutoSize() + } + + return listLayout.viewsContainerData.get(tag) +} + func (listLayout *listLayoutData) Remove(tag string) { listLayout.remove(listLayout.normalizeTag(tag)) } func (listLayout *listLayoutData) remove(tag string) { + if tag == Gap { + listLayout.remove(ListRowGap) + listLayout.remove(ListColumnGap) + return + } listLayout.viewsContainerData.remove(tag) if listLayout.created { switch tag { @@ -90,6 +112,10 @@ func (listLayout *listLayoutData) set(tag string, value any) bool { return true } + if tag == Gap { + return listLayout.set(ListRowGap, value) && listLayout.set(ListColumnGap, value) + } + if listLayout.viewsContainerData.set(tag, value) { if listLayout.created { switch tag { @@ -168,3 +194,15 @@ func GetListOrientation(view View, subviewID string) int { func GetListWrap(view View, subviewID string) int { return enumStyledProperty(view, subviewID, ListWrap, ListWrapOff, false) } + +// GetListRowGap returns the gap between ListLayout or ListView rows. +// If the second argument (subviewID) is "" then a value from the first argument (view) is returned. +func GetListRowGap(view View, subviewID string) SizeUnit { + return sizeStyledProperty(view, subviewID, ListRowGap, false) +} + +// GetListColumnGap returns the gap between ListLayout or ListView columns. +// If the second argument (subviewID) is "" then a value from the first argument (view) is returned. +func GetListColumnGap(view View, subviewID string) SizeUnit { + return sizeStyledProperty(view, subviewID, ListColumnGap, false) +} diff --git a/listView.go b/listView.go index 66e6652..f588bd1 100644 --- a/listView.go +++ b/listView.go @@ -110,6 +110,12 @@ func (listView *listViewData) normalizeTag(tag string) string { case "wrap": tag = ListWrap + + case "row-gap": + return ListRowGap + + case ColumnGap: + return ListColumnGap } return tag } @@ -120,6 +126,10 @@ func (listView *listViewData) Remove(tag string) { func (listView *listViewData) remove(tag string) { switch tag { + case Gap: + listView.remove(ListRowGap) + listView.remove(ListColumnGap) + case Checked: if len(listView.checkedItem) > 0 { listView.checkedItem = []int{} @@ -204,6 +214,9 @@ func (listView *listViewData) set(tag string, value any) bool { } switch tag { + case Gap: + return listView.set(ListRowGap, value) && listView.set(ListColumnGap, value) + case ListItemClickedEvent: listeners, ok := valueToEventListeners[ListView, int](value) if !ok { @@ -264,7 +277,7 @@ func (listView *listViewData) set(tag string, value any) bool { listener(listView, current) } - case Orientation, ListWrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight: + case Orientation, ListWrap, ListRowGap, ListColumnGap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight: result := listView.viewData.set(tag, value) if result && listView.created { updateInnerHTML(listView.htmlID(), listView.session) @@ -303,6 +316,12 @@ func (listView *listViewData) Get(tag string) any { func (listView *listViewData) get(tag string) any { switch tag { + case Gap: + if rowGap := GetListRowGap(listView, ""); rowGap.Equal(GetListColumnGap(listView, "")) { + return rowGap + } + return AutoSize() + case ListItemClickedEvent: return listView.clickedListeners @@ -875,6 +894,18 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) { buffer.WriteString(`