folder.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. PanelStyle
  19. FgColor math32.Color4
  20. Icons [2]string
  21. }
  22. type FolderStyles struct {
  23. Normal FolderStyle
  24. Over FolderStyle
  25. Focus FolderStyle
  26. Disabled FolderStyle
  27. }
  28. // NewFolder creates and returns a pointer to a new folder widget
  29. // with the specified text and initial width
  30. func NewFolder(text string, width float32, contentPanel IPanel) *Folder {
  31. f := new(Folder)
  32. f.Initialize(text, width, contentPanel)
  33. return f
  34. }
  35. // Initialize initializes the Folder with the specified text and initial width
  36. // It is normally used when the folder is embedded in another object
  37. func (f *Folder) Initialize(text string, width float32, contentPanel IPanel) {
  38. f.Panel.Initialize(width, 0)
  39. f.styles = &StyleDefault().Folder
  40. // Initialize label
  41. f.label.initialize(text, StyleDefault().Font)
  42. f.Panel.Add(&f.label)
  43. // Create icon
  44. f.icon.initialize("", StyleDefault().FontIcon)
  45. f.icon.SetFontSize(f.label.FontSize() * 1.3)
  46. f.Panel.Add(&f.icon)
  47. // Setup content panel
  48. f.contentPanel = contentPanel
  49. contentPanel.GetPanel().bounded = false
  50. contentPanel.GetPanel().SetVisible(false)
  51. f.Panel.Add(f.contentPanel)
  52. // Set event callbacks
  53. f.Panel.Subscribe(OnMouseDown, f.onMouse)
  54. f.Panel.Subscribe(OnCursorEnter, f.onCursor)
  55. f.Panel.Subscribe(OnCursorLeave, f.onCursor)
  56. f.alignRight = true
  57. f.update()
  58. f.recalc()
  59. }
  60. // SetStyles set the folder styles overriding the default style
  61. func (f *Folder) SetStyles(fs *FolderStyles) {
  62. f.styles = fs
  63. f.update()
  64. }
  65. // SetAlignRight sets the side of the alignment of the content panel
  66. // in relation to the folder
  67. func (f *Folder) SetAlignRight(state bool) {
  68. f.alignRight = state
  69. f.recalc()
  70. }
  71. // TotalHeight returns this folder total height
  72. // considering the contents panel, if visible
  73. func (f *Folder) TotalHeight() float32 {
  74. height := f.Height()
  75. if f.contentPanel.GetPanel().Visible() {
  76. height += f.contentPanel.GetPanel().Height()
  77. }
  78. return height
  79. }
  80. // onMouse receives mouse button events over the folder panel
  81. func (f *Folder) onMouse(evname string, ev interface{}) {
  82. switch evname {
  83. case OnMouseDown:
  84. cont := f.contentPanel.GetPanel()
  85. if !cont.Visible() {
  86. cont.SetVisible(true)
  87. } else {
  88. cont.SetVisible(false)
  89. }
  90. f.update()
  91. f.recalc()
  92. default:
  93. return
  94. }
  95. }
  96. // onCursor receives cursor events over the folder panel
  97. func (f *Folder) onCursor(evname string, ev interface{}) {
  98. switch evname {
  99. case OnCursorEnter:
  100. f.cursorOver = true
  101. f.update()
  102. case OnCursorLeave:
  103. f.cursorOver = false
  104. f.update()
  105. default:
  106. return
  107. }
  108. }
  109. // update updates the folder visual state
  110. func (f *Folder) update() {
  111. if f.cursorOver {
  112. f.applyStyle(&f.styles.Over)
  113. return
  114. }
  115. f.applyStyle(&f.styles.Normal)
  116. }
  117. // applyStyle applies the specified style
  118. func (f *Folder) applyStyle(s *FolderStyle) {
  119. f.Panel.ApplyStyle(&s.PanelStyle)
  120. icode := 0
  121. if f.contentPanel.GetPanel().Visible() {
  122. icode = 1
  123. }
  124. f.icon.SetText(string(s.Icons[icode]))
  125. f.icon.SetColor4(&s.FgColor)
  126. f.label.SetBgColor4(&s.BgColor)
  127. f.label.SetColor4(&s.FgColor)
  128. }
  129. func (f *Folder) recalc() {
  130. // icon position
  131. f.icon.SetPosition(0, 0)
  132. // Label position and width
  133. f.label.SetPosition(f.icon.Width()+4, 0)
  134. f.Panel.SetContentHeight(f.label.Height())
  135. // Sets position of the base folder scroller panel
  136. cont := f.contentPanel.GetPanel()
  137. if f.alignRight {
  138. cont.SetPosition(0, f.Panel.Height())
  139. } else {
  140. dx := cont.Width() - f.Panel.Width()
  141. cont.SetPosition(-dx, f.Panel.Height())
  142. }
  143. }