forked from mbk-lab/rui_orig
2
0
Fork 0

Added some properties and functions

* Added "resize", "grid-auto-flow", "caret-color", and "backdrop-filter" properties
* Added BlurView, BlurViewByID, GetResize, GetGridAutoFlow, GetCaretColor, GetBackdropFilter functions
* The "warp" property for ListView and ListLayout renamed to "list-warp"
* The "warp" property for EditView renamed to "edit-warp"
* Added CertFile and KeyFile optional fields to the AppParams struct.If they are set, then an https connection is created, otherwise http.
This commit is contained in:
Alexei Anoshenko 2022-06-07 13:07:10 +03:00
parent b43bf80856
commit 73cd9318a5
30 changed files with 776 additions and 152 deletions

View File

@ -1,3 +1,11 @@
# v0.7.0
* Added "resize", "grid-auto-flow", "caret-color", and "backdrop-filter" properties
* Added BlurView, BlurViewByID, GetResize, GetGridAutoFlow, GetCaretColor, GetBackdropFilter functions
* The "warp" property for ListView and ListLayout renamed to "list-warp"
* The "warp" property for EditView renamed to "edit-warp"
* Added CertFile and KeyFile optional fields to the AppParams struct.If they are set, then an https connection is created, otherwise http.
# v0.6.0
* Added "user-data" property

View File

@ -550,6 +550,25 @@ SizeUnit или имя константы (о константах ниже):
func GetMaxWidth(view View, subviewID string) SizeUnit
func GetMaxHeight(view View, subviewID string) SizeUnit
### Свойство "resize"
Свойство "resize" (константа Resize) типа int устанавливает, можно ли изменить размер View,
и если да, то в каких направлениях. Допустимые значения
| Значение | Константа | Имя | Описание |
|:--------:|------------------|--------------|------------------------------|
| 0 | NoneResize | "none" | Нельзя изменять размер View. |
| 1 | BothResize | "both" | Отображается механизм, позволяющий пользователю изменять размер View как по горизонтали, так и по вертикали. |
| 2 | HorizontalResize | "horizontal" | Отображается механизм, позволяющий пользователю изменять размер View только по горизонтали. |
| 3 | VerticalResize | "vertical" | Отображается механизм, позволяющий пользователю изменять размер View только по вертикали. |
Значение по умолчанию для всех типов View кроме многострочного редактора текста это NoneResize (0).
Значение по умолчанию для многострочного редактора текста это BothResize (1).
Получить значение данного свойства можно с помощью функции
func GetResize(view View, subviewID string) int
### Свойства "margin" и "padding"
Свойство "margin" определяет внешние отступы от данного View до соседних.
@ -1241,10 +1260,12 @@ radius необходимо передать nil
func GetVisibility(view View, subviewID string) int
### Свойство "filter"
### Свойства "filter" и "backdrop-filter"
Свойство "filter" (константа Filter) применяет ко View такие графические эффекты, как размытие и смещение цвета.
В качестве значения свойства "filter" используется только интерфейс ViewFilter. ViewFilter создается с помощью
Свойство "filter" (константа Filter) применяет ко View такие графические эффекты, как размытие, смещение цвета, изменение яркости/контрасности и т.п.
Свойства "backdrop-filter" (константа BackdropFilter) применяет такие же эффекты но к содержимому располагающемося ниже View.
В качестве значения свойств "filter" и "backdrop-filter" используется только интерфейс ViewFilter. ViewFilter создается с помощью
функции
func NewViewFilter(params Params) ViewFilter
@ -1264,9 +1285,10 @@ radius необходимо передать nil
| "saturate" | Saturate | float64 0…10000% | Изменение насыщености |
| "sepia" | Sepia | float64 0…100% | Преобразование в серпию |
Получить значение текущего фильтра можно с помощью функции
Получить значение текущего фильтра можно с помощью функций
func GetFilter(view View, subviewID string) ViewFilter
func GetBackdropFilter(view View, subviewID string) ViewFilter
### Свойство "semantics"
@ -2125,17 +2147,17 @@ ListLayout является контейнером, реализующим ин
свойства "text-direction". Для языков с письмом справа налево (арабский, иврит) начало находится
справа, для остальных языков - слева.
### "wrap"
### "list-wrap"
Свойство "wrap" (константа Wrap) типа int определяет расположения элементов в случае достижения
Свойство "list-wrap" (константа ListWrap) типа int определяет расположения элементов в случае достижения
границы контейнера. Возможны три варианта:
* WrapOff (0) - колонка/строка элементов продолжается и выходит за границы видимой области.
* ListWrapOff (0) - колонка/строка элементов продолжается и выходит за границы видимой области.
* WrapOn (1) - начинается новая колонка/строка элементов. Новая колонка располагается по направлению
* ListWrapOn (1) - начинается новая колонка/строка элементов. Новая колонка располагается по направлению
к концу (о положении начала и конца см. выше), новая строка - снизу.
* WrapReverse (2) - начинается новая колонка/строка элементов. Новая колонка располагается по направлению
* ListWrapReverse (2) - начинается новая колонка/строка элементов. Новая колонка располагается по направлению
к началу (о положении начала и конца см. выше), новая строка - сверху.
### "vertical-align"
@ -2175,7 +2197,7 @@ GridLayout является контейнером, реализующим ин
### "column" и "row"
Расположение View внутри GridLayout определяется с помощью свойств "column" и "row".
Данные свойства должны устанавливаться для каждого из дочерних View.
Данные свойства устанавливаться для каждого из дочерних View.
Дочерний View может занимать несколько ячеек внутри GridLayout. При этом они могут
перекрываться.
@ -2212,6 +2234,22 @@ GridLayout является контейнером, реализующим ин
В данном примере view1 занимает в нулевой строке столбцы 1 и 2, а view1 занимает
в нулевом стобце строки 0, 1 и 2.
### "grid-auto-flow"
Если для дочерних View не задаются свойства "row" и "column", то используется автоматический алгоритм размещения элементов.
Возможны четыре варианта данного алгоритма. Используемый вариант задается с помощью свойства "grid-auto-flow" типа int.
ойство "grid-auto-flow" может принимать следующие значения:
* RowAutoFlow (0) (text name "row") - Views размещаются путем заполнения каждой строки по очереди, добавляя новые столбцы по мере необходимости;
* ColumnAutoFlow (1) (text name "colunm") - Views размещаются путем заполнения каждого столбца по очереди, добавляя новые столбцы по мере необходимости;
* RowDenseAutoFlow (2) (text name "row-dense") - Views размещаются путем заполнения каждой строки и добавления новых строк по мере необходимости.
Алгоритм «плотной» упаковки пытается заполнить дыры в сетке передвигая более мелкие View вперед очереди.
* ColumnDenseAutoFlow (3) (text name "column-dense") - Views размещаются путем заполнения каждого столбца, добавляя новые столбцы по мере необходимости.
Алгоритм «плотной» упаковки пытается заполнить дыры в сетке передвигая более мелкие View вперед очереди.
### "cell-width" и "cell-height"
По умолчанию размеры ячеек вычисляются на основе размеров помещенных в них дочерних View.
@ -2699,10 +2737,14 @@ string свойство "edit-view-pattern" (константа EditViewPattern)
Для этого используется string свойство "hint" (константа Hint).
Для многострочного редактора может быть включен режим автоматического переноса. Для
этого используется bool свойство "wrap" (константа Wrap). Если "wrap" выключен (значение по умолчанию),
этого используется bool свойство "edit-wrap" (константа EditWrap). Если "edit-wrap" выключен (значение по умолчанию),
то используется горизонтальная прокрутка. Если включен, то по достижении границы EditView
текст переносится на новую строку.
Для изменения цвета каретки ввода текста используется Color свойство "caret-color" (константа CaretColor).
ойство "caret-color" может быть задано не только для EditView, но и для любого контейнера. В этом случае
цвет каретки меняется для всех дочерних EditView помещенных в этот контейнер
Для получения значений свойств EditView могут использоваться следующие функции:
func GetText(view View, subviewID string) string
@ -2713,7 +2755,7 @@ string свойство "edit-view-pattern" (константа EditViewPattern)
func IsReadOnly(view View, subviewID string) bool
func IsEditViewWrap(view View, subviewID string) bool
func IsSpellcheck(view View, subviewID string) bool
func GetCaretColor(view View, subviewID string) Color
Для отслеживания изменения текста используется событие "edit-text-changed" (константа
EditTextChangedEvent). Основной слушатель события имеет следующий формат:

View File

@ -550,6 +550,25 @@ For the properties "width", "height", "min-width", "min-height", "max-width", "m
func GetMaxWidth(view View, subviewID string) SizeUnit
func GetMaxHeight(view View, subviewID string) SizeUnit
### "resize" property
The int "resize" property (Resize constant) sets whether the View can be resized, and if so, in which directions.
Valid values
|Value | Constant | Name | Description |
|:--------:|------------------|--------------|-------------------------|
| 0 | NoneResize | "none" | View cannot be resized. |
| 1 | BothResize | "both" | The View displays a mechanism for allowing the user to resize it, which may be resized both horizontally and vertically. |
| 2 | HorizontalResize | "horizontal" | The View displays a mechanism for allowing the user to resize it in the horizontal direction. |
| 3 | VerticalResize | "vertical" | The View displays a mechanism for allowing the user to resize it in the vertical direction. |
The default value for all View types except multiline text editor is NoneResize(0).
The default value for a multiline text editor is BothResize(1).
You can get the value of this property using the function
func GetResize(view View, subviewID string) int
### "margin" and "padding" properties
The "margin" property determines the outer margins from this View to its neighbors.
@ -1207,7 +1226,7 @@ You can get the value of this property using the function
### "visibility" property
The "visibility" property (constant Visibility) of type int specifies the visibility of the View. Valid values
The "visibility" int property (constant Visibility) specifies the visibility of the View. Valid values
| Value | Constant | Name | Visibility |
|:-----:|-----------|-------------|------------------------------------------------|
@ -1219,10 +1238,12 @@ You can get the value of this property using the function
func GetVisibility(view View, subviewID string) int
### "filter" property
### "filter" and "backdrop-filter" properties
The "filter" property (Filter constant) applies graphical effects such as blur and color shift to the View.
Only the ViewFilter interface is used as the value of the "filter" property.
The "filter" property (Filter constant) applies graphical effects to the View, such as blurring, color shifting, changing brightness/contrast, etc.
The "backdrop-filter" property (BackdropFilter constant) applies the same effects but to the area behind a View.
Only the ViewFilter interface is used as the value of the "filter" properties.
ViewFilter is created using the function
func NewViewFilter(params Params) ViewFilter
@ -1249,9 +1270,10 @@ Example
rui.Contrast: 150,
}))
You can get the value of the current filter using the function
You can get the value of the current filter using functions
func GetFilter(view View, subviewID string) ViewFilter
func GetBackdropFilter(view View, subviewID string) ViewFilter
### "semantics" property
@ -2103,17 +2125,17 @@ The start and end positions for StartToEndOrientation and EndToStartOrientation
of the "text-direction" property. For languages written from right to left (Arabic, Hebrew),
the beginning is on the right, for other languages - on the left.
### "wrap" property
### "list-wrap" property
The "wrap" int property (Wrap constant) defines the position of elements in case of reaching
The "list-wrap" int property (ListWrap constant) defines the position of elements in case of reaching
the border of the container. There are three options:
* WrapOff (0) - the column / row of elements continues and goes beyond the bounds of the visible area.
* ListWrapOff (0) - the column / row of elements continues and goes beyond the bounds of the visible area.
* WrapOn (1) - starts a new column / row of items. The new column is positioned towards the end
* ListWrapOn (1) - starts a new column / row of items. The new column is positioned towards the end
(for the position of the beginning and end, see above), the new line is at the bottom.
* WrapReverse (2) - starts a new column / row of elements. The new column is positioned towards the beginning
* ListWrapReverse (2) - starts a new column / row of elements. The new column is positioned towards the beginning
(for the position of the beginning and end, see above), the new line is at the top.
### "vertical-align" property
@ -2192,6 +2214,24 @@ Example
In this example, view1 occupies columns 1 and 2 in row 0, and view1 occupies rows 0, 1, and 2 in column 0.
### "grid-auto-flow"
If the "row" and "column" properties are not set for child Views, then the automatic View placement algorithm is used.
There are four variants of this algorithm. The variant to use is specified using the "grid-auto-flow" int property.
The "grid-auto-flow" property can take the following values:
* RowAutoFlow (0) (text name "row") - Views are placed by filling each row in turn, adding new columns as necessary;
* ColumnAutoFlow (1) (text name "colunm") - Views are placed by filling each column in turn, adding new columns as necessary;
* RowDenseAutoFlow (2) (text name "row-dense") - Views are placed by filling each row, adding new rows as necessary.
"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.
* ColumnDenseAutoFlow (3) (text name "column-dense") - Views are placed by filling each column, adding new columns as necessary.
"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.
### "cell-width" and "cell-height" properties
By default, the sizes of the cells are calculated based on the sizes of the child Views placed in them.
@ -2668,10 +2708,14 @@ Spell checking can only be enabled if the editor type is set to SingleLineText o
For the editor, you can set a hint that will be shown while the editor is empty.
To do this, use the string property "hint" (Hint constant).
For a multi-line editor, auto-wrap mode can be enabled. The bool property "wrap" (constant Wrap) is used for this.
If "wrap" is off (default), then horizontal scrolling is used.
For a multi-line editor, auto-wrap mode can be enabled. The bool property "edit-wrap" (EditWrap constant) is used for this.
If "edit-wrap" is false (default), then horizontal scrolling is used.
If enabled, the text wraps to a new line when the EditView border is reached.
To change the color of the text input caret, use the Color property "caret-color" (CaretColor constant).
The "caret-color" property can be set not only for EditView, but for any container.
In this case, the color of the caret changes for all child EditViews placed in this container.
The following functions can be used to get the values of the properties of an EditView:
func GetText(view View, subviewID string) string
@ -2682,6 +2726,7 @@ The following functions can be used to get the values of the properties of an Ed
func IsReadOnly(view View, subviewID string) bool
func IsEditViewWrap(view View, subviewID string) bool
func IsSpellcheck(view View, subviewID string) bool
func GetCaretColor(view View, subviewID string) Color
The "edit-text-changed" event (EditTextChangedEvent constant) is used to track changes to the text.
The main event listener has the following format:

View File

@ -92,14 +92,6 @@ function socketClose(event) {
if (!event.wasClean && windowFocus) {
window.setTimeout(socketReconnect, 10000);
}
/*
if (event.wasClean) {
alert('Connection was clean closed');
} else {
alert('Connection was lost');
}
alert('Code: ' + event.code + ' reason: ' + event.reason);
*/
}
function socketError(error) {
@ -318,28 +310,34 @@ function activateTab(layoutId, tabNumber) {
}
}
function tabClickEvent(layoutId, tabNumber, event) {
function tabClickEvent(tab, layoutId, tabNumber, event) {
event.stopPropagation();
event.preventDefault();
activateTab(layoutId, tabNumber)
if (tab) {
tab.blur()
}
sendMessage("tabClick{session=" + sessionID + ",id=" + layoutId + ",number=" + tabNumber + "}");
}
function tabKeyClickEvent(layoutId, tabNumber, event) {
if (enterOrSpaceKeyClickEvent(event)) {
tabClickEvent(layoutId, tabNumber, event)
tabClickEvent(null, layoutId, tabNumber, event)
}
}
function tabCloseClickEvent(layoutId, tabNumber, event) {
function tabCloseClickEvent(button, layoutId, tabNumber, event) {
event.stopPropagation();
event.preventDefault();
if (button) {
button.blur()
}
sendMessage("tabCloseClick{session=" + sessionID + ",id=" + layoutId + ",number=" + tabNumber + "}");
}
function tabCloseKeyClickEvent(layoutId, tabNumber, event) {
if (enterOrSpaceKeyClickEvent(event)) {
tabCloseClickEvent(layoutId, tabNumber, event)
tabCloseClickEvent(null, layoutId, tabNumber, event)
}
}
@ -1260,6 +1258,13 @@ function focus(elementId) {
}
}
function blur(elementId) {
var element = document.getElementById(elementId);
if (element) {
element.blur();
}
}
function playerEvent(element, tag) {
//event.stopPropagation();
sendMessage(tag + "{session=" + sessionID + ",id=" + element.id + "}");

View File

@ -2,6 +2,7 @@ package rui
import (
"bytes"
"context"
_ "embed"
"fmt"
"io"
@ -13,6 +14,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
)
@ -33,6 +35,7 @@ type Application interface {
}
type application struct {
server *http.Server
params AppParams
createContentFunc func(Session) SessionContent
sessions map[int]Session
@ -40,9 +43,22 @@ type application struct {
// AppParams defines parameters of the app
type AppParams struct {
Title string
// Title - title of the app window/tab
Title string
// TitleColor - background color of the app window/tab (applied only for Safari and Chrome for Android)
TitleColor Color
Icon string
// Icon - the icon file name
Icon string
// CertFile - path of a certificate for the server must be provided
// if neither the Server's TLSConfig.Certificates nor TLSConfig.GetCertificate are populated.
// If the certificate is signed by a certificate authority, the certFile should be the concatenation
// of the server's certificate, any intermediates, and the CA's certificate.
CertFile string
// KeyFile - path of a private key for the server must be provided
// if neither the Server's TLSConfig.Certificates nor TLSConfig.GetCertificate are populated.
KeyFile string
// Redirect80 - if true then the function of redirect from port 80 to 443 is created
Redirect80 bool
}
func (app *application) getStartPage() string {
@ -90,15 +106,17 @@ func (app *application) getStartPage() string {
return buffer.String()
}
func (app *application) Start(addr string) {
http.Handle("/", app)
log.Fatal(http.ListenAndServe(addr, nil))
}
func (app *application) Finish() {
for _, session := range app.sessions {
session.close()
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := app.server.Shutdown(ctx); err != nil {
log.Println(err.Error())
}
}
func (app *application) nextSessionID() int {
@ -285,15 +303,62 @@ func (app *application) startSession(params DataObject, events chan DataObject,
return session, answerText
}
// NewApplication - create the new application and start it
var apps = []*application{}
// StartApp - create the new application and start it
func StartApp(addr string, createContentFunc func(Session) SessionContent, params AppParams) {
app := new(application)
app.params = params
app.sessions = map[int]Session{}
app.createContentFunc = createContentFunc
apps = append(apps, app)
redirectAddr := ""
if index := strings.IndexRune(addr, ':'); index >= 0 {
redirectAddr = addr[:index] + ":80"
} else {
redirectAddr = addr + ":80"
if params.CertFile != "" && params.KeyFile != "" {
addr += ":443"
} else {
addr += ":80"
}
}
app.server = &http.Server{Addr: addr}
http.Handle("/", app)
log.Fatal(http.ListenAndServe(addr, nil))
serverRun := func(err error) {
if err != nil {
if err == http.ErrServerClosed {
log.Println(err)
} else {
log.Fatal(err)
}
}
}
if params.CertFile != "" && params.KeyFile != "" {
if params.Redirect80 {
redirectTLS := func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://"+addr+r.RequestURI, http.StatusMovedPermanently)
}
go func() {
serverRun(http.ListenAndServe(redirectAddr, http.HandlerFunc(redirectTLS)))
}()
}
serverRun(app.server.ListenAndServeTLS(params.CertFile, params.KeyFile))
} else {
serverRun(app.server.ListenAndServe())
}
}
func FinishApp() {
for _, app := range apps {
app.Finish()
}
apps = []*application{}
}
func OpenBrowser(url string) bool {
@ -301,11 +366,20 @@ func OpenBrowser(url string) bool {
switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", url).Start()
for _, provider := range []string{"xdg-open", "x-www-browser", "www-browser"} {
if _, err = exec.LookPath(provider); err == nil {
if exec.Command(provider, url).Start(); err == nil {
return true
}
}
}
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
err = exec.Command("open", url).Start()
default:
err = fmt.Errorf("unsupported platform")
}

View File

@ -195,6 +195,7 @@ func (button *checkboxData) changedCheckboxState(state bool) {
func checkboxClickListener(view View) {
view.Set(Checked, !IsCheckboxChecked(view, ""))
BlurView(view)
}
func checkboxKeyListener(view View, event KeyEvent) {

View File

@ -20,7 +20,7 @@ theme {
ruiTabBarBackgroundColor = #FFEEEEEE,
ruiTabColor = #FFD0D0D0,
ruiTabTextColor = #FF808080,
ruiTabTextColor = #FF404040,
ruiCurrentTabColor = #FFFFFFFF,
ruiCurrentTabTextColor = #FF000000,
},

View File

@ -63,7 +63,7 @@ func createEditDemo(session rui.Session) rui.View {
})
rui.Set(view, "editMultiLineWrap", rui.CheckboxChangedEvent, func(checkbox rui.Checkbox, checked bool) {
rui.Set(view, "editMultiLine", rui.Wrap, checked)
rui.Set(view, "editMultiLine", rui.EditWrap, checked)
})
return view

View File

@ -44,7 +44,7 @@ func createKeyEventsDemo(session rui.Session) rui.View {
rui.Width: rui.Percent(100),
rui.Height: rui.Percent(100),
rui.ReadOnly: true,
rui.Wrap: true,
rui.EditWrap: true,
rui.Hint: "Set the focus and press a key",
rui.EditViewType: rui.MultiLineText,
rui.KeyDownEvent: func(view rui.View, event rui.KeyEvent) {

View File

@ -75,7 +75,7 @@ func createListLayoutDemo(session rui.Session) rui.View {
})
rui.Set(view, "listWrap", rui.DropDownEvent, func(list rui.DropDownList, number int) {
rui.Set(view, "listLayout", rui.Wrap, number)
rui.Set(view, "listLayout", rui.ListWrap, number)
})
rui.Set(view, "listHAlign", rui.DropDownEvent, func(list rui.DropDownList, number int) {

View File

@ -55,7 +55,7 @@ func createListViewDemo(session rui.Session) rui.View {
})
rui.Set(view, "listWrap", rui.DropDownEvent, func(list rui.DropDownList, number int) {
rui.Set(view, "listView", rui.Wrap, number)
rui.Set(view, "listView", rui.ListWrap, number)
})
setItemSize := func(tag string, number int, values []rui.SizeUnit) {

View File

@ -82,6 +82,9 @@ func (edit *editViewData) normalizeTag(tag string) string {
case "maxlength", "maxlen":
return MaxLength
case "wrap":
return EditWrap
}
return tag
@ -163,7 +166,7 @@ func (edit *editViewData) remove(tag string) {
}
}
case Wrap:
case EditWrap:
if exists {
oldWrap := IsEditViewWrap(edit, "")
delete(edit.properties, tag)
@ -310,9 +313,9 @@ func (edit *editViewData) set(tag string, value interface{}) bool {
}
return false
case Wrap:
case EditWrap:
oldWrap := IsEditViewWrap(edit, "")
if edit.setBoolProperty(Wrap, value) {
if edit.setBoolProperty(EditWrap, value) {
if GetEditViewType(edit, "") == MultiLineText {
if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap {
if edit.created {
@ -679,14 +682,14 @@ func GetEditViewPattern(view View, subviewID string) string {
return ""
}
// IsEditViewWrap returns a value of the Wrap property of MultiLineEditView.
// IsEditViewWrap returns a value of the EditWrap property of MultiLineEditView.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func IsEditViewWrap(view View, subviewID string) bool {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if wrap, ok := boolStyledProperty(view, Wrap); ok {
if wrap, ok := boolStyledProperty(view, EditWrap); ok {
return wrap
}
}
@ -708,3 +711,16 @@ func AppendEditText(view View, subviewID string, text string) {
edit.AppendText(text)
}
}
// GetCaretColor returns the color of the text input carret.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetCaretColor(view View, subviewID string) Color {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view == nil {
return 0
}
t, _ := colorStyledProperty(view, CaretColor)
return t
}

5
go.mod
View File

@ -2,4 +2,7 @@ module github.com/anoshenko/rui
go 1.17
require github.com/gorilla/websocket v1.5.0
require (
github.com/gorilla/websocket v1.5.0
github.com/webview/webview v0.0.0-20220603044542-dc41cdcc2961
)

4
go.sum
View File

@ -1,4 +1,4 @@
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/webview/webview v0.0.0-20220603044542-dc41cdcc2961 h1:T+zDKQvVOtbfrJwy8H1yn3ZtWuwbGu07aLih+qwFCsQ=
github.com/webview/webview v0.0.0-20220603044542-dc41cdcc2961/go.mod h1:rpXAuuHgyEJb6kXcXldlkOjU6y4x+YcASKKXJNUhh0Y=

View File

@ -329,7 +329,7 @@ func GetCellVerticalAlign(view View, subviewID string) int {
view = ViewByID(view, subviewID)
}
if view != nil {
if align, ok := enumProperty(view, CellVerticalAlign, view.Session(), StretchAlign); ok {
if align, ok := enumStyledProperty(view, CellVerticalAlign, StretchAlign); ok {
return align
}
}
@ -343,13 +343,27 @@ func GetCellHorizontalAlign(view View, subviewID string) int {
view = ViewByID(view, subviewID)
}
if view != nil {
if align, ok := enumProperty(view, CellHorizontalAlign, view.Session(), StretchAlign); ok {
if align, ok := enumStyledProperty(view, CellHorizontalAlign, StretchAlign); ok {
return align
}
}
return StretchAlign
}
// GetGridAutoFlow returns the value of the "grid-auto-flow" property
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetGridAutoFlow(view View, subviewID string) int {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if align, ok := enumStyledProperty(view, GridAutoFlow, 0); ok {
return align
}
}
return 0
}
// GetCellWidth returns the width of a GridLayout cell. If the result is an empty array, then the width is not set.
// If the result is a single value array, then the width of all cell is equal.
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
@ -383,7 +397,7 @@ func GetGridRowGap(view View, subviewID string) SizeUnit {
view = ViewByID(view, subviewID)
}
if view != nil {
if result, ok := sizeProperty(view, GridRowGap, view.Session()); ok {
if result, ok := sizeStyledProperty(view, GridRowGap); ok {
return result
}
}
@ -397,7 +411,7 @@ func GetGridColumnGap(view View, subviewID string) SizeUnit {
view = ViewByID(view, subviewID)
}
if view != nil {
if result, ok := sizeProperty(view, GridColumnGap, view.Session()); ok {
if result, ok := sizeStyledProperty(view, GridColumnGap); ok {
return result
}
}

View File

@ -13,12 +13,12 @@ const (
BottomUpOrientation = 2
// EndToStartOrientation - subviews are arranged from right to left
EndToStartOrientation = 3
// WrapOff - subviews are scrolled and "true" if a new row/column starts
WrapOff = 0
// WrapOn - the new row/column starts at bottom/right
WrapOn = 1
// WrapReverse - the new row/column starts at top/left
WrapReverse = 2
// ListWrapOff - subviews are scrolled and "true" if a new row/column starts
ListWrapOff = 0
// ListWrapOn - the new row/column starts at bottom/right
ListWrapOn = 1
// ListWrapReverse - the new row/column starts at top/left
ListWrapReverse = 2
)
// ListLayout - list-container of View
@ -53,22 +53,35 @@ func (listLayout *listLayoutData) String() string {
return getViewString(listLayout)
}
func (listLayout *listLayoutData) normalizeTag(tag string) string {
tag = strings.ToLower(tag)
switch tag {
case "wrap":
tag = ListWrap
}
return tag
}
func (listLayout *listLayoutData) Get(tag string) interface{} {
return listLayout.get(listLayout.normalizeTag(tag))
}
func (listLayout *listLayoutData) Remove(tag string) {
listLayout.remove(strings.ToLower(tag))
listLayout.remove(listLayout.normalizeTag(tag))
}
func (listLayout *listLayoutData) remove(tag string) {
listLayout.viewsContainerData.remove(tag)
if listLayout.created {
switch tag {
case Orientation, Wrap, HorizontalAlign, VerticalAlign:
case Orientation, ListWrap, HorizontalAlign, VerticalAlign:
updateCSSStyle(listLayout.htmlID(), listLayout.session)
}
}
}
func (listLayout *listLayoutData) Set(tag string, value interface{}) bool {
return listLayout.set(strings.ToLower(tag), value)
return listLayout.set(listLayout.normalizeTag(tag), value)
}
func (listLayout *listLayoutData) set(tag string, value interface{}) bool {
@ -80,7 +93,7 @@ func (listLayout *listLayoutData) set(tag string, value interface{}) bool {
if listLayout.viewsContainerData.set(tag, value) {
if listLayout.created {
switch tag {
case Orientation, Wrap, HorizontalAlign, VerticalAlign:
case Orientation, ListWrap, HorizontalAlign, VerticalAlign:
updateCSSStyle(listLayout.htmlID(), listLayout.session)
}
}
@ -157,9 +170,9 @@ func GetListWrap(view View, subviewID string) int {
view = ViewByID(view, subviewID)
}
if view != nil {
if result, ok := enumStyledProperty(view, Wrap, 0); ok {
if result, ok := enumStyledProperty(view, ListWrap, 0); ok {
return result
}
}
return WrapOff
return ListWrapOff
}

View File

@ -107,6 +107,9 @@ func (listView *listViewData) normalizeTag(tag string) string {
case VerticalAlign:
tag = ItemVerticalAlign
case "wrap":
tag = ListWrap
}
return tag
}
@ -135,7 +138,7 @@ func (listView *listViewData) remove(tag string) {
listView.propertyChangedEvent(tag)
}
case Orientation, Wrap:
case Orientation, ListWrap:
if _, ok := listView.properties[tag]; ok {
delete(listView.properties, tag)
if listView.created {
@ -252,7 +255,7 @@ func (listView *listViewData) set(tag string, value interface{}) bool {
listener(listView, current)
}
case Orientation, Wrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight:
case Orientation, ListWrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight:
result := listView.viewData.set(tag, value)
if result && listView.created {
updateInnerHTML(listView.htmlID(), listView.session)
@ -764,37 +767,34 @@ func (listView *listViewData) getItemView(index int) View {
return listView.items[index]
}
func (listView *listViewData) listItemStyle() string {
if value := listView.getRaw(ListItemStyle); value != nil {
func (listView *listViewData) itemStyle(tag, defaultStyle string) string {
if value := listView.getRaw(tag); value != nil {
if style, ok := value.(string); ok {
if style, ok = listView.session.resolveConstants(style); ok {
return style
}
}
}
return "ruiListItem"
if value := valueFromStyle(listView, tag); value != nil {
if style, ok := value.(string); ok {
if style, ok = listView.session.resolveConstants(style); ok {
return style
}
}
}
return defaultStyle
}
func (listView *listViewData) listItemStyle() string {
return listView.itemStyle(ListItemStyle, "ruiListItem")
}
func (listView *listViewData) currentStyle() string {
if value := listView.getRaw(CurrentStyle); value != nil {
if style, ok := value.(string); ok {
if style, ok = listView.session.resolveConstants(style); ok {
return style
}
}
}
return "ruiListItemFocused"
return listView.itemStyle(CurrentStyle, "ruiListItemFocused")
}
func (listView *listViewData) currentInactiveStyle() string {
if value := listView.getRaw(CurrentInactiveStyle); value != nil {
if style, ok := value.(string); ok {
if style, ok = listView.session.resolveConstants(style); ok {
return style
}
}
}
return "ruiListItemSelected"
return listView.itemStyle(CurrentInactiveStyle, "ruiListItemSelected")
}
func (listView *listViewData) checkboxSubviews(self View, buffer *strings.Builder, checkbox int) {
@ -981,13 +981,13 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
rows := (orientation == StartToEndOrientation || orientation == EndToStartOrientation)
if rows {
if wrap == WrapOff {
if wrap == ListWrapOff {
buffer.WriteString(` min-width: 100%; height: 100%;`)
} else {
buffer.WriteString(` width: 100%; min-height: 100%;`)
}
} else {
if wrap == WrapOff {
if wrap == ListWrapOff {
buffer.WriteString(` width: 100%; min-height: 100%;`)
} else {
buffer.WriteString(` min-width: 100%; height: 100%;`)
@ -998,10 +998,10 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
buffer.WriteString(enumProperties[Orientation].cssValues[orientation])
switch wrap {
case WrapOn:
case ListWrapOn:
buffer.WriteString(` wrap;`)
case WrapReverse:
case ListWrapReverse:
buffer.WriteString(` wrap-reverse;`)
default:
@ -1021,13 +1021,13 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
if align, ok := enumStyledProperty(listView, HorizontalAlign, LeftAlign); ok {
switch align {
case LeftAlign:
if (!rows && wrap == WrapReverse) || orientation == EndToStartOrientation {
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
value = `flex-end`
} else {
value = `flex-start`
}
case RightAlign:
if (!rows && wrap == WrapReverse) || orientation == EndToStartOrientation {
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
value = `flex-start`
} else {
value = `flex-end`
@ -1056,13 +1056,13 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
if align, ok := enumStyledProperty(listView, VerticalAlign, TopAlign); ok {
switch align {
case TopAlign:
if (rows && wrap == WrapReverse) || orientation == BottomUpOrientation {
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
value = `flex-end`
} else {
value = `flex-start`
}
case BottomAlign:
if (rows && wrap == WrapReverse) || orientation == BottomUpOrientation {
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
value = `flex-start`
} else {
value = `flex-end`

View File

@ -2,109 +2,154 @@ package rui
const (
// ID is the constant for the "id" property tag.
// The "id" property is an optional textual identifier for the View.
ID = "id"
// Style is the constant for the "style" property tag.
// The string "style" property sets the name of the style that is applied to the View when the "disabled" property is set to false
// or "style-disabled" property is not defined.
Style = "style"
// StyleDisabled is the constant for the "style-disabled" property tag.
// The string "style-disabled" property sets the name of the style that is applied to the View when the "disabled" property is set to true.
StyleDisabled = "style-disabled"
// Disabled is the constant for the "disabled" property tag.
// The bool "disabled" property allows/denies the View to receive focus.
Disabled = "disabled"
// Focusable is the constant for the "disabled" property tag.
// The bool "focusable" determines whether the view will receive focus.
Focusable = "focusable"
// Semantics is the constant for the "semantics" property tag.
// The "semantics" property defines the semantic meaning of the View.
// This property may have no visible effect, but it allows search engines to understand the structure of your application.
// It also helps to voice the interface to systems for people with disabilities.
Semantics = "semantics"
// Visibility is the constant for the "visibility" property tag.
// The "visibility" int property specifies the visibility of the View. Valid values are
// * Visible (0) - the View is visible (default value);
// * Invisible (1) - the View is invisible but takes up space;
// * Gone (2) - the View is invisible and does not take up space.
Visibility = "visibility"
// ZIndex is the constant for the "z-index" property tag.
// The int "z-index" property sets the z-order of a positioned view.
// Overlapping views with a larger z-index cover those with a smaller one.
ZIndex = "z-index"
// Opacity is the constant for the "opacity" property tag.
// The float "opacity" property in [1..0] range sets the opacity of an element.
// Opacity is the degree to which content behind an element is hidden, and is the opposite of transparency.
Opacity = "opacity"
// Row is the constant for the "row" property tag.
Row = "row"
// Column is the constant for the "column" property tag.
Column = "column"
// Left is the constant for the "left" property tag.
// The "left" SizeUnit property participates in specifying the left border position of a positioned view.
// Used only for views placed in an AbsoluteLayout.
Left = "left"
// Right is the constant for the "right" property tag.
// The "right" SizeUnit property participates in specifying the right border position of a positioned view.
// Used only for views placed in an AbsoluteLayout.
Right = "right"
// Top is the constant for the "top" property tag.
// The "top" SizeUnit property participates in specifying the top border position of a positioned view.
// Used only for views placed in an AbsoluteLayout.
Top = "top"
// Bottom is the constant for the "bottom" property tag.
// The "bottom" SizeUnit property participates in specifying the bottom border position of a positioned view.
// Used only for views placed in an AbsoluteLayout.
Bottom = "bottom"
// Width is the constant for the "width" property tag.
// The "width" SizeUnit property sets an view's width.
Width = "width"
// Height is the constant for the "height" property tag.
// The "height" SizeUnit property sets an view's height.
Height = "height"
// MinWidth is the constant for the "min-width" property tag.
// The "width" SizeUnit property sets an view's minimal width.
MinWidth = "min-width"
// MinHeight is the constant for the "min-height" property tag.
// The "height" SizeUnit property sets an view's minimal height.
MinHeight = "min-height"
// MaxWidth is the constant for the "max-width" property tag.
// The "width" SizeUnit property sets an view's maximal width.
MaxWidth = "max-width"
// MaxHeight is the constant for the "max-height" property tag.
// The "height" SizeUnit property sets an view's maximal height.
MaxHeight = "max-height"
// Margin is the constant for the "margin" property tag.
// The "margin" property sets the margin area on all four sides of an element.
// ...
Margin = "margin"
// MarginLeft is the constant for the "margin-left" property tag.
// The "margin-left" SizeUnit property sets the margin area on the left of a view.
// A positive value places it farther from its neighbors, while a negative value places it closer.
MarginLeft = "margin-left"
// MarginRight is the constant for the "margin-right" property tag.
// The "margin-right" SizeUnit property sets the margin area on the right of a view.
// A positive value places it farther from its neighbors, while a negative value places it closer.
MarginRight = "margin-right"
// MarginTop is the constant for the "margin-top" property tag.
// The "margin-top" SizeUnit property sets the margin area on the top of a view.
// A positive value places it farther from its neighbors, while a negative value places it closer.
MarginTop = "margin-top"
// MarginBottom is the constant for the "margin-bottom" property tag.
// The "margin-bottom" SizeUnit property sets the margin area on the bottom of a view.
// A positive value places it farther from its neighbors, while a negative value places it closer.
MarginBottom = "margin-bottom"
// Padding is the constant for the "padding" property tag.
// The "padding" Bounds property sets the padding area on all four sides of a view at once.
// An element's padding area is the space between its content and its border.
Padding = "padding"
// PaddingLeft is the constant for the "padding-left" property tag.
// The "padding-left" SizeUnit property sets the width of the padding area to the left of a view.
PaddingLeft = "padding-left"
// PaddingRight is the constant for the "padding-right" property tag.
// The "padding-right" SizeUnit property sets the width of the padding area to the right of a view.
PaddingRight = "padding-right"
// PaddingTop is the constant for the "padding-top" property tag.
// The "padding-top" SizeUnit property sets the height of the padding area to the top of a view.
PaddingTop = "padding-top"
// PaddingBottom is the constant for the "padding-bottom" property tag.
// The "padding-bottom" SizeUnit property sets the height of the padding area to the bottom of a view.
PaddingBottom = "padding-bottom"
// BackgroundColor is the constant for the "background-color" property tag.
// The "background-color" property sets the background color of a view.
BackgroundColor = "background-color"
// Background is the constant for the "background" property tag.
// The "background" property sets one or more background images and/or gradients on a view.
// ...
Background = "background"
// Cursor is the constant for the "cursor" property tag.
// The "cursor" int property sets the type of mouse cursor, if any, to show when the mouse pointer is over a view
// Valid values are "auto" (0), "default" (1), "none" (2), "context-menu" (3), "help" (4), "pointer" (5),
@ -114,155 +159,196 @@ const (
// "ew-resize" (25), "ns-resize" (26), "nesw-resize" (27), "nwse-resize" (28), "col-resize" (29),
// "row-resize" (30), "all-scroll" (31), "zoom-in" (32), "zoom-out" (33), "grab" (34), "grabbing" (35).
Cursor = "cursor"
// Border is the constant for the "border" property tag.
// The "border" property sets a view's border. It sets the values of a border width, style, and color.
// This property can be assigned a value of BorderProperty type, or ViewBorder type, or BorderProperty text representation.
Border = "border"
// BorderLeft is the constant for the "border-left" property tag.
// The "border-left" property sets a view's left border. It sets the values of a border width, style, and color.
// This property can be assigned a value of BorderProperty type, or ViewBorder type, or BorderProperty text representation.
BorderLeft = "border-left"
// BorderRight is the constant for the "border-right" property tag.
// The "border-right" property sets a view's right border. It sets the values of a border width, style, and color.
// This property can be assigned a value of BorderProperty type, or ViewBorder type, or BorderProperty text representation.
BorderRight = "border-right"
// BorderTop is the constant for the "border-top" property tag.
// The "border-top" property sets a view's top border. It sets the values of a border width, style, and color.
// This property can be assigned a value of BorderProperty type, or ViewBorder type, or BorderProperty text representation.
BorderTop = "border-top"
// BorderBottom is the constant for the "border-bottom" property tag.
// The "border-bottom" property sets a view's bottom border. It sets the values of a border width, style, and color.
// This property can be assigned a value of BorderProperty type, or ViewBorder type, or BorderProperty text representation.
BorderBottom = "border-bottom"
// BorderStyle is the constant for the "border-style" property tag.
// The "border-style" property sets the line style for all four sides of a view's border.
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
BorderStyle = "border-style"
// BorderLeftStyle is the constant for the "border-left-style" property tag.
// The "border-left-style" int property sets the line style of a view's left border.
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
BorderLeftStyle = "border-left-style"
// BorderRightStyle is the constant for the "border-right-style" property tag.
// The "border-right-style" int property sets the line style of a view's right border.
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
BorderRightStyle = "border-right-style"
// BorderTopStyle is the constant for the "border-top-style" property tag.
// The "border-top-style" int property sets the line style of a view's top border.
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
BorderTopStyle = "border-top-style"
// BorderBottomStyle is the constant for the "border-bottom-style" property tag.
// The "border-bottom-style" int property sets the line style of a view's bottom border.
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
BorderBottomStyle = "border-bottom-style"
// BorderWidth is the constant for the "border-width" property tag.
// The "border-width" property sets the line width for all four sides of a view's border.
BorderWidth = "border-width"
// BorderLeftWidth is the constant for the "border-left-width" property tag.
// The "border-left-width" SizeUnit property sets the line width of a view's left border.
BorderLeftWidth = "border-left-width"
// BorderRightWidth is the constant for the "border-right-width" property tag.
// The "border-right-width" SizeUnit property sets the line width of a view's right border.
BorderRightWidth = "border-right-width"
// BorderTopWidth is the constant for the "border-top-width" property tag.
// The "border-top-width" SizeUnit property sets the line width of a view's top border.
BorderTopWidth = "border-top-width"
// BorderBottomWidth is the constant for the "border-bottom-width" property tag.
// The "border-bottom-width" SizeUnit property sets the line width of a view's bottom border.
BorderBottomWidth = "border-bottom-width"
// BorderColor is the constant for the "border-color" property tag.
// The "border-color" property sets the line color for all four sides of a view's border.
BorderColor = "border-color"
// BorderLeftColor is the constant for the "border-left-color" property tag.
// The "border-left-color" property sets the line color of a view's left border.
BorderLeftColor = "border-left-color"
// BorderRightColor is the constant for the "border-right-color" property tag.
// The "border-right-color" property sets the line color of a view's right border.
BorderRightColor = "border-right-color"
// BorderTopColor is the constant for the "border-top-color" property tag.
// The "border-top-color" property sets the line color of a view's top border.
BorderTopColor = "border-top-color"
// BorderBottomColor is the constant for the "border-bottom-color" property tag.
// The "border-bottom-color" property sets the line color of a view's bottom border.
BorderBottomColor = "border-bottom-color"
// Outline is the constant for the "outline" property tag.
// The "border" property sets a view's outline. It sets the values of an outline width, style, and color.
Outline = "outline"
// OutlineStyle is the constant for the "outline-style" property tag.
// The "outline-style" int property sets the style of an view's outline.
// Valid values are NoneLine (0), SolidLine (1), DashedLine (2), DottedLine (3), and DoubleLine (4).
OutlineStyle = "outline-style"
// OutlineColor is the constant for the "outline-color" property tag.
// The "outline-color" property sets the color of an view's outline.
OutlineColor = "outline-color"
// OutlineWidth is the constant for the "outline-width" property tag.
// The "outline-width" SizeUnit property sets the width of an view's outline.
OutlineWidth = "outline-width"
// Shadow is the constant for the "shadow" property tag.
// The "shadow" property adds shadow effects around a view's frame. A shadow is described
// by X and Y offsets relative to the element, blur and spread radius, and color.
// ...
Shadow = "shadow"
// FontName is the constant for the "font-name" property tag.
// The "font-name" string property specifies a prioritized list of one or more font family names and/or
// generic family names for the selected view. Values are separated by commas to indicate that they are alternatives.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
FontName = "font-name"
// TextColor is the constant for the "text-color" property tag.
// The "color" property sets the foreground color value of a view's text and text decorations.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextColor = "text-color"
// TextSize is the constant for the "text-size" property tag.
// The "text-size" SizeUnit property sets the size of the font.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextSize = "text-size"
// Italic is the constant for the "italic" property tag.
// The "italic" is the bool property. If it is "true" then a text is displayed in italics.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
Italic = "italic"
// SmallCaps is the constant for the "small-caps" property tag.
// The "small-caps" is the bool property. If it is "true" then a text is displayed in small caps.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
SmallCaps = "small-caps"
// Strikethrough is the constant for the "strikethrough" property tag.
// The "strikethrough" is the bool property. If it is "true" then a text is displayed strikethrough.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
Strikethrough = "strikethrough"
// Overline is the constant for the "overline" property tag.
// The "overline" is the bool property. If it is "true" then a text is displayed overlined.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
Overline = "overline"
// Underline is the constant for the "underline" property tag.
// The "underline" is the bool property. If it is "true" then a text is displayed underlined.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
Underline = "underline"
// TextLineThickness is the constant for the "text-decoration-thickness" property tag.
// The "text-decoration-thickness" SizeUnit property sets the stroke thickness of the decoration line that
// is used on text in an element, such as a line-through, underline, or overline.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextLineThickness = "text-line-thickness"
// TextLineStyle is the constant for the "text-decoration-style" property tag.
// The "text-decoration-style" int property sets the style of the lines specified by "text-decoration" property.
// The style applies to all lines that are set with "text-decoration" property.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextLineStyle = "text-line-style"
// TextLineColor is the constant for the "text-decoration-color" property tag.
// The "text-decoration-color" Color property sets the color of the lines specified by "text-decoration" property.
// The color applies to all lines that are set with "text-decoration" property.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextLineColor = "text-line-color"
// TextWeight is the constant for the "text-weight" property tag.
// Valid values are SolidLine (1), DashedLine (2), DottedLine (3), DoubleLine (4) and WavyLine (5).
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextWeight = "text-weight"
// TextAlign is the constant for the "text-align" property tag.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextAlign = "text-align"
// TextIndent is the constant for the "text-indent" property tag.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextIndent = "text-indent"
// TextShadow is the constant for the "text-shadow" property tag.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextShadow = "text-shadow"
// LetterSpacing is the constant for the "letter-spacing" property tag.
// The "letter-spacing" SizeUnit property sets the horizontal spacing behavior between text characters.
// This value is added to the natural spacing between characters while rendering the text.
@ -270,30 +356,36 @@ const (
// while negative values of letter-spacing bring characters closer together.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
LetterSpacing = "letter-spacing"
// WordSpacing is the constant for the "word-spacing" property tag.
// The "word-spacing" SizeUnit property sets the length of space between words and between tags.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
WordSpacing = "word-spacing"
// LineHeight is the constant for the "line-height" property tag.
// The "line-height" SizeUnit property sets the height of a line box.
// It's commonly used to set the distance between lines of text.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
LineHeight = "line-height"
// WhiteSpace is the constant for the "white-space" property tag.
// The "white-space" int property sets how white space inside an element is handled.
// Valid values are WhiteSpaceNormal (0), WhiteSpaceNowrap (1), WhiteSpacePre (2),
// WhiteSpacePreWrap (3), WhiteSpacePreLine (4), WhiteSpaceBreakSpaces (5)
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
WhiteSpace = "white-space"
// WordBreak is the constant for the "word-break" property tag.
// The "word-break" int property sets whether line breaks appear wherever the text would otherwise overflow its content box.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
WordBreak = "word-break"
// TextTransform is the constant for the "text-transform" property tag.
// The "text-transform" int property specifies how to capitalize an element's text.
// It can be used to make text appear in all-uppercase or all-lowercase, or with each word capitalized.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextTransform = "text-transform"
// TextDirection is the constant for the "text-direction" property tag.
// The "text-direction" int property sets the direction of text, table columns, and horizontal overflow.
// Use 1 (LeftToRightDirection) for languages written from right to left (like Hebrew or Arabic),
@ -301,151 +393,249 @@ const (
// The default value of the property is 0 (SystemTextDirection): use the system text direction.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
TextDirection = "text-direction"
// WritingMode is the constant for the "writing-mode" property tag.
// The "writing-mode" int property sets whether lines of text are laid out horizontally or vertically,
// as well as the direction in which blocks progress
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
WritingMode = "writing-mode"
// VerticalTextOrientation is the constant for the "vertical-text-orientation" property tag.
// The "vertical-text-orientation" int property sets the orientation of the text characters in a line.
// It only affects text in vertical mode ("writing-mode" property).
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
VerticalTextOrientation = "vertical-text-orientation"
// TextTverflow is the constant for the "text-overflow" property tag.
// The "text-overflow" int property sets how hidden overflow content is signaled to users.
// It can be clipped or display an ellipsis ('…'). Valid values are
TextOverflow = "text-overflow"
// Hint is the constant for the "hint" property tag.
// The "hint" string property sets a hint to the user of what can be entered in the control.
Hint = "hint"
// MaxLength is the constant for the "max-length" property tag.
// The "max-length" int property sets the maximum number of characters that the user can enter
MaxLength = "max-length"
// ReadOnly is the constant for the "readonly" property tag.
// This bool property indicates that the user cannot modify the value of the EditView.
ReadOnly = "readonly"
// Content is the constant for the "content" property tag.
Content = "content"
// Items is the constant for the "items" property tag.
Items = "items"
// DisabledItems is the constant for the "disabled-items" property tag.
DisabledItems = "disabled-items"
// Current is the constant for the "current" property tag.
Current = "current"
// Type is the constant for the "type" property tag.
Type = "type"
// Pattern is the constant for the "pattern" property tag.
Pattern = "pattern"
// GridAutoFlow is the constant for the "grid-auto-flow" property tag.
// The "grid-auto-flow" int property controls how the GridLayout auto-placement algorithm works,
// specifying exactly how auto-placed items get flowed into the grid.
// Valid values are RowAutoFlow (0), ColumnAutoFlow (1), RowDenseAutoFlow (2), and ColumnDenseAutoFlow (3)
GridAutoFlow = "grid-auto-flow"
// CellWidth is the constant for the "cell-width" property tag.
// The "cell-width" properties allow to set a fixed width of GridLayout cells regardless of the size of the child elements.
// These properties are of type []SizeUnit. Each element in the array determines the size of the corresponding column.
CellWidth = "cell-width"
// CellHeight is the constant for the "cell-height" property tag.
// The "cell-height" properties allow to set a fixed height of GridLayout cells regardless of the size of the child elements.
// These properties are of type []SizeUnit. Each element in the array determines the size of the corresponding row.
CellHeight = "cell-height"
// RowGap is the constant for the "row-gap" property tag.
// GridRowGap is the constant for the "grid-row-gap" property tag.
// The "grid-row-gap" SizeUnit properties allow to set the distance between the rows of the GridLayout container.
// The default is 0px.
GridRowGap = "grid-row-gap"
// ColumnGap is the constant for the "column-gap" property tag.
// GridColumnGap is the constant for the "grid-column-gap" property tag.
// The "grid-column-gap" SizeUnit properties allow to set the distance between the columns of the GridLayout container.
// The default is 0px.
GridColumnGap = "grid-column-gap"
/*
// GridAutoRows is the constant for the "grid-auto-rows" property tag.
GridAutoRows = "grid-auto-rows"
// GridAutoColumns is the constant for the "grid-auto-columns" property tag.
GridAutoColumns = "grid-auto-columns"
*/
// Source is the constant for the "src" property tag.
Source = "src"
// Fit is the constant for the "fit" property tag.
Fit = "fit"
backgroundFit = "background-fit"
// Repeat is the constant for the "repeat" property tag.
Repeat = "repeat"
// Attachment is the constant for the "attachment" property tag.
Attachment = "attachment"
// Clip is the constant for the "clip" property tag.
// BackgroundClip is the constant for the "background-clip" property tag.
BackgroundClip = "background-clip"
// Gradient is the constant for the "gradient" property tag.
Gradient = "gradient"
// Direction is the constant for the "direction" property tag.
Direction = "direction"
// Repeating is the constant for the "repeating" property tag.
Repeating = "repeating"
// Repeating is the constant for the "repeating" property tag.
From = "from"
// RadialGradientRadius is the constant for the "radial-gradient-radius" property tag.
RadialGradientRadius = "radial-gradient-radius"
// RadialGradientShape is the constant for the "radial-gradient-shape" property tag.
RadialGradientShape = "radial-gradient-shape"
// Shape is the constant for the "shape" property tag. It's a short form of "radial-gradient-shape"
Shape = "shape"
// CenterX is the constant for the "center-x" property tag.
CenterX = "center-x"
// CenterY is the constant for the "center-x" property tag.
CenterY = "center-y"
// AltText is the constant for the "alt-text" property tag.
AltText = "alt-text"
altTag = "alt"
// AvoidBreak is the constant for the "avoid-break" property tag.
// The "avoid-break" bool property sets how region breaks should behave inside a generated box.
// If the property value is "true" then fvoids any break from being inserted within the principal box.
// If the property value is "false" then allows, but does not force, any break to be inserted within
// the principal box.
AvoidBreak = "avoid-break"
// ItemWidth is the constant for the "item-width" property tag.
ItemWidth = "item-width"
// ItemHeight is the constant for the "item-height" property tag.
ItemHeight = "item-height"
// Wrap is the constant for the "wrap" property tag.
Wrap = "wrap"
// ListWrap is the constant for the "wrap" property tag.
ListWrap = "list-wrap"
// EditWrap is the constant for the "wrap" property tag.
EditWrap = "edit-wrap"
// CaretColor is the constant for the "caret-color" property tag.
// The "caret-color" Color property sets the color of the insertion caret, the visible marker
// where the next character typed will be inserted. This is sometimes referred to as the text input cursor.
CaretColor = "caret-color"
// Min is the constant for the "min" property tag.
Min = "min"
// Max is the constant for the "max" property tag.
Max = "max"
// Step is the constant for the "step" property tag.
Step = "step"
// Value is the constant for the "value" property tag.
Value = "value"
// Orientation is the constant for the "orientation" property tag.
Orientation = "orientation"
// Gap is the constant for the "gap" property tag.
Gap = "gap"
// Text is the constant for the "text" property tag.
Text = "text"
// VerticalAlign is the constant for the "vertical-align" property tag.
VerticalAlign = "vertical-align"
// HorizontalAlign is the constant for the "horizontal-align" property tag.
// The "horizontal-align" int property sets the horizontal alignment of the content inside a block element
HorizontalAlign = "horizontal-align"
// ImageVerticalAlign is the constant for the "image-vertical-align" property tag.
ImageVerticalAlign = "image-vertical-align"
// ImageHorizontalAlign is the constant for the "image-horizontal-align" property tag.
ImageHorizontalAlign = "image-horizontal-align"
// Checked is the constant for the "checked" property tag.
Checked = "checked"
// ItemVerticalAlign is the constant for the "item-vertical-align" property tag.
ItemVerticalAlign = "item-vertical-align"
// ItemHorizontalAlign is the constant for the "item-horizontal-align" property tag.
ItemHorizontalAlign = "item-horizontal-align"
// ItemCheckbox is the constant for the "checkbox" property tag.
ItemCheckbox = "checkbox"
// CheckboxHorizontalAlign is the constant for the "checkbox-horizontal-align" property tag.
CheckboxHorizontalAlign = "checkbox-horizontal-align"
// CheckboxVerticalAlign is the constant for the "checkbox-vertical-align" property tag.
CheckboxVerticalAlign = "checkbox-vertical-align"
// NotTranslate is the constant for the "not-translate" property tag.
// This bool property indicates that no need to translate the text.
// This is an inherited property, i.e. if it is not defined, then the value of the parent view is used.
NotTranslate = "not-translate"
// Filter is the constant for the "filter" property tag.
// The "filter" property applies graphical effects like blur or color shift to a View.
// The "filter" property applies graphical effects to a View,
// such as such as blurring, color shifting, changing brightness/contrast, etc.
Filter = "filter"
// BackdropFilter is the constant for the "backdrop-filter" property tag.
// The "backdrop-filter" property applies graphical effects to the area behind a View,
// such as such as blurring, color shifting, changing brightness/contrast, etc.
BackdropFilter = "backdrop-filter"
// Clip is the constant for the "clip" property tag.
// The "clip" property creates a clipping region that sets what part of a View should be shown.
Clip = "clip"
// Points is the constant for the "points" property tag.
Points = "points"
// ShapeOutside is the constant for the "shape-outside" property tag.
// The "shape-outside" property defines a shape (which may be non-rectangular) around which adjacent
// inline content should wrap. By default, inline content wraps around its margin box;
// "shape-outside" provides a way to customize this wrapping, making it possible to wrap text around
// complex objects rather than simple boxes.
ShapeOutside = "shape-outside"
// Float is the constant for the "float" property tag.
// The "float" property places a View on the left or right side of its container,
// allowing text and inline Views to wrap around it.
Float = "float"
// UsetData is the constant for the "user-data" property tag.
// This property can contain any user data
// The "user-data" property can contain any user data
UserData = "user-data"
// Resize is the constant for the "resize" property tag.
// The "resize" int property sets whether an element is resizable, and if so, in which directions.
// Valid values are "none" (0), "both" (1), horizontal (2), and "vertical" (3)
Resize = "resize"
)

View File

@ -10,6 +10,7 @@ var colorProperties = []string{
ColorTag,
BackgroundColor,
TextColor,
CaretColor,
BorderColor,
BorderLeftColor,
BorderRightColor,
@ -42,6 +43,7 @@ var boolProperties = []string{
Inset,
BackfaceVisible,
ReadOnly,
EditWrap,
Spellcheck,
CloseButton,
OutsideClose,
@ -276,7 +278,7 @@ var enumProperties = map[string]struct {
"",
[]string{"column", "row", "column-reverse", "row-reverse"},
},
Wrap: {
ListWrap: {
[]string{"off", "on", "reverse"},
"",
[]string{"nowrap", "wrap", "wrap-reverse"},
@ -311,6 +313,11 @@ var enumProperties = map[string]struct {
"justify-items",
[]string{"start", "end", "center", "stretch"},
},
GridAutoFlow: {
[]string{"row", "column", "row-dense", "column-dense"},
GridAutoFlow,
[]string{"row", "column", "row dense", "column dense"},
},
ImageVerticalAlign: {
[]string{"top", "bottom", "center"},
"",
@ -416,6 +423,11 @@ var enumProperties = map[string]struct {
"",
[]string{"none", "cell", "row"},
},
Resize: {
[]string{"none", "both", "horizontal", "vertical"},
"resize",
[]string{"none", "both", "horizontal", "vertical"},
},
}
func notCompatibleType(tag string, value interface{}) {

View File

@ -196,4 +196,33 @@ const (
LeftFloat = 1
// RightFloat - value of the view "float" property: the View must float on the right side of its containing block.
RightFloat = 2
// NoneResize - value of the view "resize" property: the View The offers no user-controllable method for resizing it.
NoneResize = 0
// BothResize - value of the view "resize" property: the View displays a mechanism for allowing
// the user to resize it, which may be resized both horizontally and vertically.
BothResize = 1
// HorizontalResize - value of the view "resize" property: the View displays a mechanism for allowing
// the user to resize it in the horizontal direction.
HorizontalResize = 2
// VerticalResize - value of the view "resize" property: the View displays a mechanism for allowing
// the user to resize it in the vertical direction.
VerticalResize = 3
// RowAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
// Views are placed by filling each row in turn, adding new rows as necessary.
RowAutoFlow = 0
// ColumnAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
// Views are placed by filling each column in turn, adding new columns as necessary.
ColumnAutoFlow = 1
// RowDenseAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
// Views are placed by filling each row, adding new rows as necessary.
// "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.
RowDenseAutoFlow = 2
// ColumnDenseAutoFlow - value of the "grid-auto-flow" property of the GridLayout:
// Views are placed by filling each column, adding new columns as necessary.
// "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.
ColumnDenseAutoFlow = 3
)

View File

@ -400,13 +400,13 @@ func (session *sessionData) handleResize(data DataObject) {
if view := session.viewByHTMLID(viewID[:n]); view != nil {
view.onItemResize(view, viewID[n+1:], getFloat("x"), getFloat("y"), getFloat("width"), getFloat("height"))
} else {
ErrorLogF(`View with id == %s not found`, viewID[:n])
DebugLogF(`View with id == %s not found`, viewID[:n])
}
} else if view := session.viewByHTMLID(viewID); view != nil {
view.onResize(view, getFloat("x"), getFloat("y"), getFloat("width"), getFloat("height"))
view.setScroll(getFloat("scroll-x"), getFloat("scroll-y"), getFloat("scroll-width"), getFloat("scroll-height"))
} else {
ErrorLogF(`View with id == %s not found`, viewID)
DebugLogF(`View with id == %s not found`, viewID)
}
} else {
ErrorLog(`"id" property not found`)

View File

@ -45,7 +45,7 @@ func scanStringsDir(path string) {
}
}
} else {
ErrorLog(err.Error())
DebugLog(err.Error())
}
}

View File

@ -579,7 +579,7 @@ func (table *tableViewData) propertyChanged(tag string) {
CellBorder, HeadHeight, HeadStyle, FootHeight, FootStyle,
CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft,
TableCellClickedEvent, TableCellSelectedEvent, TableRowClickedEvent,
TableRowSelectedEvent, AllowSelection:
TableRowSelectedEvent, AllowSelection, Current:
table.ReloadTableData()
case Gap:
@ -648,6 +648,13 @@ func (table *tableViewData) currentStyle() string {
}
}
}
if value := valueFromStyle(table, CurrentStyle); value != nil {
if style, ok := value.(string); ok {
if style, ok = table.session.resolveConstants(style); ok {
return style
}
}
}
return "ruiCurrentTableCellFocused"
}
@ -659,6 +666,13 @@ func (table *tableViewData) currentInactiveStyle() string {
}
}
}
if value := valueFromStyle(table, CurrentInactiveStyle); value != nil {
if style, ok := value.(string); ok {
if style, ok = table.session.resolveConstants(style); ok {
return style
}
}
}
return "ruiCurrentTableCell"
}
@ -1161,7 +1175,11 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
headFootStart := func(htmlTag, styleTag string) (BorderProperty, BoundsProperty) {
buffer.WriteRune('<')
buffer.WriteString(htmlTag)
if value := table.getRaw(styleTag); value != nil {
value := table.getRaw(styleTag)
if value == nil {
value = valueFromStyle(table, styleTag)
}
if value != nil {
switch value := value.(type) {
case string:
if style, ok := session.resolveConstants(value); ok {

View File

@ -103,8 +103,8 @@ func (tabsLayout *tabsLayoutData) String() string {
return getViewString(tabsLayout)
}
func (tabsLayout *tabsLayoutData) currentItem() int {
result, _ := intProperty(tabsLayout, Current, tabsLayout.session, 0)
func (tabsLayout *tabsLayoutData) currentItem(defaultValue int) int {
result, _ := intProperty(tabsLayout, Current, tabsLayout.session, defaultValue)
return result
}
@ -145,7 +145,7 @@ func (tabsLayout *tabsLayoutData) remove(tag string) {
return
case Current:
oldCurrent := tabsLayout.currentItem()
oldCurrent := tabsLayout.currentItem(0)
delete(tabsLayout.properties, Current)
if oldCurrent == 0 {
return
@ -223,12 +223,12 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
return true
}
oldCurrent := tabsLayout.currentItem()
oldCurrent := tabsLayout.currentItem(-1)
if !tabsLayout.setIntProperty(Current, value) {
return false
}
current := tabsLayout.currentItem()
current := tabsLayout.currentItem(0)
if oldCurrent == current {
return true
}
@ -497,6 +497,13 @@ func (tabsLayout *tabsLayoutData) tabBarStyle() string {
if style, ok := stringProperty(tabsLayout, TabBarStyle, tabsLayout.session); ok {
return style
}
if value := valueFromStyle(tabsLayout, TabBarStyle); value != nil {
if style, ok := value.(string); ok {
if style, ok = tabsLayout.session.resolveConstants(style); ok {
return style
}
}
}
return "ruiTabBar"
}
@ -504,6 +511,13 @@ func (tabsLayout *tabsLayoutData) inactiveTabStyle() string {
if style, ok := stringProperty(tabsLayout, TabStyle, tabsLayout.session); ok {
return style
}
if value := valueFromStyle(tabsLayout, TabStyle); value != nil {
if style, ok := value.(string); ok {
if style, ok = tabsLayout.session.resolveConstants(style); ok {
return style
}
}
}
switch tabsLayout.tabsLocation() {
case LeftTabs, RightTabs:
return "ruiVerticalTab"
@ -515,6 +529,13 @@ func (tabsLayout *tabsLayoutData) activeTabStyle() string {
if style, ok := stringProperty(tabsLayout, CurrentTabStyle, tabsLayout.session); ok {
return style
}
if value := valueFromStyle(tabsLayout, CurrentTabStyle); value != nil {
if style, ok := value.(string); ok {
if style, ok = tabsLayout.session.resolveConstants(style); ok {
return style
}
}
}
switch tabsLayout.tabsLocation() {
case LeftTabs, RightTabs:
return "ruiCurrentVerticalTab"
@ -629,7 +650,7 @@ func (tabsLayout *tabsLayoutData) Insert(view View, index int) {
tabsLayout.views = []View{}
}
if view != nil {
if current := tabsLayout.currentItem(); current >= index {
if current := tabsLayout.currentItem(0); current >= index {
tabsLayout.properties[Current] = current + 1
defer tabsLayout.propertyChangedEvent(Current)
}
@ -658,7 +679,7 @@ func (tabsLayout *tabsLayoutData) RemoveView(index int) View {
view.SetChangeListener(Icon, nil)
view.SetChangeListener(TabCloseButton, nil)
current := tabsLayout.currentItem()
current := tabsLayout.currentItem(0)
if index < current || (index == current && current > 0) {
current--
}
@ -683,7 +704,7 @@ func (tabsLayout *tabsLayoutData) RemoveView(index int) View {
}
func (tabsLayout *tabsLayoutData) currentID() string {
return fmt.Sprintf("%s-%d", tabsLayout.htmlID(), tabsLayout.currentItem())
return fmt.Sprintf("%s-%d", tabsLayout.htmlID(), tabsLayout.currentItem(0))
}
func (tabsLayout *tabsLayoutData) htmlProperties(self View, buffer *strings.Builder) {
@ -720,7 +741,7 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
}
//viewCount := len(tabsLayout.views)
current := tabsLayout.currentItem()
current := tabsLayout.currentItem(0)
location := tabsLayout.tabsLocation()
tabsLayoutID := tabsLayout.htmlID()
@ -798,7 +819,7 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
} else {
buffer.WriteString(inactiveStyle)
}
buffer.WriteString(`" tabindex="0" onclick="tabClickEvent(\'`)
buffer.WriteString(`" tabindex="0" onclick="tabClickEvent(this, \'`)
buffer.WriteString(tabsLayoutID)
buffer.WriteString(`\', `)
buffer.WriteString(strconv.Itoa(n))
@ -840,7 +861,7 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
close = closeButton
}
if close {
buffer.WriteString(`<div class="ruiTabCloseButton" tabindex="0" onclick="tabCloseClickEvent(\'`)
buffer.WriteString(`<div class="ruiTabCloseButton" tabindex="0" onclick="tabCloseClickEvent(this, \'`)
buffer.WriteString(tabsLayoutID)
buffer.WriteString(`\', `)
buffer.WriteString(strconv.Itoa(n))
@ -903,7 +924,7 @@ func (tabsLayout *tabsLayoutData) handleCommand(self View, command string, data
case "tabClick":
if numberText, ok := data.PropertyValue("number"); ok {
if number, err := strconv.Atoi(numberText); err == nil {
current := tabsLayout.currentItem()
current := tabsLayout.currentItem(0)
if current != number {
tabsLayout.properties[Current] = number
for _, listener := range tabsLayout.tabListener {

View File

@ -52,6 +52,10 @@ type Theme interface {
MediaStyle(tag string, orientation, maxWidth, maxHeight int) ViewStyle
SetMediaStyle(tag string, orientation, maxWidth, maxHeight int, style ViewStyle)
StyleTags() []string
MediaStyles(tag string) []struct {
Selectors string
Orientation, MaxWidth, MaxHeight int
}
Append(anotherTheme Theme)
constant(tag string, touchUI bool) string
@ -268,6 +272,10 @@ func (theme *theme) MediaStyle(tag string, orientation, maxWidth, maxHeight int)
}
}
}
if orientation == 0 && maxWidth <= 0 && maxHeight <= 0 {
return theme.style(tag)
}
return nil
}
@ -397,6 +405,60 @@ func (theme *theme) StyleTags() []string {
return keys
}
func (theme *theme) MediaStyles(tag string) []struct {
Selectors string
Orientation, MaxWidth, MaxHeight int
} {
result := []struct {
Selectors string
Orientation, MaxWidth, MaxHeight int
}{}
prefix := tag + ":"
prefixLen := len(prefix)
for themeTag := range theme.styles {
if strings.HasPrefix(themeTag, prefix) {
result = append(result, struct {
Selectors string
Orientation, MaxWidth, MaxHeight int
}{
Selectors: themeTag[prefixLen:],
Orientation: DefaultMedia,
MaxWidth: 0,
MaxHeight: 0,
})
}
}
for _, media := range theme.mediaStyles {
if _, ok := media.styles[tag]; ok {
result = append(result, struct {
Selectors string
Orientation, MaxWidth, MaxHeight int
}{
Selectors: "",
Orientation: media.orientation,
MaxWidth: media.maxWidth,
MaxHeight: media.maxHeight,
})
}
for themeTag := range media.styles {
if strings.HasPrefix(themeTag, prefix) {
result = append(result, struct {
Selectors string
Orientation, MaxWidth, MaxHeight int
}{
Selectors: themeTag[prefixLen:],
Orientation: media.orientation,
MaxWidth: media.maxWidth,
MaxHeight: media.maxHeight,
})
}
}
}
return result
}
func (theme *theme) data() *theme {
return theme
}

16
view.go
View File

@ -495,12 +495,23 @@ func viewPropertyChanged(view *viewData, tag string) {
case Filter:
text := ""
if value := view.getRaw(Filter); value != nil {
if value := view.getRaw(tag); value != nil {
if filter, ok := value.(ViewFilter); ok {
text = filter.cssStyle(session)
}
}
updateCSSProperty(htmlID, Filter, text, session)
updateCSSProperty(htmlID, tag, text, session)
return
case BackdropFilter:
text := ""
if value := view.getRaw(tag); value != nil {
if filter, ok := value.(ViewFilter); ok {
text = filter.cssStyle(session)
}
}
updateCSSProperty(htmlID, "-webkit-backdrop-filter", text, session)
updateCSSProperty(htmlID, tag, text, session)
return
case FontName:
@ -584,6 +595,7 @@ func viewPropertyChanged(view *viewData, tag string) {
BackgroundColor: BackgroundColor,
TextColor: "color",
TextLineColor: "text-decoration-color",
CaretColor: CaretColor,
}
if cssTag, ok := colorTags[tag]; ok {
if color, ok := colorProperty(view, tag, session); ok {

View File

@ -224,35 +224,35 @@ func (filter *viewFilter) cssStyle(session Session) string {
return buffer.String()
}
func (style *viewStyle) setFilter(value interface{}) bool {
func (style *viewStyle) setFilter(tag string, value interface{}) bool {
switch value := value.(type) {
case ViewFilter:
style.properties[Filter] = value
style.properties[tag] = value
return true
case string:
if obj := NewDataObject(value); obj == nil {
if filter := newViewFilter(obj); filter != nil {
style.properties[Filter] = filter
style.properties[tag] = filter
return true
}
}
case DataObject:
if filter := newViewFilter(value); filter != nil {
style.properties[Filter] = filter
style.properties[tag] = filter
return true
}
case DataValue:
if value.IsObject() {
if filter := newViewFilter(value.Object()); filter != nil {
style.properties[Filter] = filter
style.properties[tag] = filter
return true
}
}
}
notCompatibleType(Filter, value)
notCompatibleType(tag, value)
return false
}
@ -272,3 +272,20 @@ func GetFilter(view View, subviewID string) ViewFilter {
return nil
}
// GetBackdropFilter returns the area behind a View graphical effects like blur or color shift.
// If the second argument (subviewID) is "" then a top position of the first argument (view) is returned
func GetBackdropFilter(view View, subviewID string) ViewFilter {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if value := view.getRaw(BackdropFilter); value != nil {
if filter, ok := value.(ViewFilter); ok {
return filter
}
}
}
return nil
}

View File

@ -213,6 +213,7 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
{BackgroundColor, BackgroundColor},
{TextColor, "color"},
{TextLineColor, "text-decoration-color"},
{CaretColor, CaretColor},
}
for _, p := range colorProperties {
if color, ok := colorProperty(style, p.property, session); ok && color != 0 {
@ -235,8 +236,8 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
writingMode := 0
for _, tag := range []string{
TextAlign, TextTransform, TextWeight, TextLineStyle, WritingMode, TextDirection,
VerticalTextOrientation, CellVerticalAlign, CellHorizontalAlign, Cursor, WhiteSpace,
WordBreak, TextOverflow, Float, TableVerticalAlign} {
VerticalTextOrientation, CellVerticalAlign, CellHorizontalAlign, GridAutoFlow, Cursor,
WhiteSpace, WordBreak, TextOverflow, Float, TableVerticalAlign, Resize} {
if data, ok := enumProperties[tag]; ok {
if tag != VerticalTextOrientation || (writingMode != VerticalLeftToRight && writingMode != VerticalRightToLeft) {
@ -295,15 +296,15 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
}
}
wrap, _ := enumProperty(style, Wrap, session, 0)
wrap, _ := enumProperty(style, ListWrap, session, 0)
orientation, ok := valueToOrientation(style.Get(Orientation), session)
if ok || wrap > 0 {
cssText := enumProperties[Orientation].cssValues[orientation]
switch wrap {
case WrapOn:
case ListWrapOn:
cssText += " wrap"
case WrapReverse:
case ListWrapReverse:
cssText += " wrap-reverse"
}
builder.add(`flex-flow`, cssText)
@ -323,13 +324,13 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
if align, ok := enumProperty(style, HorizontalAlign, session, LeftAlign); ok {
switch align {
case LeftAlign:
if (!rows && wrap == WrapReverse) || orientation == EndToStartOrientation {
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
builder.add(hAlignTag, `flex-end`)
} else {
builder.add(hAlignTag, `flex-start`)
}
case RightAlign:
if (!rows && wrap == WrapReverse) || orientation == EndToStartOrientation {
if (!rows && wrap == ListWrapReverse) || orientation == EndToStartOrientation {
builder.add(hAlignTag, `flex-start`)
} else {
builder.add(hAlignTag, `flex-end`)
@ -349,13 +350,13 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
if align, ok := enumProperty(style, VerticalAlign, session, LeftAlign); ok {
switch align {
case TopAlign:
if (rows && wrap == WrapReverse) || orientation == BottomUpOrientation {
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
builder.add(vAlignTag, `flex-end`)
} else {
builder.add(vAlignTag, `flex-start`)
}
case BottomAlign:
if (rows && wrap == WrapReverse) || orientation == BottomUpOrientation {
if (rows && wrap == ListWrapReverse) || orientation == BottomUpOrientation {
builder.add(vAlignTag, `flex-start`)
} else {
builder.add(vAlignTag, `flex-end`)
@ -400,7 +401,16 @@ func (style *viewStyle) cssViewStyle(builder cssBuilder, session Session) {
if value := style.getRaw(Filter); value != nil {
if filter, ok := value.(ViewFilter); ok {
if text := filter.cssStyle(session); text != "" {
builder.add(`filter`, text)
builder.add(Filter, text)
}
}
}
if value := style.getRaw(BackdropFilter); value != nil {
if filter, ok := value.(ViewFilter); ok {
if text := filter.cssStyle(session); text != "" {
builder.add(`-webkit-backdrop-filter`, text)
builder.add(BackdropFilter, text)
}
}
}
@ -765,10 +775,10 @@ func writeViewStyle(name string, view ViewStyle, buffer *strings.Builder, indent
ID, Row, Column, Top, Right, Bottom, Left, Semantics, Cursor, Visibility,
Opacity, ZIndex, Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight,
Margin, Padding, BackgroundClip, BackgroundColor, Background, Border, Radius, Outline, Shadow,
Orientation, Wrap, VerticalAlign, HorizontalAlign, CellWidth, CellHeight,
Orientation, ListWrap, VerticalAlign, HorizontalAlign, CellWidth, CellHeight,
CellVerticalAlign, CellHorizontalAlign, GridRowGap, GridColumnGap,
ColumnCount, ColumnWidth, ColumnSeparator, ColumnGap, AvoidBreak,
Current, Expanded, Side, ResizeBorderWidth, EditViewType, MaxLength, Hint, Text,
Current, Expanded, Side, ResizeBorderWidth, EditViewType, MaxLength, Hint, Text, EditWrap,
TextOverflow, FontName, TextSize, TextColor, TextWeight, Italic, SmallCaps,
Strikethrough, Overline, Underline, TextLineStyle, TextLineThickness,
TextLineColor, TextTransform, TextAlign, WhiteSpace, WordBreak, TextShadow, TextIndent,
@ -785,7 +795,7 @@ func writeViewStyle(name string, view ViewStyle, buffer *strings.Builder, indent
finalTags := []string{
Perspective, PerspectiveOriginX, PerspectiveOriginY, BackfaceVisible, OriginX, OriginY, OriginZ,
TranslateX, TranslateY, TranslateZ, ScaleX, ScaleY, ScaleZ, Rotate, RotateX, RotateY, RotateZ,
SkewX, SkewY, Clip, Filter, Summary, Content, Transition}
SkewX, SkewY, Clip, Filter, BackdropFilter, Summary, Content, Transition}
for _, tag := range finalTags {
removeTag(tag)
}

View File

@ -265,8 +265,8 @@ func (style *viewStyle) set(tag string, value interface{}) bool {
case Clip, ShapeOutside:
return style.setClipShape(tag, value)
case Filter:
return style.setFilter(value)
case Filter, BackdropFilter:
return style.setFilter(tag, value)
case Transition:
setObject := func(obj DataObject) bool {

View File

@ -241,6 +241,20 @@ func GetMaxHeight(view View, subviewID string) SizeUnit {
return result
}
// GetResize returns the "resize" property value if the subview. One of the following values is returned:
// NoneResize (0), BothResize (1), HorizontalResize (2), or VerticalResize (3)
// If the second argument (subviewID) is "" then a value of the first argument (view) is returned
func GetResize(view View, subviewID string) int {
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view == nil {
return 0
}
result, _ := enumStyledProperty(view, Resize, 0)
return result
}
// GetLeft returns a left position of the subview in an AbsoluteLayout container.
// If a parent view is not an AbsoluteLayout container then this value is ignored.
// If the second argument (subviewID) is "" then a left position of the first argument (view) is returned
@ -1036,18 +1050,36 @@ func colorStyledProperty(view View, tag string) (Color, bool) {
return Color(0), false
}
// FocusView sets focus on the specified View, if it can be focused.
// The focused View is the View which will receive keyboard events by default.
func FocusView(view View) {
if view != nil {
view.Session().runScript("focus('" + view.htmlID() + "')")
}
}
// FocusView sets focus on the View with the specified viewID, if it can be focused.
// The focused View is the View which will receive keyboard events by default.
func FocusViewByID(viewID string, session Session) {
if viewID != "" {
session.runScript("focus('" + viewID + "')")
}
}
// BlurView removes keyboard focus from the specified View.
func BlurView(view View) {
if view != nil {
view.Session().runScript("blur('" + view.htmlID() + "')")
}
}
// BlurViewByID removes keyboard focus from the View with the specified viewID.
func BlurViewByID(viewID string, session Session) {
if viewID != "" {
session.runScript("blur('" + viewID + "')")
}
}
// GetCurrent returns the index of the selected item (<0 if there is no a selected item) or the current view index (StackLayout, TabsLayout).
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
func GetCurrent(view View, subviewID string) int {