|
|
@@ -1,13 +1,13 @@
|
|
|
// Copyright 2016 The G3N Authors. All rights reserved.
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
// license that can be found in the LICENSE file.
|
|
|
+
|
|
|
package gui
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
"io/ioutil"
|
|
|
"os"
|
|
|
- "path/filepath"
|
|
|
"sort"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
@@ -21,10 +21,10 @@ import (
|
|
|
// Builder builds GUI objects from a declarative description in YAML format
|
|
|
type Builder struct {
|
|
|
am map[string]interface{} // parsed map with gui object atttributes
|
|
|
- imgpath string // base path for image panels files
|
|
|
builders map[string]BuilderFunc // map of builder functions by type
|
|
|
attribs map[string]AttribCheckFunc // map of attribute name with check functions
|
|
|
layouts map[string]IBuilderLayout // map of layout type to layout builder
|
|
|
+ imgpath string // base path for image panels files
|
|
|
}
|
|
|
|
|
|
// IBuilderLayout is the interface for all layout builders
|
|
|
@@ -36,6 +36,9 @@ type IBuilderLayout interface {
|
|
|
// BuilderFunc is type for functions which build a gui object from an attribute map
|
|
|
type BuilderFunc func(*Builder, map[string]interface{}) (IPanel, error)
|
|
|
|
|
|
+// IgnoreSuffix specified the suffix of ignored keys
|
|
|
+const IgnoreSuffix = "_"
|
|
|
+
|
|
|
// Panel and layout types
|
|
|
const (
|
|
|
TypePanel = "panel"
|
|
|
@@ -171,6 +174,7 @@ var mapResizable = map[string]Resizable{
|
|
|
"all": ResizeAll,
|
|
|
}
|
|
|
|
|
|
+// AttribCheckFunc is the type for all attribute check functions
|
|
|
type AttribCheckFunc func(b *Builder, am map[string]interface{}, fname string) error
|
|
|
|
|
|
// NewBuilder creates and returns a pointer to a new gui Builder object
|
|
|
@@ -284,7 +288,6 @@ func (b *Builder) ParseString(desc string) error {
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
- log.Error("single:%v", single)
|
|
|
|
|
|
// Internal function which converts map[interface{}]interface{} to
|
|
|
// map[string]interface{} recursively and lower case of all map keys.
|
|
|
@@ -315,6 +318,10 @@ func (b *Builder) ParseString(desc string) error {
|
|
|
return nil, fmt.Errorf("Keys must be strings")
|
|
|
}
|
|
|
ks = strings.ToLower(ks)
|
|
|
+ // Ignores keys suffixed by IgnoreSuffix
|
|
|
+ if strings.HasSuffix(ks, IgnoreSuffix) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
// Checks value
|
|
|
vi, err := visitor(v, ms)
|
|
|
if err != nil {
|
|
|
@@ -389,11 +396,13 @@ func (b *Builder) ParseFile(filepath string) error {
|
|
|
func (b *Builder) Names() []string {
|
|
|
|
|
|
var objs []string
|
|
|
+ // Single object
|
|
|
if b.am[AttribType] != nil {
|
|
|
objs = append(objs, "")
|
|
|
return objs
|
|
|
}
|
|
|
- for name, _ := range b.am {
|
|
|
+ // Multiple objects
|
|
|
+ for name := range b.am {
|
|
|
objs = append(objs, name)
|
|
|
}
|
|
|
sort.Strings(objs)
|
|
|
@@ -419,7 +428,7 @@ func (b *Builder) Build(name string) (IPanel, error) {
|
|
|
return b.build(am.(map[string]interface{}), nil)
|
|
|
}
|
|
|
|
|
|
-// Sets the path for image panels relative image files
|
|
|
+// SetImagePath Sets the path for image panels relative image files
|
|
|
func (b *Builder) SetImagepath(path string) {
|
|
|
|
|
|
b.imgpath = path
|
|
|
@@ -460,620 +469,77 @@ func (b *Builder) build(am map[string]interface{}, iparent IPanel) (IPanel, erro
|
|
|
return pan, nil
|
|
|
}
|
|
|
|
|
|
-// buildPanel builds an object of type Panel
|
|
|
-func buildPanel(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- pan := NewPanel(0, 0)
|
|
|
- err := b.setAttribs(am, pan, asPANEL)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Builds children recursively
|
|
|
- if am[AttribItems] != nil {
|
|
|
- items := am[AttribItems].([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- item := items[i]
|
|
|
- child, err := b.build(item, pan)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- pan.Add(child)
|
|
|
- }
|
|
|
- }
|
|
|
- return pan, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildImagePanel builds a gui object of type ImagePanel
|
|
|
-func buildImagePanel(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Checks imagefile attribute
|
|
|
- if am[AttribImageFile] == nil {
|
|
|
- return nil, b.err(am, AttribImageFile, "Must be supplied")
|
|
|
- }
|
|
|
-
|
|
|
- // If path is not absolute join with user supplied image base path
|
|
|
- imagefile := am[AttribImageFile].(string)
|
|
|
- if !filepath.IsAbs(imagefile) {
|
|
|
- imagefile = filepath.Join(b.imgpath, imagefile)
|
|
|
- }
|
|
|
-
|
|
|
- // Builds panel and set common attributes
|
|
|
- panel, err := NewImage(imagefile)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- err = b.setAttribs(am, panel, asPANEL)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional AspectWidth attribute
|
|
|
- if aw := am[AttribAspectWidth]; aw != nil {
|
|
|
- panel.SetContentAspectWidth(aw.(float32))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional AspectHeight attribute
|
|
|
- if ah := am[AttribAspectHeight]; ah != nil {
|
|
|
- panel.SetContentAspectHeight(ah.(float32))
|
|
|
- }
|
|
|
-
|
|
|
- // Builds children recursively
|
|
|
- if am[AttribItems] != nil {
|
|
|
- items := am[AttribItems].([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- item := items[i]
|
|
|
- child, err := b.build(item, panel)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- panel.Add(child)
|
|
|
- }
|
|
|
- }
|
|
|
- return panel, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildLabel builds a gui object of type Label
|
|
|
-func buildLabel(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- var label *Label
|
|
|
- if am[AttribIcon] != nil {
|
|
|
- label = NewLabel(am[AttribIcon].(string), true)
|
|
|
- } else if am[AttribText] != nil {
|
|
|
- label = NewLabel(am[AttribText].(string))
|
|
|
- } else {
|
|
|
- label = NewLabel("")
|
|
|
- }
|
|
|
-
|
|
|
- // Sets common attributes
|
|
|
- err := b.setAttribs(am, label, asPANEL)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional background color
|
|
|
- if bgc := am[AttribBgColor]; bgc != nil {
|
|
|
- label.SetBgColor4(bgc.(*math32.Color4))
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional font color
|
|
|
- if fc := am[AttribFontColor]; fc != nil {
|
|
|
- label.SetColor4(fc.(*math32.Color4))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional font size
|
|
|
- if fs := am[AttribFontSize]; fs != nil {
|
|
|
- label.SetFontSize(float64(fs.(float32)))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional font dpi
|
|
|
- if fdpi := am[AttribFontDPI]; fdpi != nil {
|
|
|
- label.SetFontDPI(float64(fdpi.(float32)))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional line spacing
|
|
|
- if ls := am[AttribLineSpacing]; ls != nil {
|
|
|
- label.SetLineSpacing(float64(ls.(float32)))
|
|
|
- }
|
|
|
-
|
|
|
- return label, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildImageLabel builds a gui object of type: ImageLabel
|
|
|
-func buildImageLabel(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds image label and set common attributes
|
|
|
- var text string
|
|
|
- if am[AttribText] != nil {
|
|
|
- text = am[AttribText].(string)
|
|
|
- }
|
|
|
- imglabel := NewImageLabel(text)
|
|
|
- err := b.setAttribs(am, imglabel, asPANEL)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional icon(s)
|
|
|
- if icon := am[AttribIcon]; icon != nil {
|
|
|
- imglabel.SetIcon(icon.(string))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional image from file
|
|
|
- // If path is not absolute join with user supplied image base path
|
|
|
- if imgf := am[AttribImageFile]; imgf != nil {
|
|
|
- path := imgf.(string)
|
|
|
- if !filepath.IsAbs(path) {
|
|
|
- path = filepath.Join(b.imgpath, path)
|
|
|
- }
|
|
|
- err := imglabel.SetImageFromFile(path)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return imglabel, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildButton builds a gui object of type: Button
|
|
|
-func buildButton(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds button and set commont attributes
|
|
|
- var text string
|
|
|
- if am[AttribText] != nil {
|
|
|
- text = am[AttribText].(string)
|
|
|
- }
|
|
|
- button := NewButton(text)
|
|
|
- err := b.setAttribs(am, button, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional icon(s)
|
|
|
- if icon := am[AttribIcon]; icon != nil {
|
|
|
- button.SetIcon(icon.(string))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional image from file
|
|
|
- // If path is not absolute join with user supplied image base path
|
|
|
- if imgf := am[AttribImageFile]; imgf != nil {
|
|
|
- path := imgf.(string)
|
|
|
- if !filepath.IsAbs(path) {
|
|
|
- path = filepath.Join(b.imgpath, path)
|
|
|
- }
|
|
|
- err := button.SetImage(path)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return button, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildEdit builds a gui object of type: "Edit"
|
|
|
-func buildEdit(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds button and set attributes
|
|
|
- var width float32
|
|
|
- var placeholder string
|
|
|
- if aw := am[AttribWidth]; aw != nil {
|
|
|
- width = aw.(float32)
|
|
|
- }
|
|
|
- if ph := am[AttribPlaceHolder]; ph != nil {
|
|
|
- placeholder = ph.(string)
|
|
|
- }
|
|
|
- edit := NewEdit(int(width), placeholder)
|
|
|
- err := b.setAttribs(am, edit, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return edit, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildCheckBox builds a gui object of type: CheckBox
|
|
|
-func buildCheckBox(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds check box and set commont attributes
|
|
|
- var text string
|
|
|
- if am[AttribText] != nil {
|
|
|
- text = am[AttribText].(string)
|
|
|
- }
|
|
|
- cb := NewCheckBox(text)
|
|
|
- err := b.setAttribs(am, cb, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional checked value
|
|
|
- if checked := am[AttribChecked]; checked != nil {
|
|
|
- cb.SetValue(checked.(bool))
|
|
|
- }
|
|
|
- return cb, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildRadioButton builds a gui object of type: RadioButton
|
|
|
-func buildRadioButton(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds check box and set commont attributes
|
|
|
- var text string
|
|
|
- if am[AttribText] != nil {
|
|
|
- text = am[AttribText].(string)
|
|
|
- }
|
|
|
- rb := NewRadioButton(text)
|
|
|
- err := b.setAttribs(am, rb, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional radio button group
|
|
|
- if gr := am[AttribGroup]; gr != nil {
|
|
|
- rb.SetGroup(gr.(string))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional checked value
|
|
|
- if checked := am[AttribChecked]; checked != nil {
|
|
|
- rb.SetValue(checked.(bool))
|
|
|
- }
|
|
|
- return rb, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildVList builds a gui object of type: VList
|
|
|
-func buildVList(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds list and set commont attributes
|
|
|
- list := NewVList(0, 0)
|
|
|
- err := b.setAttribs(am, list, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Builds children
|
|
|
- if am[AttribItems] != nil {
|
|
|
- items := am[AttribItems].([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- item := items[i]
|
|
|
- child, err := b.build(item, list)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- list.Add(child)
|
|
|
- }
|
|
|
- }
|
|
|
- return list, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildHList builds a gui object of type: VList
|
|
|
-func buildHList(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds list and set commont attributes
|
|
|
- list := NewHList(0, 0)
|
|
|
- err := b.setAttribs(am, list, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Builds children
|
|
|
- if am[AttribItems] != nil {
|
|
|
- items := am[AttribItems].([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- item := items[i]
|
|
|
- child, err := b.build(item, list)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- list.Add(child)
|
|
|
- }
|
|
|
- }
|
|
|
- return list, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildDropDown builds a gui object of type: DropDown
|
|
|
-func buildDropDown(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // If image label attribute defined use it, otherwise
|
|
|
- // uses default value.
|
|
|
- var imglabel *ImageLabel
|
|
|
- if iv := am[AttribImageLabel]; iv != nil {
|
|
|
- imgl := iv.(map[string]interface{})
|
|
|
- imgl[AttribType] = TypeImageLabel
|
|
|
- ipan, err := b.build(imgl, nil)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- imglabel = ipan.(*ImageLabel)
|
|
|
- } else {
|
|
|
- imglabel = NewImageLabel("")
|
|
|
- }
|
|
|
-
|
|
|
- // Builds drop down and set common attributes
|
|
|
- dd := NewDropDown(0, imglabel)
|
|
|
- err := b.setAttribs(am, dd, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Builds children
|
|
|
- if am[AttribItems] != nil {
|
|
|
- items := am[AttribItems].([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- item := items[i]
|
|
|
- child, err := b.build(item, dd)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- dd.Add(child.(*ImageLabel))
|
|
|
- }
|
|
|
- }
|
|
|
- return dd, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildMenu builds a gui object of type: Menu or MenuBar from the
|
|
|
-// specified panel descriptor.
|
|
|
-func buildMenu(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
+// setAttribs sets common attributes from the description to the specified panel
|
|
|
+// The attributes which are set can be specified by the specified bitmask.
|
|
|
+func (b *Builder) setAttribs(am map[string]interface{}, ipan IPanel, attr uint) error {
|
|
|
|
|
|
- // Builds menu bar or menu
|
|
|
- var menu *Menu
|
|
|
- if am[AttribType].(string) == TypeMenuBar {
|
|
|
- menu = NewMenuBar()
|
|
|
- } else {
|
|
|
- menu = NewMenu()
|
|
|
+ panel := ipan.GetPanel()
|
|
|
+ // Set optional position
|
|
|
+ if attr&aPOS != 0 && am[AttribPosition] != nil {
|
|
|
+ va := am[AttribPosition].([]float32)
|
|
|
+ panel.SetPosition(va[0], va[1])
|
|
|
}
|
|
|
|
|
|
- // Only sets attribs for top level menus
|
|
|
- if pi := am[AttribParent_]; pi != nil {
|
|
|
- par := pi.(map[string]interface{})
|
|
|
- ptype := ""
|
|
|
- if ti := par[AttribType]; ti != nil {
|
|
|
- ptype = ti.(string)
|
|
|
- }
|
|
|
- if ptype != TypeMenu && ptype != TypeMenuBar {
|
|
|
- err := b.setAttribs(am, menu, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
+ // Set optional panel width
|
|
|
+ if attr&aSIZE != 0 && am[AttribWidth] != nil {
|
|
|
+ panel.SetWidth(am[AttribWidth].(float32))
|
|
|
+ log.Error("set width:%v", am[AttribWidth])
|
|
|
}
|
|
|
|
|
|
- // Builds and adds menu items
|
|
|
- if am[AttribItems] != nil {
|
|
|
- items := am[AttribItems].([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- // Get the item optional type and text
|
|
|
- item := items[i]
|
|
|
- itype := ""
|
|
|
- itext := ""
|
|
|
- if iv := item[AttribType]; iv != nil {
|
|
|
- itype = iv.(string)
|
|
|
- }
|
|
|
- if iv := item[AttribText]; iv != nil {
|
|
|
- itext = iv.(string)
|
|
|
- }
|
|
|
- // Item is another menu
|
|
|
- if itype == TypeMenu {
|
|
|
- subm, err := buildMenu(b, item)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- menu.AddMenu(itext, subm.(*Menu))
|
|
|
- continue
|
|
|
- }
|
|
|
- // Item is a separator
|
|
|
- if itext == TypeSeparator {
|
|
|
- menu.AddSeparator()
|
|
|
- continue
|
|
|
- }
|
|
|
- // Item must be a menu option
|
|
|
- mi := menu.AddOption(itext)
|
|
|
- // Set item optional icon(s)
|
|
|
- if icon := item[AttribIcon]; icon != nil {
|
|
|
- mi.SetIcon(icon.(string))
|
|
|
- }
|
|
|
- // Sets optional menu item shortcut
|
|
|
- if sci := item[AttribShortcut]; sci != nil {
|
|
|
- sc := sci.([]int)
|
|
|
- mi.SetShortcut(window.ModifierKey(sc[0]), window.Key(sc[1]))
|
|
|
- }
|
|
|
- }
|
|
|
+ // Sets optional panel height
|
|
|
+ if attr&aSIZE != 0 && am[AttribHeight] != nil {
|
|
|
+ panel.SetHeight(am[AttribHeight].(float32))
|
|
|
}
|
|
|
- return menu, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildSlider builds a gui object of type: HSlider or VSlider
|
|
|
-func buildSlider(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
|
|
|
- // Builds horizontal or vertical slider
|
|
|
- var slider *Slider
|
|
|
- if am[AttribType].(string) == TypeHSlider {
|
|
|
- slider = NewHSlider(0, 0)
|
|
|
- } else {
|
|
|
- slider = NewVSlider(0, 0)
|
|
|
+ // Set optional margin sizes
|
|
|
+ if attr&aMARGINS != 0 && am[AttribMargins] != nil {
|
|
|
+ panel.SetMarginsFrom(am[AttribMargins].(*BorderSizes))
|
|
|
}
|
|
|
|
|
|
- // Sets common attributes
|
|
|
- err := b.setAttribs(am, slider, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
+ // Set optional border sizes
|
|
|
+ if attr&aBORDERS != 0 && am[AttribBorders] != nil {
|
|
|
+ panel.SetBordersFrom(am[AttribBorders].(*BorderSizes))
|
|
|
}
|
|
|
|
|
|
- // Sets optional text
|
|
|
- if itext := am[AttribText]; itext != nil {
|
|
|
- slider.SetText(itext.(string))
|
|
|
- }
|
|
|
- // Sets optional scale factor
|
|
|
- if isf := am[AttribScaleFactor]; isf != nil {
|
|
|
- slider.SetScaleFactor(isf.(float32))
|
|
|
- }
|
|
|
- // Sets optional value
|
|
|
- if iv := am[AttribValue]; iv != nil {
|
|
|
- slider.SetValue(iv.(float32))
|
|
|
+ // Set optional border color
|
|
|
+ if attr&aBORDERCOLOR != 0 && am[AttribBorderColor] != nil {
|
|
|
+ panel.SetBordersColor4(am[AttribBorderColor].(*math32.Color4))
|
|
|
}
|
|
|
- return slider, nil
|
|
|
-}
|
|
|
|
|
|
-// buildSplitter builds a gui object of type: HSplitterr or VSplitter
|
|
|
-func buildSplitter(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds horizontal or vertical splitter
|
|
|
- var splitter *Splitter
|
|
|
- if am[AttribType].(string) == TypeHSplitter {
|
|
|
- splitter = NewHSplitter(0, 0)
|
|
|
- } else {
|
|
|
- splitter = NewVSplitter(0, 0)
|
|
|
+ // Set optional paddings sizes
|
|
|
+ if attr&aPADDINGS != 0 && am[AttribPaddings] != nil {
|
|
|
+ panel.SetPaddingsFrom(am[AttribPaddings].(*BorderSizes))
|
|
|
}
|
|
|
|
|
|
- // Sets common attributes
|
|
|
- err := b.setAttribs(am, splitter, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
+ // Set optional panel color
|
|
|
+ if attr&aCOLOR != 0 && am[AttribColor] != nil {
|
|
|
+ panel.SetColor4(am[AttribColor].(*math32.Color4))
|
|
|
}
|
|
|
|
|
|
- // Sets optional split value
|
|
|
- if v := am[AttribSplit]; v != nil {
|
|
|
- splitter.SetSplit(v.(float32))
|
|
|
+ if attr&aNAME != 0 && am[AttribName] != nil {
|
|
|
+ panel.SetName(am[AttribName].(string))
|
|
|
}
|
|
|
|
|
|
- // Internal function to set each of the splitter's panel attributes and items
|
|
|
- setpan := func(attrib string, pan *Panel) error {
|
|
|
-
|
|
|
- // Get internal panel attributes
|
|
|
- ipattribs := am[attrib]
|
|
|
- if ipattribs == nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
- pattr := ipattribs.(map[string]interface{})
|
|
|
- // Set panel attributes
|
|
|
- err := b.setAttribs(pattr, pan, asPANEL)
|
|
|
- if err != nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
- // Builds panel children
|
|
|
- if pattr[AttribItems] != nil {
|
|
|
- items := pattr[AttribItems].([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- item := items[i]
|
|
|
- child, err := b.build(item, pan)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- pan.Add(child)
|
|
|
- }
|
|
|
- }
|
|
|
- return nil
|
|
|
+ if attr&aVISIBLE != 0 && am[AttribVisible] != nil {
|
|
|
+ panel.SetVisible(am[AttribVisible].(bool))
|
|
|
}
|
|
|
|
|
|
- // Set optional splitter panel's attributes
|
|
|
- err = setpan(AttribPanel0, &splitter.P0)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
+ if attr&aENABLED != 0 && am[AttribEnabled] != nil {
|
|
|
+ panel.SetEnabled(am[AttribEnabled].(bool))
|
|
|
}
|
|
|
- err = setpan(AttribPanel1, &splitter.P1)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
+ if attr&aRENDER != 0 && am[AttribRender] != nil {
|
|
|
+ panel.SetRenderable(am[AttribRender].(bool))
|
|
|
}
|
|
|
|
|
|
- return splitter, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildTree builds a gui object of type: Tree
|
|
|
-func buildTree(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds tree and sets its common attributes
|
|
|
- tree := NewTree(0, 0)
|
|
|
- err := b.setAttribs(am, tree, asWIDGET)
|
|
|
+ // Sets optional layout (must pass IPanel not *Panel)
|
|
|
+ err := b.setLayout(am, ipan)
|
|
|
if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Internal function to build tree nodes recursively
|
|
|
- var buildItems func(am map[string]interface{}, pnode *TreeNode) error
|
|
|
- buildItems = func(am map[string]interface{}, pnode *TreeNode) error {
|
|
|
-
|
|
|
- v := am[AttribItems]
|
|
|
- if v == nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
- items := v.([]map[string]interface{})
|
|
|
-
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- // Get the item type
|
|
|
- item := items[i]
|
|
|
- itype := ""
|
|
|
- if v := item[AttribType]; v != nil {
|
|
|
- itype = v.(string)
|
|
|
- }
|
|
|
- itext := ""
|
|
|
- if v := item[AttribText]; v != nil {
|
|
|
- itext = v.(string)
|
|
|
- }
|
|
|
-
|
|
|
- // Item is a tree node
|
|
|
- if itype == "" || itype == TypeTreeNode {
|
|
|
- var node *TreeNode
|
|
|
- if pnode == nil {
|
|
|
- node = tree.AddNode(itext)
|
|
|
- } else {
|
|
|
- node = pnode.AddNode(itext)
|
|
|
- }
|
|
|
- err := buildItems(item, node)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- continue
|
|
|
- }
|
|
|
- // Other controls
|
|
|
- ipan, err := b.build(item, nil)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- if pnode == nil {
|
|
|
- tree.Add(ipan)
|
|
|
- } else {
|
|
|
- pnode.Add(ipan)
|
|
|
- }
|
|
|
- }
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- // Build nodes
|
|
|
- err = buildItems(am, nil)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return tree, nil
|
|
|
-}
|
|
|
-
|
|
|
-// buildWindow builds a gui object of type: Window
|
|
|
-func buildWindow(b *Builder, am map[string]interface{}) (IPanel, error) {
|
|
|
-
|
|
|
- // Builds window and sets its common attributes
|
|
|
- win := NewWindow(0, 0)
|
|
|
- err := b.setAttribs(am, win, asWIDGET)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional title
|
|
|
- if title := am[AttribTitle]; title != nil {
|
|
|
- win.SetTitle(title.(string))
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional resizable borders
|
|
|
- if resiz := am[AttribResizable]; resiz != nil {
|
|
|
- win.SetResizable(resiz.(Resizable))
|
|
|
- }
|
|
|
-
|
|
|
- // Builds window children
|
|
|
- if v := am[AttribItems]; v != nil {
|
|
|
- items := v.([]map[string]interface{})
|
|
|
- for i := 0; i < len(items); i++ {
|
|
|
- item := items[i]
|
|
|
- child, err := b.build(item, win)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- win.Add(child)
|
|
|
- }
|
|
|
- }
|
|
|
- return win, nil
|
|
|
+ // Sets optional layout params
|
|
|
+ err = b.setLayoutParams(am, panel)
|
|
|
+ return err
|
|
|
}
|
|
|
|
|
|
// setLayout sets the optional layout of the specified panel
|
|
|
@@ -1105,6 +571,7 @@ func (b *Builder) setLayout(am map[string]interface{}, ipan IPanel) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// setLayoutParams sets the optional layout params of the specified panel and its attributes
|
|
|
func (b *Builder) setLayoutParams(am map[string]interface{}, ipan IPanel) error {
|
|
|
|
|
|
// Get layout params attributes
|
|
|
@@ -1137,6 +604,7 @@ func (b *Builder) setLayoutParams(am map[string]interface{}, ipan IPanel) error
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckResizable checks and converts attribute with list of window resizable borders
|
|
|
func AttribCheckResizable(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
// If attribute not found, ignore
|
|
|
@@ -1165,6 +633,7 @@ func AttribCheckResizable(b *Builder, am map[string]interface{}, fname string) e
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttributeCheckEdge checks and converts attribute with name of layout edge
|
|
|
func AttribCheckEdge(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1183,6 +652,7 @@ func AttribCheckEdge(b *Builder, am map[string]interface{}, fname string) error
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttributeCheckLayout checks and converts layout attribute
|
|
|
func AttribCheckLayout(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1204,6 +674,7 @@ func AttribCheckLayout(b *Builder, am map[string]interface{}, fname string) erro
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttributeCheckAlignt checks and converts layout align* attribute
|
|
|
func AttribCheckAlign(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1227,6 +698,7 @@ func AttribCheckAlign(b *Builder, am map[string]interface{}, fname string) error
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttributeCheckMenuShortcut checks and converts attribute describing menu shortcut key
|
|
|
func AttribCheckMenuShortcut(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1273,6 +745,7 @@ func AttribCheckMenuShortcut(b *Builder, am map[string]interface{}, fname string
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttributeCheckListMap checks and converts attribute to []map[string]interface{}
|
|
|
func AttribCheckListMap(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1296,6 +769,7 @@ func AttribCheckListMap(b *Builder, am map[string]interface{}, fname string) err
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttributeCheckMap checks and converts attribute to map[string]interface{}
|
|
|
func AttribCheckMap(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1310,6 +784,7 @@ func AttribCheckMap(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckIcons checks and converts attribute with a list of icon names or codepoints
|
|
|
func AttribCheckIcons(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1341,6 +816,7 @@ func AttribCheckIcons(b *Builder, am map[string]interface{}, fname string) error
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckColor checks and converts attribute with color name or color component values
|
|
|
func AttribCheckColor(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
// Checks if field is nil
|
|
|
@@ -1394,6 +870,7 @@ func AttribCheckColor(b *Builder, am map[string]interface{}, fname string) error
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckBorderSizes checks and convert attribute with border sizes
|
|
|
func AttribCheckBorderSizes(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
va, err := b.parseFloats(am, fname, 1, 4)
|
|
|
@@ -1411,6 +888,7 @@ func AttribCheckBorderSizes(b *Builder, am map[string]interface{}, fname string)
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckPosition checks and convert attribute with x and y position
|
|
|
func AttribCheckPosition(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1425,6 +903,7 @@ func AttribCheckPosition(b *Builder, am map[string]interface{}, fname string) er
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckStringLower checks and convert string attribute to lower case
|
|
|
func AttribCheckStringLower(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
err := AttribCheckString(b, am, fname)
|
|
|
@@ -1437,6 +916,7 @@ func AttribCheckStringLower(b *Builder, am map[string]interface{}, fname string)
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckFloat checks and convert attribute to float32
|
|
|
func AttribCheckFloat(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1456,6 +936,7 @@ func AttribCheckFloat(b *Builder, am map[string]interface{}, fname string) error
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckInt checks and convert attribute to int
|
|
|
func AttribCheckInt(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1470,6 +951,7 @@ func AttribCheckInt(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckString checks and convert attribute to string
|
|
|
func AttribCheckString(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1484,6 +966,7 @@ func AttribCheckString(b *Builder, am map[string]interface{}, fname string) erro
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// AttribCheckBool checks and convert attribute to bool
|
|
|
func AttribCheckBool(b *Builder, am map[string]interface{}, fname string) error {
|
|
|
|
|
|
v := am[fname]
|
|
|
@@ -1498,79 +981,6 @@ func AttribCheckBool(b *Builder, am map[string]interface{}, fname string) error
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-// setAttribs sets common attributes from the description to the specified panel
|
|
|
-// The attributes which are set can be specified by the specified bitmask.
|
|
|
-func (b *Builder) setAttribs(am map[string]interface{}, ipan IPanel, attr uint) error {
|
|
|
-
|
|
|
- panel := ipan.GetPanel()
|
|
|
- // Set optional position
|
|
|
- if attr&aPOS != 0 && am[AttribPosition] != nil {
|
|
|
- va := am[AttribPosition].([]float32)
|
|
|
- panel.SetPosition(va[0], va[1])
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional panel width
|
|
|
- if attr&aSIZE != 0 && am[AttribWidth] != nil {
|
|
|
- panel.SetWidth(am[AttribWidth].(float32))
|
|
|
- log.Error("set width:%v", am[AttribWidth])
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional panel height
|
|
|
- if attr&aSIZE != 0 && am[AttribHeight] != nil {
|
|
|
- panel.SetHeight(am[AttribHeight].(float32))
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional margin sizes
|
|
|
- if attr&aMARGINS != 0 && am[AttribMargins] != nil {
|
|
|
- panel.SetMarginsFrom(am[AttribMargins].(*BorderSizes))
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional border sizes
|
|
|
- if attr&aBORDERS != 0 && am[AttribBorders] != nil {
|
|
|
- panel.SetBordersFrom(am[AttribBorders].(*BorderSizes))
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional border color
|
|
|
- if attr&aBORDERCOLOR != 0 && am[AttribBorderColor] != nil {
|
|
|
- panel.SetBordersColor4(am[AttribBorderColor].(*math32.Color4))
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional paddings sizes
|
|
|
- if attr&aPADDINGS != 0 && am[AttribPaddings] != nil {
|
|
|
- panel.SetPaddingsFrom(am[AttribPaddings].(*BorderSizes))
|
|
|
- }
|
|
|
-
|
|
|
- // Set optional panel color
|
|
|
- if attr&aCOLOR != 0 && am[AttribColor] != nil {
|
|
|
- panel.SetColor4(am[AttribColor].(*math32.Color4))
|
|
|
- }
|
|
|
-
|
|
|
- if attr&aNAME != 0 && am[AttribName] != nil {
|
|
|
- panel.SetName(am[AttribName].(string))
|
|
|
- }
|
|
|
-
|
|
|
- if attr&aVISIBLE != 0 && am[AttribVisible] != nil {
|
|
|
- panel.SetVisible(am[AttribVisible].(bool))
|
|
|
- }
|
|
|
-
|
|
|
- if attr&aENABLED != 0 && am[AttribEnabled] != nil {
|
|
|
- panel.SetEnabled(am[AttribEnabled].(bool))
|
|
|
- }
|
|
|
- if attr&aRENDER != 0 && am[AttribRender] != nil {
|
|
|
- panel.SetRenderable(am[AttribRender].(bool))
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional layout (must pass IPanel not *Panel)
|
|
|
- err := b.setLayout(am, ipan)
|
|
|
- if err != nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
-
|
|
|
- // Sets optional layout params
|
|
|
- err = b.setLayoutParams(am, panel)
|
|
|
- return err
|
|
|
-}
|
|
|
-
|
|
|
// parseFloats parses a string with a list of floats with the specified size
|
|
|
// and returns a slice. The specified size is 0 any number of floats is allowed.
|
|
|
// The individual values can be separated by spaces or commas
|