Write the builder exports longhand
The macro saved four lines each but rustfmt de-indents macro bodies and leaves the doc comments at column 0. Longhand reads like the header does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d2c4134 parent: 18ec8fd modified
cosmic_ffi/src/lib.rs +92 -63 | @@ -171,39 +171,60 @@ macro_rules! builder { | ||
| 171 | 171 | }; |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | -macro_rules! builder_fn { | |
| 175 | - ($(#[$m:meta])* $name:ident ($b:ident $(, $arg:ident : $ty:ty)*) $body:block) => { | |
| 176 | - $(#[$m])* | |
| 177 | - #[no_mangle] | |
| 178 | - pub unsafe extern "C" fn $name(builder: *mut Builder $(, $arg: $ty)*) { | |
| 179 | - let $b = builder!(builder); | |
| 180 | - $body | |
| 181 | - } | |
| 182 | - }; | |
| 174 | +/// Open a vertical container. Close it with `cosmic_end`. Like every builder | |
| 175 | +/// export, a NULL handle makes it a no-op. | |
| 176 | +#[no_mangle] | |
| 177 | +pub unsafe extern "C" fn cosmic_column(b: *mut Builder) { | |
| 178 | + builder!(b).push(Kind::Column) | |
| 179 | +} | |
| 180 | + | |
| 181 | +/// Open a horizontal container. Close it with `cosmic_end`. | |
| 182 | +#[no_mangle] | |
| 183 | +pub unsafe extern "C" fn cosmic_row(b: *mut Builder) { | |
| 184 | + builder!(b).push(Kind::Row) | |
| 185 | +} | |
| 186 | + | |
| 187 | +/// Open a plain container. Close it with `cosmic_end`. | |
| 188 | +#[no_mangle] | |
| 189 | +pub unsafe extern "C" fn cosmic_container(b: *mut Builder) { | |
| 190 | + builder!(b).push(Kind::Container) | |
| 191 | +} | |
| 192 | + | |
| 193 | +/// Close the innermost open container. | |
| 194 | +#[no_mangle] | |
| 195 | +pub unsafe extern "C" fn cosmic_end(b: *mut Builder) { | |
| 196 | + builder!(b).pop() | |
| 197 | +} | |
| 198 | + | |
| 199 | +/// Gap between the open container's children, in pixels. | |
| 200 | +#[no_mangle] | |
| 201 | +pub unsafe extern "C" fn cosmic_spacing(b: *mut Builder, px: f32) { | |
| 202 | + builder!(b).top().spacing = px; | |
| 203 | +} | |
| 204 | + | |
| 205 | +/// Inset around the open container's children, in pixels. | |
| 206 | +#[no_mangle] | |
| 207 | +pub unsafe extern "C" fn cosmic_padding(b: *mut Builder, px: f32) { | |
| 208 | + builder!(b).top().padding = px; | |
| 183 | 209 | } |
| 184 | 210 | |
| 185 | -builder_fn!(/// Open a vertical container. Close it with `cosmic_end`. | |
| 186 | - cosmic_column(b) { b.push(Kind::Column) }); | |
| 187 | -builder_fn!(/// Open a horizontal container. Close it with `cosmic_end`. | |
| 188 | - cosmic_row(b) { b.push(Kind::Row) }); | |
| 189 | -builder_fn!(/// Open a plain container. Close it with `cosmic_end`. | |
| 190 | - cosmic_container(b) { b.push(Kind::Container) }); | |
| 191 | -builder_fn!(/// Close the innermost open container. | |
| 192 | - cosmic_end(b) { b.pop() }); | |
| 193 | - | |
| 194 | -builder_fn!(/// Gap between the open container's children, in pixels. | |
| 195 | - cosmic_spacing(b, px: f32) { b.top().spacing = px }); | |
| 196 | -builder_fn!(/// Inset around the open container's children, in pixels. | |
| 197 | - cosmic_padding(b, px: f32) { b.top().padding = px }); | |
| 198 | -builder_fn!(/// Centre the open container's children across its main axis. | |
| 199 | - cosmic_align_center(b) { b.top().align_center = true }); | |
| 200 | -builder_fn!(/// Let the open container take all the space it is offered. | |
| 201 | - cosmic_fill(b) { b.top().fill = true }); | |
| 202 | - | |
| 203 | -builder_fn!(/// A blank gap of `w` by `h` pixels. | |
| 204 | - cosmic_space(b, w: f32, h: f32) { | |
| 205 | - b.leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into()) | |
| 206 | - }); | |
| 211 | +/// Centre the open container's children across its main axis. | |
| 212 | +#[no_mangle] | |
| 213 | +pub unsafe extern "C" fn cosmic_align_center(b: *mut Builder) { | |
| 214 | + builder!(b).top().align_center = true; | |
| 215 | +} | |
| 216 | + | |
| 217 | +/// Let the open container take all the space it is offered. | |
| 218 | +#[no_mangle] | |
| 219 | +pub unsafe extern "C" fn cosmic_fill(b: *mut Builder) { | |
| 220 | + builder!(b).top().fill = true; | |
| 221 | +} | |
| 222 | + | |
| 223 | +/// A blank gap of `w` by `h` pixels. | |
| 224 | +#[no_mangle] | |
| 225 | +pub unsafe extern "C" fn cosmic_space(b: *mut Builder, w: f32, h: f32) { | |
| 226 | + builder!(b).leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into()) | |
| 227 | +} | |
| 207 | 228 | |
| 208 | 229 | /// Text styles for [`cosmic_text`], matching COSMIC's type scale. |
| 209 | 230 | pub const TEXT_BODY: i32 = 0; |
| @@ -215,20 +236,22 @@ pub const TEXT_HEADING: i32 = 5; | ||
| 215 | 236 | pub const TEXT_CAPTION: i32 = 6; |
| 216 | 237 | pub const TEXT_MONOTEXT: i32 = 7; |
| 217 | 238 | |
| 218 | -builder_fn!(/// A run of text in one of the `COSMIC_TEXT_*` styles. | |
| 219 | - cosmic_text(b, style: i32, text: *const c_char) { | |
| 220 | - let s = str_or(text, ""); | |
| 221 | - b.leaf(match style { | |
| 222 | - TEXT_TITLE1 => widget::text::title1(s).into(), | |
| 223 | - TEXT_TITLE2 => widget::text::title2(s).into(), | |
| 224 | - TEXT_TITLE3 => widget::text::title3(s).into(), | |
| 225 | - TEXT_TITLE4 => widget::text::title4(s).into(), | |
| 226 | - TEXT_HEADING => widget::text::heading(s).into(), | |
| 227 | - TEXT_CAPTION => widget::text::caption(s).into(), | |
| 228 | - TEXT_MONOTEXT => widget::text::monotext(s).into(), | |
| 229 | - _ => widget::text::body(s).into(), | |
| 230 | - }) | |
| 231 | - }); | |
| 239 | +/// A run of text in one of the `TEXT_*` styles. | |
| 240 | +#[no_mangle] | |
| 241 | +pub unsafe extern "C" fn cosmic_text(b: *mut Builder, style: i32, text: *const c_char) { | |
| 242 | + let b = builder!(b); | |
| 243 | + let s = str_or(text, ""); | |
| 244 | + b.leaf(match style { | |
| 245 | + TEXT_TITLE1 => widget::text::title1(s).into(), | |
| 246 | + TEXT_TITLE2 => widget::text::title2(s).into(), | |
| 247 | + TEXT_TITLE3 => widget::text::title3(s).into(), | |
| 248 | + TEXT_TITLE4 => widget::text::title4(s).into(), | |
| 249 | + TEXT_HEADING => widget::text::heading(s).into(), | |
| 250 | + TEXT_CAPTION => widget::text::caption(s).into(), | |
| 251 | + TEXT_MONOTEXT => widget::text::monotext(s).into(), | |
| 252 | + _ => widget::text::body(s).into(), | |
| 253 | + }) | |
| 254 | +} | |
| 232 | 255 | |
| 233 | 256 | /// Button styles for [`cosmic_button`]. |
| 234 | 257 | pub const BUTTON_STANDARD: i32 = 0; |
| @@ -237,23 +260,25 @@ pub const BUTTON_DESTRUCTIVE: i32 = 2; | ||
| 237 | 260 | pub const BUTTON_TEXT: i32 = 3; |
| 238 | 261 | pub const BUTTON_LINK: i32 = 4; |
| 239 | 262 | |
| 240 | -builder_fn!(/// A button that reports `id` to `on_press`. A negative `id` | |
| 241 | - /// makes it inert, which is how a disabled button is expressed. | |
| 242 | - cosmic_button(b, style: i32, label: *const c_char, id: i32) { | |
| 243 | - let s = str_or(label, ""); | |
| 244 | - let button = match style { | |
| 245 | - BUTTON_SUGGESTED => widget::button::suggested(s), | |
| 246 | - BUTTON_DESTRUCTIVE => widget::button::destructive(s), | |
| 247 | - BUTTON_TEXT => widget::button::text(s), | |
| 248 | - BUTTON_LINK => widget::button::link(s), | |
| 249 | - _ => widget::button::standard(s), | |
| 250 | - }; | |
| 251 | - b.leaf(if id < 0 { | |
| 252 | - button.into() | |
| 253 | - } else { | |
| 254 | - button.on_press(Message::Pressed(id)).into() | |
| 255 | - }) | |
| 256 | - }); | |
| 263 | +/// A button that reports `id` to `on_press`. A negative `id` makes it inert, | |
| 264 | +/// which is how a disabled button is expressed. | |
| 265 | +#[no_mangle] | |
| 266 | +pub unsafe extern "C" fn cosmic_button(b: *mut Builder, style: i32, label: *const c_char, id: i32) { | |
| 267 | + let b = builder!(b); | |
| 268 | + let s = str_or(label, ""); | |
| 269 | + let button = match style { | |
| 270 | + BUTTON_SUGGESTED => widget::button::suggested(s), | |
| 271 | + BUTTON_DESTRUCTIVE => widget::button::destructive(s), | |
| 272 | + BUTTON_TEXT => widget::button::text(s), | |
| 273 | + BUTTON_LINK => widget::button::link(s), | |
| 274 | + _ => widget::button::standard(s), | |
| 275 | + }; | |
| 276 | + b.leaf(if id < 0 { | |
| 277 | + button.into() | |
| 278 | + } else { | |
| 279 | + button.on_press(Message::Pressed(id)).into() | |
| 280 | + }) | |
| 281 | +} | |
| 257 | 282 | |
| 258 | 283 | /// Spacing steps for [`cosmic_space_unit`]. |
| 259 | 284 | pub const SPACE_NONE: i32 = 0; |
| @@ -387,7 +412,11 @@ pub unsafe extern "C" fn cosmic_run(config: *const CosmicConfig) -> i32 { | ||
| 387 | 412 | |
| 388 | 413 | let size = cosmic::iced::Size::new( |
| 389 | 414 | if c.width == 0 { 420.0 } else { c.width as f32 }, |
| 390 | - if c.height == 0 { 260.0 } else { c.height as f32 }, | |
| 415 | + if c.height == 0 { | |
| 416 | + 260.0 | |
| 417 | + } else { | |
| 418 | + c.height as f32 | |
| 419 | + }, | |
| 391 | 420 | ); |
| 392 | 421 | let settings = cosmic::app::Settings::default().size(size).debug(false); |
| 393 | 422 | |
| @@ -171,39 +171,60 @@ macro_rules! builder { | |||
| 171 | }; | 171 | }; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | -macro_rules! builder_fn { | 174 | +/// Open a vertical container. Close it with `cosmic_end`. Like every builder |
| 175 | - ($(#[$m:meta])* $name:ident ($b:ident $(, $arg:ident : $ty:ty)*) $body:block) => { | 175 | +/// export, a NULL handle makes it a no-op. |
| 176 | - $(#[$m])* | 176 | +#[no_mangle] |
| 177 | - #[no_mangle] | 177 | +pub unsafe extern "C" fn cosmic_column(b: *mut Builder) { |
| 178 | - pub unsafe extern "C" fn $name(builder: *mut Builder $(, $arg: $ty)*) { | 178 | + builder!(b).push(Kind::Column) |
| 179 | - let $b = builder!(builder); | 179 | +} |
| 180 | - $body | 180 | + |
| 181 | - } | 181 | +/// Open a horizontal container. Close it with `cosmic_end`. |
| 182 | - }; | 182 | +#[no_mangle] |
| 183 | +pub unsafe extern "C" fn cosmic_row(b: *mut Builder) { | ||
| 184 | + builder!(b).push(Kind::Row) | ||
| 185 | +} | ||
| 186 | + | ||
| 187 | +/// Open a plain container. Close it with `cosmic_end`. | ||
| 188 | +#[no_mangle] | ||
| 189 | +pub unsafe extern "C" fn cosmic_container(b: *mut Builder) { | ||
| 190 | + builder!(b).push(Kind::Container) | ||
| 191 | +} | ||
| 192 | + | ||
| 193 | +/// Close the innermost open container. | ||
| 194 | +#[no_mangle] | ||
| 195 | +pub unsafe extern "C" fn cosmic_end(b: *mut Builder) { | ||
| 196 | + builder!(b).pop() | ||
| 197 | +} | ||
| 198 | + | ||
| 199 | +/// Gap between the open container's children, in pixels. | ||
| 200 | +#[no_mangle] | ||
| 201 | +pub unsafe extern "C" fn cosmic_spacing(b: *mut Builder, px: f32) { | ||
| 202 | + builder!(b).top().spacing = px; | ||
| 203 | +} | ||
| 204 | + | ||
| 205 | +/// Inset around the open container's children, in pixels. | ||
| 206 | +#[no_mangle] | ||
| 207 | +pub unsafe extern "C" fn cosmic_padding(b: *mut Builder, px: f32) { | ||
| 208 | + builder!(b).top().padding = px; | ||
| 183 | } | 209 | } |
| 184 | 210 | ||
| 185 | -builder_fn!(/// Open a vertical container. Close it with `cosmic_end`. | 211 | +/// Centre the open container's children across its main axis. |
| 186 | - cosmic_column(b) { b.push(Kind::Column) }); | 212 | +#[no_mangle] |
| 187 | -builder_fn!(/// Open a horizontal container. Close it with `cosmic_end`. | 213 | +pub unsafe extern "C" fn cosmic_align_center(b: *mut Builder) { |
| 188 | - cosmic_row(b) { b.push(Kind::Row) }); | 214 | + builder!(b).top().align_center = true; |
| 189 | -builder_fn!(/// Open a plain container. Close it with `cosmic_end`. | 215 | +} |
| 190 | - cosmic_container(b) { b.push(Kind::Container) }); | 216 | + |
| 191 | -builder_fn!(/// Close the innermost open container. | 217 | +/// Let the open container take all the space it is offered. |
| 192 | - cosmic_end(b) { b.pop() }); | 218 | +#[no_mangle] |
| 193 | - | 219 | +pub unsafe extern "C" fn cosmic_fill(b: *mut Builder) { |
| 194 | -builder_fn!(/// Gap between the open container's children, in pixels. | 220 | + builder!(b).top().fill = true; |
| 195 | - cosmic_spacing(b, px: f32) { b.top().spacing = px }); | 221 | +} |
| 196 | -builder_fn!(/// Inset around the open container's children, in pixels. | 222 | + |
| 197 | - cosmic_padding(b, px: f32) { b.top().padding = px }); | 223 | +/// A blank gap of `w` by `h` pixels. |
| 198 | -builder_fn!(/// Centre the open container's children across its main axis. | 224 | +#[no_mangle] |
| 199 | - cosmic_align_center(b) { b.top().align_center = true }); | 225 | +pub unsafe extern "C" fn cosmic_space(b: *mut Builder, w: f32, h: f32) { |
| 200 | -builder_fn!(/// Let the open container take all the space it is offered. | 226 | + builder!(b).leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into()) |
| 201 | - cosmic_fill(b) { b.top().fill = true }); | 227 | +} |
| 202 | - | ||
| 203 | -builder_fn!(/// A blank gap of `w` by `h` pixels. | ||
| 204 | - cosmic_space(b, w: f32, h: f32) { | ||
| 205 | - b.leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into()) | ||
| 206 | - }); | ||
| 207 | 228 | ||
| 208 | /// Text styles for [`cosmic_text`], matching COSMIC's type scale. | 229 | /// Text styles for [`cosmic_text`], matching COSMIC's type scale. |
| 209 | pub const TEXT_BODY: i32 = 0; | 230 | pub const TEXT_BODY: i32 = 0; |
| @@ -215,20 +236,22 @@ pub const TEXT_HEADING: i32 = 5; | |||
| 215 | pub const TEXT_CAPTION: i32 = 6; | 236 | pub const TEXT_CAPTION: i32 = 6; |
| 216 | pub const TEXT_MONOTEXT: i32 = 7; | 237 | pub const TEXT_MONOTEXT: i32 = 7; |
| 217 | 238 | ||
| 218 | -builder_fn!(/// A run of text in one of the `COSMIC_TEXT_*` styles. | 239 | +/// A run of text in one of the `TEXT_*` styles. |
| 219 | - cosmic_text(b, style: i32, text: *const c_char) { | 240 | +#[no_mangle] |
| 220 | - let s = str_or(text, ""); | 241 | +pub unsafe extern "C" fn cosmic_text(b: *mut Builder, style: i32, text: *const c_char) { |
| 221 | - b.leaf(match style { | 242 | + let b = builder!(b); |
| 222 | - TEXT_TITLE1 => widget::text::title1(s).into(), | 243 | + let s = str_or(text, ""); |
| 223 | - TEXT_TITLE2 => widget::text::title2(s).into(), | 244 | + b.leaf(match style { |
| 224 | - TEXT_TITLE3 => widget::text::title3(s).into(), | 245 | + TEXT_TITLE1 => widget::text::title1(s).into(), |
| 225 | - TEXT_TITLE4 => widget::text::title4(s).into(), | 246 | + TEXT_TITLE2 => widget::text::title2(s).into(), |
| 226 | - TEXT_HEADING => widget::text::heading(s).into(), | 247 | + TEXT_TITLE3 => widget::text::title3(s).into(), |
| 227 | - TEXT_CAPTION => widget::text::caption(s).into(), | 248 | + TEXT_TITLE4 => widget::text::title4(s).into(), |
| 228 | - TEXT_MONOTEXT => widget::text::monotext(s).into(), | 249 | + TEXT_HEADING => widget::text::heading(s).into(), |
| 229 | - _ => widget::text::body(s).into(), | 250 | + TEXT_CAPTION => widget::text::caption(s).into(), |
| 230 | - }) | 251 | + TEXT_MONOTEXT => widget::text::monotext(s).into(), |
| 231 | - }); | 252 | + _ => widget::text::body(s).into(), |
| 253 | + }) | ||
| 254 | +} | ||
| 232 | 255 | ||
| 233 | /// Button styles for [`cosmic_button`]. | 256 | /// Button styles for [`cosmic_button`]. |
| 234 | pub const BUTTON_STANDARD: i32 = 0; | 257 | pub const BUTTON_STANDARD: i32 = 0; |
| @@ -237,23 +260,25 @@ pub const BUTTON_DESTRUCTIVE: i32 = 2; | |||
| 237 | pub const BUTTON_TEXT: i32 = 3; | 260 | pub const BUTTON_TEXT: i32 = 3; |
| 238 | pub const BUTTON_LINK: i32 = 4; | 261 | pub const BUTTON_LINK: i32 = 4; |
| 239 | 262 | ||
| 240 | -builder_fn!(/// A button that reports `id` to `on_press`. A negative `id` | 263 | +/// A button that reports `id` to `on_press`. A negative `id` makes it inert, |
| 241 | - /// makes it inert, which is how a disabled button is expressed. | 264 | +/// which is how a disabled button is expressed. |
| 242 | - cosmic_button(b, style: i32, label: *const c_char, id: i32) { | 265 | +#[no_mangle] |
| 243 | - let s = str_or(label, ""); | 266 | +pub unsafe extern "C" fn cosmic_button(b: *mut Builder, style: i32, label: *const c_char, id: i32) { |
| 244 | - let button = match style { | 267 | + let b = builder!(b); |
| 245 | - BUTTON_SUGGESTED => widget::button::suggested(s), | 268 | + let s = str_or(label, ""); |
| 246 | - BUTTON_DESTRUCTIVE => widget::button::destructive(s), | 269 | + let button = match style { |
| 247 | - BUTTON_TEXT => widget::button::text(s), | 270 | + BUTTON_SUGGESTED => widget::button::suggested(s), |
| 248 | - BUTTON_LINK => widget::button::link(s), | 271 | + BUTTON_DESTRUCTIVE => widget::button::destructive(s), |
| 249 | - _ => widget::button::standard(s), | 272 | + BUTTON_TEXT => widget::button::text(s), |
| 250 | - }; | 273 | + BUTTON_LINK => widget::button::link(s), |
| 251 | - b.leaf(if id < 0 { | 274 | + _ => widget::button::standard(s), |
| 252 | - button.into() | 275 | + }; |
| 253 | - } else { | 276 | + b.leaf(if id < 0 { |
| 254 | - button.on_press(Message::Pressed(id)).into() | 277 | + button.into() |
| 255 | - }) | 278 | + } else { |
| 256 | - }); | 279 | + button.on_press(Message::Pressed(id)).into() |
| 280 | + }) | ||
| 281 | +} | ||
| 257 | 282 | ||
| 258 | /// Spacing steps for [`cosmic_space_unit`]. | 283 | /// Spacing steps for [`cosmic_space_unit`]. |
| 259 | pub const SPACE_NONE: i32 = 0; | 284 | pub const SPACE_NONE: i32 = 0; |
| @@ -387,7 +412,11 @@ pub unsafe extern "C" fn cosmic_run(config: *const CosmicConfig) -> i32 { | |||
| 387 | 412 | ||
| 388 | let size = cosmic::iced::Size::new( | 413 | let size = cosmic::iced::Size::new( |
| 389 | if c.width == 0 { 420.0 } else { c.width as f32 }, | 414 | if c.width == 0 { 420.0 } else { c.width as f32 }, |
| 390 | - if c.height == 0 { 260.0 } else { c.height as f32 }, | 415 | + if c.height == 0 { |
| 416 | + 260.0 | ||
| 417 | + } else { | ||
| 418 | + c.height as f32 | ||
| 419 | + }, | ||
| 391 | ); | 420 | ); |
| 392 | let settings = cosmic::app::Settings::default().size(size).debug(false); | 421 | let settings = cosmic::app::Settings::default().size(size).debug(false); |
| 393 | 422 | ||