use fltk::{draw as fltk_draw, enums::*, prelude::*};
use rutle::render_context::{CaretLean, FontStyle, FontType, RenderContext};
pub struct FltkDrawContext {
has_focus: bool,
is_active: bool,
}
impl FltkDrawContext {
pub fn new(has_focus: bool, is_active: bool) -> Self {
FltkDrawContext {
has_focus,
is_active,
}
}
pub fn from_widget_ptr<T: WidgetExt>(widget: &T) -> Self {
let has_focus = fltk::app::focus().map(|f| f.as_base_widget()).as_ref()
== Some(&widget.as_base_widget());
Self::new(has_focus, widget.active())
}
}
impl FltkDrawContext {
fn inner_set_font(&self, font: FontType, style: FontStyle, size: u8) {
fltk_draw::set_font(
match font {
FontType::Content => match style {
FontStyle::Regular => Font::Helvetica,
FontStyle::Bold => Font::HelveticaBold,
FontStyle::Italic => Font::HelveticaItalic,
FontStyle::BoldItalic => Font::HelveticaBoldItalic,
},
FontType::Code => match style {
FontStyle::Regular => Font::Courier,
FontStyle::Bold => Font::CourierBold,
FontStyle::Italic => Font::CourierItalic,
FontStyle::BoldItalic => Font::CourierBoldItalic,
},
FontType::Heading => match style {
FontStyle::Regular => Font::Helvetica,
FontStyle::Bold => Font::HelveticaBold,
FontStyle::Italic => Font::HelveticaItalic,
FontStyle::BoldItalic => Font::HelveticaBoldItalic,
},
},
size as i32,
);
}
}
impl RenderContext for FltkDrawContext {
fn set_color(&mut self, color: u32) {
let r = ((color >> 24) & 0xFF) as u8;
let g = ((color >> 16) & 0xFF) as u8;
let b = ((color >> 8) & 0xFF) as u8;
fltk_draw::set_draw_color(Color::from_rgb(r, g, b));
}
fn set_font(&mut self, font: FontType, style: FontStyle, size: u8) {
self.inner_set_font(font, style, size);
}
fn draw_text(&mut self, text: &str, x: i32, y: i32) {
fltk_draw::draw_text(text, x, y);
}
fn draw_rect_filled(&mut self, x: i32, y: i32, w: i32, h: i32) {
fltk_draw::draw_rectf(x, y, w, h);
}
fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32) {
fltk_draw::draw_line(x1, y1, x2, y2);
}
fn draw_caret(&mut self, x: i32, y: i32, height: i32, lean: CaretLean) {
let dir = match lean {
CaretLean::None => {
fltk_draw::draw_rectf(x, y, 2, height);
return;
}
CaretLean::Left => -1,
CaretLean::Right => 1,
};
let w = 2; let reach = dir * 4; let rise = 2; let edge = if dir > 0 { x + w } else { x }; let far = edge - dir * w; let top = y;
let bottom = y + height - 1;
let tip_edge = edge + reach;
let tip_far = far + reach;
let pts = [
(tip_far, top - rise), (tip_edge, top - rise), (edge, top), (edge, bottom), (tip_edge, bottom + rise), (tip_far, bottom + rise), (far, bottom), (far, top), ];
fltk_draw::begin_complex_polygon();
for (vx, vy) in pts {
fltk_draw::vertex(vx as f64, vy as f64);
}
fltk_draw::end_complex_polygon();
}
fn text_width(&mut self, text: &str, font: FontType, style: FontStyle, size: u8) -> f64 {
self.set_font(font, style, size);
fltk_draw::width(text)
}
fn text_height(&self, font: FontType, style: FontStyle, size: u8) -> i32 {
self.inner_set_font(font, style, size);
fltk_draw::height()
}
fn text_descent(&self, font: FontType, style: FontStyle, size: u8) -> i32 {
self.inner_set_font(font, style, size);
fltk_draw::descent()
}
fn push_clip(&mut self, x: i32, y: i32, w: i32, h: i32) {
fltk_draw::push_clip(x, y, w, h);
}
fn pop_clip(&mut self) {
fltk_draw::pop_clip();
}
fn color_average(&self, c1: u32, c2: u32, weight: f32) -> u32 {
let r1 = ((c1 >> 24) & 0xFF) as f32;
let g1 = ((c1 >> 16) & 0xFF) as f32;
let b1 = ((c1 >> 8) & 0xFF) as f32;
let r2 = ((c2 >> 24) & 0xFF) as f32;
let g2 = ((c2 >> 16) & 0xFF) as f32;
let b2 = ((c2 >> 8) & 0xFF) as f32;
let r = (r1 * (1.0 - weight) + r2 * weight) as u32;
let g = (g1 * (1.0 - weight) + g2 * weight) as u32;
let b = (b1 * (1.0 - weight) + b2 * weight) as u32;
(r << 24) | (g << 16) | (b << 8) | 0xFF
}
fn color_contrast(&self, _fg: u32, bg: u32) -> u32 {
let r = ((bg >> 24) & 0xFF) as f32;
let g = ((bg >> 16) & 0xFF) as f32;
let b = ((bg >> 8) & 0xFF) as f32;
let brightness = (r * 0.299 + g * 0.587 + b * 0.114) / 255.0;
if brightness > 0.5 {
0x000000FF } else {
0xFFFFFFFF }
}
fn color_inactive(&self, c: u32) -> u32 {
let r = ((c >> 24) & 0xFF) as f32;
let g = ((c >> 16) & 0xFF) as f32;
let b = ((c >> 8) & 0xFF) as f32;
let gray = (r + g + b) / 3.0;
let r = (r * 0.5 + gray * 0.5) as u32;
let g = (g * 0.5 + gray * 0.5) as u32;
let b = (b * 0.5 + gray * 0.5) as u32;
(r << 24) | (g << 16) | (b << 8) | 0xFF
}
fn has_focus(&self) -> bool {
self.has_focus
}
fn is_active(&self) -> bool {
self.is_active
}
}