Sort entries by score, ui widgets
This commit is contained in:
parent
35f01cafe3
commit
8e38a59432
6 changed files with 284 additions and 175 deletions
28
src/roftl.rs
28
src/roftl.rs
|
@ -1,6 +1,7 @@
|
||||||
use std::{collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}};
|
use std::{any::type_name, collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}};
|
||||||
|
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator};
|
use log::debug;
|
||||||
|
use rayon::{iter::{IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}, slice::ParallelSliceMut};
|
||||||
|
|
||||||
use super::matcher::PrefixMatcher;
|
use super::matcher::PrefixMatcher;
|
||||||
|
|
||||||
|
@ -75,14 +76,27 @@ impl Roftl {
|
||||||
let count = Arc::new(AtomicUsize::new(0));
|
let count = Arc::new(AtomicUsize::new(0));
|
||||||
self.narrow_map.lock().unwrap().clear();
|
self.narrow_map.lock().unwrap().clear();
|
||||||
|
|
||||||
self.entries
|
let mut scored_entries: Vec<(f64, usize, &Entry, Vec<usize>)> = self.entries
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(_idx, e)| self.matcher.try_match(&e.name, input).is_some())
|
.filter_map(|(idx, entry)| {
|
||||||
.map(move |(idx, e)| {
|
let match_result = self.matcher.try_match(&entry.name, input);
|
||||||
self.narrow_map.lock().unwrap().insert(count.fetch_add(1, Ordering::Relaxed), idx);
|
return match_result.map(|(score, indices)| (score, idx, entry, indices) )
|
||||||
e
|
|
||||||
})
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
scored_entries
|
||||||
|
.par_sort_by(|e1, e2| e1.0.partial_cmp(&e2.0).unwrap());
|
||||||
|
|
||||||
|
scored_entries
|
||||||
|
.par_iter()
|
||||||
|
.for_each(|se| {
|
||||||
|
self.narrow_map.lock().unwrap().insert(count.fetch_add(1, Ordering::Relaxed), se.1);
|
||||||
|
});
|
||||||
|
|
||||||
|
scored_entries
|
||||||
|
.par_iter()
|
||||||
|
.map(|se| se.2)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ impl TestSource {
|
||||||
pub fn new(s: &str) -> Box<TestSource> {
|
pub fn new(s: &str) -> Box<TestSource> {
|
||||||
let mut ts = Box::new(TestSource { entries: vec![] });
|
let mut ts = Box::new(TestSource { entries: vec![] });
|
||||||
|
|
||||||
(1..2).for_each(|i| {
|
(1..100).for_each(|i| {
|
||||||
ts.add_entry(
|
ts.add_entry(
|
||||||
format! {"Test {} {}", i, s},
|
format! {"Test {} {}", i, s},
|
||||||
format! {"Test {} description", i},
|
format! {"Test {} description", i},
|
||||||
|
|
167
src/ui.rs
167
src/ui.rs
|
@ -1,167 +0,0 @@
|
||||||
use std::borrow::BorrowMut;
|
|
||||||
use std::ffi::c_void;
|
|
||||||
|
|
||||||
use log::debug;
|
|
||||||
use winit::{platform::unix::WindowExtUnix, window::Window};
|
|
||||||
|
|
||||||
use super::roftl::Entry;
|
|
||||||
|
|
||||||
fn get_visual_type<T>(mut connection: T, window_id: u32) -> xcb::Visualtype
|
|
||||||
where T: BorrowMut<*mut c_void>
|
|
||||||
{
|
|
||||||
let xcb_conn = unsafe { xcb::Connection::from_raw_conn(*connection.borrow_mut() as *mut xcb::ffi::xcb_connection_t) };
|
|
||||||
|
|
||||||
let window_visualid = xcb::get_window_attributes(&xcb_conn, window_id)
|
|
||||||
.get_reply()
|
|
||||||
.expect("Could not fetch attributes for window")
|
|
||||||
.visual();
|
|
||||||
|
|
||||||
debug!{"Found visualid {} for window", window_visualid}
|
|
||||||
|
|
||||||
debug!{"Trying to map visualid to visualtype {}", window_visualid}
|
|
||||||
let visualtype = xcb_conn.get_setup().roots()
|
|
||||||
.flat_map(|screen| screen.allowed_depths())
|
|
||||||
.flat_map(|depth| depth.visuals())
|
|
||||||
.find(|visualtype| {visualtype.visual_id() == window_visualid})
|
|
||||||
.expect("Could not match visualid to visualtype");
|
|
||||||
|
|
||||||
// xcb::Connection calls disconnect on the underlying xcb_connection_t
|
|
||||||
// when dropped. We cannot let this happen since the xcb_connection_t
|
|
||||||
// is actually owned by the winit::Window
|
|
||||||
// We try to signify this with `where T: BorrowMut<*mut c_void>` but
|
|
||||||
// this is unfortunately not enforced down to the raw pointer
|
|
||||||
std::mem::forget(xcb_conn);
|
|
||||||
|
|
||||||
visualtype
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_context(window: &Window) -> cairo::Context
|
|
||||||
{
|
|
||||||
let winit_xcb_conn = window
|
|
||||||
.xcb_connection()
|
|
||||||
.expect("Could not get connection from window");
|
|
||||||
|
|
||||||
let xlib_window_id = window
|
|
||||||
.xlib_window()
|
|
||||||
.expect("Could not get xlib window");
|
|
||||||
|
|
||||||
let visual_type = unsafe {
|
|
||||||
let mut visual_type = get_visual_type(winit_xcb_conn, xlib_window_id as u32).base;
|
|
||||||
cairo::XCBVisualType::from_raw_none(
|
|
||||||
&mut visual_type as *mut xcb::ffi::xcb_visualtype_t as *mut cairo::ffi::xcb_visualtype_t
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let connection = unsafe {
|
|
||||||
cairo::XCBConnection::from_raw_none(winit_xcb_conn as *mut cairo_sys::xcb_connection_t)
|
|
||||||
};
|
|
||||||
|
|
||||||
let drawable = cairo::XCBDrawable(window.xlib_window().unwrap() as u32);
|
|
||||||
|
|
||||||
let surface = cairo::XCBSurface::create(
|
|
||||||
&connection,
|
|
||||||
&drawable,
|
|
||||||
&visual_type,
|
|
||||||
window.inner_size().width as i32,
|
|
||||||
window.inner_size().height as i32,
|
|
||||||
).expect("Could not create drawing surface");
|
|
||||||
|
|
||||||
cairo::Context::new(&surface).expect("Could not create drawing context")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_rectangle(cr: &cairo::Context, x: f64, y: f64, width: f64, height: f64, aspect: f64)
|
|
||||||
{
|
|
||||||
let corner_radius = height / 10.0; /* and corner curvature radius */
|
|
||||||
let radius = corner_radius / aspect;
|
|
||||||
let degrees = std::f64::consts::PI / 180.0;
|
|
||||||
|
|
||||||
cr.new_sub_path ();
|
|
||||||
cr.arc (x + width - radius, y + radius, radius, -90.0 * degrees, 0.0 * degrees);
|
|
||||||
cr.arc (x + width - radius, y + height - radius, radius, 0.0 * degrees, 90.0 * degrees);
|
|
||||||
cr.arc (x + radius, y + height - radius, radius, 90.0 * degrees, 180.0 * degrees);
|
|
||||||
cr.arc (x + radius, y + radius, radius, 180.0 * degrees, 270.0 * degrees);
|
|
||||||
cr.close_path ();
|
|
||||||
|
|
||||||
cr.set_source_rgb (0.5, 0.5, 1.0);
|
|
||||||
cr.fill_preserve ().unwrap();
|
|
||||||
|
|
||||||
cr.set_source_rgb(1.0, 1.0, 1.0);
|
|
||||||
cr.set_line_width (cr.device_to_user_distance(1.0, 1.0).unwrap().0);
|
|
||||||
cr.stroke ().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_text(cr: &cairo::Context, input: &str)
|
|
||||||
{
|
|
||||||
cr.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Normal);
|
|
||||||
cr.set_font_size (0.25);
|
|
||||||
cr.set_source_rgb (0.0, 0.0, 1.0);
|
|
||||||
cr.move_to (0.05, 0.23);
|
|
||||||
|
|
||||||
if input.len() > 3 {
|
|
||||||
cr.show_text(&input[..3]).unwrap();
|
|
||||||
cr.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Bold);
|
|
||||||
cr.show_text(&input[3..]).unwrap();
|
|
||||||
} else {
|
|
||||||
cr.show_text(input).unwrap();
|
|
||||||
cr.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Normal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_result(cr: &cairo::Context, input: &str, x: f64, y: f64)
|
|
||||||
{
|
|
||||||
cr.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Normal);
|
|
||||||
cr.set_font_size (0.25);
|
|
||||||
cr.set_source_rgb (0.0, 0.0, 1.0);
|
|
||||||
cr.move_to (x, y);
|
|
||||||
cr.show_text(input).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_on_window(window: &Window, input: &str, result: Vec<&Entry>)
|
|
||||||
{
|
|
||||||
let cr = make_context(&window);
|
|
||||||
|
|
||||||
cr.save().unwrap();
|
|
||||||
cr.set_source_rgba(0.0, 0.0, 0.0, 0.5);
|
|
||||||
cr.set_operator(cairo::Operator::Source);
|
|
||||||
cr.paint().unwrap();
|
|
||||||
cr.restore().unwrap();
|
|
||||||
|
|
||||||
cr.translate(300.0, 300.0);
|
|
||||||
cr.scale(100.0, 100.0);
|
|
||||||
|
|
||||||
|
|
||||||
draw_rectangle(&cr, 0.0, 0.0, 4.0, 0.3, 2.0);
|
|
||||||
draw_text(&cr, input);
|
|
||||||
|
|
||||||
result.iter().enumerate()
|
|
||||||
.for_each(|(i, e)| {
|
|
||||||
draw_rectangle(&cr, 0.0, 0.3*((1+i) as f64), 4.0, 0.3, 2.0);
|
|
||||||
draw_result(&cr, &e.name, 0.05, 0.3*((i+1) as f64)+0.23);
|
|
||||||
});
|
|
||||||
|
|
||||||
// cr.set_line_width(0.5);
|
|
||||||
// cr.set_source_rgb(255.0, 255.0, 255.0);
|
|
||||||
// cr.rectangle(20.0, 20.0, 20.0, 40.0);
|
|
||||||
// cr.stroke().unwrap();
|
|
||||||
|
|
||||||
// cr.set_source_rgb(0.0, 0.0, 0.0);
|
|
||||||
// cr.move_to(0.0, 0.0);
|
|
||||||
// cr.line_to(1.0, 1.0);
|
|
||||||
// cr.move_to(1.0, 0.0);
|
|
||||||
// cr.line_to(0.0, 1.0);
|
|
||||||
// cr.set_line_width(0.2);
|
|
||||||
// cr.stroke().unwrap();
|
|
||||||
|
|
||||||
// cr.rectangle(0.0, 0.0, 0.5, 0.5);
|
|
||||||
// cr.set_source_rgba(1.0, 0.0, 0.0, 0.80);
|
|
||||||
// cr.fill().unwrap();
|
|
||||||
|
|
||||||
// cr.rectangle(0.0, 0.5, 0.5, 0.5);
|
|
||||||
// cr.set_source_rgba(0.0, 1.0, 0.0, 0.60);
|
|
||||||
// cr.fill().unwrap();
|
|
||||||
|
|
||||||
// cr.rectangle(0.5, 0.0, 0.5, 0.5);
|
|
||||||
// cr.set_source_rgba(0.0, 0.0, 1.0, 0.40);
|
|
||||||
// cr.fill().unwrap();
|
|
||||||
}
|
|
||||||
|
|
4
src/ui/mod.rs
Normal file
4
src/ui/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
mod ui;
|
||||||
|
pub use ui::draw_on_window;
|
||||||
|
|
||||||
|
mod painter;
|
167
src/ui/painter.rs
Normal file
167
src/ui/painter.rs
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
type Color = (f64, f64, f64, f64);
|
||||||
|
|
||||||
|
struct Theme {
|
||||||
|
background: Color,
|
||||||
|
|
||||||
|
frame: Color,
|
||||||
|
frame_width: f64,
|
||||||
|
|
||||||
|
input_bg: Color,
|
||||||
|
input_font_color: Color,
|
||||||
|
input_font_size: f64,
|
||||||
|
|
||||||
|
result_bg: Color,
|
||||||
|
result_bg_selected: Color,
|
||||||
|
result_font_color: Color,
|
||||||
|
result_font_selected: Color,
|
||||||
|
result_font_size: f64,
|
||||||
|
|
||||||
|
divider: Color,
|
||||||
|
divider_width: f64
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Theme {
|
||||||
|
fn default() -> Self {
|
||||||
|
let bg_color = (0.5, 0.5, 1.0, 1.0);
|
||||||
|
Theme {
|
||||||
|
background: bg_color,
|
||||||
|
|
||||||
|
frame: (1.0, 0.0, 0.0, 1.0),
|
||||||
|
frame_width: 5.0,
|
||||||
|
|
||||||
|
input_bg: (0.5, 0.5, 1.0, 1.0),
|
||||||
|
input_font_color: (0.0, 0.0, 1.0, 1.0),
|
||||||
|
input_font_size: 20.0,
|
||||||
|
|
||||||
|
result_bg: (0.5, 0.5, 1.0, 1.0),
|
||||||
|
result_bg_selected: (0.5, 0.5, 0.5, 1.0),
|
||||||
|
result_font_color: (0.0, 0.0, 1.0, 1.0),
|
||||||
|
result_font_selected: (0.5, 0.5, 0.5, 1.0),
|
||||||
|
result_font_size: 20.0,
|
||||||
|
|
||||||
|
divider: (0.0, 0.0, 0.0, 1.0),
|
||||||
|
divider_width: 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Painter<'a> {
|
||||||
|
context: &'a cairo::Context,
|
||||||
|
theme: Theme,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Painter<'a> {
|
||||||
|
pub fn new(context: &'a cairo::Context) -> Self {
|
||||||
|
Painter{context, theme: Theme::default()}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn background(&self)
|
||||||
|
{
|
||||||
|
let ctx = self.context;
|
||||||
|
|
||||||
|
// reset clip so that we can draw the entire background
|
||||||
|
ctx.reset_clip();
|
||||||
|
|
||||||
|
// fill the background
|
||||||
|
let (r,g,b,a) = self.theme.background;
|
||||||
|
ctx.set_source_rgba(r, g, b, a);
|
||||||
|
ctx.set_operator(cairo::Operator::Source);
|
||||||
|
ctx.paint().unwrap();
|
||||||
|
|
||||||
|
// draw the border
|
||||||
|
let (x1,y1,x2,y2) = ctx.clip_extents().unwrap();
|
||||||
|
let (r,g,b,a) = self.theme.frame;
|
||||||
|
ctx.rectangle(x1, y1, x2-x1, y2-y1);
|
||||||
|
ctx.set_source_rgba(r, g, b, a);
|
||||||
|
let frame_width = self.device_to_user(self.theme.frame_width);
|
||||||
|
ctx.set_line_width(frame_width);
|
||||||
|
ctx.stroke().unwrap();
|
||||||
|
|
||||||
|
ctx.rectangle(x1+(frame_width/2.0), y1+(frame_width/2.0), x2-x1-frame_width, y2-y1-frame_width);
|
||||||
|
ctx.clip();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_box<T>(&self, x: T, y: T, input: &'a str)
|
||||||
|
where T: Into<f64>
|
||||||
|
{
|
||||||
|
let ctx = self.context;
|
||||||
|
let (x, y): (f64, f64) = (x.into(), y.into());
|
||||||
|
|
||||||
|
// draw background box
|
||||||
|
ctx.rectangle(x, y, self.clip_width(), 1.0);
|
||||||
|
let (r,g,b,a) = self.theme.input_bg;
|
||||||
|
ctx.set_source_rgba(r,g,b,a);
|
||||||
|
ctx.fill().unwrap();
|
||||||
|
|
||||||
|
// draw text
|
||||||
|
ctx.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Normal);
|
||||||
|
let font_size = self.device_to_user(self.theme.input_font_size);
|
||||||
|
ctx.set_font_size(font_size);
|
||||||
|
let (r,g,b,a) = self.theme.input_font_color;
|
||||||
|
ctx.set_source_rgba(r,g,b,a);
|
||||||
|
ctx.move_to(x + 0.2, y + 0.8);
|
||||||
|
ctx.show_text(input).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn result_box<T>(&self, x: T, y: T, result: &'a str, selected: bool)
|
||||||
|
where T: Into<f64>
|
||||||
|
{
|
||||||
|
let ctx = self.context;
|
||||||
|
let (x, y): (f64, f64) = (x.into(), y.into());
|
||||||
|
|
||||||
|
// draw background box
|
||||||
|
ctx.rectangle(x.into(), y.into(), self.clip_width(), 1.0);
|
||||||
|
let (r,g,b,a) = if selected { self.theme.result_bg_selected }
|
||||||
|
else { self.theme.result_bg };
|
||||||
|
ctx.set_source_rgba(r,g,b,a);
|
||||||
|
ctx.fill().unwrap();
|
||||||
|
|
||||||
|
// draw text
|
||||||
|
ctx.select_font_face ("serif", cairo::FontSlant::Normal, cairo::FontWeight::Normal);
|
||||||
|
let font_size = self.device_to_user(self.theme.result_font_size);
|
||||||
|
ctx.set_font_size(font_size);
|
||||||
|
let (r,g,b,a) = if selected { self.theme.result_font_selected }
|
||||||
|
else { self.theme.result_font_color };
|
||||||
|
ctx.set_source_rgba(r,g,b,a);
|
||||||
|
ctx.move_to (x+0.2, y+0.8);
|
||||||
|
ctx.show_text(result).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn divider<T>(&self, x: T, y: T)
|
||||||
|
where T: Into<f64>
|
||||||
|
{
|
||||||
|
let ctx = self.context;
|
||||||
|
let (x, y): (f64, f64) = (x.into(), y.into());
|
||||||
|
|
||||||
|
ctx.move_to(x, y);
|
||||||
|
|
||||||
|
let dash_width = self.device_to_user(self.theme.divider_width);
|
||||||
|
ctx.set_line_width(dash_width);
|
||||||
|
ctx.line_to(self.clip_width(), y);
|
||||||
|
ctx.set_dash(&[self.device_to_user(3.0)], 0.0);
|
||||||
|
let (r,g,b,a) = self.theme.divider;
|
||||||
|
ctx.set_source_rgba(r,g,b,a);
|
||||||
|
ctx.stroke().unwrap();
|
||||||
|
|
||||||
|
ctx.rectangle(x, y+dash_width, self.clip_width(), self.clip_height()-dash_width);
|
||||||
|
ctx.clip();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn device_to_user(&self, point: f64) -> f64 {
|
||||||
|
self.context.device_to_user_distance(point, point).unwrap().0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn user_to_device(&self, point: f64) -> f64 {
|
||||||
|
self.context.user_to_device_distance(point, point).unwrap().0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clip_width(&self) -> f64 {
|
||||||
|
let (x1,_y1,x2,_y2) = self.context.clip_extents().unwrap();
|
||||||
|
x2 - x1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clip_height(&self) -> f64 {
|
||||||
|
let (_x1,y1,_x2,y2) = self.context.clip_extents().unwrap();
|
||||||
|
y2 - y1
|
||||||
|
}
|
||||||
|
}
|
91
src/ui/ui.rs
Normal file
91
src/ui/ui.rs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
use std::borrow::BorrowMut;
|
||||||
|
use std::ffi::c_void;
|
||||||
|
|
||||||
|
use log::debug;
|
||||||
|
use winit::{platform::unix::WindowExtUnix, window::Window};
|
||||||
|
|
||||||
|
use crate::roftl::Entry;
|
||||||
|
|
||||||
|
use super::painter;
|
||||||
|
|
||||||
|
fn get_visual_type<T>(mut connection: T, window_id: u32) -> xcb::Visualtype
|
||||||
|
where T: BorrowMut<*mut c_void>
|
||||||
|
{
|
||||||
|
let xcb_conn = unsafe { xcb::Connection::from_raw_conn(*connection.borrow_mut() as *mut xcb::ffi::xcb_connection_t) };
|
||||||
|
|
||||||
|
let window_visualid = xcb::get_window_attributes(&xcb_conn, window_id)
|
||||||
|
.get_reply()
|
||||||
|
.expect("Could not fetch attributes for window")
|
||||||
|
.visual();
|
||||||
|
|
||||||
|
debug!{"Found visualid {} for window", window_visualid}
|
||||||
|
|
||||||
|
debug!{"Trying to map visualid to visualtype {}", window_visualid}
|
||||||
|
let visualtype = xcb_conn.get_setup().roots()
|
||||||
|
.flat_map(|screen| screen.allowed_depths())
|
||||||
|
.flat_map(|depth| depth.visuals())
|
||||||
|
.find(|visualtype| {visualtype.visual_id() == window_visualid})
|
||||||
|
.expect("Could not match visualid to visualtype");
|
||||||
|
|
||||||
|
// xcb::Connection calls disconnect on the underlying xcb_connection_t
|
||||||
|
// when dropped. We cannot let this happen since the xcb_connection_t
|
||||||
|
// is actually owned by the winit::Window
|
||||||
|
// We try to signify this with `where T: BorrowMut<*mut c_void>` but
|
||||||
|
// this is unfortunately not enforced down to the raw pointer
|
||||||
|
std::mem::forget(xcb_conn);
|
||||||
|
|
||||||
|
visualtype
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_context(window: &Window) -> cairo::Context
|
||||||
|
{
|
||||||
|
let winit_xcb_conn = window
|
||||||
|
.xcb_connection()
|
||||||
|
.expect("Could not get connection from window");
|
||||||
|
|
||||||
|
let xlib_window_id = window
|
||||||
|
.xlib_window()
|
||||||
|
.expect("Could not get xlib window");
|
||||||
|
|
||||||
|
let visual_type = unsafe {
|
||||||
|
let mut visual_type = get_visual_type(winit_xcb_conn, xlib_window_id as u32).base;
|
||||||
|
cairo::XCBVisualType::from_raw_none(
|
||||||
|
&mut visual_type as *mut xcb::ffi::xcb_visualtype_t as *mut cairo::ffi::xcb_visualtype_t
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let connection = unsafe {
|
||||||
|
cairo::XCBConnection::from_raw_none(winit_xcb_conn as *mut cairo_sys::xcb_connection_t)
|
||||||
|
};
|
||||||
|
|
||||||
|
let drawable = cairo::XCBDrawable(window.xlib_window().unwrap() as u32);
|
||||||
|
|
||||||
|
let surface = cairo::XCBSurface::create(
|
||||||
|
&connection,
|
||||||
|
&drawable,
|
||||||
|
&visual_type,
|
||||||
|
window.inner_size().width as i32,
|
||||||
|
window.inner_size().height as i32,
|
||||||
|
).expect("Could not create drawing surface");
|
||||||
|
|
||||||
|
cairo::Context::new(&surface).expect("Could not create drawing context")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_on_window(window: &Window, input: &str, result: Vec<&Entry>)
|
||||||
|
{
|
||||||
|
let context = make_context(&window);
|
||||||
|
|
||||||
|
context.scale(30.0, 30.0);
|
||||||
|
|
||||||
|
let painter = painter::Painter::new(&context);
|
||||||
|
|
||||||
|
painter.background();
|
||||||
|
painter.input_box(0, 0, input);
|
||||||
|
painter.divider(0, 1);
|
||||||
|
|
||||||
|
result.iter().enumerate()
|
||||||
|
.for_each(|(i, e)| {
|
||||||
|
painter.result_box(0, 1+(i as u32), &e.name, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue