Namespace mojo.app Class Theme Field ThemeChanged:Void() Method New() _defaultStyle=New Style _defaultStyle.Font=App.DefaultFont End Property Scale:Vec2f() Return _themeScale Setter( scale:Vec2f ) If scale=_themeScale Return _themeScale=scale Reload() End Property DefaultStyle:Style() Return _defaultStyle End #rem monkeydoc Gets a font from the theme. If no font named `name` is found, [[AppInstance.DefaultFont|App.DefaultFont]] is returned. #end Method GetFont:Font( name:String ) Local font:=_fonts[name] If font Return font Return App.DefaultFont End #rem monkeydoc Gets a color from the theme. If no color named `name` is found, [[std:std.graphics.Color.Grey|Color.Grey]] is returned. #end Method GetColor:Color( name:String ) If _colors.Contains( name ) Return _colors[name] Return Color.Grey End #rem monkeydoc Gets a style from the theme. If no style named `name` is found, the [[DefaultStyle]] for the theme is returned. #end Method GetStyle:Style( name:String ) Local style:=_styles[name] If style Return style Return _defaultStyle End #rem monkeydoc Loads a font from a file. If `file` is an absolute path, this method is effectively the same as calling [[Font.Load]]. If `file` is not an absolute path, the font is searched for in the following locations: * The theme's directory. * The asset::fonts/ directory. #end Method OpenFont:Font( path:String,size:Float ) size*=_themeScale.y Local font:Font If Not ExtractRootDir( path ) font=_res.OpenFont( "theme::"+path,size ) If Not font font=_res.OpenFont( path,size ) If Not font Return App.DefaultFont Return font End Method OpenImage:Image( path:String ) Local image:Image If Not ExtractRootDir( path ) image=_res.OpenImage( "theme::"+path ) If Not image image=_res.OpenImage( path ) If Not image Return null image.Scale=_themeScale Return image End #rem monkeydoc Loads an array of icon images from a file. Loads an array of icons from an image file. The icons should be square, and laid out in a horizontal 'strip' within the image file. The width and height of each image is taken from the height of the image file. The number of icons loaded is the width of the image file divided by its height. #end Method OpenIcons:Image[]( path:String ) Local slug:="Icons:"+StripDir( StripExt( path ) ) Local icons:=Cast( _res.OpenResource( slug ) ) If Not icons Local atlas:=OpenImage( path ) If Not atlas Return Null Local size:=atlas.Rect.Height Local n:=atlas.Rect.Width/size icons=New Icons icons.atlas=atlas icons.images=New Image[n] For Local i:=0 Until n Local image:=New Image( atlas,New Recti( i*size,0,i*size+size,size ) ) icons.images[i]=image Next _res.AddResource( slug,icons ) Endif For Local image:=Eachin icons.images image.Scale=_themeScale Next Return icons.images End #rem monkeydoc Loads a skin from a file. If `file` is an absolute path, this method is effectively the same as calling [[Skin.Load]]. If `file` is not an absolute path, the skin is searched for in the following locations: * The theme directory. * The asset::images/ directory. #end Method OpenSkin:Skin( path:String ) Local skin:Skin If Not ExtractRootDir( path ) skin=_res.OpenSkin( "theme::"+path ) If Not skin skin=_res.OpenSkin( path ) If Not skin Return Null skin.Image.Scale=_themeScale Return skin End Method Load:Bool( path:String,scale:Vec2f=New Vec2f( 1 ) ) If Not LoadJson( path ) Print "Failed to load theme:"+path return False Endif _themeScale=scale Reload() Return True End Private Class Icons Extends Resource Field atlas:Image Field images:Image[] End Const _jdefault:=New JsonString( "default" ) Field _res:ResourceManager Field _themeScale:Vec2f=New Vec2f( 1,1 ) Field _jcolors:StringMap Field _jfonts:StringMap Field _jstyles:StringMap Field _defaultStyle:Style Field _fonts:=New StringMap Field _colors:=New StringMap Field _styles:=New StringMap