use conrod::{Borderable, Colorable, Positionable, Sizeable, UiCell, Widget};
use conrod::color::{self, Color as ConrodColor};
use conrod::position::Align as ConrodAlign;
use conrod::text::{Font, FontCollection, Justify, height as text_height};
use conrod::text::font::Id as FontId;
use conrod::text::line::width as text_width;
use conrod::widget::Canvas;
use conrod::widget::id::Id;
use conrod::widget::primitive::text::Text;
use font_loader::system_fonts::get as font_get;
use handlers::render::conrod::ConrodInstance;
use handlers::render::conrod::deserializer::{Align, Color, Font as ConfigFont};
use handlers::render::conrod::provider::statusbar::StatusbarItem;
use handlers::store::Store;
use handlers::workspaces::ActiveWorkspace;
use wlc::Output;
pub struct WorkspaceIndicator {
ids: [Id; 2],
font_id: FontId,
font: Font,
alignment: ConrodAlign,
margin: u32,
color: ConrodColor,
}
#[derive(Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct WorkspaceIndicatorConfig {
#[serde(default = "::handlers::render::conrod::provider::statusbar::workspace::default_font")]
pub font: ConfigFont,
#[serde(default = "::handlers::render::conrod::provider::statusbar::workspace::default_alignment")]
pub alignment: Align,
#[serde(default = "::handlers::render::conrod::provider::statusbar::workspace::default_color")]
pub color: Color,
#[serde(default = "::handlers::render::conrod::provider::statusbar::workspace::default_margin")]
pub margin: u32,
}
impl Default for WorkspaceIndicatorConfig {
fn default() -> WorkspaceIndicatorConfig {
WorkspaceIndicatorConfig {
font: default_font(),
alignment: default_alignment(),
color: default_color(),
margin: default_margin(),
}
}
}
fn default_font() -> ConfigFont {
ConfigFont {
family: None,
monospace: true,
italic: false,
oblique: false,
bold: false,
}
}
fn default_alignment() -> Align {
Align(ConrodAlign::Start)
}
fn default_color() -> Color {
Color(color::WHITE)
}
fn default_margin() -> u32 {
4
}
impl WorkspaceIndicator {
pub fn new(_output: &Output, ui: &mut ConrodInstance, arguments: WorkspaceIndicatorConfig) -> Self {
let (bytes, index) = font_get(&arguments.font.property()).expect("No font could be loaded");
let font = FontCollection::from_bytes(bytes)
.into_fonts()
.nth(index as usize)
.unwrap();
let font_id = ui.fonts.insert(font.clone());
WorkspaceIndicator {
ids: [ui.widget_id_generator().next(), ui.widget_id_generator().next()],
font_id: font_id,
font: font,
alignment: *arguments.alignment,
color: *arguments.color,
margin: arguments.margin,
}
}
}
impl StatusbarItem for WorkspaceIndicator {
fn positionable(&mut self, output: &Output, height: f64) -> (ConrodAlign, Id, Canvas) {
let text = {
let lock = output.get::<ActiveWorkspace>();
let result = if let Some(active) = lock.as_ref().and_then(|x| x.read().ok()) {
format!("{} {}", active.num(), active.name())
} else {
String::new()
};
result
};
let mut size = 2;
while text_height(1, size, 0.0) <
((height as u32 * output.scale()) - (self.margin * 2 * output.scale())) as f64 {
size += 1;
}
size -= 1;
let text_width = text_width(&text, &self.font, size);
let canvas = Canvas::new()
.h(height * output.scale() as f64)
.length(text_width + (self.margin * 2 * output.scale()) as f64)
.color(color::TRANSPARENT)
.border(0.0);
(self.alignment, self.ids[0], canvas)
}
fn render(&mut self, output: &Output, height: f64, ui: &mut UiCell) {
let text = {
let lock = output.get::<ActiveWorkspace>();
let result = if let Some(active) = lock.as_ref().and_then(|x| x.read().ok()) {
format!("{} {}", active.num(), active.name())
} else {
String::new()
};
result
};
let mut size = 2;
while text_height(1, size, 0.0) <
((height as u32 * output.scale()) - (self.margin * 2 * output.scale())) as f64 {
size += 1;
}
size -= 1;
let text_height = text_height(1, size, 0.0);
let text_width = text_width(&text, &self.font, size);
let builder = Text::new(&text)
.font_id(self.font_id)
.justify(match self.alignment {
ConrodAlign::Start => Justify::Left,
ConrodAlign::Middle => Justify::Center,
ConrodAlign::End => Justify::Right,
})
.font_size(size)
.h(text_height)
.w(text_width)
.color(self.color);
match self.alignment {
ConrodAlign::Start => {
builder.mid_left_with_margin_on(self.ids[0], (self.margin * output.scale()) as f64)
}
ConrodAlign::Middle => builder.middle_of(self.ids[0]),
ConrodAlign::End => {
builder.mid_right_with_margin_on(self.ids[0], (self.margin * output.scale()) as f64)
}
}
.set(self.ids[1], ui);
}
}