dash-frontend: Top panel title
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
<theme>
|
<theme>
|
||||||
<var key="side_size" value="48" />
|
<var key="side_size" value="48" />
|
||||||
|
<var key="top_size" value="40" />
|
||||||
<var key="side_sprite_size" value="26" />
|
<var key="side_sprite_size" value="26" />
|
||||||
<var key="side_button_size" value="48" />
|
<var key="side_button_size" value="48" />
|
||||||
</theme>
|
</theme>
|
||||||
@@ -25,13 +26,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div position="absolute" width="100%" justify_content="space_between">
|
|
||||||
<div />
|
|
||||||
<div padding="6">
|
|
||||||
<Button id="btn_close" sprite_src_builtin="dashboard/close.svg" color="#000000" border="2" border_color="~color_faded" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- left/right separator (menu and rest) -->
|
<!-- left/right separator (menu and rest) -->
|
||||||
<div flex_direction="row" gap="8" width="100%" height="100%" padding="4" interactable="0">
|
<div flex_direction="row" gap="8" width="100%" height="100%" padding="4" interactable="0">
|
||||||
<!-- LEFT MENU -->
|
<!-- LEFT MENU -->
|
||||||
@@ -60,15 +54,29 @@
|
|||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
<!-- REST -->
|
<!-- REST -->
|
||||||
<!-- content/bottom panel separator -->
|
<!-- top/content/bottom panel separator -->
|
||||||
<div
|
<div
|
||||||
flex_direction="column"
|
flex_direction="column"
|
||||||
gap="8"
|
gap="8"
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
overflow_x="scroll">
|
overflow_x="scroll">
|
||||||
<!-- CONTENT -->
|
<!-- TOP PANEL -->
|
||||||
|
<div position="relative" width="100%" height="~top_size" min_height="~top_size" max_height="~top_size" justify_content="end">
|
||||||
|
<!-- Title bar -->
|
||||||
|
<div width="100%" align_items="center" justify_content="center">
|
||||||
|
<rectangle min_width="300" height="100%" consume_mouse_events="1" round="100%" color="~color_top_panel" align_items="center" justify_content="center" gap="8">
|
||||||
|
<sprite id="sprite_titlebar_icon" width="28" height="28" />
|
||||||
|
<label id="label_titlebar_title" weight="bold" size="16" text="Title" />
|
||||||
|
</rectangle>
|
||||||
|
</div>
|
||||||
|
<!-- Close button -->
|
||||||
|
<Button position="absolute" id="btn_close" color="~color_top_panel" round="100%" width="~top_size" height="~top_size" tooltip="CLOSE_WINDOW" tooltip_side="left">
|
||||||
|
<sprite src_builtin="dashboard/close.svg" width="32" height="32" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- CONTENT -->
|
||||||
<!-- color and color2 alpha will be modified at runtime -->
|
<!-- color and color2 alpha will be modified at runtime -->
|
||||||
<rectangle
|
<rectangle
|
||||||
id="rect_content"
|
id="rect_content"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<layout>
|
<layout>
|
||||||
<include src="t_tab_title.xml" />
|
|
||||||
<include src="../theme.xml" />
|
<include src="../theme.xml" />
|
||||||
|
|
||||||
<template name="AppEntry">
|
<template name="AppEntry">
|
||||||
@@ -25,7 +24,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<TabTitle translation="APPLICATIONS" icon="dashboard/apps.svg" />
|
|
||||||
<!-- placeholders for now -->
|
<!-- placeholders for now -->
|
||||||
<!--
|
<!--
|
||||||
<div gap="4" align_items="center">
|
<div gap="4" align_items="center">
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
<layout>
|
<layout>
|
||||||
<include src="t_tab_title.xml" />
|
|
||||||
<include src="../t_group_box.xml" />
|
<include src="../t_group_box.xml" />
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<TabTitle translation="GAMES" icon="dashboard/games.svg" />
|
|
||||||
<rectangle macro="group_box" id="running_games_list_parent" align_self="center" />
|
<rectangle macro="group_box" id="running_games_list_parent" align_self="center" />
|
||||||
<div id="game_list_parent" align_items="center" />
|
<div id="game_list_parent" align_items="center" />
|
||||||
</elements>
|
</elements>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<layout>
|
<layout>
|
||||||
<include src="t_tab_title.xml" />
|
|
||||||
<include src="../t_group_box.xml" />
|
<include src="../t_group_box.xml" />
|
||||||
|
|
||||||
|
|
||||||
<!-- key: str, value: str -->
|
<!-- key: str, value: str -->
|
||||||
<template name="BoolFlag">
|
<template name="BoolFlag">
|
||||||
<div flex_direction="row" gap="4">
|
<div flex_direction="row" gap="4">
|
||||||
@@ -27,7 +25,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<TabTitle translation="MONADO_RUNTIME" icon="dashboard/monado.svg" />
|
|
||||||
<label translation="DISPLAY_BRIGHTNESS" />
|
<label translation="DISPLAY_BRIGHTNESS" />
|
||||||
<Slider id="slider_brightness" width="300" height="24" min_value="0" max_value="140" />
|
<Slider id="slider_brightness" width="300" height="24" min_value="0" max_value="140" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<layout>
|
<layout>
|
||||||
<include src="t_tab_title.xml" />
|
|
||||||
<include src="../t_group_box.xml" />
|
<include src="../t_group_box.xml" />
|
||||||
<include src="../t_dropdown_button.xml" />
|
<include src="../t_dropdown_button.xml" />
|
||||||
|
|
||||||
@@ -46,7 +45,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<TabTitle translation="SETTINGS" icon="dashboard/settings.svg" />
|
|
||||||
<div gap="4">
|
<div gap="4">
|
||||||
<Tabs id="tabs">
|
<Tabs id="tabs">
|
||||||
<Tab name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
<Tab name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
<layout>
|
|
||||||
<!-- translation, icon -->
|
|
||||||
<template name="TabTitle">
|
|
||||||
<div gap="8" align_items="center">
|
|
||||||
<sprite src_builtin="${icon}" width="24" height="24" />
|
|
||||||
<label translation="${translation}" size="18" weight="bold" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</layout>
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
<theme>
|
<theme>
|
||||||
<var key="color_menu_dark" value="#0A0A0ACC" />
|
<var key="color_menu_dark" value="#0A0A0ACC" />
|
||||||
<var key="color_accent" value="#008cff" />
|
<var key="color_accent" value="#008cff" />
|
||||||
|
<var key="color_top_panel" value="#00000099" />
|
||||||
<var key="color_bottom_panel" value="#141e28" />
|
<var key="color_bottom_panel" value="#141e28" />
|
||||||
</theme>
|
</theme>
|
||||||
</layout>
|
</layout>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::{path::PathBuf, rc::Rc};
|
use std::{path::PathBuf, rc::Rc};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use chrono::Timelike;
|
use chrono::Timelike;
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
@@ -10,8 +11,9 @@ use wgui::{
|
|||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, LayoutParams, LayoutUpdateParams, LayoutUpdateResult, WidgetID},
|
layout::{Layout, LayoutParams, LayoutUpdateParams, LayoutUpdateResult, WidgetID},
|
||||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||||
|
renderer_vk::text::custom_glyph::CustomGlyphData,
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
widget::{label::WidgetLabel, rectangle::WidgetRectangle},
|
widget::{label::WidgetLabel, rectangle::WidgetRectangle, sprite::WidgetSprite},
|
||||||
windowing::window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement},
|
windowing::window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement},
|
||||||
};
|
};
|
||||||
use wlx_common::{
|
use wlx_common::{
|
||||||
@@ -22,7 +24,7 @@ use wlx_common::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assets,
|
assets,
|
||||||
tab::{apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings, Tab, TabType},
|
tab::{Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings},
|
||||||
util::{
|
util::{
|
||||||
popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
|
popup_manager::{MountPopupParams, PopupManager, PopupManagerParams},
|
||||||
toast_manager::ToastManager,
|
toast_manager::ToastManager,
|
||||||
@@ -32,8 +34,10 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub struct FrontendWidgets {
|
pub struct FrontendWidgets {
|
||||||
pub id_label_time: WidgetID,
|
id_label_time: WidgetID,
|
||||||
pub id_rect_content: WidgetID,
|
id_rect_content: WidgetID,
|
||||||
|
id_sprite_titlebar_icon: WidgetID,
|
||||||
|
id_label_titlebar_title: WidgetID,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FrontendTasks = Tasks<FrontendTask>;
|
pub type FrontendTasks = Tasks<FrontendTask>;
|
||||||
@@ -148,6 +152,8 @@ impl<T: 'static> Frontend<T> {
|
|||||||
|
|
||||||
let id_label_time = state.get_widget_id("label_time")?;
|
let id_label_time = state.get_widget_id("label_time")?;
|
||||||
let id_rect_content = state.get_widget_id("rect_content")?;
|
let id_rect_content = state.get_widget_id("rect_content")?;
|
||||||
|
let id_sprite_titlebar_icon = state.get_widget_id("sprite_titlebar_icon")?;
|
||||||
|
let id_label_titlebar_title = state.get_widget_id("label_titlebar_title")?;
|
||||||
|
|
||||||
let timestep = Timestep::new(60.0);
|
let timestep = Timestep::new(60.0);
|
||||||
|
|
||||||
@@ -161,6 +167,8 @@ impl<T: 'static> Frontend<T> {
|
|||||||
widgets: FrontendWidgets {
|
widgets: FrontendWidgets {
|
||||||
id_label_time,
|
id_label_time,
|
||||||
id_rect_content,
|
id_rect_content,
|
||||||
|
id_sprite_titlebar_icon,
|
||||||
|
id_label_titlebar_title,
|
||||||
},
|
},
|
||||||
timestep,
|
timestep,
|
||||||
interface: params.interface,
|
interface: params.interface,
|
||||||
@@ -283,9 +291,10 @@ impl<T: 'static> Frontend<T> {
|
|||||||
let mut common = c.common();
|
let mut common = c.common();
|
||||||
|
|
||||||
{
|
{
|
||||||
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.widgets.id_label_time) else {
|
let mut label = common
|
||||||
anyhow::bail!("");
|
.state
|
||||||
};
|
.widgets
|
||||||
|
.cast_as::<WidgetLabel>(self.widgets.id_label_time)?;
|
||||||
|
|
||||||
let now = chrono::Local::now();
|
let now = chrono::Local::now();
|
||||||
let hours = now.hour();
|
let hours = now.hour();
|
||||||
@@ -370,11 +379,48 @@ impl<T: 'static> Frontend<T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_tab_title(&mut self, translation: &str, icon: &str) -> anyhow::Result<()> {
|
||||||
|
let mut c = self.layout.start_common();
|
||||||
|
let mut common = c.common();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut label = common
|
||||||
|
.state
|
||||||
|
.widgets
|
||||||
|
.cast_as::<WidgetLabel>(self.widgets.id_label_titlebar_title)?;
|
||||||
|
label.set_text(&mut common, Translation::from_translation_key(translation));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut sprite = common
|
||||||
|
.state
|
||||||
|
.widgets
|
||||||
|
.cast_as::<WidgetSprite>(self.widgets.id_sprite_titlebar_icon)?;
|
||||||
|
sprite.set_content(
|
||||||
|
&mut common,
|
||||||
|
Some(CustomGlyphData::from_assets(&self.globals, AssetPath::BuiltIn(icon))?),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
c.finish()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn set_tab(&mut self, data: &mut T, tab_type: TabType) -> anyhow::Result<()> {
|
fn set_tab(&mut self, data: &mut T, tab_type: TabType) -> anyhow::Result<()> {
|
||||||
log::info!("Setting tab to {tab_type:?}");
|
log::info!("Setting tab to {tab_type:?}");
|
||||||
let widget_content = self.state.fetch_widget(&self.layout.state, "content")?;
|
let widget_content = self.state.fetch_widget(&self.layout.state, "content")?;
|
||||||
self.layout.remove_children(widget_content.id);
|
self.layout.remove_children(widget_content.id);
|
||||||
|
|
||||||
|
let (tab_translation, icon_path) = match tab_type {
|
||||||
|
TabType::Home => ("HOME_SCREEN", "dashboard/home.svg"),
|
||||||
|
TabType::Apps => ("APPLICATIONS", "dashboard/apps.svg"),
|
||||||
|
TabType::Games => ("GAMES", "dashboard/games.svg"),
|
||||||
|
TabType::Monado => ("MONADO_RUNTIME", "dashboard/monado.svg"),
|
||||||
|
TabType::Settings => ("SETTINGS", "dashboard/settings.svg"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.set_tab_title(tab_translation, icon_path)?;
|
||||||
|
|
||||||
let tab: Box<dyn Tab<T>> = match tab_type {
|
let tab: Box<dyn Tab<T>> = match tab_type {
|
||||||
TabType::Home => Box::new(TabHome::new(self, widget_content.id, data)?),
|
TabType::Home => Box::new(TabHome::new(self, widget_content.id, data)?),
|
||||||
TabType::Apps => Box::new(TabApps::new(self, widget_content.id, data)?),
|
TabType::Apps => Box::new(TabApps::new(self, widget_content.id, data)?),
|
||||||
|
|||||||
@@ -55,8 +55,7 @@ fn button_click_callback(
|
|||||||
) -> ButtonClickCallback {
|
) -> ButtonClickCallback {
|
||||||
Rc::new(move |common, _e| {
|
Rc::new(move |common, _e| {
|
||||||
label
|
label
|
||||||
.get_as::<WidgetLabel>()
|
.cast::<WidgetLabel>()?
|
||||||
.unwrap()
|
|
||||||
.set_text(common, Translation::from_raw_text(text));
|
.set_text(common, Translation::from_raw_text(text));
|
||||||
|
|
||||||
button.try_cast::<ComponentButton>()?.set_text(
|
button.try_cast::<ComponentButton>()?.set_text(
|
||||||
@@ -169,7 +168,7 @@ impl TestbedGeneric {
|
|||||||
let cb_first = parser_state.fetch_component_as::<ComponentCheckbox>("cb_first")?;
|
let cb_first = parser_state.fetch_component_as::<ComponentCheckbox>("cb_first")?;
|
||||||
let label = label_cur_option.widget.clone();
|
let label = label_cur_option.widget.clone();
|
||||||
cb_first.on_toggle(Box::new(move |common, e| {
|
cb_first.on_toggle(Box::new(move |common, e| {
|
||||||
let mut widget = label.get_as::<WidgetLabel>().unwrap();
|
let mut widget = label.cast::<WidgetLabel>()?;
|
||||||
let text = format!("checkbox toggle: {}", e.checked);
|
let text = format!("checkbox toggle: {}", e.checked);
|
||||||
widget.set_text(common, Translation::from_raw_text(&text));
|
widget.set_text(common, Translation::from_raw_text(&text));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -103,8 +103,7 @@ pub(super) fn setup_custom_label<S: 'static>(
|
|||||||
layout
|
layout
|
||||||
.state
|
.state
|
||||||
.widgets
|
.widgets
|
||||||
.get_as::<WidgetLabel>(attribs.widget_id)
|
.cast_as::<WidgetLabel>(attribs.widget_id)?
|
||||||
.unwrap()
|
|
||||||
.set_text_simple(&mut globals, Translation::from_raw_text(pretty_tz));
|
.set_text_simple(&mut globals, Translation::from_raw_text(pretty_tz));
|
||||||
|
|
||||||
// does not need to be dynamic
|
// does not need to be dynamic
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ impl WidgetMap {
|
|||||||
self.0.get(handle)?.get_as::<T>()
|
self.0.get(handle)?.get_as::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast_as<T: 'static>(&self, handle: WidgetID) -> anyhow::Result<RefMut<'_, T>> {
|
||||||
|
self.get_as(handle).context("Widget cast failed")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(&self, handle: WidgetID) -> Option<&Widget> {
|
pub fn get(&self, handle: WidgetID) -> Option<&Widget> {
|
||||||
self.0.get(handle)
|
self.0.get(handle)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::Context;
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use taffy::{NodeId, TaffyTree};
|
use taffy::{NodeId, TaffyTree};
|
||||||
|
|
||||||
@@ -248,10 +249,18 @@ impl dyn WidgetObj {
|
|||||||
any.downcast_ref::<T>()
|
any.downcast_ref::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast<T: 'static>(&self) -> anyhow::Result<&T> {
|
||||||
|
self.get_as().context("cast failed")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_as_mut<T: 'static>(&mut self) -> Option<&mut T> {
|
pub fn get_as_mut<T: 'static>(&mut self) -> Option<&mut T> {
|
||||||
let any = self.as_any_mut();
|
let any = self.as_any_mut();
|
||||||
any.downcast_mut::<T>()
|
any.downcast_mut::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast_mut<T: 'static>(&mut self) -> anyhow::Result<&mut T> {
|
||||||
|
self.get_as_mut().context("cast failed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InvokeData<'a, 'b, U1: 'static, U2: 'static> {
|
struct InvokeData<'a, 'b, U1: 'static, U2: 'static> {
|
||||||
|
|||||||
Reference in New Issue
Block a user