forked from mbk-lab/rui_orig
2
0
Fork 0

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 * Requires go 1.18 or higher
* The "interface{}" type replaced by "any" * 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 "@ruiArrowSize" and "@ruiArrowWidth" constants to the default theme
* Added Transition, Transitions, and SetTransition functions to the ViewStyle interface * 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 * Changed GetTransition functions
* Added the OpenURL function to the Session interface * Added the OpenURL function to the Session interface

View File

@ -30,7 +30,7 @@
В функции main вызывается функция StartApp. Она создает rui приложение и запускает его основной цикл. В функции main вызывается функция StartApp. Она создает rui приложение и запускает его основной цикл.
Функция StartApp имеет 3 параметра: Функция StartApp имеет 3 параметра:
1) IP адрес по которому будет доступно приложение (в нашем примере это "localhost:8000") 1) IP адрес по которому будет доступно приложение (в нашем примере это "localhost:8000")
2) Фуекция создает структуру реализующую интерфейс SessionContent 2) Функция создает структуру реализующую интерфейс SessionContent
3) Дополнительные опциональные параметры (в нашем примере это заголовок и имя файла иконки) 3) Дополнительные опциональные параметры (в нашем примере это заголовок и имя файла иконки)
Интерфейс SessionContent объявлен как: Интерфейс SessionContent объявлен как:
@ -2205,6 +2205,11 @@ ListLayout является контейнером, реализующим ин
| 2 | CenterAlign | "center" | Выравнивание по центру | | 2 | CenterAlign | "center" | Выравнивание по центру |
| 3 | StretchAlign | "stretch" | Выравнивание по ширине | | 3 | StretchAlign | "stretch" | Выравнивание по ширине |
### "list-row-gap" и "list-column-gap"
Свойства "list-row-gap" и "list-column-gap" (константы ListRowGap и ListColumnGap) типа SizeUnit позволяют
установить соответственно расстояния между строками и столбцами контейнера. Значение по умолчанию 0.
## GridLayout ## GridLayout
GridLayout является контейнером, реализующим интерфейс ViewsContainer. Для его создания используется функция GridLayout является контейнером, реализующим интерфейс ViewsContainer. Для его создания используется функция
@ -3226,6 +3231,11 @@ int8…int64, uint, uint8…uint64
func NewListView(session Session, params Params) ListView 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" (константа Items). Основным значением Элементы списка задаются с помощью свойства "items" (константа Items). Основным значением

View File

@ -1,3 +1,5 @@
[Russian](https://github.com/anoshenko/rui/blob/main/README-ru.md)
# RUI library # RUI library
The RUI (Remote User Interface) library is designed to create web applications in the go language. 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 | | 2 | CenterAlign | "center" | Center alignment |
| 3 | StretchAlign | "stretch" | Width 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
GridLayout is a container that implements the ViewsContainer interface. To create it, use the function 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 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 ### The "items" property
List items are set using the "items" property (Items constant). 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 tag == Gap {
if gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) { return 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) {

View File

@ -58,6 +58,12 @@ func (listLayout *listLayoutData) normalizeTag(tag string) string {
switch tag { switch tag {
case "wrap": case "wrap":
tag = ListWrap tag = ListWrap
case "row-gap":
return ListRowGap
case ColumnGap:
return ListColumnGap
} }
return tag return tag
} }
@ -66,11 +72,27 @@ func (listLayout *listLayoutData) Get(tag string) any {
return listLayout.get(listLayout.normalizeTag(tag)) 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) { func (listLayout *listLayoutData) Remove(tag string) {
listLayout.remove(listLayout.normalizeTag(tag)) listLayout.remove(listLayout.normalizeTag(tag))
} }
func (listLayout *listLayoutData) remove(tag string) { func (listLayout *listLayoutData) remove(tag string) {
if tag == Gap {
listLayout.remove(ListRowGap)
listLayout.remove(ListColumnGap)
return
}
listLayout.viewsContainerData.remove(tag) listLayout.viewsContainerData.remove(tag)
if listLayout.created { if listLayout.created {
switch tag { switch tag {
@ -90,6 +112,10 @@ func (listLayout *listLayoutData) set(tag string, value any) bool {
return true return true
} }
if tag == Gap {
return listLayout.set(ListRowGap, value) && listLayout.set(ListColumnGap, value)
}
if listLayout.viewsContainerData.set(tag, value) { if listLayout.viewsContainerData.set(tag, value) {
if listLayout.created { if listLayout.created {
switch tag { switch tag {
@ -168,3 +194,15 @@ func GetListOrientation(view View, subviewID string) int {
func GetListWrap(view View, subviewID string) int { func GetListWrap(view View, subviewID string) int {
return enumStyledProperty(view, subviewID, ListWrap, ListWrapOff, false) 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": case "wrap":
tag = ListWrap tag = ListWrap
case "row-gap":
return ListRowGap
case ColumnGap:
return ListColumnGap
} }
return tag return tag
} }
@ -120,6 +126,10 @@ func (listView *listViewData) Remove(tag string) {
func (listView *listViewData) remove(tag string) { func (listView *listViewData) remove(tag string) {
switch tag { switch tag {
case Gap:
listView.remove(ListRowGap)
listView.remove(ListColumnGap)
case Checked: case Checked:
if len(listView.checkedItem) > 0 { if len(listView.checkedItem) > 0 {
listView.checkedItem = []int{} listView.checkedItem = []int{}
@ -204,6 +214,9 @@ func (listView *listViewData) set(tag string, value any) bool {
} }
switch tag { switch tag {
case Gap:
return listView.set(ListRowGap, value) && listView.set(ListColumnGap, value)
case ListItemClickedEvent: case ListItemClickedEvent:
listeners, ok := valueToEventListeners[ListView, int](value) listeners, ok := valueToEventListeners[ListView, int](value)
if !ok { if !ok {
@ -264,7 +277,7 @@ func (listView *listViewData) set(tag string, value any) bool {
listener(listView, current) 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) result := listView.viewData.set(tag, value)
if result && listView.created { if result && listView.created {
updateInnerHTML(listView.htmlID(), listView.session) updateInnerHTML(listView.htmlID(), listView.session)
@ -303,6 +316,12 @@ func (listView *listViewData) Get(tag string) any {
func (listView *listViewData) get(tag string) any { func (listView *listViewData) get(tag string) any {
switch tag { switch tag {
case Gap:
if rowGap := GetListRowGap(listView, ""); rowGap.Equal(GetListColumnGap(listView, "")) {
return rowGap
}
return AutoSize()
case ListItemClickedEvent: case ListItemClickedEvent:
return listView.clickedListeners 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;`) 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, "") wrap := GetListWrap(listView, "")
orientation := GetListOrientation(listView, "") orientation := GetListOrientation(listView, "")
rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation) rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation)

View File

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

View File

@ -568,9 +568,19 @@ const (
// Orientation is the constant for the "orientation" property tag. // Orientation is the constant for the "orientation" property tag.
Orientation = "orientation" Orientation = "orientation"
// Gap is the constant for the "gap" property tag. // Gap is t he constant for the "gap" property tag.
Gap = "gap" 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 is the constant for the "text" property tag.
Text = "text" Text = "text"

View File

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

View File

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