builder_panel.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  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. "path/filepath"
  7. "github.com/g3n/engine/math32"
  8. "github.com/g3n/engine/window"
  9. )
  10. // buildPanel builds an object of type Panel
  11. func buildPanel(b *Builder, am map[string]interface{}) (IPanel, error) {
  12. pan := NewPanel(0, 0)
  13. err := b.setAttribs(am, pan, asPANEL)
  14. if err != nil {
  15. return nil, err
  16. }
  17. // Builds children recursively
  18. if am[AttribItems] != nil {
  19. items := am[AttribItems].([]map[string]interface{})
  20. for i := 0; i < len(items); i++ {
  21. item := items[i]
  22. child, err := b.build(item, pan)
  23. if err != nil {
  24. return nil, err
  25. }
  26. pan.Add(child)
  27. }
  28. }
  29. return pan, nil
  30. }
  31. // buildImagePanel builds a gui object of type ImagePanel
  32. func buildImagePanel(b *Builder, am map[string]interface{}) (IPanel, error) {
  33. // Checks imagefile attribute
  34. if am[AttribImageFile] == nil {
  35. return nil, b.err(am, AttribImageFile, "Must be supplied")
  36. }
  37. // If path is not absolute join with user supplied image base path
  38. imagefile := am[AttribImageFile].(string)
  39. if !filepath.IsAbs(imagefile) {
  40. imagefile = filepath.Join(b.imgpath, imagefile)
  41. }
  42. // Builds panel and set common attributes
  43. panel, err := NewImage(imagefile)
  44. if err != nil {
  45. return nil, err
  46. }
  47. err = b.setAttribs(am, panel, asPANEL)
  48. if err != nil {
  49. return nil, err
  50. }
  51. // Sets optional AspectWidth attribute
  52. if aw := am[AttribAspectWidth]; aw != nil {
  53. panel.SetContentAspectWidth(aw.(float32))
  54. }
  55. // Sets optional AspectHeight attribute
  56. if ah := am[AttribAspectHeight]; ah != nil {
  57. panel.SetContentAspectHeight(ah.(float32))
  58. }
  59. // Builds children recursively
  60. if am[AttribItems] != nil {
  61. items := am[AttribItems].([]map[string]interface{})
  62. for i := 0; i < len(items); i++ {
  63. item := items[i]
  64. child, err := b.build(item, panel)
  65. if err != nil {
  66. return nil, err
  67. }
  68. panel.Add(child)
  69. }
  70. }
  71. return panel, nil
  72. }
  73. // buildLabel builds a gui object of type Label
  74. func buildLabel(b *Builder, am map[string]interface{}) (IPanel, error) {
  75. var label *Label
  76. if am[AttribIcon] != nil {
  77. label = NewLabel(am[AttribIcon].(string), true)
  78. } else if am[AttribText] != nil {
  79. label = NewLabel(am[AttribText].(string))
  80. } else {
  81. label = NewLabel("")
  82. }
  83. // Sets common attributes
  84. err := b.setAttribs(am, label, asPANEL)
  85. if err != nil {
  86. return nil, err
  87. }
  88. // Set optional background color
  89. if bgc := am[AttribBgColor]; bgc != nil {
  90. label.SetBgColor4(bgc.(*math32.Color4))
  91. }
  92. // Set optional font color
  93. if fc := am[AttribFontColor]; fc != nil {
  94. label.SetColor4(fc.(*math32.Color4))
  95. }
  96. // Sets optional font size
  97. if fs := am[AttribFontSize]; fs != nil {
  98. label.SetFontSize(float64(fs.(float32)))
  99. }
  100. // Sets optional font dpi
  101. if fdpi := am[AttribFontDPI]; fdpi != nil {
  102. label.SetFontDPI(float64(fdpi.(float32)))
  103. }
  104. // Sets optional line spacing
  105. if ls := am[AttribLineSpacing]; ls != nil {
  106. label.SetLineSpacing(float64(ls.(float32)))
  107. }
  108. return label, nil
  109. }
  110. // buildImageLabel builds a gui object of type: ImageLabel
  111. func buildImageLabel(b *Builder, am map[string]interface{}) (IPanel, error) {
  112. // Builds image label and set common attributes
  113. var text string
  114. if am[AttribText] != nil {
  115. text = am[AttribText].(string)
  116. }
  117. imglabel := NewImageLabel(text)
  118. err := b.setAttribs(am, imglabel, asPANEL)
  119. if err != nil {
  120. return nil, err
  121. }
  122. // Sets optional icon(s)
  123. if icon := am[AttribIcon]; icon != nil {
  124. imglabel.SetIcon(icon.(string))
  125. }
  126. // Sets optional image from file
  127. // If path is not absolute join with user supplied image base path
  128. if imgf := am[AttribImageFile]; imgf != nil {
  129. path := imgf.(string)
  130. if !filepath.IsAbs(path) {
  131. path = filepath.Join(b.imgpath, path)
  132. }
  133. err := imglabel.SetImageFromFile(path)
  134. if err != nil {
  135. return nil, err
  136. }
  137. }
  138. return imglabel, nil
  139. }
  140. // buildButton builds a gui object of type: Button
  141. func buildButton(b *Builder, am map[string]interface{}) (IPanel, error) {
  142. // Builds button and set commont attributes
  143. var text string
  144. if am[AttribText] != nil {
  145. text = am[AttribText].(string)
  146. }
  147. button := NewButton(text)
  148. err := b.setAttribs(am, button, asWIDGET)
  149. if err != nil {
  150. return nil, err
  151. }
  152. // Sets optional icon(s)
  153. if icon := am[AttribIcon]; icon != nil {
  154. button.SetIcon(icon.(string))
  155. }
  156. // Sets optional image from file
  157. // If path is not absolute join with user supplied image base path
  158. if imgf := am[AttribImageFile]; imgf != nil {
  159. path := imgf.(string)
  160. if !filepath.IsAbs(path) {
  161. path = filepath.Join(b.imgpath, path)
  162. }
  163. err := button.SetImage(path)
  164. if err != nil {
  165. return nil, err
  166. }
  167. }
  168. return button, nil
  169. }
  170. // buildEdit builds a gui object of type: "Edit"
  171. func buildEdit(b *Builder, am map[string]interface{}) (IPanel, error) {
  172. // Builds button and set attributes
  173. var width float32
  174. var placeholder string
  175. if aw := am[AttribWidth]; aw != nil {
  176. width = aw.(float32)
  177. }
  178. if ph := am[AttribPlaceHolder]; ph != nil {
  179. placeholder = ph.(string)
  180. }
  181. edit := NewEdit(int(width), placeholder)
  182. err := b.setAttribs(am, edit, asWIDGET)
  183. if err != nil {
  184. return nil, err
  185. }
  186. return edit, nil
  187. }
  188. // buildCheckBox builds a gui object of type: CheckBox
  189. func buildCheckBox(b *Builder, am map[string]interface{}) (IPanel, error) {
  190. // Builds check box and set commont attributes
  191. var text string
  192. if am[AttribText] != nil {
  193. text = am[AttribText].(string)
  194. }
  195. cb := NewCheckBox(text)
  196. err := b.setAttribs(am, cb, asWIDGET)
  197. if err != nil {
  198. return nil, err
  199. }
  200. // Sets optional checked value
  201. if checked := am[AttribChecked]; checked != nil {
  202. cb.SetValue(checked.(bool))
  203. }
  204. return cb, nil
  205. }
  206. // buildRadioButton builds a gui object of type: RadioButton
  207. func buildRadioButton(b *Builder, am map[string]interface{}) (IPanel, error) {
  208. // Builds check box and set commont attributes
  209. var text string
  210. if am[AttribText] != nil {
  211. text = am[AttribText].(string)
  212. }
  213. rb := NewRadioButton(text)
  214. err := b.setAttribs(am, rb, asWIDGET)
  215. if err != nil {
  216. return nil, err
  217. }
  218. // Sets optional radio button group
  219. if gr := am[AttribGroup]; gr != nil {
  220. rb.SetGroup(gr.(string))
  221. }
  222. // Sets optional checked value
  223. if checked := am[AttribChecked]; checked != nil {
  224. rb.SetValue(checked.(bool))
  225. }
  226. return rb, nil
  227. }
  228. // buildVList builds a gui object of type: VList
  229. func buildVList(b *Builder, am map[string]interface{}) (IPanel, error) {
  230. // Builds list and set commont attributes
  231. list := NewVList(0, 0)
  232. err := b.setAttribs(am, list, asWIDGET)
  233. if err != nil {
  234. return nil, err
  235. }
  236. // Builds children
  237. if am[AttribItems] != nil {
  238. items := am[AttribItems].([]map[string]interface{})
  239. for i := 0; i < len(items); i++ {
  240. item := items[i]
  241. child, err := b.build(item, list)
  242. if err != nil {
  243. return nil, err
  244. }
  245. list.Add(child)
  246. }
  247. }
  248. return list, nil
  249. }
  250. // buildHList builds a gui object of type: VList
  251. func buildHList(b *Builder, am map[string]interface{}) (IPanel, error) {
  252. // Builds list and set commont attributes
  253. list := NewHList(0, 0)
  254. err := b.setAttribs(am, list, asWIDGET)
  255. if err != nil {
  256. return nil, err
  257. }
  258. // Builds children
  259. if am[AttribItems] != nil {
  260. items := am[AttribItems].([]map[string]interface{})
  261. for i := 0; i < len(items); i++ {
  262. item := items[i]
  263. child, err := b.build(item, list)
  264. if err != nil {
  265. return nil, err
  266. }
  267. list.Add(child)
  268. }
  269. }
  270. return list, nil
  271. }
  272. // buildDropDown builds a gui object of type: DropDown
  273. func buildDropDown(b *Builder, am map[string]interface{}) (IPanel, error) {
  274. // If image label attribute defined use it, otherwise
  275. // uses default value.
  276. var imglabel *ImageLabel
  277. if iv := am[AttribImageLabel]; iv != nil {
  278. imgl := iv.(map[string]interface{})
  279. imgl[AttribType] = TypeImageLabel
  280. ipan, err := b.build(imgl, nil)
  281. if err != nil {
  282. return nil, err
  283. }
  284. imglabel = ipan.(*ImageLabel)
  285. } else {
  286. imglabel = NewImageLabel("")
  287. }
  288. // Builds drop down and set common attributes
  289. dd := NewDropDown(0, imglabel)
  290. err := b.setAttribs(am, dd, asWIDGET)
  291. if err != nil {
  292. return nil, err
  293. }
  294. // Builds children
  295. if am[AttribItems] != nil {
  296. items := am[AttribItems].([]map[string]interface{})
  297. for i := 0; i < len(items); i++ {
  298. item := items[i]
  299. child, err := b.build(item, dd)
  300. if err != nil {
  301. return nil, err
  302. }
  303. dd.Add(child.(*ImageLabel))
  304. }
  305. }
  306. return dd, nil
  307. }
  308. // buildMenu builds a gui object of type: Menu or MenuBar from the
  309. // specified panel descriptor.
  310. func buildMenu(b *Builder, am map[string]interface{}) (IPanel, error) {
  311. // Builds menu bar or menu
  312. var menu *Menu
  313. if am[AttribType].(string) == TypeMenuBar {
  314. menu = NewMenuBar()
  315. } else {
  316. menu = NewMenu()
  317. }
  318. // Only sets attribs for top level menus
  319. if pi := am[AttribParentInternal]; pi != nil {
  320. par := pi.(map[string]interface{})
  321. ptype := ""
  322. if ti := par[AttribType]; ti != nil {
  323. ptype = ti.(string)
  324. }
  325. if ptype != TypeMenu && ptype != TypeMenuBar {
  326. err := b.setAttribs(am, menu, asWIDGET)
  327. if err != nil {
  328. return nil, err
  329. }
  330. }
  331. }
  332. // Builds and adds menu items
  333. if am[AttribItems] != nil {
  334. items := am[AttribItems].([]map[string]interface{})
  335. for i := 0; i < len(items); i++ {
  336. // Get the item optional type and text
  337. item := items[i]
  338. itype := ""
  339. itext := ""
  340. if iv := item[AttribType]; iv != nil {
  341. itype = iv.(string)
  342. }
  343. if iv := item[AttribText]; iv != nil {
  344. itext = iv.(string)
  345. }
  346. // Item is another menu
  347. if itype == TypeMenu {
  348. subm, err := buildMenu(b, item)
  349. if err != nil {
  350. return nil, err
  351. }
  352. menu.AddMenu(itext, subm.(*Menu))
  353. continue
  354. }
  355. // Item is a separator
  356. if itext == TypeSeparator {
  357. menu.AddSeparator()
  358. continue
  359. }
  360. // Item must be a menu option
  361. mi := menu.AddOption(itext)
  362. // Set item optional icon(s)
  363. if icon := item[AttribIcon]; icon != nil {
  364. mi.SetIcon(icon.(string))
  365. }
  366. // Sets optional menu item shortcut
  367. if sci := item[AttribShortcut]; sci != nil {
  368. sc := sci.([]int)
  369. mi.SetShortcut(window.ModifierKey(sc[0]), window.Key(sc[1]))
  370. }
  371. }
  372. }
  373. return menu, nil
  374. }
  375. // buildSlider builds a gui object of type: HSlider or VSlider
  376. func buildSlider(b *Builder, am map[string]interface{}) (IPanel, error) {
  377. // Builds horizontal or vertical slider
  378. var slider *Slider
  379. if am[AttribType].(string) == TypeHSlider {
  380. slider = NewHSlider(0, 0)
  381. } else {
  382. slider = NewVSlider(0, 0)
  383. }
  384. // Sets common attributes
  385. err := b.setAttribs(am, slider, asWIDGET)
  386. if err != nil {
  387. return nil, err
  388. }
  389. // Sets optional text
  390. if itext := am[AttribText]; itext != nil {
  391. slider.SetText(itext.(string))
  392. }
  393. // Sets optional scale factor
  394. if isf := am[AttribScaleFactor]; isf != nil {
  395. slider.SetScaleFactor(isf.(float32))
  396. }
  397. // Sets optional value
  398. if iv := am[AttribValue]; iv != nil {
  399. slider.SetValue(iv.(float32))
  400. }
  401. return slider, nil
  402. }
  403. // buildSplitter builds a gui object of type: HSplitterr or VSplitter
  404. func buildSplitter(b *Builder, am map[string]interface{}) (IPanel, error) {
  405. // Builds horizontal or vertical splitter
  406. var splitter *Splitter
  407. if am[AttribType].(string) == TypeHSplitter {
  408. splitter = NewHSplitter(0, 0)
  409. } else {
  410. splitter = NewVSplitter(0, 0)
  411. }
  412. // Sets common attributes
  413. err := b.setAttribs(am, splitter, asWIDGET)
  414. if err != nil {
  415. return nil, err
  416. }
  417. // Sets optional split value
  418. if v := am[AttribSplit]; v != nil {
  419. splitter.SetSplit(v.(float32))
  420. }
  421. // Internal function to set each of the splitter's panel attributes and items
  422. setpan := func(attrib string, pan *Panel) error {
  423. // Get internal panel attributes
  424. ipattribs := am[attrib]
  425. if ipattribs == nil {
  426. return nil
  427. }
  428. pattr := ipattribs.(map[string]interface{})
  429. // Set panel attributes
  430. err := b.setAttribs(pattr, pan, asPANEL)
  431. if err != nil {
  432. return nil
  433. }
  434. // Builds panel children
  435. if pattr[AttribItems] != nil {
  436. items := pattr[AttribItems].([]map[string]interface{})
  437. for i := 0; i < len(items); i++ {
  438. item := items[i]
  439. child, err := b.build(item, pan)
  440. if err != nil {
  441. return err
  442. }
  443. pan.Add(child)
  444. }
  445. }
  446. return nil
  447. }
  448. // Set optional splitter panel's attributes
  449. err = setpan(AttribPanel0, &splitter.P0)
  450. if err != nil {
  451. return nil, err
  452. }
  453. err = setpan(AttribPanel1, &splitter.P1)
  454. if err != nil {
  455. return nil, err
  456. }
  457. return splitter, nil
  458. }
  459. // buildTree builds a gui object of type: Tree
  460. func buildTree(b *Builder, am map[string]interface{}) (IPanel, error) {
  461. // Builds tree and sets its common attributes
  462. tree := NewTree(0, 0)
  463. err := b.setAttribs(am, tree, asWIDGET)
  464. if err != nil {
  465. return nil, err
  466. }
  467. // Internal function to build tree nodes recursively
  468. var buildItems func(am map[string]interface{}, pnode *TreeNode) error
  469. buildItems = func(am map[string]interface{}, pnode *TreeNode) error {
  470. v := am[AttribItems]
  471. if v == nil {
  472. return nil
  473. }
  474. items := v.([]map[string]interface{})
  475. for i := 0; i < len(items); i++ {
  476. // Get the item type
  477. item := items[i]
  478. itype := ""
  479. if v := item[AttribType]; v != nil {
  480. itype = v.(string)
  481. }
  482. itext := ""
  483. if v := item[AttribText]; v != nil {
  484. itext = v.(string)
  485. }
  486. // Item is a tree node
  487. if itype == "" || itype == TypeTreeNode {
  488. var node *TreeNode
  489. if pnode == nil {
  490. node = tree.AddNode(itext)
  491. } else {
  492. node = pnode.AddNode(itext)
  493. }
  494. err := buildItems(item, node)
  495. if err != nil {
  496. return err
  497. }
  498. continue
  499. }
  500. // Other controls
  501. ipan, err := b.build(item, nil)
  502. if err != nil {
  503. return err
  504. }
  505. if pnode == nil {
  506. tree.Add(ipan)
  507. } else {
  508. pnode.Add(ipan)
  509. }
  510. }
  511. return nil
  512. }
  513. // Build nodes
  514. err = buildItems(am, nil)
  515. if err != nil {
  516. return nil, err
  517. }
  518. return tree, nil
  519. }
  520. // buildWindow builds a gui object of type: Window
  521. func buildWindow(b *Builder, am map[string]interface{}) (IPanel, error) {
  522. // Builds window and sets its common attributes
  523. win := NewWindow(0, 0)
  524. err := b.setAttribs(am, win, asWIDGET)
  525. if err != nil {
  526. return nil, err
  527. }
  528. // Sets optional title
  529. if title := am[AttribTitle]; title != nil {
  530. win.SetTitle(title.(string))
  531. }
  532. // Set optional resizable borders
  533. if resiz := am[AttribResizeBorders]; resiz != nil {
  534. win.SetResizable(resiz.(ResizeBorders))
  535. }
  536. // Builds window children
  537. if v := am[AttribItems]; v != nil {
  538. items := v.([]map[string]interface{})
  539. for i := 0; i < len(items); i++ {
  540. item := items[i]
  541. child, err := b.build(item, win)
  542. if err != nil {
  543. return nil, err
  544. }
  545. win.Add(child)
  546. }
  547. }
  548. return win, nil
  549. }
  550. // buildChart builds a gui object of type: Chart
  551. func buildChart(b *Builder, am map[string]interface{}) (IPanel, error) {
  552. // Builds window and sets its common attributes
  553. chart := NewChart(0, 0)
  554. err := b.setAttribs(am, chart, asPANEL)
  555. if err != nil {
  556. return nil, err
  557. }
  558. // Sets optional title
  559. if title := am[AttribTitle]; title != nil {
  560. chart.SetTitle(title.(string), 14)
  561. }
  562. // Sets x scale attibutes
  563. if v := am[AttribScalex]; v != nil {
  564. sx := v.(map[string]interface{})
  565. // Sets optional x scale margin
  566. if mx := sx[AttribMargin]; mx != nil {
  567. chart.SetMarginX(mx.(float32))
  568. }
  569. // Sets optional x scale format
  570. if fx := sx[AttribFormat]; fx != nil {
  571. chart.SetFormatX(fx.(string))
  572. }
  573. // Sets optional x scale font size
  574. if fsize := sx[AttribFontSize]; fsize != nil {
  575. chart.SetFontSizeX(float64(fsize.(float32)))
  576. }
  577. // Number of lines
  578. lines := 4
  579. if v := sx[AttribLines]; v != nil {
  580. lines = v.(int)
  581. }
  582. // Lines color
  583. color4 := math32.NewColor4("Black")
  584. if v := sx[AttribColor]; v != nil {
  585. color4 = v.(*math32.Color4)
  586. }
  587. color := color4.ToColor()
  588. chart.SetScaleX(lines, &color)
  589. // Range first
  590. firstX := float32(0)
  591. if v := sx[AttribFirstx]; v != nil {
  592. firstX = v.(float32)
  593. }
  594. // Range step
  595. stepX := float32(1)
  596. if v := sx[AttribStepx]; v != nil {
  597. stepX = v.(float32)
  598. }
  599. // Range count step
  600. countStepX := float32(1)
  601. if v := sx[AttribStepx]; v != nil {
  602. countStepX = v.(float32)
  603. }
  604. chart.SetRangeX(firstX, stepX, countStepX)
  605. }
  606. // Sets y scale attibutes
  607. if v := am[AttribScaley]; v != nil {
  608. sy := v.(map[string]interface{})
  609. // Sets optional y scale margin
  610. if my := sy[AttribMargin]; my != nil {
  611. chart.SetMarginY(my.(float32))
  612. }
  613. // Sets optional y scale format
  614. if fy := sy[AttribFormat]; fy != nil {
  615. chart.SetFormatY(fy.(string))
  616. }
  617. // Sets optional y scale font size
  618. if fsize := sy[AttribFontSize]; fsize != nil {
  619. chart.SetFontSizeY(float64(fsize.(float32)))
  620. }
  621. // Number of lines
  622. lines := 4
  623. if v := sy[AttribLines]; v != nil {
  624. lines = v.(int)
  625. }
  626. // Lines color
  627. color4 := math32.NewColor4("Black")
  628. if v := sy[AttribColor]; v != nil {
  629. color4 = v.(*math32.Color4)
  630. }
  631. color := color4.ToColor()
  632. chart.SetScaleY(lines, &color)
  633. // Range min
  634. rmin := float32(-10)
  635. if v := sy[AttribRangeMin]; v != nil {
  636. rmin = v.(float32)
  637. }
  638. // Range max
  639. rmax := float32(10)
  640. if v := sy[AttribRangeMax]; v != nil {
  641. rmax = v.(float32)
  642. }
  643. chart.SetRangeY(rmin, rmax)
  644. // Range auto
  645. if rauto := sy[AttribRangeAuto]; rauto != nil {
  646. chart.SetRangeYauto(v.(bool))
  647. }
  648. }
  649. return chart, nil
  650. }
  651. // buildTable builds a gui object of type: Table
  652. func buildTable(b *Builder, am map[string]interface{}) (IPanel, error) {
  653. // Internal function to build a TableColumn from its attribute map
  654. buildTableCol := func(b *Builder, am map[string]interface{}) (*TableColumn, error) {
  655. tc := &TableColumn{}
  656. if iv := am[AttribId]; iv != nil {
  657. tc.Id = iv.(string)
  658. }
  659. if iv := am[AttribHeader]; iv != nil {
  660. tc.Header = iv.(string)
  661. }
  662. if iv := am[AttribWidth]; iv != nil {
  663. tc.Width = iv.(float32)
  664. }
  665. if iv := am[AttribMinwidth]; iv != nil {
  666. tc.Minwidth = iv.(float32)
  667. }
  668. if iv := am[AttribHidden]; iv != nil {
  669. tc.Hidden = iv.(bool)
  670. }
  671. if iv := am[AttribFormat]; iv != nil {
  672. tc.Format = iv.(string)
  673. }
  674. if iv := am[AttribExpand]; iv != nil {
  675. tc.Expand = iv.(float32)
  676. }
  677. if iv := am[AttribResize]; iv != nil {
  678. tc.Resize = iv.(bool)
  679. }
  680. if iv := am[AttribSortType]; iv != nil {
  681. tc.Sort = iv.(TableSortType)
  682. }
  683. return tc, nil
  684. }
  685. // Builds table columns array
  686. tableCols := []TableColumn{}
  687. if iv := am[AttribColumns]; iv != nil {
  688. cols := iv.([]map[string]interface{})
  689. for _, c := range cols {
  690. tc, err := buildTableCol(b, c)
  691. if err != nil {
  692. return nil, err
  693. }
  694. tableCols = append(tableCols, *tc)
  695. }
  696. }
  697. // Creates table and set common attributes
  698. table, err := NewTable(0, 0, tableCols)
  699. if err != nil {
  700. return nil, err
  701. }
  702. err = b.setAttribs(am, table, asPANEL)
  703. if err != nil {
  704. return nil, err
  705. }
  706. // Sets optional show header attribute
  707. if show := am[AttribShowHeader]; show != nil {
  708. table.ShowHeader(show.(bool))
  709. }
  710. return table, nil
  711. }
  712. // buildTabBar builds a gui object of type: TabBare
  713. func buildTabBar(b *Builder, am map[string]interface{}) (IPanel, error) {
  714. // Creates TabBar and set common attributes
  715. tabbar := NewTabBar(0, 0)
  716. err := b.setAttribs(am, tabbar, asPANEL)
  717. if err != nil {
  718. return nil, err
  719. }
  720. v := am[AttribItems]
  721. // For each tab
  722. if v != nil {
  723. items := v.([]map[string]interface{})
  724. for _, item := range items {
  725. // Creates Tab
  726. text := ""
  727. if v := item[AttribText]; v != nil {
  728. text = v.(string)
  729. }
  730. tab := tabbar.AddTab(text)
  731. // Sets optional icon
  732. if v := item[AttribIcon]; v != nil {
  733. tab.SetIcon(v.(string))
  734. }
  735. // Sets optional image
  736. if v := item[AttribImageFile]; v != nil {
  737. // If path is not absolute join with user supplied image base path
  738. imagefile := v.(string)
  739. if !filepath.IsAbs(imagefile) {
  740. imagefile = filepath.Join(b.imgpath, imagefile)
  741. }
  742. err := tab.SetImage(imagefile)
  743. if err != nil {
  744. return nil, err
  745. }
  746. }
  747. // Sets content panel
  748. if v := item[AttribContent]; v != nil {
  749. am := v.(map[string]interface{})
  750. content, err := b.build(am, nil)
  751. if err != nil {
  752. return nil, err
  753. }
  754. tab.SetContent(content)
  755. }
  756. // Sets pinned state
  757. if v := item[AttribPinned]; v != nil {
  758. tab.SetPinned(v.(bool))
  759. }
  760. }
  761. }
  762. return tabbar, nil
  763. }