folder.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package gui
  5. import (
  6. "github.com/g3n/engine/math32"
  7. )
  8. type Folder struct {
  9. Panel // Embedded panel
  10. label Label // Folder label
  11. icon Label // Folder icon
  12. contentPanel IPanel // Content panel
  13. styles *FolderStyles
  14. cursorOver bool
  15. alignRight bool
  16. }
  17. type FolderStyle struct {
  18. Margins BorderSizes
  19. Border BorderSizes
  20. Paddings BorderSizes
  21. BorderColor math32.Color4
  22. BgColor math32.Color
  23. FgColor math32.Color
  24. Icons [2]int
  25. }
  26. type FolderStyles struct {
  27. Normal *FolderStyle
  28. Over *FolderStyle
  29. Focus *FolderStyle
  30. Disabled *FolderStyle
  31. }
  32. // NewFolder creates and returns a pointer to a new folder widget
  33. // with the specified text and initial width
  34. func NewFolder(text string, width float32, contentPanel IPanel) *Folder {
  35. f := new(Folder)
  36. f.Initialize(text, width, contentPanel)
  37. return f
  38. }
  39. // Initialize initializes the Folder with the specified text and initial width
  40. // It is normally used when the folder is embedded in another object
  41. func (f *Folder) Initialize(text string, width float32, contentPanel IPanel) {
  42. f.Panel.Initialize(width, 0)
  43. f.styles = &StyleDefault.Folder
  44. // Initialize label
  45. f.label.initialize(text, StyleDefault.Font)
  46. f.Panel.Add(&f.label)
  47. // Create icon
  48. f.icon.initialize("", StyleDefault.FontIcon)
  49. f.icon.SetFontSize(f.label.FontSize() * 1.3)
  50. f.Panel.Add(&f.icon)
  51. // Setup content panel
  52. f.contentPanel = contentPanel
  53. contentPanel.GetPanel().bounded = false
  54. contentPanel.GetPanel().SetVisible(false)
  55. f.Panel.Add(f.contentPanel)
  56. // Set event callbacks
  57. f.Panel.Subscribe(OnMouseDown, f.onMouse)
  58. f.Panel.Subscribe(OnCursorEnter, f.onCursor)
  59. f.Panel.Subscribe(OnCursorLeave, f.onCursor)
  60. f.alignRight = true
  61. f.update()
  62. f.recalc()
  63. }
  64. // SetStyles set the folder styles overriding the default style
  65. func (f *Folder) SetStyles(fs *FolderStyles) {
  66. f.styles = fs
  67. f.update()
  68. }
  69. // SetAlignRight sets the side of the alignment of the content panel
  70. // in relation to the folder
  71. func (f *Folder) SetAlignRight(state bool) {
  72. f.alignRight = state
  73. f.recalc()
  74. }
  75. // TotalHeight returns this folder total height
  76. // considering the contents panel, if visible
  77. func (f *Folder) TotalHeight() float32 {
  78. height := f.Height()
  79. if f.contentPanel.GetPanel().Visible() {
  80. height += f.contentPanel.GetPanel().Height()
  81. }
  82. return height
  83. }
  84. // onMouse receives mouse button events over the folder panel
  85. func (f *Folder) onMouse(evname string, ev interface{}) {
  86. switch evname {
  87. case OnMouseDown:
  88. cont := f.contentPanel.GetPanel()
  89. if !cont.Visible() {
  90. cont.SetVisible(true)
  91. log.Error("Folder PanelZ:%6.5f", cont.Position().Z)
  92. for _, c := range cont.Children() {
  93. log.Error("Folder child PanelZ:%6.5f", c.GetNode().Position().Z)
  94. }
  95. } else {
  96. cont.SetVisible(false)
  97. }
  98. f.update()
  99. f.recalc()
  100. default:
  101. return
  102. }
  103. }
  104. // onCursor receives cursor events over the folder panel
  105. func (f *Folder) onCursor(evname string, ev interface{}) {
  106. switch evname {
  107. case OnCursorEnter:
  108. f.cursorOver = true
  109. f.update()
  110. case OnCursorLeave:
  111. f.cursorOver = false
  112. f.update()
  113. default:
  114. return
  115. }
  116. }
  117. // update updates the folder visual state
  118. func (f *Folder) update() {
  119. if f.cursorOver {
  120. f.applyStyle(f.styles.Over)
  121. return
  122. }
  123. f.applyStyle(f.styles.Normal)
  124. }
  125. // applyStyle applies the specified style
  126. func (f *Folder) applyStyle(s *FolderStyle) {
  127. f.SetMarginsFrom(&s.Margins)
  128. f.SetBordersColor4(&s.BorderColor)
  129. f.SetBordersFrom(&s.Border)
  130. f.SetPaddingsFrom(&s.Paddings)
  131. f.SetColor(&s.BgColor)
  132. icode := 0
  133. if f.contentPanel.GetPanel().Visible() {
  134. icode = 1
  135. }
  136. f.icon.SetText(string(s.Icons[icode]))
  137. f.icon.SetColor(&s.FgColor)
  138. f.label.SetBgColor(&s.BgColor)
  139. f.label.SetColor(&s.FgColor)
  140. }
  141. func (f *Folder) recalc() {
  142. // icon position
  143. f.icon.SetPosition(0, 0)
  144. // Label position and width
  145. f.label.SetPosition(f.icon.Width()+4, 0)
  146. f.Panel.SetContentHeight(f.label.Height())
  147. // Sets position of the base folder scroller panel
  148. cont := f.contentPanel.GetPanel()
  149. if f.alignRight {
  150. cont.SetPosition(0, f.Panel.Height())
  151. } else {
  152. dx := cont.Width() - f.Panel.Width()
  153. cont.SetPosition(-dx, f.Panel.Height())
  154. }
  155. }