Skip to content

Commit

Permalink
Merge pull request #293 from kas-gui/work2
Browse files Browse the repository at this point in the history
Improve autoimpl! macro
  • Loading branch information
dhardy committed Mar 11, 2022
2 parents 00128f3 + 2c8974f commit a15730c
Show file tree
Hide file tree
Showing 25 changed files with 779 additions and 483 deletions.
100 changes: 8 additions & 92 deletions crates/kas-core/src/theme/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
//! "Handle" types used by themes

use std::convert::AsRef;
use std::ops::{Bound, Deref, DerefMut, Range, RangeBounds};
use std::ops::{Bound, Range, RangeBounds};

use super::{FrameStyle, IdCoord, IdRect, SizeHandle, SizeMgr, TextClass};
use crate::dir::Direction;
use crate::draw::{color::Rgb, Draw, DrawShared, ImageId, PassType};
use crate::event::EventState;
use crate::geom::{Coord, Offset, Rect};
use crate::layout::SetRectMgr;
use crate::macros::autoimpl;
use crate::text::{AccelString, Text, TextApi, TextDisplay};
use crate::{TkAction, WidgetId};

Expand Down Expand Up @@ -329,6 +330,12 @@ impl<'a> std::ops::BitOrAssign<TkAction> for DrawMgr<'a> {
/// A handle to the active theme, used for drawing
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
#[autoimpl(for<H: trait + ?Sized> Box<H>)]
#[cfg_attr(feature = "stack_dst", autoimpl(
for<'a, S: Default + Copy + AsRef<[usize]> + AsMut<[usize]>>
stack_dst::ValueA<dyn DrawHandle + 'a, S>
using dyn DrawHandle
))]
pub trait DrawHandle {
/// Access components: [`SizeHandle`], [`DrawShared`], [`EventState`]
fn components(&mut self) -> (&dyn SizeHandle, &mut dyn DrawShared, &mut EventState);
Expand Down Expand Up @@ -468,97 +475,6 @@ pub trait DrawHandle {
fn image(&mut self, id: ImageId, rect: Rect);
}

macro_rules! impl_ {
(($($args:tt)*) DrawHandle for $ty:ty) => {
impl<$($args)*> DrawHandle for $ty {
fn components(&mut self) -> (&dyn SizeHandle, &mut dyn DrawShared, &mut EventState) {
self.deref_mut().components()
}
fn draw_device(&mut self) -> &mut dyn Draw {
self.deref_mut().draw_device()
}
fn new_pass(
&mut self,
rect: Rect,
offset: Offset,
class: PassType,
f: &mut dyn FnMut(&mut dyn DrawHandle),
) {
self.deref_mut().new_pass(rect, offset, class, f);
}
fn get_clip_rect(&self) -> Rect {
self.deref().get_clip_rect()
}
fn frame(&mut self, id: &WidgetId, rect: Rect, style: FrameStyle, bg: Background) {
self.deref_mut().frame(id, rect, style, bg);
}
fn separator(&mut self, rect: Rect) {
self.deref_mut().separator(rect);
}
fn selection_box(&mut self, rect: Rect) {
self.deref_mut().selection_box(rect);
}
fn text(&mut self, id: &WidgetId, pos: Coord, text: &TextDisplay, class: TextClass) {
self.deref_mut().text(id, pos, text, class)
}
fn text_effects(
&mut self,
id: &WidgetId, pos: Coord,
text: &dyn TextApi,
class: TextClass,
) {
self.deref_mut().text_effects(id, pos, text, class);
}
fn text_accel(
&mut self,
id: &WidgetId, pos: Coord,
text: &Text<AccelString>,
class: TextClass,
) {
self.deref_mut().text_accel(id, pos, text, class);
}
fn text_selected_range(
&mut self,
id: &WidgetId, pos: Coord,
text: &TextDisplay,
range: Range<usize>,
class: TextClass,
) {
self.deref_mut()
.text_selected_range(id, pos, text, range, class);
}
fn text_cursor(&mut self, id: &WidgetId, pos: Coord, text: &TextDisplay, class: TextClass, byte: usize) {
self.deref_mut().text_cursor(id, pos, text, class, byte)
}
fn checkbox(&mut self, id: &WidgetId, rect: Rect, checked: bool) {
self.deref_mut().checkbox(id, rect, checked)
}
fn radiobox(&mut self, id: &WidgetId, rect: Rect, checked: bool) {
self.deref_mut().radiobox(id, rect, checked)
}
fn scrollbar(&mut self, id: &WidgetId, id2: &WidgetId, rect: Rect, h_rect: Rect, dir: Direction) {
self.deref_mut().scrollbar(id, id2, rect, h_rect, dir)
}
fn slider(&mut self, id: &WidgetId, id2: &WidgetId, rect: Rect, h_rect: Rect, dir: Direction) {
self.deref_mut().slider(id, id2, rect, h_rect, dir)
}
fn progress_bar(&mut self, id: &WidgetId, rect: Rect, dir: Direction, value: f32) {
self.deref_mut().progress_bar(id, rect, dir, value);
}
fn image(&mut self, id: ImageId, rect: Rect) {
self.deref_mut().image(id, rect);
}
}
};
}

impl_! { (H: DrawHandle) DrawHandle for Box<H> }
#[cfg(feature = "stack_dst")]
impl_! {
('a, S: Default + Copy + AsRef<[usize]> + AsMut<[usize]>)
DrawHandle for stack_dst::ValueA<dyn DrawHandle + 'a, S>
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
63 changes: 3 additions & 60 deletions crates/kas-core/src/theme/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use super::DrawMgr;
use super::{FrameStyle, TextClass};
use crate::geom::Size;
use crate::layout::{AxisInfo, FrameRules, Margins, SizeRules};
use crate::macros::autoimpl;
use crate::text::TextApi;

// for doc use
#[allow(unused)]
use crate::text::TextApiExt;
Expand Down Expand Up @@ -199,6 +201,7 @@ impl<'a> SizeMgr<'a> {
/// A handle to the active theme, used for sizing
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
#[autoimpl(for<S: trait + ?Sized, R: Deref<Target = S>> R)]
pub trait SizeHandle {
/// Get the scale (DPI) factor
fn scale_factor(&self) -> f32;
Expand Down Expand Up @@ -290,63 +293,3 @@ pub trait SizeHandle {
/// For a vertical bar, the values are swapped.
fn progress_bar(&self) -> Size;
}

macro_rules! impl_ {
(($($args:tt)*) SizeHandle for $ty:ty) => {
impl<$($args)*> SizeHandle for $ty {
fn scale_factor(&self) -> f32 {
self.deref().scale_factor()
}
fn pixels_from_points(&self, pt: f32) -> f32 {
self.deref().pixels_from_points(pt)
}
fn pixels_from_em(&self, em: f32) -> f32 {
self.deref().pixels_from_em(em)
}

fn frame(&self, style: FrameStyle, is_vert: bool) -> FrameRules {
self.deref().frame(style, is_vert)
}
fn separator(&self) -> Size {
self.deref().separator()
}
fn inner_margin(&self) -> Size {
self.deref().inner_margin()
}
fn outer_margins(&self) -> Margins {
self.deref().outer_margins()
}
fn text_margins(&self) -> Margins {
self.deref().text_margins()
}

fn line_height(&self, class: TextClass) -> i32 {
self.deref().line_height(class)
}
fn text_bound(&self, text: &mut dyn TextApi, class: TextClass, axis: AxisInfo) -> SizeRules {
self.deref().text_bound(text, class, axis)
}
fn text_cursor_width(&self) -> f32 {
self.deref().text_cursor_width()
}

fn checkbox(&self) -> Size {
self.deref().checkbox()
}
fn radiobox(&self) -> Size {
self.deref().radiobox()
}
fn scrollbar(&self) -> (Size, i32) {
self.deref().scrollbar()
}
fn slider(&self) -> (Size, i32) {
self.deref().slider()
}
fn progress_bar(&self) -> Size {
self.deref().progress_bar()
}
}
};
}

impl_! { (S: SizeHandle + ?Sized, R: Deref<Target = S>) SizeHandle for R }
153 changes: 0 additions & 153 deletions crates/kas-core/src/updatable/data_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use super::*;
use crate::event::UpdateHandle;
use crate::WidgetId;
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};

impl<T: Clone + Debug> ListData for [T] {
type Key = usize;
Expand Down Expand Up @@ -60,155 +59,3 @@ impl<T: Clone + Debug> ListDataMut for [T] {
self[*key] = item;
}
}

// TODO(spec): implement using Deref; for now can't since it "might" conflict
// with a RefCell impl on a derived type downstream, according to the solver.
// impl<T: Deref + Debug> SingleData for T
// where
// <T as Deref>::Target: SingleData,
macro_rules! impl_via_deref {
($t: ident: $derived:ty) => {
impl<$t: SingleData + ?Sized> SingleData for $derived {
type Item = $t::Item;
fn update_handles(&self) -> Vec<UpdateHandle> {
self.deref().update_handles()
}
fn version(&self) -> u64 {
self.deref().version()
}
fn get_cloned(&self) -> Self::Item {
self.deref().get_cloned()
}
fn update(&self, value: Self::Item) -> Option<UpdateHandle> {
self.deref().update(value)
}
}

impl<$t: ListData + ?Sized> ListData for $derived {
type Key = $t::Key;
type Item = $t::Item;

fn update_handles(&self) -> Vec<UpdateHandle> {
self.deref().update_handles()
}
fn version(&self) -> u64 {
self.deref().version()
}

fn len(&self) -> usize {
self.deref().len()
}
fn make_id(&self, parent: &WidgetId, key: &Self::Key) -> WidgetId {
self.deref().make_id(parent, key)
}
fn reconstruct_key(&self, parent: &WidgetId, child: &WidgetId) -> Option<Self::Key> {
self.deref().reconstruct_key(parent, child)
}

fn contains_key(&self, key: &Self::Key) -> bool {
self.deref().contains_key(key)
}
fn get_cloned(&self, key: &Self::Key) -> Option<Self::Item> {
self.deref().get_cloned(key)
}

fn update(&self, key: &Self::Key, value: Self::Item) -> Option<UpdateHandle> {
self.deref().update(key, value)
}

fn iter_vec(&self, limit: usize) -> Vec<Self::Key> {
self.deref().iter_vec(limit)
}
fn iter_vec_from(&self, start: usize, limit: usize) -> Vec<Self::Key> {
self.deref().iter_vec_from(start, limit)
}
}

impl<$t: MatrixData + ?Sized> MatrixData for $derived {
type ColKey = $t::ColKey;
type RowKey = $t::RowKey;
type Key = $t::Key;
type Item = $t::Item;

fn update_handles(&self) -> Vec<UpdateHandle> {
self.deref().update_handles()
}
fn version(&self) -> u64 {
self.deref().version()
}

fn is_empty(&self) -> bool {
self.deref().is_empty()
}
fn len(&self) -> (usize, usize) {
self.deref().len()
}
fn make_id(&self, parent: &WidgetId, key: &Self::Key) -> WidgetId {
self.deref().make_id(parent, key)
}
fn reconstruct_key(&self, parent: &WidgetId, child: &WidgetId) -> Option<Self::Key> {
self.deref().reconstruct_key(parent, child)
}

fn contains(&self, key: &Self::Key) -> bool {
self.deref().contains(key)
}
fn get_cloned(&self, key: &Self::Key) -> Option<Self::Item> {
self.deref().get_cloned(key)
}

fn update(&self, key: &Self::Key, value: Self::Item) -> Option<UpdateHandle> {
self.deref().update(key, value)
}

fn col_iter_vec(&self, limit: usize) -> Vec<Self::ColKey> {
self.deref().col_iter_vec(limit)
}
fn col_iter_vec_from(&self, start: usize, limit: usize) -> Vec<Self::ColKey> {
self.deref().col_iter_vec_from(start, limit)
}

fn row_iter_vec(&self, limit: usize) -> Vec<Self::RowKey> {
self.deref().row_iter_vec(limit)
}
fn row_iter_vec_from(&self, start: usize, limit: usize) -> Vec<Self::RowKey> {
self.deref().row_iter_vec_from(start, limit)
}

fn make_key(col: &Self::ColKey, row: &Self::RowKey) -> Self::Key {
<$t>::make_key(col, row)
}
}
};
($t: ident: $derived:ty, $($dd:ty),+) => {
impl_via_deref!($t: $derived);
impl_via_deref!($t: $($dd),+);
};
}
impl_via_deref!(T: &T, &mut T);
impl_via_deref!(T: std::rc::Rc<T>, std::sync::Arc<T>, Box<T>);

macro_rules! impl_via_deref_mut {
($t: ident: $derived:ty) => {
impl<$t: SingleDataMut + ?Sized> SingleDataMut for $derived {
fn set(&mut self, value: Self::Item) {
self.deref_mut().set(value)
}
}
impl<$t: ListDataMut + ?Sized> ListDataMut for $derived {
fn set(&mut self, key: &Self::Key, item: Self::Item) {
self.deref_mut().set(key, item)
}
}
impl<$t: MatrixDataMut + ?Sized> MatrixDataMut for $derived {
fn set(&mut self, key: &Self::Key, item: Self::Item) {
self.deref_mut().set(key, item)
}
}
};
($t: ident: $derived:ty, $($dd:ty),+) => {
impl_via_deref_mut!($t: $derived);
impl_via_deref_mut!($t: $($dd),+);
};
}
impl_via_deref_mut!(T: &mut T, Box<T>);
Loading

0 comments on commit a15730c

Please sign in to comment.