Merge pull request #1811 from ramox81/codex/txt2mtxt

TXT2MTXT: combine text into MText with a settings dialog

# Conflicts:
#	locales/ar-SA/opencadstudio.ftl
#	locales/bg-BG/opencadstudio.ftl
#	locales/cs-CZ/opencadstudio.ftl
#	locales/de-DE/opencadstudio.ftl
#	locales/el-GR/opencadstudio.ftl
#	locales/en-US/opencadstudio.ftl
#	locales/es-ES/opencadstudio.ftl
#	locales/fi-FI/opencadstudio.ftl
#	locales/fr-FR/opencadstudio.ftl
#	locales/hi-IN/opencadstudio.ftl
#	locales/hu-HU/opencadstudio.ftl
#	locales/it-IT/opencadstudio.ftl
#	locales/ja-JP/opencadstudio.ftl
#	locales/ko-KR/opencadstudio.ftl
#	locales/lo-LA/opencadstudio.ftl
#	locales/nl-NL/opencadstudio.ftl
#	locales/pl-PL/opencadstudio.ftl
#	locales/pt-BR/opencadstudio.ftl
#	locales/ru-RU/opencadstudio.ftl
#	locales/tr-TR/opencadstudio.ftl
#	locales/zh-CN/opencadstudio.ftl
#	locales/zh-TW/opencadstudio.ftl
This commit is contained in:
Hakan Seven committed 2026-10-15 16:47:19 +03:00
commit aa618b8327
40 files changed
+1222 -4

No files matched your search

+195
View File
@@ -101,6 +101,13 @@ pub enum PdfDialogMsg {
Lineweights(bool),
Linetypes(bool),
SettingsOk,
// Text to MText Settings (TXT2MTXT)
T2mCombine(bool),
/// Keep the selection order (else top-down).
T2mSelectOrder(bool),
T2mWrap(bool),
T2mUniform(bool),
T2mOk,
// Import PDF
ImportBrowse,
ImportPage(usize),
@@ -1261,6 +1268,194 @@ pub fn view_import_settings<'a>(
.into()
}
// ── Text to MText Settings (TXT2MTXT) ──────────────────────────────────────
/// A labelled switch; inactive (dimmed) while `on` is None.
fn t2m_switch<'a>(
label: String,
hint: String,
value: bool,
on: Option<fn(bool) -> PdfDialogMsg>,
) -> Element<'a, Message> {
let enabled = on.is_some();
let mut switch = iced::widget::toggler(value).size(18.0);
if let Some(on) = on {
switch = switch.on_toggle(move |v| msg(on(v)));
}
let dim = move |theme: &Theme| text::Style {
color: Some(theme.palette().background.strong.color),
};
let name = text(label).size(12);
let name = if enabled { name } else { name.style(dim) };
row![
switch,
name,
text(hint).size(11).style(if enabled { muted_style } else { dim }),
]
.spacing(8)
.align_y(iced::Center)
.into()
}
/// Top-down or selection order, as joined buttons; inactive without `enabled`.
fn t2m_order<'a>(select_order: bool, enabled: bool) -> Element<'a, Message> {
let choice = |value: bool, label: String| -> Element<'a, Message> {
let chosen = enabled && value == select_order;
button(text(label).size(11).width(Fill).align_x(iced::Center))
.on_press_maybe(enabled.then(|| msg(PdfDialogMsg::T2mSelectOrder(value))))
.style(move |theme: &Theme, status| {
let mut style = button_style(chosen)(theme, status);
if !enabled {
style.text_color = theme.palette().background.strong.color;
}
style
})
.padding([5, 6])
.width(Fill)
.into()
};
container(
row![
choice(false, crate::tr!("txt2mtxt", "top-down")),
choice(true, crate::tr!("txt2mtxt", "selection-order"))
]
.spacing(2),
)
.padding(2)
.width(Length::Fixed(300.0))
.style(well_style)
.into()
}
/// A text sample in a well, one line per entry.
fn t2m_sample<'a>(lines: Vec<String>, framed: bool, width: f32) -> Element<'a, Message> {
let body = iced::widget::Column::with_children(
lines
.into_iter()
.map(|l| text(l).size(12).font(iced::Font::MONOSPACE).into())
.collect::<Vec<_>>(),
)
.spacing(6);
let inner = container(body).padding([6, 8]).width(Fill);
let inner: Element<'a, Message> = if framed {
inner
.style(|theme: &Theme| container::Style {
border: Border {
width: 1.0,
radius: 2.0.into(),
color: theme.palette().primary.base.color,
},
..Default::default()
})
.into()
} else {
inner.into()
};
container(inner)
.padding(6)
.width(Length::Fixed(width))
.height(Length::Fixed(86.0))
.style(well_style)
.into()
}
pub fn view_txt2mtxt_settings<'a>(
s: &'a crate::app::settings::Txt2MtxtSettings,
sizing: crate::ui::modal::ModalSizing,
) -> Element<'a, Message> {
let result = card(
crate::tr!("txt2mtxt", "result"),
column![
t2m_switch(
crate::tr!("txt2mtxt", "combine"),
String::new(),
s.combine,
Some(PdfDialogMsg::T2mCombine),
),
column![
text(crate::tr!("txt2mtxt", "order")).size(11).style(muted_style),
t2m_order(s.select_order, s.combine),
]
.spacing(6)
.padding(iced::Padding::ZERO.left(44)),
text(crate::tr!("txt2mtxt", "combine-note"))
.size(11)
.style(muted_style),
]
.spacing(8),
);
let lines = card(
crate::tr!("txt2mtxt", "lines"),
column![
t2m_switch(
crate::tr!("txt2mtxt", "wrap"),
crate::tr!("txt2mtxt", "wrap-hint"),
s.word_wrap,
s.combine.then_some(PdfDialogMsg::T2mWrap as fn(bool) -> PdfDialogMsg),
),
t2m_switch(
crate::tr!("txt2mtxt", "uniform"),
crate::tr!("txt2mtxt", "uniform-hint"),
s.uniform_spacing || s.word_wrap,
(s.combine && !s.word_wrap)
.then_some(PdfDialogMsg::T2mUniform as fn(bool) -> PdfDialogMsg),
),
]
.spacing(10),
);
let sample: Vec<String> = ["First line", "Second line", "Third line"]
.into_iter()
.map(String::from)
.collect();
let (count, out) = if !s.combine {
(3, sample.clone())
} else if s.word_wrap {
(
1,
vec!["First line Second line Third".into(), "line".into()],
)
} else {
(1, sample.clone())
};
let preview = container(
row![
column![
text(crate::tr!("txt2mtxt", "selected")).size(11).style(muted_style),
t2m_sample(sample, false, 190.0)
]
.spacing(4),
text("→").size(20).style(accent_text),
column![
text(crate::tr!("txt2mtxt", "result-count", count = count))
.size(11)
.style(muted_style),
t2m_sample(out, true, 262.0)
]
.spacing(4),
]
.spacing(14)
.align_y(iced::Center),
)
.padding([10, 12])
.width(Fill)
.style(card_style);
column![
result,
lines,
preview,
footer(
"txt2mtxt",
None,
crate::tr!("txt2mtxt", "apply").into(),
PdfDialogMsg::T2mOk,
),
]
.spacing(10)
.padding([10, 12])
.width(sizing.width)
.into()
}
// ── Import PDF (File) ──────────────────────────────────────────────────────
pub struct PdfImportFileState {