mirror of https://github.com/anoshenko/rui.git
Added GridAdapter
This commit is contained in:
parent
f9d7c77500
commit
d0d81907eb
|
@ -1,6 +1,7 @@
|
||||||
# v0.16.0
|
# v0.16.0
|
||||||
* Can use ListAdapter as "content" property value of ListLayout
|
* Can use ListAdapter as "content" property value of ListLayout
|
||||||
* The IsListItemEnabled method of the ListAdapter interface has been made optional
|
* The IsListItemEnabled method of the ListAdapter interface has been made optional
|
||||||
|
* Can use GridAdapter as "content" property value of GridLayout
|
||||||
* Bug fixing
|
* Bug fixing
|
||||||
|
|
||||||
# v0.15.0
|
# v0.15.0
|
||||||
|
|
48
README-ru.md
48
README-ru.md
|
@ -2344,13 +2344,13 @@ ListAdapter используется для создания дочерних Vi
|
||||||
Соответственно функции этого интерфейса должны возвращать количество элементов и View i-го элемента.
|
Соответственно функции этого интерфейса должны возвращать количество элементов и View i-го элемента.
|
||||||
|
|
||||||
ListAdapter создает дочерние View в момент установки свойства "content".
|
ListAdapter создает дочерние View в момент установки свойства "content".
|
||||||
Для пересоздания дочерних элементов ListLayout имеет свойство UpdateContent().
|
Для пересоздания дочерних элементов ListLayout имеет метод UpdateContent().
|
||||||
Данный метод удаляет все дочерние View и создает их заново используя ListAdapter.
|
Данный метод удаляет все дочерние View и создает их заново используя ListAdapter.
|
||||||
|
|
||||||
Внимание! При вызове метода UpdateContent() данные из старых View не переносятся в заново создаваемые.
|
Внимание! При вызове метода UpdateContent() данные из старых View не переносятся в заново создаваемые.
|
||||||
Вы должны сделать это в ручную.
|
Вы должны сделать это в ручную.
|
||||||
|
|
||||||
Если свойство "content" присвоен не ListAdapter, то метод UpdateContent() ничего не делает.
|
Если свойству "content" присвоен не ListAdapter, то метод UpdateContent() ничего не делает.
|
||||||
|
|
||||||
Вызвать метод UpdateContent можно также с помощью глобальной функции
|
Вызвать метод UpdateContent можно также с помощью глобальной функции
|
||||||
|
|
||||||
|
@ -2435,6 +2435,50 @@ GridLayout является контейнером, реализующим ин
|
||||||
Все дочерние элементы располагаются в ячейках таблицы. Ячейка адресуется по номеру строки и
|
Все дочерние элементы располагаются в ячейках таблицы. Ячейка адресуется по номеру строки и
|
||||||
столбца. Номера строк и столбцов начинаются с 0.
|
столбца. Номера строк и столбцов начинаются с 0.
|
||||||
|
|
||||||
|
### "content"
|
||||||
|
|
||||||
|
Свойство "content" (константа Content) определяет массив дочерних View.
|
||||||
|
Данное свойство унаследовано от ViewsContainer.
|
||||||
|
Также как и для ViewsContainer данному свойству можно присваивать следующие типы данных:
|
||||||
|
|
||||||
|
* View (преобразуется во []View содержащий один View);
|
||||||
|
* []View;
|
||||||
|
* string (преобразуется во []View содержащий один TextView);
|
||||||
|
* []string (преобразуется во []View содержащий TextView);
|
||||||
|
* []any - данный массив должен содержать только View и string (преобразуется в TextView).
|
||||||
|
|
||||||
|
Однако кроме этих типов данных свойству "content" GridLayout может быть назначена реализация интерфейса GridAdapter.
|
||||||
|
|
||||||
|
GridAdapter используется для создания дочерних View и объявлен как
|
||||||
|
|
||||||
|
type GridAdapter interface {
|
||||||
|
GridColumnCount() int
|
||||||
|
GridRowCount() int
|
||||||
|
GridCellContent(row, column int, session Session) View
|
||||||
|
}
|
||||||
|
|
||||||
|
Соответственно функции этого интерфейса должны возвращать количество столбцов и строк и View элемента в позиции (row, column).
|
||||||
|
|
||||||
|
Кроме этих трех обязательных методов, при реализации GridAdapter, могут быть заданы еще два опциональных:
|
||||||
|
|
||||||
|
GridCellColumnSpan(row, column int) int
|
||||||
|
GridCellRowSpan(row, column int) int
|
||||||
|
|
||||||
|
Первый метод задает сколько столбцов занимает View в позиции (row, column) а вторая - сколько строк.
|
||||||
|
|
||||||
|
GridAdapter создает дочерние View в момент установки свойства "content".
|
||||||
|
Для пересоздания дочерних элементов GridLayout имеет метод UpdateGridContent().
|
||||||
|
Данный метод удаляет все дочерние View и создает их заново используя GridAdapter.
|
||||||
|
|
||||||
|
Внимание! При вызове метода UpdateGridContent() данные из старых View не переносятся в заново создаваемые.
|
||||||
|
Вы должны сделать это в ручную.
|
||||||
|
|
||||||
|
Если свойству "content" присвоен не GridAdapter, то метод UpdateGridContent() ничего не делает.
|
||||||
|
|
||||||
|
Вызвать метод UpdateGridContent можно также с помощью глобальной функции
|
||||||
|
|
||||||
|
func UpdateContent(view View, subviewID ...string)
|
||||||
|
|
||||||
### "column" и "row"
|
### "column" и "row"
|
||||||
|
|
||||||
Расположение View внутри GridLayout определяется с помощью свойств "column" и "row".
|
Расположение View внутри GridLayout определяется с помощью свойств "column" и "row".
|
||||||
|
|
45
README.md
45
README.md
|
@ -2410,6 +2410,51 @@ The container space of this container is split into cells in the form of a table
|
||||||
All children are located in the cells of the table. A cell is addressed by row and column number.
|
All children are located in the cells of the table. A cell is addressed by row and column number.
|
||||||
Row and column numbers start at 0.
|
Row and column numbers start at 0.
|
||||||
|
|
||||||
|
### "content"
|
||||||
|
|
||||||
|
The "content" property (Content constant) defines an array of child Views.
|
||||||
|
This property is inherited from ViewsContainer.
|
||||||
|
Just like for ViewsContainer, this property can be assigned the following data types:
|
||||||
|
|
||||||
|
* View (converts to []View containing one View);
|
||||||
|
* []View;
|
||||||
|
* string (converts to []View containing one TextView);
|
||||||
|
* []string (converts to []View containing TextView);
|
||||||
|
* []any - this array must contain only View and string.
|
||||||
|
|
||||||
|
However, in addition to these data types, the "content" property of a GridLayout
|
||||||
|
can be assigned an implementation of the GridAdapter interface.
|
||||||
|
|
||||||
|
GridAdapter is used to create child Views and is declared as
|
||||||
|
|
||||||
|
type GridAdapter interface {
|
||||||
|
GridColumnCount() int
|
||||||
|
GridRowCount() int
|
||||||
|
GridCellContent(row, column int, session Session) View
|
||||||
|
}
|
||||||
|
|
||||||
|
Accordingly, the functions of this interface must return the number of columns and rows and the View of the element at position (row, column).
|
||||||
|
|
||||||
|
In addition to these three required methods, when implementing a GridAdapter, two more optional ones can be specified:
|
||||||
|
|
||||||
|
GridCellColumnSpan(row, column int) int
|
||||||
|
GridCellRowSpan(row, column int) int
|
||||||
|
|
||||||
|
The first method sets how many columns the View occupies in (row, column) position and the second sets how many rows.
|
||||||
|
|
||||||
|
GridAdapter creates child Views when the "content" property is set.
|
||||||
|
To recreate child elements, GridLayout has the UpdateGridContent() method.
|
||||||
|
This method deletes all child Views and creates them again using the GridAdapter.
|
||||||
|
|
||||||
|
Attention! When calling the UpdateGridContent() method, data from old Views is not transferred to newly created ones.
|
||||||
|
You must do this manually.
|
||||||
|
|
||||||
|
If the "content" property is not set to a GridAdapter then the UpdateGridContent() method does nothing.
|
||||||
|
|
||||||
|
You can also call the UpdateGridContent method using the global function
|
||||||
|
|
||||||
|
func UpdateContent(view View, subviewID ...string)
|
||||||
|
|
||||||
### "column" and "row" properties
|
### "column" and "row" properties
|
||||||
|
|
||||||
The location of the View inside the GridLayout is determined using the "column" and "row" properties.
|
The location of the View inside the GridLayout is determined using the "column" and "row" properties.
|
||||||
|
|
113
gridLayout.go
113
gridLayout.go
|
@ -43,13 +43,43 @@ const (
|
||||||
CellHorizontalSelfAlign = "cell-horizontal-self-align"
|
CellHorizontalSelfAlign = "cell-horizontal-self-align"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type GridAdapter interface {
|
||||||
|
// GridColumnCount returns the number of columns in the grid
|
||||||
|
GridColumnCount() int
|
||||||
|
|
||||||
|
// GridRowCount returns the number of rows in the grid
|
||||||
|
GridRowCount() int
|
||||||
|
|
||||||
|
// GridCellContent creates a View at the given cell
|
||||||
|
GridCellContent(row, column int, session Session) View
|
||||||
|
}
|
||||||
|
|
||||||
|
// GridCellColumnSpanAdapter implements the optional method of GridAdapter interface
|
||||||
|
type GridCellColumnSpanAdapter interface {
|
||||||
|
// GridCellColumnSpan returns the number of columns that a cell spans.
|
||||||
|
// Values less than 1 are ignored.
|
||||||
|
GridCellColumnSpan(row, column int) int
|
||||||
|
}
|
||||||
|
|
||||||
|
// GridCellColumnSpanAdapter implements the optional method of GridAdapter interface
|
||||||
|
type GridCellRowSpanAdapter interface {
|
||||||
|
// GridCellRowSpan returns the number of rows that a cell spans
|
||||||
|
// Values less than 1 are ignored.
|
||||||
|
GridCellRowSpan(row, column int) int
|
||||||
|
}
|
||||||
|
|
||||||
// GridLayout - grid-container of View
|
// GridLayout - grid-container of View
|
||||||
type GridLayout interface {
|
type GridLayout interface {
|
||||||
ViewsContainer
|
ViewsContainer
|
||||||
|
|
||||||
|
// UpdateContent updates child Views if the "content" property value is set to GridAdapter,
|
||||||
|
// otherwise does nothing
|
||||||
|
UpdateGridContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
type gridLayoutData struct {
|
type gridLayoutData struct {
|
||||||
viewsContainerData
|
viewsContainerData
|
||||||
|
adapter GridAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGridLayout create new GridLayout object and return it
|
// NewGridLayout create new GridLayout object and return it
|
||||||
|
@ -69,6 +99,7 @@ func (gridLayout *gridLayoutData) init(session Session) {
|
||||||
gridLayout.viewsContainerData.init(session)
|
gridLayout.viewsContainerData.init(session)
|
||||||
gridLayout.tag = "GridLayout"
|
gridLayout.tag = "GridLayout"
|
||||||
gridLayout.systemClass = "ruiGridLayout"
|
gridLayout.systemClass = "ruiGridLayout"
|
||||||
|
gridLayout.adapter = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gridLayout *gridLayoutData) String() string {
|
func (gridLayout *gridLayoutData) String() string {
|
||||||
|
@ -257,14 +288,19 @@ func (gridLayout *gridLayoutData) Remove(tag string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gridLayout *gridLayoutData) remove(tag string) {
|
func (gridLayout *gridLayoutData) remove(tag string) {
|
||||||
if tag == Gap {
|
switch tag {
|
||||||
|
case Gap:
|
||||||
gridLayout.remove(GridRowGap)
|
gridLayout.remove(GridRowGap)
|
||||||
gridLayout.remove(GridColumnGap)
|
gridLayout.remove(GridColumnGap)
|
||||||
gridLayout.propertyChangedEvent(Gap)
|
gridLayout.propertyChangedEvent(Gap)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case Content:
|
||||||
|
gridLayout.adapter = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gridLayout.viewsContainerData.remove(tag)
|
gridLayout.viewsContainerData.remove(tag)
|
||||||
|
|
||||||
if gridLayout.created {
|
if gridLayout.created {
|
||||||
switch tag {
|
switch tag {
|
||||||
case CellWidth:
|
case CellWidth:
|
||||||
|
@ -289,8 +325,17 @@ func (gridLayout *gridLayoutData) set(tag string, value any) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if tag == Gap {
|
switch tag {
|
||||||
|
case Gap:
|
||||||
return gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value)
|
return gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value)
|
||||||
|
|
||||||
|
case Content:
|
||||||
|
if adapter, ok := value.(GridAdapter); ok {
|
||||||
|
gridLayout.adapter = adapter
|
||||||
|
gridLayout.UpdateGridContent()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
gridLayout.adapter = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if gridLayout.viewsContainerData.set(tag, value) {
|
if gridLayout.viewsContainerData.set(tag, value) {
|
||||||
|
@ -312,6 +357,70 @@ func (gridLayout *gridLayoutData) set(tag string, value any) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gridLayout *gridLayoutData) UpdateGridContent() {
|
||||||
|
if adapter := gridLayout.adapter; adapter != nil {
|
||||||
|
gridLayout.views = []View{}
|
||||||
|
|
||||||
|
session := gridLayout.session
|
||||||
|
htmlID := gridLayout.htmlID()
|
||||||
|
isDisabled := IsDisabled(gridLayout)
|
||||||
|
|
||||||
|
var columnSpan GridCellColumnSpanAdapter = nil
|
||||||
|
if span, ok := adapter.(GridCellColumnSpanAdapter); ok {
|
||||||
|
columnSpan = span
|
||||||
|
}
|
||||||
|
|
||||||
|
var rowSpan GridCellRowSpanAdapter = nil
|
||||||
|
if span, ok := adapter.(GridCellRowSpanAdapter); ok {
|
||||||
|
rowSpan = span
|
||||||
|
}
|
||||||
|
|
||||||
|
width := adapter.GridColumnCount()
|
||||||
|
height := adapter.GridRowCount()
|
||||||
|
for column := 0; column < width; column++ {
|
||||||
|
for row := 0; row < height; row++ {
|
||||||
|
if view := adapter.GridCellContent(row, column, session); view != nil {
|
||||||
|
view.setParentID(htmlID)
|
||||||
|
|
||||||
|
columnCount := 1
|
||||||
|
if columnSpan != nil {
|
||||||
|
columnCount = columnSpan.GridCellColumnSpan(row, column)
|
||||||
|
}
|
||||||
|
|
||||||
|
if columnCount > 1 {
|
||||||
|
view.Set(Column, Range{First: column, Last: column + columnCount - 1})
|
||||||
|
} else {
|
||||||
|
view.Set(Column, column)
|
||||||
|
}
|
||||||
|
|
||||||
|
rowCount := 1
|
||||||
|
if rowSpan != nil {
|
||||||
|
rowCount = rowSpan.GridCellRowSpan(row, column)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rowCount > 1 {
|
||||||
|
view.Set(Row, Range{First: row, Last: row + rowCount - 1})
|
||||||
|
} else {
|
||||||
|
view.Set(Row, row)
|
||||||
|
}
|
||||||
|
|
||||||
|
if isDisabled {
|
||||||
|
view.Set(Disabled, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
gridLayout.views = append(gridLayout.views, view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if gridLayout.created {
|
||||||
|
updateInnerHTML(htmlID, session)
|
||||||
|
}
|
||||||
|
|
||||||
|
gridLayout.propertyChangedEvent(Content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func gridCellSizes(properties Properties, tag string, session Session) []SizeUnit {
|
func gridCellSizes(properties Properties, tag string, session Session) []SizeUnit {
|
||||||
if value := properties.Get(tag); value != nil {
|
if value := properties.Get(tag); value != nil {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
|
|
@ -245,7 +245,7 @@ func GetListColumnGap(view View, subviewID ...string) SizeUnit {
|
||||||
return sizeStyledProperty(view, subviewID, ListColumnGap, false)
|
return sizeStyledProperty(view, subviewID, ListColumnGap, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateContent updates child Views of ListLayout subview if the "content" property value is set to ListAdapter,
|
// UpdateContent updates child Views of ListLayout/GridLayout subview if the "content" property value is set to ListAdapter/GridAdapter,
|
||||||
// otherwise does nothing.
|
// otherwise does nothing.
|
||||||
// If the second argument (subviewID) is not specified or it is "" then the first argument (view) updates.
|
// If the second argument (subviewID) is not specified or it is "" then the first argument (view) updates.
|
||||||
func UpdateContent(view View, subviewID ...string) {
|
func UpdateContent(view View, subviewID ...string) {
|
||||||
|
@ -255,6 +255,9 @@ func UpdateContent(view View, subviewID ...string) {
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
switch view := view.(type) {
|
switch view := view.(type) {
|
||||||
|
case GridLayout:
|
||||||
|
view.UpdateGridContent()
|
||||||
|
|
||||||
case ListLayout:
|
case ListLayout:
|
||||||
view.UpdateContent()
|
view.UpdateContent()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue