소스 검색

Merged branch 'guibuilder' (API changes made)

gui.Builder implements a builder for gui objects.
Attention: API changes were made for developing gui.Builder.
leonsal 8 년 전
부모
커밋
c5befbe4ee

+ 39 - 0
core/node.go

@@ -5,6 +5,8 @@
 package core
 
 import (
+	"strings"
+
 	"github.com/g3n/engine/gls"
 	"github.com/g3n/engine/math32"
 )
@@ -93,6 +95,43 @@ func (n *Node) LoaderID() string {
 	return n.loaderID
 }
 
+// FindPath finds a node with the specified path starting with this node and
+// searching in all its children recursively.
+// A path is the sequence of the names from the first node to the desired node
+// separated by the forward slash.
+func (n *Node) FindPath(path string) INode {
+
+	// Internal recursive function to find node
+	var finder func(inode INode, path string) INode
+	finder = func(inode INode, path string) INode {
+		// Get first component of the path
+		parts := strings.Split(path, "/")
+		if len(parts) == 0 {
+			return nil
+		}
+		first := parts[0]
+		// Checks current node
+		node := inode.GetNode()
+		if node.name != first {
+			return nil
+		}
+		// If the path has finished this is the desired node
+		rest := strings.Join(parts[1:], "/")
+		if rest == "" {
+			return inode
+		}
+		// Otherwise search in this node children
+		for _, ichild := range node.children {
+			found := finder(ichild, rest)
+			if found != nil {
+				return found
+			}
+		}
+		return nil
+	}
+	return finder(n, path)
+}
+
 // FindLoaderID looks in the specified node and all its children
 // for a node with the specifid loaderID and if found returns it.
 // Returns nil if not found

+ 1 - 1
graphic/skybox.go

@@ -39,7 +39,7 @@ func NewSkybox(data SkyboxData) (*Skybox, error) {
 		if err != nil {
 			return nil, err
 		}
-		matFace := material.NewStandard(math32.NewColor(1, 1, 1))
+		matFace := material.NewStandard(math32.NewColor("white"))
 		matFace.AddTexture(tex)
 		matFace.SetSide(material.SideBack)
 		matFace.SetUseLights(material.UseLightAmbient)

+ 1 - 0
gui/align.go

@@ -4,6 +4,7 @@
 
 package gui
 
+// Align specifies the alignment of an object inside another
 type Align int
 
 const (

+ 4 - 4
gui/assets/data.go

@@ -86,7 +86,7 @@ func fontsFreemonoTtf() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "fonts/FreeMono.ttf", size: 592632, mode: os.FileMode(420), modTime: time.Unix(1499641912, 0)}
+	info := bindataFileInfo{name: "fonts/FreeMono.ttf", size: 592632, mode: os.FileMode(436), modTime: time.Unix(1512153466, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -106,7 +106,7 @@ func fontsFreesansTtf() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "fonts/FreeSans.ttf", size: 1563256, mode: os.FileMode(420), modTime: time.Unix(1499641912, 0)}
+	info := bindataFileInfo{name: "fonts/FreeSans.ttf", size: 1563256, mode: os.FileMode(436), modTime: time.Unix(1512153466, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -126,7 +126,7 @@ func fontsFreesansboldTtf() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "fonts/FreeSansBold.ttf", size: 416128, mode: os.FileMode(420), modTime: time.Unix(1499641912, 0)}
+	info := bindataFileInfo{name: "fonts/FreeSansBold.ttf", size: 416128, mode: os.FileMode(436), modTime: time.Unix(1512153466, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }
@@ -146,7 +146,7 @@ func fontsMaterialiconsRegularTtf() (*asset, error) {
 		return nil, err
 	}
 
-	info := bindataFileInfo{name: "fonts/MaterialIcons-Regular.ttf", size: 128180, mode: os.FileMode(420), modTime: time.Unix(1499642283, 0)}
+	info := bindataFileInfo{name: "fonts/MaterialIcons-Regular.ttf", size: 128180, mode: os.FileMode(436), modTime: time.Unix(1512153466, 0)}
 	a := &asset{bytes: bytes, info: info}
 	return a, nil
 }

+ 1 - 1
gui/assets/gen.go

@@ -5,4 +5,4 @@ package assets
 // >go get -u github.com/jteeuwen/go-bindata/...
 
 //go:generate go-bindata -o data.go -pkg assets fonts
-//go:generate genicodes  genicodes/codepoints icodes.go
+//go:generate g3nicodes -pkg icon icon/codepoints icon/icodes.go

+ 0 - 941
gui/assets/icodes.go

@@ -1,941 +0,0 @@
-//
-// This file was generated from the original 'codepoints' file
-// from the material design icon fonts:
-// https://github.com/google/material-design-icons
-//
-package assets
-
-const (
-	N3dRotation                           = 0xe84d
-	AcUnit                                = 0xeb3b
-	AccessAlarm                           = 0xe190
-	AccessAlarms                          = 0xe191
-	AccessTime                            = 0xe192
-	Accessibility                         = 0xe84e
-	Accessible                            = 0xe914
-	AccountBalance                        = 0xe84f
-	AccountBalanceWallet                  = 0xe850
-	AccountBox                            = 0xe851
-	AccountCircle                         = 0xe853
-	Adb                                   = 0xe60e
-	Add                                   = 0xe145
-	AddAPhoto                             = 0xe439
-	AddAlarm                              = 0xe193
-	AddAlert                              = 0xe003
-	AddBox                                = 0xe146
-	AddCircle                             = 0xe147
-	AddCircleOutline                      = 0xe148
-	AddLocation                           = 0xe567
-	AddShoppingCart                       = 0xe854
-	AddToPhotos                           = 0xe39d
-	AddToQueue                            = 0xe05c
-	Adjust                                = 0xe39e
-	AirlineSeatFlat                       = 0xe630
-	AirlineSeatFlatAngled                 = 0xe631
-	AirlineSeatIndividualSuite            = 0xe632
-	AirlineSeatLegroomExtra               = 0xe633
-	AirlineSeatLegroomNormal              = 0xe634
-	AirlineSeatLegroomReduced             = 0xe635
-	AirlineSeatReclineExtra               = 0xe636
-	AirlineSeatReclineNormal              = 0xe637
-	AirplanemodeActive                    = 0xe195
-	AirplanemodeInactive                  = 0xe194
-	Airplay                               = 0xe055
-	AirportShuttle                        = 0xeb3c
-	Alarm                                 = 0xe855
-	AlarmAdd                              = 0xe856
-	AlarmOff                              = 0xe857
-	AlarmOn                               = 0xe858
-	Album                                 = 0xe019
-	AllInclusive                          = 0xeb3d
-	AllOut                                = 0xe90b
-	Android                               = 0xe859
-	Announcement                          = 0xe85a
-	Apps                                  = 0xe5c3
-	Archive                               = 0xe149
-	ArrowBack                             = 0xe5c4
-	ArrowDownward                         = 0xe5db
-	ArrowDropDown                         = 0xe5c5
-	ArrowDropDownCircle                   = 0xe5c6
-	ArrowDropUp                           = 0xe5c7
-	ArrowForward                          = 0xe5c8
-	ArrowUpward                           = 0xe5d8
-	ArtTrack                              = 0xe060
-	AspectRatio                           = 0xe85b
-	Assessment                            = 0xe85c
-	Assignment                            = 0xe85d
-	AssignmentInd                         = 0xe85e
-	AssignmentLate                        = 0xe85f
-	AssignmentReturn                      = 0xe860
-	AssignmentReturned                    = 0xe861
-	AssignmentTurnedIn                    = 0xe862
-	Assistant                             = 0xe39f
-	AssistantPhoto                        = 0xe3a0
-	AttachFile                            = 0xe226
-	AttachMoney                           = 0xe227
-	Attachment                            = 0xe2bc
-	Audiotrack                            = 0xe3a1
-	Autorenew                             = 0xe863
-	AvTimer                               = 0xe01b
-	Backspace                             = 0xe14a
-	Backup                                = 0xe864
-	BatteryAlert                          = 0xe19c
-	BatteryChargingFull                   = 0xe1a3
-	BatteryFull                           = 0xe1a4
-	BatteryStd                            = 0xe1a5
-	BatteryUnknown                        = 0xe1a6
-	BeachAccess                           = 0xeb3e
-	Beenhere                              = 0xe52d
-	Block                                 = 0xe14b
-	Bluetooth                             = 0xe1a7
-	BluetoothAudio                        = 0xe60f
-	BluetoothConnected                    = 0xe1a8
-	BluetoothDisabled                     = 0xe1a9
-	BluetoothSearching                    = 0xe1aa
-	BlurCircular                          = 0xe3a2
-	BlurLinear                            = 0xe3a3
-	BlurOff                               = 0xe3a4
-	BlurOn                                = 0xe3a5
-	Book                                  = 0xe865
-	Bookmark                              = 0xe866
-	BookmarkBorder                        = 0xe867
-	BorderAll                             = 0xe228
-	BorderBottom                          = 0xe229
-	BorderClear                           = 0xe22a
-	BorderColor                           = 0xe22b
-	BorderHorizontal                      = 0xe22c
-	BorderInner                           = 0xe22d
-	BorderLeft                            = 0xe22e
-	BorderOuter                           = 0xe22f
-	BorderRight                           = 0xe230
-	BorderStyle                           = 0xe231
-	BorderTop                             = 0xe232
-	BorderVertical                        = 0xe233
-	BrandingWatermark                     = 0xe06b
-	Brightness1                           = 0xe3a6
-	Brightness2                           = 0xe3a7
-	Brightness3                           = 0xe3a8
-	Brightness4                           = 0xe3a9
-	Brightness5                           = 0xe3aa
-	Brightness6                           = 0xe3ab
-	Brightness7                           = 0xe3ac
-	BrightnessAuto                        = 0xe1ab
-	BrightnessHigh                        = 0xe1ac
-	BrightnessLow                         = 0xe1ad
-	BrightnessMedium                      = 0xe1ae
-	BrokenImage                           = 0xe3ad
-	Brush                                 = 0xe3ae
-	BubbleChart                           = 0xe6dd
-	BugReport                             = 0xe868
-	Build                                 = 0xe869
-	BurstMode                             = 0xe43c
-	Business                              = 0xe0af
-	BusinessCenter                        = 0xeb3f
-	Cached                                = 0xe86a
-	Cake                                  = 0xe7e9
-	Call                                  = 0xe0b0
-	CallEnd                               = 0xe0b1
-	CallMade                              = 0xe0b2
-	CallMerge                             = 0xe0b3
-	CallMissed                            = 0xe0b4
-	CallMissedOutgoing                    = 0xe0e4
-	CallReceived                          = 0xe0b5
-	CallSplit                             = 0xe0b6
-	CallToAction                          = 0xe06c
-	Camera                                = 0xe3af
-	CameraAlt                             = 0xe3b0
-	CameraEnhance                         = 0xe8fc
-	CameraFront                           = 0xe3b1
-	CameraRear                            = 0xe3b2
-	CameraRoll                            = 0xe3b3
-	Cancel                                = 0xe5c9
-	CardGiftcard                          = 0xe8f6
-	CardMembership                        = 0xe8f7
-	CardTravel                            = 0xe8f8
-	Casino                                = 0xeb40
-	Cast                                  = 0xe307
-	CastConnected                         = 0xe308
-	CenterFocusStrong                     = 0xe3b4
-	CenterFocusWeak                       = 0xe3b5
-	ChangeHistory                         = 0xe86b
-	Chat                                  = 0xe0b7
-	ChatBubble                            = 0xe0ca
-	ChatBubbleOutline                     = 0xe0cb
-	Check                                 = 0xe5ca
-	CheckBox                              = 0xe834
-	CheckBoxOutlineBlank                  = 0xe835
-	CheckCircle                           = 0xe86c
-	ChevronLeft                           = 0xe5cb
-	ChevronRight                          = 0xe5cc
-	ChildCare                             = 0xeb41
-	ChildFriendly                         = 0xeb42
-	ChromeReaderMode                      = 0xe86d
-	Class                                 = 0xe86e
-	Clear                                 = 0xe14c
-	ClearAll                              = 0xe0b8
-	Close                                 = 0xe5cd
-	ClosedCaption                         = 0xe01c
-	Cloud                                 = 0xe2bd
-	CloudCircle                           = 0xe2be
-	CloudDone                             = 0xe2bf
-	CloudDownload                         = 0xe2c0
-	CloudOff                              = 0xe2c1
-	CloudQueue                            = 0xe2c2
-	CloudUpload                           = 0xe2c3
-	Code                                  = 0xe86f
-	Collections                           = 0xe3b6
-	CollectionsBookmark                   = 0xe431
-	ColorLens                             = 0xe3b7
-	Colorize                              = 0xe3b8
-	Comment                               = 0xe0b9
-	Compare                               = 0xe3b9
-	CompareArrows                         = 0xe915
-	Computer                              = 0xe30a
-	ConfirmationNumber                    = 0xe638
-	ContactMail                           = 0xe0d0
-	ContactPhone                          = 0xe0cf
-	Contacts                              = 0xe0ba
-	ContentCopy                           = 0xe14d
-	ContentCut                            = 0xe14e
-	ContentPaste                          = 0xe14f
-	ControlPoint                          = 0xe3ba
-	ControlPointDuplicate                 = 0xe3bb
-	Copyright                             = 0xe90c
-	Create                                = 0xe150
-	CreateNewFolder                       = 0xe2cc
-	CreditCard                            = 0xe870
-	Crop                                  = 0xe3be
-	Crop169                               = 0xe3bc
-	Crop32                                = 0xe3bd
-	Crop54                                = 0xe3bf
-	Crop75                                = 0xe3c0
-	CropDin                               = 0xe3c1
-	CropFree                              = 0xe3c2
-	CropLandscape                         = 0xe3c3
-	CropOriginal                          = 0xe3c4
-	CropPortrait                          = 0xe3c5
-	CropRotate                            = 0xe437
-	CropSquare                            = 0xe3c6
-	Dashboard                             = 0xe871
-	DataUsage                             = 0xe1af
-	DateRange                             = 0xe916
-	Dehaze                                = 0xe3c7
-	Delete                                = 0xe872
-	DeleteForever                         = 0xe92b
-	DeleteSweep                           = 0xe16c
-	Description                           = 0xe873
-	DesktopMac                            = 0xe30b
-	DesktopWindows                        = 0xe30c
-	Details                               = 0xe3c8
-	DeveloperBoard                        = 0xe30d
-	DeveloperMode                         = 0xe1b0
-	DeviceHub                             = 0xe335
-	Devices                               = 0xe1b1
-	DevicesOther                          = 0xe337
-	DialerSip                             = 0xe0bb
-	Dialpad                               = 0xe0bc
-	Directions                            = 0xe52e
-	DirectionsBike                        = 0xe52f
-	DirectionsBoat                        = 0xe532
-	DirectionsBus                         = 0xe530
-	DirectionsCar                         = 0xe531
-	DirectionsRailway                     = 0xe534
-	DirectionsRun                         = 0xe566
-	DirectionsSubway                      = 0xe533
-	DirectionsTransit                     = 0xe535
-	DirectionsWalk                        = 0xe536
-	DiscFull                              = 0xe610
-	Dns                                   = 0xe875
-	DoNotDisturb                          = 0xe612
-	DoNotDisturbAlt                       = 0xe611
-	DoNotDisturbOff                       = 0xe643
-	DoNotDisturbOn                        = 0xe644
-	Dock                                  = 0xe30e
-	Domain                                = 0xe7ee
-	Done                                  = 0xe876
-	DoneAll                               = 0xe877
-	DonutLarge                            = 0xe917
-	DonutSmall                            = 0xe918
-	Drafts                                = 0xe151
-	DragHandle                            = 0xe25d
-	DriveEta                              = 0xe613
-	Dvr                                   = 0xe1b2
-	Edit                                  = 0xe3c9
-	EditLocation                          = 0xe568
-	Eject                                 = 0xe8fb
-	Email                                 = 0xe0be
-	EnhancedEncryption                    = 0xe63f
-	Equalizer                             = 0xe01d
-	Error                                 = 0xe000
-	ErrorOutline                          = 0xe001
-	EuroSymbol                            = 0xe926
-	EvStation                             = 0xe56d
-	Event                                 = 0xe878
-	EventAvailable                        = 0xe614
-	EventBusy                             = 0xe615
-	EventNote                             = 0xe616
-	EventSeat                             = 0xe903
-	ExitToApp                             = 0xe879
-	ExpandLess                            = 0xe5ce
-	ExpandMore                            = 0xe5cf
-	Explicit                              = 0xe01e
-	Explore                               = 0xe87a
-	Exposure                              = 0xe3ca
-	ExposureNeg1                          = 0xe3cb
-	ExposureNeg2                          = 0xe3cc
-	ExposurePlus1                         = 0xe3cd
-	ExposurePlus2                         = 0xe3ce
-	ExposureZero                          = 0xe3cf
-	Extension                             = 0xe87b
-	Face                                  = 0xe87c
-	FastForward                           = 0xe01f
-	FastRewind                            = 0xe020
-	Favorite                              = 0xe87d
-	FavoriteBorder                        = 0xe87e
-	FeaturedPlayList                      = 0xe06d
-	FeaturedVideo                         = 0xe06e
-	Feedback                              = 0xe87f
-	FiberDvr                              = 0xe05d
-	FiberManualRecord                     = 0xe061
-	FiberNew                              = 0xe05e
-	FiberPin                              = 0xe06a
-	FiberSmartRecord                      = 0xe062
-	FileDownload                          = 0xe2c4
-	FileUpload                            = 0xe2c6
-	Filter                                = 0xe3d3
-	Filter1                               = 0xe3d0
-	Filter2                               = 0xe3d1
-	Filter3                               = 0xe3d2
-	Filter4                               = 0xe3d4
-	Filter5                               = 0xe3d5
-	Filter6                               = 0xe3d6
-	Filter7                               = 0xe3d7
-	Filter8                               = 0xe3d8
-	Filter9                               = 0xe3d9
-	Filter9Plus                           = 0xe3da
-	FilterBAndW                           = 0xe3db
-	FilterCenterFocus                     = 0xe3dc
-	FilterDrama                           = 0xe3dd
-	FilterFrames                          = 0xe3de
-	FilterHdr                             = 0xe3df
-	FilterList                            = 0xe152
-	FilterNone                            = 0xe3e0
-	FilterTiltShift                       = 0xe3e2
-	FilterVintage                         = 0xe3e3
-	FindInPage                            = 0xe880
-	FindReplace                           = 0xe881
-	Fingerprint                           = 0xe90d
-	FirstPage                             = 0xe5dc
-	FitnessCenter                         = 0xeb43
-	Flag                                  = 0xe153
-	Flare                                 = 0xe3e4
-	FlashAuto                             = 0xe3e5
-	FlashOff                              = 0xe3e6
-	FlashOn                               = 0xe3e7
-	Flight                                = 0xe539
-	FlightLand                            = 0xe904
-	FlightTakeoff                         = 0xe905
-	Flip                                  = 0xe3e8
-	FlipToBack                            = 0xe882
-	FlipToFront                           = 0xe883
-	Folder                                = 0xe2c7
-	FolderOpen                            = 0xe2c8
-	FolderShared                          = 0xe2c9
-	FolderSpecial                         = 0xe617
-	FontDownload                          = 0xe167
-	FormatAlignCenter                     = 0xe234
-	FormatAlignJustify                    = 0xe235
-	FormatAlignLeft                       = 0xe236
-	FormatAlignRight                      = 0xe237
-	FormatBold                            = 0xe238
-	FormatClear                           = 0xe239
-	FormatColorFill                       = 0xe23a
-	FormatColorReset                      = 0xe23b
-	FormatColorText                       = 0xe23c
-	FormatIndentDecrease                  = 0xe23d
-	FormatIndentIncrease                  = 0xe23e
-	FormatItalic                          = 0xe23f
-	FormatLineSpacing                     = 0xe240
-	FormatListBulleted                    = 0xe241
-	FormatListNumbered                    = 0xe242
-	FormatPaint                           = 0xe243
-	FormatQuote                           = 0xe244
-	FormatShapes                          = 0xe25e
-	FormatSize                            = 0xe245
-	FormatStrikethrough                   = 0xe246
-	FormatTextdirectionLToR               = 0xe247
-	FormatTextdirectionRToL               = 0xe248
-	FormatUnderlined                      = 0xe249
-	Forum                                 = 0xe0bf
-	Forward                               = 0xe154
-	Forward10                             = 0xe056
-	Forward30                             = 0xe057
-	Forward5                              = 0xe058
-	FreeBreakfast                         = 0xeb44
-	Fullscreen                            = 0xe5d0
-	FullscreenExit                        = 0xe5d1
-	Functions                             = 0xe24a
-	GTranslate                            = 0xe927
-	Gamepad                               = 0xe30f
-	Games                                 = 0xe021
-	Gavel                                 = 0xe90e
-	Gesture                               = 0xe155
-	GetApp                                = 0xe884
-	Gif                                   = 0xe908
-	GolfCourse                            = 0xeb45
-	GpsFixed                              = 0xe1b3
-	GpsNotFixed                           = 0xe1b4
-	GpsOff                                = 0xe1b5
-	Grade                                 = 0xe885
-	Gradient                              = 0xe3e9
-	Grain                                 = 0xe3ea
-	GraphicEq                             = 0xe1b8
-	GridOff                               = 0xe3eb
-	GridOn                                = 0xe3ec
-	Group                                 = 0xe7ef
-	GroupAdd                              = 0xe7f0
-	GroupWork                             = 0xe886
-	Hd                                    = 0xe052
-	HdrOff                                = 0xe3ed
-	HdrOn                                 = 0xe3ee
-	HdrStrong                             = 0xe3f1
-	HdrWeak                               = 0xe3f2
-	Headset                               = 0xe310
-	HeadsetMic                            = 0xe311
-	Healing                               = 0xe3f3
-	Hearing                               = 0xe023
-	Help                                  = 0xe887
-	HelpOutline                           = 0xe8fd
-	HighQuality                           = 0xe024
-	Highlight                             = 0xe25f
-	HighlightOff                          = 0xe888
-	History                               = 0xe889
-	Home                                  = 0xe88a
-	HotTub                                = 0xeb46
-	Hotel                                 = 0xe53a
-	HourglassEmpty                        = 0xe88b
-	HourglassFull                         = 0xe88c
-	Http                                  = 0xe902
-	Https                                 = 0xe88d
-	Image                                 = 0xe3f4
-	ImageAspectRatio                      = 0xe3f5
-	ImportContacts                        = 0xe0e0
-	ImportExport                          = 0xe0c3
-	ImportantDevices                      = 0xe912
-	Inbox                                 = 0xe156
-	IndeterminateCheckBox                 = 0xe909
-	Info                                  = 0xe88e
-	InfoOutline                           = 0xe88f
-	Input                                 = 0xe890
-	InsertChart                           = 0xe24b
-	InsertComment                         = 0xe24c
-	InsertDriveFile                       = 0xe24d
-	InsertEmoticon                        = 0xe24e
-	InsertInvitation                      = 0xe24f
-	InsertLink                            = 0xe250
-	InsertPhoto                           = 0xe251
-	InvertColors                          = 0xe891
-	InvertColorsOff                       = 0xe0c4
-	Iso                                   = 0xe3f6
-	Keyboard                              = 0xe312
-	KeyboardArrowDown                     = 0xe313
-	KeyboardArrowLeft                     = 0xe314
-	KeyboardArrowRight                    = 0xe315
-	KeyboardArrowUp                       = 0xe316
-	KeyboardBackspace                     = 0xe317
-	KeyboardCapslock                      = 0xe318
-	KeyboardHide                          = 0xe31a
-	KeyboardReturn                        = 0xe31b
-	KeyboardTab                           = 0xe31c
-	KeyboardVoice                         = 0xe31d
-	Kitchen                               = 0xeb47
-	Label                                 = 0xe892
-	LabelOutline                          = 0xe893
-	Landscape                             = 0xe3f7
-	Language                              = 0xe894
-	Laptop                                = 0xe31e
-	LaptopChromebook                      = 0xe31f
-	LaptopMac                             = 0xe320
-	LaptopWindows                         = 0xe321
-	LastPage                              = 0xe5dd
-	Launch                                = 0xe895
-	Layers                                = 0xe53b
-	LayersClear                           = 0xe53c
-	LeakAdd                               = 0xe3f8
-	LeakRemove                            = 0xe3f9
-	Lens                                  = 0xe3fa
-	LibraryAdd                            = 0xe02e
-	LibraryBooks                          = 0xe02f
-	LibraryMusic                          = 0xe030
-	LightbulbOutline                      = 0xe90f
-	LineStyle                             = 0xe919
-	LineWeight                            = 0xe91a
-	LinearScale                           = 0xe260
-	Link                                  = 0xe157
-	LinkedCamera                          = 0xe438
-	List                                  = 0xe896
-	LiveHelp                              = 0xe0c6
-	LiveTv                                = 0xe639
-	LocalActivity                         = 0xe53f
-	LocalAirport                          = 0xe53d
-	LocalAtm                              = 0xe53e
-	LocalBar                              = 0xe540
-	LocalCafe                             = 0xe541
-	LocalCarWash                          = 0xe542
-	LocalConvenienceStore                 = 0xe543
-	LocalDining                           = 0xe556
-	LocalDrink                            = 0xe544
-	LocalFlorist                          = 0xe545
-	LocalGasStation                       = 0xe546
-	LocalGroceryStore                     = 0xe547
-	LocalHospital                         = 0xe548
-	LocalHotel                            = 0xe549
-	LocalLaundryService                   = 0xe54a
-	LocalLibrary                          = 0xe54b
-	LocalMall                             = 0xe54c
-	LocalMovies                           = 0xe54d
-	LocalOffer                            = 0xe54e
-	LocalParking                          = 0xe54f
-	LocalPharmacy                         = 0xe550
-	LocalPhone                            = 0xe551
-	LocalPizza                            = 0xe552
-	LocalPlay                             = 0xe553
-	LocalPostOffice                       = 0xe554
-	LocalPrintshop                        = 0xe555
-	LocalSee                              = 0xe557
-	LocalShipping                         = 0xe558
-	LocalTaxi                             = 0xe559
-	LocationCity                          = 0xe7f1
-	LocationDisabled                      = 0xe1b6
-	LocationOff                           = 0xe0c7
-	LocationOn                            = 0xe0c8
-	LocationSearching                     = 0xe1b7
-	Lock                                  = 0xe897
-	LockOpen                              = 0xe898
-	LockOutline                           = 0xe899
-	Looks                                 = 0xe3fc
-	Looks3                                = 0xe3fb
-	Looks4                                = 0xe3fd
-	Looks5                                = 0xe3fe
-	Looks6                                = 0xe3ff
-	LooksOne                              = 0xe400
-	LooksTwo                              = 0xe401
-	Loop                                  = 0xe028
-	Loupe                                 = 0xe402
-	LowPriority                           = 0xe16d
-	Loyalty                               = 0xe89a
-	Mail                                  = 0xe158
-	MailOutline                           = 0xe0e1
-	Map                                   = 0xe55b
-	Markunread                            = 0xe159
-	MarkunreadMailbox                     = 0xe89b
-	Memory                                = 0xe322
-	Menu                                  = 0xe5d2
-	MergeType                             = 0xe252
-	Message                               = 0xe0c9
-	Mic                                   = 0xe029
-	MicNone                               = 0xe02a
-	MicOff                                = 0xe02b
-	Mms                                   = 0xe618
-	ModeComment                           = 0xe253
-	ModeEdit                              = 0xe254
-	MonetizationOn                        = 0xe263
-	MoneyOff                              = 0xe25c
-	MonochromePhotos                      = 0xe403
-	Mood                                  = 0xe7f2
-	MoodBad                               = 0xe7f3
-	More                                  = 0xe619
-	MoreHoriz                             = 0xe5d3
-	MoreVert                              = 0xe5d4
-	Motorcycle                            = 0xe91b
-	Mouse                                 = 0xe323
-	MoveToInbox                           = 0xe168
-	Movie                                 = 0xe02c
-	MovieCreation                         = 0xe404
-	MovieFilter                           = 0xe43a
-	MultilineChart                        = 0xe6df
-	MusicNote                             = 0xe405
-	MusicVideo                            = 0xe063
-	MyLocation                            = 0xe55c
-	Nature                                = 0xe406
-	NaturePeople                          = 0xe407
-	NavigateBefore                        = 0xe408
-	NavigateNext                          = 0xe409
-	Navigation                            = 0xe55d
-	NearMe                                = 0xe569
-	NetworkCell                           = 0xe1b9
-	NetworkCheck                          = 0xe640
-	NetworkLocked                         = 0xe61a
-	NetworkWifi                           = 0xe1ba
-	NewReleases                           = 0xe031
-	NextWeek                              = 0xe16a
-	Nfc                                   = 0xe1bb
-	NoEncryption                          = 0xe641
-	NoSim                                 = 0xe0cc
-	NotInterested                         = 0xe033
-	Note                                  = 0xe06f
-	NoteAdd                               = 0xe89c
-	Notifications                         = 0xe7f4
-	NotificationsActive                   = 0xe7f7
-	NotificationsNone                     = 0xe7f5
-	NotificationsOff                      = 0xe7f6
-	NotificationsPaused                   = 0xe7f8
-	OfflinePin                            = 0xe90a
-	OndemandVideo                         = 0xe63a
-	Opacity                               = 0xe91c
-	OpenInBrowser                         = 0xe89d
-	OpenInNew                             = 0xe89e
-	OpenWith                              = 0xe89f
-	Pages                                 = 0xe7f9
-	Pageview                              = 0xe8a0
-	Palette                               = 0xe40a
-	PanTool                               = 0xe925
-	Panorama                              = 0xe40b
-	PanoramaFishEye                       = 0xe40c
-	PanoramaHorizontal                    = 0xe40d
-	PanoramaVertical                      = 0xe40e
-	PanoramaWideAngle                     = 0xe40f
-	PartyMode                             = 0xe7fa
-	Pause                                 = 0xe034
-	PauseCircleFilled                     = 0xe035
-	PauseCircleOutline                    = 0xe036
-	Payment                               = 0xe8a1
-	People                                = 0xe7fb
-	PeopleOutline                         = 0xe7fc
-	PermCameraMic                         = 0xe8a2
-	PermContactCalendar                   = 0xe8a3
-	PermDataSetting                       = 0xe8a4
-	PermDeviceInformation                 = 0xe8a5
-	PermIdentity                          = 0xe8a6
-	PermMedia                             = 0xe8a7
-	PermPhoneMsg                          = 0xe8a8
-	PermScanWifi                          = 0xe8a9
-	Person                                = 0xe7fd
-	PersonAdd                             = 0xe7fe
-	PersonOutline                         = 0xe7ff
-	PersonPin                             = 0xe55a
-	PersonPinCircle                       = 0xe56a
-	PersonalVideo                         = 0xe63b
-	Pets                                  = 0xe91d
-	Phone                                 = 0xe0cd
-	PhoneAndroid                          = 0xe324
-	PhoneBluetoothSpeaker                 = 0xe61b
-	PhoneForwarded                        = 0xe61c
-	PhoneInTalk                           = 0xe61d
-	PhoneIphone                           = 0xe325
-	PhoneLocked                           = 0xe61e
-	PhoneMissed                           = 0xe61f
-	PhonePaused                           = 0xe620
-	Phonelink                             = 0xe326
-	PhonelinkErase                        = 0xe0db
-	PhonelinkLock                         = 0xe0dc
-	PhonelinkOff                          = 0xe327
-	PhonelinkRing                         = 0xe0dd
-	PhonelinkSetup                        = 0xe0de
-	Photo                                 = 0xe410
-	PhotoAlbum                            = 0xe411
-	PhotoCamera                           = 0xe412
-	PhotoFilter                           = 0xe43b
-	PhotoLibrary                          = 0xe413
-	PhotoSizeSelectActual                 = 0xe432
-	PhotoSizeSelectLarge                  = 0xe433
-	PhotoSizeSelectSmall                  = 0xe434
-	PictureAsPdf                          = 0xe415
-	PictureInPicture                      = 0xe8aa
-	PictureInPictureAlt                   = 0xe911
-	PieChart                              = 0xe6c4
-	PieChartOutlined                      = 0xe6c5
-	PinDrop                               = 0xe55e
-	Place                                 = 0xe55f
-	PlayArrow                             = 0xe037
-	PlayCircleFilled                      = 0xe038
-	PlayCircleOutline                     = 0xe039
-	PlayForWork                           = 0xe906
-	PlaylistAdd                           = 0xe03b
-	PlaylistAddCheck                      = 0xe065
-	PlaylistPlay                          = 0xe05f
-	PlusOne                               = 0xe800
-	Poll                                  = 0xe801
-	Polymer                               = 0xe8ab
-	Pool                                  = 0xeb48
-	PortableWifiOff                       = 0xe0ce
-	Portrait                              = 0xe416
-	Power                                 = 0xe63c
-	PowerInput                            = 0xe336
-	PowerSettingsNew                      = 0xe8ac
-	PregnantWoman                         = 0xe91e
-	PresentToAll                          = 0xe0df
-	Print                                 = 0xe8ad
-	PriorityHigh                          = 0xe645
-	Public                                = 0xe80b
-	Publish                               = 0xe255
-	QueryBuilder                          = 0xe8ae
-	QuestionAnswer                        = 0xe8af
-	Queue                                 = 0xe03c
-	QueueMusic                            = 0xe03d
-	QueuePlayNext                         = 0xe066
-	Radio                                 = 0xe03e
-	RadioButtonChecked                    = 0xe837
-	RadioButtonUnchecked                  = 0xe836
-	RateReview                            = 0xe560
-	Receipt                               = 0xe8b0
-	RecentActors                          = 0xe03f
-	RecordVoiceOver                       = 0xe91f
-	Redeem                                = 0xe8b1
-	Redo                                  = 0xe15a
-	Refresh                               = 0xe5d5
-	Remove                                = 0xe15b
-	RemoveCircle                          = 0xe15c
-	RemoveCircleOutline                   = 0xe15d
-	RemoveFromQueue                       = 0xe067
-	RemoveRedEye                          = 0xe417
-	RemoveShoppingCart                    = 0xe928
-	Reorder                               = 0xe8fe
-	Repeat                                = 0xe040
-	RepeatOne                             = 0xe041
-	Replay                                = 0xe042
-	Replay10                              = 0xe059
-	Replay30                              = 0xe05a
-	Replay5                               = 0xe05b
-	Reply                                 = 0xe15e
-	ReplyAll                              = 0xe15f
-	Report                                = 0xe160
-	ReportProblem                         = 0xe8b2
-	Restaurant                            = 0xe56c
-	RestaurantMenu                        = 0xe561
-	Restore                               = 0xe8b3
-	RestorePage                           = 0xe929
-	RingVolume                            = 0xe0d1
-	Room                                  = 0xe8b4
-	RoomService                           = 0xeb49
-	Rotate90DegreesCcw                    = 0xe418
-	RotateLeft                            = 0xe419
-	RotateRight                           = 0xe41a
-	RoundedCorner                         = 0xe920
-	Router                                = 0xe328
-	Rowing                                = 0xe921
-	RssFeed                               = 0xe0e5
-	RvHookup                              = 0xe642
-	Satellite                             = 0xe562
-	Save                                  = 0xe161
-	Scanner                               = 0xe329
-	Schedule                              = 0xe8b5
-	School                                = 0xe80c
-	ScreenLockLandscape                   = 0xe1be
-	ScreenLockPortrait                    = 0xe1bf
-	ScreenLockRotation                    = 0xe1c0
-	ScreenRotation                        = 0xe1c1
-	ScreenShare                           = 0xe0e2
-	SdCard                                = 0xe623
-	SdStorage                             = 0xe1c2
-	Search                                = 0xe8b6
-	Security                              = 0xe32a
-	SelectAll                             = 0xe162
-	Send                                  = 0xe163
-	SentimentDissatisfied                 = 0xe811
-	SentimentNeutral                      = 0xe812
-	SentimentSatisfied                    = 0xe813
-	SentimentVeryDissatisfied             = 0xe814
-	SentimentVerySatisfied                = 0xe815
-	Settings                              = 0xe8b8
-	SettingsApplications                  = 0xe8b9
-	SettingsBackupRestore                 = 0xe8ba
-	SettingsBluetooth                     = 0xe8bb
-	SettingsBrightness                    = 0xe8bd
-	SettingsCell                          = 0xe8bc
-	SettingsEthernet                      = 0xe8be
-	SettingsInputAntenna                  = 0xe8bf
-	SettingsInputComponent                = 0xe8c0
-	SettingsInputComposite                = 0xe8c1
-	SettingsInputHdmi                     = 0xe8c2
-	SettingsInputSvideo                   = 0xe8c3
-	SettingsOverscan                      = 0xe8c4
-	SettingsPhone                         = 0xe8c5
-	SettingsPower                         = 0xe8c6
-	SettingsRemote                        = 0xe8c7
-	SettingsSystemDaydream                = 0xe1c3
-	SettingsVoice                         = 0xe8c8
-	Share                                 = 0xe80d
-	Shop                                  = 0xe8c9
-	ShopTwo                               = 0xe8ca
-	ShoppingBasket                        = 0xe8cb
-	ShoppingCart                          = 0xe8cc
-	ShortText                             = 0xe261
-	ShowChart                             = 0xe6e1
-	Shuffle                               = 0xe043
-	SignalCellular4Bar                    = 0xe1c8
-	SignalCellularConnectedNoInternet4Bar = 0xe1cd
-	SignalCellularNoSim                   = 0xe1ce
-	SignalCellularNull                    = 0xe1cf
-	SignalCellularOff                     = 0xe1d0
-	SignalWifi4Bar                        = 0xe1d8
-	SignalWifi4BarLock                    = 0xe1d9
-	SignalWifiOff                         = 0xe1da
-	SimCard                               = 0xe32b
-	SimCardAlert                          = 0xe624
-	SkipNext                              = 0xe044
-	SkipPrevious                          = 0xe045
-	Slideshow                             = 0xe41b
-	SlowMotionVideo                       = 0xe068
-	Smartphone                            = 0xe32c
-	SmokeFree                             = 0xeb4a
-	SmokingRooms                          = 0xeb4b
-	Sms                                   = 0xe625
-	SmsFailed                             = 0xe626
-	Snooze                                = 0xe046
-	Sort                                  = 0xe164
-	SortByAlpha                           = 0xe053
-	Spa                                   = 0xeb4c
-	SpaceBar                              = 0xe256
-	Speaker                               = 0xe32d
-	SpeakerGroup                          = 0xe32e
-	SpeakerNotes                          = 0xe8cd
-	SpeakerNotesOff                       = 0xe92a
-	SpeakerPhone                          = 0xe0d2
-	Spellcheck                            = 0xe8ce
-	Star                                  = 0xe838
-	StarBorder                            = 0xe83a
-	StarHalf                              = 0xe839
-	Stars                                 = 0xe8d0
-	StayCurrentLandscape                  = 0xe0d3
-	StayCurrentPortrait                   = 0xe0d4
-	StayPrimaryLandscape                  = 0xe0d5
-	StayPrimaryPortrait                   = 0xe0d6
-	Stop                                  = 0xe047
-	StopScreenShare                       = 0xe0e3
-	Storage                               = 0xe1db
-	Store                                 = 0xe8d1
-	StoreMallDirectory                    = 0xe563
-	Straighten                            = 0xe41c
-	Streetview                            = 0xe56e
-	StrikethroughS                        = 0xe257
-	Style                                 = 0xe41d
-	SubdirectoryArrowLeft                 = 0xe5d9
-	SubdirectoryArrowRight                = 0xe5da
-	Subject                               = 0xe8d2
-	Subscriptions                         = 0xe064
-	Subtitles                             = 0xe048
-	Subway                                = 0xe56f
-	SupervisorAccount                     = 0xe8d3
-	SurroundSound                         = 0xe049
-	SwapCalls                             = 0xe0d7
-	SwapHoriz                             = 0xe8d4
-	SwapVert                              = 0xe8d5
-	SwapVerticalCircle                    = 0xe8d6
-	SwitchCamera                          = 0xe41e
-	SwitchVideo                           = 0xe41f
-	Sync                                  = 0xe627
-	SyncDisabled                          = 0xe628
-	SyncProblem                           = 0xe629
-	SystemUpdate                          = 0xe62a
-	SystemUpdateAlt                       = 0xe8d7
-	Tab                                   = 0xe8d8
-	TabUnselected                         = 0xe8d9
-	Tablet                                = 0xe32f
-	TabletAndroid                         = 0xe330
-	TabletMac                             = 0xe331
-	TagFaces                              = 0xe420
-	TapAndPlay                            = 0xe62b
-	Terrain                               = 0xe564
-	TextFields                            = 0xe262
-	TextFormat                            = 0xe165
-	Textsms                               = 0xe0d8
-	Texture                               = 0xe421
-	Theaters                              = 0xe8da
-	ThumbDown                             = 0xe8db
-	ThumbUp                               = 0xe8dc
-	ThumbsUpDown                          = 0xe8dd
-	TimeToLeave                           = 0xe62c
-	Timelapse                             = 0xe422
-	Timeline                              = 0xe922
-	Timer                                 = 0xe425
-	Timer10                               = 0xe423
-	Timer3                                = 0xe424
-	TimerOff                              = 0xe426
-	Title                                 = 0xe264
-	Toc                                   = 0xe8de
-	Today                                 = 0xe8df
-	Toll                                  = 0xe8e0
-	Tonality                              = 0xe427
-	TouchApp                              = 0xe913
-	Toys                                  = 0xe332
-	TrackChanges                          = 0xe8e1
-	Traffic                               = 0xe565
-	Train                                 = 0xe570
-	Tram                                  = 0xe571
-	TransferWithinAStation                = 0xe572
-	Transform                             = 0xe428
-	Translate                             = 0xe8e2
-	TrendingDown                          = 0xe8e3
-	TrendingFlat                          = 0xe8e4
-	TrendingUp                            = 0xe8e5
-	Tune                                  = 0xe429
-	TurnedIn                              = 0xe8e6
-	TurnedInNot                           = 0xe8e7
-	Tv                                    = 0xe333
-	Unarchive                             = 0xe169
-	Undo                                  = 0xe166
-	UnfoldLess                            = 0xe5d6
-	UnfoldMore                            = 0xe5d7
-	Update                                = 0xe923
-	Usb                                   = 0xe1e0
-	VerifiedUser                          = 0xe8e8
-	VerticalAlignBottom                   = 0xe258
-	VerticalAlignCenter                   = 0xe259
-	VerticalAlignTop                      = 0xe25a
-	Vibration                             = 0xe62d
-	VideoCall                             = 0xe070
-	VideoLabel                            = 0xe071
-	VideoLibrary                          = 0xe04a
-	Videocam                              = 0xe04b
-	VideocamOff                           = 0xe04c
-	VideogameAsset                        = 0xe338
-	ViewAgenda                            = 0xe8e9
-	ViewArray                             = 0xe8ea
-	ViewCarousel                          = 0xe8eb
-	ViewColumn                            = 0xe8ec
-	ViewComfy                             = 0xe42a
-	ViewCompact                           = 0xe42b
-	ViewDay                               = 0xe8ed
-	ViewHeadline                          = 0xe8ee
-	ViewList                              = 0xe8ef
-	ViewModule                            = 0xe8f0
-	ViewQuilt                             = 0xe8f1
-	ViewStream                            = 0xe8f2
-	ViewWeek                              = 0xe8f3
-	Vignette                              = 0xe435
-	Visibility                            = 0xe8f4
-	VisibilityOff                         = 0xe8f5
-	VoiceChat                             = 0xe62e
-	Voicemail                             = 0xe0d9
-	VolumeDown                            = 0xe04d
-	VolumeMute                            = 0xe04e
-	VolumeOff                             = 0xe04f
-	VolumeUp                              = 0xe050
-	VpnKey                                = 0xe0da
-	VpnLock                               = 0xe62f
-	Wallpaper                             = 0xe1bc
-	Warning                               = 0xe002
-	Watch                                 = 0xe334
-	WatchLater                            = 0xe924
-	WbAuto                                = 0xe42c
-	WbCloudy                              = 0xe42d
-	WbIncandescent                        = 0xe42e
-	WbIridescent                          = 0xe436
-	WbSunny                               = 0xe430
-	Wc                                    = 0xe63d
-	Web                                   = 0xe051
-	WebAsset                              = 0xe069
-	Weekend                               = 0xe16b
-	Whatshot                              = 0xe80e
-	Widgets                               = 0xe1bd
-	Wifi                                  = 0xe63e
-	WifiLock                              = 0xe1e1
-	WifiTethering                         = 0xe1e2
-	Work                                  = 0xe8f9
-	WrapText                              = 0xe25b
-	YoutubeSearchedFor                    = 0xe8fa
-	ZoomIn                                = 0xe8ff
-	ZoomOut                               = 0xe900
-	ZoomOutMap                            = 0xe56b
-)

gui/assets/genicodes/codepoints → gui/assets/icon/codepoints


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1885 - 0
gui/assets/icon/icodes.go


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1151 - 0
gui/builder.go


+ 200 - 0
gui/builder_layout.go

@@ -0,0 +1,200 @@
+// 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
+
+//
+// BuilderLayoutHBox is builder for HBox layout
+//
+type BuilderLayoutHBox struct{}
+
+// BuildLayout builds and returns an HBoxLayout with the specified attributes
+func (bl *BuilderLayoutHBox) BuildLayout(b *Builder, am map[string]interface{}) (ILayout, error) {
+
+	// Creates layout and sets optional spacing
+	l := NewHBoxLayout()
+	var spacing float32
+	if sp := am[AttribSpacing]; sp != nil {
+		spacing = sp.(float32)
+	}
+	l.SetSpacing(spacing)
+
+	// Sets optional horizontal alignment
+	if ah := am[AttribAlignh]; ah != nil {
+		l.SetAlignH(ah.(Align))
+	}
+
+	// Sets optional minheight flag
+	if mh := am[AttribAutoHeight]; mh != nil {
+		l.SetAutoHeight(mh.(bool))
+	}
+
+	// Sets optional minwidth flag
+	if mw := am[AttribAutoWidth]; mw != nil {
+		l.SetAutoWidth(mw.(bool))
+	}
+	return l, nil
+}
+
+// BuildParams builds and returns a pointer to HBoxLayoutParams with the specified attributes
+func (bl *BuilderLayoutHBox) BuildParams(b *Builder, am map[string]interface{}) (interface{}, error) {
+
+	// Creates layout parameters with default values
+	params := HBoxLayoutParams{Expand: 0, AlignV: AlignNone}
+
+	// Sets optional expand parameter
+	if expand := am[AttribExpand]; expand != nil {
+		params.Expand = expand.(float32)
+	}
+
+	// Sets optional align parameter
+	if alignv := am[AttribAlignv]; alignv != nil {
+		params.AlignV = alignv.(Align)
+	}
+	return &params, nil
+}
+
+//
+// BuilderLayoutVBox is builder for VBox layout
+//
+type BuilderLayoutVBox struct{}
+
+// BuildLayout builds and returns an VBoxLayout with the specified attributes
+func (bl *BuilderLayoutVBox) BuildLayout(b *Builder, am map[string]interface{}) (ILayout, error) {
+
+	// Creates layout and sets optional spacing
+	l := NewVBoxLayout()
+	var spacing float32
+	if sp := am[AttribSpacing]; sp != nil {
+		spacing = sp.(float32)
+	}
+	l.SetSpacing(spacing)
+
+	// Sets optional vertical alignment
+	if av := am[AttribAlignh]; av != nil {
+		l.SetAlignV(av.(Align))
+	}
+
+	// Sets optional minheight flag
+	if mh := am[AttribAutoHeight]; mh != nil {
+		l.SetAutoHeight(mh.(bool))
+	}
+
+	// Sets optional minwidth flag
+	if mw := am[AttribAutoWidth]; mw != nil {
+		l.SetAutoWidth(mw.(bool))
+	}
+	return l, nil
+}
+
+// BuildParams builds and returns a pointer to VBoxLayoutParams with the specified attributes
+func (bl *BuilderLayoutVBox) BuildParams(b *Builder, am map[string]interface{}) (interface{}, error) {
+
+	// Creates layout parameters with default values
+	params := VBoxLayoutParams{Expand: 0, AlignH: AlignNone}
+
+	// Sets optional expand parameter
+	if expand := am[AttribExpand]; expand != nil {
+		params.Expand = expand.(float32)
+	}
+
+	// Sets optional align parameter
+	if alignh := am[AttribAlignh]; alignh != nil {
+		params.AlignH = alignh.(Align)
+	}
+	return &params, nil
+}
+
+//
+// BuilderLayoutGrid is builder for Grid layout
+//
+type BuilderLayoutGrid struct{}
+
+// BuildLayout builds and returns a GridLayout with the specified attributes
+func (bl *BuilderLayoutGrid) BuildLayout(b *Builder, am map[string]interface{}) (ILayout, error) {
+
+	// Get number of columns
+	v := am[AttribCols]
+	if v == nil {
+		return nil, b.err(am, AttribCols, "Number of columns must be supplied")
+	}
+	cols := v.(int)
+	if cols <= 0 {
+		return nil, b.err(am, AttribCols, "Invalid number of columns")
+	}
+
+	// Creates layout
+	l := NewGridLayout(cols)
+
+	// Sets optional horizontal alignment
+	if ah := am[AttribAlignh]; ah != nil {
+		l.SetAlignH(ah.(Align))
+	}
+
+	// Sets optional vertical alignment
+	if av := am[AttribAlignv]; av != nil {
+		l.SetAlignV(av.(Align))
+	}
+
+	// Sets optional horizontal expand flag
+	if eh := am[AttribExpandh]; eh != nil {
+		l.SetExpandH(eh.(bool))
+	}
+
+	// Sets optional vertical expand flag
+	if ev := am[AttribExpandv]; ev != nil {
+		l.SetExpandV(ev.(bool))
+	}
+
+	return l, nil
+}
+
+// BuildParams builds and returns a pointer to GridLayoutParams with the specified attributes
+func (bl *BuilderLayoutGrid) BuildParams(b *Builder, am map[string]interface{}) (interface{}, error) {
+
+	// Creates layout parameters with default values
+	params := GridLayoutParams{
+		ColSpan: 0,
+		AlignH:  AlignNone,
+		AlignV:  AlignNone,
+	}
+
+	// Sets optional colspan
+	if cs := am[AttribColSpan]; cs != nil {
+		params.ColSpan = cs.(int)
+	}
+
+	// Sets optional alignh parameter
+	if align := am[AttribAlignh]; align != nil {
+		params.AlignH = align.(Align)
+	}
+
+	// Sets optional alignv parameter
+	if align := am[AttribAlignv]; align != nil {
+		params.AlignV = align.(Align)
+	}
+	return &params, nil
+}
+
+//
+// BuilderLayoutDock is builder for Dock layout
+//
+type BuilderLayoutDock struct{}
+
+// BuildLayout builds and returns a DockLayout with the specified attributes
+func (bl *BuilderLayoutDock) BuildLayout(b *Builder, am map[string]interface{}) (ILayout, error) {
+
+	return NewDockLayout(), nil
+}
+
+// BuildParams builds and returns a pointer to DockLayoutParams with the specified attributes
+func (bl *BuilderLayoutDock) BuildParams(b *Builder, am map[string]interface{}) (interface{}, error) {
+
+	edge := am[AttribEdge]
+	if edge == nil {
+		return nil, b.err(am, AttribEdge, "Edge name not found")
+	}
+	params := DockLayoutParams{Edge: edge.(int)}
+	return &params, nil
+}

+ 802 - 0
gui/builder_panel.go

@@ -0,0 +1,802 @@
+// 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 (
+	"path/filepath"
+
+	"github.com/g3n/engine/math32"
+	"github.com/g3n/engine/window"
+)
+
+// 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) {
+
+	// Builds menu bar or menu
+	var menu *Menu
+	if am[AttribType].(string) == TypeMenuBar {
+		menu = NewMenuBar()
+	} else {
+		menu = NewMenu()
+	}
+
+	// Only sets attribs for top level menus
+	if pi := am[AttribParentInternal]; 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
+			}
+		}
+	}
+
+	// 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]))
+			}
+		}
+	}
+	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)
+	}
+
+	// Sets common attributes
+	err := b.setAttribs(am, slider, asWIDGET)
+	if err != nil {
+		return nil, err
+	}
+
+	// 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))
+	}
+	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)
+	}
+
+	// Sets common attributes
+	err := b.setAttribs(am, splitter, asWIDGET)
+	if err != nil {
+		return nil, err
+	}
+
+	// Sets optional split value
+	if v := am[AttribSplit]; v != nil {
+		splitter.SetSplit(v.(float32))
+	}
+
+	// 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
+	}
+
+	// Set optional splitter panel's attributes
+	err = setpan(AttribPanel0, &splitter.P0)
+	if err != nil {
+		return nil, err
+	}
+	err = setpan(AttribPanel1, &splitter.P1)
+	if err != nil {
+		return nil, err
+	}
+
+	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)
+	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[AttribResizeBorders]; resiz != nil {
+		win.SetResizable(resiz.(ResizeBorders))
+	}
+
+	// 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
+}
+
+// buildChart builds a gui object of type: Chart
+func buildChart(b *Builder, am map[string]interface{}) (IPanel, error) {
+
+	// Builds window and sets its common attributes
+	chart := NewChart(0, 0)
+	err := b.setAttribs(am, chart, asPANEL)
+	if err != nil {
+		return nil, err
+	}
+
+	// Sets optional title
+	if title := am[AttribTitle]; title != nil {
+		chart.SetTitle(title.(string), 14)
+	}
+
+	// Sets x scale attibutes
+	if v := am[AttribScalex]; v != nil {
+		sx := v.(map[string]interface{})
+		// Sets optional x scale margin
+		if mx := sx[AttribMargin]; mx != nil {
+			chart.SetMarginX(mx.(float32))
+		}
+		// Sets optional x scale format
+		if fx := sx[AttribFormat]; fx != nil {
+			chart.SetFormatX(fx.(string))
+		}
+		// Sets optional x scale font size
+		if fsize := sx[AttribFontSize]; fsize != nil {
+			chart.SetFontSizeX(float64(fsize.(float32)))
+		}
+		// Number of lines
+		lines := 4
+		if v := sx[AttribLines]; v != nil {
+			lines = v.(int)
+		}
+		// Lines color
+		color4 := math32.NewColor4("Black")
+		if v := sx[AttribColor]; v != nil {
+			color4 = v.(*math32.Color4)
+		}
+		color := color4.ToColor()
+		chart.SetScaleX(lines, &color)
+		// Range first
+		firstX := float32(0)
+		if v := sx[AttribFirstx]; v != nil {
+			firstX = v.(float32)
+		}
+		// Range step
+		stepX := float32(1)
+		if v := sx[AttribStepx]; v != nil {
+			stepX = v.(float32)
+		}
+		// Range count step
+		countStepX := float32(1)
+		if v := sx[AttribStepx]; v != nil {
+			countStepX = v.(float32)
+		}
+		chart.SetRangeX(firstX, stepX, countStepX)
+	}
+
+	// Sets y scale attibutes
+	if v := am[AttribScaley]; v != nil {
+		sy := v.(map[string]interface{})
+		// Sets optional y scale margin
+		if my := sy[AttribMargin]; my != nil {
+			chart.SetMarginY(my.(float32))
+		}
+		// Sets optional y scale format
+		if fy := sy[AttribFormat]; fy != nil {
+			chart.SetFormatY(fy.(string))
+		}
+		// Sets optional y scale font size
+		if fsize := sy[AttribFontSize]; fsize != nil {
+			chart.SetFontSizeY(float64(fsize.(float32)))
+		}
+		// Number of lines
+		lines := 4
+		if v := sy[AttribLines]; v != nil {
+			lines = v.(int)
+		}
+		// Lines color
+		color4 := math32.NewColor4("Black")
+		if v := sy[AttribColor]; v != nil {
+			color4 = v.(*math32.Color4)
+		}
+		color := color4.ToColor()
+		chart.SetScaleY(lines, &color)
+		// Range min
+		rmin := float32(-10)
+		if v := sy[AttribRangeMin]; v != nil {
+			rmin = v.(float32)
+		}
+		// Range max
+		rmax := float32(10)
+		if v := sy[AttribRangeMax]; v != nil {
+			rmax = v.(float32)
+		}
+		chart.SetRangeY(rmin, rmax)
+		// Range auto
+		if rauto := sy[AttribRangeAuto]; rauto != nil {
+			chart.SetRangeYauto(v.(bool))
+		}
+	}
+
+	return chart, nil
+}
+
+// buildTable builds a gui object of type: Table
+func buildTable(b *Builder, am map[string]interface{}) (IPanel, error) {
+
+	// Internal function to build a TableColumn from its attribute map
+	buildTableCol := func(b *Builder, am map[string]interface{}) (*TableColumn, error) {
+		tc := &TableColumn{}
+		if iv := am[AttribId]; iv != nil {
+			tc.Id = iv.(string)
+		}
+		if iv := am[AttribHeader]; iv != nil {
+			tc.Header = iv.(string)
+		}
+		if iv := am[AttribWidth]; iv != nil {
+			tc.Width = iv.(float32)
+		}
+		if iv := am[AttribMinwidth]; iv != nil {
+			tc.Minwidth = iv.(float32)
+		}
+		if iv := am[AttribHidden]; iv != nil {
+			tc.Hidden = iv.(bool)
+		}
+		if iv := am[AttribFormat]; iv != nil {
+			tc.Format = iv.(string)
+		}
+		if iv := am[AttribExpand]; iv != nil {
+			tc.Expand = iv.(float32)
+		}
+		if iv := am[AttribResize]; iv != nil {
+			tc.Resize = iv.(bool)
+		}
+		if iv := am[AttribSortType]; iv != nil {
+			tc.Sort = iv.(TableSortType)
+		}
+		return tc, nil
+	}
+
+	// Builds table columns array
+	tableCols := []TableColumn{}
+	if iv := am[AttribColumns]; iv != nil {
+		cols := iv.([]map[string]interface{})
+		for _, c := range cols {
+			tc, err := buildTableCol(b, c)
+			if err != nil {
+				return nil, err
+			}
+			tableCols = append(tableCols, *tc)
+		}
+	}
+
+	// Creates table and set common attributes
+	table, err := NewTable(0, 0, tableCols)
+	if err != nil {
+		return nil, err
+	}
+	err = b.setAttribs(am, table, asPANEL)
+	if err != nil {
+		return nil, err
+	}
+
+	// Sets optional show header attribute
+	if show := am[AttribShowHeader]; show != nil {
+		table.ShowHeader(show.(bool))
+	}
+
+	return table, nil
+}

+ 15 - 5
gui/button.go

@@ -55,7 +55,7 @@ type ButtonStyles struct {
 func NewButton(text string) *Button {
 
 	b := new(Button)
-	b.styles = &StyleDefault.Button
+	b.styles = &StyleDefault().Button
 
 	// Initializes the button panel
 	b.Panel = NewPanel(0, 0)
@@ -83,9 +83,9 @@ func NewButton(text string) *Button {
 
 // SetIcon sets the button icon from the default Icon font.
 // If there is currently a selected image, it is removed
-func (b *Button) SetIcon(icode int) {
+func (b *Button) SetIcon(icode string) {
 
-	ico := NewIconLabel(string(icode))
+	ico := NewLabel(icode, true)
 	if b.image != nil {
 		b.Panel.Remove(b.image)
 		b.image = nil
@@ -218,15 +218,25 @@ func (b *Button) recalc() {
 
 	// Image or icon width
 	imgWidth := float32(0)
+	spacing := float32(4)
 	if b.image != nil {
 		imgWidth = b.image.Width()
 	} else if b.icon != nil {
 		imgWidth = b.icon.Width()
 	}
+	if imgWidth == 0 {
+		spacing = 0
+	}
+
+	// If the label is empty and an icon of image was defined ignore the label widthh
+	// to centralize the icon/image in the button
+	labelWidth := spacing + b.Label.Width()
+	if b.Label.Text() == "" && imgWidth > 0 {
+		labelWidth = 0
+	}
 
 	// Sets new content width and height if necessary
-	spacing := float32(4)
-	minWidth := imgWidth + spacing + b.Label.Width()
+	minWidth := imgWidth + labelWidth
 	minHeight := b.Label.Height()
 	resize := false
 	if width < minWidth {

+ 7 - 7
gui/checkradio.go

@@ -5,16 +5,16 @@
 package gui
 
 import (
-	"github.com/g3n/engine/gui/assets"
+	"github.com/g3n/engine/gui/assets/icon"
 	"github.com/g3n/engine/math32"
 	"github.com/g3n/engine/window"
 )
 
 const (
-	checkON  = string(assets.CheckBox)
-	checkOFF = string(assets.CheckBoxOutlineBlank)
-	radioON  = string(assets.RadioButtonChecked)
-	radioOFF = string(assets.RadioButtonUnchecked)
+	checkON  = string(icon.CheckBox)
+	checkOFF = string(icon.CheckBoxOutlineBlank)
+	radioON  = string(icon.RadioButtonChecked)
+	radioOFF = string(icon.RadioButtonUnchecked)
 )
 
 type CheckRadio struct {
@@ -65,7 +65,7 @@ func NewRadioButton(text string) *CheckRadio {
 func newCheckRadio(check bool, text string) *CheckRadio {
 
 	cb := new(CheckRadio)
-	cb.styles = &StyleDefault.CheckRadio
+	cb.styles = &StyleDefault().CheckRadio
 
 	// Adapts to specified type: CheckBox or RadioButton
 	cb.check = check
@@ -94,7 +94,7 @@ func newCheckRadio(check bool, text string) *CheckRadio {
 	cb.Panel.Add(cb.Label)
 
 	// Creates icon label
-	cb.icon = NewIconLabel(" ")
+	cb.icon = NewLabel(" ", true)
 	cb.Panel.Add(cb.icon)
 
 	cb.recalc()

+ 1 - 1
gui/control_folder.go

@@ -37,7 +37,7 @@ func NewControlFolder(text string, width float32) *ControlFolder {
 // It is normally used when the control folder is embedded in another object
 func (f *ControlFolder) Initialize(text string, width float32) {
 
-	f.styles = &StyleDefault.ControlFolder
+	f.styles = &StyleDefault().ControlFolder
 	f.tree.Initialize(width, width)
 	f.tree.SetStyles(f.styles.Tree)
 	f.tree.SetAutoHeight(600)

+ 8 - 8
gui/dropdown.go

@@ -5,7 +5,7 @@
 package gui
 
 import (
-	"github.com/g3n/engine/gui/assets"
+	"github.com/g3n/engine/gui/assets/icon"
 	"github.com/g3n/engine/math32"
 	"github.com/g3n/engine/window"
 )
@@ -44,7 +44,7 @@ type DropDownStyles struct {
 func NewDropDown(width float32, item *ImageLabel) *DropDown {
 
 	dd := new(DropDown)
-	dd.styles = &StyleDefault.DropDown
+	dd.styles = &StyleDefault().DropDown
 	dd.litem = item
 
 	dd.Panel.Initialize(width, 0)
@@ -58,9 +58,9 @@ func NewDropDown(width float32, item *ImageLabel) *DropDown {
 	dd.Panel.Add(dd.litem)
 
 	// Create icon
-	dd.icon = NewIconLabel(" ")
-	dd.icon.SetFontSize(StyleDefault.Font.Size() * 1.3)
-	dd.icon.SetText(string(assets.ArrowDropDown))
+	dd.icon = NewLabel(" ", true)
+	dd.icon.SetFontSize(StyleDefault().Font.Size() * 1.3)
+	dd.icon.SetText(string(icon.ArrowDropDown))
 	dd.Panel.Add(dd.icon)
 
 	/// Create list
@@ -259,16 +259,16 @@ func (dd *DropDown) update() {
 
 	if dd.overDropdown || dd.overList {
 		dd.applyStyle(dd.styles.Over)
-		dd.list.ApplyStyle(OverStyle)
+		dd.list.ApplyStyle(StyleOver)
 		return
 	}
 	if dd.focus {
 		dd.applyStyle(dd.styles.Focus)
-		dd.list.ApplyStyle(FocusStyle)
+		dd.list.ApplyStyle(StyleFocus)
 		return
 	}
 	dd.applyStyle(dd.styles.Normal)
-	dd.list.ApplyStyle(NormalStyle)
+	dd.list.ApplyStyle(StyleNormal)
 }
 
 // applyStyle applies the specified style

+ 2 - 2
gui/edit.go

@@ -55,13 +55,13 @@ func NewEdit(width int, placeHolder string) *Edit {
 	ed.width = width
 	ed.placeHolder = placeHolder
 
-	ed.styles = &StyleDefault.Edit
+	ed.styles = &StyleDefault().Edit
 	ed.text = ""
 	ed.MaxLength = 80
 	ed.col = 0
 	ed.focus = false
 
-	ed.Label.initialize("", StyleDefault.Font)
+	ed.Label.initialize("", StyleDefault().Font)
 	ed.Label.Subscribe(OnKeyDown, ed.onKey)
 	ed.Label.Subscribe(OnKeyRepeat, ed.onKey)
 	ed.Label.Subscribe(OnChar, ed.onChar)

+ 4 - 4
gui/folder.go

@@ -25,7 +25,7 @@ type FolderStyle struct {
 	BorderColor math32.Color4
 	BgColor     math32.Color
 	FgColor     math32.Color
-	Icons       [2]int
+	Icons       [2]string
 }
 
 type FolderStyles struct {
@@ -49,14 +49,14 @@ func NewFolder(text string, width float32, contentPanel IPanel) *Folder {
 func (f *Folder) Initialize(text string, width float32, contentPanel IPanel) {
 
 	f.Panel.Initialize(width, 0)
-	f.styles = &StyleDefault.Folder
+	f.styles = &StyleDefault().Folder
 
 	// Initialize label
-	f.label.initialize(text, StyleDefault.Font)
+	f.label.initialize(text, StyleDefault().Font)
 	f.Panel.Add(&f.label)
 
 	// Create icon
-	f.icon.initialize("", StyleDefault.FontIcon)
+	f.icon.initialize("", StyleDefault().FontIcon)
 	f.icon.SetFontSize(f.label.FontSize() * 1.3)
 	f.Panel.Add(&f.icon)
 

+ 270 - 95
gui/gridlayout.go

@@ -1,135 +1,310 @@
 // 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
 
+// GridLayout is a panel layout which arranges its children in a rectangular grid.
+// It is necessary to set the number of columns of the grid when the layout is created.
+// The panel's child elements are positioned in the grid cells accordingly to the
+// order they were added to the panel.
+// The height of each row is determined by the height of the heightest child in the row.
+// The width of each column is determined by the width of the widest child in the column
 type GridLayout struct {
-	columns int
+	pan     IPanel    // parent panel
+	columns []colInfo // columns alignment info
+	alignh  Align     // global cell horizontal alignment
+	alignv  Align     // global cell vertical alignment
+	expandh bool      // expand horizontally flag
+	expandv bool      // expand vertically flag
 }
 
+// GridLayoutParams describes layout parameter for an specific child
 type GridLayoutParams struct {
-	Row     int   // grid layout row number from 0
-	Col     int   // grid layout column number from 0
-	ColSpan int   // number of additional columns to ocuppy to the right
-	AlignH  Align // vertical alignment
-	AlignV  Align // horizontal alignment
+	ColSpan int   // Number of additional columns to ocuppy to the right
+	AlignH  Align // Vertical alignment
+	AlignV  Align // Horizontal alignment
+}
+
+// colInfo keeps information about each grid column
+type colInfo struct {
+	alignh *Align // optional column horizontal alignment
+	alignv *Align // optional column vertical alignment
 }
 
 // NewGridLayout creates and returns a pointer of a new grid layout
-func NewGridLayout() *GridLayout {
+func NewGridLayout(ncols int) *GridLayout {
+
+	if ncols <= 0 {
+		panic("Invalid number of columns")
+	}
+	gl := new(GridLayout)
+	gl.columns = make([]colInfo, ncols)
+	return gl
+}
+
+// SetAlignV sets the vertical alignment for all the grid cells
+// The alignment of an individual cell can be set by settings its layout parameters.
+func (g *GridLayout) SetAlignV(align Align) {
 
-	g := new(GridLayout)
-	return g
+	g.alignv = align
+	g.Recalc(g.pan)
 }
 
+// SetAlignH sets the horizontal alignment for all the grid cells
+// The alignment of an individual cell can be set by settings its layout parameters.
+func (g *GridLayout) SetAlignH(align Align) {
+
+	g.alignh = align
+	g.Recalc(g.pan)
+}
+
+// SetExpandH sets it the columns should expand horizontally if possible
+func (g *GridLayout) SetExpandH(expand bool) {
+
+	g.expandh = expand
+	g.Recalc(g.pan)
+}
+
+// SetExpandV sets it the rowss should expand vertically if possible
+func (g *GridLayout) SetExpandV(expand bool) {
+
+	g.expandv = expand
+	g.Recalc(g.pan)
+}
+
+// SetColAlignV sets the vertical alignment for all the cells of
+// the specified column. The function panics if the supplied column is invalid
+func (g *GridLayout) SetColAlignV(col int, align Align) {
+
+	if col < 0 || col >= len(g.columns) {
+		panic("Invalid column")
+	}
+	if g.columns[col].alignv == nil {
+		g.columns[col].alignv = new(Align)
+	}
+	*g.columns[col].alignv = align
+	g.Recalc(g.pan)
+}
+
+// SetColAlignH sets the horizontal alignment for all the cells of
+// the specified column. The function panics if the supplied column is invalid.
+func (g *GridLayout) SetColAlignH(col int, align Align) {
+
+	if col < 0 || col >= len(g.columns) {
+		panic("Invalid column")
+	}
+	if g.columns[col].alignh == nil {
+		g.columns[col].alignh = new(Align)
+	}
+	*g.columns[col].alignh = align
+	g.Recalc(g.pan)
+}
+
+// Recalc sets the position and sizes of all of the panel's children.
+// It is normally called by the parent panel when its size changes or
+// a child is added or removed.
 func (g *GridLayout) Recalc(ipan IPanel) {
 
-	type element struct {
-		panel  *Panel
-		params *GridLayoutParams
+	type cell struct {
+		panel     *Panel           // pointer to cell panel
+		params    GridLayoutParams // copy of params or default
+		paramsDef bool             // true if parameters are default
 	}
-	rows := 0
-	cols := 0
-	items := []element{}
 
+	type row struct {
+		cells  []*cell // array of row cells
+		height float32 // row height
+	}
+
+	// Saves the received panel
+	g.pan = ipan
+	if g.pan == nil {
+		return
+	}
+
+	// Builds array of child rows
 	pan := ipan.GetPanel()
-	for _, obj := range pan.Children() {
-		// Get child panel
-		child := obj.(IPanel).GetPanel()
-		// Ignore if not visible
+	var irow int
+	var icol int
+	rows := []row{}
+	for _, node := range pan.Children() {
+		// Ignore invisible child
+		child := node.(IPanel).GetPanel()
 		if !child.Visible() {
 			continue
 		}
-		// Ignore if no layout params
-		if child.layoutParams == nil {
-			continue
-		}
-		// Checks layout params
-		params, ok := child.layoutParams.(*GridLayoutParams)
-		if !ok {
-			panic("layoutParams is not GridLayoutParams")
+		// Checks child layout params, if supplied
+		ip := child.layoutParams
+		var params *GridLayoutParams
+		var ok bool
+		var paramsDef bool
+		if ip != nil {
+			params, ok = child.layoutParams.(*GridLayoutParams)
+			if !ok {
+				panic("layoutParams is not GridLayoutParams")
+			}
+			paramsDef = false
+		} else {
+			params = &GridLayoutParams{}
+			paramsDef = true
+
 		}
-		if params.Row >= rows {
-			rows = params.Row + 1
+		// If first column, creates row and appends to rows
+		if icol == 0 {
+			var r row
+			r.cells = make([]*cell, len(g.columns))
+			rows = append(rows, r)
 		}
-		if params.Col >= cols {
-			cols = params.Col + 1
+		// Set current child panel to current cells
+		rows[irow].cells[icol] = &cell{child, *params, paramsDef}
+		// Updates next cell column and row
+		icol += 1 + params.ColSpan
+		if icol >= len(g.columns) {
+			irow++
+			icol = 0
 		}
-		items = append(items, element{child, params})
 	}
-	// Check limits
-	if rows > 100 {
-		panic("Element row outsize limits")
+
+	// Sets the height of each row to the height of the heightest child
+	// Sets the width of each column to the width of the widest column
+	colWidths := make([]float32, len(g.columns))
+	spanWidths := make([]float32, len(g.columns))
+	for i := 0; i < len(rows); i++ {
+		r := &rows[i]
+		r.height = 0
+		for ci, cell := range r.cells {
+			if cell == nil {
+				continue
+			}
+			if cell.panel.Height() > r.height {
+				r.height = cell.panel.Height()
+			}
+			// If this cell span columns compare with other span cell widths
+			if cell.params.ColSpan > 0 {
+				if cell.panel.Width() > spanWidths[ci] {
+					spanWidths[ci] = cell.panel.Width()
+				}
+			} else {
+				if cell.panel.Width() > colWidths[ci] {
+					colWidths[ci] = cell.panel.Width()
+				}
+			}
+		}
 	}
-	if cols > 100 {
-		panic("Element column outsize limits")
+	// The final width for each column is the maximum no span column width
+	// but if it is zero, is the maximum span column width
+	for i := 0; i < len(colWidths); i++ {
+		if colWidths[i] == 0 {
+			colWidths[i] = spanWidths[i]
+		}
 	}
 
-	// Determine row and column maximum sizes
-	colSizes := make([]int, cols)
-	rowSizes := make([]int, rows)
-	for _, el := range items {
-		width := el.panel.Width()
-		height := el.panel.Height()
-		if int(width) > colSizes[el.params.Col] {
-			colSizes[el.params.Col] = int(width)
+	// If expand horizontally set, distribute available space between all columns
+	if g.expandh {
+		var twidth float32
+		for i := 0; i < len(colWidths); i++ {
+			twidth += colWidths[i]
 		}
-		if int(height) > rowSizes[el.params.Row] {
-			rowSizes[el.params.Row] = int(height)
+		space := pan.ContentWidth() - twidth
+		if space > 0 {
+			colspace := space / float32(len(colWidths))
+			for i := 0; i < len(colWidths); i++ {
+				colWidths[i] += colspace
+			}
 		}
 	}
 
-	// Determine row and column starting positions
-	colStart := make([]int, cols)
-	rowStart := make([]int, rows)
-	for i := 1; i < len(colSizes); i++ {
-		colStart[i] = colStart[i-1] + colSizes[i-1]
-	}
-	for i := 1; i < len(rowSizes); i++ {
-		rowStart[i] = rowStart[i-1] + rowSizes[i-1]
+	// If expand vertically set, distribute available space between all rows
+	if g.expandv {
+		// Calculates the sum of all row heights
+		var theight float32
+		for _, r := range rows {
+			theight += r.height
+		}
+		// If space available distribute between all rows
+		space := pan.ContentHeight() - theight
+		if space > 0 {
+			rowspace := space / float32(len(rows))
+			for i := 0; i < len(rows); i++ {
+				rows[i].height += rowspace
+			}
+		}
 	}
 
-	// Position the elements
-	for _, el := range items {
-		row := el.params.Row
-		col := el.params.Col
-		cellHeight := rowSizes[row]
-		// Current cell width
-		cellWidth := 0
-		for c := 0; c <= el.params.ColSpan; c++ {
-			pos := col + c
-			if pos >= len(colSizes) {
-				break
+	// Position each child panel in the parent panel
+	var celly float32
+	for _, r := range rows {
+		var cellx float32
+		for ci, cell := range r.cells {
+			if cell == nil {
+				continue
 			}
-			cellWidth += colSizes[pos]
-		}
-		rstart := float32(rowStart[row])
-		cstart := float32(colStart[col])
-		// Horizontal alignment
-		var dx float32 = 0
-		switch el.params.AlignH {
-		case AlignNone:
-		case AlignLeft:
-		case AlignRight:
-			dx = float32(cellWidth) - el.panel.width
-		case AlignCenter:
-			dx = (float32(cellWidth) - el.panel.width) / 2
-		default:
-			panic("Invalid horizontal alignment")
-		}
-		// Vertical alignment
-		var dy float32 = 0
-		switch el.params.AlignV {
-		case AlignNone:
-		case AlignTop:
-		case AlignBottom:
-			dy = float32(cellHeight) - el.panel.height
-		case AlignCenter:
-			dy = (float32(cellHeight) - el.panel.height) / 2
-		default:
-			panic("Invalid vertical alignment")
+			colspan := 0
+			// Default grid cell alignment
+			alignv := g.alignv
+			alignh := g.alignh
+			// If column has alignment, use them
+			if g.columns[ci].alignv != nil {
+				alignv = *g.columns[ci].alignv
+			}
+			if g.columns[ci].alignh != nil {
+				alignh = *g.columns[ci].alignh
+			}
+			// If cell has layout parameters, use them
+			if !cell.paramsDef {
+				alignh = cell.params.AlignH
+				alignv = cell.params.AlignV
+				colspan = cell.params.ColSpan
+			}
+			// Calculates the available width for the cell considering colspan
+			var cellWidth float32
+			for i := ci; i < ci+colspan+1; i++ {
+				if i >= len(colWidths) {
+					break
+				}
+				cellWidth += colWidths[i]
+			}
+			// Determines child panel horizontal position
+			px := cellx
+			switch alignh {
+			case AlignNone:
+			case AlignLeft:
+			case AlignRight:
+				space := cellWidth - cell.panel.Width()
+				if space > 0 {
+					px += space
+				}
+			case AlignCenter:
+				space := (cellWidth - cell.panel.Width()) / 2
+				if space > 0 {
+					px += space
+				}
+			default:
+				panic("Invalid horizontal alignment")
+			}
+			// Determines child panel vertical position
+			py := celly
+			switch alignv {
+			case AlignNone:
+			case AlignTop:
+			case AlignBottom:
+				space := r.height - cell.panel.Height()
+				if space > 0 {
+					py += space
+				}
+			case AlignCenter:
+				space := (r.height - cell.panel.Height()) / 2
+				if space > 0 {
+					py += space
+				}
+			default:
+				panic("Invalid vertical alignment")
+			}
+			// Sets child panel position
+			cell.panel.SetPosition(px, py)
+			// Advances to next row cell considering colspan
+			cellx += cellWidth
 		}
-		el.panel.SetPosition(cstart+dx, rstart+dy)
+		celly += r.height
 	}
 }

+ 99 - 11
gui/hboxlayout.go

@@ -4,13 +4,37 @@
 
 package gui
 
+// HBoxLayout implements a panel layout which arranges the panel children horizontally.
+// The children can be separated by a space in pixels set by SetSpacing().
+// The whole group of children can be aligned horizontally by SetAlignH() which can
+// accept the following types of alignment:
+//
+// 	AlignLeft: Try to align the group of children to the left if the panel width is
+// 	greater the the sum of the children widths + spacing.
+//
+// 	AlignRight: Try to align the group of children to the right if the panel width is
+// 	greater the the sum of the children widths + spacing.
+//
+// 	AlignCenter: Try to align the group of children in the center if the panel width is
+// 	greater the the sum of the children widths + spacing.
+//
+// 	AlignWidth - Try to align the individual children with the same same space between each other.
+// 	Each individual child can be aligned vertically by SetLayoutParameters()
+//
+// If the layout method SetAutoHeight(true) is called, the panel minimum content height will be the
+// height of the child with the largest height.
+//
+// If the layout method SetAutoWidth(true) is called, the panel minimum content width will be the
+// sum of its children's widths plus the spacing.
 type HBoxLayout struct {
-	pan     IPanel
-	spacing float32 // horizontal spacing between the children in pixels.
-	alignH  Align   // horizontal alignment of the whole block of children
+	pan        IPanel
+	spacing    float32
+	alignH     Align
+	autoHeight bool
+	minHeight  bool
 }
 
-// Parameters for individual children
+// HBoxLayoutParams specify the vertical alignment of each individual child.
 type HBoxLayoutParams struct {
 	Expand float32 // item expand horizontally factor (0 - no expand)
 	AlignV Align   // item vertical alignment
@@ -34,7 +58,7 @@ func (bl *HBoxLayout) SetSpacing(spacing float32) {
 }
 
 // SetAlignH sets the horizontal alignment of the whole group of items
-// inside the parent panel and updates the layout if possible.
+// inside the parent panel and updates the layout.
 // This only has any effect if there are no expanded items.
 func (bl *HBoxLayout) SetAlignH(align Align) {
 
@@ -42,6 +66,22 @@ func (bl *HBoxLayout) SetAlignH(align Align) {
 	bl.Recalc(bl.pan)
 }
 
+// SetAutoHeight sets if the panel minimum height should be the height of
+// the largest of its children's height.
+func (bl *HBoxLayout) SetAutoHeight(state bool) {
+
+	bl.autoHeight = state
+	bl.Recalc(bl.pan)
+}
+
+// SetAutoWidth sets if the panel minimum width should be sum of its
+// children's width plus the spacing
+func (bl *HBoxLayout) SetAutoWidth(state bool) {
+
+	bl.minHeight = state
+	bl.Recalc(bl.pan)
+}
+
 // Recalc recalculates and sets the position and sizes of all children
 func (bl *HBoxLayout) Recalc(ipan IPanel) {
 
@@ -55,16 +95,55 @@ func (bl *HBoxLayout) Recalc(ipan IPanel) {
 		return
 	}
 
+	// If autoHeight is set, get the maximum height of all the panel's children
+	// and if the panel content height is less than this maximum, set its content height to this value.
+	if bl.autoHeight {
+		var maxHeight float32
+		for _, ichild := range parent.Children() {
+			child := ichild.(IPanel).GetPanel()
+			if !child.Visible() {
+				continue
+			}
+			if child.Height() > maxHeight {
+				maxHeight = child.Height()
+			}
+		}
+		if parent.ContentHeight() < maxHeight {
+			parent.setContentSize(parent.ContentWidth(), maxHeight, false)
+		}
+	}
+
+	// If minHeight is set, get the sum of widths of this panel's children plus the spacings.
+	// If the panel content width is less than this width, set its content width to this value.
+	if bl.minHeight {
+		var totalWidth float32
+		for _, ichild := range parent.Children() {
+			child := ichild.(IPanel).GetPanel()
+			if !child.Visible() {
+				continue
+			}
+			totalWidth += child.Width()
+		}
+		// Adds spacing
+		totalWidth += bl.spacing * float32(len(parent.Children())-1)
+		if parent.ContentWidth() < totalWidth {
+			parent.setContentSize(totalWidth, parent.ContentHeight(), false)
+		}
+	}
+
 	// Calculates the total width, expanded width, fixed width and
 	// the sum of the expand factor for all items.
-	var twidth float32 = 0
-	var ewidth float32 = 0
-	var fwidth float32 = 0
-	var texpand float32 = 0
+	var twidth float32
+	var ewidth float32
+	var fwidth float32
+	var texpand float32
 	ecount := 0
 	paramsDef := HBoxLayoutParams{Expand: 0, AlignV: AlignTop}
 	for pos, obj := range parent.Children() {
 		pan := obj.(IPanel).GetPanel()
+		if !pan.Visible() {
+			continue
+		}
 		// Get item layout parameters or use default
 		params := paramsDef
 		if pan.layoutParams != nil {
@@ -94,13 +173,16 @@ func (bl *HBoxLayout) Recalc(ipan IPanel) {
 
 	// If there is at least on expanded item, all free space will be occupied
 	spaceMiddle := bl.spacing
-	var posX float32 = 0
+	var posX float32
 	if texpand > 0 {
 		// If there is free space, distribute space between expanded items
 		totalSpace := parent.ContentWidth() - twidth
 		if totalSpace > 0 {
 			for _, obj := range parent.Children() {
 				pan := obj.(IPanel).GetPanel()
+				if !pan.Visible() {
+					continue
+				}
 				// Get item layout parameters or use default
 				params := paramsDef
 				if pan.layoutParams != nil {
@@ -115,6 +197,9 @@ func (bl *HBoxLayout) Recalc(ipan IPanel) {
 		} else {
 			for _, obj := range parent.Children() {
 				pan := obj.(IPanel).GetPanel()
+				if !pan.Visible() {
+					continue
+				}
 				// Get item layout parameters or use default
 				params := paramsDef
 				if pan.layoutParams != nil {
@@ -155,6 +240,9 @@ func (bl *HBoxLayout) Recalc(ipan IPanel) {
 	height := parent.ContentHeight()
 	for pos, obj := range parent.Children() {
 		pan := obj.(IPanel).GetPanel()
+		if !pan.Visible() {
+			continue
+		}
 		// Get item layout parameters or use default
 		params := paramsDef
 		if pan.layoutParams != nil {
@@ -162,7 +250,7 @@ func (bl *HBoxLayout) Recalc(ipan IPanel) {
 		}
 		cheight := pan.Height()
 		switch params.AlignV {
-		case AlignTop:
+		case AlignNone, AlignTop:
 			posY = 0
 		case AlignCenter:
 			posY = (height - cheight) / 2

+ 12 - 12
gui/image_button.go

@@ -11,14 +11,14 @@ import (
 )
 
 type ImageButton struct {
-	*Panel                            // Embedded Panel
-	label       *Label                // Label panel
-	iconLabel   bool                  // True if icon
-	image       *Image                // pointer to button image (may be nil)
-	styles      *ImageButtonStyles    // pointer to current button styles
-	mouseOver   bool                  // true if mouse is over button
-	pressed     bool                  // true if button is pressed
-	stateImages [ButtonDisabled+1]*texture.Texture2D // array of images for each button state
+	*Panel                                             // Embedded Panel
+	label       *Label                                 // Label panel
+	iconLabel   bool                                   // True if icon
+	image       *Image                                 // pointer to button image (may be nil)
+	styles      *ImageButtonStyles                     // pointer to current button styles
+	mouseOver   bool                                   // true if mouse is over button
+	pressed     bool                                   // true if button is pressed
+	stateImages [ButtonDisabled + 1]*texture.Texture2D // array of images for each button state
 }
 
 type ButtonState int
@@ -54,7 +54,7 @@ type ImageButtonStyles struct {
 func NewImageButton(normalImgPath string) (*ImageButton, error) {
 
 	b := new(ImageButton)
-	b.styles = &StyleDefault.ImageButton
+	b.styles = &StyleDefault().ImageButton
 
 	tex, err := texture.NewTexture2DFromImage(normalImgPath)
 	if err != nil {
@@ -106,7 +106,7 @@ func (b *ImageButton) SetText(text string) {
 }
 
 // SetIcon sets the icon
-func (b *ImageButton) SetIcon(icode int) {
+func (b *ImageButton) SetIcon(icode string) {
 
 	if b.iconLabel == false && b.label != nil {
 		b.Panel.Remove(b.label)
@@ -117,10 +117,10 @@ func (b *ImageButton) SetIcon(icode int) {
 	b.iconLabel = true
 	if b.label == nil {
 		// Create icon
-		b.label = NewIconLabel(string(icode))
+		b.label = NewLabel(icode, true)
 		b.Panel.Add(b.label)
 	} else {
-		b.label.SetText(string(icode))
+		b.label.SetText(icode)
 	}
 	b.recalc()
 }

+ 6 - 7
gui/imagelabel.go

@@ -21,12 +21,12 @@ import (
 
 ****************************************/
 
+// ImageLabel is a panel which can contain an Image or Icon plus a Label side by side.
 type ImageLabel struct {
 	Panel        // Embedded panel
 	label Label  // internal label
 	image *Image // optional internal image
 	icon  *Label // optional internal icon label
-	icode int    // icon code (if icon is set)
 }
 
 // ImageLabel style
@@ -49,7 +49,7 @@ func NewImageLabel(text string) *ImageLabel {
 	il.Panel.Subscribe(OnResize, func(evname string, ev interface{}) { il.recalc() })
 
 	// Initializes the label
-	il.label.initialize(text, StyleDefault.Font)
+	il.label.initialize(text, StyleDefault().Font)
 	il.label.Subscribe(OnResize, func(evname string, ev interface{}) { il.recalc() })
 	il.Panel.Add(&il.label)
 
@@ -71,19 +71,18 @@ func (il *ImageLabel) Text() string {
 
 // SetIcon sets the image label icon from the default Icon font.
 // If there is currently a selected image, it is removed
-func (il *ImageLabel) SetIcon(icode int) {
+func (il *ImageLabel) SetIcon(icon string) {
 
 	if il.image != nil {
 		il.Panel.Remove(il.image)
 		il.image = nil
 	}
 	if il.icon == nil {
-		il.icon = NewIconLabel(string(icode))
+		il.icon = NewLabel(icon, true)
 		il.icon.SetFontSize(il.label.FontSize() * 1.4)
 		il.Panel.Add(il.icon)
 	}
-	il.icon.SetText(string(icode))
-	il.icode = icode
+	il.icon.SetText(icon)
 	il.recalc()
 }
 
@@ -184,7 +183,7 @@ func (il *ImageLabel) CopyFields(other *ImageLabel) {
 
 	il.label.SetText(other.label.Text())
 	if other.icon != nil {
-		il.SetIcon(other.icode)
+		il.SetIcon(other.icon.Text())
 	}
 	if other.image != nil {
 		// TODO li.SetImage(other.image.Clone())

+ 41 - 20
gui/label.go

@@ -11,6 +11,8 @@ import (
 	"github.com/g3n/engine/texture"
 )
 
+// Label is a panel which contains a texture for rendering text
+// The content size of the label panel is the exact size of texture
 type Label struct {
 	Panel       // Embedded panel
 	fontSize    float64
@@ -24,20 +26,16 @@ type Label struct {
 }
 
 // NewLabel creates and returns a label panel with the specified text
-// drawn using the current default font.
-func NewLabel(msg string) *Label {
+// drawn using the current default text font.
+// If icon is true the text is drawn using the default icon font
+func NewLabel(msg string, icon ...bool) *Label {
 
 	l := new(Label)
-	l.initialize(msg, StyleDefault.Font)
-	return l
-}
-
-// NewIconLabel creates and returns a label panel using the specified text
-// drawn using the default icon font.
-func NewIconLabel(msg string) *Label {
-
-	l := new(Label)
-	l.initialize(msg, StyleDefault.FontIcon)
+	if len(icon) > 0 && icon[0] {
+		l.initialize(msg, StyleDefault().FontIcon)
+	} else {
+		l.initialize(msg, StyleDefault().Font)
+	}
 	return l
 }
 
@@ -51,17 +49,17 @@ func (l *Label) initialize(msg string, font *text.Font) {
 	l.fontDPI = 72
 	l.lineSpacing = 1.0
 	l.bgColor = math32.Color4{0, 0, 0, 0}
-	l.fgColor = math32.Black4
+	l.fgColor = math32.Color4{0, 0, 0, 1}
 	l.SetText(msg)
 }
 
 // SetText draws the label text using the current font
 func (l *Label) SetText(msg string) {
 
-	// Do not allow empty labels
-	str := msg
-	if len(msg) == 0 {
-		str = " "
+	// Need at least a character to get dimensions
+	l.currentText = msg
+	if msg == "" {
+		msg = " "
 	}
 
 	// Set font properties
@@ -72,11 +70,11 @@ func (l *Label) SetText(msg string) {
 	l.font.SetFgColor4(&l.fgColor)
 
 	// Measure text
-	width, height := l.font.MeasureText(str)
+	width, height := l.font.MeasureText(msg)
 	// Create image canvas with the exact size of the texture
 	// and draw the text.
 	canvas := text.NewCanvas(width, height, &l.bgColor)
-	canvas.DrawText(0, 0, str, l.font)
+	canvas.DrawText(0, 0, msg, l.font)
 
 	// Creates texture if if doesnt exist.
 	if l.tex == nil {
@@ -91,7 +89,6 @@ func (l *Label) SetText(msg string) {
 
 	// Updates label panel dimensions
 	l.Panel.SetContentSize(float32(width), float32(height))
-	l.currentText = str
 }
 
 // Text returns the current label text
@@ -148,6 +145,13 @@ func (l *Label) BgColor() math32.Color4 {
 	return l.bgColor
 }
 
+// SetFont sets this label text or icon font
+func (l *Label) SetFont(f *text.Font) {
+
+	l.font = f
+	l.SetText(l.currentText)
+}
+
 // SetFontSize sets label font size
 func (l *Label) SetFontSize(size float64) *Label {
 
@@ -162,6 +166,23 @@ func (l *Label) FontSize() float64 {
 	return l.fontSize
 }
 
+// SetFontDPI sets the font dots per inch
+func (l *Label) SetFontDPI(dpi float64) *Label {
+
+	l.fontDPI = dpi
+	l.SetText(l.currentText)
+	return l
+}
+
+// SetLineSpacing sets the spacing between lines.
+// The default value is 1.0
+func (l *Label) SetLineSpacing(spacing float64) *Label {
+
+	l.lineSpacing = spacing
+	l.SetText(l.currentText)
+	return l
+}
+
 // setTextCaret sets the label text and draws a caret at the
 // specified line and column.
 // It is normally used by the Edit widget.

+ 1 - 1
gui/list.go

@@ -79,7 +79,7 @@ func newList(vert bool, width, height float32) *List {
 
 func (li *List) initialize(vert bool, width, height float32) {
 
-	li.styles = &StyleDefault.List
+	li.styles = &StyleDefault().List
 	li.single = true
 
 	li.Scroller.initialize(vert, width, height)

+ 5 - 5
gui/menu.go

@@ -5,7 +5,7 @@
 package gui
 
 import (
-	"github.com/g3n/engine/gui/assets"
+	"github.com/g3n/engine/gui/assets/icon"
 	"github.com/g3n/engine/math32"
 	"github.com/g3n/engine/window"
 	"time"
@@ -158,7 +158,7 @@ func NewMenu() *Menu {
 
 	m := new(Menu)
 	m.Panel.Initialize(0, 0)
-	m.styles = &StyleDefault.Menu
+	m.styles = &StyleDefault().Menu
 	m.items = make([]*MenuItem, 0)
 	m.Panel.Subscribe(OnCursorEnter, m.onCursor)
 	m.Panel.Subscribe(OnCursor, m.onCursor)
@@ -206,7 +206,7 @@ func (m *Menu) AddMenu(text string, subm *Menu) *MenuItem {
 	mi.submenu.autoOpen = true
 	mi.menu = m
 	if !m.bar {
-		mi.ricon = NewIconLabel(string(assets.PlayArrow))
+		mi.ricon = NewLabel(string(icon.PlayArrow), true)
 		mi.Panel.Add(mi.ricon)
 	}
 	mi.Panel.Add(mi.submenu)
@@ -596,7 +596,7 @@ func newMenuItem(text string, styles *MenuItemStyles) *MenuItem {
 
 // SetIcon sets the left icon of this menu item
 // If an image was previously set it is replaced by this icon
-func (mi *MenuItem) SetIcon(icode int) *MenuItem {
+func (mi *MenuItem) SetIcon(icon string) *MenuItem {
 
 	// Remove and dispose previous icon
 	if mi.licon != nil {
@@ -605,7 +605,7 @@ func (mi *MenuItem) SetIcon(icode int) *MenuItem {
 		mi.licon = nil
 	}
 	// Sets the new icon
-	mi.licon = NewIconLabel(string(icode))
+	mi.licon = NewLabel(icon, true)
 	mi.Panel.Add(mi.licon)
 	mi.update()
 	return mi

+ 43 - 21
gui/panel.go

@@ -46,11 +46,12 @@ type IPanel interface {
 	SetRoot(*Root)
 	LostKeyFocus()
 	TotalHeight() float32
+	SetLayout(ILayout)
 }
 
 // Panel is 2D rectangular graphic which by default has a quad (2 triangles) geometry.
 // When using the default geometry, a panel has margins, borders, paddings
-// and a content area. The content area can be associated wit a texture
+// and a content area. The content area can be associated with a texture
 // It is the building block of most GUI widgets.
 type Panel struct {
 	*graphic.Graphic                    // Embedded graphic
@@ -148,7 +149,7 @@ func (p *Panel) Initialize(width, height float32) {
 	p.udata.bordersColor = math32.Color4{0, 0, 0, 1}
 	p.bounded = true
 	p.enabled = true
-	p.resize(width, height)
+	p.resize(width, height, true)
 }
 
 // InitializeGraphic initializes this panel with a different graphic
@@ -166,7 +167,7 @@ func (p *Panel) InitializeGraphic(width, height float32, gr *graphic.Graphic) {
 	p.udata.bordersColor = math32.Color4{0, 0, 0, 1}
 	p.bounded = true
 	p.enabled = true
-	p.resize(width, height)
+	p.resize(width, height, true)
 }
 
 // GetPanel satisfies the IPanel interface and
@@ -244,7 +245,7 @@ func (p *Panel) SetSize(width, height float32) {
 		log.Warn("Invalid panel height:%v", height)
 		height = 0
 	}
-	p.resize(width, height)
+	p.resize(width, height, true)
 }
 
 // SetWidth sets this panel external width in pixels.
@@ -314,7 +315,7 @@ func (p *Panel) ContentHeight() float32 {
 func (p *Panel) SetMargins(top, right, bottom, left float32) {
 
 	p.marginSizes.Set(top, right, bottom, left)
-	p.resize(p.calcWidth(), p.calcHeight())
+	p.resize(p.calcWidth(), p.calcHeight(), true)
 }
 
 // SetMarginsFrom sets this panel margins sizes from the specified
@@ -322,7 +323,7 @@ func (p *Panel) SetMargins(top, right, bottom, left float32) {
 func (p *Panel) SetMarginsFrom(src *BorderSizes) {
 
 	p.marginSizes = *src
-	p.resize(p.calcWidth(), p.calcHeight())
+	p.resize(p.calcWidth(), p.calcHeight(), true)
 }
 
 // Margins returns the current margin sizes in pixels
@@ -336,7 +337,7 @@ func (p *Panel) Margins() BorderSizes {
 func (p *Panel) SetBorders(top, right, bottom, left float32) {
 
 	p.borderSizes.Set(top, right, bottom, left)
-	p.resize(p.calcWidth(), p.calcHeight())
+	p.resize(p.calcWidth(), p.calcHeight(), true)
 }
 
 // SetBordersFrom sets this panel border sizes from the specified
@@ -344,7 +345,7 @@ func (p *Panel) SetBorders(top, right, bottom, left float32) {
 func (p *Panel) SetBordersFrom(src *BorderSizes) {
 
 	p.borderSizes = *src
-	p.resize(p.calcWidth(), p.calcHeight())
+	p.resize(p.calcWidth(), p.calcHeight(), true)
 }
 
 // Borders returns this panel current border sizes
@@ -357,7 +358,7 @@ func (p *Panel) Borders() BorderSizes {
 func (p *Panel) SetPaddings(top, right, bottom, left float32) {
 
 	p.paddingSizes.Set(top, right, bottom, left)
-	p.resize(p.calcWidth(), p.calcHeight())
+	p.resize(p.calcWidth(), p.calcHeight(), true)
 }
 
 // SetPaddingsFrom sets this panel padding sizes from the specified
@@ -365,7 +366,7 @@ func (p *Panel) SetPaddings(top, right, bottom, left float32) {
 func (p *Panel) SetPaddingsFrom(src *BorderSizes) {
 
 	p.paddingSizes = *src
-	p.resize(p.calcWidth(), p.calcHeight())
+	p.resize(p.calcWidth(), p.calcHeight(), true)
 }
 
 // Paddings returns this panel padding sizes in pixels
@@ -426,16 +427,7 @@ func (p *Panel) Color4() math32.Color4 {
 // the new content size.
 func (p *Panel) SetContentSize(width, height float32) {
 
-	// Calculates the new desired external width and height
-	eWidth := width +
-		p.paddingSizes.Left + p.paddingSizes.Right +
-		p.borderSizes.Left + p.borderSizes.Right +
-		p.marginSizes.Left + p.marginSizes.Right
-	eHeight := height +
-		p.paddingSizes.Top + p.paddingSizes.Bottom +
-		p.borderSizes.Top + p.borderSizes.Bottom +
-		p.marginSizes.Top + p.marginSizes.Bottom
-	p.resize(eWidth, eHeight)
+	p.setContentSize(width, height, true)
 }
 
 // SetContentWidth sets this panel content width to the specified dimension in pixels.
@@ -592,6 +584,12 @@ func (p *Panel) SetLayoutParams(params interface{}) {
 	p.layoutParams = params
 }
 
+// LayoutParams returns this panel current layout parameters
+func (p *Panel) LayoutParams() interface{} {
+
+	return p.layoutParams
+}
+
 // ContentCoords converts the specified window absolute coordinates in pixels
 // (as informed by OnMouse event) to this panel internal content area pixel coordinates
 func (p *Panel) ContentCoords(wx, wy float32) (float32, float32) {
@@ -635,6 +633,24 @@ func (p *Panel) Pix2NDC(px, py float32) (nx, ny float32) {
 	return px / w, -py / h
 }
 
+// setContentSize is an internal version of SetContentSize() which allows
+// to determine if the panel will recalculate its layout and dispatch event.
+// It is normally used by layout managers when setting the panel content size
+// to avoid another invokation of the layout manager.
+func (p *Panel) setContentSize(width, height float32, dispatch bool) {
+
+	// Calculates the new desired external width and height
+	eWidth := width +
+		p.paddingSizes.Left + p.paddingSizes.Right +
+		p.borderSizes.Left + p.borderSizes.Right +
+		p.marginSizes.Left + p.marginSizes.Right
+	eHeight := height +
+		p.paddingSizes.Top + p.paddingSizes.Bottom +
+		p.borderSizes.Top + p.borderSizes.Bottom +
+		p.marginSizes.Top + p.marginSizes.Bottom
+	p.resize(eWidth, eHeight, dispatch)
+}
+
 // setZ sets the Z coordinate for this panel and its children recursively
 // starting at the specified z and zunb coordinates.
 // The z coordinate is used for bound panels and zunb for unbounded panels.
@@ -772,7 +788,9 @@ func (p *Panel) calcHeight() float32 {
 // The margins, borders and padding sizes are kept and the content
 // area size is adjusted. So if the panel is decreased, its minimum
 // size is determined by the margins, borders and paddings.
-func (p *Panel) resize(width, height float32) {
+// Normally it should be called with dispatch=true to recalculate the
+// panel layout and dispatch OnSize event.
+func (p *Panel) resize(width, height float32, dispatch bool) {
 
 	var padding Rect
 	var border Rect
@@ -836,7 +854,11 @@ func (p *Panel) resize(width, height float32) {
 		float32(p.content.Width) / float32(p.width),
 		float32(p.content.Height) / float32(p.height),
 	}
+
 	// Update layout and dispatch event
+	if !dispatch {
+		return
+	}
 	if p.layout != nil {
 		p.layout.Recalc(p)
 	}

+ 1 - 1
gui/scrollbar.go

@@ -78,7 +78,7 @@ func newScrollBar(width, height float32, vertical bool) *ScrollBar {
 // initialize initializes this scrollbar
 func (sb *ScrollBar) initialize(width, height float32, vertical bool) {
 
-	sb.style = &StyleDefault.ScrollBar
+	sb.style = &StyleDefault().ScrollBar
 	sb.vertical = vertical
 	sb.Panel.Initialize(width, height)
 	sb.Panel.Subscribe(OnMouseDown, sb.onMouse)

+ 5 - 5
gui/scroller.go

@@ -258,13 +258,13 @@ func (s *Scroller) SetStyles(ss *ScrollerStyles) {
 func (s *Scroller) ApplyStyle(style int) {
 
 	switch style {
-	case OverStyle:
+	case StyleOver:
 		s.applyStyle(&s.styles.Over)
-	case FocusStyle:
+	case StyleFocus:
 		s.applyStyle(&s.styles.Focus)
-	case NormalStyle:
+	case StyleNormal:
 		s.applyStyle(&s.styles.Normal)
-	case DefaultStyle:
+	case StyleDef:
 		s.update()
 	}
 }
@@ -284,7 +284,7 @@ func (s *Scroller) initialize(vert bool, width, height float32) {
 
 	s.vert = vert
 	s.Panel.Initialize(width, height)
-	s.styles = &StyleDefault.Scroller
+	s.styles = &StyleDefault().Scroller
 
 	s.Panel.Subscribe(OnCursorEnter, s.onCursor)
 	s.Panel.Subscribe(OnCursorLeave, s.onCursor)

+ 1 - 1
gui/slider.go

@@ -73,7 +73,7 @@ func newSlider(horiz bool, width, height float32) *Slider {
 
 	s := new(Slider)
 	s.horiz = horiz
-	s.styles = &StyleDefault.Slider
+	s.styles = &StyleDefault().Slider
 	s.scaleFactor = 1.0
 
 	// Initialize main panel

+ 1 - 1
gui/splitter.go

@@ -54,7 +54,7 @@ func newSplitter(horiz bool, width, height float32) *Splitter {
 
 	s := new(Splitter)
 	s.horiz = horiz
-	s.styles = &StyleDefault.Splitter
+	s.styles = &StyleDefault().Splitter
 	s.Panel.Initialize(width, height)
 
 	// Initialize left/top panel

+ 5 - 805
gui/style.go

@@ -5,19 +5,9 @@
 package gui
 
 import (
-	"github.com/g3n/engine/gui/assets"
-	"github.com/g3n/engine/math32"
 	"github.com/g3n/engine/text"
 )
 
-func init() {
-
-	setupDefaultStyle()
-}
-
-// Pointer to default style
-var StyleDefault *Style
-
 // All styles
 type Style struct {
 	Font          *text.Font
@@ -41,799 +31,9 @@ type Style struct {
 }
 
 const (
-	defaultFont     = "fonts/FreeSans.ttf"
-	defaultFontBold = "fonts/FreeSansBold.ttf"
-	defaultFontIcon = "fonts/MaterialIcons-Regular.ttf"
+	StyleOver = iota + 1
+	StyleFocus
+	StyleDisabled
+	StyleNormal
+	StyleDef
 )
-
-const (
-	OverStyle = iota + 1
-	FocusStyle
-	DisabledStyle
-	NormalStyle
-	DefaultStyle
-)
-
-// setupDefaultStyle initializes the default Gui global styles
-func setupDefaultStyle() {
-
-	StyleDefault = &Style{}
-
-	// Creates Default Font
-	fontData := assets.MustAsset(defaultFont)
-	font, err := text.NewFontFromData(fontData)
-	if err != nil {
-		panic(err)
-	}
-	font.SetLineSpacing(1.0)
-	font.SetSize(14)
-	font.SetDPI(72)
-	font.SetFgColor4(&math32.Color4{0, 0, 0, 1})
-	font.SetBgColor4(&math32.Color4{1, 1, 1, 0})
-	StyleDefault.Font = font
-
-	// Creates Icon Font
-	fontIconData := assets.MustAsset(defaultFontIcon)
-	fontIcon, err := text.NewFontFromData(fontIconData)
-	if err != nil {
-		panic(err)
-	}
-	fontIcon.SetLineSpacing(1.0)
-	fontIcon.SetSize(14)
-	fontIcon.SetDPI(72)
-	fontIcon.SetFgColor4(&math32.Color4{0, 0, 0, 1})
-	fontIcon.SetBgColor4(&math32.Color4{1, 1, 1, 1})
-	StyleDefault.FontIcon = fontIcon
-
-	borderSizes := BorderSizes{1, 1, 1, 1}
-	borderColor := math32.Color4{0, 0, 0, 1}
-	borderColorDis := math32.Color4{0.4, 0.4, 0.4, 1}
-
-	bgColor := math32.Color{0.85, 0.85, 0.85}
-	bgColor4 := math32.Color4{0, 0, 0, 0}
-	bgColorOver := math32.Color{0.9, 0.9, 0.9}
-	bgColor4Over := math32.Color4{1, 1, 1, 0.5}
-	bgColor4Sel := math32.Color4{0.6, 0.6, 0.6, 1}
-
-	fgColor := math32.Color{0, 0, 0}
-	fgColorSel := math32.Color{0, 0, 0}
-	fgColorDis := math32.Color{0.4, 0.4, 0.4}
-
-	// Button styles
-	StyleDefault.Button = ButtonStyles{
-		Normal: ButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{2, 4, 2, 4},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			FgColor:     fgColor,
-		},
-		Over: ButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{2, 4, 2, 4},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-		},
-		Focus: ButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{2, 4, 2, 4},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-		},
-		Pressed: ButtonStyle{
-			Border:      BorderSizes{2, 2, 2, 2},
-			Paddings:    BorderSizes{2, 4, 2, 4},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-		},
-		Disabled: ButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{2, 4, 2, 4},
-			BorderColor: borderColorDis,
-			BgColor:     bgColor,
-			FgColor:     fgColorDis,
-		},
-	}
-
-	// CheckRadio styles
-	StyleDefault.CheckRadio = CheckRadioStyles{
-		Normal: CheckRadioStyle{
-			Border:      BorderSizes{0, 0, 0, 0},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4,
-			FgColor:     fgColor,
-		},
-		Over: CheckRadioStyle{
-			Border:      BorderSizes{0, 0, 0, 0},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4Over,
-			FgColor:     fgColor,
-		},
-		Focus: CheckRadioStyle{
-			Border:      BorderSizes{0, 0, 0, 0},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4Over,
-			FgColor:     fgColor,
-		},
-		Disabled: CheckRadioStyle{
-			Border:      BorderSizes{0, 0, 0, 0},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4,
-			FgColor:     fgColorDis,
-		},
-	}
-
-	// Edit styles
-	StyleDefault.Edit = EditStyles{
-		Normal: EditStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			BgAlpha:     1.0,
-			FgColor:     fgColor,
-			HolderColor: math32.Color{0.4, 0.4, 0.4},
-		},
-		Over: EditStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			BgAlpha:     1.0,
-			FgColor:     fgColor,
-			HolderColor: math32.Color{0.4, 0.4, 0.4},
-		},
-		Focus: EditStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			BgAlpha:     1.0,
-			FgColor:     fgColor,
-			HolderColor: math32.Color{0.4, 0.4, 0.4},
-		},
-		Disabled: EditStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			BgAlpha:     1.0,
-			FgColor:     fgColorDis,
-			HolderColor: math32.Color{0.4, 0.4, 0.4},
-		},
-	}
-
-	// ScrollBar style
-	StyleDefault.ScrollBar = ScrollBarStyle{
-		Paddings:     BorderSizes{1, 1, 1, 1},
-		Borders:      BorderSizes{1, 1, 1, 1},
-		BordersColor: borderColor,
-		Color:        math32.Color{0.8, 0.8, 0.8},
-		Button: ScrollBarButtonStyle{
-			Borders:      BorderSizes{1, 1, 1, 1},
-			BordersColor: borderColor,
-			Color:        math32.Color{0.5, 0.5, 0.5},
-			Size:         30,
-		},
-	}
-
-	// Slider styles
-	StyleDefault.Slider = SliderStyles{
-		Normal: SliderStyle{
-			Border:      borderSizes,
-			BorderColor: borderColor,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BgColor:     math32.Color4{0.8, 0.8, 0.8, 1},
-			FgColor:     math32.Color4{0, 0.8, 0, 1},
-		},
-		Over: SliderStyle{
-			Border:      borderSizes,
-			BorderColor: borderColor,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BgColor:     math32.Color4{1, 1, 1, 1},
-			FgColor:     math32.Color4{0, 1, 0, 1},
-		},
-		Focus: SliderStyle{
-			Border:      borderSizes,
-			BorderColor: borderColor,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BgColor:     math32.Color4{1, 1, 1, 1},
-			FgColor:     math32.Color4{0, 1, 0, 1},
-		},
-		Disabled: SliderStyle{
-			Border:      borderSizes,
-			BorderColor: borderColor,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BgColor:     math32.Color4{0.8, 0.8, 0.8, 1},
-			FgColor:     math32.Color4{0, 0.8, 0, 1},
-		},
-	}
-
-	// Splitter styles
-	StyleDefault.Splitter = SplitterStyles{
-		Normal: SplitterStyle{
-			SpacerBorderColor: borderColor,
-			SpacerColor:       bgColor,
-			SpacerSize:        6,
-		},
-		Over: SplitterStyle{
-			SpacerBorderColor: borderColor,
-			SpacerColor:       bgColorOver,
-			SpacerSize:        6,
-		},
-		Drag: SplitterStyle{
-			SpacerBorderColor: borderColor,
-			SpacerColor:       bgColorOver,
-			SpacerSize:        6,
-		},
-	}
-
-	StyleDefault.Window = WindowStyles{
-		Normal: WindowStyle{
-			Border:           BorderSizes{4, 4, 4, 4},
-			Paddings:         BorderSizes{0, 0, 0, 0},
-			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
-			TitleBorders:     BorderSizes{0, 0, 1, 0},
-			TitleBorderColor: math32.Color4{0, 0, 0, 1},
-			TitleBgColor:     math32.Color4{0, 1, 0, 1},
-			TitleFgColor:     math32.Color4{0, 0, 0, 1},
-		},
-		Over: WindowStyle{
-			Border:           BorderSizes{4, 4, 4, 4},
-			Paddings:         BorderSizes{0, 0, 0, 0},
-			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
-			TitleBorders:     BorderSizes{0, 0, 1, 0},
-			TitleBorderColor: math32.Color4{0, 0, 0, 1},
-			TitleBgColor:     math32.Color4{0, 1, 0, 1},
-			TitleFgColor:     math32.Color4{0, 0, 0, 1},
-		},
-		Focus: WindowStyle{
-			Border:           BorderSizes{4, 4, 4, 4},
-			Paddings:         BorderSizes{0, 0, 0, 0},
-			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
-			TitleBorders:     BorderSizes{0, 0, 1, 0},
-			TitleBorderColor: math32.Color4{0, 0, 0, 1},
-			TitleBgColor:     math32.Color4{0, 1, 0, 1},
-			TitleFgColor:     math32.Color4{0, 0, 0, 1},
-		},
-		Disabled: WindowStyle{
-			Border:           BorderSizes{4, 4, 4, 4},
-			Paddings:         BorderSizes{0, 0, 0, 0},
-			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
-			TitleBorders:     BorderSizes{0, 0, 1, 0},
-			TitleBorderColor: math32.Color4{0, 0, 0, 1},
-			TitleBgColor:     math32.Color4{0, 1, 0, 1},
-			TitleFgColor:     math32.Color4{0, 0, 0, 1},
-		},
-	}
-
-	// Scroller styles
-	StyleDefault.Scroller = ScrollerStyles{
-		Normal: ScrollerStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			FgColor:     fgColor,
-		},
-		Over: ScrollerStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-		},
-		Focus: ScrollerStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-		},
-		Disabled: ScrollerStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			FgColor:     fgColor,
-		},
-	}
-
-	// List styles
-	StyleDefault.List = ListStyles{
-		Scroller: &ScrollerStyles{
-			Normal: ScrollerStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{0, 0, 0, 0},
-				BorderColor: borderColor,
-				BgColor:     bgColor,
-				FgColor:     fgColor,
-			},
-			Over: ScrollerStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{0, 0, 0, 0},
-				BorderColor: borderColor,
-				BgColor:     bgColorOver,
-				FgColor:     fgColor,
-			},
-			Focus: ScrollerStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{0, 0, 0, 0},
-				BorderColor: borderColor,
-				BgColor:     bgColorOver,
-				FgColor:     fgColor,
-			},
-			Disabled: ScrollerStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{0, 0, 0, 0},
-				BorderColor: borderColor,
-				BgColor:     bgColor,
-				FgColor:     fgColor,
-			},
-		},
-		Item: &ListItemStyles{
-			Normal: ListItemStyle{
-				Border:      BorderSizes{1, 0, 1, 0},
-				Paddings:    BorderSizes{0, 0, 0, 2},
-				BorderColor: math32.Color4{0, 0, 0, 0},
-				BgColor:     bgColor4,
-				FgColor:     fgColor,
-			},
-			Selected: ListItemStyle{
-				Border:      BorderSizes{1, 0, 1, 0},
-				Paddings:    BorderSizes{0, 0, 0, 2},
-				BorderColor: math32.Color4{0, 0, 0, 0},
-				BgColor:     bgColor4Sel,
-				FgColor:     fgColorSel,
-			},
-			Highlighted: ListItemStyle{
-				Border:      BorderSizes{1, 0, 1, 0},
-				Paddings:    BorderSizes{0, 0, 0, 2},
-				BorderColor: math32.Color4{0, 0, 0, 1},
-				BgColor:     bgColor4Over,
-				FgColor:     fgColor,
-			},
-			SelHigh: ListItemStyle{
-				Border:      BorderSizes{1, 0, 1, 0},
-				Paddings:    BorderSizes{0, 0, 0, 2},
-				BorderColor: math32.Color4{0, 0, 0, 1},
-				BgColor:     bgColor4Sel,
-				FgColor:     fgColorSel,
-			},
-		},
-	}
-
-	StyleDefault.DropDown = DropDownStyles{
-		Normal: &DropDownStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			FgColor:     fgColor,
-		},
-		Over: &DropDownStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-		},
-		Focus: &DropDownStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-		},
-		Disabled: &DropDownStyle{
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{0, 0, 0, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			FgColor:     fgColor,
-		},
-	}
-
-	StyleDefault.Folder = FolderStyles{
-		Normal: &FolderStyle{
-			Margins:     BorderSizes{0, 0, 0, 0},
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{2, 0, 2, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColor,
-			FgColor:     fgColor,
-			Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-		},
-		Over: &FolderStyle{
-			Margins:     BorderSizes{0, 0, 0, 0},
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{2, 0, 2, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-			Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-		},
-		Focus: &FolderStyle{
-			Margins:     BorderSizes{0, 0, 0, 0},
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-			Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-		},
-		Disabled: &FolderStyle{
-			Margins:     BorderSizes{0, 0, 0, 0},
-			Border:      BorderSizes{1, 1, 1, 1},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: borderColor,
-			BgColor:     bgColorOver,
-			FgColor:     fgColor,
-			Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-		},
-	}
-
-	StyleDefault.Tree = TreeStyles{
-		List: &ListStyles{
-			Scroller: &ScrollerStyles{
-				Normal: ScrollerStyle{
-					Border:      BorderSizes{1, 1, 1, 1},
-					Paddings:    BorderSizes{0, 0, 0, 0},
-					BorderColor: borderColor,
-					BgColor:     bgColor,
-					FgColor:     fgColor,
-				},
-				Over: ScrollerStyle{
-					Border:      BorderSizes{1, 1, 1, 1},
-					Paddings:    BorderSizes{0, 0, 0, 0},
-					BorderColor: borderColor,
-					BgColor:     bgColorOver,
-					FgColor:     fgColor,
-				},
-				Focus: ScrollerStyle{
-					Border:      BorderSizes{1, 1, 1, 1},
-					Paddings:    BorderSizes{0, 0, 0, 0},
-					BorderColor: borderColor,
-					BgColor:     bgColorOver,
-					FgColor:     fgColor,
-				},
-				Disabled: ScrollerStyle{
-					Border:      BorderSizes{1, 1, 1, 1},
-					Paddings:    BorderSizes{0, 0, 0, 0},
-					BorderColor: borderColor,
-					BgColor:     bgColor,
-					FgColor:     fgColor,
-				},
-			},
-			Item: &ListItemStyles{
-				Normal: ListItemStyle{
-					Border:      BorderSizes{1, 0, 1, 0},
-					Paddings:    BorderSizes{0, 0, 0, 2},
-					BorderColor: math32.Color4{0, 0, 0, 0},
-					BgColor:     bgColor4,
-					FgColor:     fgColor,
-				},
-				Selected: ListItemStyle{
-					Border:      BorderSizes{1, 0, 1, 0},
-					Paddings:    BorderSizes{0, 0, 0, 2},
-					BorderColor: math32.Color4{0, 0, 0, 0},
-					BgColor:     bgColor4Sel,
-					FgColor:     fgColorSel,
-				},
-				Highlighted: ListItemStyle{
-					Border:      BorderSizes{1, 0, 1, 0},
-					Paddings:    BorderSizes{0, 0, 0, 2},
-					BorderColor: math32.Color4{0, 0, 0, 1},
-					BgColor:     bgColor4Over,
-					FgColor:     fgColor,
-				},
-				SelHigh: ListItemStyle{
-					Border:      BorderSizes{1, 0, 1, 0},
-					Paddings:    BorderSizes{0, 0, 0, 2},
-					BorderColor: math32.Color4{0, 0, 0, 1},
-					BgColor:     bgColor4Sel,
-					FgColor:     fgColorSel,
-				},
-			},
-		},
-		Node: &TreeNodeStyles{
-			Normal: TreeNodeStyle{
-				Border:      BorderSizes{0, 0, 0, 0},
-				Paddings:    BorderSizes{0, 0, 0, 0},
-				BorderColor: borderColor,
-				BgColor:     bgColor4,
-				FgColor:     fgColor,
-				Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-			},
-		},
-		Padlevel: 16.0,
-	}
-
-	StyleDefault.ControlFolder = ControlFolderStyles{
-		Folder: &FolderStyles{
-			Normal: &FolderStyle{
-				Margins:     BorderSizes{0, 0, 0, 0},
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 0, 2, 2},
-				BorderColor: math32.Color4{0, 0, 0, 0},
-				BgColor:     math32.Color{0, 0.5, 1},
-				FgColor:     fgColor,
-				Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-			},
-			Over: &FolderStyle{
-				Margins:     BorderSizes{0, 0, 0, 0},
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 0, 2, 2},
-				BorderColor: math32.Color4{0, 0, 0, 0},
-				BgColor:     math32.Color{0, 0.5, 1},
-				FgColor:     fgColor,
-				Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-			},
-			Focus: &FolderStyle{
-				Margins:     BorderSizes{0, 0, 0, 0},
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 2, 2, 2},
-				BorderColor: math32.Color4{0, 0, 0, 0},
-				BgColor:     math32.Color{0, 0.5, 1},
-				FgColor:     fgColor,
-				Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-			},
-			Disabled: &FolderStyle{
-				Margins:     BorderSizes{0, 0, 0, 0},
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 2, 2, 2},
-				BorderColor: math32.Color4{0, 0, 0, 0},
-				BgColor:     math32.Color{0, 0.5, 1},
-				FgColor:     fgColor,
-				Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-			},
-		},
-		Tree: &TreeStyles{
-			List: &ListStyles{
-				Scroller: &ScrollerStyles{
-					Normal: ScrollerStyle{
-						Border:      BorderSizes{1, 1, 1, 1},
-						Paddings:    BorderSizes{0, 2, 0, 0},
-						BorderColor: borderColor,
-						BgColor:     bgColor,
-						FgColor:     fgColor,
-					},
-					Over: ScrollerStyle{
-						Border:      BorderSizes{1, 1, 1, 1},
-						Paddings:    BorderSizes{0, 2, 0, 0},
-						BorderColor: borderColor,
-						BgColor:     bgColorOver,
-						FgColor:     fgColor,
-					},
-					Focus: ScrollerStyle{
-						Border:      BorderSizes{1, 1, 1, 1},
-						Paddings:    BorderSizes{0, 2, 0, 0},
-						BorderColor: borderColor,
-						BgColor:     bgColorOver,
-						FgColor:     fgColor,
-					},
-					Disabled: ScrollerStyle{
-						Border:      BorderSizes{1, 1, 1, 1},
-						Paddings:    BorderSizes{0, 2, 0, 0},
-						BorderColor: borderColor,
-						BgColor:     bgColor,
-						FgColor:     fgColor,
-					},
-				},
-				Item: &ListItemStyles{
-					Normal: ListItemStyle{
-						Border:      BorderSizes{1, 0, 1, 0},
-						Paddings:    BorderSizes{0, 0, 0, 2},
-						BorderColor: math32.Color4{0, 0, 0, 0},
-						BgColor:     bgColor4,
-						FgColor:     fgColor,
-					},
-					Selected: ListItemStyle{
-						Border:      BorderSizes{1, 0, 1, 0},
-						Paddings:    BorderSizes{0, 0, 0, 2},
-						BorderColor: math32.Color4{0, 0, 0, 0},
-						BgColor:     bgColor4,
-						FgColor:     fgColor,
-					},
-					Highlighted: ListItemStyle{
-						Border:      BorderSizes{1, 0, 1, 0},
-						Paddings:    BorderSizes{0, 0, 0, 2},
-						BorderColor: math32.Color4{0, 0, 0, 1},
-						BgColor:     bgColor4Over,
-						FgColor:     fgColor,
-					},
-					SelHigh: ListItemStyle{
-						Border:      BorderSizes{1, 0, 1, 0},
-						Paddings:    BorderSizes{0, 0, 0, 2},
-						BorderColor: math32.Color4{0, 0, 0, 1},
-						BgColor:     bgColor4Sel,
-						FgColor:     fgColorSel,
-					},
-				},
-			},
-			Node: &TreeNodeStyles{
-				Normal: TreeNodeStyle{
-					Border:      BorderSizes{0, 0, 0, 0},
-					Paddings:    BorderSizes{0, 0, 0, 0},
-					BorderColor: borderColor,
-					BgColor:     bgColor4,
-					FgColor:     fgColor,
-					Icons:       [2]int{assets.ExpandMore, assets.ExpandLess},
-				},
-			},
-			Padlevel: 2.0,
-		},
-	}
-
-	// Menu styles
-	StyleDefault.Menu = MenuStyles{
-		Body: &MenuBodyStyles{
-			Normal: MenuBodyStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 2, 2, 2},
-				BorderColor: borderColor,
-				BgColor:     bgColor,
-				FgColor:     fgColor,
-			},
-			Over: MenuBodyStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 2, 2, 2},
-				BorderColor: borderColor,
-				BgColor:     bgColorOver,
-				FgColor:     fgColor,
-			},
-			Focus: MenuBodyStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 2, 2, 2},
-				BorderColor: borderColor,
-				BgColor:     bgColorOver,
-				FgColor:     fgColor,
-			},
-			Disabled: MenuBodyStyle{
-				Border:      BorderSizes{1, 1, 1, 1},
-				Paddings:    BorderSizes{2, 2, 2, 2},
-				BorderColor: borderColor,
-				BgColor:     bgColor,
-				FgColor:     fgColor,
-			},
-		},
-		Item: &MenuItemStyles{
-			Normal: MenuItemStyle{
-				Border:           BorderSizes{0, 0, 0, 0},
-				Paddings:         BorderSizes{2, 4, 2, 2},
-				BorderColor:      borderColor,
-				BgColor:          bgColor,
-				FgColor:          fgColor,
-				IconPaddings:     BorderSizes{0, 6, 0, 4},
-				ShortcutPaddings: BorderSizes{0, 0, 0, 10},
-				RiconPaddings:    BorderSizes{2, 0, 0, 4},
-			},
-			Over: MenuItemStyle{
-				Border:           BorderSizes{0, 0, 0, 0},
-				Paddings:         BorderSizes{2, 4, 2, 2},
-				BorderColor:      borderColor,
-				BgColor:          math32.Color{0.6, 0.6, 0.6},
-				FgColor:          fgColor,
-				IconPaddings:     BorderSizes{0, 6, 0, 4},
-				ShortcutPaddings: BorderSizes{0, 0, 0, 10},
-				RiconPaddings:    BorderSizes{2, 0, 0, 4},
-			},
-			Disabled: MenuItemStyle{
-				Border:           BorderSizes{0, 0, 0, 0},
-				Paddings:         BorderSizes{2, 4, 2, 2},
-				BorderColor:      borderColor,
-				BgColor:          bgColor,
-				FgColor:          fgColorDis,
-				IconPaddings:     BorderSizes{0, 6, 0, 4},
-				ShortcutPaddings: BorderSizes{0, 0, 0, 10},
-				RiconPaddings:    BorderSizes{2, 0, 0, 4},
-			},
-			Separator: MenuItemStyle{
-				Border:      BorderSizes{2, 2, 2, 2},
-				Paddings:    BorderSizes{0, 0, 0, 0},
-				BorderColor: math32.Color4{0, 0, 0, 0},
-				BgColor:     math32.Color{0.6, 0.6, 0.6},
-				FgColor:     fgColor,
-			},
-		},
-	}
-
-	// Table styles
-	StyleDefault.Table = TableStyles{
-		Header: &TableHeaderStyle{
-			Border:      BorderSizes{0, 1, 1, 0},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: borderColor,
-			BgColor:     math32.Color{0.7, 0.7, 0.7},
-			FgColor:     fgColor,
-		},
-		RowEven: &TableRowStyle{
-			Border:      BorderSizes{0, 1, 1, 0},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
-			BgColor:     math32.Color{0.90, 0.90, 0.90},
-			FgColor:     fgColor,
-		},
-		RowOdd: &TableRowStyle{
-			Border:      BorderSizes{0, 1, 1, 0},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
-			BgColor:     math32.Color{0.88, 0.88, 0.88},
-			FgColor:     fgColor,
-		},
-		RowCursor: &TableRowStyle{
-			Border:      BorderSizes{0, 1, 1, 0},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
-			BgColor:     math32.Color{0.75, 0.75, 0.75},
-			FgColor:     fgColor,
-		},
-		RowSel: &TableRowStyle{
-			Border:      BorderSizes{0, 1, 1, 0},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
-			BgColor:     math32.Color{0.70, 0.70, 0.70},
-			FgColor:     fgColor,
-		},
-		Status: &TableStatusStyle{
-			Border:      BorderSizes{1, 0, 0, 0},
-			Paddings:    BorderSizes{2, 2, 2, 2},
-			BorderColor: borderColor,
-			BgColor:     math32.Color{0.9, 0.9, 0.9},
-			FgColor:     fgColor,
-		},
-		Resizer: &TableResizerStyle{
-			Width:       4,
-			Border:      BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     math32.Color4{0.4, 0.4, 0.4, 0.6},
-		},
-	}
-
-	// Button styles
-	StyleDefault.ImageButton = ImageButtonStyles{
-		Normal: ImageButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4,
-			FgColor:     fgColor,
-		},
-		Over: ImageButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4Over,
-			FgColor:     fgColor,
-		},
-		Focus: ImageButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4Over,
-			FgColor:     fgColor,
-		},
-		Pressed: ImageButtonStyle{
-			Border:      BorderSizes{2, 2, 2, 2},
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColor,
-			BgColor:     bgColor4Over,
-			FgColor:     fgColor,
-		},
-		Disabled: ImageButtonStyle{
-			Border:      borderSizes,
-			Paddings:    BorderSizes{0, 0, 0, 0},
-			BorderColor: borderColorDis,
-			BgColor:     bgColor4,
-			FgColor:     fgColorDis,
-		},
-	}
-
-}

+ 25 - 0
gui/style_default.go

@@ -0,0 +1,25 @@
+// 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
+
+var defaultStyle *Style
+
+// Sets the default style
+func init() {
+
+	defaultStyle = NewLightStyle()
+}
+
+// StyleDefault() returns a pointer to the current default style
+func StyleDefault() *Style {
+
+	return defaultStyle
+}
+
+// SetStyleDefault sets the default style
+func SetStyleDefault(s *Style) {
+
+	defaultStyle = s
+}

+ 798 - 0
gui/style_light.go

@@ -0,0 +1,798 @@
+// 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 (
+	"github.com/g3n/engine/gui/assets"
+	"github.com/g3n/engine/gui/assets/icon"
+	"github.com/g3n/engine/math32"
+	"github.com/g3n/engine/text"
+)
+
+// NewLightStyle creates and returns a pointer to the a new "light" style
+func NewLightStyle() *Style {
+
+	// Fonts to use
+	const fontName = "fonts/FreeSans.ttf"
+	const iconName = "fonts/MaterialIcons-Regular.ttf"
+	s := new(Style)
+
+	// Creates text font
+	fontData := assets.MustAsset(fontName)
+	font, err := text.NewFontFromData(fontData)
+	if err != nil {
+		panic(err)
+	}
+	font.SetLineSpacing(1.0)
+	font.SetSize(14)
+	font.SetDPI(72)
+	font.SetFgColor4(math32.NewColor4("black"))
+	font.SetBgColor4(math32.NewColor4("black", 0))
+	s.Font = font
+
+	// Creates icon font
+	fontIconData := assets.MustAsset(iconName)
+	fontIcon, err := text.NewFontFromData(fontIconData)
+	if err != nil {
+		panic(err)
+	}
+	fontIcon.SetLineSpacing(1.0)
+	fontIcon.SetSize(14)
+	fontIcon.SetDPI(72)
+	fontIcon.SetFgColor4(math32.NewColor4("black"))
+	fontIcon.SetBgColor4(math32.NewColor4("white", 0))
+	s.FontIcon = fontIcon
+
+	borderSizes := BorderSizes{1, 1, 1, 1}
+	borderColor := math32.Color4Name("DimGray")
+	borderColorDis := math32.Color4Name("LightGray")
+
+	bgColor := math32.Color{0.85, 0.85, 0.85}
+	bgColor4 := math32.Color4{0, 0, 0, 0}
+	bgColorOver := math32.Color{0.9, 0.9, 0.9}
+	bgColor4Over := math32.Color4{1, 1, 1, 0.5}
+	bgColor4Sel := math32.Color4{0.6, 0.6, 0.6, 1}
+
+	fgColor := math32.Color{0, 0, 0}
+	fgColorSel := math32.Color{0, 0, 0}
+	fgColorDis := math32.Color{0.4, 0.4, 0.4}
+
+	// Button styles
+	s.Button = ButtonStyles{
+		Normal: ButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{2, 4, 2, 4},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			FgColor:     fgColor,
+		},
+		Over: ButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{2, 4, 2, 4},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+		},
+		Focus: ButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{2, 4, 2, 4},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+		},
+		Pressed: ButtonStyle{
+			Border:      BorderSizes{2, 2, 2, 2},
+			Paddings:    BorderSizes{2, 4, 2, 4},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+		},
+		Disabled: ButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{2, 4, 2, 4},
+			BorderColor: borderColorDis,
+			BgColor:     bgColor,
+			FgColor:     fgColorDis,
+		},
+	}
+
+	// CheckRadio styles
+	s.CheckRadio = CheckRadioStyles{
+		Normal: CheckRadioStyle{
+			Border:      BorderSizes{0, 0, 0, 0},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4,
+			FgColor:     fgColor,
+		},
+		Over: CheckRadioStyle{
+			Border:      BorderSizes{0, 0, 0, 0},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4Over,
+			FgColor:     fgColor,
+		},
+		Focus: CheckRadioStyle{
+			Border:      BorderSizes{0, 0, 0, 0},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4Over,
+			FgColor:     fgColor,
+		},
+		Disabled: CheckRadioStyle{
+			Border:      BorderSizes{0, 0, 0, 0},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4,
+			FgColor:     fgColorDis,
+		},
+	}
+
+	// Edit styles
+	s.Edit = EditStyles{
+		Normal: EditStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			BgAlpha:     1.0,
+			FgColor:     fgColor,
+			HolderColor: math32.Color{0.4, 0.4, 0.4},
+		},
+		Over: EditStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			BgAlpha:     1.0,
+			FgColor:     fgColor,
+			HolderColor: math32.Color{0.4, 0.4, 0.4},
+		},
+		Focus: EditStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			BgAlpha:     1.0,
+			FgColor:     fgColor,
+			HolderColor: math32.Color{0.4, 0.4, 0.4},
+		},
+		Disabled: EditStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			BgAlpha:     1.0,
+			FgColor:     fgColorDis,
+			HolderColor: math32.Color{0.4, 0.4, 0.4},
+		},
+	}
+
+	// ScrollBar style
+	s.ScrollBar = ScrollBarStyle{
+		Paddings:     BorderSizes{1, 1, 1, 1},
+		Borders:      BorderSizes{1, 1, 1, 1},
+		BordersColor: borderColor,
+		Color:        math32.Color{0.8, 0.8, 0.8},
+		Button: ScrollBarButtonStyle{
+			Borders:      BorderSizes{1, 1, 1, 1},
+			BordersColor: borderColor,
+			Color:        math32.Color{0.5, 0.5, 0.5},
+			Size:         30,
+		},
+	}
+
+	// Slider styles
+	s.Slider = SliderStyles{
+		Normal: SliderStyle{
+			Border:      borderSizes,
+			BorderColor: borderColor,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BgColor:     math32.Color4{0.8, 0.8, 0.8, 1},
+			FgColor:     math32.Color4{0, 0.8, 0, 1},
+		},
+		Over: SliderStyle{
+			Border:      borderSizes,
+			BorderColor: borderColor,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BgColor:     math32.Color4{1, 1, 1, 1},
+			FgColor:     math32.Color4{0, 1, 0, 1},
+		},
+		Focus: SliderStyle{
+			Border:      borderSizes,
+			BorderColor: borderColor,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BgColor:     math32.Color4{1, 1, 1, 1},
+			FgColor:     math32.Color4{0, 1, 0, 1},
+		},
+		Disabled: SliderStyle{
+			Border:      borderSizes,
+			BorderColor: borderColor,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BgColor:     math32.Color4{0.8, 0.8, 0.8, 1},
+			FgColor:     math32.Color4{0, 0.8, 0, 1},
+		},
+	}
+
+	// Splitter styles
+	s.Splitter = SplitterStyles{
+		Normal: SplitterStyle{
+			SpacerBorderColor: borderColor,
+			SpacerColor:       bgColor,
+			SpacerSize:        6,
+		},
+		Over: SplitterStyle{
+			SpacerBorderColor: borderColor,
+			SpacerColor:       bgColorOver,
+			SpacerSize:        6,
+		},
+		Drag: SplitterStyle{
+			SpacerBorderColor: borderColor,
+			SpacerColor:       bgColorOver,
+			SpacerSize:        6,
+		},
+	}
+
+	s.Window = WindowStyles{
+		Normal: WindowStyle{
+			Border:           BorderSizes{4, 4, 4, 4},
+			Paddings:         BorderSizes{0, 0, 0, 0},
+			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
+			TitleBorders:     BorderSizes{0, 0, 1, 0},
+			TitleBorderColor: math32.Color4{0, 0, 0, 1},
+			TitleBgColor:     math32.Color4{0, 1, 0, 1},
+			TitleFgColor:     math32.Color4{0, 0, 0, 1},
+		},
+		Over: WindowStyle{
+			Border:           BorderSizes{4, 4, 4, 4},
+			Paddings:         BorderSizes{0, 0, 0, 0},
+			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
+			TitleBorders:     BorderSizes{0, 0, 1, 0},
+			TitleBorderColor: math32.Color4{0, 0, 0, 1},
+			TitleBgColor:     math32.Color4{0, 1, 0, 1},
+			TitleFgColor:     math32.Color4{0, 0, 0, 1},
+		},
+		Focus: WindowStyle{
+			Border:           BorderSizes{4, 4, 4, 4},
+			Paddings:         BorderSizes{0, 0, 0, 0},
+			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
+			TitleBorders:     BorderSizes{0, 0, 1, 0},
+			TitleBorderColor: math32.Color4{0, 0, 0, 1},
+			TitleBgColor:     math32.Color4{0, 1, 0, 1},
+			TitleFgColor:     math32.Color4{0, 0, 0, 1},
+		},
+		Disabled: WindowStyle{
+			Border:           BorderSizes{4, 4, 4, 4},
+			Paddings:         BorderSizes{0, 0, 0, 0},
+			BorderColor:      math32.Color4{0.2, 0.2, 0.2, 1},
+			TitleBorders:     BorderSizes{0, 0, 1, 0},
+			TitleBorderColor: math32.Color4{0, 0, 0, 1},
+			TitleBgColor:     math32.Color4{0, 1, 0, 1},
+			TitleFgColor:     math32.Color4{0, 0, 0, 1},
+		},
+	}
+
+	// Scroller styles
+	s.Scroller = ScrollerStyles{
+		Normal: ScrollerStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			FgColor:     fgColor,
+		},
+		Over: ScrollerStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+		},
+		Focus: ScrollerStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+		},
+		Disabled: ScrollerStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			FgColor:     fgColor,
+		},
+	}
+
+	// List styles
+	s.List = ListStyles{
+		Scroller: &ScrollerStyles{
+			Normal: ScrollerStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{0, 0, 0, 0},
+				BorderColor: borderColor,
+				BgColor:     bgColor,
+				FgColor:     fgColor,
+			},
+			Over: ScrollerStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{0, 0, 0, 0},
+				BorderColor: borderColor,
+				BgColor:     bgColorOver,
+				FgColor:     fgColor,
+			},
+			Focus: ScrollerStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{0, 0, 0, 0},
+				BorderColor: borderColor,
+				BgColor:     bgColorOver,
+				FgColor:     fgColor,
+			},
+			Disabled: ScrollerStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{0, 0, 0, 0},
+				BorderColor: borderColor,
+				BgColor:     bgColor,
+				FgColor:     fgColor,
+			},
+		},
+		Item: &ListItemStyles{
+			Normal: ListItemStyle{
+				Border:      BorderSizes{1, 0, 1, 0},
+				Paddings:    BorderSizes{0, 0, 0, 2},
+				BorderColor: math32.Color4{0, 0, 0, 0},
+				BgColor:     bgColor4,
+				FgColor:     fgColor,
+			},
+			Selected: ListItemStyle{
+				Border:      BorderSizes{1, 0, 1, 0},
+				Paddings:    BorderSizes{0, 0, 0, 2},
+				BorderColor: math32.Color4{0, 0, 0, 0},
+				BgColor:     bgColor4Sel,
+				FgColor:     fgColorSel,
+			},
+			Highlighted: ListItemStyle{
+				Border:      BorderSizes{1, 0, 1, 0},
+				Paddings:    BorderSizes{0, 0, 0, 2},
+				BorderColor: math32.Color4{0, 0, 0, 1},
+				BgColor:     bgColor4Over,
+				FgColor:     fgColor,
+			},
+			SelHigh: ListItemStyle{
+				Border:      BorderSizes{1, 0, 1, 0},
+				Paddings:    BorderSizes{0, 0, 0, 2},
+				BorderColor: math32.Color4{0, 0, 0, 1},
+				BgColor:     bgColor4Sel,
+				FgColor:     fgColorSel,
+			},
+		},
+	}
+
+	s.DropDown = DropDownStyles{
+		Normal: &DropDownStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			FgColor:     fgColor,
+		},
+		Over: &DropDownStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+		},
+		Focus: &DropDownStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+		},
+		Disabled: &DropDownStyle{
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{0, 0, 0, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			FgColor:     fgColor,
+		},
+	}
+
+	s.Folder = FolderStyles{
+		Normal: &FolderStyle{
+			Margins:     BorderSizes{0, 0, 0, 0},
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{2, 0, 2, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColor,
+			FgColor:     fgColor,
+			Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+		},
+		Over: &FolderStyle{
+			Margins:     BorderSizes{0, 0, 0, 0},
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{2, 0, 2, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+			Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+		},
+		Focus: &FolderStyle{
+			Margins:     BorderSizes{0, 0, 0, 0},
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+			Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+		},
+		Disabled: &FolderStyle{
+			Margins:     BorderSizes{0, 0, 0, 0},
+			Border:      BorderSizes{1, 1, 1, 1},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: borderColor,
+			BgColor:     bgColorOver,
+			FgColor:     fgColor,
+			Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+		},
+	}
+
+	s.Tree = TreeStyles{
+		List: &ListStyles{
+			Scroller: &ScrollerStyles{
+				Normal: ScrollerStyle{
+					Border:      BorderSizes{1, 1, 1, 1},
+					Paddings:    BorderSizes{0, 0, 0, 0},
+					BorderColor: borderColor,
+					BgColor:     bgColor,
+					FgColor:     fgColor,
+				},
+				Over: ScrollerStyle{
+					Border:      BorderSizes{1, 1, 1, 1},
+					Paddings:    BorderSizes{0, 0, 0, 0},
+					BorderColor: borderColor,
+					BgColor:     bgColorOver,
+					FgColor:     fgColor,
+				},
+				Focus: ScrollerStyle{
+					Border:      BorderSizes{1, 1, 1, 1},
+					Paddings:    BorderSizes{0, 0, 0, 0},
+					BorderColor: borderColor,
+					BgColor:     bgColorOver,
+					FgColor:     fgColor,
+				},
+				Disabled: ScrollerStyle{
+					Border:      BorderSizes{1, 1, 1, 1},
+					Paddings:    BorderSizes{0, 0, 0, 0},
+					BorderColor: borderColor,
+					BgColor:     bgColor,
+					FgColor:     fgColor,
+				},
+			},
+			Item: &ListItemStyles{
+				Normal: ListItemStyle{
+					Border:      BorderSizes{1, 0, 1, 0},
+					Paddings:    BorderSizes{0, 0, 0, 2},
+					BorderColor: math32.Color4{0, 0, 0, 0},
+					BgColor:     bgColor4,
+					FgColor:     fgColor,
+				},
+				Selected: ListItemStyle{
+					Border:      BorderSizes{1, 0, 1, 0},
+					Paddings:    BorderSizes{0, 0, 0, 2},
+					BorderColor: math32.Color4{0, 0, 0, 0},
+					BgColor:     bgColor4Sel,
+					FgColor:     fgColorSel,
+				},
+				Highlighted: ListItemStyle{
+					Border:      BorderSizes{1, 0, 1, 0},
+					Paddings:    BorderSizes{0, 0, 0, 2},
+					BorderColor: math32.Color4{0, 0, 0, 1},
+					BgColor:     bgColor4Over,
+					FgColor:     fgColor,
+				},
+				SelHigh: ListItemStyle{
+					Border:      BorderSizes{1, 0, 1, 0},
+					Paddings:    BorderSizes{0, 0, 0, 2},
+					BorderColor: math32.Color4{0, 0, 0, 1},
+					BgColor:     bgColor4Sel,
+					FgColor:     fgColorSel,
+				},
+			},
+		},
+		Node: &TreeNodeStyles{
+			Normal: TreeNodeStyle{
+				Border:      BorderSizes{0, 0, 0, 0},
+				Paddings:    BorderSizes{0, 0, 0, 0},
+				BorderColor: borderColor,
+				BgColor:     bgColor4,
+				FgColor:     fgColor,
+				Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+			},
+		},
+		Padlevel: 16.0,
+	}
+
+	s.ControlFolder = ControlFolderStyles{
+		Folder: &FolderStyles{
+			Normal: &FolderStyle{
+				Margins:     BorderSizes{0, 0, 0, 0},
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 0, 2, 2},
+				BorderColor: math32.Color4{0, 0, 0, 0},
+				BgColor:     math32.Color{0, 0.5, 1},
+				FgColor:     fgColor,
+				Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+			},
+			Over: &FolderStyle{
+				Margins:     BorderSizes{0, 0, 0, 0},
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 0, 2, 2},
+				BorderColor: math32.Color4{0, 0, 0, 0},
+				BgColor:     math32.Color{0, 0.5, 1},
+				FgColor:     fgColor,
+				Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+			},
+			Focus: &FolderStyle{
+				Margins:     BorderSizes{0, 0, 0, 0},
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: math32.Color4{0, 0, 0, 0},
+				BgColor:     math32.Color{0, 0.5, 1},
+				FgColor:     fgColor,
+				Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+			},
+			Disabled: &FolderStyle{
+				Margins:     BorderSizes{0, 0, 0, 0},
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: math32.Color4{0, 0, 0, 0},
+				BgColor:     math32.Color{0, 0.5, 1},
+				FgColor:     fgColor,
+				Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+			},
+		},
+		Tree: &TreeStyles{
+			List: &ListStyles{
+				Scroller: &ScrollerStyles{
+					Normal: ScrollerStyle{
+						Border:      BorderSizes{1, 1, 1, 1},
+						Paddings:    BorderSizes{0, 2, 0, 0},
+						BorderColor: borderColor,
+						BgColor:     bgColor,
+						FgColor:     fgColor,
+					},
+					Over: ScrollerStyle{
+						Border:      BorderSizes{1, 1, 1, 1},
+						Paddings:    BorderSizes{0, 2, 0, 0},
+						BorderColor: borderColor,
+						BgColor:     bgColorOver,
+						FgColor:     fgColor,
+					},
+					Focus: ScrollerStyle{
+						Border:      BorderSizes{1, 1, 1, 1},
+						Paddings:    BorderSizes{0, 2, 0, 0},
+						BorderColor: borderColor,
+						BgColor:     bgColorOver,
+						FgColor:     fgColor,
+					},
+					Disabled: ScrollerStyle{
+						Border:      BorderSizes{1, 1, 1, 1},
+						Paddings:    BorderSizes{0, 2, 0, 0},
+						BorderColor: borderColor,
+						BgColor:     bgColor,
+						FgColor:     fgColor,
+					},
+				},
+				Item: &ListItemStyles{
+					Normal: ListItemStyle{
+						Border:      BorderSizes{1, 0, 1, 0},
+						Paddings:    BorderSizes{0, 0, 0, 2},
+						BorderColor: math32.Color4{0, 0, 0, 0},
+						BgColor:     bgColor4,
+						FgColor:     fgColor,
+					},
+					Selected: ListItemStyle{
+						Border:      BorderSizes{1, 0, 1, 0},
+						Paddings:    BorderSizes{0, 0, 0, 2},
+						BorderColor: math32.Color4{0, 0, 0, 0},
+						BgColor:     bgColor4,
+						FgColor:     fgColor,
+					},
+					Highlighted: ListItemStyle{
+						Border:      BorderSizes{1, 0, 1, 0},
+						Paddings:    BorderSizes{0, 0, 0, 2},
+						BorderColor: math32.Color4{0, 0, 0, 1},
+						BgColor:     bgColor4Over,
+						FgColor:     fgColor,
+					},
+					SelHigh: ListItemStyle{
+						Border:      BorderSizes{1, 0, 1, 0},
+						Paddings:    BorderSizes{0, 0, 0, 2},
+						BorderColor: math32.Color4{0, 0, 0, 1},
+						BgColor:     bgColor4Sel,
+						FgColor:     fgColorSel,
+					},
+				},
+			},
+			Node: &TreeNodeStyles{
+				Normal: TreeNodeStyle{
+					Border:      BorderSizes{0, 0, 0, 0},
+					Paddings:    BorderSizes{0, 0, 0, 0},
+					BorderColor: borderColor,
+					BgColor:     bgColor4,
+					FgColor:     fgColor,
+					Icons:       [2]string{icon.ExpandMore, icon.ExpandLess},
+				},
+			},
+			Padlevel: 2.0,
+		},
+	}
+
+	// Menu styles
+	s.Menu = MenuStyles{
+		Body: &MenuBodyStyles{
+			Normal: MenuBodyStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: borderColor,
+				BgColor:     bgColor,
+				FgColor:     fgColor,
+			},
+			Over: MenuBodyStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: borderColor,
+				BgColor:     bgColorOver,
+				FgColor:     fgColor,
+			},
+			Focus: MenuBodyStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: borderColor,
+				BgColor:     bgColorOver,
+				FgColor:     fgColor,
+			},
+			Disabled: MenuBodyStyle{
+				Border:      BorderSizes{1, 1, 1, 1},
+				Paddings:    BorderSizes{2, 2, 2, 2},
+				BorderColor: borderColor,
+				BgColor:     bgColor,
+				FgColor:     fgColor,
+			},
+		},
+		Item: &MenuItemStyles{
+			Normal: MenuItemStyle{
+				Border:           BorderSizes{0, 0, 0, 0},
+				Paddings:         BorderSizes{2, 4, 2, 2},
+				BorderColor:      borderColor,
+				BgColor:          bgColor,
+				FgColor:          fgColor,
+				IconPaddings:     BorderSizes{0, 6, 0, 4},
+				ShortcutPaddings: BorderSizes{0, 0, 0, 10},
+				RiconPaddings:    BorderSizes{2, 0, 0, 4},
+			},
+			Over: MenuItemStyle{
+				Border:           BorderSizes{0, 0, 0, 0},
+				Paddings:         BorderSizes{2, 4, 2, 2},
+				BorderColor:      borderColor,
+				BgColor:          math32.Color{0.6, 0.6, 0.6},
+				FgColor:          fgColor,
+				IconPaddings:     BorderSizes{0, 6, 0, 4},
+				ShortcutPaddings: BorderSizes{0, 0, 0, 10},
+				RiconPaddings:    BorderSizes{2, 0, 0, 4},
+			},
+			Disabled: MenuItemStyle{
+				Border:           BorderSizes{0, 0, 0, 0},
+				Paddings:         BorderSizes{2, 4, 2, 2},
+				BorderColor:      borderColor,
+				BgColor:          bgColor,
+				FgColor:          fgColorDis,
+				IconPaddings:     BorderSizes{0, 6, 0, 4},
+				ShortcutPaddings: BorderSizes{0, 0, 0, 10},
+				RiconPaddings:    BorderSizes{2, 0, 0, 4},
+			},
+			Separator: MenuItemStyle{
+				Border:      BorderSizes{2, 2, 2, 2},
+				Paddings:    BorderSizes{0, 0, 0, 0},
+				BorderColor: math32.Color4{0, 0, 0, 0},
+				BgColor:     math32.Color{0.6, 0.6, 0.6},
+				FgColor:     fgColor,
+			},
+		},
+	}
+
+	// Table styles
+	s.Table = TableStyles{
+		Header: &TableHeaderStyle{
+			Border:      BorderSizes{0, 1, 1, 0},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: borderColor,
+			BgColor:     math32.Color{0.7, 0.7, 0.7},
+			FgColor:     fgColor,
+		},
+		RowEven: &TableRowStyle{
+			Border:      BorderSizes{0, 1, 1, 0},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
+			BgColor:     math32.Color{0.90, 0.90, 0.90},
+			FgColor:     fgColor,
+		},
+		RowOdd: &TableRowStyle{
+			Border:      BorderSizes{0, 1, 1, 0},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
+			BgColor:     math32.Color{0.88, 0.88, 0.88},
+			FgColor:     fgColor,
+		},
+		RowCursor: &TableRowStyle{
+			Border:      BorderSizes{0, 1, 1, 0},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
+			BgColor:     math32.Color{0.75, 0.75, 0.75},
+			FgColor:     fgColor,
+		},
+		RowSel: &TableRowStyle{
+			Border:      BorderSizes{0, 1, 1, 0},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: math32.Color4{0.6, 0.6, 0.6, 1},
+			BgColor:     math32.Color{0.70, 0.70, 0.70},
+			FgColor:     fgColor,
+		},
+		Status: &TableStatusStyle{
+			Border:      BorderSizes{1, 0, 0, 0},
+			Paddings:    BorderSizes{2, 2, 2, 2},
+			BorderColor: borderColor,
+			BgColor:     math32.Color{0.9, 0.9, 0.9},
+			FgColor:     fgColor,
+		},
+		Resizer: &TableResizerStyle{
+			Width:       4,
+			Border:      BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     math32.Color4{0.4, 0.4, 0.4, 0.6},
+		},
+	}
+
+	// Button styles
+	s.ImageButton = ImageButtonStyles{
+		Normal: ImageButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4,
+			FgColor:     fgColor,
+		},
+		Over: ImageButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4Over,
+			FgColor:     fgColor,
+		},
+		Focus: ImageButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4Over,
+			FgColor:     fgColor,
+		},
+		Pressed: ImageButtonStyle{
+			Border:      BorderSizes{2, 2, 2, 2},
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColor,
+			BgColor:     bgColor4Over,
+			FgColor:     fgColor,
+		},
+		Disabled: ImageButtonStyle{
+			Border:      borderSizes,
+			Paddings:    BorderSizes{0, 0, 0, 0},
+			BorderColor: borderColorDis,
+			BgColor:     bgColor4,
+			FgColor:     fgColorDis,
+		},
+	}
+	return s
+}

+ 7 - 7
gui/table.go

@@ -10,7 +10,7 @@ import (
 	"sort"
 	"strconv"
 
-	"github.com/g3n/engine/gui/assets"
+	"github.com/g3n/engine/gui/assets/icon"
 	"github.com/g3n/engine/math32"
 	"github.com/g3n/engine/window"
 )
@@ -43,9 +43,9 @@ const (
 )
 
 const (
-	tableSortedNoneIcon = assets.SwapVert
-	tableSortedAscIcon  = assets.ArrowDownward
-	tableSortedDescIcon = assets.ArrowUpward
+	tableSortedNoneIcon = icon.SwapVert
+	tableSortedAscIcon  = icon.ArrowDownward
+	tableSortedDescIcon = icon.ArrowUpward
 	tableSortedNone     = 0
 	tableSortedAsc      = 1
 	tableSortedDesc     = 2
@@ -217,7 +217,7 @@ func NewTable(width, height float32, cols []TableColumn) (*Table, error) {
 
 	t := new(Table)
 	t.Panel.Initialize(width, height)
-	t.styles = &StyleDefault.Table
+	t.styles = &StyleDefault().Table
 	t.rowCursor = -1
 
 	// Initialize table header
@@ -259,7 +259,7 @@ func NewTable(width, height float32, cols []TableColumn) (*Table, error) {
 		c.resize = cdesc.Resize
 		// Adds optional sort icon
 		if c.sort != TableSortNone {
-			c.ricon = NewIconLabel(string(tableSortedNoneIcon))
+			c.ricon = NewLabel(string(tableSortedNoneIcon), true)
 			c.Add(c.ricon)
 			c.ricon.Subscribe(OnMouseDown, func(evname string, ev interface{}) {
 				t.onRicon(evname, c)
@@ -722,7 +722,7 @@ func (t *Table) insertRow(row int, values map[string]interface{}) {
 		// Creates tableRow cell panel
 		cell := new(tableCell)
 		cell.Initialize(0, 0)
-		cell.label.initialize("", StyleDefault.Font)
+		cell.label.initialize("", StyleDefault().Font)
 		cell.Add(&cell.label)
 		trow.cells = append(trow.cells, cell)
 		trow.Panel.Add(cell)

+ 4 - 4
gui/tree.go

@@ -31,7 +31,7 @@ type TreeNodeStyle struct {
 	BorderColor math32.Color4
 	BgColor     math32.Color4
 	FgColor     math32.Color
-	Icons       [2]int
+	Icons       [2]string
 }
 
 type TreeNode struct {
@@ -57,7 +57,7 @@ func NewTree(width, height float32) *Tree {
 func (t *Tree) Initialize(width, height float32) {
 
 	t.List.initialize(true, width, height)
-	t.SetStyles(&StyleDefault.Tree)
+	t.SetStyles(&StyleDefault().Tree)
 	t.List.Subscribe(OnKeyDown, t.onKey)
 	t.List.Subscribe(OnKeyUp, t.onKey)
 	t.List.Subscribe(OnCursor, t.onCursor)
@@ -206,11 +206,11 @@ func newTreeNode(text string, tree *Tree, parNode *TreeNode) *TreeNode {
 	n.Panel.Initialize(0, 0)
 
 	// Initialize node label
-	n.label.initialize(text, StyleDefault.Font)
+	n.label.initialize(text, StyleDefault().Font)
 	n.Panel.Add(&n.label)
 
 	// Create node icon
-	n.icon.initialize("", StyleDefault.FontIcon)
+	n.icon.initialize("", StyleDefault().FontIcon)
 	n.icon.SetFontSize(n.label.FontSize() * 1.3)
 	n.Panel.Add(&n.icon)
 

+ 88 - 12
gui/vboxlayout.go

@@ -4,13 +4,37 @@
 
 package gui
 
+// VBoxLayout implements a panel layout which arranges the panel children vertically.
+// The children can be separated by a space in pixels set by SetSpacing().
+// The whole group of children can be aligned vertically by SetAlignV() which can
+// accept the following types of alignment:
+//
+// 	AlignTop: Try to align the group of children to the top if the panel height is
+// 	greater the the sum of the children heights + spacing.
+//
+// 	AlignBottom: Try to align the group of children to the bottoom if the panel height is
+// 	greater the the sum of the children heights + spacing.
+//
+// 	AlignCenter: Try to align the group of children in the center if the panel height is
+// 	greater the the sum of the children heights + spacing.
+//
+// 	AlignHeight - Try to align the individual children vertically with the same same space between each other.
+// 	Each individual child can be aligned horizontally by SetLayoutParameters()
+//
+// If the layout method SetAutoHeight(true) is called, the panel minimum content height will be the
+// sum of its children's heights plus the spacing.
+//
+// If the layout method SetAutoWidth(true) is called, the panel minimum content width will be the
+// width of the widest child.
 type VBoxLayout struct {
-	pan     IPanel
-	spacing float32 // vertical spacing between the children in pixels.
-	alignV  Align   // vertical alignment of the whole block of children
+	pan        IPanel
+	spacing    float32
+	alignV     Align
+	autoHeight bool
+	autoWidth  bool
 }
 
-// Parameters for individual children
+// VBoxLayoutParams specify the horizontal alignment of each individual child.
 type VBoxLayoutParams struct {
 	Expand float32 // item expand vertically factor (0 - no expand)
 	AlignH Align   // item horizontal alignment
@@ -33,7 +57,7 @@ func (bl *VBoxLayout) SetSpacing(spacing float32) {
 	bl.Recalc(bl.pan)
 }
 
-// SetAlignH sets the horizontal alignment of the whole group of items
+// SetAlignV sets the vertical alignment of the whole group of items
 // inside the parent panel and updates the layout if possible.
 // This only has any effect if there are no expanded items.
 func (bl *VBoxLayout) SetAlignV(align Align) {
@@ -42,6 +66,22 @@ func (bl *VBoxLayout) SetAlignV(align Align) {
 	bl.Recalc(bl.pan)
 }
 
+// SetAutoHeight sets if the panel minimum height should be the height of
+// the largest of its children's height.
+func (bl *VBoxLayout) SetAutoHeight(state bool) {
+
+	bl.autoHeight = state
+	bl.Recalc(bl.pan)
+}
+
+// SetAutoWidth sets if the panel minimum width should be sum of its
+// children's width plus the spacing
+func (bl *VBoxLayout) SetAutoWidth(state bool) {
+
+	bl.autoWidth = state
+	bl.Recalc(bl.pan)
+}
+
 // Recalc recalculates and sets the position and sizes of all children
 func (bl *VBoxLayout) Recalc(ipan IPanel) {
 
@@ -55,12 +95,48 @@ func (bl *VBoxLayout) Recalc(ipan IPanel) {
 		return
 	}
 
+	// If autoHeight is set, get the sum of heights of this panel's children plus the spacings.
+	// If the panel content height is less than this height, set its content height to this value.
+	if bl.autoHeight {
+		var totalHeight float32
+		for _, ichild := range parent.Children() {
+			child := ichild.(IPanel).GetPanel()
+			if !child.Visible() {
+				continue
+			}
+			totalHeight += child.Height()
+		}
+		// Adds spacing
+		totalHeight += bl.spacing * float32(len(parent.Children())-1)
+		if parent.ContentHeight() < totalHeight {
+			parent.setContentSize(parent.ContentWidth(), totalHeight, false)
+		}
+	}
+
+	// If autoWidth is set, get the maximum width of all the panel's children
+	// and if the panel content width is less than this maximum, set its content width to this value.
+	if bl.autoWidth {
+		var maxWidth float32
+		for _, ichild := range parent.Children() {
+			child := ichild.(IPanel).GetPanel()
+			if !child.Visible() {
+				continue
+			}
+			if child.Width() > maxWidth {
+				maxWidth = child.Width()
+			}
+		}
+		if parent.ContentWidth() < maxWidth {
+			parent.setContentSize(maxWidth, parent.ContentHeight(), false)
+		}
+	}
+
 	// Calculates the total height, expanded height, fixed height and
 	// the sum of the expand factor for all items.
-	var theight float32 = 0
-	var eheight float32 = 0
-	var fheight float32 = 0
-	var texpand float32 = 0
+	var theight float32
+	var eheight float32
+	var fheight float32
+	var texpand float32
 	ecount := 0
 	paramsDef := VBoxLayoutParams{Expand: 0, AlignH: AlignLeft}
 	for pos, obj := range parent.Children() {
@@ -94,7 +170,7 @@ func (bl *VBoxLayout) Recalc(ipan IPanel) {
 
 	// If there is at least on expanded item, all free space will be occupied
 	spaceMiddle := bl.spacing
-	var posY float32 = 0
+	var posY float32
 	if texpand > 0 {
 		// If there is free space, distribute space between expanded items
 		totalSpace := parent.ContentHeight() - theight
@@ -132,7 +208,7 @@ func (bl *VBoxLayout) Recalc(ipan IPanel) {
 		// Calculates initial y position which depends
 		// on the current horizontal alignment.
 		switch bl.alignV {
-		case AlignTop:
+		case AlignNone, AlignTop:
 			posY = 0
 		case AlignCenter:
 			posY = (parent.ContentHeight() - theight) / 2
@@ -163,7 +239,7 @@ func (bl *VBoxLayout) Recalc(ipan IPanel) {
 		}
 		cwidth := pan.Width()
 		switch params.AlignH {
-		case AlignLeft:
+		case AlignNone, AlignLeft:
 			posX = 0
 		case AlignCenter:
 			posX = (width - cwidth) / 2

+ 7 - 8
gui/window.go

@@ -34,7 +34,7 @@ type Window struct {
 	styles     *WindowStyles
 	title      *WindowTitle // internal optional title panel
 	client     Panel        // internal client panel
-	resizable  Resizable
+	resizable  ResizeBorders
 	overBorder string
 	drag       bool
 	mouseX     float32
@@ -59,10 +59,10 @@ type WindowStyles struct {
 	Disabled WindowStyle
 }
 
-type Resizable int
+type ResizeBorders int
 
 const (
-	ResizeTop = Resizable(1 << (iota + 1))
+	ResizeTop = ResizeBorders(1 << (iota + 1))
 	ResizeRight
 	ResizeBottom
 	ResizeLeft
@@ -74,7 +74,7 @@ const (
 func NewWindow(width, height float32) *Window {
 
 	w := new(Window)
-	w.styles = &StyleDefault.Window
+	w.styles = &StyleDefault().Window
 
 	w.Panel.Initialize(width, height)
 	w.Panel.Subscribe(OnMouseDown, w.onMouse)
@@ -93,7 +93,7 @@ func NewWindow(width, height float32) *Window {
 }
 
 // SetResizable set the borders which are resizable
-func (w *Window) SetResizable(res Resizable) {
+func (w *Window) SetResizable(res ResizeBorders) {
 
 	w.resizable = res
 }
@@ -119,10 +119,9 @@ func (w *Window) Add(ichild IPanel) *Window {
 }
 
 // SetLayout set the layout of this window content area
-func (w *Window) SetLayout(layout ILayout) *Window {
+func (w *Window) SetLayout(layout ILayout) {
 
 	w.client.SetLayout(layout)
-	return w
 }
 
 // onMouse process subscribed mouse events over the window
@@ -281,7 +280,7 @@ func newWindowTitle(win *Window, text string) *WindowTitle {
 	wt.win = win
 
 	wt.Panel.Initialize(0, 0)
-	wt.label.initialize(text, StyleDefault.Font)
+	wt.label.initialize(text, StyleDefault().Font)
 	wt.Panel.Add(&wt.label)
 
 	wt.Subscribe(OnMouseDown, wt.onMouse)

+ 1 - 1
loader/collada/scene.go

@@ -87,7 +87,7 @@ func (d *Decoder) newNode(cnode *Node) (core.INode, error) {
 			node = mesh
 
 		case gls.POINTS:
-			mat := material.NewPoint(math32.NewColor(0, 0, 0))
+			mat := material.NewPoint(&math32.Color{})
 			mat.SetSize(1000)
 			node = graphic.NewPoints(geomi, mat)
 

+ 179 - 163
math32/color.go

@@ -1,29 +1,37 @@
 // 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 math32
 
-import ()
+import (
+	"strings"
+)
 
+// Type color describes an RGB color
 type Color struct {
 	R float32
 	G float32
 	B float32
 }
 
-var Black = Color{0, 0, 0}
-var White = Color{1, 1, 1}
-var Red = Color{1, 0, 0}
-var Green = Color{0, 1, 0}
-var Blue = Color{0, 0, 1}
-var Gray = Color{0.5, 0.5, 0.5}
+// New creates and returns a pointer to a new Color
+// with the specified web standard color name (case insensitive).
+// Returns nil if the color name not found
+func NewColor(name string) *Color {
+
+	c, ok := mapColorNames[strings.ToLower(name)]
+	if !ok {
+		return nil
+	}
+	return &c
+}
 
-// NewColor creates and returns a pointer to a new color
-// with the specified RGB components
-func NewColor(r, g, b float32) *Color {
+// Name returns a Color with the specified standard web color
+// name (case insensitive).
+// Returns black color if the specified color name not found
+func ColorName(name string) Color {
 
-	return &Color{R: r, G: g, B: b}
+	return mapColorNames[strings.ToLower(name)]
 }
 
 // NewColorHex creates and returns a pointer to a new color
@@ -53,10 +61,14 @@ func (c *Color) SetHex(value uint) *Color {
 }
 
 // SetName sets the color RGB components from the
-// specified HTML color name
+// specified standard web color name
 func (c *Color) SetName(name string) *Color {
 
-	return c.SetHex(colorKeywords[name])
+	color, ok := mapColorNames[strings.ToLower(name)]
+	if ok {
+		*c = color
+	}
+	return c
 }
 
 func (c *Color) Add(other *Color) *Color {
@@ -112,156 +124,160 @@ func (c *Color) Equals(other *Color) bool {
 	return (c.R == other.R) && (c.G == other.G) && (c.B == other.B)
 }
 
-func (c *Color) Clone() *Color {
+func IsColorName(name string) (Color, bool) {
 
-	return NewColor(c.R, c.G, c.B)
+	c, ok := mapColorNames[strings.ToLower(name)]
+	return c, ok
 }
 
-var colorKeywords = map[string]uint{
-	"aliceblue":            0xF0F8FF,
-	"antiquewhite":         0xFAEBD7,
-	"aqua":                 0x00FFFF,
-	"aquamarine":           0x7FFFD4,
-	"azure":                0xF0FFFF,
-	"beige":                0xF5F5DC,
-	"bisque":               0xFFE4C4,
-	"black":                0x000000,
-	"blanchedalmond":       0xFFEBCD,
-	"blue":                 0x0000FF,
-	"blueviolet":           0x8A2BE2,
-	"brown":                0xA52A2A,
-	"burlywood":            0xDEB887,
-	"cadetblue":            0x5F9EA0,
-	"chartreuse":           0x7FFF00,
-	"chocolate":            0xD2691E,
-	"coral":                0xFF7F50,
-	"cornflowerblue":       0x6495ED,
-	"cornsilk":             0xFFF8DC,
-	"crimson":              0xDC143C,
-	"cyan":                 0x00FFFF,
-	"darkblue":             0x00008B,
-	"darkcyan":             0x008B8B,
-	"darkgoldenrod":        0xB8860B,
-	"darkgray":             0xA9A9A9,
-	"darkgreen":            0x006400,
-	"darkgrey":             0xA9A9A9,
-	"darkkhaki":            0xBDB76B,
-	"darkmagenta":          0x8B008B,
-	"darkolivegreen":       0x556B2F,
-	"darkorange":           0xFF8C00,
-	"darkorchid":           0x9932CC,
-	"darkred":              0x8B0000,
-	"darksalmon":           0xE9967A,
-	"darkseagreen":         0x8FBC8F,
-	"darkslateblue":        0x483D8B,
-	"darkslategray":        0x2F4F4F,
-	"darkslategrey":        0x2F4F4F,
-	"darkturquoise":        0x00CED1,
-	"darkviolet":           0x9400D3,
-	"deeppink":             0xFF1493,
-	"deepskyblue":          0x00BFFF,
-	"dimgray":              0x696969,
-	"dimgrey":              0x696969,
-	"dodgerblue":           0x1E90FF,
-	"firebrick":            0xB22222,
-	"floralwhite":          0xFFFAF0,
-	"forestgreen":          0x228B22,
-	"fuchsia":              0xFF00FF,
-	"gainsboro":            0xDCDCDC,
-	"ghostwhite":           0xF8F8FF,
-	"gold":                 0xFFD700,
-	"goldenrod":            0xDAA520,
-	"gray":                 0x808080,
-	"green":                0x008000,
-	"greenyellow":          0xADFF2F,
-	"grey":                 0x808080,
-	"honeydew":             0xF0FFF0,
-	"hotpink":              0xFF69B4,
-	"indianred":            0xCD5C5C,
-	"indigo":               0x4B0082,
-	"ivory":                0xFFFFF0,
-	"khaki":                0xF0E68C,
-	"lavender":             0xE6E6FA,
-	"lavenderblush":        0xFFF0F5,
-	"lawngreen":            0x7CFC00,
-	"lemonchiffon":         0xFFFACD,
-	"lightblue":            0xADD8E6,
-	"lightcoral":           0xF08080,
-	"lightcyan":            0xE0FFFF,
-	"lightgoldenrodyellow": 0xFAFAD2,
-	"lightgray":            0xD3D3D3,
-	"lightgreen":           0x90EE90,
-	"lightgrey":            0xD3D3D3,
-	"lightpink":            0xFFB6C1,
-	"lightsalmon":          0xFFA07A,
-	"lightseagreen":        0x20B2AA,
-	"lightskyblue":         0x87CEFA,
-	"lightslategray":       0x778899,
-	"lightslategrey":       0x778899,
-	"lightsteelblue":       0xB0C4DE,
-	"lightyellow":          0xFFFFE0,
-	"lime":                 0x00FF00,
-	"limegreen":            0x32CD32,
-	"linen":                0xFAF0E6,
-	"magenta":              0xFF00FF,
-	"maroon":               0x800000,
-	"mediumaquamarine":     0x66CDAA,
-	"mediumblue":           0x0000CD,
-	"mediumorchid":         0xBA55D3,
-	"mediumpurple":         0x9370DB,
-	"mediumseagreen":       0x3CB371,
-	"mediumslateblue":      0x7B68EE,
-	"mediumspringgreen":    0x00FA9A,
-	"mediumturquoise":      0x48D1CC,
-	"mediumvioletred":      0xC71585,
-	"midnightblue":         0x191970,
-	"mintcream":            0xF5FFFA,
-	"mistyrose":            0xFFE4E1,
-	"moccasin":             0xFFE4B5,
-	"navajowhite":          0xFFDEAD,
-	"navy":                 0x000080,
-	"oldlace":              0xFDF5E6,
-	"olive":                0x808000,
-	"olivedrab":            0x6B8E23,
-	"orange":               0xFFA500,
-	"orangered":            0xFF4500,
-	"orchid":               0xDA70D6,
-	"palegoldenrod":        0xEEE8AA,
-	"palegreen":            0x98FB98,
-	"paleturquoise":        0xAFEEEE,
-	"palevioletred":        0xDB7093,
-	"papayawhip":           0xFFEFD5,
-	"peachpuff":            0xFFDAB9,
-	"peru":                 0xCD853F,
-	"pink":                 0xFFC0CB,
-	"plum":                 0xDDA0DD,
-	"powderblue":           0xB0E0E6,
-	"purple":               0x800080,
-	"red":                  0xFF0000,
-	"rosybrown":            0xBC8F8F,
-	"royalblue":            0x4169E1,
-	"saddlebrown":          0x8B4513,
-	"salmon":               0xFA8072,
-	"sandybrown":           0xF4A460,
-	"seagreen":             0x2E8B57,
-	"seashell":             0xFFF5EE,
-	"sienna":               0xA0522D,
-	"silver":               0xC0C0C0,
-	"skyblue":              0x87CEEB,
-	"slateblue":            0x6A5ACD,
-	"slategrey":            0x708090,
-	"snow":                 0xFFFAFA,
-	"springgreen":          0x00FF7F,
-	"steelblue":            0x4682B4,
-	"tan":                  0xD2B48C,
-	"teal":                 0x008080,
-	"thistle":              0xD8BFD8,
-	"tomato":               0xFF6347,
-	"turquoise":            0x40E0D0,
-	"violet":               0xEE82EE,
-	"wheat":                0xF5DEB3,
-	"white":                0xFFFFFF,
-	"whitesmoke":           0xF5F5F5,
-	"yellow":               0xFFFF00,
-	"yellowgreen":          0x9ACD32,
+// mapColorNames maps standard web color names to a Color with
+// the standard web color's RGB component values
+var mapColorNames = map[string]Color{
+	"aliceblue":            Color{0.941, 0.973, 1.000},
+	"antiquewhite":         Color{0.980, 0.922, 0.843},
+	"aqua":                 Color{0.000, 1.000, 1.000},
+	"aquamarine":           Color{0.498, 1.000, 0.831},
+	"azure":                Color{0.941, 1.000, 1.000},
+	"beige":                Color{0.961, 0.961, 0.863},
+	"bisque":               Color{1.000, 0.894, 0.769},
+	"black":                Color{0.000, 0.000, 0.000},
+	"blanchedalmond":       Color{1.000, 0.922, 0.804},
+	"blue":                 Color{0.000, 0.000, 1.000},
+	"blueviolet":           Color{0.541, 0.169, 0.886},
+	"brown":                Color{0.647, 0.165, 0.165},
+	"burlywood":            Color{0.871, 0.722, 0.529},
+	"cadetblue":            Color{0.373, 0.620, 0.627},
+	"chartreuse":           Color{0.498, 1.000, 0.000},
+	"chocolate":            Color{0.824, 0.412, 0.118},
+	"coral":                Color{1.000, 0.498, 0.314},
+	"cornflowerblue":       Color{0.392, 0.584, 0.929},
+	"cornsilk":             Color{1.000, 0.973, 0.863},
+	"crimson":              Color{0.863, 0.078, 0.235},
+	"cyan":                 Color{0.000, 1.000, 1.000},
+	"darkblue":             Color{0.000, 0.000, 0.545},
+	"darkcyan":             Color{0.000, 0.545, 0.545},
+	"darkgoldenrod":        Color{0.722, 0.525, 0.043},
+	"darkgray":             Color{0.663, 0.663, 0.663},
+	"darkgreen":            Color{0.000, 0.392, 0.000},
+	"darkgrey":             Color{0.663, 0.663, 0.663},
+	"darkkhaki":            Color{0.741, 0.718, 0.420},
+	"darkmagenta":          Color{0.545, 0.000, 0.545},
+	"darkolivegreen":       Color{0.333, 0.420, 0.184},
+	"darkorange":           Color{1.000, 0.549, 0.000},
+	"darkorchid":           Color{0.600, 0.196, 0.800},
+	"darkred":              Color{0.545, 0.000, 0.000},
+	"darksalmon":           Color{0.914, 0.588, 0.478},
+	"darkseagreen":         Color{0.561, 0.737, 0.561},
+	"darkslateblue":        Color{0.282, 0.239, 0.545},
+	"darkslategray":        Color{0.184, 0.310, 0.310},
+	"darkslategrey":        Color{0.184, 0.310, 0.310},
+	"darkturquoise":        Color{0.000, 0.808, 0.820},
+	"darkviolet":           Color{0.580, 0.000, 0.827},
+	"deeppink":             Color{1.000, 0.078, 0.576},
+	"deepskyblue":          Color{0.000, 0.749, 1.000},
+	"dimgray":              Color{0.412, 0.412, 0.412},
+	"dimgrey":              Color{0.412, 0.412, 0.412},
+	"dodgerblue":           Color{0.118, 0.565, 1.000},
+	"firebrick":            Color{0.698, 0.133, 0.133},
+	"floralwhite":          Color{1.000, 0.980, 0.941},
+	"forestgreen":          Color{0.133, 0.545, 0.133},
+	"fuchsia":              Color{1.000, 0.000, 1.000},
+	"gainsboro":            Color{0.863, 0.863, 0.863},
+	"ghostwhite":           Color{0.973, 0.973, 1.000},
+	"gold":                 Color{1.000, 0.843, 0.000},
+	"goldenrod":            Color{0.855, 0.647, 0.125},
+	"gray":                 Color{0.502, 0.502, 0.502},
+	"green":                Color{0.000, 0.502, 0.000},
+	"greenyellow":          Color{0.678, 1.000, 0.184},
+	"grey":                 Color{0.502, 0.502, 0.502},
+	"honeydew":             Color{0.941, 1.000, 0.941},
+	"hotpink":              Color{1.000, 0.412, 0.706},
+	"indianred":            Color{0.804, 0.361, 0.361},
+	"indigo":               Color{0.294, 0.000, 0.510},
+	"ivory":                Color{1.000, 1.000, 0.941},
+	"khaki":                Color{0.941, 0.902, 0.549},
+	"lavender":             Color{0.902, 0.902, 0.980},
+	"lavenderblush":        Color{1.000, 0.941, 0.961},
+	"lawngreen":            Color{0.486, 0.988, 0.000},
+	"lemonchiffon":         Color{1.000, 0.980, 0.804},
+	"lightblue":            Color{0.678, 0.847, 0.902},
+	"lightcoral":           Color{0.941, 0.502, 0.502},
+	"lightcyan":            Color{0.878, 1.000, 1.000},
+	"lightgoldenrodyellow": Color{0.980, 0.980, 0.824},
+	"lightgray":            Color{0.827, 0.827, 0.827},
+	"lightgreen":           Color{0.565, 0.933, 0.565},
+	"lightgrey":            Color{0.827, 0.827, 0.827},
+	"lightpink":            Color{1.000, 0.714, 0.757},
+	"lightsalmon":          Color{1.000, 0.627, 0.478},
+	"lightseagreen":        Color{0.125, 0.698, 0.667},
+	"lightskyblue":         Color{0.529, 0.808, 0.980},
+	"lightslategray":       Color{0.467, 0.533, 0.600},
+	"lightslategrey":       Color{0.467, 0.533, 0.600},
+	"lightsteelblue":       Color{0.690, 0.769, 0.871},
+	"lightyellow":          Color{1.000, 1.000, 0.878},
+	"lime":                 Color{0.000, 1.000, 0.000},
+	"limegreen":            Color{0.196, 0.804, 0.196},
+	"linen":                Color{0.980, 0.941, 0.902},
+	"magenta":              Color{1.000, 0.000, 1.000},
+	"maroon":               Color{0.502, 0.000, 0.000},
+	"mediumaquamarine":     Color{0.400, 0.804, 0.667},
+	"mediumblue":           Color{0.000, 0.000, 0.804},
+	"mediumorchid":         Color{0.729, 0.333, 0.827},
+	"mediumpurple":         Color{0.576, 0.439, 0.859},
+	"mediumseagreen":       Color{0.235, 0.702, 0.443},
+	"mediumslateblue":      Color{0.482, 0.408, 0.933},
+	"mediumspringgreen":    Color{0.000, 0.980, 0.604},
+	"mediumturquoise":      Color{0.282, 0.820, 0.800},
+	"mediumvioletred":      Color{0.780, 0.082, 0.522},
+	"midnightblue":         Color{0.098, 0.098, 0.439},
+	"mintcream":            Color{0.961, 1.000, 0.980},
+	"mistyrose":            Color{1.000, 0.894, 0.882},
+	"moccasin":             Color{1.000, 0.894, 0.710},
+	"navajowhite":          Color{1.000, 0.871, 0.678},
+	"navy":                 Color{0.000, 0.000, 0.502},
+	"oldlace":              Color{0.992, 0.961, 0.902},
+	"olive":                Color{0.502, 0.502, 0.000},
+	"olivedrab":            Color{0.420, 0.557, 0.137},
+	"orange":               Color{1.000, 0.647, 0.000},
+	"orangered":            Color{1.000, 0.271, 0.000},
+	"orchid":               Color{0.855, 0.439, 0.839},
+	"palegoldenrod":        Color{0.933, 0.910, 0.667},
+	"palegreen":            Color{0.596, 0.984, 0.596},
+	"paleturquoise":        Color{0.686, 0.933, 0.933},
+	"palevioletred":        Color{0.859, 0.439, 0.576},
+	"papayawhip":           Color{1.000, 0.937, 0.835},
+	"peachpuff":            Color{1.000, 0.855, 0.725},
+	"peru":                 Color{0.804, 0.522, 0.247},
+	"pink":                 Color{1.000, 0.753, 0.796},
+	"plum":                 Color{0.867, 0.627, 0.867},
+	"powderblue":           Color{0.690, 0.878, 0.902},
+	"purple":               Color{0.502, 0.000, 0.502},
+	"red":                  Color{1.000, 0.000, 0.000},
+	"rosybrown":            Color{0.737, 0.561, 0.561},
+	"royalblue":            Color{0.255, 0.412, 0.882},
+	"saddlebrown":          Color{0.545, 0.271, 0.075},
+	"salmon":               Color{0.980, 0.502, 0.447},
+	"sandybrown":           Color{0.957, 0.643, 0.376},
+	"seagreen":             Color{0.180, 0.545, 0.341},
+	"seashell":             Color{1.000, 0.961, 0.933},
+	"sienna":               Color{0.627, 0.322, 0.176},
+	"silver":               Color{0.753, 0.753, 0.753},
+	"skyblue":              Color{0.529, 0.808, 0.922},
+	"slateblue":            Color{0.416, 0.353, 0.804},
+	"slategray":            Color{0.439, 0.502, 0.565},
+	"slategrey":            Color{0.439, 0.502, 0.565},
+	"snow":                 Color{1.000, 0.980, 0.980},
+	"springgreen":          Color{0.000, 1.000, 0.498},
+	"steelblue":            Color{0.275, 0.510, 0.706},
+	"tan":                  Color{0.824, 0.706, 0.549},
+	"teal":                 Color{0.000, 0.502, 0.502},
+	"thistle":              Color{0.847, 0.749, 0.847},
+	"tomato":               Color{1.000, 0.388, 0.278},
+	"turquoise":            Color{0.251, 0.878, 0.816},
+	"violet":               Color{0.933, 0.510, 0.933},
+	"wheat":                Color{0.961, 0.871, 0.702},
+	"white":                Color{1.000, 1.000, 1.000},
+	"whitesmoke":           Color{0.961, 0.961, 0.961},
+	"yellow":               Color{1.000, 1.000, 0.000},
+	"yellowgreen":          Color{0.604, 0.804, 0.196},
 }

+ 33 - 13
math32/color4.go

@@ -1,11 +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 math32
 
-import ()
+import (
+	"strings"
+)
 
+// Type Color4 describes an RGBA color
 type Color4 struct {
 	R float32
 	G float32
@@ -13,16 +15,33 @@ type Color4 struct {
 	A float32
 }
 
-var Black4 = Color4{0, 0, 0, 1}
-var White4 = Color4{1, 1, 1, 1}
-var Red4 = Color4{1, 0, 0, 1}
-var Green4 = Color4{0, 1, 0, 1}
-var Blue4 = Color4{0, 0, 1, 1}
-var Gray4 = Color4{0.5, 0.5, 0.5, 1}
+// NewColor4 creates and returns a pointer to a new Color4
+// with the specified standard web color name (case insensitive)
+// and an optional alpha channel value.
+// Returns nil if the specified color name not found
+func NewColor4(name string, alpha ...float32) *Color4 {
+
+	c, ok := mapColorNames[strings.ToLower(name)]
+	if !ok {
+		return nil
+	}
+	a := float32(1)
+	if len(alpha) > 0 {
+		a = alpha[0]
+	}
+	return &Color4{c.R, c.G, c.B, a}
+}
 
-func NewColor4(r, g, b, a float32) *Color4 {
+// Color4Name returns a Color4 with the specified standard web color name
+// and an optional alpha channel value.
+func Color4Name(name string, alpha ...float32) Color4 {
 
-	return &Color4{R: r, G: g, B: b, A: a}
+	c := mapColorNames[strings.ToLower(name)]
+	a := float32(1)
+	if len(alpha) > 0 {
+		a = alpha[0]
+	}
+	return Color4{c.R, c.G, c.B, a}
 }
 
 // Set sets this color individual R,G,B,A components
@@ -47,11 +66,11 @@ func (c *Color4) SetHex(value uint) *Color4 {
 }
 
 // SetName sets the color RGB components from the
-// specified HTML color name
-// Alpha component is not modified
+// specified standard web color name
 func (c *Color4) SetName(name string) *Color4 {
 
-	return c.SetHex(colorKeywords[name])
+	*c = Color4Name(name, 1)
+	return c
 }
 
 func (c *Color4) Add(other *Color4) *Color4 {
@@ -68,6 +87,7 @@ func (c *Color4) MultiplyScalar(v float32) *Color4 {
 	c.R *= v
 	c.G *= v
 	c.B *= v
+	c.A *= v
 	return c
 }
 

+ 2 - 2
text/font.go

@@ -65,8 +65,8 @@ func NewFontFromData(fontData []byte) (*Font, error) {
 	f.fontDPI = 72
 	f.lineSpacing = 1.0
 	f.hinting = font.HintingNone
-	f.SetFgColor4(math32.NewColor4(0, 0, 0, 1))
-	f.SetBgColor4(math32.NewColor4(1, 1, 1, 0))
+	f.SetFgColor4(&math32.Color4{0, 0, 0, 1})
+	f.SetBgColor4(&math32.Color4{1, 1, 1, 0})
 	f.changed = false
 
 	// Creates font face

+ 17 - 4
gui/assets/genicodes/main.go

@@ -16,11 +16,11 @@ import (
 
 // Command line options
 var (
-	oPackage = flag.String("p", "assets", "Package name")
+	oPackage = flag.String("pkg", "icon", "Package name")
 )
 
 const (
-	PROGNAME = "genicodes"
+	PROGNAME = "g3nicodes"
 	VMAJOR   = 0
 	VMINOR   = 1
 )
@@ -60,8 +60,8 @@ func main() {
 			log.Fatal(err)
 			return
 		}
+		defer fout.Close()
 	}
-	defer fout.Close()
 
 	// Parse input file
 	var td TemplateData
@@ -153,8 +153,21 @@ const templText = `//
 package {{.Packname}}
 const (
 	{{range .Consts}}
-		{{.Name}} = {{.Value}}
+		{{.Name}} = string({{.Value}})
 	{{- end}}
 )
 
+// IconCodepoint returns the codepoint for the specified icon name.
+// Returns 0 if the name not found
+func Codepoint(name string) string {
+
+	return name2Codepoint[name]
+}
+
+// Maps icon name to codepoint
+var name2Codepoint = map[string]string{
+	{{range .Consts}}
+		"{{.Name}}": string({{.Value}}),	
+	{{- end}}
+}
 `