use conrod::{Borderable, Colorable, Positionable, Sizeable, Widget};
use conrod::UiCell;
use conrod::color;
use conrod::widget::Canvas;
use conrod::widget::id::Id;
use handlers::geometry::UsableViewGeometry;
use handlers::render::conrod::ConrodRenderer;
use handlers::render::conrod::provider::ConrodProvider;
use handlers::store::Store;
use std::sync::{Arc, RwLock};
use ::utils::coordinates::*;
use wlc::{Callback, Output, View, ViewState, WeakView};
#[derive(Default)]
pub struct IndicatorsHandler {
width: u32,
views: Arc<RwLock<Vec<WeakView>>>,
}
impl IndicatorsHandler {
pub fn new(config: IndicatorConfig) -> IndicatorsHandler {
IndicatorsHandler {
width: config.width,
views: Arc::new(RwLock::new(Vec::new())),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)]
pub struct IndicatorConfig {
#[serde(default = "::handlers::workspaces::modes::bsp::indicators::default_width")]
pub width: u32,
}
impl Default for IndicatorConfig {
fn default() -> IndicatorConfig {
IndicatorConfig { width: default_width() }
}
}
pub fn default_width() -> u32 {
4
}
impl Callback for IndicatorsHandler {
fn output_context_created(&mut self, output: &Output) {
if let Some(lock) = output.get::<ConrodRenderer>() {
let mut ui = lock.write().unwrap();
ui.background.register(Indicator::new(self.width, self.views.clone()));
}
}
fn view_created(&mut self, view: &View) -> bool {
if let Some(lock) = view.get::<UsableViewGeometry>() {
let mut scissor = lock.write().unwrap();
scissor.up += (self.width * view.output().scale()) as usize;
scissor.down += (self.width * view.output().scale()) as usize;
scissor.left += (self.width * view.output().scale()) as usize;
scissor.right += (self.width * view.output().scale()) as usize;
}
self.views.write().unwrap().push(view.weak_reference());
true
}
fn view_destroyed(&mut self, view: &View) {
self.views.write().unwrap().retain(|x| x != view);
if let Some(lock) = view.get::<UsableViewGeometry>() {
let mut scissor = lock.write().unwrap();
scissor.up -= (self.width * view.output().scale()) as usize;
scissor.down -= (self.width * view.output().scale()) as usize;
scissor.left -= (self.width * view.output().scale()) as usize;
scissor.right -= (self.width * view.output().scale()) as usize;
}
}
}
pub struct Indicator {
ids: Vec<[Id; 4]>,
width: u32,
views: Arc<RwLock<Vec<WeakView>>>,
}
impl Indicator {
fn new(width: u32, views: Arc<RwLock<Vec<WeakView>>>) -> Indicator {
Indicator {
ids: Vec::new(),
width: width,
views: views,
}
}
}
impl ConrodProvider for Indicator {
fn render(&mut self, output: &Output, ui: &mut UiCell) {
let views = self.views.read().unwrap();
while views.len() > self.ids.len() {
self.ids.push([ui.widget_id_generator().next(),
ui.widget_id_generator().next(),
ui.widget_id_generator().next(),
ui.widget_id_generator().next()]);
}
let dim = ui.window_dim();
for (ids, view) in self.ids.iter().zip(views.iter()) {
view.run(|view| {
let indicator_color = if view.state().contains(ViewState::Activated) {
color::LIGHT_BLUE
} else {
color::DARK_CHARCOAL
};
if view.output() != output {
return;
}
if view.visibility() != output.visibility() {
return;
}
let geo = view.geometry();
Canvas::new()
.x_y(x_wlc_to_conrod((geo.origin.x - self.width as i32) * output.scale() as i32,
self.width * output.scale(),
dim[0] as u32),
y_wlc_to_conrod(geo.origin.y * output.scale() as i32,
geo.size.h * output.scale(),
dim[1] as u32))
.h((geo.size.h * output.scale()) as f64)
.w((self.width * output.scale()) as f64)
.color(indicator_color)
.border(0.0)
.set(ids[0], ui);
Canvas::new()
.x_y(x_wlc_to_conrod((geo.origin.x + geo.size.w as i32) * output.scale() as i32,
self.width * output.scale(),
dim[0] as u32),
y_wlc_to_conrod(geo.origin.y * output.scale() as i32,
geo.size.h * output.scale(),
dim[1] as u32))
.h((geo.size.h * output.scale()) as f64)
.w((self.width * output.scale()) as f64)
.color(indicator_color)
.border(0.0)
.set(ids[1], ui);
Canvas::new()
.x_y(x_wlc_to_conrod((geo.origin.x - self.width as i32) * output.scale() as i32,
(geo.size.w + self.width * 2) * output.scale(),
dim[0] as u32),
y_wlc_to_conrod((geo.origin.y - self.width as i32) * output.scale() as i32,
self.width * output.scale(),
dim[1] as u32))
.h((self.width * output.scale()) as f64)
.w(((geo.size.w + self.width * 2) * output.scale()) as f64)
.color(indicator_color)
.border(0.0)
.set(ids[2], ui);
Canvas::new()
.x_y(x_wlc_to_conrod((geo.origin.x - self.width as i32) * output.scale() as i32,
(geo.size.w + self.width * 2) * output.scale(),
dim[0] as u32),
y_wlc_to_conrod((geo.origin.y + geo.size.h as i32) * output.scale() as i32,
self.width * output.scale(),
dim[1] as u32))
.h((self.width * output.scale()) as f64)
.w(((geo.size.w + self.width * 2) * output.scale()) as f64)
.color(indicator_color)
.border(0.0)
.set(ids[3], ui);
});
}
}
}