Correctly implement image sizing (although ugly)
This commit is contained in:
parent
7d24de48b5
commit
ffd4a2d5a5
2 changed files with 62 additions and 2 deletions
|
@ -109,7 +109,34 @@ impl EwwState {
|
||||||
Ok(())
|
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.
|
/// 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>(
|
pub fn resolve<F: Fn(HashMap<String, PrimitiveValue>) -> Result<()> + 'static + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
window_name: &WindowName,
|
window_name: &WindowName,
|
||||||
|
|
|
@ -9,6 +9,8 @@ use gtk::ImageExt;
|
||||||
use maplit::hashmap;
|
use maplit::hashmap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use gdk_pixbuf;
|
||||||
|
|
||||||
// TODO figure out how to
|
// TODO figure out how to
|
||||||
// TODO https://developer.gnome.org/gtk3/stable/GtkFixed.html
|
// 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
|
/// attributes that apply to all widgets
|
||||||
pub(super) fn resolve_widget_attrs(bargs: &mut BuilderArgs, gtk_widget: >k::Widget) {
|
pub(super) fn resolve_widget_attrs(bargs: &mut BuilderArgs, gtk_widget: >k::Widget) {
|
||||||
let css_provider = gtk::CssProvider::new();
|
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, {
|
resolve_block!(bargs, gtk_widget, {
|
||||||
prop(class: as_string) { gtk_widget.get_style_context().add_class(&class) },
|
prop(class: as_string) { gtk_widget.get_style_context().add_class(&class) },
|
||||||
prop(valign: as_string) { gtk_widget.set_valign(parse_align(&valign)?) },
|
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: >k::Wi
|
||||||
prop(width: as_f64 ) { gtk_widget.set_size_request(width as i32, gtk_widget.get_allocated_height()) },
|
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(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(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,....
|
// 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(); }
|
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> {
|
fn build_gtk_image(bargs: &mut BuilderArgs) -> Result<gtk::Image> {
|
||||||
let gtk_widget = gtk::Image::new();
|
let gtk_widget = gtk::Image::new();
|
||||||
resolve_block!(bargs, gtk_widget, {
|
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)
|
Ok(gtk_widget)
|
||||||
}
|
}
|
||||||
|
@ -194,3 +217,13 @@ fn parse_align(o: &str) -> Result<gtk::Align> {
|
||||||
_ => bail!("Couldn't parse alignment: '{}'", o),
|
_ => 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue