Turtle Draw Layout System

Basic Concepts

The turtle layout system contains the following core concepts:

1pub struct Turtle {
2    // Current turtle position
3    walk: Walk,         // Layout behavior
4    layout: Layout,     // Layout rules
5    wrap_spacing: f64,  // Wrapping spacing
6    align_start: usize, // Alignment start position
7    defer_count: usize, // Defer count
8    shift: DVec2,      // Offset amount
9    pos: DVec2,        // Current position
10    origin: DVec2,     // Starting position
11    width: f64,        // Width
12    height: f64,       // Height
13    width_used: f64,   // Width consumed
14    height_used: f64,  // Height consumed
15}

Basic Drawing Process

1// Start a turtle layout
2cx.begin_turtle(walk, layout);
3
4// Drawing process example
5turtle.move_to(10.0, 10.0);  // Move to specified position
6turtle.line_to(100.0, 100.0); // Draw line to specified position
7turtle.rect(0.0, 0.0, 50.0, 30.0); // Draw rectangle
8
9// End layout
10cx.end_turtle();

Position Calculation Example

1impl Turtle {
2    // Calculate next position
3    pub fn next_pos(&mut self, size: DVec2) -> DVec2 {
4        match self.layout.flow {
5            Flow::Right => {
6                let pos = self.pos;
7                self.pos.x += size.x + self.layout.spacing;
8                self.width_used = self.width_used.max(self.pos.x);
9                pos
10            }
11            Flow::Down => {
12                let pos = self.pos;
13                self.pos.y += size.y + self.layout.spacing;
14                self.height_used = self.height_used.max(self.pos.y);
15                pos
16            }
17            // ... Handle other flow directions
18        }
19    }
20}

Complex Layout Examples

Nested Layouts

1MyView = <View> {
2    // Outer turtle
3    walk: {width: Fill, height: Fit},
4    layout: {flow: Down, spacing: 10},
5
6    // Inner turtle
7    <View> {
8        walk: {width: Fill, height: Fit},
9        layout: {
10            flow: Right,
11            spacing: 5,
12            padding: {left: 10, right: 10}
13        },
14
15        // Content components
16        <Button> {}
17        <Button> {}
18    }
19}

Defer Mechanism

When layout needs to wait for certain conditions to be met, it can use deferred layout:

1impl Turtle {
2    pub fn defer_walk(&mut self, walk: Walk) -> Option<DeferWalk> {
3        if walk.abs_pos.is_some() {
4            return None;
5        }
6
7        // Handle deferred layout logic
8        match self.layout.flow {
9            Flow::Right if walk.width.is_fill() => {
10                // Handle deferral in right-flowing layout
11                let spacing = self.child_spacing();
12                self.pos.x += spacing.x;
13                Some(DeferWalk::Unresolved{...})
14            }
15            // ... Handle other cases
16        }
17    }
18}

Turtle Layout Alignment System

Alignment Calculation

1pub struct AlignEntry {
2    align_range: TurtleAlignRange,
3    size: DVec2,
4    shift: f64,
5    index: usize
6}
7
8impl Cx2d {
9    pub fn align_items(&mut self) {
10        // Iterate through all items needing alignment
11        for item in &self.draw_align_list {
12            // Calculate alignment position
13            let shift = match self.layout.align {
14                Align::Center => {
15                    (self.width - item.size.x) * 0.5
16                },
17                // ... Handle other alignment types
18            };
19
20            // Apply alignment
21            self.shift_align_range(&item.align_range, shift);
22        }
23    }
24}

Practical Alignment Example

1CenteredContent = <View> {
2    layout: {
3        flow: Down,
4        align: {x: 0.5, y: 0.0}  // Horizontal center, top align
5    },
6
7    <Text> {
8        walk: {
9            width: Fit,
10            height: Fit
11        },
12        text: "Centered Text"
13    }
14}

Turtle Performance Optimization

Caching Mechanism

1pub struct DrawStateWrap<T: Clone> {
2    state: Option<T>,
3    redraw_id: u64,
4}
5
6impl<T: Clone> DrawStateWrap<T> {
7    pub fn begin(&mut self, cx: &mut Cx2d, init: T) -> bool {
8        if self.redraw_id != cx.redraw_id() {
9            // Only update state when necessary
10            self.redraw_id = cx.redraw_id();
11            self.state = Some(init);
12            true
13        } else {
14            false
15        }
16    }
17}