mirror of https://github.com/buggins/dlangui.git
support loading of theme from .xml file
This commit is contained in:
parent
b69d55f3eb
commit
1f9e1eba27
|
@ -96,6 +96,12 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
// select translation file - for english language
|
// select translation file - for english language
|
||||||
i18n.load("en.ini"); //"ru.ini", "en.ini"
|
i18n.load("en.ini"); //"ru.ini", "en.ini"
|
||||||
|
|
||||||
|
Theme theme = loadTheme("theme_default");
|
||||||
|
if (theme) {
|
||||||
|
Log.d("Applying loaded theme ", theme.id);
|
||||||
|
currentTheme = theme;
|
||||||
|
}
|
||||||
|
|
||||||
// create window
|
// create window
|
||||||
Window window = Platform.instance.createWindow("My Window", null);
|
Window window = Platform.instance.createWindow("My Window", null);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<theme id="theme_default" >
|
||||||
|
<style id="BUTTON"
|
||||||
|
backgroundImageId="btn_default_small"
|
||||||
|
align="Center"
|
||||||
|
margins="5,5,5,5"
|
||||||
|
/>
|
||||||
|
<style id="BUTTON_TRANSPARENT"
|
||||||
|
backgroundImageId="btn_default_small_transparent"
|
||||||
|
align="Center"
|
||||||
|
/>
|
||||||
|
<style id="BUTTON_LABEL"
|
||||||
|
layoutWidth="FILL_PARENT"
|
||||||
|
align="Left|VCenter"
|
||||||
|
/>
|
||||||
|
<style id="BUTTON_ICON"
|
||||||
|
align="Center"
|
||||||
|
/>
|
||||||
|
<style id="TEXT"
|
||||||
|
margins="2,2,2,2"
|
||||||
|
padding="1,1,1,1"
|
||||||
|
/>
|
||||||
|
<style id="HSPACER"
|
||||||
|
layoutWidth="FILL_PARENT"
|
||||||
|
layoutWeight="100"
|
||||||
|
minWidth="5"
|
||||||
|
/>
|
||||||
|
<style id="VSPACER"
|
||||||
|
layoutHeight="FILL_PARENT"
|
||||||
|
layoutWeight="100"
|
||||||
|
minHeight="5"
|
||||||
|
/>
|
||||||
|
<style id="BUTTON_NOMARGINS"
|
||||||
|
backgroundImageId="btn_default_small"
|
||||||
|
align="Center"
|
||||||
|
/>
|
||||||
|
<drawable id="scrollbar_button_up" value="scrollbar_btn_up"/>
|
||||||
|
<drawable id="scrollbar_button_down" value="scrollbar_btn_down"/>
|
||||||
|
<srawable id="scrollbar_button_left" value="scrollbar_btn_left"/>
|
||||||
|
<drawable id="scrollbar_button_right" value="scrollbar_btn_right"/>
|
||||||
|
<drawable id="scrollbar_indicator_vertical" value="scrollbar_indicator_vertical"/>
|
||||||
|
<drawable id="scrollbar_indicator_horizontal" value="scrollbar_indicator_horizontal"/>
|
||||||
|
<style id="SCROLLBAR"
|
||||||
|
backgroundColor="#C0808080"
|
||||||
|
align="Center"
|
||||||
|
/>
|
||||||
|
<style id="SCROLLBAR_BUTTON" parent="BUTTON"
|
||||||
|
/>
|
||||||
|
<style id="SLIDER"
|
||||||
|
/>
|
||||||
|
<style id="PAGE_SCROLL"
|
||||||
|
backgroundColor="#FFFFFFFF"
|
||||||
|
>
|
||||||
|
<state state_pressed="true" backgroundColor="#C0404080"/>
|
||||||
|
<state state_hovered="true" backgroundColor="#F0404080"/>
|
||||||
|
</style>
|
||||||
|
<style id="TAB_UP"
|
||||||
|
backgroundImageId="tab_up_background"
|
||||||
|
layoutWidth="FILL_PARENT"
|
||||||
|
>
|
||||||
|
<state state_selected="true" backgroundImageId="tab_up_backgrond_selected"/>
|
||||||
|
</style>
|
||||||
|
<style id="TAB_UP_BUTTON_TEXT"
|
||||||
|
textColor="#000000"
|
||||||
|
backgroundImageId="tab_up_background"
|
||||||
|
fontSize="12"
|
||||||
|
align="Center"
|
||||||
|
>
|
||||||
|
<state state_selected="true" state_focused="true" textColor="#000000"/>
|
||||||
|
<state state_selected="true" textColor="#000000"/>
|
||||||
|
<state state_focused="true" textColor="#000000"/>
|
||||||
|
<state state_hovered="true" textColor="#FFE0E0"/>
|
||||||
|
</style>
|
||||||
|
<style id="TAB_UP_BUTTON"
|
||||||
|
backgroundImageId="tab_btn_up"
|
||||||
|
/>
|
||||||
|
<style id="TAB_HOST"
|
||||||
|
layoutWidth="FILL_PARENT"
|
||||||
|
layoutHeight="FILL_PARENT"
|
||||||
|
backgroundColor="#F0F0F0"
|
||||||
|
/>
|
||||||
|
<style id="TAB_WIDGET"
|
||||||
|
padding="3,3,3,3"
|
||||||
|
backgroundColor="#EEEEEE"
|
||||||
|
/>
|
||||||
|
<style id="MAIN_MENU"
|
||||||
|
layoutWidth="FILL_PARENT"
|
||||||
|
backgroundColor="#EFEFF2"
|
||||||
|
/>
|
||||||
|
<style id="MAIN_MENU_ITEM"
|
||||||
|
padding="4,2,4,2"
|
||||||
|
backgroundImageId="main_menu_item_background"
|
||||||
|
textFlags="Parent"
|
||||||
|
/>
|
||||||
|
<style id="MENU_ITEM"
|
||||||
|
padding="4,2,4,2"
|
||||||
|
>
|
||||||
|
<state state_focused="true" backgroundColor="#40C0C000"/>
|
||||||
|
<state state_pressed="true" backgroundColor="#4080C000"/>
|
||||||
|
<state state_selected="true" backgroundColor="#00F8F9Fa"/>
|
||||||
|
<state state_hovered="true" backgroundColor="#C0FFFF00"/>
|
||||||
|
</style>
|
||||||
|
<style id="MENU_ICON"
|
||||||
|
margins="2,2,2,2"
|
||||||
|
align="Left|VCenter"
|
||||||
|
>
|
||||||
|
<state state_enabled="false" alpha="160"/>
|
||||||
|
</style>
|
||||||
|
<style id="MENU_LABEL"
|
||||||
|
margins="4,2,4,2"
|
||||||
|
align="Left|VCenter"
|
||||||
|
textFlags="UnderlineHotKeys"
|
||||||
|
>
|
||||||
|
<state state_enabled="false" textColor="#80404040"/>
|
||||||
|
</style>
|
||||||
|
<style id="MAIN_MENU_LABEL"
|
||||||
|
margins="4,2,4,2"
|
||||||
|
align="Left|VCenter"
|
||||||
|
textFlags="Parent"
|
||||||
|
>
|
||||||
|
<state state_enabled="false" textColor="#80404040"/>
|
||||||
|
</style>
|
||||||
|
<style id="MENU_ACCEL"
|
||||||
|
margins="4,2,4,2"
|
||||||
|
align="Left|VCenter"
|
||||||
|
>
|
||||||
|
<state state_enabled="false" textColor="#80404040"/>
|
||||||
|
</style>
|
||||||
|
<style id="TRANSPARENT_BUTTON_BACKGROUND"
|
||||||
|
backgroundImageId="transparent_button_background"
|
||||||
|
padding="4,2,4,2"
|
||||||
|
/>
|
||||||
|
<style id="POPUP_MENU"
|
||||||
|
backgroundImageId="popup_menu_background_normal"
|
||||||
|
/>
|
||||||
|
<style id="LIST_ITEM"
|
||||||
|
backgroundImageId="list_item_background"
|
||||||
|
/>
|
||||||
|
<style id="EDIT_LINE"
|
||||||
|
backgroundImageId="editbox_background"
|
||||||
|
padding="5,6,5,6"
|
||||||
|
margins="2,2,2,2"
|
||||||
|
minWidth="40"
|
||||||
|
fontFace="Arial"
|
||||||
|
fontFamily="SansSerif"
|
||||||
|
fontSize="16"
|
||||||
|
/>
|
||||||
|
<style id="EDIT_BOX"
|
||||||
|
backgroundImageId="editbox_background"
|
||||||
|
padding="5,6,5,6"
|
||||||
|
margins="2,2,2,2"
|
||||||
|
minWidth="100"
|
||||||
|
minHeight="60"
|
||||||
|
layoutWidth="FILL_PARENT"
|
||||||
|
layoutHeight="FILL_PARENT"
|
||||||
|
fontFace="Courier New"
|
||||||
|
fontFamily="MonoSpace"
|
||||||
|
fontSize="16"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</theme>
|
||||||
|
|
|
@ -299,18 +299,18 @@ class ImageDrawable : Drawable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string attrValue(Element item, string attrname, string attrname2) {
|
string attrValue(Element item, string attrname, string attrname2 = null) {
|
||||||
if (attrname in item.tag.attr)
|
if (attrname in item.tag.attr)
|
||||||
return item.tag.attr[attrname];
|
return item.tag.attr[attrname];
|
||||||
if (attrname2 in item.tag.attr)
|
if (attrname2 && attrname2 in item.tag.attr)
|
||||||
return item.tag.attr[attrname2];
|
return item.tag.attr[attrname2];
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
string attrValue(ref string[string] attr, string attrname, string attrname2) {
|
string attrValue(ref string[string] attr, string attrname, string attrname2 = null) {
|
||||||
if (attrname in attr)
|
if (attrname in attr)
|
||||||
return attr[attrname];
|
return attr[attrname];
|
||||||
if (attrname2 in attr)
|
if (attrname2 && attrname2 in attr)
|
||||||
return attr[attrname2];
|
return attr[attrname2];
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -863,6 +863,7 @@ class DrawableCache {
|
||||||
return fn.dup;
|
return fn.dup;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
/// get resource file full pathname by resource id, null if not found
|
||||||
string findResource(string id) {
|
string findResource(string id) {
|
||||||
if (id.startsWith("#"))
|
if (id.startsWith("#"))
|
||||||
return id; // it's not a file name, just a color #AARRGGBB
|
return id; // it's not a file name, just a color #AARRGGBB
|
||||||
|
|
|
@ -22,6 +22,10 @@ Authors: Vadim Lopatin, coolreader.org@gmail.com
|
||||||
*/
|
*/
|
||||||
module dlangui.widgets.styles;
|
module dlangui.widgets.styles;
|
||||||
|
|
||||||
|
private import std.xml;
|
||||||
|
private import std.string;
|
||||||
|
private import std.algorithm;
|
||||||
|
|
||||||
import dlangui.core.types;
|
import dlangui.core.types;
|
||||||
import dlangui.graphics.fonts;
|
import dlangui.graphics.fonts;
|
||||||
import dlangui.graphics.drawbuf;
|
import dlangui.graphics.drawbuf;
|
||||||
|
@ -165,6 +169,10 @@ class Style {
|
||||||
}
|
}
|
||||||
|
|
||||||
@property string id() const { return _id; }
|
@property string id() const { return _id; }
|
||||||
|
@property Style id(string id) {
|
||||||
|
this._id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// access to parent style for this style
|
/// access to parent style for this style
|
||||||
@property const(Style) parentStyle() const {
|
@property const(Style) parentStyle() const {
|
||||||
|
@ -683,8 +691,10 @@ class Theme : Style {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// create new named style
|
/// create new named style or get existing
|
||||||
override Style createSubstyle(string id) {
|
override Style createSubstyle(string id) {
|
||||||
|
if (id !is null && id in _byId)
|
||||||
|
return _byId[id]; // already exists
|
||||||
Style style = new Style(this, id);
|
Style style = new Style(this, id);
|
||||||
if (id !is null)
|
if (id !is null)
|
||||||
_byId[id] = style;
|
_byId[id] = style;
|
||||||
|
@ -824,6 +834,267 @@ Theme createDefaultTheme() {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// decode comma delimited dimension list or single value - and put to Rect
|
||||||
|
Rect decodeRect(string s) {
|
||||||
|
uint[6] values;
|
||||||
|
int valueCount = 0;
|
||||||
|
int start = 0;
|
||||||
|
for (int i = 0; i <= s.length; i++) {
|
||||||
|
if (i == s.length || s[i] == ',') {
|
||||||
|
if (i > start) {
|
||||||
|
string item = s[start .. i];
|
||||||
|
values[valueCount++] = decodeDimension(item);
|
||||||
|
if (valueCount >= 6)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valueCount == 1) // same value for all dimensions
|
||||||
|
return Rect(values[0], values[0], values[0], values[0]);
|
||||||
|
else if (valueCount == 2) // one value of horizontal, and one for vertical
|
||||||
|
return Rect(values[0], values[1], values[0], values[1]);
|
||||||
|
else if (valueCount == 4) // separate left, top, right, bottom
|
||||||
|
return Rect(values[0], values[1], values[2], values[3]);
|
||||||
|
Log.e("Invalid rect attribute value ", s);
|
||||||
|
return Rect(0,0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// parses string like "Left|VCenter" to bit set of Align flags
|
||||||
|
ubyte decodeAlignment(string s) {
|
||||||
|
ubyte res = 0;
|
||||||
|
int start = 0;
|
||||||
|
for (int i = 0; i <= s.length; i++) {
|
||||||
|
if (i == s.length || s[i] == '|') {
|
||||||
|
if (i > start) {
|
||||||
|
string item = s[start .. i];
|
||||||
|
if (item.equal("Left"))
|
||||||
|
res |= Align.Left;
|
||||||
|
else if (item.equal("Right"))
|
||||||
|
res |= Align.Right;
|
||||||
|
else if (item.equal("Top"))
|
||||||
|
res |= Align.Top;
|
||||||
|
else if (item.equal("Bottom"))
|
||||||
|
res |= Align.Bottom;
|
||||||
|
else if (item.equal("HCenter"))
|
||||||
|
res |= Align.HCenter;
|
||||||
|
else if (item.equal("VCenter"))
|
||||||
|
res |= Align.VCenter;
|
||||||
|
else if (item.equal("Center"))
|
||||||
|
res |= Align.Center;
|
||||||
|
else if (item.equal("TopLeft"))
|
||||||
|
res |= Align.TopLeft;
|
||||||
|
else
|
||||||
|
Log.e("unknown Align value: ", item);
|
||||||
|
}
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// parses string like "HotKeys|UnderlineHotKeysWhenAltPressed" to bit set of TextFlag flags
|
||||||
|
uint decodeTextFlags(string s) {
|
||||||
|
uint res = 0;
|
||||||
|
int start = 0;
|
||||||
|
for (int i = 0; i <= s.length; i++) {
|
||||||
|
if (i == s.length || s[i] == '|') {
|
||||||
|
if (i > start) {
|
||||||
|
string item = s[start .. i];
|
||||||
|
if (item.equal("HotKeys"))
|
||||||
|
res |= TextFlag.HotKeys;
|
||||||
|
else if (item.equal("UnderlineHotKeys"))
|
||||||
|
res |= TextFlag.UnderlineHotKeys;
|
||||||
|
else if (item.equal("UnderlineHotKeysWhenAltPressed"))
|
||||||
|
res |= TextFlag.UnderlineHotKeysWhenAltPressed;
|
||||||
|
else if (item.equal("Underline"))
|
||||||
|
res |= TextFlag.Underline;
|
||||||
|
else if (item.equal("Unspecified"))
|
||||||
|
res = TEXT_FLAGS_UNSPECIFIED;
|
||||||
|
else if (item.equal("Parent"))
|
||||||
|
res = TEXT_FLAGS_USE_PARENT;
|
||||||
|
else
|
||||||
|
Log.e("unknown text flag value: ", item);
|
||||||
|
}
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// decode FontFamily item name to value
|
||||||
|
FontFamily decodeFontFamily(string s) {
|
||||||
|
if (s.equal("SansSerif"))
|
||||||
|
return FontFamily.SansSerif;
|
||||||
|
if (s.equal("Serif"))
|
||||||
|
return FontFamily.Serif;
|
||||||
|
if (s.equal("Cursive"))
|
||||||
|
return FontFamily.Cursive;
|
||||||
|
if (s.equal("Fantasy"))
|
||||||
|
return FontFamily.Fantasy;
|
||||||
|
if (s.equal("MonoSpace"))
|
||||||
|
return FontFamily.MonoSpace;
|
||||||
|
if (s.equal("Unspecified"))
|
||||||
|
return FontFamily.Unspecified;
|
||||||
|
Log.e("unknown font family ", s);
|
||||||
|
return FontFamily.SansSerif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// decode layout dimension (FILL_PARENT, WRAP_CONTENT, or just size)
|
||||||
|
int decodeLayoutDimension(string s) {
|
||||||
|
if (s.equal("FILL_PARENT"))
|
||||||
|
return FILL_PARENT;
|
||||||
|
if (s.equal("WRAP_CONTENT"))
|
||||||
|
return WRAP_CONTENT;
|
||||||
|
return decodeDimension(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// load style attributes from XML element
|
||||||
|
bool loadStyleAttributes(Style style, Element elem, bool allowStates) {
|
||||||
|
if ("backgroundImageId" in elem.tag.attr)
|
||||||
|
style.backgroundImageId = elem.tag.attr["backgroundImageId"];
|
||||||
|
if ("backgroundColor" in elem.tag.attr)
|
||||||
|
style.backgroundColor = decodeHexColor(elem.tag.attr["backgroundColor"]);
|
||||||
|
if ("textColor" in elem.tag.attr)
|
||||||
|
style.textColor = decodeHexColor(elem.tag.attr["textColor"]);
|
||||||
|
if ("margins" in elem.tag.attr)
|
||||||
|
style.margins = decodeRect(elem.tag.attr["margins"]);
|
||||||
|
if ("padding" in elem.tag.attr)
|
||||||
|
style.padding = decodeRect(elem.tag.attr["padding"]);
|
||||||
|
if ("align" in elem.tag.attr)
|
||||||
|
style.alignment = decodeAlignment(elem.tag.attr["align"]);
|
||||||
|
if ("minWidth" in elem.tag.attr)
|
||||||
|
style.minWidth = decodeDimension(elem.tag.attr["minWidth"]);
|
||||||
|
if ("maxWidth" in elem.tag.attr)
|
||||||
|
style.maxWidth = decodeDimension(elem.tag.attr["maxWidth"]);
|
||||||
|
if ("minHeight" in elem.tag.attr)
|
||||||
|
style.minHeight = decodeDimension(elem.tag.attr["minHeight"]);
|
||||||
|
if ("maxHeight" in elem.tag.attr)
|
||||||
|
style.maxHeight = decodeDimension(elem.tag.attr["maxHeight"]);
|
||||||
|
if ("fontFace" in elem.tag.attr)
|
||||||
|
style.fontFace = elem.tag.attr["fontFace"];
|
||||||
|
if ("fontFamily" in elem.tag.attr)
|
||||||
|
style.fontFamily = decodeFontFamily(elem.tag.attr["fontFamily"]);
|
||||||
|
if ("fontSize" in elem.tag.attr)
|
||||||
|
style.fontSize = cast(ushort)decodeDimension(elem.tag.attr["fontFace"]);
|
||||||
|
if ("layoutWidth" in elem.tag.attr)
|
||||||
|
style.layoutWidth = decodeLayoutDimension(elem.tag.attr["layoutWidth"]);
|
||||||
|
if ("layoutHeight" in elem.tag.attr)
|
||||||
|
style.layoutHeight = decodeLayoutDimension(elem.tag.attr["layoutHeight"]);
|
||||||
|
if ("alpha" in elem.tag.attr)
|
||||||
|
style.alpha = decodeDimension(elem.tag.attr["alpha"]);
|
||||||
|
if ("textFlags" in elem.tag.attr)
|
||||||
|
style.textFlags = decodeTextFlags(elem.tag.attr["textFlags"]);
|
||||||
|
foreach(item; elem.elements) {
|
||||||
|
if (allowStates && item.tag.name.equal("state")) {
|
||||||
|
uint stateMask = 0;
|
||||||
|
uint stateValue = 0;
|
||||||
|
extractStateFlags(item.tag.attr, stateMask, stateValue);
|
||||||
|
if (stateMask) {
|
||||||
|
Style state = style.createState(stateMask, stateValue);
|
||||||
|
loadStyleAttributes(state, item, false);
|
||||||
|
}
|
||||||
|
} else if (item.tag.name.equal("drawable")) {
|
||||||
|
// <drawable id="scrollbar_button_up" value="scrollbar_btn_up"/>
|
||||||
|
string drawableid = attrValue(item, "id");
|
||||||
|
string drawablevalue = attrValue(item, "value");
|
||||||
|
if (drawableid)
|
||||||
|
style.setCustomDrawable(drawableid, drawablevalue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load theme from XML document
|
||||||
|
*
|
||||||
|
* Sample:
|
||||||
|
* ---
|
||||||
|
* <?xml version="1.0" encoding="utf-8"?>
|
||||||
|
* <theme id="theme_custom" parent="theme_default">
|
||||||
|
* <style id="BUTTON"
|
||||||
|
* backgroundImageId="btn_default_small"
|
||||||
|
* >
|
||||||
|
* </style>
|
||||||
|
* </theme>
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool loadTheme(Theme theme, Element doc, int level = 0) {
|
||||||
|
if (doc.tag.name.equal("theme")) {
|
||||||
|
Log.e("<theme> element should be main in theme file!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// <theme>
|
||||||
|
string id = attrValue(doc, "id");
|
||||||
|
string parent = attrValue(doc, "parent");
|
||||||
|
theme.id = id;
|
||||||
|
if (parent.length > 0) {
|
||||||
|
// load base theme
|
||||||
|
if (level < 3) // to prevent infinite recursion
|
||||||
|
loadTheme(theme, parent, level + 1);
|
||||||
|
}
|
||||||
|
loadStyleAttributes(theme, doc, false);
|
||||||
|
foreach(styleitem; doc.elements) {
|
||||||
|
if (styleitem.tag.name.equal("style")) {
|
||||||
|
// load <style>
|
||||||
|
string styleid = attrValue(styleitem, "id");
|
||||||
|
string styleparent = attrValue(styleitem, "parent");
|
||||||
|
if (styleid !is null) {
|
||||||
|
// create new style
|
||||||
|
Style parentStyle = null;
|
||||||
|
if (styleparent !is null)
|
||||||
|
parentStyle = theme.get(styleparent);
|
||||||
|
Style style = parentStyle.createSubstyle(styleid);
|
||||||
|
loadStyleAttributes(style, styleitem, true);
|
||||||
|
} else {
|
||||||
|
Log.e("style without ID in theme file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// load theme from file
|
||||||
|
bool loadTheme(Theme theme, string resourceId, int level = 0) {
|
||||||
|
|
||||||
|
import std.file;
|
||||||
|
import std.string;
|
||||||
|
|
||||||
|
string filename;
|
||||||
|
try {
|
||||||
|
filename = drawableCache.findResource(resourceId);
|
||||||
|
if (!filename || !filename.endsWith(".xml"))
|
||||||
|
return false;
|
||||||
|
string s = cast(string)std.file.read(filename);
|
||||||
|
|
||||||
|
// Check for well-formedness
|
||||||
|
//check(s);
|
||||||
|
|
||||||
|
// Make a DOM tree
|
||||||
|
auto doc = new Document(s);
|
||||||
|
|
||||||
|
return loadTheme(theme, doc);
|
||||||
|
} catch (CheckException e) {
|
||||||
|
Log.e("Invalid XML resource ", resourceId);
|
||||||
|
return false;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Log.e("Cannot read drawable resource ", resourceId, " from file ", filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// load theme from XML file (null if failed)
|
||||||
|
Theme loadTheme(string resourceId) {
|
||||||
|
Theme res = new Theme(resourceId);
|
||||||
|
if (loadTheme(res, resourceId)) {
|
||||||
|
res.id = resourceId;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
destroy(res);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
shared static ~this() {
|
shared static ~this() {
|
||||||
currentTheme = null;
|
currentTheme = null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue