diff --git a/demo/src/demo/AppTheme.hx b/demo/src/demo/AppTheme.hx index 8e08677..6a4acdb 100644 --- a/demo/src/demo/AppTheme.hx +++ b/demo/src/demo/AppTheme.hx @@ -14,12 +14,12 @@ class AppTheme extends Theme { override private function reload():Void { super.reload(); - data.set("view", create([ + register(new Style("view", [ "skin.background.color" => colors.light, "skin.border.color" => colors.border, "geometry.padding" => Box.fromFloat(3), ], ["text"])); - data.set("test", create([ + register(new Style("test", [ "skin.background.color" => Color.fromInt(0x00ffff), ])); } diff --git a/src/main/haxework/view/theme/Theme.hx b/src/main/haxework/view/theme/Theme.hx index 6719fef..0b78a94 100644 --- a/src/main/haxework/view/theme/Theme.hx +++ b/src/main/haxework/view/theme/Theme.hx @@ -11,17 +11,31 @@ import haxework.view.theme.ITheme; using haxework.color.ColorUtil; +class Style { + public var id(default, null):StyleId; + public var parent(default, null):StyleId; + public var data(default, null):Map; + + public function new(id:StyleId, data:Map, ?parent:StyleId) { + this.id = id; + this.parent = parent; + this.data = data; + } +} + class Theme implements ITheme { public var font(default, set):ThemeFont; public var fontSize(default, set):ThemeFontSize; public var colors(default, set):ThemeColors; public var updateSignal(default, null):Signal0; - private var data:Map>; + private var data:Map; + private var cache:Map; public function new(?font:ThemeFont, ?colors:ThemeColors, ?fontSize:ThemeFontSize) { updateSignal = new Signal0(); data = new Map(); + cache = new Map(); this.font = font; this.colors = colors; this.fontSize = fontSize; @@ -47,25 +61,12 @@ class Theme implements ITheme { return colors; } - private function create(values:Map, ?parents:Array):Map { - if (parents != null) { - for (key in parents) { - var parent = data.get(key); - for (property in parent.keys()) { - if (!values.exists(property)) { - values.set(property, parent.get(property)); - } - } - } - } - return values; - } - private function _reload():Void { if (colors == null || font == null || fontSize == null) { return; } reload(); + cache = new Map(); // ToDo: hardcode update views if (Root.instance != null) { for (view in Root.instance.views()) { @@ -75,51 +76,56 @@ class Theme implements ITheme { updateSignal.emit(); } + private function register(style:Style):Void { + data.set(style.id, style); + } + private function reload():Void { - data.set("background", [ + register(new Style("background", [ "skin.background.color" => colors.dark, - ]); - data.set("border", [ + ])); + register(new Style("border", [ "skin.border.color" => colors.border, - ]); - data.set("frame", create([ + ])); + register(new Style("frame", [ "geometry.padding" => Box.fromFloat(2), ], ["background", "border"])); - data.set("text", [ + register(new Style("text", [ "font.color" => colors.text, "font.family" => font.name, "font.embed" => font.embed, "font.size" => fontSize.base, - ]); - data.set("text0", create([ + ])); + register(new Style("text0", [ "skin.background.color" => colors.light.diff(-16), ], ["text"])); - data.set("text1", create([ + register(new Style("text1", [ "skin.background.color" => colors.light.diff(16), ], ["text"])); - data.set("label", create([ + register(new Style("label", [ "geometry.padding" => Box.fromArray([8, 2]), ], ["text"])); - data.set("button", create([ + register(new Style("button", [ "skin.color" => colors.light, "geometry.padding" => Box.fromArray([25, 8]), ], ["text"])); - data.set("button.active", create([ + register(new Style("button.active", [ "skin.borderColor" => colors.active, + "font.color" => colors.active, ], ["button"])); - data.set("button.tab", create([ + register(new Style("button.tab", [ "skin" => function() return new TabColorSkin(), ], ["button"])); - data.set("dropdown", create([ + register(new Style("dropdown", [ "_" => null, ], ["background", "border"])); - data.set("scroll.vertical", create([ + register(new Style("scroll.vertical", [ "skin.foreColor" => colors.light, "skin.backColor" => colors.dark, "geometry.width" => SizeValue.fromFloat(10), "geometry.height" => SizeValue.fromString("100%"), ])); - data.set("scroll.horizontal", create([ + register(new Style("scroll.horizontal", [ "skin.foreColor" => colors.light, "skin.backColor" => colors.dark, "geometry.width" => SizeValue.fromString("100%"), @@ -127,8 +133,33 @@ class Theme implements ITheme { ])); } + private function _resolve(key:String, style:Style):Null { + if (style == null) { + return null; + } else if (style.data.exists(key)) { + return style.data.get(key); + } else if (style.parent != null) { + for (s in style.parent.toArray()) { + var result = _resolve(key, data.get(s)); + if (result != null) { + return result; + } + } + } + return null; + } + public function resolve(key:String, style:StyleId):T { - var result:Dynamic = style != null && data.exists(style) ? data.get(style).get(key) : null; + var result:Dynamic = null; + if (style != null) { + var k = key + "." + style; + if (cache.exists(k)) { + result = cache.get(k); + } else { + result = _resolve(key, data.get(style)); + cache.set(k, result); + } + } if (Reflect.isFunction(result)) { result = result(); }