Add centerbox widget

This commit is contained in:
elkowar 2021-08-12 16:19:00 +02:00
parent dcf27a0cbf
commit 9ee852c0fd
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
5 changed files with 59 additions and 18 deletions

View file

@ -1,4 +1,7 @@
use crate::{EwwPaths, config, daemon_response::DaemonResponseSender, display_backend, error_handling_ctx, eww_state, script_var_handler::*}; use crate::{
config, daemon_response::DaemonResponseSender, display_backend, error_handling_ctx, eww_state, script_var_handler::*,
EwwPaths,
};
use anyhow::*; use anyhow::*;
use debug_stub_derive::*; use debug_stub_derive::*;
use eww_shared_util::VarName; use eww_shared_util::VarName;

View file

@ -35,10 +35,8 @@ pub fn format_error(err: &anyhow::Error) -> String {
for err in err.chain() { for err in err.chain() {
format!("chain: {}", err); format!("chain: {}", err);
} }
match err.downcast_ref::<AstError>() { let diag = anyhow_err_to_diagnostic(err);
Some(err) => stringify_diagnostic(err.to_diagnostic()).unwrap_or_else(|_| format!("{:?}", err)), stringify_diagnostic(diag).unwrap_or_else(|_| format!("{}", err))
None => format!("{:?}", err),
}
} }
pub fn anyhow_err_to_diagnostic(err: &anyhow::Error) -> Diagnostic<usize> { pub fn anyhow_err_to_diagnostic(err: &anyhow::Error) -> Diagnostic<usize> {

View file

@ -70,6 +70,7 @@ fn build_builtin_gtk_widget(
if let Some(gtk_widget) = gtk_widget.dynamic_cast_ref::<gtk::Container>() { if let Some(gtk_widget) = gtk_widget.dynamic_cast_ref::<gtk::Container>() {
resolve_container_attrs(&mut bargs, gtk_widget); resolve_container_attrs(&mut bargs, gtk_widget);
if gtk_widget.get_children().is_empty() {
for child in &widget.children { for child in &widget.children {
let child_widget = child.render(bargs.eww_state, window_name, widget_definitions).with_context(|| { let child_widget = child.render(bargs.eww_state, window_name, widget_definitions).with_context(|| {
format!( format!(
@ -83,6 +84,7 @@ fn build_builtin_gtk_widget(
child_widget.show(); child_widget.show();
} }
} }
}
if let Some(w) = gtk_widget.dynamic_cast_ref() { if let Some(w) = gtk_widget.dynamic_cast_ref() {
resolve_range_attrs(&mut bargs, w) resolve_range_attrs(&mut bargs, w)

View file

@ -1,14 +1,18 @@
#![allow(clippy::option_map_unit_fn)] #![allow(clippy::option_map_unit_fn)]
use super::{run_command, BuilderArgs}; use super::{run_command, BuilderArgs};
use crate::{enum_parse, error_handling_ctx, eww_state, resolve_block, util::list_difference, widgets::widget_node}; use crate::{
enum_parse, error::DiagError, error_handling_ctx, eww_state, resolve_block, util::list_difference, widgets::widget_node,
};
use anyhow::*; use anyhow::*;
use gdk::WindowExt; use gdk::WindowExt;
use glib; use glib;
use gtk::{self, prelude::*, ImageExt}; use gtk::{self, prelude::*, ImageExt};
use itertools::Itertools;
use std::{cell::RefCell, collections::HashMap, rc::Rc, time::Duration}; use std::{cell::RefCell, collections::HashMap, rc::Rc, time::Duration};
use yuck::{ use yuck::{
config::validate::ValidationError, config::validate::ValidationError,
error::{AstError, AstResult, AstResultExt}, error::{AstError, AstResult, AstResultExt},
gen_diagnostic,
parser::from_ast::FromAst, parser::from_ast::FromAst,
}; };
@ -20,6 +24,7 @@ use yuck::{
pub(super) fn widget_to_gtk_widget(bargs: &mut BuilderArgs) -> Result<gtk::Widget> { pub(super) fn widget_to_gtk_widget(bargs: &mut BuilderArgs) -> Result<gtk::Widget> {
let gtk_widget = match bargs.widget.name.as_str() { let gtk_widget = match bargs.widget.name.as_str() {
"box" => build_gtk_box(bargs)?.upcast(), "box" => build_gtk_box(bargs)?.upcast(),
"centerbox" => build_center_box(bargs)?.upcast(),
"scale" => build_gtk_scale(bargs)?.upcast(), "scale" => build_gtk_scale(bargs)?.upcast(),
"progress" => build_gtk_progress(bargs)?.upcast(), "progress" => build_gtk_progress(bargs)?.upcast(),
"image" => build_gtk_image(bargs)?.upcast(), "image" => build_gtk_image(bargs)?.upcast(),
@ -494,6 +499,39 @@ fn build_gtk_box(bargs: &mut BuilderArgs) -> Result<gtk::Box> {
Ok(gtk_widget) Ok(gtk_widget)
} }
/// @widget centerbox extends container
/// @desc a box that must contain exactly three children, which will be layed out at the start, center and end of the container.
fn build_center_box(bargs: &mut BuilderArgs) -> Result<gtk::Box> {
let gtk_widget = gtk::Box::new(gtk::Orientation::Horizontal, 0);
resolve_block!(bargs, gtk_widget, {
// @prop orientation - orientation of the centerbox. possible values: $orientation
prop(orientation: as_string) { gtk_widget.set_orientation(parse_orientation(&orientation)?) },
});
if bargs.widget.children.len() < 3 {
Err(DiagError::new(gen_diagnostic!("centerbox must contain exactly 3 elements", bargs.widget.span)))?
} else if bargs.widget.children.len() > 3 {
let (_, additional_children) = bargs.widget.children.split_at(3);
// we know that there is more than three children, so unwrapping on first and left here is fine.
let first_span = additional_children.first().unwrap().span();
let last_span = additional_children.last().unwrap().span();
Err(DiagError::new(gen_diagnostic!("centerbox must contain exactly 3 elements, but got more", first_span.to(last_span))))?
}
let mut children =
bargs.widget.children.iter().map(|child| child.render(bargs.eww_state, bargs.window_name, bargs.widget_definitions));
// we know that we have exactly three children here, so we can unwrap here.
let (first, center, end) = children.next_tuple().unwrap();
let (first, center, end) = (first?, center?, end?);
gtk_widget.pack_start(&first, true, true, 0);
gtk_widget.set_center_widget(Some(&center));
gtk_widget.pack_end(&end, true, true, 0);
first.show();
center.show();
end.show();
Ok(gtk_widget)
}
/// @widget label /// @widget label
/// @desc A text widget giving you more control over how the text is displayed /// @desc A text widget giving you more control over how the text is displayed
fn build_gtk_label(bargs: &mut BuilderArgs) -> Result<gtk::Label> { fn build_gtk_label(bargs: &mut BuilderArgs) -> Result<gtk::Label> {

View file

@ -9,7 +9,7 @@ use yuck::{
error::{AstError, AstResult}, error::{AstError, AstResult},
}; };
pub trait WidgetNode: std::fmt::Debug + dyn_clone::DynClone + Send + Sync { pub trait WidgetNode: Spanned + std::fmt::Debug + dyn_clone::DynClone + Send + Sync {
fn get_name(&self) -> &str; fn get_name(&self) -> &str;
/// Generate a [gtk::Widget] from a [element::WidgetUse]. /// Generate a [gtk::Widget] from a [element::WidgetUse].