diff --git a/demo/src/demo/AppTheme.hx b/demo/src/demo/AppTheme.hx index e3024ec..8803270 100644 --- a/demo/src/demo/AppTheme.hx +++ b/demo/src/demo/AppTheme.hx @@ -1,6 +1,8 @@ package demo; import haxework.color.Color; +import haxework.view.skin.Skin; +import haxework.view.theme.SkinStyle; import haxework.view.theme.Theme; using haxework.color.ColorUtil; @@ -13,7 +15,7 @@ class AppTheme extends Theme { override private function reload():Void { super.reload(); -// data.put("view", text().concat(background(colors.light)).concat(border())); -// data.put("test", [Skin.color(0x00ffff)]); + styles.put("view", text().concat(background(colors.light, true))); + styles.put("test", [new SkinStyle(Skin.color(0x00ffff))]); } } diff --git a/demo/src/demo/Demo.hx b/demo/src/demo/Demo.hx index e410866..86a4855 100644 --- a/demo/src/demo/Demo.hx +++ b/demo/src/demo/Demo.hx @@ -17,7 +17,7 @@ import haxework.view.IView; @:view var tabs:IGroupView; private function init():Void { - switcher.change("list"); + switcher.change("test_layout"); } private function onFrameSwitch(frame:IView):Void { diff --git a/demo/src/demo/DemoView.yaml b/demo/src/demo/DemoView.yaml index a93ec8e..dceed7a 100644 --- a/demo/src/demo/DemoView.yaml +++ b/demo/src/demo/DemoView.yaml @@ -1,6 +1,5 @@ --- style: background -geometry.stretch: true views: - $type: haxework.view.ImageView geometry.padding: 10 diff --git a/demo/src/demo/popup/ColorPopup.hx b/demo/src/demo/popup/ColorPopup.hx index 62f9829..47bb881 100644 --- a/demo/src/demo/popup/ColorPopup.hx +++ b/demo/src/demo/popup/ColorPopup.hx @@ -9,6 +9,7 @@ import haxework.view.skin.Skin; private function colorViewFactory(index:Int, color:Int) { var view = new ButtonView(); view.setSize(48, 48, "fixed"); + view.geometry.padding = 0; view.skin = Skin.buttonColor(color); return view; } diff --git a/demo/src/demo/test/TestView.yaml b/demo/src/demo/test/TestView.yaml index e8e0994..79110f2 100644 --- a/demo/src/demo/test/TestView.yaml +++ b/demo/src/demo/test/TestView.yaml @@ -7,21 +7,24 @@ views: layout.margin: 10 layout.vAlign: middle skin: - $type: haxework.view.skin.ColorSkin - color: 0xffff00 + $type: haxework.view.skin.SpriteSkin + background.color: 0xffff00 + background.alpha: 1 views: - $type: haxework.view.SpriteView geometry.width: 100 geometry.height: 100 skin: - $type: haxework.view.skin.ColorSkin - color: 0xff0000 + $type: haxework.view.skin.SpriteSkin + background.color: 0xff0000 + background.alpha: 1 - $type: haxework.view.group.VGroupView geometry.padding: 10 layout.margin: 10 skin: - $type: haxework.view.skin.ColorSkin - color: 0x00ffff + $type: haxework.view.skin.SpriteSkin + background.color: 0x00ffff + background.alpha: 1 views: - $type: haxework.view.SpriteView geometry.width: 100 @@ -29,31 +32,30 @@ views: size: _test_: [200, 200] skin: - $type: haxework.view.skin.ColorSkin - color: 0xff0000 + $type: haxework.view.skin.SpriteSkin + background.color: 0xff0000 + background.alpha: 1 - $type: haxework.view.SpriteView geometry.width: 100 geometry.height: 100 skin: - $type: haxework.view.skin.ColorSkin - color: 0xff0000 - - $type: haxework.view.list.VListView - factory: ~haxework.view.list.LabelListItem.factory - geometry.width: 100 - geometry.height: 100 - scroll: - $type: haxework.view.list.VScrollBarView - data: - - "aaa" + $type: haxework.view.skin.SpriteSkin + background.color: 0xff0000 + background.alpha: 1 + - $type: haxework.view.text.TextView + geometry.padding: 20 + text: "Azazaza" - $type: haxework.view.SpriteView geometry.width: 60% geometry.height: 100% skin: - $type: haxework.view.skin.ColorSkin - color: 0xff0000 + $type: haxework.view.skin.SpriteSkin + background.color: 0xff0000 + background.alpha: 1 - $type: haxework.view.SpriteView geometry.width: 40% geometry.height: 80% skin: - $type: haxework.view.skin.ColorSkin - color: 0xff0000 + $type: haxework.view.skin.SpriteSkin + background.color: 0xff0000 + background.alpha: 1 diff --git a/src/main/haxework/view/IView.hx b/src/main/haxework/view/IView.hx index 16b15d2..c20d65e 100755 --- a/src/main/haxework/view/IView.hx +++ b/src/main/haxework/view/IView.hx @@ -3,13 +3,14 @@ package haxework.view; import flash.display.DisplayObject; import flash.geom.Rectangle; import haxework.view.geometry.Geometry; +import haxework.view.geometry.Size; import haxework.view.group.IGroupView; import haxework.view.skin.ISkin; import haxework.view.theme.StyleId; interface IView { @:style public var geometry(default, default):Geometry; - @:style public var skin(default, default):ISkin; + @:style public var skin(default, set):ISkin; public var id(default, default):String; @@ -19,7 +20,9 @@ interface IView { public var width(default, null):Float; public var height(default, null):Float; - public var style(default, default):StyleId; + public var size(default, null):Size; + + public var style(default, set):StyleId; public var content(default, null):C; diff --git a/src/main/haxework/view/ImageView.hx b/src/main/haxework/view/ImageView.hx index d141ca1..7c3f8ec 100755 --- a/src/main/haxework/view/ImageView.hx +++ b/src/main/haxework/view/ImageView.hx @@ -20,6 +20,7 @@ class ImageView extends SpriteView { public function new(image:BitmapData = null) { super(); fillType = FillType.DEFAULT; + skin = bitmapSkin; if (image != null) { this.image = image; } diff --git a/src/main/haxework/view/SpriteView.hx b/src/main/haxework/view/SpriteView.hx index 1faed34..cb7b153 100755 --- a/src/main/haxework/view/SpriteView.hx +++ b/src/main/haxework/view/SpriteView.hx @@ -1,17 +1,17 @@ package haxework.view; -import haxework.view.skin.ColorSkin; import flash.display.Sprite; +import haxework.view.skin.Skin; class SpriteView extends View { public function new() { super(new Sprite()); - skin = new ColorSkin(0, 0); + skin = Skin.transparent; } override public function redraw():Void { - this.content.graphics.clear(); + this.content.graphics.clear(); // ToDo: in skin super.redraw(); #if dev_layout var graphics = content.graphics; diff --git a/src/main/haxework/view/View.hx b/src/main/haxework/view/View.hx index 71c5ad7..5644219 100755 --- a/src/main/haxework/view/View.hx +++ b/src/main/haxework/view/View.hx @@ -4,6 +4,7 @@ import flash.display.DisplayObject; import flash.display.InteractiveObject; import flash.geom.Rectangle; import haxework.view.geometry.Geometry; +import haxework.view.geometry.Size; import haxework.view.geometry.SizeSet; import haxework.view.group.IGroupView; import haxework.view.skin.ISkin; @@ -18,8 +19,8 @@ class View implements IView { @:provide var theme:ITheme; public var geometry(default, default):Geometry; - public var skin(default, default):ISkin; - public var style(default, default):StyleId; + public var skin(default, set):ISkin; + public var style(default, set):StyleId; public var id(default, default):String; @@ -29,6 +30,8 @@ class View implements IView { public var width(default, null):Float; public var height(default, null):Float; + public var size(default, null):Size; + public var content(default, null):C; public var parent(default, null):Null; @@ -39,11 +42,12 @@ class View implements IView { public var rect(get, null):Rectangle; - private var size:SizeSet; + private var sizeSet:SizeSet; public function new(content:C) { id = Type.getClassName(Type.getClass(this)) + counter++; - size = new SizeSet(); + sizeSet = new SizeSet(); + size = 0; this.content = content; x = 0; y = 0; @@ -80,10 +84,13 @@ class View implements IView { } public function setSize(width:Float, height:Float, type:String = "default"):Void { - if (size.update([width, height], type)) { - var s = size.toSize(); - this.width = s.width; - this.height = s.height; + if (sizeSet.update([width, height], type)) { + var s = sizeSet.toSize(); + this.width = s.width + geometry.padding.horizontal; + this.height = s.height + geometry.padding.vertical; + size = sizeSet.toSize(false); + size.width += geometry.padding.horizontal; + size.height += geometry.padding.vertical; toUpdateParent(); toRedraw(); } @@ -113,6 +120,16 @@ class View implements IView { return this.skin; } + private function set_style(value:StyleId):StyleId { + if (value != null && style != value) { + style = value; + if (theme != null) { + theme.bind(style, this); + } + } + return style; + } + private function set_visible(value:Bool):Bool { if (visible != value) { visible = value; diff --git a/src/main/haxework/view/geometry/Box.hx b/src/main/haxework/view/geometry/Box.hx index 0b828c4..44dc00b 100644 --- a/src/main/haxework/view/geometry/Box.hx +++ b/src/main/haxework/view/geometry/Box.hx @@ -65,6 +65,10 @@ abstract Box(Array) { } } + public function clone():Box { + return new Box(this); + } + @:from static public inline function fromArray(value:Array):Box { return new Box(value); } diff --git a/src/main/haxework/view/geometry/SizeSet.hx b/src/main/haxework/view/geometry/SizeSet.hx index 6199559..91424d9 100644 --- a/src/main/haxework/view/geometry/SizeSet.hx +++ b/src/main/haxework/view/geometry/SizeSet.hx @@ -17,11 +17,14 @@ class SizeSet extends StringMap { return false; } - public function toSize():Size { + public function toSize(percent:Bool = true):Size { var result:Size = 0; - for (value in iterator()) { - result.width = Math.max(result.width, value.width); - result.height = Math.max(result.height, value.height); + for (type in keys()) { + if (percent || type.indexOf("percent") == -1) { + var value = get(type); + result.width = Math.max(result.width, value.width); + result.height = Math.max(result.height, value.height); + } } return result; } diff --git a/src/main/haxework/view/layout/DefaultLayout.hx b/src/main/haxework/view/layout/DefaultLayout.hx index d9dd7e5..117365c 100755 --- a/src/main/haxework/view/layout/DefaultLayout.hx +++ b/src/main/haxework/view/layout/DefaultLayout.hx @@ -15,8 +15,8 @@ class DefaultLayout extends Layout { setViewHeight(group, view); placeViewHorizontal(group, view); placeViewVertical(group, view); - width = Math.max(width, view.width + view.geometry.margin.horizontal); - height = Math.max(height, view.height + view.geometry.margin.horizontal); + width = Math.max(width, view.size.width + view.geometry.margin.horizontal); + height = Math.max(height, view.size.height + view.geometry.margin.horizontal); } if (!overflow) group.setSize(width, height, "group"); } @@ -38,11 +38,11 @@ class DefaultLayout extends Layout { } private function setViewWidth(group:IGroupView, view:IView):Void { - view.setSize(view.geometry.width.percent / 100 * (group.width - view.geometry.margin.horizontal - group.geometry.padding.horizontal), 0, "percent.width"); + view.setSize(view.geometry.width.percent / 100 * (group.width - view.geometry.margin.horizontal - group.geometry.padding.horizontal) - view.geometry.padding.horizontal, 0, "percent.width"); } private function setViewHeight(group:IGroupView, view:IView):Void { - view.setSize(0, view.geometry.height.percent / 100 * (group.height - view.geometry.margin.vertical - group.geometry.padding.vertical), "percent.height"); + view.setSize(0, view.geometry.height.percent / 100 * (group.height - view.geometry.margin.vertical - group.geometry.padding.vertical) - view.geometry.padding.vertical, "percent.height"); } private function placeViewHorizontal(group:IGroupView, view:IView):Void { diff --git a/src/main/haxework/view/layout/HorizontalLayout.hx b/src/main/haxework/view/layout/HorizontalLayout.hx index b2eff44..bf645f6 100755 --- a/src/main/haxework/view/layout/HorizontalLayout.hx +++ b/src/main/haxework/view/layout/HorizontalLayout.hx @@ -10,21 +10,19 @@ class HorizontalLayout extends DefaultLayout { override public function place(group:IGroupView, views:Array>):Void { views = filterViews(group, views); - var fixedSize:Float = group.geometry.padding.horizontal + margin * (views.length - 1); - var leftSize:Float = group.width; + var fixedSize:Float = margin * (views.length - 1); + var leftSize:Float = group.width - group.geometry.padding.horizontal; - var maxSize:Float = group.geometry.padding.vertical; + var maxSize:Float = 0; for (view in views) { - setViewHeight(group, view); - placeViewVertical(group, view); switch view.geometry.width.type { case PERCENT: leftSize -= (view.geometry.margin.horizontal); case FIXED: fixedSize += (view.width + view.geometry.margin.horizontal); } - maxSize = Math.max(maxSize, view.height + view.geometry.margin.vertical + group.geometry.padding.vertical); + maxSize = Math.max(maxSize, view.size.height + view.geometry.margin.vertical); } if (!overflow) group.setSize(fixedSize, maxSize, "group"); @@ -35,7 +33,7 @@ class HorizontalLayout extends DefaultLayout { case PERCENT: var result = view.geometry.width.value / 100 * leftSize; fixedSize += result + view.geometry.margin.horizontal; - view.setSize(result, 0, "percent.width"); + view.setSize(result - view.geometry.padding.horizontal, 0, "percent.width"); case _: }; } @@ -50,6 +48,8 @@ class HorizontalLayout extends DefaultLayout { for (view in views) { view.x = x + view.geometry.margin.left; x += (view.width + view.geometry.margin.horizontal + margin); + setViewHeight(group, view); + placeViewVertical(group, view); } } } diff --git a/src/main/haxework/view/layout/VerticalLayout.hx b/src/main/haxework/view/layout/VerticalLayout.hx index c40b2f5..76fae49 100755 --- a/src/main/haxework/view/layout/VerticalLayout.hx +++ b/src/main/haxework/view/layout/VerticalLayout.hx @@ -10,21 +10,19 @@ class VerticalLayout extends DefaultLayout { override public function place(group:IGroupView, views:Array>):Void { views = filterViews(group, views); - var fixedSize:Float = group.geometry.padding.vertical + margin * (views.length - 1); - var leftSize:Float = group.height; + var fixedSize:Float = margin * (views.length - 1); + var leftSize:Float = group.height - group.geometry.padding.vertical; - var maxSize:Float = group.geometry.padding.horizontal; + var maxSize:Float = 0; for (view in views) { - setViewWidth(group, view); - placeViewHorizontal(group, view); switch view.geometry.height.type { case PERCENT: leftSize -= (view.geometry.margin.vertical); case FIXED: fixedSize += (Math.max(view.geometry.height.value, view.height) + view.geometry.margin.vertical); } - maxSize = Math.max(maxSize, view.width + view.geometry.margin.horizontal + group.geometry.padding.horizontal); + maxSize = Math.max(maxSize, view.size.width + view.geometry.margin.horizontal); } if (!overflow) group.setSize(maxSize, fixedSize, "group"); @@ -35,7 +33,7 @@ class VerticalLayout extends DefaultLayout { case PERCENT: var result = view.geometry.height.value / 100 * leftSize; fixedSize += result + view.geometry.margin.vertical; - view.setSize(0, result, "percent.height"); + view.setSize(0, result - view.geometry.padding.vertical, "percent.height"); case _: }; } @@ -50,6 +48,8 @@ class VerticalLayout extends DefaultLayout { for (view in views) { view.y = y + view.geometry.margin.top; y += (view.height + view.geometry.margin.vertical + margin); + setViewWidth(group, view); + placeViewHorizontal(group, view); } } } diff --git a/src/main/haxework/view/skin/BorderSkin.hx b/src/main/haxework/view/skin/BorderSkin.hx deleted file mode 100644 index d87e3dd..0000000 --- a/src/main/haxework/view/skin/BorderSkin.hx +++ /dev/null @@ -1,20 +0,0 @@ -package haxework.view.skin; - -class BorderSkin implements ISkin { - - public var color(default, default):Int; - public var alpha(default, default):Float; - public var tickness(default, default):Float; - - public function new(color:Int = 0xffffff, alpha:Float = 1.0, tickness: Float = 1.0) { - this.color = color; - this.alpha = alpha; - this.tickness = tickness; - } - - public function draw(view:SpriteView):Void { - view.content.graphics.lineStyle(tickness, color, alpha, true); - view.content.graphics.drawRect(tickness / 2, tickness / 2, view.width - tickness, view.height - tickness); - view.content.graphics.lineStyle(); - } -} diff --git a/src/main/haxework/view/skin/ColorSkin.hx b/src/main/haxework/view/skin/ColorSkin.hx deleted file mode 100644 index 050dbc2..0000000 --- a/src/main/haxework/view/skin/ColorSkin.hx +++ /dev/null @@ -1,18 +0,0 @@ -package haxework.view.skin; - -class ColorSkin implements ISkin { - - public var color(default, default):Int; - public var alpha(default, default):Float; - - public function new(color:Int = 0xffffff, alpha:Float = 1.0) { - this.color = color; - this.alpha = alpha; - } - - public function draw(view:SpriteView):Void { - view.content.graphics.beginFill(color, alpha); - view.content.graphics.drawRect(0, 0, view.width, view.height); - view.content.graphics.endFill(); - } -} diff --git a/src/main/haxework/view/skin/Skin.hx b/src/main/haxework/view/skin/Skin.hx index 84085e1..db7d396 100644 --- a/src/main/haxework/view/skin/Skin.hx +++ b/src/main/haxework/view/skin/Skin.hx @@ -6,18 +6,14 @@ import haxework.view.utils.DrawUtil; class Skin { - public static var transparent(default, never):ISkin = new ColorSkin(0, 0); + public static var transparent(default, never):ISkin = new SpriteSkin({color: 0, alpha: 0}); public static function bitmap(image:BitmapData, fillType:FillType = null):ISkin { return new BitmapSkin(image, fillType); } public static function color(color:Int, alpha:Float = 1.0):ISkin { - return new ColorSkin(color, alpha); - } - - public static function border(color:Int, alpha:Float = 1.0, tickness:Float = 1.0):ISkin { - return new BorderSkin(color, alpha, tickness); + return new SpriteSkin({color: color, alpha: alpha}); } public static function buttonColor(color:Int, borderColor:Int = -1):ISkin { diff --git a/src/main/haxework/view/skin/SpriteSkin.hx b/src/main/haxework/view/skin/SpriteSkin.hx new file mode 100644 index 0000000..78c45e0 --- /dev/null +++ b/src/main/haxework/view/skin/SpriteSkin.hx @@ -0,0 +1,55 @@ +package haxework.view.skin; + +import flash.display.Graphics; +import haxework.color.Color; + +typedef Border = { + @:optional var color:Color; + @:optional var thickness:Float; + @:optional var alpha:Float; +} + +typedef Background = { + @:optional var color:Color; + @:optional var alpha:Float; +} + +class SpriteSkin implements ISkin { + + public var border(default, default):Border; + public var background(default, default):Background; + + public function new(?background:Background, ?border:Border) { + this.background = resolveBackground(background); + this.border = resolveBorder(border); + } + + private static function resolveBackground(value:Background):Background { + return value != null ? { + color: value.color != null ? value.color : 0x000000, + alpha: value.alpha != null ? value.alpha : 1.0 + } : {}; + } + + private static function resolveBorder(value:Border):Border { + return value != null ? { + color: value.color != null ? value.color : 0x000000, + alpha: value.alpha != null ? value.alpha : 1.0, + thickness: value.thickness != null ? value.thickness : 1 + } : {}; + } + + public function draw(view:SpriteView):Void { + var graphics:Graphics = view.content.graphics; + graphics.clear(); + if (border.color != null) { + graphics.lineStyle(border.thickness, border.color, border.alpha, true); + } + if (background.color != null) { + graphics.beginFill(background.color, background.alpha); + } + graphics.drawRect(0, 0, view.width, view.height); + graphics.lineStyle(); + graphics.endFill(); + } +} diff --git a/src/main/haxework/view/text/FontPreset.hx b/src/main/haxework/view/text/FontPreset.hx new file mode 100644 index 0000000..900e013 --- /dev/null +++ b/src/main/haxework/view/text/FontPreset.hx @@ -0,0 +1,23 @@ +package haxework.view.text; + +import haxework.color.Color; +import flash.text.TextFormatAlign; + +class FontPreset { + public var family(default, default):String; + public var embed(default, default):Bool; + public var color(default, default):Color; + public var size(default, default):Int; + public var bold(default, default):Bool; + public var align(default, default):TextFormatAlign; + + public function new(family:String = null, embed:Bool = false, color:Color = null, size:Int = 16, + bold:Bool = false, align:TextFormatAlign = null) { + this.family = family; + this.embed = embed; + this.color = color != null ? color : 0xffffff; + this.size = size; + this.bold = bold; + this.align = align; + } +} diff --git a/src/main/haxework/view/text/FontStyle.hx b/src/main/haxework/view/text/FontStyle.hx deleted file mode 100644 index 3d14af3..0000000 --- a/src/main/haxework/view/text/FontStyle.hx +++ /dev/null @@ -1,21 +0,0 @@ -package haxework.view.text; - -import flash.text.TextFormatAlign; - -class FontStyle { - public var family(default, default):String; - public var embed(default, default):Bool; - public var color(default, default):Int; - public var size(default, default):Int; - public var bold(default, default):Bool; - public var align(default, default):TextFormatAlign; - - public function new() { - family = null; - embed = false; - color = 0xffffff; - size = 16; - bold = false; - align = null; - } -} diff --git a/src/main/haxework/view/text/ITextView.hx b/src/main/haxework/view/text/ITextView.hx index cd13e59..9426d77 100755 --- a/src/main/haxework/view/text/ITextView.hx +++ b/src/main/haxework/view/text/ITextView.hx @@ -5,7 +5,7 @@ import haxework.view.IView; import haxework.view.layout.ILayout; interface ITextView extends IView { - @:style public var font(default, default):FontStyle; + @:style public var font(default, default):FontPreset; @:style public var layout(default, default):ILayout; public var textField(default, null):TextField; diff --git a/src/main/haxework/view/text/TextView.hx b/src/main/haxework/view/text/TextView.hx index fb0841d..ea0453e 100755 --- a/src/main/haxework/view/text/TextView.hx +++ b/src/main/haxework/view/text/TextView.hx @@ -12,7 +12,7 @@ import haxework.view.layout.ILayout; import haxework.view.layout.Layout; class TextView extends SpriteView implements ITextView { - public var font(default, default):FontStyle; + public var font(default, default):FontPreset; public var layout(default, default):ILayout; public var textField(default, null):TextField; @@ -27,7 +27,7 @@ class TextView extends SpriteView implements ITextView { public function new() { super(); - font = new FontStyle(); + font = new FontPreset(); style = "text"; layout = new Layout(); textField = buildTextField(); diff --git a/src/main/haxework/view/theme/FontStyle.hx b/src/main/haxework/view/theme/FontStyle.hx new file mode 100644 index 0000000..3dad054 --- /dev/null +++ b/src/main/haxework/view/theme/FontStyle.hx @@ -0,0 +1,18 @@ +package haxework.view.theme; + +import haxework.view.text.ITextView; +import haxework.view.text.FontPreset; + +class FontStyle implements IStyle { + + private var font:FontPreset; + + public function new(font:FontPreset) { + this.font = font; + } + + public function apply(view:ITextView):Void { + view.font = font; + view.toUpdate(); + } +} diff --git a/src/main/haxework/view/theme/GeometryStyle.hx b/src/main/haxework/view/theme/GeometryStyle.hx new file mode 100644 index 0000000..2def7a0 --- /dev/null +++ b/src/main/haxework/view/theme/GeometryStyle.hx @@ -0,0 +1,23 @@ +package haxework.view.theme; + +import haxework.view.geometry.Geometry; + +class GeometryStyle implements IStyle> { + + private var geometry:Geometry; + + public function new(geometry:Geometry) { + this.geometry = geometry; + } + + public function apply(view:IView):Void { + var update = false; + if (!geometry.padding.empty) { + view.geometry.padding = geometry.padding.clone(); + update = true; + } + if (update) { + view.toUpdateParent(); + } + } +} diff --git a/src/main/haxework/view/theme/IStyle.hx b/src/main/haxework/view/theme/IStyle.hx new file mode 100644 index 0000000..1320f98 --- /dev/null +++ b/src/main/haxework/view/theme/IStyle.hx @@ -0,0 +1,5 @@ +package haxework.view.theme; + +interface IStyle> { + public function apply(view:V):Void; +} diff --git a/src/main/haxework/view/theme/ITheme.hx b/src/main/haxework/view/theme/ITheme.hx index 63ef6fe..ad85637 100644 --- a/src/main/haxework/view/theme/ITheme.hx +++ b/src/main/haxework/view/theme/ITheme.hx @@ -18,6 +18,5 @@ typedef ThemeColors = { interface ITheme { public var font(default, set):ThemeFont; public var colors(default, set):ThemeColors; - - public function bind(styles:Array, view:IView):Void; + public function bind(style:StyleId, view:IView):Void; } diff --git a/src/main/haxework/view/theme/LayoutStyle.hx b/src/main/haxework/view/theme/LayoutStyle.hx new file mode 100644 index 0000000..f1981bd --- /dev/null +++ b/src/main/haxework/view/theme/LayoutStyle.hx @@ -0,0 +1,18 @@ +package haxework.view.theme; + +import haxework.view.group.IGroupView; +import haxework.view.layout.ILayout; + +class LayoutStyle implements IStyle { + + private var layout:ILayout; + + public function new(layout:ILayout) { + this.layout = layout; + } + + public function apply(view:IGroupView):Void { + view.layout = layout; + view.toUpdate(); + } +} diff --git a/src/main/haxework/view/theme/SkinStyle.hx b/src/main/haxework/view/theme/SkinStyle.hx new file mode 100644 index 0000000..6e1a850 --- /dev/null +++ b/src/main/haxework/view/theme/SkinStyle.hx @@ -0,0 +1,17 @@ +package haxework.view.theme; + +import haxework.view.skin.ISkin; + +class SkinStyle implements IStyle> { + + private var skin:ISkin; + + public function new(skin:ISkin) { + this.skin = skin; + } + + public function apply(view:IView):Void { + view.skin = skin; + view.toRedraw(); + } +} diff --git a/src/main/haxework/view/theme/StyleId.hx b/src/main/haxework/view/theme/StyleId.hx index e49f0cd..81ed490 100644 --- a/src/main/haxework/view/theme/StyleId.hx +++ b/src/main/haxework/view/theme/StyleId.hx @@ -3,7 +3,7 @@ package haxework.view.theme; abstract StyleId(Array) { public function new(value:Array) { - this = value; + this = value != null ? value : []; } @:to public inline function toArray():Array { diff --git a/src/main/haxework/view/theme/Theme.hx b/src/main/haxework/view/theme/Theme.hx index 3d23f5d..ca635d5 100644 --- a/src/main/haxework/view/theme/Theme.hx +++ b/src/main/haxework/view/theme/Theme.hx @@ -2,11 +2,57 @@ package haxework.view.theme; import flash.text.Font; import flash.text.FontType; +import haxe.ds.StringMap; import haxework.color.Color; +import haxework.view.geometry.Geometry; +import haxework.view.skin.Skin; +import haxework.view.skin.SpriteSkin; +import haxework.view.text.FontPreset; import haxework.view.theme.ITheme; using haxework.color.ColorUtil; +typedef StyleSet = Array>; + +class StyleMap extends StringMap { + + private var views:Map, String> = new Map(); + private var viewsByStyle:Map>> = new Map(); + + private function apply(styles:StyleSet, view:IView):Void { + for (item in styles) { + item.apply(view); + } + } + + public function put(key:String, value:StyleSet):Void { + set(key, value); + if (viewsByStyle.exists(key)) { + for (view in viewsByStyle.get(key)) { + apply(value, view); + } + } + } + + public function connect(key:String, view:IView):Void { + disconnect(view); + if (!viewsByStyle.exists(key)) { + viewsByStyle.set(key, []); + } + viewsByStyle.get(key).push(view); + if (exists(key)) { + apply(get(key), view); + } + } + + public function disconnect(view:IView):Void { + if (views.exists(view)) { + viewsByStyle.get(views.get(view)).remove(view); + views.remove(view); + } + } +} + class Theme implements ITheme { // ToDo: configurable public var baseFontSize = 18; @@ -16,7 +62,10 @@ class Theme implements ITheme { public var font(default, set):ThemeFont; public var colors(default, set):ThemeColors; + private var styles:StyleMap; + public function new(?font:ThemeFont, ?colors:ThemeColors) { + styles = new StyleMap(); this.font = font; this.colors = colors; L.d("Theme", 'font: ${this.font}'); @@ -39,12 +88,74 @@ class Theme implements ITheme { return colors; } - private function reload():Void { + private function reload():Void { + styles.put("background", background()); + styles.put("border", background(null, true)); + styles.put("frame", background(null, true).concat([new GeometryStyle(new Geometry().setPadding(2))])); + + styles.put("text", text()); + styles.put("label", text().concat([new GeometryStyle(new Geometry().setPadding([8, 2]))])); + styles.put("button", button()); + styles.put("dropdown", background(null, true)); + styles.put("tab", text().concat([ + new SkinStyle(Skin.tabColor(this.colors.light)), + new GeometryStyle(new Geometry().setPadding([25, 8])) + ])); + + styles.put("text0", text().concat(background(this.colors.light.diff(-16)))); + styles.put("text1", text().concat(background(this.colors.light.diff(16)))); + styles.put("scroll.vertical", [ + new SkinStyle(Skin.scrollVertical(this.colors.light, this.colors.dark)), + ]); + styles.put("scroll.horizontal", [ + new SkinStyle(Skin.scrollHorizontal(this.colors.light, this.colors.dark)), + ]); } - public function bind(styles:Array, view:IView):Void { - //data.bind(id, view, "skin"); + public function background(?color:Color, border:Bool = false):StyleSet { + if (color == null) { + color = colors.dark; + } + return [ + new SkinStyle(new SpriteSkin( + {color: color}, + border ? {color: colors.light, thickness: 2} : null + )), + ]; + } + + public function text(?color:Color):StyleSet { + if (color == null) { + color = colors.text; + } + return [ + new FontStyle(new FontPreset(font.name, font.embed, color, baseFontSize)), + ]; + } + + public function button(?color:Color, ?textColor:Color):StyleSet { + if (color == null) { + color = colors.light; + } + return text(textColor).concat([ + new SkinStyle(Skin.buttonColor(color)), + new GeometryStyle(new Geometry().setPadding([25, 8])), + ]); + } + + public function textBox(?color:Color):StyleSet { + return text(color).concat([ + new SkinStyle(new SpriteSkin({color: 0, alpha: 0.1}, {color: colors.light, thickness: 2})), + ]); + } + + public function bind(style:StyleId, view:IView):Void { + styles.connect(style, view); + } + + public function unbind(view:IView):Void { + styles.disconnect(view); } private static function resolveFont(font:ThemeFont):ThemeFont {