forked from mbk-lab/rui_orig
Updated TabsLayout
This commit is contained in:
parent
f74fede3db
commit
07e1dd3799
|
@ -303,6 +303,12 @@ function tabClickEvent(layoutId, tabNumber, event) {
|
||||||
sendMessage("tabClick{session=" + sessionID + ",id=" + layoutId + ",number=" + tabNumber + "}");
|
sendMessage("tabClick{session=" + sessionID + ",id=" + layoutId + ",number=" + tabNumber + "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tabCloseClickEvent(layoutId, tabNumber, event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
sendMessage("tabCloseClick{session=" + sessionID + ",id=" + layoutId + ",number=" + tabNumber + "}");
|
||||||
|
}
|
||||||
|
|
||||||
function tabKeyClickEvent(layoutId, tabNumber, event) {
|
function tabKeyClickEvent(layoutId, tabNumber, event) {
|
||||||
if (enterOrSpaceKeyClickEvent(event)) {
|
if (enterOrSpaceKeyClickEvent(event)) {
|
||||||
tabClickEvent(layoutId, tabNumber, event)
|
tabClickEvent(layoutId, tabNumber, event)
|
||||||
|
|
|
@ -33,6 +33,12 @@ theme {
|
||||||
ruiButtonDisabledTextColor = #FFA0A0A0,
|
ruiButtonDisabledTextColor = #FFA0A0A0,
|
||||||
ruiHighlightColor = #FF1A74E8,
|
ruiHighlightColor = #FF1A74E8,
|
||||||
ruiHighlightTextColor = #FFFFFFFF,
|
ruiHighlightTextColor = #FFFFFFFF,
|
||||||
|
|
||||||
|
ruiTabsBackgroundColor = #FF303030,
|
||||||
|
ruiInactiveTabColor = #FF606060,
|
||||||
|
ruiInactiveTabTextColor = #FFE0E0E0,
|
||||||
|
ruiActiveTabColor = #FF000000,
|
||||||
|
ruiActiveTabTextColor = #FFFFFFFF,
|
||||||
},
|
},
|
||||||
constants = _{
|
constants = _{
|
||||||
ruiButtonHorizontalPadding = 16px,
|
ruiButtonHorizontalPadding = 16px,
|
||||||
|
@ -49,7 +55,8 @@ theme {
|
||||||
ruiPopupButtonGap = 4px,
|
ruiPopupButtonGap = 4px,
|
||||||
ruiTabSpace = 2px,
|
ruiTabSpace = 2px,
|
||||||
ruiTabHeight = 32px,
|
ruiTabHeight = 32px,
|
||||||
ruiTabPadding = 2px,
|
ruiTabsPadding = 2px,
|
||||||
|
ruiTabRadius = 2px,
|
||||||
},
|
},
|
||||||
constants:touch = _{
|
constants:touch = _{
|
||||||
ruiButtonHorizontalPadding = 20px,
|
ruiButtonHorizontalPadding = 20px,
|
||||||
|
@ -114,26 +121,42 @@ theme {
|
||||||
ruiActiveTab {
|
ruiActiveTab {
|
||||||
background-color = @ruiActiveTabColor,
|
background-color = @ruiActiveTabColor,
|
||||||
text-color = @ruiActiveTabTextColor,
|
text-color = @ruiActiveTabTextColor,
|
||||||
padding-left = 8px,
|
padding-left = 4px,
|
||||||
padding-right = 8px,
|
padding-right = 4px,
|
||||||
|
radius = @ruiTabRadius,
|
||||||
},
|
},
|
||||||
ruiInactiveTab {
|
ruiInactiveTab {
|
||||||
background-color = @ruiInactiveTabColor,
|
background-color = @ruiInactiveTabColor,
|
||||||
text-color = @ruiInactiveTabTextColor,
|
text-color = @ruiInactiveTabTextColor,
|
||||||
padding-left = 8px,
|
padding-left = 4px,
|
||||||
padding-right = 8px,
|
padding-right = 4px,
|
||||||
|
radius = @ruiTabRadius,
|
||||||
},
|
},
|
||||||
ruiActiveVerticalTab {
|
ruiActiveVerticalTab {
|
||||||
background-color = @ruiActiveTabColor,
|
background-color = @ruiActiveTabColor,
|
||||||
text-color = @ruiActiveTabTextColor,
|
text-color = @ruiActiveTabTextColor,
|
||||||
padding-top = 8px,
|
padding-top = 4px,
|
||||||
padding-bottom = 8px,
|
padding-bottom = 4px,
|
||||||
|
radius = @ruiTabRadius,
|
||||||
},
|
},
|
||||||
ruiInactiveVerticalTab {
|
ruiInactiveVerticalTab {
|
||||||
background-color = @ruiInactiveTabColor,
|
background-color = @ruiInactiveTabColor,
|
||||||
text-color = @ruiInactiveTabTextColor,
|
text-color = @ruiInactiveTabTextColor,
|
||||||
padding-top = 8px,
|
padding-top = 4px,
|
||||||
padding-bottom = 8px,
|
padding-bottom = 4px,
|
||||||
|
radius = @ruiTabRadius,
|
||||||
|
},
|
||||||
|
ruiTabCloseButton {
|
||||||
|
width = 16px,
|
||||||
|
height = 16px,
|
||||||
|
cell-vertical-align = center,
|
||||||
|
cell-horizontal-align = center,
|
||||||
|
font = Helvetica,
|
||||||
|
text-size = 16px,
|
||||||
|
},
|
||||||
|
ruiTabCloseButton:hover {
|
||||||
|
background-color = @ruiTabsBackgroundColor,
|
||||||
|
radius = 3px,
|
||||||
},
|
},
|
||||||
ruiPopup {
|
ruiPopup {
|
||||||
background-color = @ruiPopupBackgroundColor,
|
background-color = @ruiPopupBackgroundColor,
|
||||||
|
|
|
@ -16,7 +16,7 @@ GridLayout {
|
||||||
content = [
|
content = [
|
||||||
GridLayout {
|
GridLayout {
|
||||||
id = rootTitle, width = 100%, cell-width = "auto, 1fr",
|
id = rootTitle, width = 100%, cell-width = "auto, 1fr",
|
||||||
cell-vertical-align = center, background-color = #ffc0ded9,
|
cell-vertical-align = center, background-color = #ffc0ded9, text-color = black,
|
||||||
content = [
|
content = [
|
||||||
ImageView {
|
ImageView {
|
||||||
id = rootTitleButton, padding = 8px, src = menu_icon.svg,
|
id = rootTitleButton, padding = 8px, src = menu_icon.svg,
|
||||||
|
@ -78,6 +78,7 @@ func createDemo(session rui.Session) rui.SessionContent {
|
||||||
{"GridLayout", createGridLayoutDemo, nil},
|
{"GridLayout", createGridLayoutDemo, nil},
|
||||||
{"ColumnLayout", createColumnLayoutDemo, nil},
|
{"ColumnLayout", createColumnLayoutDemo, nil},
|
||||||
{"StackLayout", createStackLayoutDemo, nil},
|
{"StackLayout", createStackLayoutDemo, nil},
|
||||||
|
{"Tabs", createTabsDemo, nil},
|
||||||
{"Resizable", createResizableDemo, nil},
|
{"Resizable", createResizableDemo, nil},
|
||||||
{"ListView", createListViewDemo, nil},
|
{"ListView", createListViewDemo, nil},
|
||||||
{"Checkbox", createCheckboxDemo, nil},
|
{"Checkbox", createCheckboxDemo, nil},
|
||||||
|
@ -99,7 +100,6 @@ func createDemo(session rui.Session) rui.SessionContent {
|
||||||
{"Mouse events", createMouseEventsDemo, nil},
|
{"Mouse events", createMouseEventsDemo, nil},
|
||||||
{"Pointer events", createPointerEventsDemo, nil},
|
{"Pointer events", createPointerEventsDemo, nil},
|
||||||
{"Touch events", createTouchEventsDemo, nil},
|
{"Touch events", createTouchEventsDemo, nil},
|
||||||
//{"Tabs", createTabsDemo, nil},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionContent
|
return sessionContent
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.1 (c4e8f9e, 2021-05-24)"
|
||||||
|
sodipodi:docname="black_icon.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
units="px"
|
||||||
|
inkscape:showpageshadow="false"
|
||||||
|
inkscape:zoom="24"
|
||||||
|
inkscape:cx="7.1458333"
|
||||||
|
inkscape:cy="8"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="968"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid846" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Слой 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
style="fill:#000000;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path848"
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="7.5" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.1 (c4e8f9e, 2021-05-24)"
|
||||||
|
sodipodi:docname="blue_icon.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
units="px"
|
||||||
|
inkscape:showpageshadow="false"
|
||||||
|
inkscape:zoom="24"
|
||||||
|
inkscape:cx="7.1458333"
|
||||||
|
inkscape:cy="8"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="968"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid846" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Слой 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
style="fill:#0000ff;stroke:none"
|
||||||
|
id="path848"
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="8" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.1 (c4e8f9e, 2021-05-24)"
|
||||||
|
sodipodi:docname="green_icon.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
units="px"
|
||||||
|
inkscape:showpageshadow="false"
|
||||||
|
inkscape:zoom="24"
|
||||||
|
inkscape:cx="7.1458333"
|
||||||
|
inkscape:cy="8"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="968"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid846" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Слой 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
style="fill:#00ff00;stroke:none"
|
||||||
|
id="path848"
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="8" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.1 (c4e8f9e, 2021-05-24)"
|
||||||
|
sodipodi:docname="red_icon.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
units="px"
|
||||||
|
inkscape:showpageshadow="false"
|
||||||
|
inkscape:zoom="24"
|
||||||
|
inkscape:cx="7.1458333"
|
||||||
|
inkscape:cy="8"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="968"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid846" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Слой 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
style="fill:#ff0000;stroke:none"
|
||||||
|
id="path848"
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="8" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -1,6 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/anoshenko/rui"
|
"github.com/anoshenko/rui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -8,12 +10,12 @@ const tabsDemoText = `
|
||||||
GridLayout {
|
GridLayout {
|
||||||
style = demoPage,
|
style = demoPage,
|
||||||
content = [
|
content = [
|
||||||
TabsLayout { id = tabsLayout, width = 100%, height = 100%, tabs = top,
|
TabsLayout { id = tabsLayout, width = 100%, height = 100%, tabs = top, tab-close-button = true,
|
||||||
content = [
|
content = [
|
||||||
View { width = 300px, height = 200px, background-color = #FFFF0000, title = "Red tab"},
|
View { width = 300px, height = 200px, background-color = #FFFF0000, title = "Red tab", icon = red_icon.svg },
|
||||||
View { width = 400px, height = 250px, background-color = #FF00FF00, title = "Green tab"},
|
View { width = 400px, height = 250px, background-color = #FF00FF00, title = "Green tab", icon = green_icon.svg },
|
||||||
View { width = 100px, height = 400px, background-color = #FF0000FF, title = "Blue tab"},
|
View { width = 100px, height = 400px, background-color = #FF0000FF, title = "Blue tab", icon = blue_icon.svg },
|
||||||
View { width = 300px, height = 200px, background-color = #FF000000, title = "Black tab"},
|
View { width = 300px, height = 200px, background-color = #FF000000, title = "Black tab", icon = black_icon.svg },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
ListLayout {
|
ListLayout {
|
||||||
|
@ -23,8 +25,8 @@ GridLayout {
|
||||||
style = optionsTable,
|
style = optionsTable,
|
||||||
content = [
|
content = [
|
||||||
TextView { row = 0, text = "Tabs location" },
|
TextView { row = 0, text = "Tabs location" },
|
||||||
DropDownList { row = 0, column = 1, id = tabsTypeList, current = 1,
|
DropDownList { row = 0, column = 1, id = tabsTypeList,
|
||||||
items = ["hidden", "top", "bottom", "left", "right", "left list", "right list"]
|
items = ["top", "bottom", "left", "right", "left list", "right list", "hidden"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -44,5 +46,8 @@ func createTabsDemo(session rui.Session) rui.View {
|
||||||
rui.Set(view, "tabsLayout", rui.Tabs, number)
|
rui.Set(view, "tabsLayout", rui.Tabs, number)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
rui.Set(view, "tabsLayout", rui.TabCloseEvent, func(index int) {
|
||||||
|
rui.ShowMessage("", fmt.Sprintf(`The close button of the tab "%d" was clicked`, index), session)
|
||||||
|
})
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package rui
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
// Params defines a type of a parameters list
|
||||||
|
type Params map[string]interface{}
|
||||||
|
|
||||||
|
func (params Params) Get(tag string) interface{} {
|
||||||
|
return params.getRaw(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params Params) getRaw(tag string) interface{} {
|
||||||
|
if value, ok := params[tag]; ok {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params Params) Set(tag string, value interface{}) bool {
|
||||||
|
params.setRaw(tag, value)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params Params) setRaw(tag string, value interface{}) {
|
||||||
|
if value != nil {
|
||||||
|
params[tag] = value
|
||||||
|
} else {
|
||||||
|
delete(params, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params Params) Remove(tag string) {
|
||||||
|
delete(params, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params Params) Clear() {
|
||||||
|
for tag := range params {
|
||||||
|
delete(params, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params Params) AllTags() []string {
|
||||||
|
tags := make([]string, 0, len(params))
|
||||||
|
for t := range params {
|
||||||
|
tags = append(tags, t)
|
||||||
|
}
|
||||||
|
sort.Strings(tags)
|
||||||
|
return tags
|
||||||
|
}
|
68
popup.go
68
popup.go
|
@ -13,6 +13,7 @@ const (
|
||||||
OutsideClose = "outside-close"
|
OutsideClose = "outside-close"
|
||||||
Buttons = "buttons"
|
Buttons = "buttons"
|
||||||
ButtonsAlign = "buttons-align"
|
ButtonsAlign = "buttons-align"
|
||||||
|
DismissEvent = "dismiss-event"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PopupButton struct {
|
type PopupButton struct {
|
||||||
|
@ -32,9 +33,9 @@ type Popup interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type popupData struct {
|
type popupData struct {
|
||||||
//propertyList
|
|
||||||
layerView View
|
layerView View
|
||||||
view View
|
view View
|
||||||
|
dismissListener []func(Popup)
|
||||||
}
|
}
|
||||||
|
|
||||||
type popupManager struct {
|
type popupManager struct {
|
||||||
|
@ -43,17 +44,61 @@ type popupManager struct {
|
||||||
|
|
||||||
func (popup *popupData) init(view View, params Params) {
|
func (popup *popupData) init(view View, params Params) {
|
||||||
popup.view = view
|
popup.view = view
|
||||||
|
|
||||||
props := propertyList{properties: params}
|
|
||||||
session := view.Session()
|
session := view.Session()
|
||||||
|
|
||||||
|
popup.dismissListener = []func(Popup){}
|
||||||
|
if value, ok := params[DismissEvent]; ok && value != nil {
|
||||||
|
switch value := value.(type) {
|
||||||
|
case func(Popup):
|
||||||
|
popup.dismissListener = []func(Popup){value}
|
||||||
|
|
||||||
|
case func():
|
||||||
|
popup.dismissListener = []func(Popup){
|
||||||
|
func(popup Popup) {
|
||||||
|
value()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
case []func(Popup):
|
||||||
|
for _, fn := range value {
|
||||||
|
if fn != nil {
|
||||||
|
popup.dismissListener = append(popup.dismissListener, fn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case []func():
|
||||||
|
for _, fn := range value {
|
||||||
|
if fn != nil {
|
||||||
|
popup.dismissListener = append(popup.dismissListener, func(popup Popup) {
|
||||||
|
fn()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
for _, val := range value {
|
||||||
|
if val != nil {
|
||||||
|
switch fn := val.(type) {
|
||||||
|
case func(Popup):
|
||||||
|
popup.dismissListener = append(popup.dismissListener, fn)
|
||||||
|
|
||||||
|
case func():
|
||||||
|
popup.dismissListener = append(popup.dismissListener, func(popup Popup) {
|
||||||
|
fn()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var title View = nil
|
var title View = nil
|
||||||
titleStyle := "ruiPopupTitle"
|
titleStyle := "ruiPopupTitle"
|
||||||
closeButton, _ := boolProperty(&props, CloseButton, session)
|
closeButton, _ := boolProperty(params, CloseButton, session)
|
||||||
outsideClose, _ := boolProperty(&props, OutsideClose, session)
|
outsideClose, _ := boolProperty(params, OutsideClose, session)
|
||||||
vAlign, _ := enumProperty(&props, VerticalAlign, session, CenterAlign)
|
vAlign, _ := enumProperty(params, VerticalAlign, session, CenterAlign)
|
||||||
hAlign, _ := enumProperty(&props, HorizontalAlign, session, CenterAlign)
|
hAlign, _ := enumProperty(params, HorizontalAlign, session, CenterAlign)
|
||||||
buttonsAlign, _ := enumProperty(&props, ButtonsAlign, session, RightAlign)
|
buttonsAlign, _ := enumProperty(params, ButtonsAlign, session, RightAlign)
|
||||||
|
|
||||||
buttons := []PopupButton{}
|
buttons := []PopupButton{}
|
||||||
if value, ok := params[Buttons]; ok && value != nil {
|
if value, ok := params[Buttons]; ok && value != nil {
|
||||||
|
@ -110,7 +155,7 @@ func (popup *popupData) init(view View, params Params) {
|
||||||
viewRow := 0
|
viewRow := 0
|
||||||
if title != nil || closeButton {
|
if title != nil || closeButton {
|
||||||
viewRow = 1
|
viewRow = 1
|
||||||
titleHeight, _ := sizeConstant(popup.Session(), "popupTitleHeight")
|
titleHeight, _ := sizeConstant(popup.Session(), "ruiPopupTitleHeight")
|
||||||
titleView := NewGridLayout(session, Params{
|
titleView := NewGridLayout(session, Params{
|
||||||
Row: 0,
|
Row: 0,
|
||||||
Style: titleStyle,
|
Style: titleStyle,
|
||||||
|
@ -147,7 +192,7 @@ func (popup *popupData) init(view View, params Params) {
|
||||||
|
|
||||||
if buttonCount := len(buttons); buttonCount > 0 {
|
if buttonCount := len(buttons); buttonCount > 0 {
|
||||||
cellHeight = append(cellHeight, AutoSize())
|
cellHeight = append(cellHeight, AutoSize())
|
||||||
gap, _ := sizeConstant(session, "popupButtonGap")
|
gap, _ := sizeConstant(session, "ruiPopupButtonGap")
|
||||||
cellWidth := []SizeUnit{}
|
cellWidth := []SizeUnit{}
|
||||||
for i := 0; i < buttonCount; i++ {
|
for i := 0; i < buttonCount; i++ {
|
||||||
cellWidth = append(cellWidth, Fr(1))
|
cellWidth = append(cellWidth, Fr(1))
|
||||||
|
@ -212,6 +257,9 @@ func (popup *popupData) Session() Session {
|
||||||
|
|
||||||
func (popup *popupData) Dismiss() {
|
func (popup *popupData) Dismiss() {
|
||||||
popup.Session().popupManager().dismissPopup(popup)
|
popup.Session().popupManager().dismissPopup(popup)
|
||||||
|
for _, listener := range popup.dismissListener {
|
||||||
|
listener(popup)
|
||||||
|
}
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,10 @@ type popupMenuData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (popup *popupMenuData) itemClick(list ListView, n int) {
|
func (popup *popupMenuData) itemClick(list ListView, n int) {
|
||||||
|
if popup.popup != nil {
|
||||||
popup.popup.Dismiss()
|
popup.popup.Dismiss()
|
||||||
|
popup.popup = nil
|
||||||
|
}
|
||||||
if popup.result != nil {
|
if popup.result != nil {
|
||||||
popup.result(n)
|
popup.result(n)
|
||||||
}
|
}
|
||||||
|
@ -128,11 +131,11 @@ func (popup *popupMenuData) IsListItemEnabled(index int) bool {
|
||||||
const PopupMenuResult = "popup-menu-result"
|
const PopupMenuResult = "popup-menu-result"
|
||||||
|
|
||||||
// ShowMenu displays the popup with text message
|
// ShowMenu displays the popup with text message
|
||||||
func ShowMenu(session Session, params Params) bool {
|
func ShowMenu(session Session, params Params) Popup {
|
||||||
value, ok := params[Items]
|
value, ok := params[Items]
|
||||||
if !ok || value == nil {
|
if !ok || value == nil {
|
||||||
ErrorLog("Unable to show empty menu")
|
ErrorLog("Unable to show empty menu")
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var adapter ListAdapter
|
var adapter ListAdapter
|
||||||
|
@ -149,7 +152,7 @@ func ShowMenu(session Session, params Params) bool {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
notCompatibleType(Items, value)
|
notCompatibleType(Items, value)
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
value, ok = params[PopupMenuResult]
|
value, ok = params[PopupMenuResult]
|
||||||
|
@ -167,5 +170,5 @@ func ShowMenu(session Session, params Params) bool {
|
||||||
data.popup = NewPopup(listView, params)
|
data.popup = NewPopup(listView, params)
|
||||||
data.popup.Show()
|
data.popup.Show()
|
||||||
FocusView(listView)
|
FocusView(listView)
|
||||||
return true
|
return data.popup
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ var boolProperties = []string{
|
||||||
Muted,
|
Muted,
|
||||||
AnimationPaused,
|
AnimationPaused,
|
||||||
Multiple,
|
Multiple,
|
||||||
|
TabCloseButton,
|
||||||
}
|
}
|
||||||
|
|
||||||
var intProperties = []string{
|
var intProperties = []string{
|
||||||
|
@ -251,9 +252,9 @@ var enumProperties = map[string]struct {
|
||||||
[]string{"none", "solid", "dashed", "dotted", "double"},
|
[]string{"none", "solid", "dashed", "dotted", "double"},
|
||||||
},
|
},
|
||||||
Tabs: {
|
Tabs: {
|
||||||
[]string{"hidden", "top", "bottom", "left", "right", "left-list", "right-list"},
|
[]string{"top", "bottom", "left", "right", "left-list", "right-list", "hidden"},
|
||||||
"",
|
"",
|
||||||
[]string{"hidden", "top", "bottom", "left", "right", "left-list", "right-list"},
|
[]string{"top", "bottom", "left", "right", "left-list", "right-list", "hidden"},
|
||||||
},
|
},
|
||||||
NumberPickerType: {
|
NumberPickerType: {
|
||||||
[]string{"editor", "slider"},
|
[]string{"editor", "slider"},
|
||||||
|
|
644
tabsLayout.go
644
tabsLayout.go
|
@ -7,41 +7,49 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// HiddenTabs - tabs of TabsLayout are hidden
|
// CurrentTabChangedEvent is the constant for "current-tab-changed" property tag.
|
||||||
HiddenTabs = 0
|
// The "current-tab-changed" event occurs when the new tab becomes active.
|
||||||
|
// The main listener format: func(TabsLayout, int, int), where
|
||||||
|
// the second argument is the index of the new active tab,
|
||||||
|
// the third argument is the index of the old active tab.
|
||||||
|
CurrentTabChangedEvent = "current-tab-changed"
|
||||||
|
|
||||||
|
// Icon is the constant for "icon" property tag.
|
||||||
|
// The string "icon" property defines the icon name that is displayed in the tab.
|
||||||
|
Icon = "icon"
|
||||||
|
|
||||||
|
// TabCloseButton is the constant for "tab-close-button" property tag.
|
||||||
|
// The "tab-close-button" is the bool property. If it is "true" then a close button is displayed within the tab.
|
||||||
|
TabCloseButton = "tab-close-button"
|
||||||
|
|
||||||
|
// TabCloseEvent is the constant for "tab-close-event" property tag.
|
||||||
|
// The "tab-close-event" occurs when when the user clicks on the tab close button.
|
||||||
|
// The main listener format: func(TabsLayout, int), where the second argument is the index of the tab.
|
||||||
|
TabCloseEvent = "tab-close-event"
|
||||||
|
|
||||||
// TopTabs - tabs of TabsLayout are on the top
|
// TopTabs - tabs of TabsLayout are on the top
|
||||||
TopTabs = 1
|
TopTabs = 0
|
||||||
// BottomTabs - tabs of TabsLayout are on the bottom
|
// BottomTabs - tabs of TabsLayout are on the bottom
|
||||||
BottomTabs = 2
|
BottomTabs = 1
|
||||||
// LeftTabs - tabs of TabsLayout are on the left
|
// LeftTabs - tabs of TabsLayout are on the left. Bookmarks are rotated counterclockwise 90 degrees.
|
||||||
LeftTabs = 3
|
LeftTabs = 2
|
||||||
// RightTabs - tabs of TabsLayout are on the right
|
// RightTabs - tabs of TabsLayout are on the right. Bookmarks are rotated clockwise 90 degrees.
|
||||||
RightTabs = 4
|
RightTabs = 3
|
||||||
// LeftListTabs - tabs of TabsLayout are on the left
|
// LeftListTabs - tabs of TabsLayout are on the left
|
||||||
LeftListTabs = 5
|
LeftListTabs = 4
|
||||||
// RightListTabs - tabs of TabsLayout are on the right
|
// RightListTabs - tabs of TabsLayout are on the right
|
||||||
RightListTabs = 6
|
RightListTabs = 5
|
||||||
|
// HiddenTabs - tabs of TabsLayout are hidden
|
||||||
|
HiddenTabs = 6
|
||||||
|
|
||||||
|
inactiveTabStyle = "data-inactiveTabStyle"
|
||||||
|
activeTabStyle = "data-activeTabStyle"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TabsLayoutCurrentChangedListener - listener of the current tab changing
|
|
||||||
type TabsLayoutCurrentChangedListener interface {
|
|
||||||
OnTabsLayoutCurrentChanged(tabsLayout TabsLayout, newCurrent int, newCurrentView View, oldCurrent int, oldCurrentView View)
|
|
||||||
}
|
|
||||||
|
|
||||||
type tabsLayoutCurrentChangedListenerFunc struct {
|
|
||||||
listenerFunc func(tabsLayout TabsLayout, newCurrent int, newCurrentView View, oldCurrent int, oldCurrentView View)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (listener *tabsLayoutCurrentChangedListenerFunc) OnTabsLayoutCurrentChanged(tabsLayout TabsLayout,
|
|
||||||
newCurrent int, newCurrentView View, oldCurrent int, oldCurrentView View) {
|
|
||||||
if listener.listenerFunc != nil {
|
|
||||||
listener.listenerFunc(tabsLayout, newCurrent, newCurrentView, oldCurrent, oldCurrentView)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TabsLayout - multi-tab container of View
|
// TabsLayout - multi-tab container of View
|
||||||
type TabsLayout interface {
|
type TabsLayout interface {
|
||||||
ViewsContainer
|
ViewsContainer
|
||||||
|
ListAdapter
|
||||||
/*
|
/*
|
||||||
// Current return the index of active tab
|
// Current return the index of active tab
|
||||||
currentItem() int
|
currentItem() int
|
||||||
|
@ -57,18 +65,14 @@ type TabsLayout interface {
|
||||||
TabStyle() (string, string)
|
TabStyle() (string, string)
|
||||||
SetTabStyle(tabStyle string, activeTabStyle string)
|
SetTabStyle(tabStyle string, activeTabStyle string)
|
||||||
*/
|
*/
|
||||||
// SetCurrentTabChangedListener add the listener of the current tab changing
|
|
||||||
SetCurrentTabChangedListener(listener TabsLayoutCurrentChangedListener)
|
|
||||||
// SetCurrentTabChangedListener add the listener function of the current tab changing
|
|
||||||
SetCurrentTabChangedListenerFunc(listenerFunc func(tabsLayout TabsLayout,
|
|
||||||
newCurrent int, newCurrentView View, oldCurrent int, oldCurrentView View))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type tabsLayoutData struct {
|
type tabsLayoutData struct {
|
||||||
viewsContainerData
|
viewsContainerData
|
||||||
//currentTab, tabsLocation int
|
//currentTab, tabsLocation int
|
||||||
//tabStyle, activeTabStyle string
|
//tabStyle, activeTabStyle string
|
||||||
tabListener TabsLayoutCurrentChangedListener
|
tabListener []func(TabsLayout, int, int)
|
||||||
|
tabCloseListener []func(TabsLayout, int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTabsLayout create new TabsLayout object and return it
|
// NewTabsLayout create new TabsLayout object and return it
|
||||||
|
@ -87,7 +91,8 @@ func (tabsLayout *tabsLayoutData) Init(session Session) {
|
||||||
tabsLayout.viewsContainerData.Init(session)
|
tabsLayout.viewsContainerData.Init(session)
|
||||||
tabsLayout.tag = "TabsLayout"
|
tabsLayout.tag = "TabsLayout"
|
||||||
tabsLayout.systemClass = "ruiTabsLayout"
|
tabsLayout.systemClass = "ruiTabsLayout"
|
||||||
tabsLayout.tabListener = nil
|
tabsLayout.tabListener = []func(TabsLayout, int, int){}
|
||||||
|
tabsLayout.tabCloseListener = []func(TabsLayout, int){}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) currentItem() int {
|
func (tabsLayout *tabsLayoutData) currentItem() int {
|
||||||
|
@ -95,8 +100,101 @@ func (tabsLayout *tabsLayoutData) currentItem() int {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool {
|
func (tabsLayout *tabsLayoutData) Get(tag string) interface{} {
|
||||||
|
return tabsLayout.get(strings.ToLower(tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) get(tag string) interface{} {
|
||||||
switch tag {
|
switch tag {
|
||||||
|
case CurrentTabChangedEvent:
|
||||||
|
return tabsLayout.tabListener
|
||||||
|
|
||||||
|
case TabCloseEvent:
|
||||||
|
return tabsLayout.tabCloseListener
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabsLayout.viewsContainerData.get(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) Remove(tag string) {
|
||||||
|
tabsLayout.remove(strings.ToLower(tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) remove(tag string) {
|
||||||
|
switch tag {
|
||||||
|
case CurrentTabChangedEvent:
|
||||||
|
tabsLayout.tabListener = []func(TabsLayout, int, int){}
|
||||||
|
|
||||||
|
case TabCloseEvent:
|
||||||
|
tabsLayout.tabCloseListener = []func(TabsLayout, int){}
|
||||||
|
|
||||||
|
case Current:
|
||||||
|
oldCurrent := tabsLayout.currentItem()
|
||||||
|
delete(tabsLayout.properties, Current)
|
||||||
|
if !tabsLayout.session.ignoreViewUpdates() && oldCurrent != 0 {
|
||||||
|
tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), 0))
|
||||||
|
for _, listener := range tabsLayout.tabListener {
|
||||||
|
listener(tabsLayout, 0, oldCurrent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case Tabs:
|
||||||
|
delete(tabsLayout.properties, Tabs)
|
||||||
|
if !tabsLayout.session.ignoreViewUpdates() {
|
||||||
|
htmlID := tabsLayout.htmlID()
|
||||||
|
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
|
||||||
|
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
|
||||||
|
updateCSSStyle(htmlID, tabsLayout.session)
|
||||||
|
updateInnerHTML(htmlID, tabsLayout.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
case TabStyle, CurrentTabStyle:
|
||||||
|
delete(tabsLayout.properties, tag)
|
||||||
|
if !tabsLayout.session.ignoreViewUpdates() {
|
||||||
|
htmlID := tabsLayout.htmlID()
|
||||||
|
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
|
||||||
|
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
|
||||||
|
updateInnerHTML(htmlID, tabsLayout.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
case TabCloseButton:
|
||||||
|
delete(tabsLayout.properties, tag)
|
||||||
|
if !tabsLayout.session.ignoreViewUpdates() {
|
||||||
|
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
tabsLayout.viewsContainerData.remove(tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool {
|
||||||
|
return tabsLayout.set(strings.ToLower(tag), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool {
|
||||||
|
if value == nil {
|
||||||
|
tabsLayout.remove(tag)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tag {
|
||||||
|
case CurrentTabChangedEvent:
|
||||||
|
listeners := tabsLayout.valueToTabListeners(value)
|
||||||
|
if listeners == nil {
|
||||||
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tabsLayout.tabListener = listeners
|
||||||
|
|
||||||
|
case TabCloseEvent:
|
||||||
|
listeners := tabsLayout.valueToCloseListeners(value)
|
||||||
|
if listeners == nil {
|
||||||
|
notCompatibleType(tag, value)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tabsLayout.tabCloseListener = listeners
|
||||||
|
|
||||||
case Current:
|
case Current:
|
||||||
oldCurrent := tabsLayout.currentItem()
|
oldCurrent := tabsLayout.currentItem()
|
||||||
if !tabsLayout.setIntProperty(Current, value) {
|
if !tabsLayout.setIntProperty(Current, value) {
|
||||||
|
@ -107,10 +205,8 @@ func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool {
|
||||||
current := tabsLayout.currentItem()
|
current := tabsLayout.currentItem()
|
||||||
if oldCurrent != current {
|
if oldCurrent != current {
|
||||||
tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), current))
|
tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), current))
|
||||||
if tabsLayout.tabListener != nil {
|
for _, listener := range tabsLayout.tabListener {
|
||||||
oldView := tabsLayout.views[oldCurrent]
|
listener(tabsLayout, current, oldCurrent)
|
||||||
view := tabsLayout.views[current]
|
|
||||||
tabsLayout.tabListener.OnTabsLayoutCurrentChanged(tabsLayout, current, view, oldCurrent, oldView)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,14 +217,14 @@ func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool {
|
||||||
}
|
}
|
||||||
if !tabsLayout.session.ignoreViewUpdates() {
|
if !tabsLayout.session.ignoreViewUpdates() {
|
||||||
htmlID := tabsLayout.htmlID()
|
htmlID := tabsLayout.htmlID()
|
||||||
|
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
|
||||||
|
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
|
||||||
updateCSSStyle(htmlID, tabsLayout.session)
|
updateCSSStyle(htmlID, tabsLayout.session)
|
||||||
updateInnerHTML(htmlID, tabsLayout.session)
|
updateInnerHTML(htmlID, tabsLayout.session)
|
||||||
}
|
}
|
||||||
|
|
||||||
case TabStyle, CurrentTabStyle:
|
case TabStyle, CurrentTabStyle:
|
||||||
if value == nil {
|
if text, ok := value.(string); ok {
|
||||||
delete(tabsLayout.properties, tag)
|
|
||||||
} else if text, ok := value.(string); ok {
|
|
||||||
if text == "" {
|
if text == "" {
|
||||||
delete(tabsLayout.properties, tag)
|
delete(tabsLayout.properties, tag)
|
||||||
} else {
|
} else {
|
||||||
|
@ -141,18 +237,228 @@ func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool {
|
||||||
|
|
||||||
if !tabsLayout.session.ignoreViewUpdates() {
|
if !tabsLayout.session.ignoreViewUpdates() {
|
||||||
htmlID := tabsLayout.htmlID()
|
htmlID := tabsLayout.htmlID()
|
||||||
updateProperty(htmlID, "data-tabStyle", tabsLayout.inactiveTabStyle(), tabsLayout.session)
|
updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session)
|
||||||
updateProperty(htmlID, "data-activeTabStyle", tabsLayout.activeTabStyle(), tabsLayout.session)
|
updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session)
|
||||||
updateInnerHTML(htmlID, tabsLayout.session)
|
updateInnerHTML(htmlID, tabsLayout.session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TabCloseButton:
|
||||||
|
if !tabsLayout.setBoolProperty(tag, value) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !tabsLayout.session.ignoreViewUpdates() {
|
||||||
|
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session)
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return tabsLayout.viewsContainerData.Set(tag, value)
|
return tabsLayout.viewsContainerData.set(tag, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) valueToTabListeners(value interface{}) []func(TabsLayout, int, int) {
|
||||||
|
if value == nil {
|
||||||
|
return []func(TabsLayout, int, int){}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value := value.(type) {
|
||||||
|
case func(TabsLayout, int, int):
|
||||||
|
return []func(TabsLayout, int, int){value}
|
||||||
|
|
||||||
|
case func(TabsLayout, int):
|
||||||
|
fn := func(view TabsLayout, current, old int) {
|
||||||
|
value(view, current)
|
||||||
|
}
|
||||||
|
return []func(TabsLayout, int, int){fn}
|
||||||
|
|
||||||
|
case func(TabsLayout):
|
||||||
|
fn := func(view TabsLayout, current, old int) {
|
||||||
|
value(view)
|
||||||
|
}
|
||||||
|
return []func(TabsLayout, int, int){fn}
|
||||||
|
|
||||||
|
case func(int, int):
|
||||||
|
fn := func(view TabsLayout, current, old int) {
|
||||||
|
value(current, old)
|
||||||
|
}
|
||||||
|
return []func(TabsLayout, int, int){fn}
|
||||||
|
|
||||||
|
case func(int):
|
||||||
|
fn := func(view TabsLayout, current, old int) {
|
||||||
|
value(current)
|
||||||
|
}
|
||||||
|
return []func(TabsLayout, int, int){fn}
|
||||||
|
|
||||||
|
case func():
|
||||||
|
fn := func(view TabsLayout, current, old int) {
|
||||||
|
value()
|
||||||
|
}
|
||||||
|
return []func(TabsLayout, int, int){fn}
|
||||||
|
|
||||||
|
case []func(TabsLayout, int, int):
|
||||||
|
return value
|
||||||
|
|
||||||
|
case []func(TabsLayout, int):
|
||||||
|
listeners := make([]func(TabsLayout, int, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(view, current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
|
||||||
|
case []func(TabsLayout):
|
||||||
|
listeners := make([]func(TabsLayout, int, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
|
||||||
|
case []func(int, int):
|
||||||
|
listeners := make([]func(TabsLayout, int, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(current, old)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
|
||||||
|
case []func(int):
|
||||||
|
listeners := make([]func(TabsLayout, int, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
|
||||||
|
case []func():
|
||||||
|
listeners := make([]func(TabsLayout, int, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
listeners := make([]func(TabsLayout, int, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch val := val.(type) {
|
||||||
|
case func(TabsLayout, int, int):
|
||||||
|
listeners[i] = val
|
||||||
|
|
||||||
|
case func(TabsLayout, int):
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(view, current)
|
||||||
|
}
|
||||||
|
|
||||||
|
case func(TabsLayout):
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
case func(int, int):
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(current, old)
|
||||||
|
}
|
||||||
|
|
||||||
|
case func(int):
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val(current)
|
||||||
|
}
|
||||||
|
|
||||||
|
case func():
|
||||||
|
listeners[i] = func(view TabsLayout, current, old int) {
|
||||||
|
val()
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) valueToCloseListeners(value interface{}) []func(TabsLayout, int) {
|
||||||
|
if value == nil {
|
||||||
|
return []func(TabsLayout, int){}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch value := value.(type) {
|
||||||
|
case func(TabsLayout, int):
|
||||||
|
return []func(TabsLayout, int){value}
|
||||||
|
|
||||||
|
case func(int):
|
||||||
|
fn := func(view TabsLayout, index int) {
|
||||||
|
value(index)
|
||||||
|
}
|
||||||
|
return []func(TabsLayout, int){fn}
|
||||||
|
|
||||||
|
case []func(TabsLayout, int):
|
||||||
|
return value
|
||||||
|
|
||||||
|
case []func(int):
|
||||||
|
listeners := make([]func(TabsLayout, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
listeners[i] = func(view TabsLayout, index int) {
|
||||||
|
val(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
|
||||||
|
case []interface{}:
|
||||||
|
listeners := make([]func(TabsLayout, int), len(value))
|
||||||
|
for i, val := range value {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch val := val.(type) {
|
||||||
|
case func(TabsLayout, int):
|
||||||
|
listeners[i] = val
|
||||||
|
|
||||||
|
case func(int):
|
||||||
|
listeners[i] = func(view TabsLayout, index int) {
|
||||||
|
val(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) tabsLocation() int {
|
func (tabsLayout *tabsLayoutData) tabsLocation() int {
|
||||||
tabs, _ := enumProperty(tabsLayout, Tabs, tabsLayout.session, 0)
|
tabs, _ := enumProperty(tabsLayout, Tabs, tabsLayout.session, 0)
|
||||||
return tabs
|
return tabs
|
||||||
|
@ -180,31 +486,82 @@ func (tabsLayout *tabsLayoutData) activeTabStyle() string {
|
||||||
return "ruiActiveTab"
|
return "ruiActiveTab"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) TabStyle() (string, string) {
|
func (tabsLayout *tabsLayoutData) ListSize() int {
|
||||||
return tabsLayout.inactiveTabStyle(), tabsLayout.activeTabStyle()
|
if tabsLayout.views == nil {
|
||||||
|
tabsLayout.views = []View{}
|
||||||
|
}
|
||||||
|
return len(tabsLayout.views)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) SetCurrentTabChangedListener(listener TabsLayoutCurrentChangedListener) {
|
func (tabsLayout *tabsLayoutData) ListItem(index int, session Session) View {
|
||||||
tabsLayout.tabListener = listener
|
if tabsLayout.views == nil {
|
||||||
|
tabsLayout.views = []View{}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if index < 0 || index >= len(tabsLayout.views) {
|
||||||
// SetCurrentTabChangedListener add the listener of the current tab changing
|
return NewTextView(session, Params{
|
||||||
func (tabsLayout *tabsLayoutData) SetCurrentTabChangedListener(listener TabsLayoutCurrentChangedListener) {
|
Text: "Invalid index",
|
||||||
tabsLayout.tabListener = listener
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCurrentTabChangedListener add the listener function of the current tab changing
|
views := []View{}
|
||||||
func (tabsLayout *tabsLayoutData) SetCurrentTabChangedListenerFunc(listenerFunc func(tabsLayout TabsLayout,
|
page := tabsLayout.views[index]
|
||||||
newCurrent int, newCurrentView View, oldCurrent int, oldCurrentView View)) {
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func (tabsLayout *tabsLayoutData) SetCurrentTabChangedListenerFunc(listenerFunc func(tabsLayout TabsLayout,
|
if icon, ok := stringProperty(page, Icon, session); ok && icon != "" {
|
||||||
newCurrent int, newCurrentView View, oldCurrent int, oldCurrentView View)) {
|
views = append(views, NewImageView(session, Params{
|
||||||
listener := new(tabsLayoutCurrentChangedListenerFunc)
|
Source: icon,
|
||||||
listener.listenerFunc = listenerFunc
|
Row: 0,
|
||||||
tabsLayout.SetCurrentTabChangedListener(listener)
|
Column: 0,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
title, ok := stringProperty(page, Title, session)
|
||||||
|
if !ok || title == "" {
|
||||||
|
title = "No title"
|
||||||
|
}
|
||||||
|
if !GetNotTranslate(tabsLayout, "") {
|
||||||
|
title, _ = tabsLayout.Session().GetString(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
views = append(views, NewTextView(session, Params{
|
||||||
|
Text: title,
|
||||||
|
Row: 0,
|
||||||
|
Column: 1,
|
||||||
|
}))
|
||||||
|
|
||||||
|
closeButton, _ := boolProperty(tabsLayout, TabCloseButton, tabsLayout.session)
|
||||||
|
if close, ok := boolProperty(page, TabCloseButton, tabsLayout.session); ok {
|
||||||
|
closeButton = close
|
||||||
|
}
|
||||||
|
|
||||||
|
if closeButton {
|
||||||
|
views = append(views, NewGridLayout(session, Params{
|
||||||
|
Style: "ruiTabCloseButton",
|
||||||
|
Row: 0,
|
||||||
|
Column: 2,
|
||||||
|
Content: "✕",
|
||||||
|
ClickEvent: func() {
|
||||||
|
// TODO close menu
|
||||||
|
for _, listener := range tabsLayout.tabCloseListener {
|
||||||
|
listener(tabsLayout, index)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
tabsHeight, _ := sizeConstant(session, "ruiTabHeight")
|
||||||
|
|
||||||
|
return NewGridLayout(session, Params{
|
||||||
|
Height: tabsHeight,
|
||||||
|
CellWidth: []SizeUnit{AutoSize(), Fr(1), AutoSize()},
|
||||||
|
CellVerticalAlign: CenterAlign,
|
||||||
|
GridRowGap: Px(8),
|
||||||
|
Content: views,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tabsLayout *tabsLayoutData) IsListItemEnabled(index int) bool {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append appends view to the end of view list
|
// Append appends view to the end of view list
|
||||||
|
@ -212,27 +569,31 @@ func (tabsLayout *tabsLayoutData) Append(view View) {
|
||||||
if tabsLayout.views == nil {
|
if tabsLayout.views == nil {
|
||||||
tabsLayout.views = []View{}
|
tabsLayout.views = []View{}
|
||||||
}
|
}
|
||||||
|
if view != nil {
|
||||||
tabsLayout.viewsContainerData.Append(view)
|
tabsLayout.viewsContainerData.Append(view)
|
||||||
if len(tabsLayout.views) == 1 {
|
if len(tabsLayout.views) == 1 {
|
||||||
tabsLayout.setIntProperty(Current, 0)
|
tabsLayout.setIntProperty(Current, 0)
|
||||||
if tabsLayout.tabListener != nil {
|
for _, listener := range tabsLayout.tabListener {
|
||||||
tabsLayout.tabListener.OnTabsLayoutCurrentChanged(tabsLayout, 0, tabsLayout.views[0], -1, nil)
|
listener(tabsLayout, 0, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session)
|
updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Insert inserts view to the "index" position in view list
|
// Insert inserts view to the "index" position in view list
|
||||||
func (tabsLayout *tabsLayoutData) Insert(view View, index uint) {
|
func (tabsLayout *tabsLayoutData) Insert(view View, index uint) {
|
||||||
if tabsLayout.views == nil {
|
if tabsLayout.views == nil {
|
||||||
tabsLayout.views = []View{}
|
tabsLayout.views = []View{}
|
||||||
}
|
}
|
||||||
|
if view != nil {
|
||||||
tabsLayout.viewsContainerData.Insert(view, index)
|
tabsLayout.viewsContainerData.Insert(view, index)
|
||||||
current := tabsLayout.currentItem()
|
current := tabsLayout.currentItem()
|
||||||
if current >= int(index) {
|
if current >= int(index) {
|
||||||
tabsLayout.Set(Current, current+1)
|
tabsLayout.Set(Current, current+1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove removes view from list and return it
|
// Remove removes view from list and return it
|
||||||
func (tabsLayout *tabsLayoutData) RemoveView(index uint) View {
|
func (tabsLayout *tabsLayoutData) RemoveView(index uint) View {
|
||||||
|
@ -249,8 +610,8 @@ func (tabsLayout *tabsLayoutData) RemoveView(index uint) View {
|
||||||
if count == 1 {
|
if count == 1 {
|
||||||
view := tabsLayout.views[0]
|
view := tabsLayout.views[0]
|
||||||
tabsLayout.views = []View{}
|
tabsLayout.views = []View{}
|
||||||
if tabsLayout.tabListener != nil {
|
for _, listener := range tabsLayout.tabListener {
|
||||||
tabsLayout.tabListener.OnTabsLayoutCurrentChanged(tabsLayout, 0, nil, 0, view)
|
listener(tabsLayout, 0, 0)
|
||||||
}
|
}
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@ -259,10 +620,8 @@ func (tabsLayout *tabsLayoutData) RemoveView(index uint) View {
|
||||||
removeCurrent := (i == current)
|
removeCurrent := (i == current)
|
||||||
if i < current || (removeCurrent && i == count-1) {
|
if i < current || (removeCurrent && i == count-1) {
|
||||||
tabsLayout.properties[Current] = current - 1
|
tabsLayout.properties[Current] = current - 1
|
||||||
if tabsLayout.tabListener != nil {
|
for _, listener := range tabsLayout.tabListener {
|
||||||
currentView := tabsLayout.views[current-1]
|
listener(tabsLayout, current-1, current)
|
||||||
oldCurrentView := tabsLayout.views[current]
|
|
||||||
tabsLayout.tabListener.OnTabsLayoutCurrentChanged(tabsLayout, current-1, currentView, current, oldCurrentView)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,8 +700,17 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
|
||||||
rowLayout = true
|
rowLayout = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch location {
|
||||||
|
case LeftTabs, RightTabs:
|
||||||
|
if tabsHeight.Type != Auto {
|
||||||
|
buffer.WriteString(` width: `)
|
||||||
|
buffer.WriteString(tabsHeight.cssString(""))
|
||||||
|
buffer.WriteByte(';')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var tabsPadding Bounds
|
var tabsPadding Bounds
|
||||||
if value, ok := tabsLayout.session.Constant("ruiTabPadding"); ok {
|
if value, ok := tabsLayout.session.Constant("ruiTabsPadding"); ok {
|
||||||
if tabsPadding.parse(value, tabsLayout.session) {
|
if tabsPadding.parse(value, tabsLayout.session) {
|
||||||
if !tabsPadding.allFieldsAuto() {
|
if !tabsPadding.allFieldsAuto() {
|
||||||
buffer.WriteByte(' ')
|
buffer.WriteByte(' ')
|
||||||
|
@ -354,7 +722,7 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tabsBackground, ok := tabsLayout.session.Color("tabsBackgroundColor"); ok {
|
if tabsBackground, ok := tabsLayout.session.Color("ruiTabsBackgroundColor"); ok {
|
||||||
buffer.WriteString(` background-color: `)
|
buffer.WriteString(` background-color: `)
|
||||||
buffer.WriteString(tabsBackground.cssString())
|
buffer.WriteString(tabsBackground.cssString())
|
||||||
buffer.WriteByte(';')
|
buffer.WriteByte(';')
|
||||||
|
@ -366,9 +734,51 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
|
||||||
activeStyle := tabsLayout.activeTabStyle()
|
activeStyle := tabsLayout.activeTabStyle()
|
||||||
|
|
||||||
notTranslate := GetNotTranslate(tabsLayout, "")
|
notTranslate := GetNotTranslate(tabsLayout, "")
|
||||||
|
closeButton, _ := boolProperty(tabsLayout, TabCloseButton, tabsLayout.session)
|
||||||
|
|
||||||
|
tabMargin := ""
|
||||||
|
if tabsSpace.Type != Auto && tabsSpace.Value > 0 {
|
||||||
|
if rowLayout {
|
||||||
|
tabMargin = ` margin-right: ` + tabsSpace.cssString("") + ";"
|
||||||
|
} else {
|
||||||
|
tabMargin = ` margin-bottom: ` + tabsSpace.cssString("") + ";"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tabStyle, titleDiv string
|
||||||
|
switch location {
|
||||||
|
case LeftTabs, RightTabs:
|
||||||
|
tabStyle = `display: grid; grid-template-rows: auto 1fr auto; align-items: center; justify-items: center; grid-row-gap: 8px;`
|
||||||
|
|
||||||
|
case LeftListTabs, RightListTabs:
|
||||||
|
tabStyle = `display: grid; grid-template-columns: auto 1fr auto; align-items: start; justify-items: center; grid-column-gap: 8px;`
|
||||||
|
|
||||||
|
default:
|
||||||
|
tabStyle = `display: grid; grid-template-columns: auto 1fr auto; align-items: center; justify-items: center; grid-column-gap: 8px;`
|
||||||
|
}
|
||||||
|
|
||||||
|
switch location {
|
||||||
|
case LeftListTabs, RightListTabs:
|
||||||
|
if tabsHeight.Type != Auto {
|
||||||
|
tabStyle += ` height: ` + tabsHeight.cssString("") + ";"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch location {
|
||||||
|
case LeftTabs:
|
||||||
|
titleDiv = `<div style="writing-mode: vertical-lr; transform: rotate(180deg); grid-row-start: 2; grid-row-end: 3; grid-column-start: 1; grid-column-end: 2;">`
|
||||||
|
|
||||||
|
case RightTabs:
|
||||||
|
titleDiv = `<div style="writing-mode: vertical-lr; grid-row-start: 2; grid-row-end: 3; grid-column-start: 1; grid-column-end: 2;">`
|
||||||
|
|
||||||
|
default:
|
||||||
|
titleDiv = `<div style="grid-row-start: 1; grid-row-end: 2; grid-column-start: 2; grid-column-end: 3;">`
|
||||||
|
}
|
||||||
|
|
||||||
last := len(tabsLayout.views) - 1
|
last := len(tabsLayout.views) - 1
|
||||||
for n, view := range tabsLayout.views {
|
for n, view := range tabsLayout.views {
|
||||||
title, _ := stringProperty(view, "title", tabsLayout.session)
|
icon, _ := stringProperty(view, Icon, tabsLayout.session)
|
||||||
|
title, _ := stringProperty(view, Title, tabsLayout.session)
|
||||||
if !notTranslate {
|
if !notTranslate {
|
||||||
title, _ = tabsLayout.Session().GetString(title)
|
title, _ = tabsLayout.Session().GetString(title)
|
||||||
}
|
}
|
||||||
|
@ -387,54 +797,70 @@ func (tabsLayout *tabsLayoutData) htmlSubviews(self View, buffer *strings.Builde
|
||||||
buffer.WriteString(tabsLayoutID)
|
buffer.WriteString(tabsLayoutID)
|
||||||
buffer.WriteString(`\', `)
|
buffer.WriteString(`\', `)
|
||||||
buffer.WriteString(strconv.Itoa(n))
|
buffer.WriteString(strconv.Itoa(n))
|
||||||
buffer.WriteString(`, event)`)
|
buffer.WriteString(`, event)" onclick="tabKeyClickEvent(\'`)
|
||||||
buffer.WriteString(`" onclick="tabKeyClickEvent(\'`)
|
|
||||||
buffer.WriteString(tabsLayoutID)
|
buffer.WriteString(tabsLayoutID)
|
||||||
buffer.WriteString(`\', `)
|
buffer.WriteString(`\', `)
|
||||||
buffer.WriteString(strconv.Itoa(n))
|
buffer.WriteString(strconv.Itoa(n))
|
||||||
buffer.WriteString(`, event)" style="display: flex; flex-flow: row nowrap; justify-content: center; align-items: center; `)
|
buffer.WriteString(`, event)" style="`)
|
||||||
|
buffer.WriteString(tabStyle)
|
||||||
|
|
||||||
if n != last && tabsSpace.Type != Auto && tabsSpace.Value > 0 {
|
if n != last {
|
||||||
if rowLayout {
|
buffer.WriteString(tabMargin)
|
||||||
buffer.WriteString(` margin-right: `)
|
|
||||||
buffer.WriteString(tabsSpace.cssString(""))
|
|
||||||
} else {
|
|
||||||
buffer.WriteString(` margin-bottom: `)
|
|
||||||
buffer.WriteString(tabsSpace.cssString(""))
|
|
||||||
}
|
|
||||||
buffer.WriteByte(';')
|
|
||||||
}
|
|
||||||
|
|
||||||
switch location {
|
|
||||||
case LeftListTabs, RightListTabs:
|
|
||||||
if tabsHeight.Type != Auto {
|
|
||||||
buffer.WriteString(` height: `)
|
|
||||||
buffer.WriteString(tabsHeight.cssString(""))
|
|
||||||
buffer.WriteByte(';')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(`" data-container="`)
|
buffer.WriteString(`" data-container="`)
|
||||||
buffer.WriteString(tabsLayoutID)
|
buffer.WriteString(tabsLayoutID)
|
||||||
buffer.WriteString(`" data-view="`)
|
buffer.WriteString(`" data-view="`)
|
||||||
//buffer.WriteString(view.htmlID())
|
|
||||||
buffer.WriteString(tabsLayoutID)
|
buffer.WriteString(tabsLayoutID)
|
||||||
buffer.WriteString(`-page`)
|
buffer.WriteString(`-page`)
|
||||||
buffer.WriteString(strconv.Itoa(n))
|
buffer.WriteString(strconv.Itoa(n))
|
||||||
buffer.WriteString(`"><div`)
|
buffer.WriteString(`">`)
|
||||||
|
|
||||||
|
if icon != "" {
|
||||||
|
switch location {
|
||||||
|
case LeftTabs:
|
||||||
|
buffer.WriteString(`<img style="grid-row-start: 3; grid-row-end: 4; grid-column-start: 1; grid-column-end: 2;" src="`)
|
||||||
|
|
||||||
|
case RightTabs:
|
||||||
|
buffer.WriteString(`<img style="grid-row-start: 1; grid-row-end: 2; grid-column-start: 1; grid-column-end: 2;" src="`)
|
||||||
|
|
||||||
|
default:
|
||||||
|
buffer.WriteString(`<img style="grid-row-start: 1; grid-row-end: 2; grid-column-start: 1; grid-column-end: 2;" src="`)
|
||||||
|
}
|
||||||
|
buffer.WriteString(icon)
|
||||||
|
buffer.WriteString(`">`)
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.WriteString(titleDiv)
|
||||||
|
buffer.WriteString(title)
|
||||||
|
buffer.WriteString(`</div>`)
|
||||||
|
|
||||||
|
close, ok := boolProperty(view, TabCloseButton, tabsLayout.session)
|
||||||
|
if !ok {
|
||||||
|
close = closeButton
|
||||||
|
}
|
||||||
|
if close {
|
||||||
|
buffer.WriteString(`<div class="ruiTabCloseButton" onclick="tabCloseClickEvent(\'`)
|
||||||
|
buffer.WriteString(tabsLayoutID)
|
||||||
|
buffer.WriteString(`\', `)
|
||||||
|
buffer.WriteString(strconv.Itoa(n))
|
||||||
|
buffer.WriteString(`, event)" style="display: grid; `)
|
||||||
|
|
||||||
switch location {
|
switch location {
|
||||||
case LeftTabs:
|
case LeftTabs:
|
||||||
buffer.WriteString(` style="writing-mode: vertical-lr; transform: rotate(180deg)">`)
|
buffer.WriteString(`grid-row-start: 1; grid-row-end: 2; grid-column-start: 1; grid-column-end: 2;">`)
|
||||||
|
|
||||||
case RightTabs:
|
case RightTabs:
|
||||||
buffer.WriteString(` style="writing-mode: vertical-lr;">`)
|
buffer.WriteString(`grid-row-start: 3; grid-row-end: 4; grid-column-start: 1; grid-column-end: 2;">`)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
buffer.WriteByte('>')
|
buffer.WriteString(`grid-row-start: 1; grid-row-end: 2; grid-column-start: 3; grid-column-end: 4;">`)
|
||||||
}
|
}
|
||||||
buffer.WriteString(title)
|
|
||||||
buffer.WriteString(`</div></div>`)
|
buffer.WriteString(`✕</div>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.WriteString(`</div>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.WriteString(`</div>`)
|
buffer.WriteString(`</div>`)
|
||||||
|
@ -476,15 +902,23 @@ func (tabsLayout *tabsLayoutData) handleCommand(self View, command string, data
|
||||||
current := tabsLayout.currentItem()
|
current := tabsLayout.currentItem()
|
||||||
if current != number {
|
if current != number {
|
||||||
tabsLayout.properties[Current] = number
|
tabsLayout.properties[Current] = number
|
||||||
if tabsLayout.tabListener != nil {
|
for _, listener := range tabsLayout.tabListener {
|
||||||
oldView := tabsLayout.views[current]
|
listener(tabsLayout, number, current)
|
||||||
view := tabsLayout.views[number]
|
|
||||||
tabsLayout.tabListener.OnTabsLayoutCurrentChanged(tabsLayout, number, view, current, oldView)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
case "tabCloseClick":
|
||||||
|
if numberText, ok := data.PropertyValue("number"); ok {
|
||||||
|
if number, err := strconv.Atoi(numberText); err == nil {
|
||||||
|
for _, listener := range tabsLayout.tabCloseListener {
|
||||||
|
listener(tabsLayout, number)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return tabsLayout.viewsContainerData.handleCommand(self, command, data)
|
return tabsLayout.viewsContainerData.handleCommand(self, command, data)
|
||||||
}
|
}
|
||||||
|
|
13
view.go
13
view.go
|
@ -2,7 +2,6 @@ package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -29,18 +28,6 @@ func (frame Frame) Bottom() float64 {
|
||||||
return frame.Top + frame.Height
|
return frame.Top + frame.Height
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params defines a type of a parameters list
|
|
||||||
type Params map[string]interface{}
|
|
||||||
|
|
||||||
func (params Params) AllTags() []string {
|
|
||||||
tags := make([]string, 0, len(params))
|
|
||||||
for t := range params {
|
|
||||||
tags = append(tags, t)
|
|
||||||
}
|
|
||||||
sort.Strings(tags)
|
|
||||||
return tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// View - base view interface
|
// View - base view interface
|
||||||
type View interface {
|
type View interface {
|
||||||
Properties
|
Properties
|
||||||
|
|
Loading…
Reference in New Issue