diff --git a/examples/win_widget/win_widget.rs b/examples/win_widget/win_widget.rs index 8617cf5..d4341f3 100644 --- a/examples/win_widget/win_widget.rs +++ b/examples/win_widget/win_widget.rs @@ -10,7 +10,7 @@ pub enum CrsWinMsg { Test(i32, i32), } -#[extends(Widget)] +#[extends(Widget, Layout(HBox))] #[win_widget(o2s = "CrsWinMsg", s2o(CrsWinMsg))] #[run_after] pub struct MyWinWidget {} diff --git a/tmui/src/animation/snapshot.rs b/tmui/src/animation/snapshot.rs index 16ece9f..03d14dd 100644 --- a/tmui/src/animation/snapshot.rs +++ b/tmui/src/animation/snapshot.rs @@ -3,8 +3,7 @@ use super::{ AnimationState, Direction, }; use crate::{ - animation::state_holder::ReflectRectHolder, prelude::*, primitive::frame::Frame, - widget::WidgetImpl, + graphics::element::ElementInner, prelude::*, primitive::frame::Frame, widget::WidgetImpl, }; use std::ptr::NonNull; @@ -150,10 +149,10 @@ pub trait Snapshot: WidgetImpl + Animatable { if let Some(rect_holder) = cast!(self as RectHolder) { let rect = rect_holder.animated_rect(); - self.set_fixed_x(rect.x() as i32); - self.set_fixed_y(rect.y() as i32); - self.set_fixed_width(rect.width() as i32); - self.set_fixed_height(rect.height() as i32); + self.as_element().set_fixed_x(rect.x() as i32); + self.as_element().set_fixed_y(rect.y() as i32); + self.as_element().set_fixed_width(rect.width() as i32); + self.as_element().set_fixed_height(rect.height() as i32); if self.animation_model().mode() == AnimationMode::Flex { ApplicationWindow::window_of(self.window_id()) .animation_layout_change(self.as_widget_mut()); @@ -175,10 +174,10 @@ pub trait Snapshot: WidgetImpl + Animatable { } if let Some(origin) = self.animation_model().origin_rect() { - self.set_fixed_x(origin.x()); - self.set_fixed_y(origin.y()); - self.set_fixed_width(origin.width()); - self.set_fixed_height(origin.height()); + self.as_element().set_fixed_x(origin.x()); + self.as_element().set_fixed_y(origin.y()); + self.as_element().set_fixed_width(origin.width()); + self.as_element().set_fixed_height(origin.height()); } if let Some(transparency) = self.animation_model().origin_transparency() { diff --git a/tmui/src/application_window.rs b/tmui/src/application_window.rs index a6c753c..90f32b2 100644 --- a/tmui/src/application_window.rs +++ b/tmui/src/application_window.rs @@ -4,7 +4,7 @@ use crate::{ container::ContainerLayoutEnum, graphics::{ board::Board, - element::{HierachyZ, RenderOrder, TOP_Z_INDEX}, + element::{ElementInner, HierachyZ, RenderOrder, TOP_Z_INDEX}, }, input::{dialog::TyInputDialog, focus_mgr::FocusMgr, ReflectInputEle}, layout::LayoutMgr, @@ -741,6 +741,11 @@ impl ApplicationWindow { self.crs_win_handlers .iter_mut() .for_each(|hnd| nonnull_mut!(hnd).handle_inner()); + + self.widgets.values_mut().for_each(|hnd| { + let widget = nonnull_mut!(hnd); + widget.set_rect_record(widget.rect_f()); + }); } #[inline] diff --git a/tmui/src/font/mgr.rs b/tmui/src/font/mgr.rs index d0e95b8..0834cd5 100644 --- a/tmui/src/font/mgr.rs +++ b/tmui/src/font/mgr.rs @@ -1,7 +1,9 @@ use ahash::AHashMap; use derivative::Derivative; +use lazy_static::lazy_static; use log::error; -use std::{cell::RefCell, io::Read}; +use std::{cell::RefCell, io::Read, sync::Arc}; +use tipc::parking_lot::Mutex; use tlib::{ skia_safe::FontMgr, typedef::{SkiaFontStyle, SkiaTypeface}, @@ -40,6 +42,11 @@ thread_local! { static MGR: RefCell = RefCell::new(FontManager::default()); } +type FontLoaderFn = dyn Fn(&mut FontManager) + 'static + Send + Sync; +lazy_static! { + static ref FONT_LOADER: Arc>>> = Arc::new(Mutex::new(None)); +} + impl FontManager { #[inline] pub(crate) fn load_fonts() { @@ -64,6 +71,10 @@ impl FontManager { manager.fonts.insert(tf.family_name(), tf); } + + if let Some(f) = FONT_LOADER.lock().as_ref() { + f(&mut manager) + } }) } } @@ -79,7 +90,12 @@ impl FontManager { } #[inline] - pub fn load_file(path: &str) { + pub fn register_font_loader(loader: F) { + *FONT_LOADER.lock() = Some(Box::new(loader)); + } + + #[inline] + pub fn load_file(&mut self, path: &str) { let mut file = std::fs::File::open(path).unwrap_or_else(|_| panic!("Open file `{}` failed.", path)); @@ -87,31 +103,21 @@ impl FontManager { file.read_to_end(&mut data) .unwrap_or_else(|_| panic!("Read file `{}` failed", path)); - MGR.with(|mgr| { - let mut manager = mgr.borrow_mut(); + let tf = self + .system_mgr + .new_from_data(&data, None) + .unwrap_or_else(|| panic!("Make customize font typeface failed, ttf file: {}.", path)); - let tf = manager - .system_mgr - .new_from_data(&data, None) - .unwrap_or_else(|| { - panic!("Make customize font typeface failed, ttf file: {}.", path) - }); - - manager.fonts.insert(tf.family_name(), tf); - }); + self.fonts.insert(tf.family_name(), tf); } #[inline] - pub fn load_data(data: &[u8]) { - MGR.with(|mgr| { - let mut manager = mgr.borrow_mut(); - - let tf = manager - .system_mgr - .new_from_data(data, None) - .unwrap_or_else(|| panic!("Make customize font typeface failed.")); + pub fn load_data(&mut self, data: &[u8]) { + let tf = self + .system_mgr + .new_from_data(data, None) + .unwrap_or_else(|| panic!("Make customize font typeface failed.")); - manager.fonts.insert(tf.family_name(), tf); - }) + self.fonts.insert(tf.family_name(), tf); } } diff --git a/tmui/src/graphics/element.rs b/tmui/src/graphics/element.rs index 2b75ac6..72a7477 100644 --- a/tmui/src/graphics/element.rs +++ b/tmui/src/graphics/element.rs @@ -1,5 +1,5 @@ use super::{board::Board, drawing_context::DrawingContext}; -use crate::{application_window::window_id, widget::WidgetImpl}; +use crate::{application_window::window_id, popup::PopupImpl, widget::WidgetImpl}; use log::error; use tlib::{ figure::{FRect, Rect}, @@ -99,18 +99,6 @@ pub trait ElementExt { /// Get the geometry rect of element which contains element's size and position. fn rect_f(&self) -> FRect; - /// Set the width of element. - fn set_fixed_width(&mut self, width: i32); - - /// Set the height of element. - fn set_fixed_height(&mut self, height: i32); - - /// Set the x position of element. - fn set_fixed_x(&mut self, x: i32); - - /// Set the y position of element. - fn set_fixed_y(&mut self, y: i32); - /// The element was invalidated or not. fn invalidate(&self) -> bool; @@ -169,26 +157,6 @@ impl ElementExt for T { self.element_props().rect } - #[inline] - fn set_fixed_width(&mut self, width: i32) { - self.element_props_mut().rect.set_width(width as f32) - } - - #[inline] - fn set_fixed_height(&mut self, height: i32) { - self.element_props_mut().rect.set_height(height as f32) - } - - #[inline] - fn set_fixed_x(&mut self, x: i32) { - self.element_props_mut().rect.set_x(x as f32) - } - - #[inline] - fn set_fixed_y(&mut self, y: i32) { - self.element_props_mut().rect.set_y(y as f32) - } - #[inline] fn invalidate(&self) -> bool { match self.get_property("invalidate") { @@ -211,6 +179,56 @@ impl ElementExt for T { } } +pub(crate) trait ElementInner { + /// Set the width of element. + fn set_fixed_width(&mut self, width: i32); + + /// Set the height of element. + fn set_fixed_height(&mut self, height: i32); + + /// Set the x position of element. + fn set_fixed_x(&mut self, x: i32); + + /// Set the y position of element. + fn set_fixed_y(&mut self, y: i32); +} +macro_rules! element_inner_impl { + () => { + #[inline] + fn set_fixed_width(&mut self, width: i32) { + self.element_props_mut().rect.set_width(width as f32) + } + + #[inline] + fn set_fixed_height(&mut self, height: i32) { + self.element_props_mut().rect.set_height(height as f32) + } + + #[inline] + fn set_fixed_x(&mut self, x: i32) { + self.element_props_mut().rect.set_x(x as f32) + } + + #[inline] + fn set_fixed_y(&mut self, y: i32) { + self.element_props_mut().rect.set_y(y as f32) + } + }; +} + +impl ElementInner for T { + element_inner_impl!(); +} +impl ElementInner for dyn ElementImpl { + element_inner_impl!(); +} +impl ElementInner for dyn WidgetImpl { + element_inner_impl!(); +} +impl ElementInner for dyn PopupImpl { + element_inner_impl!(); +} + /// Every Element's subclass should impl this trait manually, and implements `on_renderer` function.
/// Each subclass which impl [`WidgetImpl`] will impl this trait automatically. #[reflect_trait] diff --git a/tmui/src/hbox.rs b/tmui/src/hbox.rs index cbd32fb..dd123b8 100644 --- a/tmui/src/hbox.rs +++ b/tmui/src/hbox.rs @@ -4,6 +4,7 @@ use crate::{ ContainerLayoutEnum, ContainerScaleCalculate, ScaleStrat, StaticContainerScaleCalculate, StaticSizeUnifiedAdjust, SCALE_ADAPTION, }, + graphics::element::ElementInner, layout::LayoutMgr, prelude::*, }; diff --git a/tmui/src/icons/font_icon.rs b/tmui/src/icons/font_icon.rs index 2120e70..5cfa487 100644 --- a/tmui/src/icons/font_icon.rs +++ b/tmui/src/icons/font_icon.rs @@ -1,5 +1,6 @@ use crate::{ font::FontCalculation, + graphics::element::ElementInner, prelude::*, tlib::object::{ObjectImpl, ObjectSubclass}, widget::{widget_inner::WidgetInnerExt, WidgetImpl}, diff --git a/tmui/src/icons/svg_icon.rs b/tmui/src/icons/svg_icon.rs index 7436ffb..e1b1542 100644 --- a/tmui/src/icons/svg_icon.rs +++ b/tmui/src/icons/svg_icon.rs @@ -1,4 +1,5 @@ use crate::{ + graphics::element::ElementInner, prelude::*, tlib::object::{ObjectImpl, ObjectSubclass}, widget::{widget_inner::WidgetInnerExt, WidgetImpl}, diff --git a/tmui/src/icons/svg_toggle_icon.rs b/tmui/src/icons/svg_toggle_icon.rs index 35d17a9..2c35507 100644 --- a/tmui/src/icons/svg_toggle_icon.rs +++ b/tmui/src/icons/svg_toggle_icon.rs @@ -1,6 +1,7 @@ use std::io::Read; use crate::{ + graphics::element::ElementInner, prelude::*, tlib::object::{ObjectImpl, ObjectSubclass}, widget::{widget_inner::WidgetInnerExt, WidgetImpl}, diff --git a/tmui/src/input/dialog.rs b/tmui/src/input/dialog.rs index 6ffff6b..3300540 100644 --- a/tmui/src/input/dialog.rs +++ b/tmui/src/input/dialog.rs @@ -7,7 +7,7 @@ use super::{ InputType, }; use crate::{ - graphics::styles::Styles, + graphics::{element::ElementInner, styles::Styles}, input::InputSignals, prelude::*, tlib::object::{ObjectImpl, ObjectSubclass}, diff --git a/tmui/src/input/select/mod.rs b/tmui/src/input/select/mod.rs index 6378f61..da03d57 100644 --- a/tmui/src/input/select/mod.rs +++ b/tmui/src/input/select/mod.rs @@ -10,6 +10,7 @@ use crate::widget::widget_ext::FocusStrat; use crate::{ asset::Asset, font::FontCalculation, + graphics::element::ElementInner, input::INPUT_DEFAULT_BORDER_COLOR, input_ele_impl, prelude::*, diff --git a/tmui/src/input/text.rs b/tmui/src/input/text.rs index cb21392..491213e 100644 --- a/tmui/src/input/text.rs +++ b/tmui/src/input/text.rs @@ -12,6 +12,7 @@ use crate::{ system::System, tlib::object::{ObjectImpl, ObjectSubclass}, widget::{widget_inner::WidgetInnerExt, RegionClear, WidgetImpl}, + graphics::element::ElementInner }; use log::warn; use std::{ diff --git a/tmui/src/label.rs b/tmui/src/label.rs index 12dc727..4e440ca 100644 --- a/tmui/src/label.rs +++ b/tmui/src/label.rs @@ -1,5 +1,5 @@ use crate::{ - graphics::painter::Painter, + graphics::{element::ElementInner, painter::Painter}, layout::ContentAlignment, prelude::*, widget::{widget_inner::WidgetInnerExt, WidgetImpl}, diff --git a/tmui/src/layout.rs b/tmui/src/layout.rs index f37316c..b0262aa 100644 --- a/tmui/src/layout.rs +++ b/tmui/src/layout.rs @@ -1,5 +1,6 @@ use crate::{ container::{Container, ContainerImpl, ReflectSizeUnifiedAdjust, ScaleMeasure, SpacingSize}, + graphics::element::ElementInner, opti::tracker::Tracker, prelude::*, primitive::Message, diff --git a/tmui/src/overlay.rs b/tmui/src/overlay.rs index 45f9213..fef95d5 100644 --- a/tmui/src/overlay.rs +++ b/tmui/src/overlay.rs @@ -2,6 +2,7 @@ use crate::{ container::{ ContainerLayoutEnum, ContainerScaleCalculate, StaticContainerScaleCalculate, SCALE_DISMISS, }, + graphics::element::ElementInner, layout::LayoutMgr, prelude::*, tlib::object::{ObjectImpl, ObjectSubclass}, diff --git a/tmui/src/popup.rs b/tmui/src/popup.rs index 8d8bb8b..785cbd9 100644 --- a/tmui/src/popup.rs +++ b/tmui/src/popup.rs @@ -1,4 +1,5 @@ use crate::{ + graphics::element::ElementInner, prelude::*, tlib::object::{ObjectImpl, ObjectSubclass}, widget::WidgetImpl, diff --git a/tmui/src/runtime/wed.rs b/tmui/src/runtime/wed.rs index a051a80..411f000 100644 --- a/tmui/src/runtime/wed.rs +++ b/tmui/src/runtime/wed.rs @@ -1,7 +1,7 @@ use crate::{ application, application_window::ApplicationWindow, - graphics::element::HierachyZ, + graphics::element::{ElementInner, HierachyZ}, input::focus_mgr::FocusMgr, prelude::*, primitive::{global_watch::GlobalWatchEvent, Message}, @@ -18,8 +18,6 @@ use tlib::{ values::ToValue, }; -use super::ElementExt; - ////////////////////////////////////////////////////////////////////////////////////////////// /// [`Event`] dispatch ////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/tmui/src/scroll_area.rs b/tmui/src/scroll_area.rs index 8d332d5..95c6afa 100644 --- a/tmui/src/scroll_area.rs +++ b/tmui/src/scroll_area.rs @@ -1,6 +1,7 @@ use crate::{ application_window::ApplicationWindow, container::{ContainerLayoutEnum, ContainerScaleCalculate, SCALE_ADAPTION}, + graphics::element::ElementInner, layout::LayoutMgr, prelude::*, scroll_bar::{ScrollBar, ScrollBarPosition}, diff --git a/tmui/src/split_pane.rs b/tmui/src/split_pane.rs index e2d0787..df8764d 100644 --- a/tmui/src/split_pane.rs +++ b/tmui/src/split_pane.rs @@ -4,6 +4,7 @@ use crate::{ ContainerLayoutEnum, ContainerScaleCalculate, ReflectSizeUnifiedAdjust, StaticContainerScaleCalculate, SCALE_DISMISS, }, + graphics::element::ElementInner, layout::LayoutMgr, prelude::*, tlib::{ diff --git a/tmui/src/vbox.rs b/tmui/src/vbox.rs index f4d56cb..c0feecb 100644 --- a/tmui/src/vbox.rs +++ b/tmui/src/vbox.rs @@ -4,6 +4,7 @@ use crate::{ ContainerLayoutEnum, ContainerScaleCalculate, ScaleStrat, StaticContainerScaleCalculate, StaticSizeUnifiedAdjust, SCALE_ADAPTION, }, + graphics::element::ElementInner, layout::LayoutMgr, prelude::*, }; diff --git a/tmui/src/widget/mod.rs b/tmui/src/widget/mod.rs index 1f320f3..d617eea 100644 --- a/tmui/src/widget/mod.rs +++ b/tmui/src/widget/mod.rs @@ -285,6 +285,19 @@ impl WidgetSignals for dyn WidgetImpl {} ////////////////////////////////////// Widget Implements ////////////////////////////////////// impl Widget { + #[inline] + pub fn resize_batch( + mut base: DynTr, + widgets: &mut [&mut dyn WidgetImpl], + width: Option, + height: Option, + ) { + for w in widgets.iter_mut() { + w.resize_ex(width, height, false); + } + ApplicationWindow::window().layout_change(base.bind_mut()); + } + #[inline] pub fn _child_internal(&mut self, mut child: Tr) where diff --git a/tmui/src/widget/widget_ext.rs b/tmui/src/widget/widget_ext.rs index 23c9bff..eb18240 100644 --- a/tmui/src/widget/widget_ext.rs +++ b/tmui/src/widget/widget_ext.rs @@ -6,6 +6,7 @@ use crate::{ animation::snapshot::ReflectSnapshot, application_window::ApplicationWindow, font::FontTypeface, + graphics::element::ElementInner, graphics::{ border::Border, box_shadow::{BoxShadow, ShadowPos, ShadowSide}, @@ -104,6 +105,13 @@ pub trait WidgetExt { /// `resize() will set fixed_width and fixed_height to false`, make widget flexible. fn resize(&mut self, width: Option, height: Option); + /// Resize the widget.
+ /// If `cause_layout_change` is false, shouold call [`ApplicationWindow::window().layout_change(self)`](crate::application_window::ApplicationWindow::layout_change) after all widgets resized manually.
+ /// Use [`Widget::resize_batch`](crate::widget::Widget::resize_batch) if all widget has the same size to resize. + /// + /// `resize() will set fixed_width and fixed_height to false`, make widget flexible. + fn resize_ex(&mut self, width: Option, height: Option, cause_layout_change: bool); + /// Request the widget's width.
/// This function should be used in construct phase of the ui component, /// the function will not change the layout and will not trigger the signal `size_changed()`. @@ -826,6 +834,11 @@ impl WidgetExt for T { #[inline] fn resize(&mut self, width: Option, height: Option) { + self.resize_ex(width, height, true); + } + + #[inline] + fn resize_ex(&mut self, width: Option, height: Option, cause_layout_change: bool) { if width.is_none() && height.is_none() { return; } @@ -877,7 +890,7 @@ impl WidgetExt for T { emit!(self, size_changed(self.size())) } - if self.id() != self.window_id() { + if self.id() != self.window_id() && cause_layout_change { self.window().layout_change(self); } } diff --git a/tmui/src/widget/widget_inner.rs b/tmui/src/widget/widget_inner.rs index b61200f..84823e8 100644 --- a/tmui/src/widget/widget_inner.rs +++ b/tmui/src/widget/widget_inner.rs @@ -1,4 +1,5 @@ use super::{Container, EventBubble, WidgetImpl}; +use crate::graphics::element::ElementInner; use crate::graphics::painter::Painter; use nohash_hasher::IntSet; use tlib::{