Makepad Patterns logo

Makepad Patterns

Visit

Reusable patterns for Makepad widget development, data management, and async architecture. Covers modal overlays, state machines, async loading, and Tokio integration.

Share:

Makepad Patterns

Proven patterns for building robust Makepad applications.

Quick Navigation

Category Description
Widget Patterns Extension traits, modals, collapsibles, lists
Data Patterns Async loading, streaming, state machines
Advanced Patterns Tokio integration, tooltips, theme switching

Widget Extension Pattern

pub trait ButtonExt {
    fn set_enabled(&mut self, cx: &mut Cx, enabled: bool);
}

impl ButtonExt for Button {
    fn set_enabled(&mut self, cx: &mut Cx, enabled: bool) {
        if enabled {
            self.animator_play(cx, id!(hover.off));
        } else {
            self.animator_play(cx, id!(disabled.on));
        }
    }
}
live_design! {
    <View> {
        // Main content
        <Button> { text: "Show Modal" }

        // Modal overlay (initially hidden)
        modal_overlay = <View> {
            visible: false
            abs_pos: vec2(0, 0)
            width: Fill, height: Fill

            draw_bg: { color: #00000080 }

            <View> {
                // Modal content
                width: 400, height: 300
                <Label> { text: "Modal Content" }
            }
        }
    }
}

Async Loading Pattern

pub enum LoadState<T> {
    Loading,
    Loaded(T),
    Error(String),
}

impl Widget for MyWidget {
    fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
        match &self.load_state {
            LoadState::Loading => {
                // Show loading spinner
            }
            LoadState::Loaded(data) => {
                // Render data
            }
            LoadState::Error(msg) => {
                // Show error
            }
        }
    }
}

State Machine Pattern

#[derive(Clone, Debug, PartialEq)]
pub enum ViewState {
    List,
    Detail(String),
    Edit(String),
    Loading,
}

impl MyView {
    fn transition_to(&mut self, cx: &mut Cx, new_state: ViewState) {
        self.state = new_state;
        self.redraw(cx);
    }
}

Tokio Integration Pattern

// In main.rs
fn main() {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    let _guard = runtime.enter();

    makepad_widgets::live_design(live_design);
    makepad_widgets::makepad_platform::event_loop::event_loop(|cx, event| {
        // Event handling
    });
}

// In widget
fn fetch_data(&mut self, cx: &mut Cx) {
    let sender = cx.get_sender();
    tokio::spawn(async move {
        let data = fetch_from_api().await;
        sender.send(DataLoadedEvent(data));
    });
}

Theme Switching Pattern

live_design! {
    THEME_LIGHT = {
        bg_color: #FFFFFF
        text_color: #000000
    }

    THEME_DARK = {
        bg_color: #1E1E1E
        text_color: #FFFFFF
    }

    <View> {
        theme: $(THEME_LIGHT)
        draw_bg: { color: (theme.bg_color) }
    }
}

Pattern Selection Guide

For UI State

  • Simple toggle → Instance variables
  • Multiple states → State Machine pattern
  • Mutually exclusive → Radio Navigation pattern

For Data

  • One-time fetch → Async Loading pattern
  • Incremental display → Streaming Results pattern
  • Persist settings → Local Persistence pattern

For Performance

  • Large lists → List Template pattern
  • Heavy views → LRU View Cache pattern
  • Background work → Tokio Integration pattern

Resources

  • Robrix - Matrix chat client
  • Moly - AI model manager

Comments

No comments yet. Be the first to comment!