mirror of https://github.com/buggins/dlangui.git
support changing of theme
This commit is contained in:
parent
1f9e1eba27
commit
60776f2ce9
|
@ -0,0 +1,166 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<theme
|
||||||
|
id="theme_custom1"
|
||||||
|
parent="theme_default"
|
||||||
|
fontSize="24"
|
||||||
|
>
|
||||||
|
<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"
|
||||||
|
fontSize="16"
|
||||||
|
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="#404040"
|
||||||
|
/>
|
||||||
|
<style id="MAIN_MENU_ITEM"
|
||||||
|
padding="4,2,4,2"
|
||||||
|
backgroundImageId="main_menu_item_background"
|
||||||
|
textColor="#E0E0E0"
|
||||||
|
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="20"
|
||||||
|
/>
|
||||||
|
<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="20"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</theme>
|
||||||
|
|
|
@ -89,18 +89,13 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
appendPath(exePath, "../res/mdpi/"), // when res dir is located at project directory
|
appendPath(exePath, "../res/mdpi/"), // when res dir is located at project directory
|
||||||
appendPath(exePath, "../../res/mdpi/") // when res dir is located at the same directory as executable
|
appendPath(exePath, "../../res/mdpi/") // when res dir is located at the same directory as executable
|
||||||
];
|
];
|
||||||
// setup resource directories - will use only existing directories
|
|
||||||
drawableCache.setResourcePaths(resourceDirs);
|
|
||||||
// setup i18n - look for i18n directory inside one of passed directories
|
|
||||||
i18n.findTranslationsDir(resourceDirs);
|
|
||||||
// select translation file - for english language
|
|
||||||
i18n.load("en.ini"); //"ru.ini", "en.ini"
|
|
||||||
|
|
||||||
Theme theme = loadTheme("theme_default");
|
// setup resource directories - will use only existing directories
|
||||||
if (theme) {
|
Platform.instance.resourceDirs = resourceDirs;
|
||||||
Log.d("Applying loaded theme ", theme.id);
|
// select translation file - for english language
|
||||||
currentTheme = theme;
|
Platform.instance.uiLanguage = "en";
|
||||||
}
|
// load theme from file "theme_default.xml"
|
||||||
|
Platform.instance.uiTheme = "theme_default";
|
||||||
|
|
||||||
// create window
|
// create window
|
||||||
Window window = Platform.instance.createWindow("My Window", null);
|
Window window = Platform.instance.createWindow("My Window", null);
|
||||||
|
@ -142,12 +137,10 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
return false;
|
return false;
|
||||||
if (item.id == 611) {
|
if (item.id == 611) {
|
||||||
// set interface language to english
|
// set interface language to english
|
||||||
i18n.load("en.ini");
|
platform.instance.uiLanguage = "en";
|
||||||
contentLayout.requestLayout();
|
|
||||||
} else if (item.id == 612) {
|
} else if (item.id == 612) {
|
||||||
// set interface language to russian
|
// set interface language to russian
|
||||||
i18n.load("ru.ini", "en.ini");
|
platform.instance.uiLanguage = "ru";
|
||||||
contentLayout.requestLayout();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -157,10 +150,24 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
ruLang.onMenuItemClick = onLangChange;
|
ruLang.onMenuItemClick = onLangChange;
|
||||||
langItem.add(enLang);
|
langItem.add(enLang);
|
||||||
langItem.add(ruLang);
|
langItem.add(ruLang);
|
||||||
MenuItem themeItem = new MenuItem(new Action(62, "MENU_VIEW_THEME"));
|
|
||||||
themeItem.add((new MenuItem(new Action(621, "MENU_VIEW_THEME_DEFAULT"))).type(MenuItemType.Radio).checked(true));
|
|
||||||
themeItem.add((new MenuItem(new Action(622, "MENU_VIEW_THEME_CUSTOM1"))).type(MenuItemType.Radio));
|
|
||||||
viewItem.add(langItem);
|
viewItem.add(langItem);
|
||||||
|
MenuItem themeItem = new MenuItem(new Action(62, "MENU_VIEW_THEME"));
|
||||||
|
MenuItem theme1 = (new MenuItem(new Action(621, "MENU_VIEW_THEME_DEFAULT"))).type(MenuItemType.Radio).checked(true);
|
||||||
|
MenuItem theme2 = (new MenuItem(new Action(622, "MENU_VIEW_THEME_CUSTOM1"))).type(MenuItemType.Radio);
|
||||||
|
auto onThemeChange = delegate (MenuItem item) {
|
||||||
|
if (!item.checked)
|
||||||
|
return false;
|
||||||
|
if (item.id == 621) {
|
||||||
|
platform.instance.uiTheme = "theme_default";
|
||||||
|
} else if (item.id == 622) {
|
||||||
|
platform.instance.uiTheme = "theme_custom1";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
theme1.onMenuItemClick = onThemeChange;
|
||||||
|
theme2.onMenuItemClick = onThemeChange;
|
||||||
|
themeItem.add(theme1);
|
||||||
|
themeItem.add(theme2);
|
||||||
viewItem.add(themeItem);
|
viewItem.add(themeItem);
|
||||||
|
|
||||||
MenuItem windowItem = new MenuItem(new Action(3, "MENU_WINDOW"c));
|
MenuItem windowItem = new MenuItem(new Action(3, "MENU_WINDOW"c));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<theme id="theme_default" >
|
<theme id="theme_default" fontSize="15" >
|
||||||
<style id="BUTTON"
|
<style id="BUTTON"
|
||||||
backgroundImageId="btn_default_small"
|
backgroundImageId="btn_default_small"
|
||||||
align="Center"
|
align="Center"
|
||||||
|
@ -62,7 +62,6 @@
|
||||||
</style>
|
</style>
|
||||||
<style id="TAB_UP_BUTTON_TEXT"
|
<style id="TAB_UP_BUTTON_TEXT"
|
||||||
textColor="#000000"
|
textColor="#000000"
|
||||||
backgroundImageId="tab_up_background"
|
|
||||||
fontSize="12"
|
fontSize="12"
|
||||||
align="Center"
|
align="Center"
|
||||||
>
|
>
|
||||||
|
|
|
@ -28,7 +28,12 @@ import dlangui.widgets.popup;
|
||||||
import dlangui.graphics.drawbuf;
|
import dlangui.graphics.drawbuf;
|
||||||
|
|
||||||
private import dlangui.graphics.gldrawbuf;
|
private import dlangui.graphics.gldrawbuf;
|
||||||
|
private import std.algorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Window abstraction layer. Widgets can be shown only inside window.
|
||||||
|
*
|
||||||
|
*/
|
||||||
class Window {
|
class Window {
|
||||||
protected int _dx;
|
protected int _dx;
|
||||||
protected int _dy;
|
protected int _dy;
|
||||||
|
@ -49,8 +54,17 @@ class Window {
|
||||||
_mainWidget.window = this;
|
_mainWidget.window = this;
|
||||||
}
|
}
|
||||||
abstract void show();
|
abstract void show();
|
||||||
|
/// returns window caption
|
||||||
abstract @property string windowCaption();
|
abstract @property string windowCaption();
|
||||||
|
/// sets window caption
|
||||||
abstract @property void windowCaption(string caption);
|
abstract @property void windowCaption(string caption);
|
||||||
|
/// requests layout for main widget and popups
|
||||||
|
void requestLayout() {
|
||||||
|
if (_mainWidget)
|
||||||
|
_mainWidget.requestLayout();
|
||||||
|
foreach(p; _popups)
|
||||||
|
p.requestLayout();
|
||||||
|
}
|
||||||
void measure() {
|
void measure() {
|
||||||
if (_mainWidget !is null) {
|
if (_mainWidget !is null) {
|
||||||
_mainWidget.measure(_dx, _dy);
|
_mainWidget.measure(_dx, _dy);
|
||||||
|
@ -524,6 +538,14 @@ class Window {
|
||||||
abstract void invalidate();
|
abstract void invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform abstraction layer.
|
||||||
|
*
|
||||||
|
* Represents application.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
class Platform {
|
class Platform {
|
||||||
static __gshared Platform _instance;
|
static __gshared Platform _instance;
|
||||||
static void setInstance(Platform instance) {
|
static void setInstance(Platform instance) {
|
||||||
|
@ -540,6 +562,60 @@ class Platform {
|
||||||
abstract dstring getClipboardText(bool mouseBuffer = false);
|
abstract dstring getClipboardText(bool mouseBuffer = false);
|
||||||
/// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux)
|
/// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux)
|
||||||
abstract void setClipboardText(dstring text, bool mouseBuffer = false);
|
abstract void setClipboardText(dstring text, bool mouseBuffer = false);
|
||||||
|
|
||||||
|
/// calls request layout for all windows
|
||||||
|
abstract void requestLayout();
|
||||||
|
|
||||||
|
protected string _uiLanguage;
|
||||||
|
/// returns currently selected UI language code
|
||||||
|
@property string uiLanguage() {
|
||||||
|
return _uiLanguage;
|
||||||
|
}
|
||||||
|
/// set UI language (e.g. "en", "fr", "ru")
|
||||||
|
@property Platform uiLanguage(string langCode) {
|
||||||
|
if (_uiLanguage.equal(langCode))
|
||||||
|
return this;
|
||||||
|
_uiLanguage = langCode;
|
||||||
|
if (langCode.equal("en"))
|
||||||
|
i18n.load("en.ini"); //"ru.ini", "en.ini"
|
||||||
|
else
|
||||||
|
i18n.load(langCode ~ ".ini", "en.ini");
|
||||||
|
requestLayout();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
protected string _themeId;
|
||||||
|
@property string uiTheme() {
|
||||||
|
return _themeId;
|
||||||
|
}
|
||||||
|
/// sets application UI theme
|
||||||
|
@property Platform uiTheme(string themeResourceId) {
|
||||||
|
if (_themeId.equal(themeResourceId))
|
||||||
|
return this;
|
||||||
|
_themeId = themeResourceId;
|
||||||
|
Theme theme = loadTheme(themeResourceId);
|
||||||
|
if (!theme) {
|
||||||
|
Log.e("Cannot load theme from resource ", themeResourceId, " - will use default theme");
|
||||||
|
theme = createDefaultTheme();
|
||||||
|
} else {
|
||||||
|
Log.i("Applying loaded theme ", theme.id);
|
||||||
|
}
|
||||||
|
currentTheme = theme;
|
||||||
|
requestLayout();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string[] _resourceDirs;
|
||||||
|
/// returns list of resource directories
|
||||||
|
@property string[] resourceDirs() { return _resourceDirs; }
|
||||||
|
/// set list of directories to load resources from
|
||||||
|
@property Platform resourceDirs(string[] dirs) {
|
||||||
|
// setup resource directories - will use only existing directories
|
||||||
|
drawableCache.setResourcePaths(dirs);
|
||||||
|
_resourceDirs = drawableCache.resourcePaths;
|
||||||
|
// setup i18n - look for i18n directory inside one of passed directories
|
||||||
|
i18n.findTranslationsDir(dirs);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get current platform object instance
|
/// get current platform object instance
|
||||||
|
|
|
@ -662,6 +662,15 @@ version(USE_SDL) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// calls request layout for all windows
|
||||||
|
override void requestLayout() {
|
||||||
|
foreach(w; _windowMap) {
|
||||||
|
w.requestLayout();
|
||||||
|
w.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private uint _redrawEventId;
|
private uint _redrawEventId;
|
||||||
|
|
||||||
void sendRedrawEvent(uint windowId, uint code) {
|
void sendRedrawEvent(uint windowId, uint code) {
|
||||||
|
|
|
@ -976,7 +976,7 @@ bool loadStyleAttributes(Style style, Element elem, bool allowStates) {
|
||||||
if ("fontFamily" in elem.tag.attr)
|
if ("fontFamily" in elem.tag.attr)
|
||||||
style.fontFamily = decodeFontFamily(elem.tag.attr["fontFamily"]);
|
style.fontFamily = decodeFontFamily(elem.tag.attr["fontFamily"]);
|
||||||
if ("fontSize" in elem.tag.attr)
|
if ("fontSize" in elem.tag.attr)
|
||||||
style.fontSize = cast(ushort)decodeDimension(elem.tag.attr["fontFace"]);
|
style.fontSize = cast(ushort)decodeDimension(elem.tag.attr["fontSize"]);
|
||||||
if ("layoutWidth" in elem.tag.attr)
|
if ("layoutWidth" in elem.tag.attr)
|
||||||
style.layoutWidth = decodeLayoutDimension(elem.tag.attr["layoutWidth"]);
|
style.layoutWidth = decodeLayoutDimension(elem.tag.attr["layoutWidth"]);
|
||||||
if ("layoutHeight" in elem.tag.attr)
|
if ("layoutHeight" in elem.tag.attr)
|
||||||
|
@ -1021,7 +1021,7 @@ bool loadStyleAttributes(Style style, Element elem, bool allowStates) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool loadTheme(Theme theme, Element doc, int level = 0) {
|
bool loadTheme(Theme theme, Element doc, int level = 0) {
|
||||||
if (doc.tag.name.equal("theme")) {
|
if (!doc.tag.name.equal("theme")) {
|
||||||
Log.e("<theme> element should be main in theme file!");
|
Log.e("<theme> element should be main in theme file!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1040,11 +1040,10 @@ bool loadTheme(Theme theme, Element doc, int level = 0) {
|
||||||
// load <style>
|
// load <style>
|
||||||
string styleid = attrValue(styleitem, "id");
|
string styleid = attrValue(styleitem, "id");
|
||||||
string styleparent = attrValue(styleitem, "parent");
|
string styleparent = attrValue(styleitem, "parent");
|
||||||
if (styleid !is null) {
|
if (styleid.length) {
|
||||||
// create new style
|
// create new style
|
||||||
Style parentStyle = null;
|
Style parentStyle = null;
|
||||||
if (styleparent !is null)
|
parentStyle = theme.get(styleparent);
|
||||||
parentStyle = theme.get(styleparent);
|
|
||||||
Style style = parentStyle.createSubstyle(styleid);
|
Style style = parentStyle.createSubstyle(styleid);
|
||||||
loadStyleAttributes(style, styleitem, true);
|
loadStyleAttributes(style, styleitem, true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1079,7 +1078,7 @@ bool loadTheme(Theme theme, string resourceId, int level = 0) {
|
||||||
Log.e("Invalid XML resource ", resourceId);
|
Log.e("Invalid XML resource ", resourceId);
|
||||||
return false;
|
return false;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e("Cannot read drawable resource ", resourceId, " from file ", filename);
|
Log.e("Cannot read XML resource ", resourceId, " from file ", filename, " exception: ", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue