Add Iced panel adapter and AI chat/script panels

- Implemented a theme system in `iced-panel-adapter` for consistent styling across panels.
- Created `iced-panel-ai-chat` for an AI assistant interface, including message handling and UI components.
- Developed `iced-panel-script` for a DSL editor with execution capabilities, allowing procedural drawing commands.
- Introduced message types for interaction in both chat and script panels.
- Added color and theme management for improved visual consistency.
This commit is contained in:
2026-07-11 18:13:03 +03:00
parent 0d1b0eae4c
commit f4ad22b55b
113 changed files with 8604 additions and 141 deletions
@@ -0,0 +1,88 @@
//! Confirm dialog — save/discard/cancel confirmation.
use crate::app::Message;
use iced::widget::{button, column, container, horizontal_rule, row, slider, text};
use iced::{Element, Length};
/// Build a confirmation dialog with save/discard/cancel.
pub fn close_confirm_view(doc_name: &str) -> Element<'static, Message> {
let msg = format!("\"{}\" has unsaved changes.", doc_name);
let save_btn = button(text("Save").size(12))
.on_press(Message::DialogCloseSave)
.padding([8, 16]);
let discard_btn = button(text("Discard").size(12))
.on_press(Message::DialogCloseDiscard)
.padding([8, 16]);
let cancel_btn = button(text("Cancel").size(12))
.on_press(Message::DialogClose)
.padding([8, 16]);
let dialog = column![
text("Unsaved Changes").size(16).font(iced::Font::MONOSPACE),
horizontal_rule(1),
text(msg).size(12),
horizontal_rule(1),
row![save_btn, discard_btn, cancel_btn].spacing(12),
]
.spacing(8)
.padding(16)
.width(400);
container(dialog)
.center_x(Length::Fill)
.center_y(Length::Fill)
.style(|_theme| iced::widget::container::Style {
background: Some(iced::Background::Color(iced::Color::from_rgba(0.0, 0.0, 0.0, 0.5))),
..Default::default()
})
.width(Length::Fill)
.height(Length::Fill)
.into()
}
/// Build a selection operation dialog (grow/shrink/feather).
pub fn selection_op_view(
op_name: &str,
value: f32,
min: f32,
max: f32,
) -> Element<'static, Message> {
let op_owned = op_name.to_string();
let value_slider = slider(min..=max, value, |v| Message::SelectionOpValue(v))
.step(1.0)
.width(Length::Fill);
let apply_btn = button(text("Apply").size(11))
.on_press(Message::SelectionOpApply)
.padding([6, 12]);
let cancel_btn = button(text("Cancel").size(11))
.on_press(Message::DialogClose)
.padding([6, 12]);
let dialog = column![
text(op_owned).size(14).font(iced::Font::MONOSPACE),
horizontal_rule(1),
text(format!("Value: {:.0}", value)).size(11),
value_slider,
horizontal_rule(1),
row![apply_btn, cancel_btn].spacing(12),
]
.spacing(8)
.padding(16)
.width(350);
container(dialog)
.center_x(Length::Fill)
.center_y(Length::Fill)
.style(|_theme| iced::widget::container::Style {
background: Some(iced::Background::Color(iced::Color::from_rgba(0.0, 0.0, 0.0, 0.5))),
..Default::default()
})
.width(Length::Fill)
.height(Length::Fill)
.into()
}