Files
squeekboard/src/drawing.rs
Dorota Czaplejewicz dd21bfed8d positioning: Calculate sizes instead of storing, move position out of widgets
Sizes of widgets can be derived, so storing them was only for C compatibility. Similar with storing position inside of widgets.

Some layout margin and scaling changes could be introduced, meaning a possibility of visual differences.
2019-12-07 21:20:21 +00:00

121 lines
3.3 KiB
Rust

/*! Drawing the UI */
use cairo;
use std::cell::RefCell;
use ::keyboard;
use ::layout::{ Button, Layout };
use ::layout::c::{ EekGtkKeyboard, Point };
use glib::translate::FromGlibPtrNone;
use gtk::WidgetExt;
mod c {
use super::*;
use cairo_sys;
use std::os::raw::c_void;
// This is constructed only in C, no need for warnings
#[allow(dead_code)]
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct EekRenderer(*const c_void);
#[no_mangle]
extern "C" {
// Button and View inside CButtonPlace are safe to pass to C
// as long as they don't outlive the call
// and nothing dereferences them
#[allow(improper_ctypes)]
pub fn eek_render_button(
renderer: EekRenderer,
cr: *mut cairo_sys::cairo_t,
button: *const Button,
pressed: u64,
locked: u64,
);
}
#[no_mangle]
pub extern "C"
fn squeek_layout_draw_all_changed(
layout: *mut Layout,
renderer: EekRenderer,
cr: *mut cairo_sys::cairo_t,
) {
let layout = unsafe { &mut *layout };
let cr = unsafe { cairo::Context::from_raw_none(cr) };
let view = layout.get_current_view();
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
let state = RefCell::borrow(&button.state).clone();
if state.pressed == keyboard::PressType::Pressed || state.locked {
render_button_at_position(
renderer, &cr,
row_offset + Point { x: *x_offset, y: 0.0 },
button.as_ref(),
state.pressed, state.locked,
);
}
}
}
}
#[no_mangle]
pub extern "C"
fn squeek_draw_layout_base_view(
layout: *mut Layout,
renderer: EekRenderer,
cr: *mut cairo_sys::cairo_t,
) {
let layout = unsafe { &mut *layout };
let cr = unsafe { cairo::Context::from_raw_none(cr) };
let view = layout.get_current_view();
for (row_offset, row) in &view.get_rows() {
for (x_offset, button) in &row.buttons {
render_button_at_position(
renderer, &cr,
row_offset + Point { x: *x_offset, y: 0.0 },
button.as_ref(),
keyboard::PressType::Released, false,
);
}
}
}
}
/// Renders a button at a position (button's own bounds ignored)
pub fn render_button_at_position(
renderer: c::EekRenderer,
cr: &cairo::Context,
position: Point,
button: &Button,
pressed: keyboard::PressType,
locked: bool,
) {
cr.save();
cr.translate(position.x, position.y);
cr.rectangle(
0.0, 0.0,
button.size.width, button.size.height
);
cr.clip();
unsafe {
c::eek_render_button(
renderer,
cairo::Context::to_raw_none(&cr),
button as *const Button,
pressed as u64,
locked as u64,
)
};
cr.restore();
}
pub fn queue_redraw(keyboard: EekGtkKeyboard) {
let widget = unsafe { gtk::Widget::from_glib_none(keyboard.0) };
widget.queue_draw();
}