mirror of https://github.com/anoshenko/rui.git
				
				
				
			Added "list-row-gap" and "list-column-gap" properties
This commit is contained in:
		
							parent
							
								
									379d98fe4a
								
							
						
					
					
						commit
						6dad96c2a7
					
				|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										12
									
								
								README-ru.md
								
								
								
								
							
							
						
						
									
										12
									
								
								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). Основным значением | ||||
|  |  | |||
							
								
								
									
										12
									
								
								README.md
								
								
								
								
							
							
						
						
									
										12
									
								
								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).  | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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) | ||||
| } | ||||
|  |  | |||
							
								
								
									
										33
									
								
								listView.go
								
								
								
								
							
							
						
						
									
										33
									
								
								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(`<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) | ||||
|  |  | |||
|  | @ -103,19 +103,22 @@ func ShowCancellableQuestion(title, text string, session Session, onYes func(), | |||
| } | ||||
| 
 | ||||
| type popupMenuData struct { | ||||
| 	items   []string | ||||
| 	session Session | ||||
| 	popup   Popup | ||||
| 	result  func(int) | ||||
| 	items    []string | ||||
| 	disabled []int | ||||
| 	session  Session | ||||
| 	popup    Popup | ||||
| 	result   func(int) | ||||
| } | ||||
| 
 | ||||
| func (popup *popupMenuData) itemClick(list ListView, n int) { | ||||
| 	if popup.popup != nil { | ||||
| 		popup.popup.Dismiss() | ||||
| 		popup.popup = nil | ||||
| 	} | ||||
| 	if popup.result != nil { | ||||
| 		popup.result(n) | ||||
| 	if popup.IsListItemEnabled(n) { | ||||
| 		if popup.popup != nil { | ||||
| 			popup.popup.Dismiss() | ||||
| 			popup.popup = nil | ||||
| 		} | ||||
| 		if popup.result != nil { | ||||
| 			popup.result(n) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -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: | ||||
|  |  | |||
|  | @ -568,9 +568,19 @@ const ( | |||
| 	// Orientation is the constant for the "orientation" property tag.
 | ||||
| 	Orientation = "orientation" | ||||
| 
 | ||||
| 	// Gap is the constant for the "gap" property tag.
 | ||||
| 	// 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" | ||||
| 
 | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue