|
|
@@ -4,7 +4,11 @@
|
|
|
|
|
|
package gui
|
|
|
|
|
|
-import "github.com/g3n/engine/math32"
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+
|
|
|
+ "github.com/g3n/engine/math32"
|
|
|
+)
|
|
|
|
|
|
// TabBar is a panel which can contain other panels arranged in horizontal Tabs.
|
|
|
// Only one panel is visible at a time.
|
|
|
@@ -13,8 +17,11 @@ type TabBar struct {
|
|
|
Panel // Embedded panel
|
|
|
styles *TabBarStyles // Pointer to current styles
|
|
|
tabs []*Tab // Array of tabs
|
|
|
+ separator Panel // Separator Panel
|
|
|
+ iconList *Label // Icon for tab list button
|
|
|
+ list *List // List for not visible tabs
|
|
|
selected int // Index of the selected tab
|
|
|
- cursorOver bool // Cursor over flag
|
|
|
+ cursorOver bool // Cursor over TabBar panel flag
|
|
|
}
|
|
|
|
|
|
// TabBarStyle describes the style of the TabBar
|
|
|
@@ -27,15 +34,19 @@ type TabBarStyle struct {
|
|
|
|
|
|
// TabBarStyles describes all the TabBarStyles
|
|
|
type TabBarStyles struct {
|
|
|
- Normal TabBarStyle // Style for normal exhibition
|
|
|
- Over TabBarStyle // Style when cursor is over the TabBar
|
|
|
- Focus TabBarStyle // Style when the TabBar has key focus
|
|
|
- Disabled TabBarStyle // Style when the TabBar is disabled
|
|
|
- Tab TabStyles // Style for Tabs
|
|
|
+ SepHeight float32 // Separator width
|
|
|
+ IconList string // Icon for showing tab list
|
|
|
+ IconPaddings BorderSizes
|
|
|
+ Normal TabBarStyle // Style for normal exhibition
|
|
|
+ Over TabBarStyle // Style when cursor is over the TabBar
|
|
|
+ Focus TabBarStyle // Style when the TabBar has key focus
|
|
|
+ Disabled TabBarStyle // Style when the TabBar is disabled
|
|
|
+ Tab TabStyles // Style for Tabs
|
|
|
}
|
|
|
|
|
|
// TabStyle describes the style of the individual Tabs
|
|
|
type TabStyle struct {
|
|
|
+ Margins BorderSizes
|
|
|
Border BorderSizes
|
|
|
Paddings BorderSizes
|
|
|
BorderColor math32.Color4
|
|
|
@@ -45,12 +56,12 @@ type TabStyle struct {
|
|
|
|
|
|
// TabStyles describes all Tab styles
|
|
|
type TabStyles struct {
|
|
|
- MinWidth float32 // Minimum Tab header width
|
|
|
- Normal TabStyle // Style for normal exhibition
|
|
|
- Over TabStyle // Style when cursor is over the Tab
|
|
|
- Focus TabStyle // Style when the Tab has key focus
|
|
|
- Disabled TabStyle // Style when the Tab is disabled
|
|
|
- Selected TabStyle // Style when the Tab is selected
|
|
|
+ IconClose string // Codepoint for close icon in Tab header
|
|
|
+ Normal TabStyle // Style for normal exhibition
|
|
|
+ Over TabStyle // Style when cursor is over the Tab
|
|
|
+ Focus TabStyle // Style when the Tab has key focus
|
|
|
+ Disabled TabStyle // Style when the Tab is disabled
|
|
|
+ Selected TabStyle // Style when the Tab is selected
|
|
|
}
|
|
|
|
|
|
// NewTabBar creates and returns a pointer to a new TabBar widget
|
|
|
@@ -64,6 +75,24 @@ func NewTabBar(width, height float32) *TabBar {
|
|
|
tb.tabs = make([]*Tab, 0)
|
|
|
tb.selected = -1
|
|
|
|
|
|
+ // Creates separator panel
|
|
|
+ tb.separator.Initialize(0, 0)
|
|
|
+ tb.Add(&tb.separator)
|
|
|
+
|
|
|
+ // Create list
|
|
|
+ tb.list = NewVList(0, 0)
|
|
|
+ tb.list.Subscribe(OnMouseOut, func(evname string, ev interface{}) {
|
|
|
+ tb.list.SetVisible(false)
|
|
|
+ })
|
|
|
+ tb.list.Subscribe(OnChange, tb.onListChange)
|
|
|
+ tb.Add(tb.list)
|
|
|
+
|
|
|
+ // Creates list icon button
|
|
|
+ tb.iconList = NewLabel(tb.styles.IconList, true)
|
|
|
+ tb.iconList.SetPaddingsFrom(&tb.styles.IconPaddings)
|
|
|
+ tb.iconList.Subscribe(OnMouseDown, tb.onListButton)
|
|
|
+ tb.Add(tb.iconList)
|
|
|
+
|
|
|
// Subscribe to panel events
|
|
|
tb.Subscribe(OnCursorEnter, tb.onCursor)
|
|
|
tb.Subscribe(OnCursorLeave, tb.onCursor)
|
|
|
@@ -76,11 +105,13 @@ func NewTabBar(width, height float32) *TabBar {
|
|
|
}
|
|
|
|
|
|
// AddTab creates and adds a new Tab panel with the specified header text
|
|
|
-// at end of this TabBar list of tabs.
|
|
|
+// at the end of this TabBar list of tabs.
|
|
|
// Returns the pointer to thew new Tab.
|
|
|
func (tb *TabBar) AddTab(text string) *Tab {
|
|
|
|
|
|
- return tb.InsertTab(text, len(tb.tabs))
|
|
|
+ tab := tb.InsertTab(text, len(tb.tabs))
|
|
|
+ tb.SetSelected(len(tb.tabs) - 1)
|
|
|
+ return tab
|
|
|
}
|
|
|
|
|
|
// InsertTab creates and inserts a new Tab panel with the specified header text
|
|
|
@@ -94,7 +125,7 @@ func (tb *TabBar) InsertTab(text string, pos int) *Tab {
|
|
|
}
|
|
|
|
|
|
// Inserts created Tab at the specified position
|
|
|
- tab := newTab(text, &tb.styles.Tab)
|
|
|
+ tab := newTab(text, tb, &tb.styles.Tab)
|
|
|
tb.tabs = append(tb.tabs, nil)
|
|
|
copy(tb.tabs[pos+1:], tb.tabs[pos:])
|
|
|
tb.tabs[pos] = tab
|
|
|
@@ -107,41 +138,59 @@ func (tb *TabBar) InsertTab(text string, pos int) *Tab {
|
|
|
}
|
|
|
|
|
|
// RemoveTab removes the tab at the specified position in the TabBar.
|
|
|
-// Returns the pointer of the removed tab or nil if the position is invalid.
|
|
|
-func (tb *TabBar) RemoveTab(pos int) *Tab {
|
|
|
+// Returns an error if the position is invalid.
|
|
|
+func (tb *TabBar) RemoveTab(pos int) error {
|
|
|
|
|
|
// Check position to remove from
|
|
|
if pos < 0 || pos >= len(tb.tabs) {
|
|
|
- return nil
|
|
|
+ return fmt.Errorf("Invalid tab position:%d", pos)
|
|
|
}
|
|
|
|
|
|
- // Remove tab from array
|
|
|
+ // Remove tab from TabBar panel
|
|
|
tab := tb.tabs[pos]
|
|
|
+ tb.Remove(&tab.header)
|
|
|
+ tb.Remove(&tab.content)
|
|
|
+
|
|
|
+ // Remove tab from tabbar array
|
|
|
copy(tb.tabs[pos:], tb.tabs[pos+1:])
|
|
|
tb.tabs[len(tb.tabs)-1] = nil
|
|
|
tb.tabs = tb.tabs[:len(tb.tabs)-1]
|
|
|
|
|
|
// Checks if removed tab was selected
|
|
|
if tb.selected == pos {
|
|
|
-
|
|
|
+ // TODO
|
|
|
}
|
|
|
- return tab
|
|
|
+
|
|
|
+ tb.update()
|
|
|
+ tb.recalc()
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-// TabCount returns the current number of tabs
|
|
|
+// TabCount returns the current number of Tabs in the TabBar
|
|
|
func (tb *TabBar) TabCount() int {
|
|
|
|
|
|
return len(tb.tabs)
|
|
|
}
|
|
|
|
|
|
-// TabAt returns the pointer of the Tab object at the specified index.
|
|
|
-// Return nil if the index is invalid
|
|
|
-func (tb *TabBar) TabAt(idx int) *Tab {
|
|
|
+// TabAt returns the pointer of the Tab object at the specified position.
|
|
|
+// Return nil if the position is invalid
|
|
|
+func (tb *TabBar) TabAt(pos int) *Tab {
|
|
|
|
|
|
- if idx < 0 || idx >= len(tb.tabs) {
|
|
|
+ if pos < 0 || pos >= len(tb.tabs) {
|
|
|
return nil
|
|
|
}
|
|
|
- return tb.tabs[idx]
|
|
|
+ return tb.tabs[pos]
|
|
|
+}
|
|
|
+
|
|
|
+// TabPosition returns the position of the Tab specified by its pointer
|
|
|
+func (tb *TabBar) TabPosition(tab *Tab) int {
|
|
|
+
|
|
|
+ for i := 0; i < len(tb.tabs); i++ {
|
|
|
+ if tb.tabs[i] == tab {
|
|
|
+ return i
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -1
|
|
|
}
|
|
|
|
|
|
// SetSelected sets the selected tab of the TabBar to the tab with the specified position.
|
|
|
@@ -151,7 +200,13 @@ func (tb *TabBar) SetSelected(pos int) *Tab {
|
|
|
if pos < 0 || pos >= len(tb.tabs) {
|
|
|
return nil
|
|
|
}
|
|
|
-
|
|
|
+ for i := 0; i < len(tb.tabs); i++ {
|
|
|
+ if i == pos {
|
|
|
+ tb.tabs[i].setSelected(true)
|
|
|
+ } else {
|
|
|
+ tb.tabs[i].setSelected(false)
|
|
|
+ }
|
|
|
+ }
|
|
|
tb.selected = pos
|
|
|
return tb.tabs[pos]
|
|
|
}
|
|
|
@@ -179,6 +234,29 @@ func (tb *TabBar) onCursor(evname string, ev interface{}) {
|
|
|
tb.root.StopPropagation(StopAll)
|
|
|
}
|
|
|
|
|
|
+// onListButtonMouse process subscribed MouseButton events over the list button
|
|
|
+func (tb *TabBar) onListButton(evname string, ev interface{}) {
|
|
|
+
|
|
|
+ switch evname {
|
|
|
+ case OnMouseDown:
|
|
|
+ if !tb.list.Visible() {
|
|
|
+ tb.list.SetVisible(true)
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ return
|
|
|
+ }
|
|
|
+ tb.root.StopPropagation(StopAll)
|
|
|
+}
|
|
|
+
|
|
|
+// onListChange process OnChange event from the tab list
|
|
|
+func (tb *TabBar) onListChange(evname string, ev interface{}) {
|
|
|
+
|
|
|
+ selected := tb.list.Selected()
|
|
|
+ pos := selected[0].GetPanel().UserData().(int)
|
|
|
+ tb.SetSelected(pos)
|
|
|
+ tb.list.SetVisible(false)
|
|
|
+}
|
|
|
+
|
|
|
// applyStyle applies the specified TabBar style
|
|
|
func (tb *TabBar) applyStyle(s *TabBarStyle) {
|
|
|
|
|
|
@@ -186,24 +264,84 @@ func (tb *TabBar) applyStyle(s *TabBarStyle) {
|
|
|
tb.SetBordersColor4(&s.BorderColor)
|
|
|
tb.SetPaddingsFrom(&s.Paddings)
|
|
|
tb.SetColor4(&s.BgColor)
|
|
|
+ tb.separator.SetColor4(&s.BorderColor)
|
|
|
}
|
|
|
|
|
|
// recalc recalculates and updates the positions of all tabs
|
|
|
func (tb *TabBar) recalc() {
|
|
|
|
|
|
- maxWidth := tb.ContentWidth() / float32(len(tb.tabs))
|
|
|
- headerx := float32(0)
|
|
|
+ // Determines how many tabs could be fully shown
|
|
|
+ iconWidth := tb.iconList.Width()
|
|
|
+ availWidth := tb.ContentWidth() - iconWidth
|
|
|
+ var tabWidth float32
|
|
|
+ var totalWidth float32
|
|
|
+ var count int
|
|
|
+ for i := 0; i < len(tb.tabs); i++ {
|
|
|
+ tab := tb.tabs[i]
|
|
|
+ minw := tab.minWidth()
|
|
|
+ if minw > tabWidth {
|
|
|
+ tabWidth = minw
|
|
|
+ }
|
|
|
+ totalWidth = float32(count+1) * tabWidth
|
|
|
+ if totalWidth > availWidth {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ count++
|
|
|
+ }
|
|
|
+
|
|
|
+ tb.list.Clear()
|
|
|
+ if count < len(tb.tabs) {
|
|
|
+ // Sets the list button visible andposition
|
|
|
+ tb.iconList.SetVisible(true)
|
|
|
+ height := tb.tabs[0].header.Height()
|
|
|
+ iy := (height - tb.iconList.Height()) / 2
|
|
|
+ tb.iconList.SetPosition(availWidth, iy)
|
|
|
+ // Sets the tab list position and size
|
|
|
+ listWidth := float32(200)
|
|
|
+ lx := tb.ContentWidth() - listWidth
|
|
|
+ ly := height + 1
|
|
|
+ tb.list.SetPosition(lx, ly)
|
|
|
+ tb.list.SetSize(listWidth, 200)
|
|
|
+ tb.SetTopChild(tb.list)
|
|
|
+
|
|
|
+ } else {
|
|
|
+ tb.iconList.SetVisible(false)
|
|
|
+ tb.list.SetVisible(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ var headerx float32
|
|
|
+ twidth := availWidth / float32(count)
|
|
|
for i := 0; i < len(tb.tabs); i++ {
|
|
|
tab := tb.tabs[i]
|
|
|
- tab.recalc(maxWidth)
|
|
|
- tab.header.SetPosition(headerx, 0)
|
|
|
- // Sets size and position of the Tab content panel
|
|
|
- contentx := float32(0)
|
|
|
- contenty := tab.header.Height()
|
|
|
- tab.content.SetWidth(tb.ContentWidth())
|
|
|
- tab.content.SetHeight(tb.ContentHeight() - tab.header.Height())
|
|
|
- tab.content.SetPosition(contentx, contenty)
|
|
|
- headerx += tab.header.Width()
|
|
|
+ // If Tab can be shown
|
|
|
+ if i < count {
|
|
|
+ tab.recalc(twidth)
|
|
|
+ tab.header.SetPosition(headerx, 0)
|
|
|
+ // Sets size and position of the Tab content panel
|
|
|
+ contentx := float32(0)
|
|
|
+ contenty := tab.header.Height() + tb.styles.SepHeight
|
|
|
+ tab.content.SetWidth(tb.ContentWidth())
|
|
|
+ tab.content.SetHeight(tb.ContentHeight() - contenty)
|
|
|
+ tab.content.SetPosition(contentx, contenty)
|
|
|
+ headerx += tab.header.Width()
|
|
|
+ tab.header.SetVisible(true)
|
|
|
+ continue
|
|
|
+ // Tab cannot be shown, insert into vertical list
|
|
|
+ } else {
|
|
|
+ tab.header.SetVisible(false)
|
|
|
+ item := NewImageLabel(tab.label.Text())
|
|
|
+ item.SetUserData(i)
|
|
|
+ tb.list.Add(item)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Sets the separator size, position and visibility
|
|
|
+ if len(tb.tabs) > 0 {
|
|
|
+ tb.separator.SetSize(tb.ContentWidth(), tb.styles.SepHeight)
|
|
|
+ tb.separator.SetPositionY(tb.tabs[0].header.Height())
|
|
|
+ tb.separator.SetVisible(true)
|
|
|
+ } else {
|
|
|
+ tb.separator.SetVisible(false)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -227,34 +365,49 @@ func (tb *TabBar) update() {
|
|
|
|
|
|
// Tab describes an individual tab of the TabBar
|
|
|
type Tab struct {
|
|
|
+ tb *TabBar // Pointer to parent *TabBar
|
|
|
styles *TabStyles // Pointer to Tab current styles
|
|
|
header Panel // Tab header
|
|
|
- label *Label // Tab label
|
|
|
- icon *Label // Tab optional icon
|
|
|
- img *Image // Tab optional image
|
|
|
- content Panel // User content panel
|
|
|
+ label *Label // Tab user label
|
|
|
+ iconClose *Label // Tab close icon
|
|
|
+ icon *Label // Tab optional user icon
|
|
|
+ img *Image // Tab optional user image
|
|
|
+ bottom Panel
|
|
|
+ content Panel // User content panel
|
|
|
cursorOver bool
|
|
|
+ selected bool
|
|
|
}
|
|
|
|
|
|
// newTab creates and returns a pointer to a new Tab
|
|
|
-func newTab(text string, styles *TabStyles) *Tab {
|
|
|
+func newTab(text string, tb *TabBar, styles *TabStyles) *Tab {
|
|
|
|
|
|
tab := new(Tab)
|
|
|
+ tab.tb = tb
|
|
|
tab.styles = styles
|
|
|
+ // Setup the header panel
|
|
|
tab.header.Initialize(0, 0)
|
|
|
tab.label = NewLabel(text)
|
|
|
+ tab.iconClose = NewLabel(styles.IconClose, true)
|
|
|
tab.header.Add(tab.label)
|
|
|
+ tab.header.Add(tab.iconClose)
|
|
|
+ // Creates the bottom panel
|
|
|
+ tab.bottom.Initialize(0, 0)
|
|
|
+ tab.bottom.SetBounded(false)
|
|
|
+ tab.bottom.SetColor4(&tab.styles.Selected.BgColor)
|
|
|
+ tab.header.Add(&tab.bottom)
|
|
|
tab.content.Initialize(0, 0)
|
|
|
|
|
|
- // Subscribe to header events
|
|
|
+ // Subscribe to header panel events
|
|
|
tab.header.Subscribe(OnCursorEnter, tab.onCursor)
|
|
|
tab.header.Subscribe(OnCursorLeave, tab.onCursor)
|
|
|
+ tab.header.Subscribe(OnMouseDown, tab.onMouseHeader)
|
|
|
+ tab.iconClose.Subscribe(OnMouseDown, tab.onMouseIcon)
|
|
|
|
|
|
tab.update()
|
|
|
return tab
|
|
|
}
|
|
|
|
|
|
-// onCursor process subscribed cursor events
|
|
|
+// onCursor process subscribed cursor events over the tab header
|
|
|
func (tab *Tab) onCursor(evname string, ev interface{}) {
|
|
|
|
|
|
switch evname {
|
|
|
@@ -270,6 +423,30 @@ func (tab *Tab) onCursor(evname string, ev interface{}) {
|
|
|
tab.header.root.StopPropagation(StopAll)
|
|
|
}
|
|
|
|
|
|
+// onMouse process subscribed mouse events over the tab header
|
|
|
+func (tab *Tab) onMouseHeader(evname string, ev interface{}) {
|
|
|
+
|
|
|
+ switch evname {
|
|
|
+ case OnMouseDown:
|
|
|
+ tab.tb.SetSelected(tab.tb.TabPosition(tab))
|
|
|
+ default:
|
|
|
+ return
|
|
|
+ }
|
|
|
+ tab.header.root.StopPropagation(StopAll)
|
|
|
+}
|
|
|
+
|
|
|
+// onMouseIcon process subscribed mouse events over the tab close icon
|
|
|
+func (tab *Tab) onMouseIcon(evname string, ev interface{}) {
|
|
|
+
|
|
|
+ switch evname {
|
|
|
+ case OnMouseDown:
|
|
|
+ tab.tb.RemoveTab(tab.tb.TabPosition(tab))
|
|
|
+ default:
|
|
|
+ return
|
|
|
+ }
|
|
|
+ tab.header.root.StopPropagation(StopAll)
|
|
|
+}
|
|
|
+
|
|
|
// SetText sets the text of the tab header
|
|
|
func (tab *Tab) SetText(text string) *Tab {
|
|
|
|
|
|
@@ -288,21 +465,51 @@ func (tab *Tab) Content() *Panel {
|
|
|
return &tab.content
|
|
|
}
|
|
|
|
|
|
+func (tab *Tab) setSelected(selected bool) {
|
|
|
+
|
|
|
+ tab.selected = selected
|
|
|
+ tab.content.SetVisible(selected)
|
|
|
+ tab.bottom.SetVisible(selected)
|
|
|
+ tab.update()
|
|
|
+ tab.setBottomPanel()
|
|
|
+}
|
|
|
+
|
|
|
+// minWidth returns the minimum width of this Tab header to allow
|
|
|
+// all of its elements to be shown in full.
|
|
|
+func (tab *Tab) minWidth() float32 {
|
|
|
+
|
|
|
+ var minWidth float32
|
|
|
+ if tab.icon != nil {
|
|
|
+ minWidth = tab.icon.Width()
|
|
|
+ } else if tab.img != nil {
|
|
|
+ minWidth = tab.img.Width()
|
|
|
+ }
|
|
|
+ minWidth += tab.label.Width()
|
|
|
+ minWidth += tab.iconClose.Width()
|
|
|
+ return minWidth + tab.header.MinWidth()
|
|
|
+}
|
|
|
+
|
|
|
// applyStyle applies the specified Tab style to the Tab header
|
|
|
func (tab *Tab) applyStyle(s *TabStyle) {
|
|
|
|
|
|
+ tab.header.SetMarginsFrom(&s.Margins)
|
|
|
tab.header.SetBordersFrom(&s.Border)
|
|
|
tab.header.SetBordersColor4(&s.BorderColor)
|
|
|
tab.header.SetPaddingsFrom(&s.Paddings)
|
|
|
tab.header.SetColor4(&s.BgColor)
|
|
|
}
|
|
|
|
|
|
+// update updates the Tab header visual style
|
|
|
func (tab *Tab) update() {
|
|
|
|
|
|
if !tab.header.Enabled() {
|
|
|
tab.applyStyle(&tab.styles.Disabled)
|
|
|
return
|
|
|
}
|
|
|
+ if tab.selected {
|
|
|
+ tab.applyStyle(&tab.styles.Selected)
|
|
|
+ return
|
|
|
+ }
|
|
|
if tab.cursorOver {
|
|
|
tab.applyStyle(&tab.styles.Over)
|
|
|
return
|
|
|
@@ -310,21 +517,41 @@ func (tab *Tab) update() {
|
|
|
tab.applyStyle(&tab.styles.Normal)
|
|
|
}
|
|
|
|
|
|
+// setBottomPanel sets the position and size of the Tab bottom panel
|
|
|
+// to cover the Tabs separator
|
|
|
+func (tab *Tab) setBottomPanel() {
|
|
|
+
|
|
|
+ if tab.selected {
|
|
|
+ bwidth := tab.header.ContentWidth() + tab.header.Paddings().Left + tab.header.Paddings().Right
|
|
|
+ bx := tab.styles.Selected.Margins.Left + tab.styles.Selected.Border.Left
|
|
|
+ tab.bottom.SetSize(bwidth, tab.tb.styles.SepHeight)
|
|
|
+ tab.bottom.SetPosition(bx, tab.header.Height())
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// recalc recalculates the size of the Tab header and the size
|
|
|
-// and positions of the Taheader internal panels
|
|
|
-func (tab *Tab) recalc(maxWidth float32) {
|
|
|
+// and positions of the Tab header internal panels
|
|
|
+func (tab *Tab) recalc(width float32) {
|
|
|
|
|
|
height := tab.label.Height()
|
|
|
- //iconWidth := float32(0)
|
|
|
- //if tab.icon != nil {
|
|
|
- // tab.icon.SetPosition(0, 0)
|
|
|
- // iconWidth = tab.icon.Width()
|
|
|
- //} else if tab.img != nil {
|
|
|
- // tab.img.SetPosition(0, 0)
|
|
|
- // iconWidth = tab.img.Width()
|
|
|
- //}
|
|
|
-
|
|
|
- width := tab.label.Width()
|
|
|
- tab.header.SetContentSize(width, height)
|
|
|
+ tab.header.SetContentHeight(height)
|
|
|
+ tab.header.SetWidth(width)
|
|
|
+
|
|
|
+ labx := float32(0)
|
|
|
+ if tab.icon != nil {
|
|
|
+ tab.icon.SetPosition(0, 0)
|
|
|
+ labx = tab.icon.Width()
|
|
|
+ } else if tab.img != nil {
|
|
|
+ tab.img.SetPosition(0, 0)
|
|
|
+ labx = tab.img.Width()
|
|
|
+ }
|
|
|
+ tab.label.SetPosition(labx, 0)
|
|
|
+
|
|
|
+ // Sets the close icon position
|
|
|
+ icx := tab.header.ContentWidth() - tab.iconClose.Width()
|
|
|
+ icy := (tab.header.ContentHeight() - tab.iconClose.Height()) / 2
|
|
|
+ tab.iconClose.SetPosition(icx, icy)
|
|
|
|
|
|
+ // Sets the position of the bottom panel to cover separator
|
|
|
+ tab.setBottomPanel()
|
|
|
}
|