mirror of https://github.com/anoshenko/rui.git
Added: "focusable" and "user-data" properties, ConstantTags and ColorTags function to Session, ReloadTableViewData function. Bug fixing
This commit is contained in:
parent
1e3c820c61
commit
8a625dcc78
|
@ -9,8 +9,8 @@
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
"program": "${workspaceRoot}/demo",
|
//"program": "${workspaceRoot}/demo",
|
||||||
//"program": "${workspaceRoot}/editor",
|
"program": "${workspaceRoot}/ruiEditor",
|
||||||
"env": {},
|
"env": {},
|
||||||
"args": []
|
"args": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
# v0.6.0
|
||||||
|
|
||||||
|
* Added "user-data" property
|
||||||
|
* Added "focusable" property
|
||||||
|
* Added ReloadTableViewData function
|
||||||
|
|
||||||
# v0.5.0
|
# v0.5.0
|
||||||
|
|
||||||
* NewApplication function and Start function of the Application interface were replaced by StartApp function
|
* NewApplication function and Start function of the Application interface were replaced by StartApp function
|
||||||
|
|
28
README-ru.md
28
README-ru.md
|
@ -1679,6 +1679,10 @@ radius необходимо передать nil
|
||||||
|
|
||||||
func GetSkew(view View, subviewID string) (AngleUnit, AngleUnit)
|
func GetSkew(view View, subviewID string) (AngleUnit, AngleUnit)
|
||||||
|
|
||||||
|
### Пользовательские данные
|
||||||
|
|
||||||
|
Вы можете сохранить любые ваши данные в виде свойства "user-data" (константа UserData)
|
||||||
|
|
||||||
### События клавиатуры
|
### События клавиатуры
|
||||||
|
|
||||||
Для View получившего фокус ввода могут генерироваться два вида событий клавиатуры
|
Для View получившего фокус ввода могут генерироваться два вида событий клавиатуры
|
||||||
|
@ -2682,16 +2686,16 @@ EditTextChangedEvent). Основной слушатель события име
|
||||||
func NewNumberPicker(session Session, params Params) NumberPicker
|
func NewNumberPicker(session Session, params Params) NumberPicker
|
||||||
|
|
||||||
NumberPicker может работать в двух режимах: редактор текста и слайдер.
|
NumberPicker может работать в двух режимах: редактор текста и слайдер.
|
||||||
Режим устанавливает int свойство "date-picker-type" (константа NumberPickerType).
|
Режим устанавливает int свойство "number-picker-type" (константа NumberPickerType).
|
||||||
Свойство "date-picker-type" может принимать следующие значения:
|
Свойство "number-picker-type" может принимать следующие значения:
|
||||||
|
|
||||||
| Значение | Константа | Имя | Тип редактора |
|
| Значение | Константа | Имя | Тип редактора |
|
||||||
|:--------:|--------------|----------|----------------------------------------|
|
|:--------:|--------------|----------|----------------------------------------|
|
||||||
| 0 | NumberEditor | "editor" | Редактор текста. Значение по умолчанию |
|
| 0 | NumberEditor | "editor" | Редактор текста. Значение по умолчанию |
|
||||||
| 1 | NumberSlider | "slider" | Слайдер |
|
| 1 | NumberSlider | "slider" | Слайдер |
|
||||||
|
|
||||||
Установить/прочитать текущее значение можно с помощью свойства "date-picker-value"
|
Установить/прочитать текущее значение можно с помощью свойства "number-picker-value"
|
||||||
(константа NumberPickerValue). В качестве значения свойству "date-picker-value" могут быть переданы:
|
(константа NumberPickerValue). В качестве значения свойству "number-picker-value" могут быть переданы:
|
||||||
|
|
||||||
* float64
|
* float64
|
||||||
* float32
|
* float32
|
||||||
|
@ -2702,7 +2706,7 @@ NumberPicker может работать в двух режимах: редак
|
||||||
* текстовое представление любых из выше перечисленых типов
|
* текстовое представление любых из выше перечисленых типов
|
||||||
|
|
||||||
Все эти типы приводятся к float64. Соответственно функция Get всегда возвращает float64 значение.
|
Все эти типы приводятся к float64. Соответственно функция Get всегда возвращает float64 значение.
|
||||||
Прочитано значение свойства "date-picker-value" может быть также с помощью функции:
|
Прочитано значение свойства "number-picker-value" может быть также с помощью функции:
|
||||||
|
|
||||||
func GetNumberPickerValue(view View, subviewID string) float64
|
func GetNumberPickerValue(view View, subviewID string) float64
|
||||||
|
|
||||||
|
@ -2710,14 +2714,14 @@ NumberPicker может работать в двух режимах: редак
|
||||||
|
|
||||||
| Свойство | Константа | Ограничение |
|
| Свойство | Константа | Ограничение |
|
||||||
|----------------------|------------------|------------------------|
|
|----------------------|------------------|------------------------|
|
||||||
| "date-picker-min" | NumberPickerMin | Минимальное значение |
|
| "number-picker-min" | NumberPickerMin | Минимальное значение |
|
||||||
| "date-picker-max" | NumberPickerMax | Максимальное значение |
|
| "number-picker-max" | NumberPickerMax | Максимальное значение |
|
||||||
| "date-picker-step" | NumberPickerStep | Шаг изменения значения |
|
| "number-picker-step" | NumberPickerStep | Шаг изменения значения |
|
||||||
|
|
||||||
Присвоины данным свойствам могут те же типы значений, что и "date-picker-value".
|
Присвоины данным свойствам могут те же типы значений, что и "number-picker-value".
|
||||||
|
|
||||||
По умолчанию, в случае если "date-picker-type" равно NumberSlider, минимальное значение равно 0,
|
По умолчанию, в случае если "number-picker-type" равно NumberSlider, минимальное значение равно 0,
|
||||||
максимальное - 1. Если же "date-picker-type" равно NumberEditor то вводимые числа, по умолчанию,
|
максимальное - 1. Если же "number-picker-type" равно NumberEditor то вводимые числа, по умолчанию,
|
||||||
ограничены лишь диапазоном значений float64.
|
ограничены лишь диапазоном значений float64.
|
||||||
|
|
||||||
Прочитать значения данных свойств можно с помощью функций:
|
Прочитать значения данных свойств можно с помощью функций:
|
||||||
|
@ -2725,7 +2729,7 @@ NumberPicker может работать в двух режимах: редак
|
||||||
func GetNumberPickerMinMax(view View, subviewID string) (float64, float64)
|
func GetNumberPickerMinMax(view View, subviewID string) (float64, float64)
|
||||||
func GetNumberPickerStep(view View, subviewID string) float64
|
func GetNumberPickerStep(view View, subviewID string) float64
|
||||||
|
|
||||||
Для отслеживания изменения вводимого значения используется событие "date-changed" (константа
|
Для отслеживания изменения вводимого значения используется событие "number-changed" (константа
|
||||||
NumberChangedEvent). Основной слушатель события имеет следующий формат:
|
NumberChangedEvent). Основной слушатель события имеет следующий формат:
|
||||||
|
|
||||||
func(picker NumberPicker, newValue float64)
|
func(picker NumberPicker, newValue float64)
|
||||||
|
|
32
README.md
32
README.md
|
@ -1654,6 +1654,10 @@ You can get the value of these properties using the function
|
||||||
|
|
||||||
func GetSkew(view View, subviewID string) (AngleUnit, AngleUnit)
|
func GetSkew(view View, subviewID string) (AngleUnit, AngleUnit)
|
||||||
|
|
||||||
|
### User data
|
||||||
|
|
||||||
|
You can save any of your data as "user-data" property (UserData constant)
|
||||||
|
|
||||||
### Keyboard events
|
### Keyboard events
|
||||||
|
|
||||||
Two kinds of keyboard events can be generated for a View that has received input focus.
|
Two kinds of keyboard events can be generated for a View that has received input focus.
|
||||||
|
@ -2648,16 +2652,16 @@ To create a NumberPicker, the function is used:
|
||||||
func NewNumberPicker(session Session, params Params) NumberPicker
|
func NewNumberPicker(session Session, params Params) NumberPicker
|
||||||
|
|
||||||
NumberPicker can work in two modes: text editor and slider.
|
NumberPicker can work in two modes: text editor and slider.
|
||||||
The mode sets the int property "date-picker-type" (NumberPickerType constant).
|
The mode sets the int property "number-picker-type" (NumberPickerType constant).
|
||||||
The "date-picker-type" property can take the following values:
|
The "number-picker-type" property can take the following values:
|
||||||
|
|
||||||
| Value | Constant | Name | Editor type |
|
| Value | Constant | Name | Editor type |
|
||||||
|:-----:|--------------|----------|----------------------------|
|
|:-----:|--------------|----------|----------------------------|
|
||||||
| 0 | NumberEditor | "editor" | Text editor. Default value |
|
| 0 | NumberEditor | "editor" | Text editor. Default value |
|
||||||
| 1 | NumberSlider | "slider" | Slider |
|
| 1 | NumberSlider | "slider" | Slider |
|
||||||
|
|
||||||
You can set/get the current value using the "date-picker-value" property (NumberPickerValue constant).
|
You can set/get the current value using the "number-picker-value" property (NumberPickerValue constant).
|
||||||
The following can be passed as a value to the "date-picker-value" property:
|
The following can be passed as a value to the "number-picker-value" property:
|
||||||
|
|
||||||
* float64
|
* float64
|
||||||
* float32
|
* float32
|
||||||
|
@ -2668,29 +2672,29 @@ The following can be passed as a value to the "date-picker-value" property:
|
||||||
* textual representation of any of the above types
|
* textual representation of any of the above types
|
||||||
|
|
||||||
All of these types are cast to float64. Accordingly, the Get function always returns a float64 value.
|
All of these types are cast to float64. Accordingly, the Get function always returns a float64 value.
|
||||||
The value of the "date-picker-value" property can also be read using the function:
|
The value of the "number-picker-value" property can also be read using the function:
|
||||||
|
|
||||||
func GetNumberPickerValue(view View, subviewID string) float64
|
func GetNumberPickerValue(view View, subviewID string) float64
|
||||||
|
|
||||||
The entered values may be subject to restrictions. For this, the following properties are used:
|
The entered values may be subject to restrictions. For this, the following properties are used:
|
||||||
|
|
||||||
| Property | Constant | Restriction |
|
| Property | Constant | Restriction |
|
||||||
|--------------------|------------------|-------------------|
|
|----------------------|------------------|-------------------|
|
||||||
| "date-picker-min" | NumberPickerMin | Minimum value |
|
| "number-picker-min" | NumberPickerMin | Minimum value |
|
||||||
| "date-picker-max" | NumberPickerMax | Maximum value |
|
| "number-picker-max" | NumberPickerMax | Maximum value |
|
||||||
| "date-picker-step" | NumberPickerStep | Value change step |
|
| "number-picker-step" | NumberPickerStep | Value change step |
|
||||||
|
|
||||||
Assignments to these properties can be the same value types as "date-picker-value".
|
Assignments to these properties can be the same value types as "number-picker-value".
|
||||||
|
|
||||||
By default, if "date-picker-type" is equal to NumberSlider, the minimum value is 0, maximum is 1.
|
By default, if "number-picker-type" is equal to NumberSlider, the minimum value is 0, maximum is 1.
|
||||||
If "date-picker-type" is equal to NumberEditor, then the entered numbers, by default, are limited only by the range of float64 values.
|
If "number-picker-type" is equal to NumberEditor, then the entered numbers, by default, are limited only by the range of float64 values.
|
||||||
|
|
||||||
You can read the values of these properties using the functions:
|
You can read the values of these properties using the functions:
|
||||||
|
|
||||||
func GetNumberPickerMinMax(view View, subviewID string) (float64, float64)
|
func GetNumberPickerMinMax(view View, subviewID string) (float64, float64)
|
||||||
func GetNumberPickerStep(view View, subviewID string) float64
|
func GetNumberPickerStep(view View, subviewID string) float64
|
||||||
|
|
||||||
The "date-changed" event (NumberChangedEvent constant) is used to track the change in the entered value.
|
The "number-changed" event (NumberChangedEvent constant) is used to track the change in the entered value.
|
||||||
The main event listener has the following format:
|
The main event listener has the following format:
|
||||||
|
|
||||||
func(picker NumberPicker, newValue float64)
|
func(picker NumberPicker, newValue float64)
|
||||||
|
|
|
@ -1759,7 +1759,7 @@ function tableRowClickEvent(element, event) {
|
||||||
const table = document.getElementById(tableID);
|
const table = document.getElementById(tableID);
|
||||||
if (table) {
|
if (table) {
|
||||||
const selection = table.getAttribute("data-selection");
|
const selection = table.getAttribute("data-selection");
|
||||||
if (selection == "cell") {
|
if (selection == "row") {
|
||||||
const currentID = table.getAttribute("data-current");
|
const currentID = table.getAttribute("data-current");
|
||||||
if (!currentID || currentID != element.ID) {
|
if (!currentID || currentID != element.ID) {
|
||||||
setTableRowCursor(table, row)
|
setTableRowCursor(table, row)
|
||||||
|
|
|
@ -21,13 +21,25 @@ div:focus {
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
padding: 4px;
|
margin: 2px;
|
||||||
overflow: auto;
|
padding: 1px;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
margin: 2px;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
padding: 4px;
|
margin: 2px;
|
||||||
|
padding: 1px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul:focus {
|
ul:focus {
|
||||||
|
|
|
@ -65,7 +65,7 @@ theme {
|
||||||
styles = [
|
styles = [
|
||||||
ruiApp {
|
ruiApp {
|
||||||
font-name = "Arial, Helvetica, sans-serif",
|
font-name = "Arial, Helvetica, sans-serif",
|
||||||
text-size = 12pt,
|
text-size = 10pt,
|
||||||
text-color = @ruiTextColor,
|
text-color = @ruiTextColor,
|
||||||
background-color = @ruiBackgroundColor,
|
background-color = @ruiBackgroundColor,
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,6 +9,9 @@ const (
|
||||||
StyleDisabled = "style-disabled"
|
StyleDisabled = "style-disabled"
|
||||||
// Disabled is the constant for the "disabled" property tag.
|
// Disabled is the constant for the "disabled" property tag.
|
||||||
Disabled = "disabled"
|
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.
|
// Semantics is the constant for the "semantics" property tag.
|
||||||
Semantics = "semantics"
|
Semantics = "semantics"
|
||||||
// Visibility is the constant for the "visibility" property tag.
|
// Visibility is the constant for the "visibility" property tag.
|
||||||
|
@ -440,4 +443,7 @@ const (
|
||||||
// The "float" property places a View on the left or right side of its container,
|
// The "float" property places a View on the left or right side of its container,
|
||||||
// allowing text and inline Views to wrap around it.
|
// allowing text and inline Views to wrap around it.
|
||||||
Float = "float"
|
Float = "float"
|
||||||
|
// UsetData is the constant for the "user-data" property tag.
|
||||||
|
// This property can contain any user data
|
||||||
|
UserData = "user-data"
|
||||||
)
|
)
|
||||||
|
|
|
@ -37,6 +37,7 @@ var angleProperties = []string{
|
||||||
|
|
||||||
var boolProperties = []string{
|
var boolProperties = []string{
|
||||||
Disabled,
|
Disabled,
|
||||||
|
Focusable,
|
||||||
Inset,
|
Inset,
|
||||||
BackfaceVisible,
|
BackfaceVisible,
|
||||||
ReadOnly,
|
ReadOnly,
|
||||||
|
|
52
session.go
52
session.go
|
@ -29,8 +29,12 @@ type Session interface {
|
||||||
TextDirection() int
|
TextDirection() int
|
||||||
// Constant returns the constant with "tag" name or "" if it is not exists
|
// Constant returns the constant with "tag" name or "" if it is not exists
|
||||||
Constant(tag string) (string, bool)
|
Constant(tag string) (string, bool)
|
||||||
|
// ConstantTags returns the list of all available constants
|
||||||
|
ConstantTags() []string
|
||||||
// Color returns the color with "tag" name or 0 if it is not exists
|
// Color returns the color with "tag" name or 0 if it is not exists
|
||||||
Color(tag string) (Color, bool)
|
Color(tag string) (Color, bool)
|
||||||
|
// ColorTags returns the list of all available color constants
|
||||||
|
ColorTags() []string
|
||||||
// SetCustomTheme set the custom theme
|
// SetCustomTheme set the custom theme
|
||||||
SetCustomTheme(name string) bool
|
SetCustomTheme(name string) bool
|
||||||
// UserAgent returns the "user-agent" text of the client browser
|
// UserAgent returns the "user-agent" text of the client browser
|
||||||
|
@ -106,6 +110,7 @@ type Session interface {
|
||||||
|
|
||||||
type sessionData struct {
|
type sessionData struct {
|
||||||
customTheme *theme
|
customTheme *theme
|
||||||
|
currentTheme *theme
|
||||||
darkTheme bool
|
darkTheme bool
|
||||||
touchScreen bool
|
touchScreen bool
|
||||||
textDirection int
|
textDirection int
|
||||||
|
@ -146,6 +151,7 @@ func newSession(app Application, id int, customTheme string, params DataObject)
|
||||||
if customTheme != "" {
|
if customTheme != "" {
|
||||||
if theme, ok := newTheme(customTheme); ok {
|
if theme, ok := newTheme(customTheme); ok {
|
||||||
session.customTheme = theme
|
session.customTheme = theme
|
||||||
|
session.currentTheme = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,18 +212,11 @@ func (session *sessionData) close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) styleProperty(styleTag, propertyTag string) (string, bool) {
|
func (session *sessionData) styleProperty(styleTag, propertyTag string) (string, bool) {
|
||||||
var style DataObject
|
if style, ok := session.getCurrentTheme().styles[styleTag]; ok {
|
||||||
ok := false
|
if value, ok := style[propertyTag]; ok {
|
||||||
if session.customTheme != nil {
|
if text, ok := value.(string); ok {
|
||||||
style, ok = session.customTheme.styles[styleTag]
|
return session.resolveConstants(text)
|
||||||
}
|
}
|
||||||
if !ok {
|
|
||||||
style, ok = defaultTheme.styles[styleTag]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
if node := style.PropertyWithTag(propertyTag); node != nil && node.Type() == TextNode {
|
|
||||||
return session.resolveConstants(node.Text())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,17 +225,12 @@ func (session *sessionData) styleProperty(styleTag, propertyTag string) (string,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) stylePropertyNode(styleTag, propertyTag string) DataNode {
|
func (session *sessionData) stylePropertyNode(styleTag, propertyTag string) DataNode {
|
||||||
var style DataObject
|
if style, ok := session.getCurrentTheme().styles[styleTag]; ok {
|
||||||
ok := false
|
if value, ok := style[propertyTag]; ok {
|
||||||
if session.customTheme != nil {
|
if node, ok := value.(DataNode); ok {
|
||||||
style, ok = session.customTheme.styles[styleTag]
|
return node
|
||||||
}
|
}
|
||||||
if !ok {
|
}
|
||||||
style, ok = defaultTheme.styles[styleTag]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
return style.PropertyWithTag(propertyTag)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -280,17 +274,7 @@ func (session *sessionData) RootView() View {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) writeInitScript(writer *strings.Builder) {
|
func (session *sessionData) writeInitScript(writer *strings.Builder) {
|
||||||
var workTheme *theme
|
if css := session.getCurrentTheme().cssText(session); css != "" {
|
||||||
if session.customTheme == nil {
|
|
||||||
workTheme = defaultTheme
|
|
||||||
} else {
|
|
||||||
workTheme = new(theme)
|
|
||||||
workTheme.init()
|
|
||||||
workTheme.concat(defaultTheme)
|
|
||||||
workTheme.concat(session.customTheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
if css := workTheme.cssText(session); css != "" {
|
|
||||||
writer.WriteString(`document.querySelector('style').textContent += "`)
|
writer.WriteString(`document.querySelector('style').textContent += "`)
|
||||||
writer.WriteString(css)
|
writer.WriteString(css)
|
||||||
writer.WriteString("\";\n")
|
writer.WriteString("\";\n")
|
||||||
|
|
105
sessionTheme.go
105
sessionTheme.go
|
@ -2,24 +2,10 @@ package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
type Session struct {
|
|
||||||
customTheme *theme
|
|
||||||
darkTheme bool
|
|
||||||
touchScreen bool
|
|
||||||
textDirection int
|
|
||||||
pixelRatio float64
|
|
||||||
language string
|
|
||||||
languages []string
|
|
||||||
checkboxOff string
|
|
||||||
checkboxOn string
|
|
||||||
radiobuttonOff string
|
|
||||||
radiobuttonOn string
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (session *sessionData) DarkTheme() bool {
|
func (session *sessionData) DarkTheme() bool {
|
||||||
return session.darkTheme
|
return session.darkTheme
|
||||||
}
|
}
|
||||||
|
@ -39,27 +25,17 @@ func (session *sessionData) TextDirection() int {
|
||||||
func (session *sessionData) constant(tag string, prevTags []string) (string, bool) {
|
func (session *sessionData) constant(tag string, prevTags []string) (string, bool) {
|
||||||
tags := append(prevTags, tag)
|
tags := append(prevTags, tag)
|
||||||
result := ""
|
result := ""
|
||||||
themes := session.themes()
|
theme := session.getCurrentTheme()
|
||||||
for {
|
for {
|
||||||
ok := false
|
ok := false
|
||||||
if session.touchScreen {
|
if session.touchScreen {
|
||||||
for _, theme := range themes {
|
if theme.touchConstants != nil {
|
||||||
if theme.touchConstants != nil {
|
result, ok = theme.touchConstants[tag]
|
||||||
if result, ok = theme.touchConstants[tag]; ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
for _, theme := range themes {
|
result, ok = theme.constants[tag]
|
||||||
if theme.constants != nil {
|
|
||||||
if result, ok = theme.constants[tag]; ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -149,38 +125,38 @@ func (session *sessionData) Constant(tag string) (string, bool) {
|
||||||
return session.constant(tag, []string{})
|
return session.constant(tag, []string{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) themes() []*theme {
|
func (session *sessionData) getCurrentTheme() *theme {
|
||||||
if session.customTheme != nil {
|
if session.currentTheme != nil {
|
||||||
return []*theme{session.customTheme, defaultTheme}
|
return session.currentTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
return []*theme{defaultTheme}
|
if session.customTheme != nil {
|
||||||
|
session.currentTheme = new(theme)
|
||||||
|
session.currentTheme.init()
|
||||||
|
session.currentTheme.concat(defaultTheme)
|
||||||
|
session.currentTheme.concat(session.customTheme)
|
||||||
|
return session.currentTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color return the color with "tag" name or 0 if it is not exists
|
// Color return the color with "tag" name or 0 if it is not exists
|
||||||
func (session *sessionData) Color(tag string) (Color, bool) {
|
func (session *sessionData) Color(tag string) (Color, bool) {
|
||||||
tags := []string{tag}
|
tags := []string{tag}
|
||||||
result := ""
|
result := ""
|
||||||
themes := session.themes()
|
theme := session.getCurrentTheme()
|
||||||
for {
|
for {
|
||||||
ok := false
|
ok := false
|
||||||
if session.darkTheme {
|
if session.darkTheme {
|
||||||
for _, theme := range themes {
|
if theme.darkColors != nil {
|
||||||
if theme.darkColors != nil {
|
result, ok = theme.darkColors[tag]
|
||||||
if result, ok = theme.darkColors[tag]; ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
for _, theme := range themes {
|
if theme.colors != nil {
|
||||||
if theme.colors != nil {
|
result, ok = theme.colors[tag]
|
||||||
if result, ok = theme.colors[tag]; ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +193,7 @@ func (session *sessionData) SetCustomTheme(name string) bool {
|
||||||
}
|
}
|
||||||
} else if theme, ok := resources.themes[name]; ok {
|
} else if theme, ok := resources.themes[name]; ok {
|
||||||
session.customTheme = theme
|
session.customTheme = theme
|
||||||
|
session.currentTheme = nil
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -361,3 +338,39 @@ func (session *sessionData) SetLanguage(lang string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) ConstantTags() []string {
|
||||||
|
theme := session.getCurrentTheme()
|
||||||
|
|
||||||
|
keys := make([]string, 0, len(theme.constants))
|
||||||
|
for k := range theme.constants {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag := range theme.touchConstants {
|
||||||
|
if _, ok := theme.constants[tag]; !ok {
|
||||||
|
keys = append(keys, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) ColorTags() []string {
|
||||||
|
theme := session.getCurrentTheme()
|
||||||
|
|
||||||
|
keys := make([]string, 0, len(theme.colors))
|
||||||
|
for k := range theme.colors {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
for tag := range theme.darkColors {
|
||||||
|
if _, ok := theme.colors[tag]; !ok {
|
||||||
|
keys = append(keys, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
|
@ -230,3 +230,21 @@ func GetTableRowSelectedListeners(view View, subviewID string) []func(TableView,
|
||||||
}
|
}
|
||||||
return []func(TableView, int){}
|
return []func(TableView, int){}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReloadTableViewData updates TableView
|
||||||
|
func ReloadTableViewData(view View, subviewID string) bool {
|
||||||
|
var tableView TableView
|
||||||
|
if subviewID != "" {
|
||||||
|
if tableView = TableViewByID(view, subviewID); tableView == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var ok bool
|
||||||
|
if tableView, ok = view.(TableView); !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tableView.ReloadTableData()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ func (tabsLayout *tabsLayoutData) remove(tag string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if tabsLayout.created {
|
if tabsLayout.created {
|
||||||
tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), 0))
|
tabsLayout.session.runScript(fmt.Sprintf("activateTab('%v', %d);", tabsLayout.htmlID(), 0))
|
||||||
for _, listener := range tabsLayout.tabListener {
|
for _, listener := range tabsLayout.tabListener {
|
||||||
listener(tabsLayout, 0, oldCurrent)
|
listener(tabsLayout, 0, oldCurrent)
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if tabsLayout.created {
|
if tabsLayout.created {
|
||||||
tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), current))
|
tabsLayout.session.runScript(fmt.Sprintf("activateTab('%v', %d);", tabsLayout.htmlID(), current))
|
||||||
for _, listener := range tabsLayout.tabListener {
|
for _, listener := range tabsLayout.tabListener {
|
||||||
listener(tabsLayout, current, oldCurrent)
|
listener(tabsLayout, current, oldCurrent)
|
||||||
}
|
}
|
||||||
|
|
39
theme.go
39
theme.go
|
@ -16,7 +16,7 @@ type mediaStyle struct {
|
||||||
orientation int
|
orientation int
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
styles map[string]DataObject
|
styles map[string]Params
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rule mediaStyle) cssText() string {
|
func (rule mediaStyle) cssText() string {
|
||||||
|
@ -47,7 +47,7 @@ func (rule mediaStyle) cssText() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseMediaRule(text string) (mediaStyle, bool) {
|
func parseMediaRule(text string) (mediaStyle, bool) {
|
||||||
rule := mediaStyle{orientation: defaultMedia, width: 0, height: 0, styles: map[string]DataObject{}}
|
rule := mediaStyle{orientation: defaultMedia, width: 0, height: 0, styles: map[string]Params{}}
|
||||||
elements := strings.Split(text, ":")
|
elements := strings.Split(text, ":")
|
||||||
for i := 1; i < len(elements); i++ {
|
for i := 1; i < len(elements); i++ {
|
||||||
switch element := elements[i]; element {
|
switch element := elements[i]; element {
|
||||||
|
@ -111,7 +111,7 @@ type theme struct {
|
||||||
touchConstants map[string]string
|
touchConstants map[string]string
|
||||||
colors map[string]string
|
colors map[string]string
|
||||||
darkColors map[string]string
|
darkColors map[string]string
|
||||||
styles map[string]DataObject
|
styles map[string]Params
|
||||||
mediaStyles []mediaStyle
|
mediaStyles []mediaStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ func (theme *theme) init() {
|
||||||
theme.touchConstants = map[string]string{}
|
theme.touchConstants = map[string]string{}
|
||||||
theme.colors = map[string]string{}
|
theme.colors = map[string]string{}
|
||||||
theme.darkColors = map[string]string{}
|
theme.darkColors = map[string]string{}
|
||||||
theme.styles = map[string]DataObject{}
|
theme.styles = map[string]Params{}
|
||||||
theme.mediaStyles = []mediaStyle{}
|
theme.mediaStyles = []mediaStyle{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,9 @@ func (theme *theme) cssText(session Session) string {
|
||||||
for tag, obj := range theme.styles {
|
for tag, obj := range theme.styles {
|
||||||
var style viewStyle
|
var style viewStyle
|
||||||
style.init()
|
style.init()
|
||||||
parseProperties(&style, obj)
|
for tag, value := range obj {
|
||||||
|
style.Set(tag, value)
|
||||||
|
}
|
||||||
builder.startStyle(tag)
|
builder.startStyle(tag)
|
||||||
style.cssViewStyle(&builder, session)
|
style.cssViewStyle(&builder, session)
|
||||||
builder.endStyle()
|
builder.endStyle()
|
||||||
|
@ -200,7 +202,9 @@ func (theme *theme) cssText(session Session) string {
|
||||||
for tag, obj := range media.styles {
|
for tag, obj := range media.styles {
|
||||||
var style viewStyle
|
var style viewStyle
|
||||||
style.init()
|
style.init()
|
||||||
parseProperties(&style, obj)
|
for tag, value := range obj {
|
||||||
|
style.Set(tag, value)
|
||||||
|
}
|
||||||
builder.startStyle(tag)
|
builder.startStyle(tag)
|
||||||
style.cssViewStyle(&builder, session)
|
style.cssViewStyle(&builder, session)
|
||||||
builder.endStyle()
|
builder.endStyle()
|
||||||
|
@ -234,6 +238,25 @@ func (theme *theme) addData(data DataObject) {
|
||||||
func (theme *theme) parseThemeData(data DataObject) {
|
func (theme *theme) parseThemeData(data DataObject) {
|
||||||
count := data.PropertyCount()
|
count := data.PropertyCount()
|
||||||
|
|
||||||
|
objToParams := func(obj DataObject) Params {
|
||||||
|
params := Params{}
|
||||||
|
for i := 0; i < obj.PropertyCount(); i++ {
|
||||||
|
if node := obj.Property(i); node != nil {
|
||||||
|
switch node.Type() {
|
||||||
|
case ArrayNode:
|
||||||
|
params[node.Tag()] = node.ArrayElements()
|
||||||
|
|
||||||
|
case ObjectNode:
|
||||||
|
params[node.Tag()] = node.Object()
|
||||||
|
|
||||||
|
default:
|
||||||
|
params[node.Tag()] = node.Text()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
if d := data.Property(i); d != nil {
|
if d := data.Property(i); d != nil {
|
||||||
switch tag := d.Tag(); tag {
|
switch tag := d.Tag(); tag {
|
||||||
|
@ -291,7 +314,7 @@ func (theme *theme) parseThemeData(data DataObject) {
|
||||||
for k := 0; k < arraySize; k++ {
|
for k := 0; k < arraySize; k++ {
|
||||||
if element := d.ArrayElement(k); element != nil && element.IsObject() {
|
if element := d.ArrayElement(k); element != nil && element.IsObject() {
|
||||||
if obj := element.Object(); obj != nil {
|
if obj := element.Object(); obj != nil {
|
||||||
theme.styles[obj.Tag()] = obj
|
theme.styles[obj.Tag()] = objToParams(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,7 +327,7 @@ func (theme *theme) parseThemeData(data DataObject) {
|
||||||
for k := 0; k < arraySize; k++ {
|
for k := 0; k < arraySize; k++ {
|
||||||
if element := d.ArrayElement(k); element != nil && element.IsObject() {
|
if element := d.ArrayElement(k); element != nil && element.IsObject() {
|
||||||
if obj := element.Object(); obj != nil {
|
if obj := element.Object(); obj != nil {
|
||||||
rule.styles[obj.Tag()] = obj
|
rule.styles[obj.Tag()] = objToParams(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
view.go
9
view.go
|
@ -177,6 +177,9 @@ func (view *viewData) ViewByID(id string) View {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *viewData) Focusable() bool {
|
func (view *viewData) Focusable() bool {
|
||||||
|
if focus, ok := boolProperty(view, Focusable, view.session); ok {
|
||||||
|
return focus
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +192,9 @@ func (view *viewData) remove(tag string) {
|
||||||
case ID:
|
case ID:
|
||||||
view.viewID = ""
|
view.viewID = ""
|
||||||
|
|
||||||
|
case UserData:
|
||||||
|
delete(view.properties, tag)
|
||||||
|
|
||||||
case Style, StyleDisabled:
|
case Style, StyleDisabled:
|
||||||
if _, ok := view.properties[tag]; ok {
|
if _, ok := view.properties[tag]; ok {
|
||||||
delete(view.properties, tag)
|
delete(view.properties, tag)
|
||||||
|
@ -311,6 +317,9 @@ func (view *viewData) set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
view.viewID = text
|
view.viewID = text
|
||||||
|
|
||||||
|
case UserData:
|
||||||
|
view.properties[tag] = value
|
||||||
|
|
||||||
case Style, StyleDisabled:
|
case Style, StyleDisabled:
|
||||||
text, ok := value.(string)
|
text, ok := value.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -135,5 +136,13 @@ func CreateViewFromResources(session Session, name string) View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resources.path != "" {
|
||||||
|
if data, err := os.ReadFile(resources.path + viewDir + "/" + name); err == nil {
|
||||||
|
if data := ParseDataText(string(data)); data != nil {
|
||||||
|
return CreateViewFromObject(session, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
14
viewUtils.go
14
viewUtils.go
|
@ -1053,19 +1053,13 @@ func GetCurrent(view View, subviewID string) int {
|
||||||
view = ViewByID(view, subviewID)
|
view = ViewByID(view, subviewID)
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultValue int
|
defaultValue := -1
|
||||||
switch view.Tag() {
|
|
||||||
case "ListView":
|
|
||||||
defaultValue = -1
|
|
||||||
|
|
||||||
default:
|
|
||||||
defaultValue = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if view != nil {
|
if view != nil {
|
||||||
if result, ok := intProperty(view, Current, view.Session(), defaultValue); ok {
|
if result, ok := intProperty(view, Current, view.Session(), defaultValue); ok {
|
||||||
return result
|
return result
|
||||||
|
} else if view.Tag() != "ListView" {
|
||||||
|
defaultValue = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1
|
return defaultValue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue