use elicitation::elicit_tool;
use rmcp::ErrorData;
use rmcp::model::{CallToolResult, Content};
use schemars::JsonSchema;
use serde::Deserialize;
use tracing::instrument;
use crate::serde_types::{LayoutAlign, LayoutJson, Vec2Json};
fn layout_result(layout: &LayoutJson) -> CallToolResult {
match serde_json::to_string(layout) {
Ok(s) => CallToolResult::success(vec![Content::text(s)]),
Err(e) => CallToolResult::error(vec![Content::text(format!("serialize error: {e}"))]),
}
}
#[derive(Debug, Deserialize, JsonSchema)]
pub struct EmptyLayoutParams {}
#[derive(Debug, Deserialize, JsonSchema)]
pub struct HorizontalParams {
pub align: Option<LayoutAlign>,
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_horizontal",
description = "Arrange widgets horizontally. Returns LayoutJson::Horizontal."
)]
#[instrument(skip_all)]
async fn layout_horizontal(p: HorizontalParams) -> Result<CallToolResult, ErrorData> {
let l = LayoutJson::Horizontal { align: p.align };
Ok(layout_result(&l))
}
#[derive(Debug, Deserialize, JsonSchema)]
pub struct VerticalParams {
pub align: Option<LayoutAlign>,
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_vertical",
description = "Arrange widgets vertically. Returns LayoutJson::Vertical."
)]
#[instrument(skip_all)]
async fn layout_vertical(p: VerticalParams) -> Result<CallToolResult, ErrorData> {
let l = LayoutJson::Vertical { align: p.align };
Ok(layout_result(&l))
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_horizontal_centered",
description = "Horizontal layout with centred cross-axis. Returns LayoutJson::HorizontalCentered."
)]
#[instrument(skip_all)]
async fn layout_horizontal_centered(p: EmptyLayoutParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(layout_result(&LayoutJson::HorizontalCentered))
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_vertical_centered",
description = "Vertical layout with centred cross-axis. Returns LayoutJson::VerticalCentered.",
emit = None
)]
#[instrument(skip_all)]
async fn layout_vertical_centered(p: EmptyLayoutParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(layout_result(&LayoutJson::VerticalCentered))
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_horizontal_justified",
description = "Horizontal layout with justified items. Returns LayoutJson::HorizontalJustified.",
emit = None
)]
#[instrument(skip_all)]
async fn layout_horizontal_justified(p: EmptyLayoutParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(layout_result(&LayoutJson::HorizontalJustified))
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_vertical_justified",
description = "Vertical layout with justified items. Returns LayoutJson::VerticalJustified.",
emit = None
)]
#[instrument(skip_all)]
async fn layout_vertical_justified(p: EmptyLayoutParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(layout_result(&LayoutJson::VerticalJustified))
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_horizontal_wrapped",
description = "Horizontal layout that wraps to next line. Returns LayoutJson::HorizontalWrapped.",
emit = None
)]
#[instrument(skip_all)]
async fn layout_horizontal_wrapped(p: EmptyLayoutParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(layout_result(&LayoutJson::HorizontalWrapped))
}
#[derive(Debug, Deserialize, JsonSchema)]
pub struct ColumnsParams {
pub count: usize,
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_columns",
description = "Create a column-based layout. Returns LayoutJson::Columns."
)]
#[instrument(skip_all)]
async fn layout_columns(p: ColumnsParams) -> Result<CallToolResult, ErrorData> {
let l = LayoutJson::Columns { count: p.count };
Ok(layout_result(&l))
}
#[derive(Debug, Deserialize, JsonSchema)]
pub struct GridParams {
pub id: String,
pub num_columns: Option<usize>,
#[serde(default)]
pub striped: bool,
pub min_col_width: Option<f32>,
pub max_col_width: Option<f32>,
pub spacing: Option<Vec2Json>,
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_grid",
description = "Create a grid layout. Returns LayoutJson::Grid."
)]
#[instrument(skip_all)]
async fn layout_grid(p: GridParams) -> Result<CallToolResult, ErrorData> {
let l = LayoutJson::Grid {
id: p.id,
num_columns: p.num_columns,
striped: p.striped,
min_col_width: p.min_col_width,
max_col_width: p.max_col_width,
spacing: p.spacing,
};
Ok(layout_result(&l))
}
#[derive(Debug, Deserialize, JsonSchema)]
pub struct IndentParams {
pub indent: Option<f32>,
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_indent",
description = "Add indentation. Returns LayoutJson::Indent."
)]
#[instrument(skip_all)]
async fn layout_indent(p: IndentParams) -> Result<CallToolResult, ErrorData> {
let l = LayoutJson::Indent { indent: p.indent };
Ok(layout_result(&l))
}
#[derive(Debug, Deserialize, JsonSchema)]
pub struct AddSpaceParams {
pub amount: f32,
}
#[elicit_tool(
plugin = "egui_layout",
name = "layout_add_space",
description = "Add explicit spacing between widgets. Returns LayoutJson::AddSpace."
)]
#[instrument(skip_all)]
async fn layout_add_space(p: AddSpaceParams) -> Result<CallToolResult, ErrorData> {
let l = LayoutJson::AddSpace { amount: p.amount };
Ok(layout_result(&l))
}