Merge PR #1110: expose selection settings

# Conflicts:
#	src/app/mod.rs
#	src/app/properties.rs
#	src/app/settings.rs
#	src/app/update/file.rs
#	src/app/view/modal.rs
#	src/ui/window/options.rs
This commit is contained in:
Hakan Seven committed 2026-09-09 14:40:37 +03:00
commit 9fe6033304
34 files changed
+616 -34

No files matched your search

+2
View File
@@ -367,6 +367,7 @@ impl OpenCADStudio {
pick_box: self.pick_box,
double_click_block_refedit: self.double_click_block_refedit,
double_click_block_attedit: self.double_click_block_attedit,
grip_object_limit: self.grip_object_limit,
cursor_type: self.cursor_type,
crosshair_color: self.crosshair_color,
lineweight_display_scale: self.lineweight_display_scale,
@@ -422,6 +423,7 @@ impl OpenCADStudio {
self.pick_box = s.pick_box.clamp(0, 50);
self.double_click_block_refedit = s.double_click_block_refedit;
self.double_click_block_attedit = s.double_click_block_attedit;
self.grip_object_limit = s.grip_object_limit.clamp(0, 32767);
self.cursor_type = s.cursor_type;
self.crosshair_color = s.crosshair_color;
self.crosshair_color_input = s
+55
View File
@@ -6137,6 +6137,48 @@ impl OpenCADStudio {
Task::none()
}
Message::GripObjectLimitChanged(limit) => {
self.grip_object_limit = limit.clamp(0, 32767);
self.persist_settings_if_changed();
Task::none()
}
Message::SelectionEffectToggled(enabled) => {
self.model_space.selection_effect = enabled;
self.sync_model_space_theme(false);
self.persist_settings_if_changed();
Task::none()
}
// SELECTIONPREVIEW is a bitmask and the two checkboxes own one bit
// each: 1 = rollover while idle, 2 = rollover during a command.
Message::SelectionPreviewIdleToggled(enabled) => {
self.model_space.selection_preview =
set_preview_bit(self.model_space.selection_preview, 1, enabled);
self.persist_settings_if_changed();
Task::none()
}
Message::SelectionPreviewCommandToggled(enabled) => {
self.model_space.selection_preview =
set_preview_bit(self.model_space.selection_preview, 2, enabled);
self.persist_settings_if_changed();
Task::none()
}
// "Use Shift to add" is the inverse of PICKADD.
Message::ShiftToAddToggled(shift_to_add) => {
self.pick_add = !shift_to_add;
self.persist_settings_if_changed();
Task::none()
}
Message::PickDragRectToggled(rectangle) => {
self.pick_drag_rect = rectangle;
self.persist_settings_if_changed();
Task::none()
}
Message::RestoreSelectionVisualDefaults => {
self.model_space.selection_area = true;
self.model_space.selection_opacity = 12;
@@ -6149,6 +6191,10 @@ impl OpenCADStudio {
self.model_space.grip_color = 0;
self.model_space.grip_hot = 0;
self.model_space.grip_hover = 0;
// The button restores the *visual* defaults, which is why the
// grip limit is here and PICKADD / PICKDRAG are not — those are
// how selection behaves, not how it looks.
self.grip_object_limit = crate::app::settings::DEFAULT_GRIP_OBJECT_LIMIT;
self.sync_model_space_theme(false);
self.persist_settings_if_changed();
Task::none()
@@ -8661,3 +8707,12 @@ mod free_text_entry_tests {
assert_eq!(app.text_entry_mode(), TextEntryMode::Command);
}
}
/// Set or clear one bit of `SELECTIONPREVIEW`.
fn set_preview_bit(current: u8, bit: u8, enabled: bool) -> u8 {
if enabled {
current | bit
} else {
current & !bit
}
}
+54
View File
@@ -5778,3 +5778,57 @@ properties={:.1}ms picked={}",
Task::none()
}
}
#[cfg(test)]
mod selection_preview_tests {
use super::*;
use crate::app::{HoverDwell, OpenCADStudio, HOVER_DWELL_MS};
/// Drive one settled rollover pick over a line and report what the scene
/// ended up highlighting.
fn rollover_hits(preview: u8) -> bool {
let mut app = OpenCADStudio::new_for_test();
app.automation_op(r#"{"op":"new"}"#);
let i = app.active_tab;
app.model_space.selection_preview = preview;
let _ = app.run_command_line("LINE 0,0 10,10");
app.tabs[i].scene.selection.borrow_mut().vp_size = (800.0, 600.0);
let _ = app.run_command_line("ZOOM EXTENTS");
// The pick only runs once the cursor has been still for the dwell
// window, so the arming timestamp is backdated past it.
app.hover_dwell = Some(HoverDwell {
last_move_at: Instant::now()
- std::time::Duration::from_millis(HOVER_DWELL_MS as u64 * 2),
point: iced::Point::new(400.0, 300.0),
tile_size: (800.0, 600.0),
tab: i,
});
let _ = app.on_hover_dwell_tick();
app.tabs[i].scene.hover_highlight.is_some()
}
/// Bit 1 of `SELECTIONPREVIEW` is the rollover that runs with no command
/// active, and the Options card gives it a checkbox. The config comment
/// used to describe the bits the wrong way round, so which bit does what
/// is worth asserting rather than reading.
#[test]
fn the_idle_rollover_follows_bit_one() {
assert!(
rollover_hits(1),
"bit 1 set: the line under the cursor must be highlighted",
);
assert!(
rollover_hits(3),
"both bits set: still highlighted",
);
assert!(
!rollover_hits(0),
"preview off: nothing may be highlighted",
);
assert!(
!rollover_hits(2),
"only the in-command bit: the idle rollover stays off",
);
}
}