Added "list-row-gap" and "list-column-gap" properties

This commit is contained in:
Alexei Anoshenko 2022-08-31 17:31:17 +03:00
parent 379d98fe4a
commit 6dad96c2a7
10 changed files with 140 additions and 25 deletions

View File

@ -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

View File

@ -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). Основным значением

View File

@ -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).

View File

@ -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) {

View File

@ -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)
}

View File

@ -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(`<div style="display: flex; align-content: stretch;`)
if gap := GetListRowGap(listView, ""); gap.Type != Auto {
buffer.WriteString(` row-gap: `)
buffer.WriteString(gap.cssString("0"))
buffer.WriteRune(';')
}
if gap := GetListColumnGap(listView, ""); gap.Type != Auto {
buffer.WriteString(` column-gap: `)
buffer.WriteString(gap.cssString("0"))
buffer.WriteRune(';')
}
wrap := GetListWrap(listView, "")
orientation := GetListOrientation(listView, "")
rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation)

View File

@ -104,12 +104,14 @@ func ShowCancellableQuestion(title, text string, session Session, onYes func(),
type popupMenuData struct {
items []string
disabled []int
session Session
popup Popup
result func(int)
}
func (popup *popupMenuData) itemClick(list ListView, n int) {
if popup.IsListItemEnabled(n) {
if popup.popup != nil {
popup.popup.Dismiss()
popup.popup = nil
@ -118,6 +120,7 @@ func (popup *popupMenuData) itemClick(list ListView, n int) {
popup.result(n)
}
}
}
func (popup *popupMenuData) ListSize() int {
return len(popup.items)
@ -131,6 +134,13 @@ func (popup *popupMenuData) ListItem(index int, session Session) View {
}
func (popup *popupMenuData) IsListItemEnabled(index int) bool {
if popup.disabled != nil {
for _, n := range popup.disabled {
if index == n {
return false
}
}
}
return true
}
@ -165,13 +175,18 @@ func ShowMenu(session Session, params Params) Popup {
return nil
}
value, ok = params[PopupMenuResult]
if ok && value != nil {
if value, ok := params[PopupMenuResult]; ok && value != nil {
if result, ok := value.(func(int)); ok {
data.result = result
}
}
if value, ok := params[DisabledItems]; ok && value != nil {
if value, ok := value.([]int); ok {
data.disabled = value
}
}
listView := NewListView(session, Params{
Items: adapter,
Orientation: TopDownOrientation,
@ -181,7 +196,7 @@ func ShowMenu(session Session, params Params) Popup {
popupParams := Params{}
for tag, value := range params {
switch tag {
case Items, PopupMenuResult:
case Items, PopupMenuResult, DisabledItems:
// do nothing
default:

View File

@ -571,6 +571,16 @@ const (
// Gap is t he constant for the "gap" property tag.
Gap = "gap"
// ListRowGap is the constant for the "list-row-gap" property tag.
// The "list-row-gap" SizeUnit properties allow to set the distance between the rows of the ListLayout or ListView.
// The default is 0px.
ListRowGap = "list-row-gap"
// ListColumnGap is the constant for the "list-column-gap" property tag.
// The "list-column-gap" SizeUnit properties allow to set the distance between the columns of the GridLayout or ListView.
// The default is 0px.
ListColumnGap = "list-column-gap"
// Text is the constant for the "text" property tag.
Text = "text"

View File

@ -110,6 +110,8 @@ var sizeProperties = map[string]string{
WordSpacing: WordSpacing,
LineHeight: LineHeight,
TextLineThickness: "text-decoration-thickness",
ListRowGap: "row-gap",
ListColumnGap: "column-gap",
GridRowGap: GridRowGap,
GridColumnGap: GridColumnGap,
ColumnWidth: ColumnWidth,

View File

@ -208,7 +208,7 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
for _, tag := range []string{
Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight, Left, Right, Top, Bottom,
TextSize, TextIndent, LetterSpacing, WordSpacing, LineHeight, TextLineThickness,
GridRowGap, GridColumnGap, ColumnGap, ColumnWidth} {
ListRowGap, ListColumnGap, GridRowGap, GridColumnGap, ColumnGap, ColumnWidth} {
if size, ok := sizeProperty(style, tag, session); ok && size.Type != Auto {
cssTag, ok := sizeProperties[tag]
@ -799,7 +799,7 @@ func writeViewStyle(name string, view ViewStyle, buffer *strings.Builder, indent
Opacity, ZIndex, Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight,
Margin, Padding, BackgroundClip, BackgroundColor, Background, Border, Radius, Outline, Shadow,
Orientation, ListWrap, VerticalAlign, HorizontalAlign, CellWidth, CellHeight,
CellVerticalAlign, CellHorizontalAlign, GridRowGap, GridColumnGap,
CellVerticalAlign, CellHorizontalAlign, ListRowGap, ListColumnGap, GridRowGap, GridColumnGap,
ColumnCount, ColumnWidth, ColumnSeparator, ColumnGap, AvoidBreak,
Current, Expanded, Side, ResizeBorderWidth, EditViewType, MaxLength, Hint, Text, EditWrap,
TextOverflow, FontName, TextSize, TextColor, TextWeight, Italic, SmallCaps,