menu.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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 MenuBar struct {
  9. }
  10. type Menu struct {
  11. Panel // embedded panel
  12. styles *MenuStyles // pointer to current styles
  13. }
  14. // MenuBodyStyle describes the style of the menu body
  15. type MenuBodyStyle struct {
  16. Border BorderSizes
  17. Paddings BorderSizes
  18. BorderColor math32.Color4
  19. BgColor math32.Color
  20. FgColor math32.Color
  21. }
  22. // MenuBodyStyles describes all styles of the menu body
  23. type MenuBodyStyles struct {
  24. Normal MenuBodyStyle
  25. Over MenuBodyStyle
  26. Focus MenuBodyStyle
  27. Disabled MenuBodyStyle
  28. }
  29. // MenuStyles describes all styles of the menu (body and item)
  30. type MenuStyles struct {
  31. Body *MenuBodyStyles // Menu body styles
  32. Item *MenuItemStyles // Menu item styles
  33. }
  34. // MenuItem is an option of a Menu
  35. type MenuItem struct {
  36. Panel // embedded panel
  37. styles *MenuItemStyles // pointer to current styles
  38. label *Label // optional internal label (nil for separators)
  39. image *Image // optional left internal image
  40. licon *Label // optional left internal icon label
  41. ricon *Label // optional right internal icon label for submenu
  42. icode int // icon code (if icon is set)
  43. subm *MenuItem // optional pointer to sub menu
  44. shorcut int32 // shortcut code
  45. enabled bool // enabled state
  46. mouseOver bool
  47. }
  48. // MenuItemStyle describes the style of a menu item
  49. type MenuItemStyle struct {
  50. Border BorderSizes
  51. Paddings BorderSizes
  52. BorderColor math32.Color4
  53. BgColor math32.Color
  54. FgColor math32.Color
  55. }
  56. // MenuItemStyles describes all the menu item styles
  57. type MenuItemStyles struct {
  58. Normal MenuItemStyle
  59. Over MenuItemStyle
  60. Disabled MenuItemStyle
  61. Separator MenuItemStyle
  62. }
  63. // NewMenu creates and returns a pointer to a new empty menu
  64. func NewMenu() *Menu {
  65. m := new(Menu)
  66. m.Panel.Initialize(0, 0)
  67. m.styles = &StyleDefault.Menu
  68. m.update()
  69. return m
  70. }
  71. // AddItem creates and adds a new menu item to this menu and returns the pointer
  72. // to the created item.
  73. func (m *Menu) AddItem(text string) *MenuItem {
  74. mi := newMenuItem(text, m.styles.Item)
  75. m.Panel.Add(mi)
  76. m.recalc()
  77. return mi
  78. }
  79. // AddSeparator creates and adds a new separator to the menu
  80. func (m *Menu) AddSeparator() *MenuItem {
  81. mi := newMenuItem("", m.styles.Item)
  82. m.Panel.Add(mi)
  83. m.recalc()
  84. return mi
  85. }
  86. // RemoveItem removes the specified menu item from this menu
  87. func (m *Menu) RemoveItem(mi *MenuItem) {
  88. }
  89. // update updates the menu visual state
  90. func (m *Menu) update() {
  91. //if s.cursorOver {
  92. // s.applyStyle(&s.styles.Over)
  93. // return
  94. //}
  95. //if s.focus {
  96. // s.applyStyle(&s.styles.Focus)
  97. // return
  98. //}
  99. m.applyStyle(&m.styles.Body.Normal)
  100. }
  101. // applyStyle applies the specified menu body style
  102. func (m *Menu) applyStyle(mbs *MenuBodyStyle) {
  103. m.SetBordersFrom(&mbs.Border)
  104. m.SetBordersColor4(&mbs.BorderColor)
  105. m.SetPaddingsFrom(&mbs.Paddings)
  106. m.SetColor(&mbs.BgColor)
  107. }
  108. // recalc recalculates the positions of this menu internal items
  109. // and the content width and height of the menu
  110. func (m *Menu) recalc() {
  111. // Find maximum item width
  112. maxw := float32(0)
  113. for i := 0; i < len(m.Children()); i++ {
  114. minw := m.Children()[i].(*MenuItem).minWidth()
  115. if minw > maxw {
  116. maxw = minw
  117. }
  118. }
  119. // Sets the position and width of the menu items
  120. // The height is defined by the menu item itself
  121. px := float32(0)
  122. py := float32(0)
  123. for i := 0; i < len(m.Children()); i++ {
  124. mi := m.Children()[i].(*MenuItem)
  125. mi.SetPosition(px, py)
  126. py += mi.height
  127. mi.SetWidth(maxw)
  128. log.Error("width:%v", maxw)
  129. mi.recalc()
  130. }
  131. m.SetContentSize(maxw, py)
  132. }
  133. // newMenuItem creates and returns a pointer to a new menu item
  134. // with the specified text.
  135. func newMenuItem(text string, styles *MenuItemStyles) *MenuItem {
  136. mi := new(MenuItem)
  137. mi.Panel.Initialize(0, 0)
  138. mi.styles = styles
  139. if text != "" {
  140. mi.label = NewLabel(text)
  141. mi.Panel.Add(mi.label)
  142. mi.Panel.Subscribe(OnCursorEnter, mi.onCursor)
  143. mi.Panel.Subscribe(OnCursorLeave, mi.onCursor)
  144. }
  145. mi.recalc()
  146. mi.update()
  147. return mi
  148. }
  149. // SetIcon sets the left icon of this menu item
  150. // If an image was previously set it is replaced by this icon
  151. func (mi *MenuItem) SetIcon(icode int) *MenuItem {
  152. return mi
  153. }
  154. // SetImage sets the left image of this menu item
  155. // If an icon was previously set it is replaced by this image
  156. func (mi *MenuItem) SetImage(img *Image) *MenuItem {
  157. return mi
  158. }
  159. // SetText sets the text of this menu item
  160. func (mi *MenuItem) SetText(text string) *MenuItem {
  161. return mi
  162. }
  163. // SetShortcut sets the keyboard shortcut of this menu item
  164. func (mi *MenuItem) SetShortcut(text string) *MenuItem {
  165. return mi
  166. }
  167. // SetSubmenu sets an associated sub menu item for this menu item
  168. func (mi *MenuItem) SetSubmenu(smi *MenuItem) *MenuItem {
  169. return mi
  170. }
  171. // SetEnabled sets the enabled state of this menu item
  172. func (mi *MenuItem) SetEnabled(enabled bool) *MenuItem {
  173. return mi
  174. }
  175. func (mi *MenuItem) onCursor(evname string, ev interface{}) {
  176. switch evname {
  177. case OnCursorEnter:
  178. mi.mouseOver = true
  179. mi.update()
  180. case OnCursorLeave:
  181. mi.mouseOver = false
  182. mi.update()
  183. }
  184. }
  185. // update updates the menu item visual state
  186. func (mi *MenuItem) update() {
  187. // Separator
  188. if mi.label == nil {
  189. mi.applyStyle(&mi.styles.Separator)
  190. return
  191. }
  192. if mi.mouseOver {
  193. mi.applyStyle(&mi.styles.Over)
  194. return
  195. }
  196. mi.applyStyle(&mi.styles.Normal)
  197. }
  198. // applyStyle applies the specified menu item style
  199. func (mi *MenuItem) applyStyle(mis *MenuItemStyle) {
  200. mi.SetBordersFrom(&mis.Border)
  201. mi.SetBordersColor4(&mis.BorderColor)
  202. mi.SetPaddingsFrom(&mis.Paddings)
  203. mi.SetColor(&mis.BgColor)
  204. }
  205. // recalc recalculates the positions of this menu item internal panels
  206. // and the total height of the menu item.
  207. func (mi *MenuItem) recalc() {
  208. // Separator
  209. if mi.label == nil {
  210. mi.SetHeight(4)
  211. return
  212. }
  213. h := mi.label.height
  214. w := mi.label.width
  215. mi.SetContentSize(w, h)
  216. log.Error("menuitem size: %v/%v", w, h)
  217. }
  218. // minWidth returns the minimum width of this menu item
  219. func (mi *MenuItem) minWidth() float32 {
  220. mw := mi.MinWidth()
  221. if mi.licon != nil {
  222. mw += mi.licon.width
  223. }
  224. if mi.image != nil {
  225. mw += mi.image.width
  226. }
  227. if mi.label != nil {
  228. mw += mi.label.width
  229. }
  230. if mi.ricon != nil {
  231. mw += mi.ricon.width
  232. }
  233. return mw
  234. }
  235. // minHeight returns the minimum height of this menu item
  236. func (mi *MenuItem) minHeight() float32 {
  237. mh := mi.MinHeight()
  238. if mi.label == nil {
  239. return mh + 4
  240. }
  241. mh += mi.label.height
  242. return mh
  243. }