139 lines
4.4 KiB
Rust
139 lines
4.4 KiB
Rust
use crate::{ensure_xml_tag_is, value::NumWithUnit, widgets::widget_node};
|
|
use anyhow::*;
|
|
use derive_more::*;
|
|
use serde::{Deserialize, Serialize};
|
|
use smart_default::SmartDefault;
|
|
use std::collections::HashMap;
|
|
|
|
use super::*;
|
|
|
|
/// Full window-definition containing the fully expanded widget tree.
|
|
/// **Use this** rather than `[RawEwwWindowDefinition]`.
|
|
#[derive(Debug, Clone)]
|
|
pub struct EwwWindowDefinition {
|
|
pub name: WindowName,
|
|
pub geometry: EwwWindowGeometry,
|
|
pub stacking: WindowStacking,
|
|
pub screen_number: Option<i32>,
|
|
pub widget: Box<dyn widget_node::WidgetNode>,
|
|
pub struts: StrutDefinition,
|
|
pub focusable: bool,
|
|
}
|
|
|
|
impl EwwWindowDefinition {
|
|
pub fn generate(defs: &HashMap<String, WidgetDefinition>, window: RawEwwWindowDefinition) -> Result<Self> {
|
|
Ok(EwwWindowDefinition {
|
|
name: window.name,
|
|
geometry: window.geometry,
|
|
stacking: window.stacking,
|
|
screen_number: window.screen_number,
|
|
widget: widget_node::generate_generic_widget_node(defs, &HashMap::new(), window.widget)?,
|
|
struts: window.struts,
|
|
focusable: window.focusable,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Window-definition storing the raw WidgetUse, as received directly from parsing.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct RawEwwWindowDefinition {
|
|
pub name: WindowName,
|
|
pub geometry: EwwWindowGeometry,
|
|
pub stacking: WindowStacking,
|
|
pub screen_number: Option<i32>,
|
|
pub widget: WidgetUse,
|
|
pub struts: StrutDefinition,
|
|
pub focusable: bool,
|
|
}
|
|
|
|
impl RawEwwWindowDefinition {
|
|
pub fn from_xml_element(xml: &XmlElement) -> Result<Self> {
|
|
ensure_xml_tag_is!(xml, "window");
|
|
let stacking: WindowStacking = xml.parse_optional_attr("stacking")?.unwrap_or_default();
|
|
|
|
// TODO maybe rename this to monitor?
|
|
let focusable = xml.parse_optional_attr("focusable")?;
|
|
let screen_number = xml.parse_optional_attr("screen")?;
|
|
|
|
let struts: Option<StrutDefinition> =
|
|
xml.child("reserve").ok().map(StrutDefinition::from_xml_element).transpose().context("Failed to parse <reserve>")?;
|
|
|
|
Ok(RawEwwWindowDefinition {
|
|
name: WindowName(xml.attr("name")?.to_owned()),
|
|
geometry: match xml.child("geometry") {
|
|
Ok(node) => EwwWindowGeometry::from_xml_element(node)?,
|
|
Err(_) => EwwWindowGeometry::default(),
|
|
},
|
|
widget: WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?,
|
|
stacking,
|
|
screen_number,
|
|
focusable: focusable.unwrap_or(false),
|
|
struts: struts.unwrap_or_default(),
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, smart_default::SmartDefault)]
|
|
pub enum Side {
|
|
#[default]
|
|
Top,
|
|
Left,
|
|
Right,
|
|
Bottom,
|
|
}
|
|
impl std::str::FromStr for Side {
|
|
type Err = anyhow::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Side> {
|
|
match s {
|
|
"l" | "left" => Ok(Side::Left),
|
|
"r" | "right" => Ok(Side::Right),
|
|
"t" | "top" => Ok(Side::Top),
|
|
"b" | "bottom" => Ok(Side::Bottom),
|
|
_ => Err(anyhow!("Failed to parse {} as valid side. Must be one of \"left\", \"right\", \"top\", \"bottom\"", s)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
|
|
pub struct StrutDefinition {
|
|
pub side: Side,
|
|
pub dist: NumWithUnit,
|
|
}
|
|
|
|
impl StrutDefinition {
|
|
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
|
Ok(StrutDefinition { side: xml.attr("side")?.parse()?, dist: xml.attr("distance")?.parse()? })
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display, SmartDefault)]
|
|
pub enum WindowStacking {
|
|
#[default]
|
|
Foreground,
|
|
Background,
|
|
}
|
|
|
|
impl std::str::FromStr for WindowStacking {
|
|
type Err = anyhow::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self> {
|
|
let s = s.to_lowercase();
|
|
match s.as_str() {
|
|
"foreground" | "fg" | "f" => Ok(WindowStacking::Foreground),
|
|
"background" | "bg" | "b" => Ok(WindowStacking::Background),
|
|
_ => Err(anyhow!("Couldn't parse '{}' as window stacking, must be either foreground, fg, background or bg", s)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(transparent)]
|
|
#[derive(Clone, Hash, PartialEq, Eq, AsRef, FromStr, Display, Serialize, Deserialize, Default, From, DebugCustom)]
|
|
#[debug(fmt = "WindowName(\".0\")")]
|
|
pub struct WindowName(String);
|
|
|
|
impl std::borrow::Borrow<str> for WindowName {
|
|
fn borrow(&self) -> &str {
|
|
&self.0
|
|
}
|
|
}
|