Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/border/border_with_child.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl ObjectSubclass for BorderWithChild {

impl ObjectImpl for BorderWithChild {
fn initialize(&mut self) {
self.set_background(Color::GREY_LIGHT);
self.set_background(Color::TRANSPARENT);
self.set_halign(Align::Center);
self.enable_bubble(EventBubble::MOUSE_MOVE);

Expand All @@ -44,6 +44,6 @@ impl WidgetImpl for BorderWithChild {

fn on_mouse_leave(&mut self, _: &MouseEvent) {
info!("Mouse leaved.");
self.set_background(Color::GREY_LIGHT);
self.set_background(Color::TRANSPARENT);
}
}
4 changes: 2 additions & 2 deletions tmui/src/graphics/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ impl<'a> Painter<'a> {
}

#[inline]
pub fn draw_dom(&self, dom: &tlib::typedef::SkiaSvgDom) {
dom.render(self.canvas);
pub fn draw_dom(&self, dom: impl AsRef<tlib::typedef::SkiaSvgDom>) {
dom.as_ref().render(self.canvas);
}
}
3 changes: 2 additions & 1 deletion tmui/src/icons/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod font_icon;
pub mod svg_dom;
pub mod svg_icon;
pub mod svg_toggle_icon;
pub mod svg_toggle_icon;
52 changes: 52 additions & 0 deletions tmui/src/icons/svg_dom.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::io::Read;

use tlib::{figure::Size, skia_safe::FontMgr, typedef::SkiaSvgDom};
use usvg::{fontdb::Database, Options, Tree};

#[derive(Debug, Clone)]
pub struct SvgDom {
dom: SkiaSvgDom,
size: Size,
}

impl SvgDom {
pub fn from_file(path: &str) -> Self {
let mut file = std::fs::File::open(path).expect("Open file failed");
let mut data = vec![];
file.read_to_end(&mut data).expect("Read file failed");

Self::build_from_data(&data)
}

#[inline]
pub fn from_bytes(data: &[u8]) -> Self {
Self::build_from_data(data)
}

#[inline]
fn build_from_data(data: &[u8]) -> Self {
let svg_tree = Tree::from_data(data, &Options::default(), &Database::default())
.expect("Create svg tree failed");
let size = svg_tree.size();
let (w, h) = (size.width().ceil() as i32, size.height().ceil() as i32);

let dom = SkiaSvgDom::from_bytes(data, FontMgr::default()).expect("Create svg dom failed");

Self {
dom,
size: Size::new(w, h),
}
}

#[inline]
pub fn get_size(&self) -> Size {
self.size
}
}

impl AsRef<SkiaSvgDom> for SvgDom {
#[inline]
fn as_ref(&self) -> &SkiaSvgDom {
&self.dom
}
}
30 changes: 22 additions & 8 deletions tmui/src/icons/svg_icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ impl ObjectImpl for SvgIcon {}

impl WidgetImpl for SvgIcon {
fn paint(&mut self, painter: &mut Painter) {
let rect = self.rect_f();
let (x1, y1, w1, h1) = (rect.x(), rect.y(), rect.width(), rect.height());
let (w2, h2) = (
self.view_size.width() as f32,
self.view_size.height() as f32,
);
let origin = FPoint::new(x1 + (w1 - w2) / 2., y1 + (h1 - h2) / 2.);

if let Some(ref dom) = self.dom {
let rect = self.rect_f();
let (x1, y1, w1, h1) = (rect.x(), rect.y(), rect.width(), rect.height());
let (w2, h2) = (
self.view_size.width() as f32,
self.view_size.height() as f32,
);
let origin = FPoint::new(x1 + (w1 - w2) / 2., y1 + (h1 - h2) / 2.);

painter.save();
painter.translate(origin.x(), origin.y());
painter.draw_dom(dom);
Expand Down Expand Up @@ -61,6 +61,20 @@ impl SvgIcon {

icon
}

#[inline]
pub fn load_file(&mut self, path: &str) {
let mut file = std::fs::File::open(path).expect("Open file failed");
let mut data = vec![];
file.read_to_end(&mut data).expect("Read file failed");

self.build_from_data(&data);
}

#[inline]
pub fn load_bytes(&mut self, data: &[u8]) {
self.build_from_data(data);
}
}

impl SvgIcon {
Expand Down
37 changes: 31 additions & 6 deletions tmui/src/views/cell/cell_render.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#![allow(dead_code)]
use crate::graphics::painter::Painter;
use crate::{graphics::painter::Painter, icons::svg_dom::SvgDom};
use derivative::Derivative;
use log::warn;
use std::fmt::Debug;
use tlib::{
figure::{Color, FRect},
figure::{Color, FPoint, FRect},
global::{shown_value_32, shown_value_64},
namespace::BorderStyle,
skia_safe::ClipOp,
Expand All @@ -14,10 +15,11 @@ use tlib::{
pub enum CellRenderType {
Text,
Image,
Svg,
}

pub trait CellRender: Debug + 'static + Send + Sync {
fn render(&self, painter: &mut Painter, geometry: FRect, val: &Value);
fn render(&self, painter: &mut Painter, geometry: FRect, val: Option<&Value>);

fn border(&self) -> (f32, f32, f32, f32);

Expand Down Expand Up @@ -48,7 +50,7 @@ pub trait CellRender: Debug + 'static + Send + Sync {

macro_rules! cell_render_struct {
( $cell:ident, $builder:ident, $render_type:ident $(, $field:ident:$ty:tt)* ) => {
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub struct $cell {
border: (f32, f32, f32, f32),
border_style: BorderStyle,
Expand Down Expand Up @@ -209,11 +211,14 @@ macro_rules! impl_cell_render_common {
};
}

type OptSvgDom = Option<SvgDom>;

cell_render_struct!(TextCellRender, TextCellRenderBuilder, Text, color:Color, letter_spacing:f32);
cell_render_struct!(ImageCellRender, ImageCellRenderBuilder, Image);
cell_render_struct!(SvgCellRender, SvgCellRenderBuilder, Svg, dom:OptSvgDom);

impl CellRender for TextCellRender {
fn render(&self, painter: &mut Painter, geometry: FRect, val: &Value) {
fn render(&self, painter: &mut Painter, geometry: FRect, val: Option<&Value>) {
painter.save();
painter.save_pen();
painter.clip_rect(geometry, ClipOp::Intersect);
Expand All @@ -223,6 +228,7 @@ impl CellRender for TextCellRender {
if let Some(background) = self.background {
painter.fill_rect(geometry, background);
}
let val = val.as_ref().unwrap();

let text = match val.ty() {
Type::STRING => val.get::<String>(),
Expand Down Expand Up @@ -280,7 +286,26 @@ impl TextCellRender {
}

impl CellRender for ImageCellRender {
fn render(&self, _painter: &mut Painter, _geometry: FRect, _val: &Value) {}
fn render(&self, _painter: &mut Painter, _geometry: FRect, _val: Option<&Value>) {}

impl_cell_render_common!();
}

impl CellRender for SvgCellRender {
fn render(&self, painter: &mut Painter, rect: FRect, _: Option<&Value>) {
if let Some(dom) = self.dom.as_ref() {
let view_size = dom.get_size();
let (x1, y1, w1, h1) = (rect.x(), rect.y(), rect.width(), rect.height());
let (w2, h2) = (view_size.width() as f32, view_size.height() as f32);
let origin = FPoint::new(x1 + (w1 - w2) / 2., y1 + (h1 - h2) / 2.);
painter.save();
painter.translate(origin.x(), origin.y());
painter.draw_dom(dom);
painter.restore();
} else {
warn!("The `dom` of `SvgCellRender` is not assigned.");
}
}

impl_cell_render_common!();
}
51 changes: 49 additions & 2 deletions tmui/src/views/cell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ pub enum Cell {
F32 { expand: bool, val: Value, render: Option<Box<dyn CellRender>> },
F64 { expand: bool, val: Value, render: Option<Box<dyn CellRender>> },
Image { expand: bool, image_address: Value, render: Option<Box<dyn CellRender>> },
Svg { expand: bool, render: Option<Box<dyn CellRender>> },
Value { val: Value },
}

macro_rules! common_cell_render_clause {
($render:ident, $painter:ident, $geometry:ident, $val:ident) => {
if let Some(render) = $render {
render.render($painter, $geometry, $val);
render.render($painter, $geometry, Some($val));
}
};
}
Expand Down Expand Up @@ -88,7 +89,12 @@ impl Cell {
..
} => {
if let Some(render) = render {
render.render(painter, geometry, image_address);
render.render(painter, geometry, Some(image_address));
}
}
Self::Svg { render, .. } => {
if let Some(render) = render {
render.render(painter, geometry, None);
}
}
Self::Value { .. } => {}
Expand All @@ -112,6 +118,7 @@ impl Cell {
Self::F32 { .. } => f32::static_type(),
Self::F64 { .. } => f64::static_type(),
Self::Image { .. } => String::static_type(),
Self::Svg { .. } => Type::NONE,
Self::Value { val } => val.ty(),
}
}
Expand All @@ -133,6 +140,7 @@ impl Cell {
Self::F32 { val, .. } => val,
Self::F64 { val, .. } => val,
Self::Image { image_address, .. } => image_address,
Self::Svg { .. } => panic!("Invalid access, Svg cell does not has the value."),
Self::Value { val } => val,
}
}
Expand All @@ -154,6 +162,7 @@ impl Cell {
Self::F32 { val, .. } => *val = value,
Self::F64 { val, .. } => *val = value,
Self::Image { image_address, .. } => *image_address = value,
Self::Svg { .. } => {}
Self::Value { val } => *val = value,
}
}
Expand All @@ -175,6 +184,7 @@ impl Cell {
Self::F32 { render, .. } => render.as_deref(),
Self::F64 { render, .. } => render.as_deref(),
Self::Image { render, .. } => render.as_deref(),
Self::Svg { render, .. } => render.as_deref(),
Self::Value { .. } => None,
}
}
Expand All @@ -196,6 +206,7 @@ impl Cell {
Self::F32 { render, .. } => render.as_deref_mut(),
Self::F64 { render, .. } => render.as_deref_mut(),
Self::Image { render, .. } => render.as_deref_mut(),
Self::Svg { render, .. } => render.as_deref_mut(),
Self::Value { .. } => None,
}
}
Expand All @@ -217,6 +228,7 @@ impl Cell {
Self::F32 { .. } => vec![Text],
Self::F64 { .. } => vec![Text],
Self::Image { .. } => vec![Image],
Self::Svg { .. } => vec![Svg],
Self::Value { .. } => vec![],
}
}
Expand Down Expand Up @@ -351,6 +363,40 @@ impl CellValueBuilder {
}
}

#[derive(Default, Debug)]
pub struct CellSvgBuilder {
expand: bool,
cell_render: Option<Box<dyn CellRender>>,
}
impl CellSvgBuilder {
#[inline]
pub fn expand(mut self, expand: bool) -> Self {
self.expand = expand;
self
}

#[inline]
pub fn cell_render(mut self, render: Box<dyn CellRender>) -> Self {
self.cell_render = Some(render);
self
}

#[inline]
pub fn build(self) -> Cell {
let cell = Cell::Svg {
expand: self.expand,
render: self.cell_render,
};

if let Some(cell_render) = cell.get_render() {
if !cell.support_render_types().contains(&cell_render.ty()) {
panic!("Unsupported cell render type.");
}
}
cell
}
}

macro_rules! cell_builder_func {
( $name:ident, $builder:ident ) => {
#[inline]
Expand All @@ -376,5 +422,6 @@ impl Cell {
cell_builder_func!(f32, CellF32Builder);
cell_builder_func!(f64, CellF64Builder);
cell_builder_func!(image, CellImageBuilder);
cell_builder_func!(svg, CellSvgBuilder);
cell_builder_func!(value_cell, CellValueBuilder);
}
8 changes: 8 additions & 0 deletions tmui/src/widget/widget_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,14 @@ impl<T: WidgetImpl> WidgetExt for T {

self.set_whole_styles_render(true);
self.notify_update();

if self.border_ref().should_draw_radius() {
if let Some(parent) = self.get_parent_mut() {
parent.set_whole_styles_render(true);
parent.set_render_styles(true);
parent.update();
}
}
}

#[inline]
Expand Down