Correctly implement image sizing (although ugly)

This commit is contained in:
elkowar 2020-10-11 20:30:53 +02:00
parent 7d24de48b5
commit ffd4a2d5a5
2 changed files with 62 additions and 2 deletions

View file

@ -109,7 +109,34 @@ impl EwwState {
Ok(())
}
/// resolves a value if possible, using the current eww_state
/// Expects there to be at max one level of nesting var_refs from local-env.
/// This means that no elements in the local_env may be var-refs into the local_env again, but only into the global state.
pub fn resolve_once<'a>(
&'a self,
local_env: &'a HashMap<VarName, AttrValue>,
value: &'a AttrValue,
) -> Result<&'a PrimitiveValue> {
match value {
AttrValue::Concrete(primitive) => Ok(&primitive),
AttrValue::VarRef(var_name) => match local_env.get(var_name) {
// look up if variables are found in the local env, and resolve as far as possible
Some(AttrValue::Concrete(primitive)) => Ok(primitive),
Some(AttrValue::VarRef(var_name)) => self
.variables_state
.get(var_name)
.ok_or_else(|| anyhow!("Unknown variable '{}' referenced", var_name)),
None => self
.variables_state
.get(var_name)
.ok_or_else(|| anyhow!("Unknown variable '{}' referenced", var_name)),
},
}
}
/// Resolve takes a function that applies a set of fully resolved attribute values to it's gtk widget.
/// Expects there to be at max one level of nesting var_refs from local-env.
/// This means that no elements in the local_env may be var-refs into the local_env again, but only into the global state.
pub fn resolve<F: Fn(HashMap<String, PrimitiveValue>) -> Result<()> + 'static + Clone>(
&mut self,
window_name: &WindowName,

View file

@ -9,6 +9,8 @@ use gtk::ImageExt;
use maplit::hashmap;
use std::path::Path;
use gdk_pixbuf;
// TODO figure out how to
// TODO https://developer.gnome.org/gtk3/stable/GtkFixed.html
@ -32,6 +34,21 @@ pub(super) fn widget_to_gtk_widget(bargs: &mut BuilderArgs) -> Result<Option<gtk
/// attributes that apply to all widgets
pub(super) fn resolve_widget_attrs(bargs: &mut BuilderArgs, gtk_widget: &gtk::Widget) {
let css_provider = gtk::CssProvider::new();
if let Ok(visible) = bargs
.widget
.get_attr("visible")
.and_then(|v| bargs.eww_state.resolve_once(bargs.local_env, v)?.as_bool())
{
connect_first_map(gtk_widget, move |w| {
if visible {
w.show();
} else {
w.hide();
}
})
}
resolve_block!(bargs, gtk_widget, {
prop(class: as_string) { gtk_widget.get_style_context().add_class(&class) },
prop(valign: as_string) { gtk_widget.set_valign(parse_align(&valign)?) },
@ -39,7 +56,7 @@ pub(super) fn resolve_widget_attrs(bargs: &mut BuilderArgs, gtk_widget: &gtk::Wi
prop(width: as_f64 ) { gtk_widget.set_size_request(width as i32, gtk_widget.get_allocated_height()) },
prop(height: as_f64 ) { gtk_widget.set_size_request(gtk_widget.get_allocated_width(), height as i32) },
prop(active: as_bool = true) { gtk_widget.set_sensitive(active) },
prop(visible: as_bool ) {
prop(visible: as_bool = true) {
// TODO how do i call this only after the widget has been mapped? this is actually an issue,....
if visible { gtk_widget.show(); } else { gtk_widget.hide(); }
},
@ -104,7 +121,13 @@ fn build_gtk_button(bargs: &mut BuilderArgs) -> Result<gtk::Button> {
fn build_gtk_image(bargs: &mut BuilderArgs) -> Result<gtk::Image> {
let gtk_widget = gtk::Image::new();
resolve_block!(bargs, gtk_widget, {
prop(path: as_string) { gtk_widget.set_from_file(Path::new(&path)); }
prop(path: as_string) {
gtk_widget.set_from_file(Path::new(&path));
},
prop(path: as_string, width: as_f64, height: as_f64) {
let pixbuf = gdk_pixbuf::Pixbuf::from_file_at_size(std::path::PathBuf::from(path), width as i32, height as i32)?;
gtk_widget.set_from_pixbuf(Some(&pixbuf));
}
});
Ok(gtk_widget)
}
@ -194,3 +217,13 @@ fn parse_align(o: &str) -> Result<gtk::Align> {
_ => bail!("Couldn't parse alignment: '{}'", o),
})
}
fn connect_first_map<W: IsA<gtk::Widget>, F: Fn(&W) + 'static>(widget: &W, func: F) {
// TODO it would be better to actually remove the connect_map after first map, but that would be highly annoying to implement...
let is_first_map = std::rc::Rc::new(std::cell::RefCell::new(true));
widget.connect_map(move |w| {
if is_first_map.replace(false) {
func(&w);
}
});
}