diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index e36b0deb..116e67b3 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -13,7 +13,7 @@ 0 0 1 - 1 + 0 0 0 0 @@ -32,7 +32,7 @@ 0 0 0 - 1 + 0 0 0 0 diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj index a058304d..cba3de88 100644 --- a/examples/example1/example1.visualdproj +++ b/examples/example1/example1.visualdproj @@ -13,7 +13,7 @@ 0 0 1 - 1 + 0 0 0 0 @@ -29,7 +29,7 @@ 0 0 0 - 1 + 0 0 0 0 diff --git a/examples/example1/res/btn_default_small.xml b/examples/example1/res/btn_default_small.xml new file mode 100644 index 00000000..0ad26807 --- /dev/null +++ b/examples/example1/res/btn_default_small.xml @@ -0,0 +1,24 @@ + + + + android:state_focused="true" /> + + + + + + diff --git a/examples/example1/res/btn_default_small_transparent.xml b/examples/example1/res/btn_default_small_transparent.xml new file mode 100644 index 00000000..2f38acbe --- /dev/null +++ b/examples/example1/res/btn_default_small_transparent.xml @@ -0,0 +1,24 @@ + + + + android:state_focused="true" /> + + + + + + diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d index de72071c..5dde1419 100644 --- a/src/dlangui/core/types.d +++ b/src/dlangui/core/types.d @@ -24,6 +24,17 @@ struct Rect { top += dy; bottom += dy; } + /// for all fields, sets this.field to rc.field if rc.field > this.field + void setMax(Rect rc) { + if (left < rc.left) + left = rc.left; + if (right < rc.right) + right = rc.right; + if (top < rc.top) + top = rc.top; + if (bottom < rc.bottom) + bottom = rc.bottom; + } @property int width() { return right - left; } @property int height() { return bottom - top; } this(int x0, int y0, int x1, int y1) { diff --git a/src/dlangui/graphics/resources.d b/src/dlangui/graphics/resources.d index 6609d819..1697e5f3 100644 --- a/src/dlangui/graphics/resources.d +++ b/src/dlangui/graphics/resources.d @@ -235,14 +235,19 @@ class StateDrawable : Drawable { return (stateMask & state) == stateValue; } } + // list of states protected StateItem[] _stateList; + // max paddings for all states + protected Rect _paddings; + // max drawable size for all states + protected Point _size; void addState(uint stateMask, uint stateValue, string resourceId) { StateItem item; item.stateMask = stateMask; item.stateValue = stateValue; item.drawable = drawableCache.get(resourceId); - _stateList ~= item; + itemAdded(item); } void addState(uint stateMask, uint stateValue, DrawableRef drawable) { @@ -250,7 +255,18 @@ class StateDrawable : Drawable { item.stateMask = stateMask; item.stateValue = stateValue; item.drawable = drawable; + itemAdded(item); + } + + private void itemAdded(ref StateItem item) { _stateList ~= item; + if (!item.drawable.isNull) { + if (_size.x < item.drawable.width) + _size.x = item.drawable.width; + if (_size.y < item.drawable.height) + _size.y = item.drawable.height; + _paddings.setMax(item.drawable.padding); + } } bool load(Element element) { @@ -296,19 +312,20 @@ class StateDrawable : Drawable { override void drawTo(DrawBuf buf, Rect rc, uint state = 0, int tilex0 = 0, int tiley0 = 0) { foreach(ref item; _stateList) if (item.matchState(state)) { - item.drawable.drawTo(buf, rc, state, tilex0, tiley0); + if (!item.drawable.isNull) + item.drawable.drawTo(buf, rc, state, tilex0, tiley0); return; } } @property override int width() { - return (_stateList.length > 0) ? _stateList[0].drawable.width : 0; + return _size.x; } @property override int height() { - return (_stateList.length > 0) ? _stateList[0].drawable.height : 0; + return _size.y; } @property override Rect padding() { - return (_stateList.length > 0) ? _stateList[0].drawable.padding : Rect(0,0,0,0); + return _paddings; } } @@ -498,7 +515,10 @@ class DrawableCache { string[] _resourcePaths; string[string] _idToFileMap; DrawableCacheItem[string] _idToDrawableMap; + DrawableRef _nullDrawable; ref DrawableRef get(string id) { + if (id.equal("@null")) + return _nullDrawable; if (id in _idToDrawableMap) return _idToDrawableMap[id].drawable; string resourceId = id; diff --git a/src/dlangui/widgets/controls.d b/src/dlangui/widgets/controls.d index ef5c85d6..13ad4a61 100644 --- a/src/dlangui/widgets/controls.d +++ b/src/dlangui/widgets/controls.d @@ -123,7 +123,7 @@ class ImageWidget : Widget { sz.x = img.width; sz.y = img.height; applyAlign(rc, sz); - img.drawTo(buf, rc); + img.drawTo(buf, rc, state); } } } diff --git a/src/dlangui/widgets/styles.d b/src/dlangui/widgets/styles.d index 7d51c8b9..99097585 100644 --- a/src/dlangui/widgets/styles.d +++ b/src/dlangui/widgets/styles.d @@ -482,7 +482,7 @@ class Style { if (state == 0) return this; //Log.d("forState ", state, " styleId=", _id, " substates=", _substates.length); - if (parentStyle !is null && _substates.length == 0) //id is null && + if (parentStyle !is null && _substates.length == 0 && parentStyle._substates.length > 0) //id is null && return parentStyle.forState(state); foreach(item; _substates) { if ((item._stateMask & state) == item._stateValue) @@ -584,6 +584,11 @@ class Theme : Style { return this; } + /// find substyle based on widget state (e.g. focused, pressed, ...) + override const(Style) forState(uint state) const { + return this; + } + void dumpStats() { Log.d("Theme ", _id, ": children:", _children.length, ", substates:", _substates.length, ", mapsize:", _byId.length); } @@ -610,13 +615,14 @@ Theme createDefaultTheme() { Log.d("Creating default theme"); Theme res = new Theme("default"); res.fontSize(14); - Style button = res.createSubstyle("BUTTON").backgroundImageId("btn_default_small_normal").alignment(Align.Center); + Style button = res.createSubstyle("BUTTON").backgroundImageId("btn_default_small").alignment(Align.Center); + Style buttonTransparent = res.createSubstyle("BUTTON_TRANSPARENT").backgroundImageId("btn_default_small_transparent").alignment(Align.Center); Style text = res.createSubstyle("TEXT").margins(Rect(2,2,2,2)).padding(Rect(1,1,1,1)); - button.createState(State.Enabled | State.Focused, State.Focused).backgroundImageId("btn_default_small_normal_disable_focused"); - button.createState(State.Enabled, 0).backgroundImageId("btn_default_small_normal_disable"); - button.createState(State.Pressed, State.Pressed).backgroundImageId("btn_default_small_pressed"); - button.createState(State.Focused, State.Focused).backgroundImageId("btn_default_small_selected"); - button.createState(State.Hovered, State.Hovered).backgroundImageId("btn_default_small_normal_hover"); + //button.createState(State.Enabled | State.Focused, State.Focused).backgroundImageId("btn_default_small_normal_disable_focused"); + //button.createState(State.Enabled, 0).backgroundImageId("btn_default_small_normal_disable"); + //button.createState(State.Pressed, State.Pressed).backgroundImageId("btn_default_small_pressed"); + //button.createState(State.Focused, State.Focused).backgroundImageId("btn_default_small_selected"); + //button.createState(State.Hovered, State.Hovered).backgroundImageId("btn_default_small_normal_hover"); res.setCustomDrawable(ATTR_SCROLLBAR_BUTTON_UP, "scrollbar_btn_up"); res.setCustomDrawable(ATTR_SCROLLBAR_BUTTON_DOWN, "scrollbar_btn_down"); res.setCustomDrawable(ATTR_SCROLLBAR_BUTTON_LEFT, "scrollbar_btn_left"); diff --git a/src/dlangui/widgets/tabs.d b/src/dlangui/widgets/tabs.d index d9cedfc9..240ed975 100644 --- a/src/dlangui/widgets/tabs.d +++ b/src/dlangui/widgets/tabs.d @@ -49,6 +49,7 @@ class TabItemWidget : HorizontalLayout { _label.styleId = "TAB_UP_BUTTON_TEXT"; _label.state = State.Parent; _closeButton = new ImageButton("CLOSE"); + _closeButton.styleId = "BUTTON_TRANSPARENT"; _closeButton.drawableId = "close"; _closeButton.onClickListener = &onClick; if (_enableCloseButton) { @@ -152,6 +153,7 @@ class TabControl : WidgetGroup { super(ID); _items = new TabItemList(); _moreButton = new ImageButton("MORE", "tab_more"); + _moreButton.styleId = "BUTTON_TRANSPARENT"; _moreButton.onClickListener = &onClick; _enableCloseButton = true; styleId = "TAB_UP"; @@ -231,6 +233,7 @@ class TabControl : WidgetGroup { } /// Measure widget according to desired width and height constraints. (Step 1 of two phase layout). override void measure(int parentWidth, int parentHeight) { + //Log.d("tabControl.measure enter"); Rect m = margins; Rect p = padding; // calc size constraints for children @@ -257,9 +260,11 @@ class TabControl : WidgetGroup { sz.x += tab.measuredWidth; } measuredContent(parentWidth, parentHeight, sz.x, sz.y); + //Log.d("tabControl.measure exit"); } /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). override void layout(Rect rc) { + //Log.d("tabControl.layout enter"); _needLayout = false; if (visibility == Visibility.Gone) { return; @@ -297,9 +302,11 @@ class TabControl : WidgetGroup { widget.layout(rc); rc.left += w; } + //Log.d("tabControl.layout exit"); } /// Draw widget at its position to buffer override void onDraw(DrawBuf buf) { + //Log.d("tabControl.onDraw enter"); if (visibility != Visibility.Visible) return; super.onDraw(buf); @@ -313,6 +320,7 @@ class TabControl : WidgetGroup { continue; item.onDraw(buf); } + //Log.d("tabControl.onDraw exit"); } protected string _selectedTabId; diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index 4a519408..58016671 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -77,6 +77,7 @@ class Widget { /// create widget, with optional id this(string ID = null) { _id = ID; + _state = State.Enabled; //Log.d("Created widget, count = ", ++_instanceCount); } ~this() { @@ -413,7 +414,7 @@ class Widget { applyMargins(rc); DrawableRef bg = stateStyle.backgroundDrawable; if (!bg.isNull) { - bg.drawTo(buf, rc); + bg.drawTo(buf, rc, state); } applyPadding(rc); _needDraw = false;