koibumi-sync 0.0.1

An experimental Bitmessage client (sync version)
use ::log::Level;
use conrod_core::{color, Color};

use crate::{config::Config as GuiConfig, ids::Ids};

#[derive(Clone, Debug)]
pub(crate) struct Entry {
    level: Level,
    message: String,
}

impl Entry {
    pub(crate) fn new(level: Level, message: String) -> Self {
        Self { level, message }
    }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Tab {
    entries: Vec<Entry>,
}

fn log_color(level: Level) -> Color {
    match level {
        Level::Error => color::LIGHT_RED,
        Level::Info => color::LIGHT_GREEN,
        _ => color::LIGHT_BLUE,
    }
}

impl Tab {
    pub(crate) fn log(&mut self, level: Level, message: String) {
        self.entries.push(Entry { level, message });
    }

    // Draw the Ui.
    pub(crate) fn set_widgets(
        &mut self,
        ui: &mut conrod_core::UiCell,
        ids: &mut Ids,
        config: &GuiConfig,
    ) {
        let text_size = config.text_size();

        use conrod_core::{widget, Colorable, Positionable, Sizeable, Widget};

        widget::Canvas::new()
            .top_left_of(ids.tabs_body)
            .wh_of(ids.tabs_body)
            .set(ids.log_canvas, ui);

        let (mut items, scrollbar) = widget::List::flow_down(self.entries.len())
            .top_left_with_margins_on(ids.log_canvas, 2.0, 2.0)
            .padded_wh_of(ids.log_canvas, 2.0)
            .item_size(text_size as f64 + 8.0)
            .scrollbar_on_top()
            .set(ids.log, ui);

        while let Some(item) = items.next(ui) {
            let i = item.i;
            let label = &self.entries[i].message;
            let text = widget::Text::new(label)
                .font_size(text_size as u32)
                .padded_w_of(ids.log_canvas, 2.0)
                .h(text_size as f64 + 8.0)
                .color(log_color(self.entries[i].level));
            item.set(text, ui);
        }

        if let Some(s) = scrollbar {
            s.set(ui)
        }
    }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Bar {
    entry: Option<Entry>,
}

impl Bar {
    pub(crate) fn log(&mut self, level: Level, message: String) {
        self.entry = Some(Entry::new(level, message));
    }

    // Draw the Ui.
    pub(crate) fn set_widgets(
        &mut self,
        ui: &mut conrod_core::UiCell,
        ids: &mut Ids,
        config: &GuiConfig,
    ) {
        let text_size = config.text_size();

        use conrod_core::{widget, Colorable, Positionable, Sizeable, Widget};

        if let Some(entry) = &self.entry {
            widget::Text::new(&entry.message)
                .top_left_with_margins_on(ids.footer, 2.0, 2.0)
                .padded_wh_of(ids.footer, 2.0)
                .color(log_color(entry.level))
                .font_size(text_size as u32)
                .set(ids.logbar, ui);
        }
    }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Logger {
    pub(crate) tab: Tab,
    pub(crate) bar: Bar,
}

impl Logger {
    pub(crate) fn log(&mut self, level: Level, message: &str) {
        let message = message.to_string();
        self.tab.log(level, message.clone());
        self.bar.log(level, message);
    }

    pub(crate) fn error(&mut self, message: &str) {
        self.log(Level::Error, message);
    }

    pub(crate) fn info(&mut self, message: &str) {
        self.log(Level::Info, message);
    }
}