mirror of https://github.com/wayvr-org/wayvr.git
settings tab styles
This commit is contained in:
parent
6a064248dc
commit
031157ea8c
|
|
@ -56,17 +56,19 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<macro name="tab_style" color="background" sticky_color="primary" sticky_border_color="primary(rgb-mult-0.5)" hover_color="tertiary" hover_border_color="tertiary(rgb-mult-0.5)" />
|
||||
|
||||
<elements>
|
||||
<div gap="4">
|
||||
<Tabs id="tabs">
|
||||
<Tab name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
||||
<Tab name="skybox" translation="APP_SETTINGS.SKYBOX" sprite_src_builtin="dashboard/globe.svg" />
|
||||
<Tab name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="dashboard/options.svg" />
|
||||
<Tab name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="dashboard/controller.svg" />
|
||||
<Tab name="space_drag" translation="APP_SETTINGS.SPACE_DRAG" sprite_src_builtin="dashboard/drag.svg" />
|
||||
<Tab name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="dashboard/blocks.svg" />
|
||||
<Tab name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="dashboard/apps.svg" />
|
||||
<Tab name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="dashboard/cpu.svg" />
|
||||
<Tab macro="tab_style" name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
||||
<Tab macro="tab_style" name="skybox" translation="APP_SETTINGS.SKYBOX" sprite_src_builtin="dashboard/globe.svg" />
|
||||
<Tab macro="tab_style" name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="dashboard/options.svg" />
|
||||
<Tab macro="tab_style" name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="dashboard/controller.svg" />
|
||||
<Tab macro="tab_style" name="space_drag" translation="APP_SETTINGS.SPACE_DRAG" sprite_src_builtin="dashboard/drag.svg" />
|
||||
<Tab macro="tab_style" name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="dashboard/blocks.svg" />
|
||||
<Tab macro="tab_style" name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="dashboard/apps.svg" />
|
||||
<Tab macro="tab_style" name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="dashboard/cpu.svg" />
|
||||
</Tabs>
|
||||
<div flex_wrap="wrap" justify_content="stretch" gap="4" id="settings_root" width="100%">
|
||||
<!-- filled-in at runtime -->
|
||||
|
|
|
|||
|
|
@ -2,9 +2,34 @@ use flate2::read::GzDecoder;
|
|||
use std::ffi::OsStr;
|
||||
use std::io::Read;
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::i18n::LangsList;
|
||||
|
||||
pub enum AssetPathRc {
|
||||
WguiInternal(Rc<str>), // tied to internal wgui AssetProvider. Used internally
|
||||
BuiltIn(Rc<str>), // tied to user AssetProvider
|
||||
FileOrBuiltIn(Rc<str>), // attempts to load from a path relative to asset_folder, falls back to BuiltIn
|
||||
File(Rc<str>), // load from filesystem
|
||||
}
|
||||
|
||||
impl AssetPathRc {
|
||||
pub fn as_borrowed(&self) -> AssetPath<'_> {
|
||||
match self {
|
||||
Self::WguiInternal(path) => AssetPath::WguiInternal(path.as_ref()),
|
||||
Self::BuiltIn(path) => AssetPath::BuiltIn(path.as_ref()),
|
||||
Self::FileOrBuiltIn(path) => AssetPath::FileOrBuiltIn(path.as_ref()),
|
||||
Self::File(path) => AssetPath::File(path.as_ref()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a AssetPathRc> for AssetPath<'a> {
|
||||
fn from(path: &'a AssetPathRc) -> Self {
|
||||
path.as_borrowed()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum AssetPath<'a> {
|
||||
WguiInternal(&'a str), // tied to internal wgui AssetProvider. Used internally
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
assets::AssetPath,
|
||||
color::WguiColorName,
|
||||
assets::AssetPathRc,
|
||||
color::WguiColor,
|
||||
components::{
|
||||
Component, ComponentBase, ComponentTrait, RefreshData,
|
||||
button::{self, ComponentButton},
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
event::CallbackDataCommon,
|
||||
i18n::Translation,
|
||||
layout::WidgetPair,
|
||||
widget::{ConstructEssentials, div::WidgetDiv},
|
||||
widget::{ConstructEssentials, div::WidgetDiv, util::WLength},
|
||||
};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use taffy::{
|
||||
|
|
@ -16,17 +16,25 @@ use taffy::{
|
|||
prelude::{length, percent},
|
||||
};
|
||||
|
||||
pub struct Entry<'a> {
|
||||
pub sprite_src: Option<AssetPath<'a>>,
|
||||
pub struct Entry {
|
||||
pub sprite_src: Option<AssetPathRc>,
|
||||
pub text: Translation,
|
||||
pub name: &'a str,
|
||||
pub name: Rc<str>,
|
||||
}
|
||||
|
||||
pub struct Params<'a> {
|
||||
pub style: taffy::Style,
|
||||
pub entries: Vec<Entry<'a>>,
|
||||
pub entries: Vec<Entry>,
|
||||
pub selected_entry_name: &'a str, // default: ""
|
||||
pub on_select: Option<TabSelectCallback>,
|
||||
pub round: WLength,
|
||||
pub color: Option<WguiColor>,
|
||||
pub border: f32,
|
||||
pub border_color: Option<WguiColor>,
|
||||
pub hover_color: Option<WguiColor>,
|
||||
pub hover_border_color: Option<WguiColor>,
|
||||
pub sticky_color: Option<WguiColor>,
|
||||
pub sticky_border_color: Option<WguiColor>,
|
||||
}
|
||||
|
||||
struct MountedEntry {
|
||||
|
|
@ -65,18 +73,10 @@ impl ComponentTrait for ComponentTabs {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_button_selected(common: &mut CallbackDataCommon, button: &Rc<ComponentButton>, selected: bool) {
|
||||
if selected {
|
||||
button.set_color(common, WguiColorName::Primary.into());
|
||||
} else {
|
||||
button.set_color(common, WguiColorName::Background.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn select_entry(&mut self, common: &mut CallbackDataCommon, name: &Rc<str>) {
|
||||
for entry in &self.mounted_entries {
|
||||
set_button_selected(common, &entry.button, *entry.name == **name);
|
||||
entry.button.set_sticky_state(common, *entry.name == **name);
|
||||
}
|
||||
self.selected_entry_name = name.clone();
|
||||
|
||||
|
|
@ -121,7 +121,9 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||
let mut mounted_entries = Vec::<MountedEntry>::new();
|
||||
|
||||
// Mount entries
|
||||
for entry in params.entries {
|
||||
for (idx, entry) in params.entries.into_iter().enumerate() {
|
||||
let sprite_src = entry.sprite_src.as_ref().map(AssetPathRc::as_borrowed);
|
||||
|
||||
let (_, button) = button::construct(
|
||||
&mut ConstructEssentials {
|
||||
layout: ess.layout,
|
||||
|
|
@ -129,7 +131,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||
},
|
||||
button::Params {
|
||||
text: Some(entry.text),
|
||||
sprite_src: entry.sprite_src,
|
||||
sprite_src,
|
||||
style: taffy::Style {
|
||||
min_size: taffy::Size {
|
||||
width: percent(1.0),
|
||||
|
|
@ -138,15 +140,23 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||
justify_content: Some(taffy::JustifyContent::START),
|
||||
..Default::default()
|
||||
},
|
||||
round: params.round,
|
||||
color: params.color,
|
||||
border: params.border,
|
||||
border_color: params.border_color,
|
||||
hover_color: params.hover_color,
|
||||
hover_border_color: params.hover_border_color,
|
||||
sticky_color: params.sticky_color,
|
||||
sticky_border_color: params.sticky_border_color,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
// init colors
|
||||
set_button_selected(&mut ess.layout.common(), &button, false);
|
||||
button.set_sticky_state(&mut ess.layout.common(), idx == 0);
|
||||
|
||||
mounted_entries.push(MountedEntry {
|
||||
name: Rc::from(entry.name),
|
||||
name: entry.name,
|
||||
button,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
assets::AssetPath,
|
||||
assets::AssetPathRc,
|
||||
color::WguiColor,
|
||||
components::{Component, tabs},
|
||||
i18n::Translation,
|
||||
layout::WidgetID,
|
||||
parser::{AttribPair, ParserContext, get_asset_path_from_kv, process_component, style::parse_style},
|
||||
parser::{
|
||||
AttribPair, ParserContext, ParserFile, get_asset_path_rc_from_kv, process_attribs, process_component,
|
||||
style::{parse_color_opt, parse_round, parse_style},
|
||||
},
|
||||
widget::util::WLength,
|
||||
};
|
||||
|
||||
pub fn parse_component_tabs<'a>(
|
||||
file: &'a ParserFile,
|
||||
ctx: &mut ParserContext,
|
||||
node: roxmltree::Node<'a, 'a>,
|
||||
parent_id: WidgetID,
|
||||
|
|
@ -17,25 +25,71 @@ pub fn parse_component_tabs<'a>(
|
|||
|
||||
let mut entries = Vec::<tabs::Entry>::new();
|
||||
|
||||
let mut border = 2.0;
|
||||
let mut color: Option<WguiColor> = None;
|
||||
let mut border_color: Option<WguiColor> = None;
|
||||
let mut hover_color: Option<WguiColor> = None;
|
||||
let mut hover_border_color: Option<WguiColor> = None;
|
||||
let mut sticky_color: Option<WguiColor> = None;
|
||||
let mut sticky_border_color: Option<WguiColor> = None;
|
||||
let mut round = WLength::Units(4.0);
|
||||
|
||||
for child in node.children() {
|
||||
match child.tag_name().name() {
|
||||
"" => { /* ignore */ }
|
||||
"Tab" => {
|
||||
let mut name: Option<&str> = None;
|
||||
let mut name: Option<Rc<str>> = None;
|
||||
let mut text: Option<Translation> = None;
|
||||
let mut sprite_src: Option<AssetPath> = None;
|
||||
let mut sprite_src: Option<AssetPathRc> = None;
|
||||
|
||||
for attrib in child.attributes() {
|
||||
let (key, value) = (attrib.name(), attrib.value());
|
||||
match key {
|
||||
"name" => name = Some(value),
|
||||
"text" => text = Some(Translation::from_raw_text(value)),
|
||||
"translation" => text = Some(Translation::from_translation_key(value)),
|
||||
let attribs = process_attribs(file, ctx, &child, false);
|
||||
|
||||
for attrib in attribs.iter() {
|
||||
match &*attrib.attrib {
|
||||
"name" => name = Some(attrib.value.clone()),
|
||||
"text" => text = Some(Translation::from_raw_text(&*attrib.value)),
|
||||
"translation" => text = Some(Translation::from_translation_key(&*attrib.value)),
|
||||
"sprite_src" | "sprite_src_ext" | "sprite_src_builtin" | "sprite_src_internal" => {
|
||||
sprite_src = Some(get_asset_path_from_kv("sprite_", key, value));
|
||||
sprite_src = Some(get_asset_path_rc_from_kv(
|
||||
"sprite_",
|
||||
&*attrib.attrib,
|
||||
attrib.value.clone(),
|
||||
));
|
||||
continue;
|
||||
}
|
||||
"round" => {
|
||||
parse_round(
|
||||
ctx,
|
||||
tag_name,
|
||||
&*attrib.attrib,
|
||||
&*attrib.value,
|
||||
&mut round,
|
||||
ctx.layout.state.theme.rounding_mult,
|
||||
);
|
||||
}
|
||||
"color" => {
|
||||
parse_color_opt(ctx, tag_name, &*attrib.attrib, &*attrib.value, &mut color);
|
||||
}
|
||||
"border" => {
|
||||
ctx.parse_check_f32(tag_name, &*attrib.attrib, &*attrib.value, &mut border);
|
||||
}
|
||||
"border_color" => {
|
||||
parse_color_opt(ctx, tag_name, &*attrib.attrib, &*attrib.value, &mut border_color);
|
||||
}
|
||||
"hover_color" => {
|
||||
parse_color_opt(ctx, tag_name, &*attrib.attrib, &*attrib.value, &mut hover_color);
|
||||
}
|
||||
"hover_border_color" => {
|
||||
parse_color_opt(ctx, tag_name, &*attrib.attrib, &*attrib.value, &mut hover_border_color);
|
||||
}
|
||||
"sticky_color" => {
|
||||
parse_color_opt(ctx, tag_name, &*attrib.attrib, &*attrib.value, &mut sticky_color);
|
||||
}
|
||||
"sticky_border_color" => {
|
||||
parse_color_opt(ctx, tag_name, &*attrib.attrib, &*attrib.value, &mut sticky_border_color);
|
||||
}
|
||||
other_key => {
|
||||
ctx.print_invalid_attrib("Tab", other_key, value);
|
||||
ctx.print_invalid_attrib("Tab", other_key, &*attrib.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -59,6 +113,14 @@ pub fn parse_component_tabs<'a>(
|
|||
selected_entry_name: "first",
|
||||
entries,
|
||||
on_select: None,
|
||||
border,
|
||||
color,
|
||||
border_color,
|
||||
hover_color,
|
||||
hover_border_color,
|
||||
sticky_color,
|
||||
sticky_border_color,
|
||||
round,
|
||||
},
|
||||
)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ mod widget_rectangle;
|
|||
mod widget_sprite;
|
||||
|
||||
use crate::{
|
||||
assets::{AssetPath, AssetPathOwned, normalize_path},
|
||||
assets::{AssetPath, AssetPathOwned, AssetPathRc, normalize_path},
|
||||
components::{Component, ComponentWeak},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
|
|
@ -1082,7 +1082,9 @@ fn parse_child<'a>(
|
|||
"EditBox" => new_widget_id = Some(parse_component_editbox(ctx, parent_id, &attribs, tag_name)?),
|
||||
"BarGraph" => new_widget_id = Some(parse_component_bar_graph(ctx, parent_id, &attribs, tag_name)?),
|
||||
"Tabs" => {
|
||||
new_widget_id = Some(parse_component_tabs(ctx, child_node, parent_id, &attribs, tag_name)?);
|
||||
new_widget_id = Some(parse_component_tabs(
|
||||
file, ctx, child_node, parent_id, &attribs, tag_name,
|
||||
)?);
|
||||
}
|
||||
"" => { /* ignore */ }
|
||||
other_tag_name => {
|
||||
|
|
@ -1327,21 +1329,26 @@ fn parse_document_root(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_asset_path_from_kv<'a>(prefix: &'static str, key: &'a str, value: &'a str) -> AssetPath<'a> {
|
||||
let key_split = match key.find(prefix) {
|
||||
Some(pos) => {
|
||||
assert!(pos == 0, "invalid split");
|
||||
key.get(prefix.len()..).unwrap()
|
||||
}
|
||||
None => key,
|
||||
};
|
||||
match key_split {
|
||||
fn get_asset_path_from_kv<'a>(prefix: &str, key: &'a str, value: &'a str) -> AssetPath<'a> {
|
||||
let key = key.strip_prefix(prefix).unwrap_or(key);
|
||||
|
||||
match key {
|
||||
"src" => AssetPath::FileOrBuiltIn(value),
|
||||
"src_ext" => AssetPath::File(value),
|
||||
"src_builtin" => AssetPath::BuiltIn(value),
|
||||
"src_internal" => AssetPath::WguiInternal(value),
|
||||
other => {
|
||||
panic!("unexpected attrib {other}");
|
||||
}
|
||||
other => panic!("unexpected attrib {other}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_asset_path_rc_from_kv(prefix: &'static str, key: &str, value: Rc<str>) -> AssetPathRc {
|
||||
let key = key.strip_prefix(prefix).unwrap_or(key);
|
||||
|
||||
match key {
|
||||
"src" => AssetPathRc::FileOrBuiltIn(value),
|
||||
"src_ext" => AssetPathRc::File(value),
|
||||
"src_builtin" => AssetPathRc::BuiltIn(value),
|
||||
"src_internal" => AssetPathRc::WguiInternal(value),
|
||||
other => panic!("unexpected attrib {other}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue