wgui: pretty-print tree
This commit is contained in:
@@ -77,7 +77,8 @@ fn load_testbed(
|
|||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
init_logging();
|
init_logging();
|
||||||
|
|
||||||
let (gfx, event_loop, window, surface) = init_window("[-/=]: gui scale, F10: debug draw")?;
|
let (gfx, event_loop, window, surface) =
|
||||||
|
init_window("[-/=]: gui scale, F10: debug draw, F11: print tree")?;
|
||||||
let inner_size = window.inner_size();
|
let inner_size = window.inner_size();
|
||||||
let mut swapchain_size = [inner_size.width, inner_size.height];
|
let mut swapchain_size = [inner_size.width, inner_size.height];
|
||||||
|
|
||||||
@@ -230,6 +231,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
testbed.layout().borrow_mut().mark_redraw();
|
testbed.layout().borrow_mut().mark_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event.physical_key == PhysicalKey::Code(KeyCode::F11) {
|
||||||
|
testbed.layout().borrow_mut().print_tree();
|
||||||
|
}
|
||||||
|
|
||||||
if event.physical_key == PhysicalKey::Code(KeyCode::Equal) {
|
if event.physical_key == PhysicalKey::Code(KeyCode::Equal) {
|
||||||
scale *= 1.25;
|
scale *= 1.25;
|
||||||
render_context
|
render_context
|
||||||
@@ -309,7 +314,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
log::trace!("drawing frame {frame_index}");
|
log::trace!("drawing frame {frame_index}");
|
||||||
frame_index += 1;
|
frame_index += 1;
|
||||||
|
|
||||||
limiter.start(0); // max 120 fps
|
limiter.start(120); // max 120 fps
|
||||||
profiler.start();
|
profiler.start();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ pub struct Color {
|
|||||||
pub a: f32,
|
pub a: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const ANSI_RESET_CODE: &str = "\x1b[39m\x1b[49m";
|
||||||
|
pub const ANSI_BOLD_CODE: &str = "\x1b[1m";
|
||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
|
pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
|
||||||
Self { r, g, b, a }
|
Self { r, g, b, a }
|
||||||
@@ -109,6 +112,18 @@ impl Color {
|
|||||||
a: self.a * (1.0 - n) + other.a * n,
|
a: self.a * (1.0 - n) + other.a * n,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn debug_ansi_format(&self) -> String {
|
||||||
|
let r = (self.r * 255.0).clamp(0.0, 255.0) as u8;
|
||||||
|
let g = (self.g * 255.0).clamp(0.0, 255.0) as u8;
|
||||||
|
let b = (self.b * 255.0).clamp(0.0, 255.0) as u8;
|
||||||
|
format!("\x1b[38;2;{r};{g};{b}m")
|
||||||
|
}
|
||||||
|
|
||||||
|
// pretty-print ansi escape code color
|
||||||
|
pub fn debug_ansi_block(&self) -> String {
|
||||||
|
format!("{}███{}", self.debug_ansi_format(), ANSI_RESET_CODE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Color {
|
impl Default for Color {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use crate::assets::AssetProvider;
|
|||||||
// for now it's just a simple string container
|
// for now it's just a simple string container
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Translation {
|
pub struct Translation {
|
||||||
text: Rc<str>,
|
pub text: Rc<str>,
|
||||||
translated: bool, // if true, `text` is a translation key
|
pub translated: bool, // if true, `text` is a translation key
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Translation {
|
impl PartialEq for Translation {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::{RefCell, RefMut},
|
cell::{RefCell, RefMut},
|
||||||
|
io::Write,
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
animation::Animations,
|
animation::Animations,
|
||||||
components::{Component, InitData},
|
components::{Component, InitData},
|
||||||
drawing::{Boundary, push_scissor_stack, push_transform_stack},
|
drawing::{self, ANSI_BOLD_CODE, ANSI_RESET_CODE, Boundary, push_scissor_stack, push_transform_stack},
|
||||||
event::{self, CallbackDataCommon, EventAlterables, EventListenerCollection},
|
event::{self, CallbackDataCommon, EventAlterables, EventListenerCollection},
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
widget::{self, EventParams, WidgetObj, WidgetState, div::WidgetDiv},
|
widget::{self, EventParams, WidgetObj, WidgetState, div::WidgetDiv},
|
||||||
@@ -546,6 +547,54 @@ impl Layout {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_tree(&self) {
|
||||||
|
let mut buf = Vec::<u8>::new();
|
||||||
|
self.print_tree_recur(&mut buf, 0, self.tree_root_node);
|
||||||
|
let str = format!("\n{}", unsafe { str::from_utf8_unchecked(&buf) });
|
||||||
|
std::io::stdout().write_all(str.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_tree_recur(&self, buf: &mut Vec<u8>, depth: u32, node_id: taffy::NodeId) {
|
||||||
|
// indent
|
||||||
|
for _ in 0..depth {
|
||||||
|
buf.push(b'|');
|
||||||
|
buf.push(b' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
let widget_id = self.state.tree.get_node_context(node_id).unwrap();
|
||||||
|
let layout = self.state.tree.layout(node_id).unwrap();
|
||||||
|
|
||||||
|
let widget = self.state.widgets.get(*widget_id).unwrap();
|
||||||
|
|
||||||
|
let state = widget.state();
|
||||||
|
|
||||||
|
let type_color = match state.obj.get_type() {
|
||||||
|
widget::WidgetType::Div => drawing::Color::new(1.0, 1.0, 1.0, 1.0),
|
||||||
|
widget::WidgetType::Label => drawing::Color::new(0.4, 1.0, 0.0, 1.0),
|
||||||
|
widget::WidgetType::Sprite => drawing::Color::new(0.0, 0.8, 1.0, 1.0),
|
||||||
|
widget::WidgetType::Rectangle => drawing::Color::new(1.0, 0.5, 0.2, 1.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
let line = format!(
|
||||||
|
"{}{}{}{}: [pos: {}x{}][size: {}x{}]{}\n",
|
||||||
|
ANSI_BOLD_CODE,
|
||||||
|
type_color.debug_ansi_format(),
|
||||||
|
state.obj.get_type().as_str(),
|
||||||
|
ANSI_RESET_CODE,
|
||||||
|
layout.location.x,
|
||||||
|
layout.location.y,
|
||||||
|
layout.content_size.width,
|
||||||
|
layout.content_size.height,
|
||||||
|
state.obj.debug_print()
|
||||||
|
);
|
||||||
|
|
||||||
|
buf.append(&mut line.into_bytes());
|
||||||
|
|
||||||
|
for child_id in self.state.tree.child_ids(node_id) {
|
||||||
|
self.print_tree_recur(buf, depth + 1, child_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutState {
|
impl LayoutState {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const DEFAULT_LINE_HEIGHT_RATIO: f32 = 1.43;
|
|||||||
pub(crate) const DEFAULT_METRICS: Metrics =
|
pub(crate) const DEFAULT_METRICS: Metrics =
|
||||||
Metrics::new(DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE * DEFAULT_LINE_HEIGHT_RATIO);
|
Metrics::new(DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE * DEFAULT_LINE_HEIGHT_RATIO);
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TextShadow {
|
pub struct TextShadow {
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
@@ -42,7 +42,7 @@ impl Default for TextShadow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct TextStyle {
|
pub struct TextStyle {
|
||||||
pub size: Option<f32>,
|
pub size: Option<f32>,
|
||||||
pub line_height: Option<f32>,
|
pub line_height: Option<f32>,
|
||||||
@@ -78,11 +78,7 @@ impl From<&TextStyle> for Metrics {
|
|||||||
|
|
||||||
impl From<&TextStyle> for Wrap {
|
impl From<&TextStyle> for Wrap {
|
||||||
fn from(value: &TextStyle) -> Self {
|
fn from(value: &TextStyle) -> Self {
|
||||||
if value.wrap {
|
if value.wrap { Self::WordOrGlyph } else { Self::None }
|
||||||
Self::WordOrGlyph
|
|
||||||
} else {
|
|
||||||
Self::None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,4 +26,12 @@ impl WidgetObj for WidgetDiv {
|
|||||||
fn set_id(&mut self, id: WidgetID) {
|
fn set_id(&mut self, id: WidgetID) {
|
||||||
self.id = id;
|
self.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_type(&self) -> super::WidgetType {
|
||||||
|
super::WidgetType::Div
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug_print(&self) -> String {
|
||||||
|
String::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{WidgetObj, WidgetState};
|
use super::{WidgetObj, WidgetState};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct WidgetLabelParams {
|
pub struct WidgetLabelParams {
|
||||||
pub content: Translation,
|
pub content: Translation,
|
||||||
pub style: TextStyle,
|
pub style: TextStyle,
|
||||||
@@ -160,4 +160,18 @@ impl WidgetObj for WidgetLabel {
|
|||||||
fn set_id(&mut self, id: WidgetID) {
|
fn set_id(&mut self, id: WidgetID) {
|
||||||
self.id = id;
|
self.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_type(&self) -> super::WidgetType {
|
||||||
|
super::WidgetType::Label
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug_print(&self) -> String {
|
||||||
|
let color = if let Some(color) = self.params.style.color {
|
||||||
|
format!("[color: {}]", color.debug_ansi_block())
|
||||||
|
} else {
|
||||||
|
String::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
format!("[text: \"{}\"]{}", self.params.content.text, color)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,10 +115,30 @@ pub struct DrawParams<'a> {
|
|||||||
pub taffy_layout: &'a taffy::Layout,
|
pub taffy_layout: &'a taffy::Layout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum WidgetType {
|
||||||
|
Div,
|
||||||
|
Label,
|
||||||
|
Sprite,
|
||||||
|
Rectangle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetType {
|
||||||
|
pub const fn as_str(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
WidgetType::Div => "div",
|
||||||
|
WidgetType::Label => "label",
|
||||||
|
WidgetType::Sprite => "sprite",
|
||||||
|
WidgetType::Rectangle => "rectangle",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait WidgetObj: AnyTrait {
|
pub trait WidgetObj: AnyTrait {
|
||||||
// every widget stores their of id for convenience reasons
|
// every widget stores their of id for convenience reasons
|
||||||
fn get_id(&self) -> WidgetID;
|
fn get_id(&self) -> WidgetID;
|
||||||
fn set_id(&mut self, id: WidgetID); // always set at insertion
|
fn set_id(&mut self, id: WidgetID); // always set at insertion
|
||||||
|
fn get_type(&self) -> WidgetType;
|
||||||
|
fn debug_print(&self) -> String;
|
||||||
|
|
||||||
fn draw(&mut self, state: &mut DrawState, params: &DrawParams);
|
fn draw(&mut self, state: &mut DrawState, params: &DrawParams);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{WidgetObj, WidgetState};
|
use super::{WidgetObj, WidgetState};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct WidgetRectangleParams {
|
pub struct WidgetRectangleParams {
|
||||||
pub color: drawing::Color,
|
pub color: drawing::Color,
|
||||||
pub color2: drawing::Color,
|
pub color2: drawing::Color,
|
||||||
@@ -66,4 +66,17 @@ impl WidgetObj for WidgetRectangle {
|
|||||||
fn set_id(&mut self, id: WidgetID) {
|
fn set_id(&mut self, id: WidgetID) {
|
||||||
self.id = id;
|
self.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_type(&self) -> super::WidgetType {
|
||||||
|
super::WidgetType::Rectangle
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug_print(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"[color: {}][color2: {}][gradient: {:?}]",
|
||||||
|
self.params.color.debug_ansi_block(),
|
||||||
|
self.params.color2.debug_ansi_block(),
|
||||||
|
self.params.gradient,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,4 +101,12 @@ impl WidgetObj for WidgetSprite {
|
|||||||
fn set_id(&mut self, id: WidgetID) {
|
fn set_id(&mut self, id: WidgetID) {
|
||||||
self.id = id;
|
self.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_type(&self) -> super::WidgetType {
|
||||||
|
super::WidgetType::Sprite
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debug_print(&self) -> String {
|
||||||
|
String::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user