dash-frontend: popup manager
This commit is contained in:
@@ -80,6 +80,7 @@
|
|||||||
<rectangle
|
<rectangle
|
||||||
position="absolute" width="100%" height="100%"
|
position="absolute" width="100%" height="100%"
|
||||||
gradient="radial" color="#44BBFF22" color2="#00000000" />
|
gradient="radial" color="#44BBFF22" color2="#00000000" />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id="content"
|
id="content"
|
||||||
flex_direction="column"
|
flex_direction="column"
|
||||||
@@ -95,6 +96,9 @@
|
|||||||
>
|
>
|
||||||
<!-- filled-in at runtime -->
|
<!-- filled-in at runtime -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div position="absolute" id="popup_manager" width="100%" height="100%" />
|
||||||
|
|
||||||
</rectangle>
|
</rectangle>
|
||||||
<!-- BOTTOM PANEL -->
|
<!-- BOTTOM PANEL -->
|
||||||
<rectangle
|
<rectangle
|
||||||
|
|||||||
7
dash-frontend/assets/gui/view/app_launcher.xml
Normal file
7
dash-frontend/assets/gui/view/app_launcher.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<layout>
|
||||||
|
<elements>
|
||||||
|
<rectangle new_pass="1" color="#ff000099" width="100%" height="100%">
|
||||||
|
<label text="TEST" size="80" />
|
||||||
|
</rectangle>
|
||||||
|
</elements>
|
||||||
|
</layout>
|
||||||
45
dash-frontend/assets/gui/view/popup_window.xml
Normal file
45
dash-frontend/assets/gui/view/popup_window.xml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<layout>
|
||||||
|
<include src="../theme.xml" />
|
||||||
|
|
||||||
|
<elements>
|
||||||
|
<div
|
||||||
|
id="root"
|
||||||
|
new_pass="1"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
flex_direction="column"
|
||||||
|
>
|
||||||
|
<!-- Top black bar -->
|
||||||
|
<rectangle
|
||||||
|
position="relative"
|
||||||
|
color="#000000"
|
||||||
|
round="4"
|
||||||
|
width="100%" height="48"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- Shine effect at the top -->
|
||||||
|
<rectangle position="absolute" width="100%" height="2" round="4" color="#ffffff55" />
|
||||||
|
|
||||||
|
<!-- Top bar contents -->
|
||||||
|
<div gap="16" align_items="center">
|
||||||
|
<!-- Back button -->
|
||||||
|
<Button id="but_back" width="48" height="48" color="#ffffff00" border_color="#ffffff00">
|
||||||
|
<sprite src="dashboard/back.svg" width="24" height="24" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<label id="popup_title" weight="bold" size="18" text="Pop-up title" />
|
||||||
|
</div>
|
||||||
|
</rectangle>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<rectangle width="100%" height="100%"
|
||||||
|
color="#010310cc"
|
||||||
|
color2="#061e4acc"
|
||||||
|
gradient="vertical"
|
||||||
|
padding="16"
|
||||||
|
id="content">
|
||||||
|
</rectangle>
|
||||||
|
</div>
|
||||||
|
</elements>
|
||||||
|
</layout>
|
||||||
@@ -19,8 +19,14 @@ use crate::{
|
|||||||
Tab, TabParams, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses,
|
Tab, TabParams, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses,
|
||||||
settings::TabSettings,
|
settings::TabSettings,
|
||||||
},
|
},
|
||||||
|
util::popup_manager::{PopupManager, PopupManagerParams},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct FrontendWidgets {
|
||||||
|
pub id_label_time: WidgetID,
|
||||||
|
pub id_rect_content: WidgetID,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Frontend {
|
pub struct Frontend {
|
||||||
pub layout: RcLayout,
|
pub layout: RcLayout,
|
||||||
globals: WguiGlobals,
|
globals: WguiGlobals,
|
||||||
@@ -36,8 +42,8 @@ pub struct Frontend {
|
|||||||
|
|
||||||
ticks: u32,
|
ticks: u32,
|
||||||
|
|
||||||
id_label_time: WidgetID,
|
widgets: FrontendWidgets,
|
||||||
id_rect_content: WidgetID,
|
popup_manager: PopupManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InitParams {
|
pub struct InitParams {
|
||||||
@@ -50,6 +56,7 @@ pub enum FrontendTask {
|
|||||||
SetTab(TabType),
|
SetTab(TabType),
|
||||||
RefreshClock,
|
RefreshClock,
|
||||||
RefreshBackground,
|
RefreshBackground,
|
||||||
|
MountPopup,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frontend {
|
impl Frontend {
|
||||||
@@ -71,7 +78,7 @@ impl Frontend {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
let (mut layout, state) = wgui::parser::new_layout_from_assets(
|
||||||
&ParseDocumentParams {
|
&ParseDocumentParams {
|
||||||
globals: globals.clone(),
|
globals: globals.clone(),
|
||||||
path: AssetPath::BuiltIn("gui/dashboard.xml"),
|
path: AssetPath::BuiltIn("gui/dashboard.xml"),
|
||||||
@@ -80,6 +87,13 @@ impl Frontend {
|
|||||||
&LayoutParams { resize_to_parent: true },
|
&LayoutParams { resize_to_parent: true },
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let id_popup_manager = state.get_widget_id("popup_manager")?;
|
||||||
|
let popup_manager = PopupManager::new(PopupManagerParams {
|
||||||
|
globals: globals.clone(),
|
||||||
|
layout: &mut layout,
|
||||||
|
parent_id: id_popup_manager,
|
||||||
|
})?;
|
||||||
|
|
||||||
let rc_layout = layout.as_rc();
|
let rc_layout = layout.as_rc();
|
||||||
|
|
||||||
let mut tasks = VecDeque::<FrontendTask>::new();
|
let mut tasks = VecDeque::<FrontendTask>::new();
|
||||||
@@ -95,9 +109,12 @@ impl Frontend {
|
|||||||
globals,
|
globals,
|
||||||
tasks,
|
tasks,
|
||||||
ticks: 0,
|
ticks: 0,
|
||||||
|
widgets: FrontendWidgets {
|
||||||
id_label_time,
|
id_label_time,
|
||||||
id_rect_content,
|
id_rect_content,
|
||||||
|
},
|
||||||
settings: params.settings,
|
settings: params.settings,
|
||||||
|
popup_manager,
|
||||||
};
|
};
|
||||||
|
|
||||||
// init some things first
|
// init some things first
|
||||||
@@ -142,7 +159,7 @@ impl Frontend {
|
|||||||
let mut common = c.common();
|
let mut common = c.common();
|
||||||
|
|
||||||
{
|
{
|
||||||
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.id_label_time) else {
|
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.widgets.id_label_time) else {
|
||||||
anyhow::bail!("");
|
anyhow::bail!("");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -165,10 +182,22 @@ impl Frontend {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mount_popup(&mut self) -> anyhow::Result<()> {
|
||||||
|
let mut layout = self.layout.borrow_mut();
|
||||||
|
|
||||||
|
self.popup_manager.push_popup(self.globals.clone(), &mut layout)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn update_background(&self) -> anyhow::Result<()> {
|
fn update_background(&self) -> anyhow::Result<()> {
|
||||||
let layout = self.layout.borrow_mut();
|
let layout = self.layout.borrow_mut();
|
||||||
|
|
||||||
let Some(mut rect) = layout.state.widgets.get_as::<WidgetRectangle>(self.id_rect_content) else {
|
let Some(mut rect) = layout
|
||||||
|
.state
|
||||||
|
.widgets
|
||||||
|
.get_as::<WidgetRectangle>(self.widgets.id_rect_content)
|
||||||
|
else {
|
||||||
anyhow::bail!("");
|
anyhow::bail!("");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -197,6 +226,7 @@ impl Frontend {
|
|||||||
FrontendTask::SetTab(tab_type) => self.set_tab(tab_type, rc_this)?,
|
FrontendTask::SetTab(tab_type) => self.set_tab(tab_type, rc_this)?,
|
||||||
FrontendTask::RefreshClock => self.update_time()?,
|
FrontendTask::RefreshClock => self.update_time()?,
|
||||||
FrontendTask::RefreshBackground => self.update_background()?,
|
FrontendTask::RefreshBackground => self.update_background()?,
|
||||||
|
FrontendTask::MountPopup => self.mount_popup()?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -212,6 +242,7 @@ impl Frontend {
|
|||||||
layout: &mut layout,
|
layout: &mut layout,
|
||||||
parent_id: widget_content.id,
|
parent_id: widget_content.id,
|
||||||
frontend: rc_this,
|
frontend: rc_this,
|
||||||
|
frontend_widgets: &self.widgets,
|
||||||
settings: self.settings.get_mut(),
|
settings: self.settings.get_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ pub mod settings;
|
|||||||
mod tab;
|
mod tab;
|
||||||
mod util;
|
mod util;
|
||||||
mod various;
|
mod various;
|
||||||
|
mod views;
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ use wgui::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
frontend::FrontendTask,
|
||||||
tab::{Tab, TabParams, TabType},
|
tab::{Tab, TabParams, TabType},
|
||||||
util::{self, desktop_finder::DesktopEntry},
|
util::{self, desktop_finder::DesktopEntry},
|
||||||
|
views,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TabApps {
|
pub struct TabApps {
|
||||||
@@ -95,10 +97,14 @@ impl AppList {
|
|||||||
let data = parser_state.parse_template(doc_params, "AppEntry", params.layout, list_parent.id, template_params)?;
|
let data = parser_state.parse_template(doc_params, "AppEntry", params.layout, list_parent.id, template_params)?;
|
||||||
|
|
||||||
let button = data.fetch_component_as::<ComponentButton>("button")?;
|
let button = data.fetch_component_as::<ComponentButton>("button")?;
|
||||||
button.on_click(Box::new(move |_common, _evt| {
|
|
||||||
log::info!("click");
|
button.on_click({
|
||||||
|
let frontend = params.frontend.clone();
|
||||||
|
Box::new(move |_common, _evt| {
|
||||||
|
frontend.borrow_mut().push_task(FrontendTask::MountPopup);
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
})
|
||||||
|
});
|
||||||
|
|
||||||
self.data.push(data);
|
self.data.push(data);
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use wgui::{
|
|||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::frontend::{FrontendTask, RcFrontend};
|
use crate::frontend::{FrontendTask, FrontendWidgets, RcFrontend};
|
||||||
|
|
||||||
pub mod apps;
|
pub mod apps;
|
||||||
pub mod games;
|
pub mod games;
|
||||||
@@ -30,6 +30,7 @@ pub struct TabParams<'a> {
|
|||||||
pub layout: &'a mut Layout,
|
pub layout: &'a mut Layout,
|
||||||
pub parent_id: WidgetID,
|
pub parent_id: WidgetID,
|
||||||
pub frontend: &'a RcFrontend,
|
pub frontend: &'a RcFrontend,
|
||||||
|
pub frontend_widgets: &'a FrontendWidgets,
|
||||||
pub settings: &'a mut crate::settings::Settings,
|
pub settings: &'a mut crate::settings::Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use gio::prelude::{AppInfoExt, IconExt};
|
use gio::prelude::{AppInfoExt, IconExt};
|
||||||
use gtk::traits::IconThemeExt;
|
use gtk::traits::IconThemeExt;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
#[allow(dead_code)] // TODO: remove this
|
#[allow(dead_code)] // TODO: remove this
|
||||||
pub struct DesktopEntry {
|
pub struct DesktopEntry {
|
||||||
pub exec_path: String,
|
pub exec_path: String,
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
pub mod desktop_finder;
|
pub mod desktop_finder;
|
||||||
|
pub mod popup_manager;
|
||||||
|
|||||||
110
dash-frontend/src/util/popup_manager.rs
Normal file
110
dash-frontend/src/util/popup_manager.rs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
rc::{Rc, Weak},
|
||||||
|
};
|
||||||
|
|
||||||
|
use wgui::{
|
||||||
|
assets::AssetPath,
|
||||||
|
components::button::ComponentButton,
|
||||||
|
event::{EventAlterables, StyleSetRequest},
|
||||||
|
globals::WguiGlobals,
|
||||||
|
layout::{Layout, LayoutTask, WidgetID},
|
||||||
|
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||||
|
taffy::Display,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PopupManagerParams<'a> {
|
||||||
|
pub globals: WguiGlobals,
|
||||||
|
pub layout: &'a mut Layout,
|
||||||
|
pub parent_id: WidgetID,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MountedPopup {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
state: ParserState,
|
||||||
|
id_root: WidgetID,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
popup_stack: Vec<MountedPopup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PopupManager {
|
||||||
|
pub state: Rc<RefCell<State>>,
|
||||||
|
globals: WguiGlobals,
|
||||||
|
parent_id: WidgetID,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PushPopupResult {
|
||||||
|
pub id_content: WidgetID,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn refresh_stack(&mut self, alterables: &mut EventAlterables) {
|
||||||
|
// show only the topmost popup
|
||||||
|
for (idx, popup) in self.popup_stack.iter().enumerate() {
|
||||||
|
alterables.set_style(
|
||||||
|
popup.id_root,
|
||||||
|
StyleSetRequest::Display(if idx == self.popup_stack.len() - 1 {
|
||||||
|
Display::Flex
|
||||||
|
} else {
|
||||||
|
Display::None
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_popup(&mut self, alterables: &mut EventAlterables) {
|
||||||
|
let Some(popup) = self.popup_stack.pop() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
alterables.tasks.push(LayoutTask::RemoveWidget(popup.id_root));
|
||||||
|
self.refresh_stack(alterables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PopupManager {
|
||||||
|
pub fn new(params: PopupManagerParams) -> anyhow::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
globals: params.globals,
|
||||||
|
parent_id: params.parent_id,
|
||||||
|
state: Rc::new(RefCell::new(State {
|
||||||
|
popup_stack: Vec::new(),
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_popup(&mut self, globals: WguiGlobals, layout: &mut Layout) -> anyhow::Result<PushPopupResult> {
|
||||||
|
let doc_params = &ParseDocumentParams {
|
||||||
|
globals,
|
||||||
|
path: AssetPath::BuiltIn("gui/view/popup_window.xml"),
|
||||||
|
extra: Default::default(),
|
||||||
|
};
|
||||||
|
let state = wgui::parser::parse_from_assets(doc_params, layout, self.parent_id)?;
|
||||||
|
|
||||||
|
let id_root = state.get_widget_id("root")?;
|
||||||
|
let id_content = state.get_widget_id("content")?;
|
||||||
|
|
||||||
|
let but_back = state.fetch_component_as::<ComponentButton>("but_back")?;
|
||||||
|
|
||||||
|
but_back.on_click({
|
||||||
|
let state = self.state.clone();
|
||||||
|
Box::new(move |common, _evt| {
|
||||||
|
state.borrow_mut().pop_popup(common.alterables);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let mounted_popup = MountedPopup { state, id_root };
|
||||||
|
|
||||||
|
let mut state = self.state.borrow_mut();
|
||||||
|
state.popup_stack.push(mounted_popup);
|
||||||
|
|
||||||
|
let mut c = layout.start_common();
|
||||||
|
state.refresh_stack(c.common().alterables);
|
||||||
|
c.finish()?;
|
||||||
|
|
||||||
|
Ok(PushPopupResult { id_content })
|
||||||
|
}
|
||||||
|
}
|
||||||
39
dash-frontend/src/views/app_launcher.rs
Normal file
39
dash-frontend/src/views/app_launcher.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
use wgui::{
|
||||||
|
assets::AssetPath,
|
||||||
|
globals::WguiGlobals,
|
||||||
|
layout::{Layout, WidgetID},
|
||||||
|
parser::{ParseDocumentParams, ParserState},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::util::desktop_finder::DesktopEntry;
|
||||||
|
|
||||||
|
pub struct View {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub state: ParserState,
|
||||||
|
|
||||||
|
entry: DesktopEntry,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Params<'a> {
|
||||||
|
pub globals: WguiGlobals,
|
||||||
|
pub entry: DesktopEntry,
|
||||||
|
pub layout: &'a mut Layout,
|
||||||
|
pub parent_id: WidgetID,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View {
|
||||||
|
pub fn new(params: Params) -> anyhow::Result<Self> {
|
||||||
|
let doc_params = &ParseDocumentParams {
|
||||||
|
globals: params.globals.clone(),
|
||||||
|
path: AssetPath::BuiltIn("gui/view/app_launcher.xml"),
|
||||||
|
extra: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut state = wgui::parser::parse_from_assets(doc_params, params.layout, params.parent_id)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
entry: params.entry,
|
||||||
|
state,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
1
dash-frontend/src/views/mod.rs
Normal file
1
dash-frontend/src/views/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod app_launcher;
|
||||||
Reference in New Issue
Block a user