mirror of https://github.com/buggins/dlangui.git
state drawables; use state drawables for buttons
This commit is contained in:
parent
9e562548ba
commit
5accf91de5
|
@ -13,7 +13,7 @@
|
|||
<verbose>0</verbose>
|
||||
<vtls>0</vtls>
|
||||
<symdebug>1</symdebug>
|
||||
<optimize>1</optimize>
|
||||
<optimize>0</optimize>
|
||||
<cpu>0</cpu>
|
||||
<isX86_64>0</isX86_64>
|
||||
<isLinux>0</isLinux>
|
||||
|
@ -32,7 +32,7 @@
|
|||
<noboundscheck>0</noboundscheck>
|
||||
<useSwitchError>0</useSwitchError>
|
||||
<useUnitTests>0</useUnitTests>
|
||||
<useInline>1</useInline>
|
||||
<useInline>0</useInline>
|
||||
<release>0</release>
|
||||
<preservePaths>0</preservePaths>
|
||||
<warnings>0</warnings>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<verbose>0</verbose>
|
||||
<vtls>0</vtls>
|
||||
<symdebug>1</symdebug>
|
||||
<optimize>1</optimize>
|
||||
<optimize>0</optimize>
|
||||
<cpu>0</cpu>
|
||||
<isX86_64>0</isX86_64>
|
||||
<isLinux>0</isLinux>
|
||||
|
@ -29,7 +29,7 @@
|
|||
<useIn>0</useIn>
|
||||
<useOut>0</useOut>
|
||||
<useArrayBounds>0</useArrayBounds>
|
||||
<noboundscheck>1</noboundscheck>
|
||||
<noboundscheck>0</noboundscheck>
|
||||
<useSwitchError>0</useSwitchError>
|
||||
<useUnitTests>0</useUnitTests>
|
||||
<useInline>0</useInline>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:constantSize="true"
|
||||
android:dither="false"
|
||||
android:variablePadding="false" >
|
||||
<item
|
||||
android:drawable="btn_default_small_normal_disable_focused"
|
||||
android:state_enabled="false" />
|
||||
android:state_focused="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_normal_disable"
|
||||
android:state_focused="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_pressed"
|
||||
android:state_pressed="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_selected"
|
||||
android:state_selected="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_normal_hover"
|
||||
android:state_hovered="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_normal" />
|
||||
</selector>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:constantSize="true"
|
||||
android:dither="false"
|
||||
android:variablePadding="false" >
|
||||
<item
|
||||
android:drawable="btn_default_small_normal_disable_focused"
|
||||
android:state_enabled="false" />
|
||||
android:state_focused="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_normal_disable"
|
||||
android:state_focused="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_pressed"
|
||||
android:state_pressed="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_selected"
|
||||
android:state_selected="true" />
|
||||
<item
|
||||
android:drawable="btn_default_small_normal_hover"
|
||||
android:state_hovered="true" />
|
||||
<item
|
||||
android:drawable="@null" />
|
||||
</selector>
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue