Merge pull request #3 from anoshenko/0.11.0

0.11.0
This commit is contained in:
Alexei Anoshenko 2023-01-03 15:08:09 +03:00 committed by GitHub
commit b99c39f947
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 615 additions and 82 deletions

View File

@ -1,6 +1,14 @@
# v.11.0
* Added "tabindex", "order", "column-fill", "column-span-all", "background-blend-mode", and "mix-blend-mode" properties
* Added GetTabIndex, GetOrder, GetColumnFill, IsColumnSpanAll, GetBackgroundBlendMode, and GetMixBlendMode functions
* ClientItem, SetClientItem, and RemoveAllClientItems method added to Session interface
* PropertyWithTag method of DataObject interface renamed to PropertyByTag
# v.10.0 # v.10.0
* The Canvas.TextWidth method replaced by Canvas.TextMetrics * The Canvas.TextWidth method replaced by Canvas.TextMetrics
* Added support of WebAssembly
# v0.9.0 # v0.9.0

View File

@ -615,7 +615,7 @@ SizeUnit или имя константы (о константах ниже):
Значение по умолчанию для всех типов View кроме многострочного редактора текста это NoneResize (0). Значение по умолчанию для всех типов View кроме многострочного редактора текста это NoneResize (0).
Значение по умолчанию для многострочного редактора текста это BothResize (1). Значение по умолчанию для многострочного редактора текста это BothResize (1).
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetResize(view View, subviewID ...string) int func GetResize(view View, subviewID ...string) int
@ -1021,7 +1021,7 @@ RadiusProperty, а не структура BoxRadius. Получить стру
[, spread-radius = <увеличение>] [, inset = <тип>] } [, spread-radius = <увеличение>] [, inset = <тип>] }
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetViewShadows(view View, subviewID ...string) []ViewShadow func GetViewShadows(view View, subviewID ...string) []ViewShadow
@ -1202,7 +1202,7 @@ AngleUnit или string (угловая константа или текстов
* Attachment - ??? * Attachment - ???
* Repeat (repeat) - необязательный параметр задающий повтор изображения. * Repeat (repeat) - необязательный параметр задающий повтор изображения.
Может принимать одно из следующих значений типа Int: Может принимать одно из следующих значений типа int:
| Константа | Значение | Имя | Описание | | Константа | Значение | Имя | Описание |
|-------------|:--------:|-------------|---------------------------------------------------------------| |-------------|:--------:|-------------|---------------------------------------------------------------|
@ -1216,6 +1216,47 @@ AngleUnit или string (угловая константа или текстов
* ImageHorizontalAlign, * ImageHorizontalAlign,
* ImageVerticalAlign, * ImageVerticalAlign,
### Свойство "background-blend-mode"
Свойство "background-blend-mode" (константа BackgroundBlendMode) типа int устанавливает,
как фоновые изображения / градиенты элемента должны смешиваться друг с другом и с цветом фона.
Может принимать одно из следующих значений:
| Константа | Значение | Имя | Описание |
|-----------------|:--------:|--------------|---------------------------------------------------------------|
| BlendNormal | 0 | "normal" | Конечный цвет это верхний цвет, независимо от того, какой нижний цвет. Эффект подобен двум непрозрачным листам бумаги, перекрывающимся друг с другом. |
| BlendMultiply | 1 | "multiply" | Конечный цвет является результатом умножения верхнего и нижнего цветов. Черный слой приводит к черному конечному слою, а белый слой не приводит к изменению. Эффект подобен наложению двух изображений, напечатанных на прозрачной пленке. |
| BlendScreen | 2 | "screen" | Конечный цвет является результатом инвертирования цветов, их умножения и инвертирования этого значения. Черный слой не приводит к изменению, а белый слой приводит к белому конечному слою. Эффект подобен двум изображениям на проекционном экране. |
| BlendOverlay | 3 | "overlay" | Конечный цвет является результатом умножения, если нижний цвет темнее, или "screen", если нижний цвет светлее. Этот режим наложения эквивалентен жесткому свету, но с перестановкой слоев. |
| BlendDarken | 4 | "darken" | Конечный цвет состоит из самых темных значений каждого цветового канала. |
| BlendLighten | 5 | "lighten" | Конечный цвет состоит из самых светлых значений каждого цветового канала. |
| BlendColorDodge | 6 | "color-dodge"| Окончательный цвет является результатом деления нижнего цвета на инверсию верхнего цвета. Черный передний план не приводит к изменениям. Передний план с обратным цветом фона приводит к полностью освещенному цвету. Этот режим наложения похож на "screen", но передний план должен быть таким же светлым, как и обратная сторона фона, чтобы создать полностью освещенный цвет. |
| BlendColorBurn | 7 | "color-burn" | Конечный цвет является результатом инвертирования нижнего цвета, деления значения на верхний цвет и инвертирования этого значения. Белый передний план не приводит к изменениям. Передний план с обратным цветом фона приводит к черному конечному изображению. Этот режим наложения похож на режим умножения, но передний план должен быть таким же темным, как и обратная сторона фона, чтобы окончательное изображение стало черным. |
| BlendHardLight | 8 | "hard-light" | Окончательный цвет является результатом умножения, если верхний цвет темнее, или "screen", если верхний цвет светлее. Этот режим наложения эквивалентен наложению, но слои меняются местами. Эффект подобен яркому прожектору на фоне. |
| BlendSoftLight | 9 | "soft-light" | Конечный цвет похож на "hard-light", но мягче. Этот режим наложения ведет себя аналогично "hard-light". Эффект подобен рассеянному свету прожектора на фоне |
| BlendDifference | 10 | "difference" | Окончательный цвет получается в результате вычитания более темного из двух цветов из более светлого. Черный слой не имеет никакого эффекта, а белый слой инвертирует цвет другого слоя. |
| BlendExclusion | 11 | "exclusion" | Конечный цвет подобен "difference", но с меньшим контрастом. Как и в случае с "difference", черный слой не имеет эффекта, а белый слой инвертирует цвет другого слоя. |
| BlendHue | 12 | "hue" | Конечный цвет имеет оттенок верхнего цвета, используя при этом насыщенность и яркость нижнего цвета. |
| BlendSaturation | 13 | "saturation" | Конечный цвет имеет насыщенность верхнего цвета при использовании оттенка и яркости нижнего цвета. Чисто серый фон, не имеющий насыщенности, не будет иметь никакого эффекта. |
| BlendColor | 14 | "color" | Конечный цвет имеет оттенок и насыщенность верхнего цвета, используя при этом яркость нижнего цвета. Эффект сохраняет уровни серого и может использоваться для раскрашивания переднего плана. |
| BlendLuminosity | 15 | "luminosity" | Окончательный цвет имеет яркость верхнего цвета, используя при этом оттенок и насыщенность нижнего цвета. Этот режим наложения эквивалентен "color", но с перестановкой слоев. |
Получить значение данного свойства можно с помощью функции
func GetBackgroundBlendMode(view View, subviewID ...string) int
### Свойство "mix-blend-mode"
Свойство "mix-blend-mode" (константа MixBlendMode) типа int устанавливает,
как содержимое View должно сочетаться с содержимым родительского View и фоном.
Возможные значения данного свойства аналогичны значениям свойства "background-blend-mode" (см. выше)
Получить значение данного свойства можно с помощью функции
func GetMixBlendMode(view View, subviewID ...string) int
### Свойство "clip" ### Свойство "clip"
Свойство "clip" (константа Clip) типа ClipShape задает задает область образки. Свойство "clip" (константа Clip) типа ClipShape задает задает область образки.
@ -1282,17 +1323,33 @@ radius необходимо передать nil
Свойство "opacity" (константа Opacity) типа float64 задает прозрачность View. Допустимые значения от 0 до 1. Свойство "opacity" (константа Opacity) типа float64 задает прозрачность View. Допустимые значения от 0 до 1.
Где 1 - View полностью непрозрачен, 0 - полностью прозрачен. Где 1 - View полностью непрозрачен, 0 - полностью прозрачен.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetOpacity(view View, subviewID ...string) float64 func GetOpacity(view View, subviewID ...string) float64
### Свойство "tabindex"
Свойство "tabindex" (константа TabIndex) типа int определяет должен ли данный View участвовать в последовательной
навигации по всей странице с помощью клавиатуры и в каком порядке. Может принимать одно из следующих видов значений:
* отрицательное значение View может быть выделен с помощью мыши или прикосновения, однако не участвует в последовательной навигации;
* 0 View может быть выделен и достигнут с помощью последовательной навигации, порядок навигации определён браузером (обычно в порядке добавления);
* положительное значение элемент будет достигнут (и выделен) с помощью последовательной навигации, а навигация осуществляется по возрастанию значения "tabindex".
В случае, если несколько элементов содержат одно и то же значение "tabindex", то навигации осуществляется в порядке их добавления.
Получить значение данного свойства можно с помощью функции
func GetTabIndex(view View, subviewID ...string) int
### Свойство "z-index" ### Свойство "z-index"
Свойство "z-index" (константа ZIndex) типа int определяет положение элемента и нижестоящих элементов по оси z. Свойство "z-index" (константа ZIndex) типа int определяет положение элемента и нижестоящих элементов по оси z.
В случае перекрытия элементов, это значение определяет порядок наложения. В общем случае, элементы В случае перекрытия элементов, это значение определяет порядок наложения. В общем случае, элементы
с большим z-index перекрывают элементы с меньшим. с большим z-index перекрывают элементы с меньшим.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetZIndex(view View, subviewID ...string) int func GetZIndex(view View, subviewID ...string) int
@ -1306,7 +1363,7 @@ radius необходимо передать nil
| 1 | Invisible | "invisible" | View невидим, но занимает место. | | 1 | Invisible | "invisible" | View невидим, но занимает место. |
| 2 | Gone | "gone" | View невидим и не занимает место. | | 2 | Gone | "gone" | View невидим и не занимает место. |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetVisibility(view View, subviewID ...string) int func GetVisibility(view View, subviewID ...string) int
@ -1383,7 +1440,7 @@ radius необходимо передать nil
Шрифты применяются в том порядке в котором они перечислены. Т.е. сначала Шрифты применяются в том порядке в котором они перечислены. Т.е. сначала
применяется первый, если он недоступен, то второй, третий и т.д. применяется первый, если он недоступен, то второй, третий и т.д.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetFontName(view View, subviewID ...string) string func GetFontName(view View, subviewID ...string) string
@ -1391,7 +1448,7 @@ radius необходимо передать nil
Свойство "text-color" (константа TextColor) - Свойство типа Color определяет цвет текста. Свойство "text-color" (константа TextColor) - Свойство типа Color определяет цвет текста.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextColor(view View, subviewID ...string) Color func GetTextColor(view View, subviewID ...string) Color
@ -1399,7 +1456,7 @@ radius необходимо передать nil
Свойство "text-size" (константа TextSize) - Свойство типа SizeUnit определяет размер шрифта. Свойство "text-size" (константа TextSize) - Свойство типа SizeUnit определяет размер шрифта.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextSize(view View, subviewID ...string) SizeUnit func GetTextSize(view View, subviewID ...string) SizeUnit
@ -1407,7 +1464,7 @@ radius необходимо передать nil
Свойство "italic" (константа Italic) - Свойство типа bool. Если значение равно true, то к тексту применяется курсивное начертание Свойство "italic" (константа Italic) - Свойство типа bool. Если значение равно true, то к тексту применяется курсивное начертание
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func IsItalic(view View, subviewID ...string) bool func IsItalic(view View, subviewID ...string) bool
@ -1415,7 +1472,7 @@ radius необходимо передать nil
Свойство "small-caps" (константа SmallCaps) - Свойство типа bool. Если значение равно true, то к тексту применяется начертание капителью Свойство "small-caps" (константа SmallCaps) - Свойство типа bool. Если значение равно true, то к тексту применяется начертание капителью
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func IsSmallCaps(view View, subviewID ...string) bool func IsSmallCaps(view View, subviewID ...string) bool
@ -1501,7 +1558,7 @@ radius необходимо передать nil
Свойство "text-line-thickness" (константа TextLineThickness) - Свойство типа SizeUnit. Свойство "text-line-thickness" (константа TextLineThickness) - Свойство типа SizeUnit.
Свойство устанавливает толщину декоративных линий на тексте заданных с помощью Свойств "strikethrough", "overline" и "underline". Свойство устанавливает толщину декоративных линий на тексте заданных с помощью Свойств "strikethrough", "overline" и "underline".
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
GetTextLineThickness(view View, subviewID ...string) SizeUnit GetTextLineThickness(view View, subviewID ...string) SizeUnit
@ -1521,7 +1578,7 @@ radius необходимо передать nil
Если Свойство не определено то используется сплошная линия (SolidLine (1)). Если Свойство не определено то используется сплошная линия (SolidLine (1)).
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextLineStyle(view View, subviewID ...string) int func GetTextLineStyle(view View, subviewID ...string) int
@ -1531,7 +1588,7 @@ radius необходимо передать nil
Свойство устанавливает цвет декоративных линий на тексте заданных с помощью Свойств "strikethrough", "overline" и "underline". Свойство устанавливает цвет декоративных линий на тексте заданных с помощью Свойств "strikethrough", "overline" и "underline".
Если Свойство не определено то для линий используется цвет текста заданный с помощью Свойства "text-color". Если Свойство не определено то для линий используется цвет текста заданный с помощью Свойства "text-color".
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextLineColor(view View, subviewID ...string) Color func GetTextLineColor(view View, subviewID ...string) Color
@ -1551,9 +1608,9 @@ radius необходимо передать nil
| 8 | ExtraBoldFont | Дополнительный жирный (Сверх жирный) Extra Bold (Ultra Bold) | | 8 | ExtraBoldFont | Дополнительный жирный (Сверх жирный) Extra Bold (Ultra Bold) |
| 9 | BlackFont | Чёрный (Густой) Black (Heavy) | | 9 | BlackFont | Чёрный (Густой) Black (Heavy) |
Некоторые шрифты доступны только в нормальном или полужирном начертании. В этом случае значение данного Свойства игнорируется Некоторые шрифты доступны только в нормальном или полужирном начертании. В этом случае значение данного свойства игнорируется
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextWeight(view View, subviewID ...string) int func GetTextWeight(view View, subviewID ...string) int
@ -1580,7 +1637,7 @@ radius необходимо передать nil
В качестве значения Свойству "text-shadow" может быть присвоено ViewShadow, массив ViewShadow, В качестве значения Свойству "text-shadow" может быть присвоено ViewShadow, массив ViewShadow,
текстовое представление ViewShadow (см. выше, раздел "Свойство 'shadow'"). текстовое представление ViewShadow (см. выше, раздел "Свойство 'shadow'").
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextShadows(view View, subviewID ...string) []ViewShadow func GetTextShadows(view View, subviewID ...string) []ViewShadow
@ -1597,7 +1654,7 @@ radius необходимо передать nil
| 2 | CenterAlign | "center" | Выравнивание по центру | | 2 | CenterAlign | "center" | Выравнивание по центру |
| 3 | JustifyAlign | "justify" | Выравнивание по ширине | | 3 | JustifyAlign | "justify" | Выравнивание по ширине |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextAlign(view View, subviewID ...string) int func GetTextAlign(view View, subviewID ...string) int
@ -1605,7 +1662,7 @@ radius необходимо передать nil
Свойство "text-indent" (TextIndent) - Свойство типа SizeUnit определяет размер отступа (пустого места) перед первой строкой текста. Свойство "text-indent" (TextIndent) - Свойство типа SizeUnit определяет размер отступа (пустого места) перед первой строкой текста.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextIndent(view View, subviewID ...string) SizeUnit func GetTextIndent(view View, subviewID ...string) SizeUnit
@ -1615,7 +1672,7 @@ radius необходимо передать nil
Значение может быть отрицательным, но при этом могут быть ограничения, зависящие от конкретной реализации. Значение может быть отрицательным, но при этом могут быть ограничения, зависящие от конкретной реализации.
Агент пользователя может не увеличивать или уменьшать межбуквенное расстояние для выравнивания текста. Агент пользователя может не увеличивать или уменьшать межбуквенное расстояние для выравнивания текста.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetLetterSpacing(view View, subviewID ...string) SizeUnit func GetLetterSpacing(view View, subviewID ...string) SizeUnit
@ -1625,7 +1682,7 @@ radius необходимо передать nil
Если величина задана в процентах, то она определяет дополнительный интервал как процент от предварительной ширины символа. Если величина задана в процентах, то она определяет дополнительный интервал как процент от предварительной ширины символа.
В остальных случаях она определяет дополнительный интервал в дополнение к внутреннему интервалу между словами, определяемому шрифтом. В остальных случаях она определяет дополнительный интервал в дополнение к внутреннему интервалу между словами, определяемому шрифтом.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetWordSpacing(view View, subviewID ...string) SizeUnit func GetWordSpacing(view View, subviewID ...string) SizeUnit
@ -1633,7 +1690,7 @@ radius необходимо передать nil
Свойство "line-height" (константа LineHeight) - Свойство типа SizeUnit устанавливает величину пространства между строками. Свойство "line-height" (константа LineHeight) - Свойство типа SizeUnit устанавливает величину пространства между строками.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetLineHeight(view View, subviewID ...string) SizeUnit func GetLineHeight(view View, subviewID ...string) SizeUnit
@ -1648,7 +1705,7 @@ radius необходимо передать nil
| 2 | LowerCaseTextTransform | Все символы строчные | | 2 | LowerCaseTextTransform | Все символы строчные |
| 3 | UpperCaseTextTransform | Все символы заглавные | | 3 | UpperCaseTextTransform | Все символы заглавные |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextTransform(view View, subviewID ...string) int func GetTextTransform(view View, subviewID ...string) int
@ -1662,7 +1719,7 @@ radius необходимо передать nil
| 1 | LeftToRightDirection | Слева направо. Используется для английского и большинства других языков. | | 1 | LeftToRightDirection | Слева направо. Используется для английского и большинства других языков. |
| 2 | RightToLeftDirection | Справа налево. Используется для иврит, арабский и некоторых других. | | 2 | RightToLeftDirection | Справа налево. Используется для иврит, арабский и некоторых других. |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTextDirection(view View, subviewID ...string) int func GetTextDirection(view View, subviewID ...string) int
@ -1679,7 +1736,7 @@ radius необходимо передать nil
| 2 | VerticalRightToLeft | Вертикальные строки выводятся справа налево. | | 2 | VerticalRightToLeft | Вертикальные строки выводятся справа налево. |
| 3 | VerticalLeftToRight | Вертикальные строки выводятся слева направо. | | 3 | VerticalLeftToRight | Вертикальные строки выводятся слева направо. |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetWritingMode(view View, subviewID ...string) int func GetWritingMode(view View, subviewID ...string) int
@ -1694,7 +1751,7 @@ radius необходимо передать nil
| 0 | MixedTextOrientation | Символы повернуты на 90 по часовой стрелке. Значение по умолчанию. | | 0 | MixedTextOrientation | Символы повернуты на 90 по часовой стрелке. Значение по умолчанию. |
| 1 | UprightTextOrientation | Символы расположены нормально (вертикально). | | 1 | UprightTextOrientation | Символы расположены нормально (вертикально). |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetVerticalTextOrientation(view View, subviewID ...string) int func GetVerticalTextOrientation(view View, subviewID ...string) int
@ -1710,7 +1767,7 @@ radius необходимо передать nil
Как и все Свойства текста Свойство "user-select" наследуемое, т.е. если вы установите его для контейнера, Как и все Свойства текста Свойство "user-select" наследуемое, т.е. если вы установите его для контейнера,
то оно также примениться ко всем дочерним элементам то оно также примениться ко всем дочерним элементам
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func IsUserSelect(view View, subviewID ...string) bool func IsUserSelect(view View, subviewID ...string) bool
@ -1729,7 +1786,7 @@ radius необходимо передать nil
Точка схождения по умолчанию расположена в центре элемента, но её можно переместить используя Свойства Точка схождения по умолчанию расположена в центре элемента, но её можно переместить используя Свойства
"perspective-origin-x" и "perspective-origin-y". "perspective-origin-x" и "perspective-origin-y".
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetPerspective(view View, subviewID ...string) SizeUnit func GetPerspective(view View, subviewID ...string) SizeUnit
@ -1753,7 +1810,7 @@ radius необходимо передать nil
задняя грань может быть видимой, когда преобразование вызывает вращение элемента в 3D пространстве. задняя грань может быть видимой, когда преобразование вызывает вращение элемента в 3D пространстве.
(Это Свойство не влияет на 2D-преобразования, которые не имеют перспективы.) (Это Свойство не влияет на 2D-преобразования, которые не имеют перспективы.)
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetBackfaceVisible(view View, subviewID ...string) bool func GetBackfaceVisible(view View, subviewID ...string) bool
@ -2154,7 +2211,7 @@ radius необходимо передать nil
### "content" ### "content"
Свойство "content" (константа Content) определяет массив дочерних View. Функция Get интерфейса Свойство "content" (константа Content) определяет массив дочерних View. Функция Get интерфейса
для данного Свойства всегда возвращает []View. для данного свойства всегда возвращает []View.
В качестве значения Свойства "content" могут быть переданы следующие 5 типов данных: В качестве значения Свойства "content" могут быть переданы следующие 5 типов данных:
@ -2260,6 +2317,17 @@ ListLayout является контейнером, реализующим ин
Свойства "list-row-gap" и "list-column-gap" (константы ListRowGap и ListColumnGap) типа SizeUnit позволяют Свойства "list-row-gap" и "list-column-gap" (константы ListRowGap и ListColumnGap) типа SizeUnit позволяют
установить соответственно расстояния между строками и столбцами контейнера. Значение по умолчанию 0. установить соответственно расстояния между строками и столбцами контейнера. Значение по умолчанию 0.
### "order"
Свойство "order" (константа Order) типа int используется View, помещенными в контейнер ListLayout или GridLayout (см. ниже),
для изменения своего положения в контейнере.
Свойство "order" определяет порядок, используемый для размещения View в контейнере. Элементы располагаются в восходящем порядке по значению order.
Элементы с одинаковым значением order располагаются в том порядке, в каком они добавлялись в контейнер.
Значение по умолчанию равно 0. Поэтому для помещения View в начало надо использовать отрицательные значения свойства "order".
Внимание: свойство "order" воздействует только на визуальный порядок элементов, но не логический порядок или табуляцию.
## GridLayout ## GridLayout
GridLayout является контейнером, реализующим интерфейс ViewsContainer. Для его создания используется функция GridLayout является контейнером, реализующим интерфейс ViewsContainer. Для его создания используется функция
@ -2406,12 +2474,12 @@ ColumnLayout является контейнером, реализующим и
Если данное Свойство равно 0 и не задано Свойство "column-width", то разбитие на колонки Если данное Свойство равно 0 и не задано Свойство "column-width", то разбитие на колонки
не выполняется, а контейнер прокручивается вниз. не выполняется, а контейнер прокручивается вниз.
Если значение данного Свойства больше 0, то список разбивается на колонки. Высота колонки Если значение данного свойства больше 0, то список разбивается на колонки. Высота колонки
равна высоте ColumnLayout, а ширина вычисляется как ширина ColumnLayout делённая на равна высоте ColumnLayout, а ширина вычисляется как ширина ColumnLayout делённая на
"column-count". Каждая следующая колонка располагается в зависимости от Свойства "column-count". Каждая следующая колонка располагается в зависимости от Свойства
"text-direction" справа или слева от предыдущей, а контейнер прокручивается по горизонтали. "text-direction" справа или слева от предыдущей, а контейнер прокручивается по горизонтали.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetColumnCount(view View, subviewID ...string) int func GetColumnCount(view View, subviewID ...string) int
@ -2423,7 +2491,7 @@ ColumnLayout является контейнером, реализующим и
ВАЖНО! В качестве значения "column-width" нельзя использовать проценты (т.е. если вы зададите ВАЖНО! В качестве значения "column-width" нельзя использовать проценты (т.е. если вы зададите
значение в процентах, то это проигнорируется системой) значение в процентах, то это проигнорируется системой)
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetColumnWidth(view View, subviewID ...string) SizeUnit func GetColumnWidth(view View, subviewID ...string) SizeUnit
@ -2431,7 +2499,7 @@ ColumnLayout является контейнером, реализующим и
Свойство "column-gap" (константа ColumnGap) типа SizeUnit устанавливает ширину разрыва между колонками. Свойство "column-gap" (константа ColumnGap) типа SizeUnit устанавливает ширину разрыва между колонками.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetColumnGap(view View, subviewID ...string) SizeUnit func GetColumnGap(view View, subviewID ...string) SizeUnit
@ -2506,6 +2574,20 @@ ViewBorder описана как
rui.ColorProperty: rui.Black, rui.ColorProperty: rui.Black,
})) }))
### Свойство "column-fill"
Свойство "column-fill" (константа ColumnFill) типа int управляет тем, как содержимое элемента сбалансировано при разбиении на столбцы.
Может принимать одно из двух значений
| Значение | Константа | Имя | Описание |
|:--------:|-------------------|-----------|------------------------------------------------------------------|
| 0 | ColumnFillBalance | "balance" | Контент поровну разделен между столбцами (значение по умолчанию) |
| 1 | ColumnFillAuto | "auto" | Столбцы заполняются последовательно. Контент занимает ровно столько места, сколько ему нужно, что может привести к тому, что некоторые столбцы останутся пустыми. |
Получить значение данного свойства можно с помощью функции
func GetColumnFill(view View, subviewID ...string) int
### Свойство "avoid-break" ### Свойство "avoid-break"
При формировании колонок ColumnLayout может разрывать некоторые типы View, так что начало При формировании колонок ColumnLayout может разрывать некоторые типы View, так что начало
@ -2514,13 +2596,27 @@ ViewBorder описана как
Свойство "avoid-break" (константа AvoidBreak) типа bool позволяет избежать этого эффекта. Свойство "avoid-break" (константа AvoidBreak) типа bool позволяет избежать этого эффекта.
Необходимо установить для View, который нельзя разрывать, данное Свойство со значением "true". Необходимо установить для View, который нельзя разрывать, данное Свойство со значением "true".
Соответственно значение "false" данного Свойства позволяет разрывать View. Соответственно значение "false" данного свойства позволяет разрывать View.
Значение по умолчанию "false". Значение по умолчанию "false".
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetAvoidBreak(view View, subviewID ...string) bool func GetAvoidBreak(view View, subviewID ...string) bool
### Свойство "column-span-all"
Свойство "column-span-all" (константа ColumnSpanAll) типа bool устанавливается для View помещенных в ColumnLayout.
Если данное свойство установлено в true, то View расширяется на всю ширину ColumnLayout, занимая все колонки.
Такое View будет как бы разрывать контейнер.
Обычно данное свойство используется для заголовков.
Значение по умолчанию "false".
Получить значение данного свойства можно с помощью функции
func IsColumnSpanAll(view View, subviewID ...string) bool
## StackLayout ## StackLayout
StackLayout является контейнером, реализующим интерфейс ViewsContainer. Все дочерние View StackLayout является контейнером, реализующим интерфейс ViewsContainer. Все дочерние View
@ -3225,7 +3321,7 @@ float32, float64, int, int8…int64, uint, uint8…uint64.
func GetDropDownDisabledItems(view View, subviewID ...string) []int func GetDropDownDisabledItems(view View, subviewID ...string) []int
Выбранное значение определяется int Свойством "current" (константа Current). Значение по умолчанию 0. Выбранное значение определяется int Свойством "current" (константа Current). Значение по умолчанию 0.
Прочитать значение данного Свойства можно с помощью функции Прочитать значение данного свойства можно с помощью функции
func GetCurrent(view View, subviewID ...string) int func GetCurrent(view View, subviewID ...string) int
@ -3339,7 +3435,7 @@ ReloadListViewData() интерфейса ListView или глобальную
Свойства "text-direction". Для языков с письмом справа налево (арабский, иврит) начало находится Свойства "text-direction". Для языков с письмом справа налево (арабский, иврит) начало находится
справа, для остальных языков - слева. справа, для остальных языков - слева.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetListOrientation(view View, subviewID ...string) int func GetListOrientation(view View, subviewID ...string) int
@ -3356,7 +3452,7 @@ ReloadListViewData() интерфейса ListView или глобальную
* WrapReverse (2) - начинается новая колонка/строка элементов. Новая колонка располагается по направлению * WrapReverse (2) - начинается новая колонка/строка элементов. Новая колонка располагается по направлению
к началу (о положении начала и конца см. выше), новая строка - сверху. к началу (о положении начала и конца см. выше), новая строка - сверху.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetListWrap(view View, subviewID ...string) int func GetListWrap(view View, subviewID ...string) int
@ -3386,7 +3482,7 @@ ReloadListViewData() интерфейса ListView или глобальную
| 2 | CenterAlign | "center" | Выравнивание по центру | | 2 | CenterAlign | "center" | Выравнивание по центру |
| 3 | StretchAlign | "stretch" | Выравнивание по высоте | | 3 | StretchAlign | "stretch" | Выравнивание по высоте |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetListItemVerticalAlign(view View, subviewID ...string) int func GetListItemVerticalAlign(view View, subviewID ...string) int
@ -3402,7 +3498,7 @@ ReloadListViewData() интерфейса ListView или глобальную
| 2 | CenterAlign | "center" | Выравнивание по центру | | 2 | CenterAlign | "center" | Выравнивание по центру |
| 3 | StretchAlign | "stretch" | Выравнивание по ширине | | 3 | StretchAlign | "stretch" | Выравнивание по ширине |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
GetListItemHorizontalAlign(view View, subviewID ...string) int GetListItemHorizontalAlign(view View, subviewID ...string) int
@ -3413,7 +3509,7 @@ ListView позволяет выбирать пункты списка имею
int Свойство "current" (константа Current). Значение "current" меньше 0 означает что int Свойство "current" (константа Current). Значение "current" меньше 0 означает что
не выбран ни один пункт не выбран ни один пункт
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetCurrent(view View, subviewID ...string) int func GetCurrent(view View, subviewID ...string) int
@ -3441,13 +3537,13 @@ int Свойство "current" (константа Current). Значение "c
| 2 | MultipleCheckbox | "multiple" | ☑ Чекбокс позволяющий пометить несколько пунктов | | 2 | MultipleCheckbox | "multiple" | ☑ Чекбокс позволяющий пометить несколько пунктов |
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetListViewCheckbox(view View, subviewID ...string) int func GetListViewCheckbox(view View, subviewID ...string) int
Получить/установить список помеченных пунктов можно с помощью Свойства "checked" (константа Checked). Получить/установить список помеченных пунктов можно с помощью Свойства "checked" (константа Checked).
Данное Свойство имеет тип []int и хранит индексы помеченных элементов. Данное Свойство имеет тип []int и хранит индексы помеченных элементов.
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetListViewCheckedItems(view View, subviewID ...string) []int func GetListViewCheckedItems(view View, subviewID ...string) []int
@ -3698,7 +3794,7 @@ TableColumnStyle объявлена как
Для горизонтального выравнивания используется Свойство "text-align". Для горизонтального выравнивания используется Свойство "text-align".
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTableVerticalAlign(view View, subviewID ...string) int func GetTableVerticalAlign(view View, subviewID ...string) int
@ -3720,7 +3816,7 @@ TableColumnStyle объявлена как
(с использованием клавиш управления курсором). В данном режиме таблица может получить фокус ввода. (с использованием клавиш управления курсором). В данном режиме таблица может получить фокус ввода.
В данном режиме таблица генерирует два вида событий: "table-row-selected" и "table-row-clicked" (о них ниже). В данном режиме таблица генерирует два вида событий: "table-row-selected" и "table-row-clicked" (о них ниже).
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetSelectionMode(view View, subviewID ...string) int func GetSelectionMode(view View, subviewID ...string) int
@ -3738,7 +3834,7 @@ TableColumnStyle объявлена как
В режиме RowSelection значение поля Column игнорируется. Также в данном режиме В режиме RowSelection значение поля Column игнорируется. Также в данном режиме
Свойству "current" можно присваивать значение типа int (индекс строки). Свойству "current" можно присваивать значение типа int (индекс строки).
Получить значение данного Свойства можно с помощью функции Получить значение данного свойства можно с помощью функции
func GetTableCurrent(view View, subviewID ...string) CellIndex func GetTableCurrent(view View, subviewID ...string) CellIndex
@ -3869,7 +3965,7 @@ CanvasView это область в которой вы можете рисов
func NewCanvasView(session Session, params Params) CanvasView func NewCanvasView(session Session, params Params) CanvasView
CanvasView имеет всего одно дополнительное Свойство: "draw-function" (константа DrawFunction). CanvasView имеет всего одно дополнительное Свойство: "draw-function" (константа DrawFunction).
С помощью данного Свойства задается функция рисования имеющая следующее описание С помощью данного свойства задается функция рисования имеющая следующее описание
func(Canvas) func(Canvas)

102
README.md
View File

@ -1195,6 +1195,47 @@ Can be one of the following int values:
* ImageVerticalAlign, * ImageVerticalAlign,
### "background-blend-mode" property
The "background-blend-mode" int property (BackgroundBlendMode constant)sets how an view's background images should blend
with each other and with the view's background color.
Can take one of the following values:
| Constant | Value | Name | Description |
|-----------------|:-----:|--------------|------------------------------------------------------------------|
| BlendNormal | 0 | "normal" | The final color is the top color, regardless of what the bottom color is. The effect is like two opaque pieces of paper overlapping. |
| BlendMultiply | 1 | "multiply" | The final color is the result of multiplying the top and bottom colors. A black layer leads to a black final layer, and a white layer leads to no change. The effect is like two images printed on transparent film overlapping. |
| BlendScreen | 2 | "screen" | The final color is the result of inverting the colors, multiplying them, and inverting that value. A black layer leads to no change, and a white layer leads to a white final layer. The effect is like two images shone onto a projection screen. |
| BlendOverlay | 3 | "overlay" | The final color is the result of multiply if the bottom color is darker, or screen if the bottom color is lighter. This blend mode is equivalent to hard-light but with the layers swapped. |
| BlendDarken | 4 | "darken" | The final color is composed of the darkest values of each color channel. |
| BlendLighten | 5 | "lighten" | The final color is composed of the lightest values of each color channel. |
| BlendColorDodge | 6 | "color-dodge"| The final color is the result of dividing the bottom color by the inverse of the top color. A black foreground leads to no change. A foreground with the inverse color of the backdrop leads to a fully lit color. This blend mode is similar to screen, but the foreground need only be as light as the inverse of the backdrop to create a fully lit color. |
| BlendColorBurn | 7 | "color-burn" | The final color is the result of inverting the bottom color, dividing the value by the top color, and inverting that value. A white foreground leads to no change. A foreground with the inverse color of the backdrop leads to a black final image. This blend mode is similar to multiply, but the foreground need only be as dark as the inverse of the backdrop to make the final image black. |
| BlendHardLight | 8 | "hard-light" | The final color is the result of multiply if the top color is darker, or screen if the top color is lighter. This blend mode is equivalent to overlay but with the layers swapped. The effect is similar to shining a harsh spotlight on the backdrop. |
| BlendSoftLight | 9 | "soft-light" | The final color is similar to hard-light, but softer. This blend mode behaves similar to hard-light. The effect is similar to shining a diffused spotlight on the backdrop*.* |
| BlendDifference | 10 | "difference" | The final color is the result of subtracting the darker of the two colors from the lighter one. A black layer has no effect, while a white layer inverts the other layer's color. |
| BlendExclusion | 11 | "exclusion" | The final color is similar to difference, but with less contrast. As with difference, a black layer has no effect, while a white layer inverts the other layer's color. |
| BlendHue | 12 | "hue" | The final color has the hue of the top color, while using the saturation and luminosity of the bottom color. |
| BlendSaturation | 13 | "saturation" | The final color has the saturation of the top color, while using the hue and luminosity of the bottom color. A pure gray backdrop, having no saturation, will have no effect. |
| BlendColor | 14 | "color" | The final color has the hue and saturation of the top color, while using the luminosity of the bottom color. The effect preserves gray levels and can be used to colorize the foreground. |
| BlendLuminosity | 15 | "luminosity" | The final color has the luminosity of the top color, while using the hue and saturation of the bottom color. This blend mode is equivalent to BlendColor, but with the layers swapped. |
You can get the value of this property using the function
func GetBackgroundBlendMode(view View, subviewID ...string) int
### "mix-blend-mode" property
The "mix-blend-mode" int property (MixBlendMode constant) sets how a view's content should blend
with the content of the view's parent and the view's background.
Possible values of this property are similar to the values of the "background-blend-mode" property (see above)
You can get the value of this property using the function
func GetMixBlendMode(view View, subviewID ...string) int
### "clip" property ### "clip" property
The "clip" property (Clip constant) of the ClipShape type specifies the crop area. The "clip" property (Clip constant) of the ClipShape type specifies the crop area.
@ -1257,13 +1298,29 @@ The textual description of the polygonal cropping area is in the following forma
### "opacity" property ### "opacity" property
The "opacity" property (constant Opacity) of the float64 type sets the transparency of the View. Valid values are from 0 to 1. The "opacity" property (Opacity constant) of the float64 type sets the transparency of the View. Valid values are from 0 to 1.
Where 1 - View is fully opaque, 0 - fully transparent. Where 1 - View is fully opaque, 0 - fully transparent.
You can get the value of this property using the function You can get the value of this property using the function
func GetOpacity(view View, subviewID ...string) float64 func GetOpacity(view View, subviewID ...string) float64
### "tabindex" property
The "tabindex" int property (TabIndex constant) determines whether this View should participate in sequential navigation
throughout the page using the keyboard and in what order. It can take one of the following types of values:
* negative value - View can be selected with the mouse or touch, but does not participate in sequential navigation;
* 0 - View can be selected and reached using sequential navigation, the order of navigation is determined by the browser (usually in order of addition);
* positive value - the element will be reached (and selected) using sequential navigation, and navigation is performed by ascending "tabindex" value.
If multiple elements contain the same "tabindex" value, navigation is done in the order in which they were added.
You can get the value of this property using the function
func GetTabIndex(viewView, subviewID ...string) int
### "z-index" property ### "z-index" property
The "z-index" property (constant ZIndex) of type int defines the position of the element and its children along the z-axis. The "z-index" property (constant ZIndex) of type int defines the position of the element and its children along the z-axis.
@ -2238,6 +2295,17 @@ alignment of items in the list. Valid values:
The "list-row-gap" and "list-column-gap" SizeUnit properties (ListRowGap and ListColumnGap constants) 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. allow you to set the distance between the rows and columns of the container, respectively. The default is 0px.
### "order"
The "order" property (Order constant) of type int is used by Views placed in a ListLayout or GridLayout container (see below),
to change its position in the container.
The "order" property defines the order used to place the View in the container. The elements are arranged in ascending order by their order value.
Elements with the same order value are placed in the order in which they were added to the container.
The default value is 0. Therefore, negative values of the "order" property must be used to place the View at the beginning.
Note: The "order" property only affects the visual order of the elements, not the logical order or tabs.
## 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
@ -2428,7 +2496,7 @@ which implements the Properties interface (see above). ColumnSeparatorProperty c
Line style can take the following values: Line style can take the following values:
| Value | Constant | Name | Description | | Value | Constant | Name | Description |
|:-----:|------------|----------| ------------------| |:-----:|------------|----------|-------------------|
| 0 | NoneLine | "none" | No frame | | 0 | NoneLine | "none" | No frame |
| 1 | SolidLine | "solid" | Solid line | | 1 | SolidLine | "solid" | Solid line |
| 2 | DashedLine | "dashed" | Dashed line | | 2 | DashedLine | "dashed" | Dashed line |
@ -2482,6 +2550,20 @@ equivalent to
rui.ColorProperty: rui.Black, rui.ColorProperty: rui.Black,
})) }))
### "column-fill" property
The "column-fill" int property (ColumnFill constant) controls how an ColumnLayout's contents are balanced when broken into columns.
Valid values:
| Value | Constant | Name | Description |
|:-----:|-------------------|-----------|------------------------------------------------------------|
| 0 | ColumnFillBalance | "balance" | Content is equally divided between columns (default value) |
| 1 | ColumnFillAuto | "auto" | Columns are filled sequentially. Content takes up only the room it needs, possibly resulting in some columns remaining empty |
You can get the value of this property using the function
func GetColumnFill(view View, subviewID ...string) int
### "avoid-break" property ### "avoid-break" property
When forming columns, ColumnLayout can break some types of View, so that the beginning When forming columns, ColumnLayout can break some types of View, so that the beginning
@ -2497,6 +2579,20 @@ You can get the value of this property using the function
func GetAvoidBreak(view View, subviewID ...string) bool func GetAvoidBreak(view View, subviewID ...string) bool
### "column-span-all" property
The "column-span-all" bool property (ColumnSpanAll constant) is set for Views placed in the ColumnLayout.
If this property is set to true, then the View expands to the full width of the ColumnLayout, covering all columns.
Such a View will, as it were, break the container.
Typically, this property is used for headers.
The default value is "false".
You can get the value of this property using the function
func IsColumnSpanAll(view View, subviewID ...string) bool
## StackLayout ## StackLayout
StackLayout is a container that implements the ViewsContainer interface. StackLayout is a container that implements the ViewsContainer interface.
@ -2739,7 +2835,7 @@ It determines how the text is cut if it goes out of bounds.
This property of type int can take the following values This property of type int can take the following values
| Value | Constant | Name | Cropping Text | | Value | Constant | Name | Cropping Text |
|:-----:|----------------------| -----------|-------------------------------------------------------------| |:-----:|----------------------|------------|-------------------------------------------------------------|
| 0 | TextOverflowClip | "clip" | Text is clipped at the border (default) | | 0 | TextOverflowClip | "clip" | Text is clipped at the border (default) |
| 1 | TextOverflowEllipsis | "ellipsis" | At the end of the visible part of the text '…' is displayed | | 1 | TextOverflowEllipsis | "ellipsis" | At the end of the visible part of the text '…' is displayed |

View File

@ -52,6 +52,24 @@ function sessionInfo() {
message += ",pixel-ratio=" + pixelRatio; message += ",pixel-ratio=" + pixelRatio;
} }
if (localStorage.length > 0) {
message += ",storage="
lead = "_{"
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i)
var value = localStorage.getItem(key)
key = key.replaceAll(/\\/g, "\\\\")
key = key.replaceAll(/\"/g, "\\\"")
key = key.replaceAll(/\'/g, "\\\'")
value = value.replaceAll(/\\/g, "\\\\")
value = value.replaceAll(/\"/g, "\\\"")
value = value.replaceAll(/\'/g, "\\\'")
message += lead + "\"" + key + "\"=\"" + value + "\""
lead = ","
}
message += "}"
}
return message + "}"; return message + "}";
} }
@ -408,6 +426,7 @@ function mouseOutEvent(element, event) {
function clickEvent(element, event) { function clickEvent(element, event) {
mouseEvent(element, event, "click-event") mouseEvent(element, event, "click-event")
event.preventDefault(); event.preventDefault();
event.stopPropagation();
} }
function doubleClickEvent(element, event) { function doubleClickEvent(element, event) {
@ -940,8 +959,8 @@ function radioButtonKeyClickEvent(element, event) {
function editViewInputEvent(element) { function editViewInputEvent(element) {
var text = element.value var text = element.value
text = text.replace(/\\/g, "\\\\") text = text.replaceAll(/\\/g, "\\\\")
text = text.replace(/\"/g, "\\\"") text = text.replaceAll(/\"/g, "\\\"")
var message = "textChanged{session=" + sessionID + ",id=" + element.id + ",text=\"" + text + "\"}" var message = "textChanged{session=" + sessionID + ",id=" + element.id + ",text=\"" + text + "\"}"
sendMessage(message); sendMessage(message);
} }
@ -1147,7 +1166,7 @@ function loadImage(url) {
img.addEventListener("error", function(event) { img.addEventListener("error", function(event) {
var message = "imageError{session=" + sessionID + ",url=\"" + url + "\""; var message = "imageError{session=" + sessionID + ",url=\"" + url + "\"";
if (event && event.message) { if (event && event.message) {
var text = event.message.replace(new RegExp("\"", 'g'), "\\\"") var text = event.message.replaceAll(new RegExp("\"", 'g'), "\\\"")
message += ",message=\"" + text + "\""; message += ",message=\"" + text + "\"";
} }
sendMessage(message + "}") sendMessage(message + "}")
@ -1178,7 +1197,7 @@ function loadInlineImage(url, content) {
img.addEventListener("error", function(event) { img.addEventListener("error", function(event) {
var message = "imageError{session=" + sessionID + ",url=\"" + url + "\""; var message = "imageError{session=" + sessionID + ",url=\"" + url + "\"";
if (event && event.message) { if (event && event.message) {
var text = event.message.replace(new RegExp("\"", 'g'), "\\\"") var text = event.message.replaceAll(new RegExp("\"", 'g'), "\\\"")
message += ",message=\"" + text + "\""; message += ",message=\"" + text + "\"";
} }
sendMessage(message + "}") sendMessage(message + "}")
@ -1842,3 +1861,19 @@ function getCanvasContext(elementId) {
} }
return null; return null;
} }
function localStorageSet(key, value) {
try {
localStorage.setItem(key, value)
} catch (err) {
sendMessage("storageError{session=" + sessionID + ", error=`" + err + "`}")
}
}
function localStorageClear() {
try {
localStorage.setItem(key, value)
} catch (err) {
sendMessage("storageError{session=" + sessionID + ", error=`" + err + "`}")
}
}

View File

@ -286,7 +286,7 @@ func (border *borderProperty) setBorderObject(obj DataObject) bool {
result := true result := true
for _, side := range []string{Top, Right, Bottom, Left} { for _, side := range []string{Top, Right, Bottom, Left} {
if node := obj.PropertyWithTag(side); node != nil { if node := obj.PropertyByTag(side); node != nil {
if node.Type() == ObjectNode { if node.Type() == ObjectNode {
if !border.setSingleBorderObject(side, node.Object()) { if !border.setSingleBorderObject(side, node.Object()) {
result = false result = false

View File

@ -11,28 +11,45 @@ const (
// Values less than zero are not valid. if the "column-count" property value is 0 then // Values less than zero are not valid. if the "column-count" property value is 0 then
// the number of columns is calculated based on the "column-width" property // the number of columns is calculated based on the "column-width" property
ColumnCount = "column-count" ColumnCount = "column-count"
// ColumnWidth is the constant for the "column-width" property tag. // ColumnWidth is the constant for the "column-width" property tag.
// The "column-width" SizeUnit property specifies the width of each column. // The "column-width" SizeUnit property specifies the width of each column.
ColumnWidth = "column-width" ColumnWidth = "column-width"
// ColumnGap is the constant for the "column-gap" property tag. // ColumnGap is the constant for the "column-gap" property tag.
// The "column-width" SizeUnit property sets the size of the gap (gutter) between columns. // The "column-width" SizeUnit property sets the size of the gap (gutter) between columns.
ColumnGap = "column-gap" ColumnGap = "column-gap"
// ColumnSeparator is the constant for the "column-separator" property tag. // ColumnSeparator is the constant for the "column-separator" property tag.
// The "column-separator" property specifies the line drawn between columns in a multi-column layout. // The "column-separator" property specifies the line drawn between columns in a multi-column layout.
ColumnSeparator = "column-separator" ColumnSeparator = "column-separator"
// ColumnSeparatorStyle is the constant for the "column-separator-style" property tag. // ColumnSeparatorStyle is the constant for the "column-separator-style" property tag.
// The "column-separator-style" int property sets the style of the line drawn between // The "column-separator-style" int property sets the style of the line drawn between
// columns in a multi-column layout. // columns in a multi-column layout.
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4). // Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
ColumnSeparatorStyle = "column-separator-style" ColumnSeparatorStyle = "column-separator-style"
// ColumnSeparatorWidth is the constant for the "column-separator-width" property tag. // ColumnSeparatorWidth is the constant for the "column-separator-width" property tag.
// The "column-separator-width" SizeUnit property sets the width of the line drawn between // The "column-separator-width" SizeUnit property sets the width of the line drawn between
// columns in a multi-column layout. // columns in a multi-column layout.
ColumnSeparatorWidth = "column-separator-width" ColumnSeparatorWidth = "column-separator-width"
// ColumnSeparatorColor is the constant for the "column-separator-color" property tag. // ColumnSeparatorColor is the constant for the "column-separator-color" property tag.
// The "column-separator-color" Color property sets the color of the line drawn between // The "column-separator-color" Color property sets the color of the line drawn between
// columns in a multi-column layout. // columns in a multi-column layout.
ColumnSeparatorColor = "column-separator-color" ColumnSeparatorColor = "column-separator-color"
// ColumnFill is the constant for the "column-fill" property tag.
// The "column-fill" int property controls how an ColumnLayout's contents are balanced when broken into columns.
// Valid values are
// * ColumnFillBalance (0) - Content is equally divided between columns (default value);
// * ColumnFillAuto (1) - Columns are filled sequentially. Content takes up only the room it needs, possibly resulting in some columns remaining empty.
ColumnFill = "column-fill"
// ColumnSpanAll is the constant for the "column-span-all" property tag.
// The "column-span-all" bool property makes it possible for a view to span across all columns when its value is set to true.
ColumnSpanAll = "column-span-all"
) )
// ColumnLayout - grid-container of View // ColumnLayout - grid-container of View
@ -206,3 +223,16 @@ func GetColumnSeparatorColor(view View, subviewID ...string) Color {
border := getColumnSeparator(view, subviewID) border := getColumnSeparator(view, subviewID)
return border.Color return border.Color
} }
// GetColumnFill returns a "column-fill" property value of the subview.
// Returns one of next values: ColumnFillBalance (0) or ColumnFillAuto (1)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetColumnFill(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, ColumnFill, ColumnFillBalance, true)
}
// IsColumnSpanAll returns a "column-span-all" property value of the subview.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func IsColumnSpanAll(view View, subviewID ...string) bool {
return boolStyledProperty(view, subviewID, ColumnSpanAll, false)
}

View File

@ -18,7 +18,7 @@ type DataObject interface {
Tag() string Tag() string
PropertyCount() int PropertyCount() int
Property(index int) DataNode Property(index int) DataNode
PropertyWithTag(tag string) DataNode PropertyByTag(tag string) DataNode
PropertyValue(tag string) (string, bool) PropertyValue(tag string) (string, bool)
PropertyObject(tag string) DataObject PropertyObject(tag string) DataObject
SetPropertyValue(tag, value string) SetPropertyValue(tag, value string)
@ -106,7 +106,7 @@ func (object *dataObject) Property(index int) DataNode {
return object.property[index] return object.property[index]
} }
func (object *dataObject) PropertyWithTag(tag string) DataNode { func (object *dataObject) PropertyByTag(tag string) DataNode {
if object.property != nil { if object.property != nil {
for _, node := range object.property { for _, node := range object.property {
if node.Tag() == tag { if node.Tag() == tag {
@ -118,14 +118,14 @@ func (object *dataObject) PropertyWithTag(tag string) DataNode {
} }
func (object *dataObject) PropertyValue(tag string) (string, bool) { func (object *dataObject) PropertyValue(tag string) (string, bool) {
if node := object.PropertyWithTag(tag); node != nil && node.Type() == TextNode { if node := object.PropertyByTag(tag); node != nil && node.Type() == TextNode {
return node.Text(), true return node.Text(), true
} }
return "", false return "", false
} }
func (object *dataObject) PropertyObject(tag string) DataObject { func (object *dataObject) PropertyObject(tag string) DataObject {
if node := object.PropertyWithTag(tag); node != nil && node.Type() == ObjectNode { if node := object.PropertyByTag(tag); node != nil && node.Type() == ObjectNode {
return node.Object() return node.Object()
} }
return nil return nil

View File

@ -270,7 +270,7 @@ func (picker *filePickerData) htmlDisabledProperties(self View, buffer *strings.
func (picker *filePickerData) handleCommand(self View, command string, data DataObject) bool { func (picker *filePickerData) handleCommand(self View, command string, data DataObject) bool {
switch command { switch command {
case "fileSelected": case "fileSelected":
if node := data.PropertyWithTag("files"); node != nil && node.Type() == ArrayNode { if node := data.PropertyByTag("files"); node != nil && node.Type() == ArrayNode {
count := node.ArraySize() count := node.ArraySize()
files := make([]FileInfo, count) files := make([]FileInfo, count)
for i := 0; i < count; i++ { for i := 0; i < count; i++ {

View File

@ -669,4 +669,33 @@ const (
// The "user-select" bool property controls whether the user can select text. // The "user-select" bool property controls whether the user can select text.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used. // This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
UserSelect = "user-select" UserSelect = "user-select"
// Order is the constant for the "Order" property tag.
// The "Order" int property sets the order to layout an item in a ListLayout or GridLayout container.
// Items in a container are sorted by ascending order value and then by their source code order.
Order = "Order"
// BackgroundBlendMode is the constant for the "background-blend-mode" property tag.
// The "background-blend-mode" int property sets how an view's background images should blend
// with each other and with the view's background color.
// Valid values are "normal" (0), "multiply" (1), "screen" (2), "overlay" (3), "darken" (4), "lighten" (5),
// "color-dodge" (6), "color-burn" (7), "hard-light" (8), "soft-light" (9), "difference" (10),
// "exclusion" (11), "hue" (12), "saturation" (13), "color" (14), "luminosity" (15).
BackgroundBlendMode = "background-blend-mode"
// MixBlendMode is the constant for the "mix-blend-mode" property tag.
// The "mix-blend-mode" int property sets how a view's content should blend
// with the content of the view's parent and the view's background.
// Valid values are "normal" (0), "multiply" (1), "screen" (2), "overlay" (3), "darken" (4), "lighten" (5),
// "color-dodge" (6), "color-burn" (7), "hard-light" (8), "soft-light" (9), "difference" (10),
// "exclusion" (11), "hue" (12), "saturation" (13), "color" (14), "luminosity" (15).
MixBlendMode = "mix-blend-mode"
// TabIndex is the constant for the "tabindex" property tag.
// The "tabindex" int property indicates that View can be focused, and where it participates in sequential keyboard navigation
// (usually with the Tab key, hence the name).
// * A negative value means that View is not reachable via sequential keyboard navigation, but could be focused by clicking with the mouse or touching.
// * tabindex="0" means that View should be focusable in sequential keyboard navigation, after any positive tabindex values and its order is defined in order of its addition.
// * A positive value means View should be focusable in sequential keyboard navigation, with its order defined by the value of the number.
TabIndex = "tabindex"
) )

View File

@ -63,6 +63,7 @@ var boolProperties = []string{
TabCloseButton, TabCloseButton,
Repeating, Repeating,
UserSelect, UserSelect,
ColumnSpanAll,
} }
var intProperties = []string{ var intProperties = []string{
@ -73,6 +74,8 @@ var intProperties = []string{
RowSpan, RowSpan,
ColumnSpan, ColumnSpan,
ColumnCount, ColumnCount,
Order,
TabIndex,
} }
var floatProperties = map[string]struct{ min, max float64 }{ var floatProperties = map[string]struct{ min, max float64 }{
@ -447,6 +450,21 @@ var enumProperties = map[string]struct {
"", "",
[]string{"none", "top", "right", "bottom", "left"}, []string{"none", "top", "right", "bottom", "left"},
}, },
MixBlendMode: {
[]string{"normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"},
MixBlendMode,
[]string{"normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"},
},
BackgroundBlendMode: {
[]string{"normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"},
BackgroundBlendMode,
[]string{"normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"},
},
ColumnFill: {
[]string{"balance", "auto"},
ColumnFill,
[]string{"balance", "auto"},
},
} }
func notCompatibleType(tag string, value any) { func notCompatibleType(tag string, value any) {

View File

@ -307,4 +307,92 @@ const (
// "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later. // "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later.
// This may cause views to appear out-of-order, when doing so would fill in holes left by larger views. // This may cause views to appear out-of-order, when doing so would fill in holes left by larger views.
ColumnDenseAutoFlow = 3 ColumnDenseAutoFlow = 3
// BlendNormal - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the top color, regardless of what the bottom color is.
// The effect is like two opaque pieces of paper overlapping.
BlendNormal = 0
// BlendMultiply - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the result of multiplying the top and bottom colors.
// A black layer leads to a black final layer, and a white layer leads to no change.
// The effect is like two images printed on transparent film overlapping.
BlendMultiply = 1
// BlendScreen - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the result of inverting the colors, multiplying them, and inverting that value.
// A black layer leads to no change, and a white layer leads to a white final layer.
// The effect is like two images shone onto a projection screen.
BlendScreen = 2
// BlendOverlay - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the result of multiply if the bottom color is darker, or screen if the bottom color is lighter.
// This blend mode is equivalent to hard-light but with the layers swapped.
BlendOverlay = 3
// BlendDarken - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is composed of the darkest values of each color channel.
BlendDarken = 4
// BlendLighten - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is composed of the lightest values of each color channel.
BlendLighten = 5
// BlendColorDodge - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the result of dividing the bottom color by the inverse of the top color.
// A black foreground leads to no change. A foreground with the inverse color of the backdrop leads to a fully lit color.
// This blend mode is similar to screen, but the foreground need only be as light as the inverse of the backdrop to create a fully lit color.
BlendColorDodge = 6
// BlendColorBurn - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the result of inverting the bottom color, dividing the value by the top color, and inverting that value.
// A white foreground leads to no change. A foreground with the inverse color of the backdrop leads to a black final image.
// This blend mode is similar to multiply, but the foreground need only be as dark as the inverse of the backdrop to make the final image black.
BlendColorBurn = 7
// BlendHardLight - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the result of multiply if the top color is darker, or screen if the top color is lighter.
// This blend mode is equivalent to overlay but with the layers swapped. The effect is similar to shining a harsh spotlight on the backdrop.
BlendHardLight = 8
// BlendSoftLight - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is similar to hard-light, but softer. This blend mode behaves similar to hard-light.
// The effect is similar to shining a diffused spotlight on the backdrop*.*
BlendSoftLight = 9
// BlendDifference - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is the result of subtracting the darker of the two colors from the lighter one.
// A black layer has no effect, while a white layer inverts the other layer's color.
BlendDifference = 10
// BlendExclusion - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color is similar to difference, but with less contrast.
// As with difference, a black layer has no effect, while a white layer inverts the other layer's color.
BlendExclusion = 11
// BlendHue - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color has the hue of the top color, while using the saturation and luminosity of the bottom color.
BlendHue = 12
// BlendSaturation - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color has the saturation of the top color, while using the hue and luminosity of the bottom color.
// A pure gray backdrop, having no saturation, will have no effect.
BlendSaturation = 13
// BlendColor - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color has the hue and saturation of the top color, while using the luminosity of the bottom color.
// The effect preserves gray levels and can be used to colorize the foreground.
BlendColor = 14
// BlendLuminosity - value of the "mix-blend-mode" and "background-blend-mode" property:
// The final color has the luminosity of the top color, while using the hue and saturation of the bottom color.
// This blend mode is equivalent to BlendColor, but with the layers swapped.
BlendLuminosity = 15
// ColumnFillBalance - value of the "column-fill" property: content is equally divided between columns.
ColumnFillBalance = 0
// ColumnFillAuto - value of the "column-fill" property:
// Columns are filled sequentially. Content takes up only the room it needs, possibly resulting in some columns remaining empty.
ColumnFillAuto = 1
) )

View File

@ -100,6 +100,10 @@ type Session interface {
// OpenURL opens the url in the new browser tab // OpenURL opens the url in the new browser tab
OpenURL(url string) OpenURL(url string)
ClientItem(key string) (string, bool)
SetClientItem(key, value string)
RemoveAllClientItems()
getCurrentTheme() Theme getCurrentTheme() Theme
registerAnimation(props []AnimatedProperty) string registerAnimation(props []AnimatedProperty) string
@ -183,6 +187,7 @@ type sessionData struct {
animationCounter int animationCounter int
animationCSS string animationCSS string
updateScripts map[string]*strings.Builder updateScripts map[string]*strings.Builder
clientStorage map[string]string
} }
func newSession(app Application, id int, customTheme string, params DataObject) Session { func newSession(app Application, id int, customTheme string, params DataObject) Session {
@ -199,6 +204,7 @@ func newSession(app Application, id int, customTheme string, params DataObject)
session.animationCounter = 0 session.animationCounter = 0
session.animationCSS = "" session.animationCSS = ""
session.updateScripts = map[string]*strings.Builder{} session.updateScripts = map[string]*strings.Builder{}
session.clientStorage = map[string]string{}
if customTheme != "" { if customTheme != "" {
if theme, ok := CreateThemeFromText(customTheme); ok { if theme, ok := CreateThemeFromText(customTheme); ok {
@ -516,7 +522,7 @@ func (session *sessionData) handleRootSize(data DataObject) {
} }
func (session *sessionData) handleResize(data DataObject) { func (session *sessionData) handleResize(data DataObject) {
if node := data.PropertyWithTag("views"); node != nil && node.Type() == ArrayNode { if node := data.PropertyByTag("views"); node != nil && node.Type() == ArrayNode {
for _, el := range node.ArrayElements() { for _, el := range node.ArrayElements() {
if el.IsObject() { if el.IsObject() {
obj := el.Object() obj := el.Object()
@ -591,6 +597,16 @@ func (session *sessionData) handleSessionInfo(params DataObject) {
session.pixelRatio = f session.pixelRatio = f
} }
} }
if node := params.PropertyByTag("storage"); node != nil && node.Type() == ObjectNode {
if obj := node.Object(); obj != nil {
for i := 0; i < obj.PropertyCount(); i++ {
if element := obj.Property(i); element.Type() == TextNode {
session.clientStorage[element.Tag()] = element.Text()
}
}
}
}
} }
func (session *sessionData) handleEvent(command string, data DataObject) { func (session *sessionData) handleEvent(command string, data DataObject) {
@ -610,6 +626,11 @@ func (session *sessionData) handleEvent(command string, data DataObject) {
case "sessionInfo": case "sessionInfo":
session.handleSessionInfo(data) session.handleSessionInfo(data)
case "storageError":
if text, ok := data.PropertyValue("error"); ok {
ErrorLog(text)
}
default: default:
if viewID, ok := data.PropertyValue("id"); ok { if viewID, ok := data.PropertyValue("id"); ok {
if view := session.viewByHTMLID(viewID); view != nil { if view := session.viewByHTMLID(viewID); view != nil {
@ -641,3 +662,18 @@ func (session *sessionData) OpenURL(urlStr string) {
} }
session.callFunc("openURL", urlStr) session.callFunc("openURL", urlStr)
} }
func (session *sessionData) ClientItem(key string) (string, bool) {
value, ok := session.clientStorage[key]
return value, ok
}
func (session *sessionData) SetClientItem(key, value string) {
session.clientStorage[key] = value
session.bridge.callFunc("localStorageSet", key, value)
}
func (session *sessionData) RemoveAllClientItems() {
session.clientStorage = map[string]string{}
session.bridge.callFunc("localStorageClear")
}

View File

@ -606,7 +606,8 @@ func (table *tableViewData) propertyChanged(tag string) {
switch GetTableSelectionMode(table) { switch GetTableSelectionMode(table) {
case CellSelection: case CellSelection:
session.updateProperty(htmlID, "tabindex", "0") tabIndex, _ := intProperty(table, TabIndex, session, 0)
session.updateProperty(htmlID, "tabindex", tabIndex)
session.updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)") session.updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)")
session.updateProperty(htmlID, "onblur", "tableViewBlurEvent(this, event)") session.updateProperty(htmlID, "onblur", "tableViewBlurEvent(this, event)")
session.updateProperty(htmlID, "data-selection", "cell") session.updateProperty(htmlID, "data-selection", "cell")
@ -621,7 +622,8 @@ func (table *tableViewData) propertyChanged(tag string) {
session.updateProperty(htmlID, "onkeydown", "tableViewCellKeyDownEvent(this, event)") session.updateProperty(htmlID, "onkeydown", "tableViewCellKeyDownEvent(this, event)")
case RowSelection: case RowSelection:
session.updateProperty(htmlID, "tabindex", "0") tabIndex, _ := intProperty(table, TabIndex, session, 0)
session.updateProperty(htmlID, "tabindex", tabIndex)
session.updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)") session.updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)")
session.updateProperty(htmlID, "onblur", "tableViewBlurEvent(this, event)") session.updateProperty(htmlID, "onblur", "tableViewBlurEvent(this, event)")
session.updateProperty(htmlID, "data-selection", "row") session.updateProperty(htmlID, "data-selection", "row")
@ -636,7 +638,11 @@ func (table *tableViewData) propertyChanged(tag string) {
session.updateProperty(htmlID, "onkeydown", "tableViewRowKeyDownEvent(this, event)") session.updateProperty(htmlID, "onkeydown", "tableViewRowKeyDownEvent(this, event)")
default: // NoneSelection default: // NoneSelection
for _, prop := range []string{"tabindex", "data-current", "onfocus", "onblur", "onkeydown", "data-selection"} { if tabIndex, ok := intProperty(table, TabIndex, session, -1); !ok || tabIndex < 0 {
session.removeProperty(htmlID, "tabindex")
}
for _, prop := range []string{"data-current", "onfocus", "onblur", "onkeydown", "data-selection"} {
session.removeProperty(htmlID, prop) session.removeProperty(htmlID, prop)
} }
} }
@ -831,7 +837,7 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
var view tableCellView var view tableCellView
view.init(session) view.init(session)
ignorCells := []struct{ row, column int }{} ignoreCells := []struct{ row, column int }{}
selectionMode := GetTableSelectionMode(table) selectionMode := GetTableSelectionMode(table)
var allowCellSelection TableAllowCellSelection = nil var allowCellSelection TableAllowCellSelection = nil
@ -908,7 +914,7 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
for column := 0; column < columnCount; column++ { for column := 0; column < columnCount; column++ {
ignore := false ignore := false
for _, cell := range ignorCells { for _, cell := range ignoreCells {
if cell.row == row && cell.column == column { if cell.row == row && cell.column == column {
ignore = true ignore = true
break break
@ -994,7 +1000,7 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
buffer.WriteString(strconv.Itoa(columnSpan)) buffer.WriteString(strconv.Itoa(columnSpan))
buffer.WriteRune('"') buffer.WriteRune('"')
for c := column + 1; c < column+columnSpan; c++ { for c := column + 1; c < column+columnSpan; c++ {
ignorCells = append(ignorCells, struct { ignoreCells = append(ignoreCells, struct {
row int row int
column int column int
}{row: row, column: c}) }{row: row, column: c})
@ -1010,7 +1016,7 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
} }
for r := row + 1; r < row+rowSpan; r++ { for r := row + 1; r < row+rowSpan; r++ {
for c := column; c < column+columnSpan; c++ { for c := column; c < column+columnSpan; c++ {
ignorCells = append(ignorCells, struct { ignoreCells = append(ignoreCells, struct {
row int row int
column int column int
}{row: r, column: c}) }{row: r, column: c})

View File

@ -140,7 +140,7 @@ func (event *TouchEvent) init(data DataObject) {
event.Touches = []Touch{} event.Touches = []Touch{}
event.TimeStamp = getTimeStamp(data) event.TimeStamp = getTimeStamp(data)
if node := data.PropertyWithTag("touches"); node != nil && node.Type() == ArrayNode { if node := data.PropertyByTag("touches"); node != nil && node.Type() == ArrayNode {
for i := 0; i < node.ArraySize(); i++ { for i := 0; i < node.ArraySize(); i++ {
if element := node.ArrayElement(i); element != nil && element.IsObject() { if element := node.ArrayElement(i); element != nil && element.IsObject() {
if obj := element.Object(); obj != nil { if obj := element.Object(); obj != nil {

38
view.go
View File

@ -187,6 +187,14 @@ func (view *viewData) remove(tag string) {
case ID: case ID:
view.viewID = "" view.viewID = ""
case TabIndex, "tab-index":
delete(view.properties, tag)
if view.Focusable() {
view.session.updateProperty(view.htmlID(), "tabindex", "0")
} else {
view.session.updateProperty(view.htmlID(), "tabindex", "-1")
}
case UserData: case UserData:
delete(view.properties, tag) delete(view.properties, tag)
@ -312,6 +320,18 @@ func (view *viewData) set(tag string, value any) bool {
} }
view.viewID = text view.viewID = text
case TabIndex, "tab-index":
if !view.setIntProperty(tag, value) {
return false
}
if value, ok := intProperty(view, TabIndex, view.Session(), 0); ok {
view.session.updateProperty(view.htmlID(), "tabindex", strconv.Itoa(value))
} else if view.Focusable() {
view.session.updateProperty(view.htmlID(), "tabindex", "0")
} else {
view.session.updateProperty(view.htmlID(), "tabindex", "-1")
}
case UserData: case UserData:
view.properties[tag] = value view.properties[tag] = value
@ -577,7 +597,7 @@ func viewPropertyChanged(view *viewData, tag string) {
} }
return return
case ZIndex, TabSize: case ZIndex, Order, TabSize:
if i, ok := intProperty(view, tag, session, 0); ok { if i, ok := intProperty(view, tag, session, 0); ok {
session.updateCSSProperty(htmlID, tag, strconv.Itoa(i)) session.updateCSSProperty(htmlID, tag, strconv.Itoa(i))
} }
@ -606,6 +626,14 @@ func viewPropertyChanged(view *viewData, tag string) {
session.updateCSSProperty(htmlID, "user-select", "") session.updateCSSProperty(htmlID, "user-select", "")
} }
return return
case ColumnSpanAll:
if spanAll, ok := boolProperty(view, ColumnSpanAll, session); ok && spanAll {
session.updateCSSProperty(htmlID, `column-span`, `all`)
} else {
session.updateCSSProperty(htmlID, `column-span`, `none`)
}
return
} }
if cssTag, ok := sizeProperties[tag]; ok { if cssTag, ok := sizeProperties[tag]; ok {
@ -758,9 +786,15 @@ func viewHTML(view View, buffer *strings.Builder) {
buffer.WriteRune(' ') buffer.WriteRune(' ')
} }
if view.Focusable() && !disabled { if !disabled {
if value, ok := intProperty(view, TabIndex, view.Session(), -1); ok {
buffer.WriteString(`tabindex="`)
buffer.WriteString(strconv.Itoa(value))
buffer.WriteString(`" `)
} else if view.Focusable() {
buffer.WriteString(`tabindex="0" `) buffer.WriteString(`tabindex="0" `)
} }
}
buffer.WriteString(`onscroll="scrollEvent(this, event)" `) buffer.WriteString(`onscroll="scrollEvent(this, event)" `)

View File

@ -193,16 +193,20 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
outline.ViewOutline(session).cssValue(builder, session) outline.ViewOutline(session).cssValue(builder, session)
} }
if z, ok := intProperty(style, ZIndex, session, 0); ok { for _, tag := range []string{ZIndex, Order} {
builder.add(ZIndex, strconv.Itoa(z)) if value, ok := intProperty(style, tag, session, 0); ok {
builder.add(tag, strconv.Itoa(value))
}
} }
if opacity, ok := floatProperty(style, Opacity, session, 1.0); ok && opacity >= 0 && opacity <= 1 { if opacity, ok := floatProperty(style, Opacity, session, 1.0); ok && opacity >= 0 && opacity <= 1 {
builder.add(Opacity, strconv.FormatFloat(opacity, 'f', 3, 32)) builder.add(Opacity, strconv.FormatFloat(opacity, 'f', 3, 32))
} }
if n, ok := intProperty(style, ColumnCount, session, 0); ok && n > 0 { for _, tag := range []string{ColumnCount, TabSize} {
builder.add(ColumnCount, strconv.Itoa(n)) if value, ok := intProperty(style, tag, session, 0); ok && value > 0 {
builder.add(tag, strconv.Itoa(value))
}
} }
for _, tag := range []string{ for _, tag := range []string{
@ -248,7 +252,7 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
for _, tag := range []string{ for _, tag := range []string{
Overflow, TextAlign, TextTransform, TextWeight, TextLineStyle, WritingMode, TextDirection, Overflow, TextAlign, TextTransform, TextWeight, TextLineStyle, WritingMode, TextDirection,
VerticalTextOrientation, CellVerticalAlign, CellHorizontalAlign, GridAutoFlow, Cursor, VerticalTextOrientation, CellVerticalAlign, CellHorizontalAlign, GridAutoFlow, Cursor,
WhiteSpace, WordBreak, TextOverflow, Float, TableVerticalAlign, Resize} { WhiteSpace, WordBreak, TextOverflow, Float, TableVerticalAlign, Resize, MixBlendMode, BackgroundBlendMode} {
if data, ok := enumProperties[tag]; ok { if data, ok := enumProperties[tag]; ok {
if tag != VerticalTextOrientation || (writingMode != VerticalLeftToRight && writingMode != VerticalRightToLeft) { if tag != VerticalTextOrientation || (writingMode != VerticalLeftToRight && writingMode != VerticalRightToLeft) {
@ -279,10 +283,6 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
} }
} }
if tabSize, ok := intProperty(style, TabSize, session, 8); ok && tabSize > 0 {
builder.add(TabSize, strconv.Itoa(tabSize))
}
if text := style.cssTextDecoration(session); text != "" { if text := style.cssTextDecoration(session); text != "" {
builder.add("text-decoration", text) builder.add("text-decoration", text)
} }
@ -453,6 +453,14 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
builder.add(`animation-play-state`, `running`) builder.add(`animation-play-state`, `running`)
} }
} }
if spanAll, ok := boolProperty(style, ColumnSpanAll, session); ok {
if spanAll {
builder.add(`column-span`, `all`)
} else {
builder.add(`column-span`, `none`)
}
}
} }
func valueToOrientation(value any, session Session) (int, bool) { func valueToOrientation(value any, session Session) (int, bool) {

View File

@ -153,12 +153,37 @@ func GetOverflow(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, Overflow, defaultOverflow, false) return enumStyledProperty(view, subviewID, Overflow, defaultOverflow, false)
} }
// GetTabIndex returns the subview tab-index.
// If the second argument (subviewID) is not specified or it is "" then a tab-index of the first argument (view) is returned
func GetTabIndex(view View, subviewID ...string) int {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])
}
defaultValue := -1
if view != nil {
if view.Focusable() {
defaultValue = 0
}
if value, ok := intProperty(view, TabIndex, view.Session(), defaultValue); ok {
return value
}
}
return defaultValue
}
// GetZIndex returns the subview z-order. // GetZIndex returns the subview z-order.
// If the second argument (subviewID) is not specified or it is "" then a z-order of the first argument (view) is returned // If the second argument (subviewID) is not specified or it is "" then a z-order of the first argument (view) is returned
func GetZIndex(view View, subviewID ...string) int { func GetZIndex(view View, subviewID ...string) int {
return intStyledProperty(view, subviewID, ZIndex, 0) return intStyledProperty(view, subviewID, ZIndex, 0)
} }
// GetOrder returns the subview order to layout an item in a ListLayout or GridLayout container.
// If the second argument (subviewID) is not specified or it is "" then an order of the first argument (view) is returned
func GetOrder(view View, subviewID ...string) int {
return intStyledProperty(view, subviewID, Order, 0)
}
// GetWidth returns the subview width. // GetWidth returns the subview width.
// If the second argument (subviewID) is not specified or it is "" then a width of the first argument (view) is returned // If the second argument (subviewID) is not specified or it is "" then a width of the first argument (view) is returned
func GetWidth(view View, subviewID ...string) SizeUnit { func GetWidth(view View, subviewID ...string) SizeUnit {
@ -890,3 +915,27 @@ func isUserSelect(view View) (bool, bool) {
return false, false return false, false
} }
// GetMixBlendMode returns a "mix-blend-mode" of the subview. Returns one of next values:
//
// BlendNormal (0), BlendMultiply (1), BlendScreen (2), BlendOverlay (3), BlendDarken (4),
// BlendLighten (5), BlendColorDodge (6), BlendColorBurn (7), BlendHardLight (8),
// BlendSoftLight (9), BlendDifference (10), BlendExclusion (11), BlendHue (12),
// BlendSaturation (13), BlendColor (14), BlendLuminosity (15)
//
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetMixBlendMode(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, MixBlendMode, BlendNormal, true)
}
// GetBackgroundBlendMode returns a "background-blend-mode" of the subview. Returns one of next values:
//
// BlendNormal (0), BlendMultiply (1), BlendScreen (2), BlendOverlay (3), BlendDarken (4),
// BlendLighten (5), BlendColorDodge (6), BlendColorBurn (7), BlendHardLight (8),
// BlendSoftLight (9), BlendDifference (10), BlendExclusion (11), BlendHue (12),
// BlendSaturation (13), BlendColor (14), BlendLuminosity (15)
//
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetBackgroundBlendMode(view View, subviewID ...string) int {
return enumStyledProperty(view, subviewID, BackgroundBlendMode, BlendNormal, true)
}