Merge pull request #1549 from MarcelP102/codex/graphic-attributes-cleanup

[UX] Introducing graphic attributes panel

# 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
#	src/app/mod.rs
#	src/app/update/dialog.rs
#	src/app/view/mod.rs
#	src/locale_catalog.rs
#	src/ui/dock.rs
This commit is contained in:
Hakan Seven committed 2026-10-12 00:49:27 +03:00
commit 1333efcad2
68 files changed
+6178 -173

No files matched your search

+56 -27
View File
@@ -99,6 +99,7 @@ mod context_menu;
mod dialog;
mod dynamic;
mod file;
mod graphic_attributes;
pub(in crate::app) use file::background_task;
#[cfg(not(target_arch = "wasm32"))]
pub(in crate::app) use file::native_paths_match;
@@ -473,6 +474,10 @@ impl OpenCADStudio {
}
}
self.refresh_gpu_status();
if self.graphic_attributes.tracks_selection() {
let selected = self.tabs[self.active_tab].scene.selected_handles_in_order();
self.graphic_attributes.retain_selection(&selected);
}
self.show_next_startup_modal();
self.sync_open_command_history();
// Close the document-level first-touch transaction started by
@@ -486,6 +491,7 @@ impl OpenCADStudio {
.active_cmd
.as_ref()
.map(|c| c.prompt())
.or_else(|| self.graphic_attributes.fill_close_prompt())
.or_else(|| self.pending_pick_label());
self.command_line.set_step_prompt(prompt);
// Mirror the step's clickable options so they render as buttons (#304).
@@ -493,6 +499,14 @@ impl OpenCADStudio {
.active_cmd
.as_ref()
.map(|c| c.options())
.or_else(|| {
self.graphic_attributes.pending_fill_close.as_ref().map(|_| {
vec![
crate::command::CmdOption::new("Yes", "Y"),
crate::command::CmdOption::new("No", "N"),
]
})
})
.unwrap_or_default();
self.command_line.set_step_options(opts);
// Persist UI preferences whenever a toggle changes them (issue #68).
@@ -2535,6 +2549,9 @@ impl OpenCADStudio {
// finishes the step like Enter. (#304)
self.command_line.input.clear();
self.command_line.close_history();
if self.awaiting_fill_close_answer() {
return self.on_graphic_fill_close_input(&kw);
}
if kw.is_empty() {
return self.feed_command(crate::command::StepInput::Enter);
}
@@ -3877,6 +3894,7 @@ impl OpenCADStudio {
}
Message::ViewportLeftPress => {
self.graphic_attributes.open_menu = None;
let sweep = self.sync_active_field_if_any();
Task::batch(vec![sweep, self.on_viewport_left_press()])
}
@@ -3884,6 +3902,7 @@ impl OpenCADStudio {
Message::ViewportLeftRelease => self.on_viewport_left_release(),
Message::ViewportRightPress => {
self.graphic_attributes.open_menu = None;
let i = self.active_tab;
self.ribbon.close_dropdown();
// Shift+RMB: the one-shot snap override menu at the cursor —
@@ -3986,7 +4005,10 @@ impl OpenCADStudio {
self.unfocus_widgets()
}
Message::ViewportMiddlePress => self.on_viewport_middle_press(),
Message::ViewportMiddlePress => {
self.graphic_attributes.open_menu = None;
self.on_viewport_middle_press()
}
Message::ViewportMiddleRelease => {
let i = self.active_tab;
@@ -4318,6 +4340,14 @@ impl OpenCADStudio {
self.ribbon.set_properties(self.show_properties);
Task::none()
}
Message::ToggleGraphicAttributes => {
let id = crate::ui::dock::PanelId::GraphicAttributes;
let open = !self.show_graphic_attributes;
if open {
self.dock.dock_below_properties(id);
}
self.dock_set_open(id, open)
}
Message::ToggleFileTabs => {
self.show_file_tabs ^= true;
self.ribbon.set_file_tabs(self.show_file_tabs);
@@ -6697,31 +6727,7 @@ impl OpenCADStudio {
Task::none()
}
Message::RibbonLinetypeChanged(lt) => self.on_ribbon_linetype_changed(lt),
Message::RibbonLineweightChanged(lw) => {
let i = self.active_tab;
self.ribbon.close_dropdown();
let handles = self.property_target_handles(i);
if handles.is_empty() {
if self.has_property_selection(i) {
return Task::none();
}
// Persist into the tab's header (CELWEIGHT). #21.
self.tabs[i].scene.document.header.current_line_weight = lw.value();
self.tabs[i].dirty = true;
self.ribbon.active_lineweight = lw;
} else {
// Lineweight is baked into the cached wire geometry —
// re-tessellate so the change shows immediately (issue #231
// class).
self.apply_property_op(i, "CHPROP", &handles, |app, handle| {
if let Some(entity) = app.tabs[i].scene.document.get_entity_mut(handle) {
crate::scene::view::dispatch::apply_line_weight(entity, lw);
}
});
self.ribbon.active_lineweight = lw;
}
Task::none()
}
Message::RibbonLineweightChanged(lw) => self.on_ribbon_lineweight_changed(lw),
Message::RibbonStyleChanged { key, name } => self.on_ribbon_style_changed(key, name),
@@ -7132,13 +7138,28 @@ impl OpenCADStudio {
Message::PropAttrCommit(tag) => self.on_prop_attr_commit(tag),
Message::PropPointerPressed => {
if !self.dock_panel_visible(crate::ui::dock::PanelId::Properties) {
if !self.dock_panel_visible(crate::ui::dock::PanelId::Properties)
&& !self.dock_panel_visible(crate::ui::dock::PanelId::GraphicAttributes)
{
return Task::none();
}
crate::ui::properties::sync_active_field_task()
}
Message::PropSyncActive(focused) => {
// The Graphic Attributes linetype scale field behaves like a
// Properties field: the first click selects its value.
let scale_field = iced::widget::Id::new(
crate::ui::window::graphic_attributes::LINETYPE_SCALE_FIELD,
);
if focused.as_ref() == Some(&scale_field) {
if !std::mem::replace(&mut self.graphic_attributes.linetype_scale_focused, true) {
return iced::widget::operation::select_all(scale_field);
}
return Task::none();
}
self.graphic_attributes.linetype_scale_focused = false;
self.graphic_attributes.linetype_scale_input = None;
let panel = &mut self.tabs[self.active_tab].properties;
if let Some(id) = focused.as_ref() {
if let Some(key) = panel.prop_field_key_for_id(id) {
@@ -9853,6 +9874,7 @@ impl OpenCADStudio {
Message::PlotDialogOpen => self.on_plot_dialog_open(),
Message::PlotDlg(m) => self.on_plot_dlg(m),
Message::BlockPalette(m) => self.on_block_palette(m),
Message::GraphicAttributes(m) => self.on_graphic_attributes(m),
Message::Dock(m) => self.on_dock(m),
Message::PrintAllOpen => self.on_print_all_open(),
Message::PrintAllToggle(name) => {
@@ -11015,6 +11037,13 @@ impl OpenCADStudio {
Task::none()
}
Message::OpenColorWindow(target, color) => {
if matches!(
target,
crate::app::ColorPickTarget::GraphicAttributesLine
| crate::app::ColorPickTarget::GraphicAttributesSolid
) {
self.graphic_attributes.open_menu = None;
}
self.color_pick_target = Some((target, color));
// Always open the shared CAD colour picker on the indexed ACI page.