feat(viewport): RMB 1st=Enter, 2nd=menu (no setting)
Replaces the opt-in `rmb_enter` setting (and `RMBENTER` command) with always-on behavior. While a command is active, the first viewport right-click acts as Enter (commit / close) and a second consecutive right-click opens the context menu instead. Idle right-click still opens the menu; right-drag still orbits. The cycle is tracked per tab (`right_click_entered`) and restarts on any other interaction — a left-click pick, a new command, an orbit, or leaving the viewport — so the next right-click is Enter again. Refines #185. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
098585bb2d
commit
b691854e7a
8 changed files with 26 additions and 41 deletions
|
|
@ -17,27 +17,6 @@ impl OpenCADStudio {
|
|||
.push_output("PAN: drag with the left mouse button. Press Esc to exit.");
|
||||
}
|
||||
|
||||
// RMBENTER [ON|OFF] — toggle whether a viewport right-click acts as
|
||||
// Enter (commit / close) while a command is active. Idle right-click
|
||||
// still opens the context menu and right-drag still orbits. The
|
||||
// preference is persisted across runs.
|
||||
cmd if cmd == "RMBENTER" || cmd.starts_with("RMBENTER ") => {
|
||||
let arg = cmd
|
||||
.split_once(' ')
|
||||
.map(|(_, r)| r.trim().to_uppercase())
|
||||
.unwrap_or_default();
|
||||
self.rmb_enter = match arg.as_str() {
|
||||
"ON" | "1" => true,
|
||||
"OFF" | "0" => false,
|
||||
_ => !self.rmb_enter,
|
||||
};
|
||||
self.command_line.push_output(if self.rmb_enter {
|
||||
"RMBENTER on: right-click acts as Enter while a command is active."
|
||||
} else {
|
||||
"RMBENTER off: right-click opens the context menu."
|
||||
});
|
||||
}
|
||||
|
||||
// ── TABLE cell editing ─────────────────────────────────────────────
|
||||
// TABLE CELL <row> <col> <text> — set text for a cell in the selected Table
|
||||
cmd if cmd.starts_with("TABLE ") => {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ impl OpenCADStudio {
|
|||
// Reset the last committed point so the first click of the new command
|
||||
// is not constrained by ortho/polar relative to a previous command's endpoint.
|
||||
self.last_point = None;
|
||||
// Starting a command restarts the right-click cycle, so its first
|
||||
// right-click acts as Enter rather than opening the context menu.
|
||||
self.tabs[i].scene.selection.borrow_mut().right_click_entered = false;
|
||||
// A fresh command starts at the polar/cartesian default — clear
|
||||
// any `,`-driven reshape from a previous command (#35).
|
||||
self.dyn_user_reshaped = false;
|
||||
|
|
@ -208,7 +211,7 @@ inventory::submit!(crate::command::CommandRegistration {
|
|||
"P", "PAN", "PAGESETUP", "PERF", "PERSP", "PLOT", "PLOTSTYLE", "PLOTSTYLEEDITOR",
|
||||
"PLOTSTYLEPANEL", "PR",
|
||||
"PRINT", "PROPERTIES", "PROPS", "PSPACE", "PURGE", "QS", "QSAVE", "QSELECT",
|
||||
"QUIT", "REDO", "REDRAW", "REDRWALL", "REGEN", "REGENALL", "RENAME", "REPORT", "RMBENTER",
|
||||
"QUIT", "REDO", "REDRAW", "REDRWALL", "REGEN", "REGENALL", "RENAME", "REPORT",
|
||||
"SA", "SAVE", "SAVEAS", "SCALETEXT", "SELECTALL", "SELECTSIMILAR", "SELSIM", "SHEETSET",
|
||||
"SHORTCUTS", "SOLID", "SSM", "STEPOUT", "STLOUT", "STPOUT", "STYLE", "STYLESMANAGER",
|
||||
"TABLESTYLE", "TOOLPALETTES", "TP", "TS", "U", "UCS", "UCSICON", "UNDERLAY",
|
||||
|
|
|
|||
|
|
@ -247,9 +247,6 @@ pub(super) struct OpenCADStudio {
|
|||
dyn_input: bool,
|
||||
/// Controls whether the TEXTEDIT command repeats automatically (0 = Multiple, 1 = Single).
|
||||
pub texteditmode: bool,
|
||||
/// When true, a viewport right-click acts as Enter while a command is active
|
||||
/// (idle right-click still opens the context menu). Toggled by `RMBENTER`.
|
||||
pub rmb_enter: bool,
|
||||
/// Persisted default viewport background, restored from settings and applied
|
||||
/// to every drawing tab (new and opened) so a chosen background survives
|
||||
/// restarts (#188). `None` = the built-in dark-grey / off-white defaults.
|
||||
|
|
@ -1826,7 +1823,6 @@ impl OpenCADStudio {
|
|||
show_grid: false,
|
||||
dyn_input: true,
|
||||
texteditmode: false,
|
||||
rmb_enter: false,
|
||||
default_bg_color: None,
|
||||
default_paper_bg_color: None,
|
||||
awaiting_vports: false,
|
||||
|
|
|
|||
|
|
@ -103,10 +103,6 @@ pub struct UserSettings {
|
|||
pub plugin_repos: Vec<String>,
|
||||
/// Controls whether the TEXTEDIT command repeats automatically (0 = Multiple, 1 = Single).
|
||||
pub texteditmode: bool,
|
||||
/// When true, a right-click in the viewport acts as Enter (commit / close)
|
||||
/// while a command is active; when idle it still opens the context menu.
|
||||
/// Toggled by the `RMBENTER` command. Right-drag always orbits.
|
||||
pub rmb_enter: bool,
|
||||
/// Persisted viewport background colours (0–255 RGB); `None` = app default
|
||||
/// (dark grey model / off-white paper). Applied to every drawing tab on
|
||||
/// launch and to tabs opened later, so a chosen background survives restarts
|
||||
|
|
@ -137,7 +133,6 @@ impl Default for UserSettings {
|
|||
disabled_plugins: Vec::new(),
|
||||
plugin_repos: Vec::new(),
|
||||
texteditmode: false,
|
||||
rmb_enter: false,
|
||||
bg_color: None,
|
||||
paper_bg_color: None,
|
||||
}
|
||||
|
|
@ -175,7 +170,6 @@ impl UserSettings {
|
|||
"bg_color" => s.bg_color = parse_rgb(val),
|
||||
"paper_bg_color" => s.paper_bg_color = parse_rgb(val),
|
||||
"default_assoc_prompted" => s.default_assoc_prompted = val == "1",
|
||||
"rmb_enter" => s.rmb_enter = val == "1",
|
||||
"texteditmode" => {
|
||||
if let Some(v) =
|
||||
crate::modules::annotate::textedit::parse_texteditmode(val)
|
||||
|
|
@ -224,7 +218,7 @@ impl UserSettings {
|
|||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
let body = format!(
|
||||
"dyn={}\northo={}\npolar={}\npolar_increment_deg={}\nosnap={}\notrack={}\ndefault_assoc_prompted={}\nsnap_modes={}\ndisabled_plugins={}\nplugin_repos={}\ntexteditmode={}\nrmb_enter={}\nbg_color={}\npaper_bg_color={}\n",
|
||||
"dyn={}\northo={}\npolar={}\npolar_increment_deg={}\nosnap={}\notrack={}\ndefault_assoc_prompted={}\nsnap_modes={}\ndisabled_plugins={}\nplugin_repos={}\ntexteditmode={}\nbg_color={}\npaper_bg_color={}\n",
|
||||
b(self.dyn_input),
|
||||
b(self.ortho),
|
||||
b(self.polar),
|
||||
|
|
@ -236,7 +230,6 @@ impl UserSettings {
|
|||
self.disabled_plugins.join(","),
|
||||
self.plugin_repos.join(","),
|
||||
self.texteditmode,
|
||||
b(self.rmb_enter),
|
||||
rgb_to_str(self.bg_color),
|
||||
rgb_to_str(self.paper_bg_color),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ impl OpenCADStudio {
|
|||
},
|
||||
plugin_repos: self.plugin_repos.clone(),
|
||||
texteditmode: self.texteditmode,
|
||||
rmb_enter: self.rmb_enter,
|
||||
bg_color: self.default_bg_color.map(f4_to_u3),
|
||||
paper_bg_color: self.default_paper_bg_color.map(f4_to_u3),
|
||||
}
|
||||
|
|
@ -59,7 +58,6 @@ impl OpenCADStudio {
|
|||
self.disabled_plugins = s.disabled_plugins.iter().cloned().collect();
|
||||
self.plugin_repos = s.plugin_repos.clone();
|
||||
self.texteditmode = s.texteditmode;
|
||||
self.rmb_enter = s.rmb_enter;
|
||||
self.default_bg_color = s.bg_color.map(u3_to_f4);
|
||||
self.default_paper_bg_color = s.paper_bg_color.map(u3_to_f4);
|
||||
// Push the restored background onto every drawing tab that exists now
|
||||
|
|
|
|||
|
|
@ -1119,14 +1119,18 @@ impl OpenCADStudio {
|
|||
if !was_click {
|
||||
return Task::none();
|
||||
}
|
||||
// A right-click (no orbit). With "RMB = Enter" enabled, a click
|
||||
// while a command is active fires Enter (commit/close) instead
|
||||
// of the menu; when idle — or the option is off — it opens the
|
||||
// context menu as before, so the menu is never lost.
|
||||
if self.rmb_enter && self.tabs[i].active_cmd.is_some() {
|
||||
// A right-click (no orbit). While a command is active the first
|
||||
// right-click acts as Enter (commit / close); a second
|
||||
// consecutive right-click opens the context menu instead. When
|
||||
// idle it always opens the menu. (Right-drag, handled above,
|
||||
// always orbits.) Any other interaction — a left-click pick or a
|
||||
// new command — resets the cycle so the next right-click is Enter.
|
||||
if self.tabs[i].active_cmd.is_some() && !sel.right_click_entered {
|
||||
sel.right_click_entered = true;
|
||||
drop(sel);
|
||||
return self.update(Message::CommandFinalize);
|
||||
}
|
||||
sel.right_click_entered = false;
|
||||
sel.context_menu = Some(click_pos);
|
||||
sel.draworder_submenu = false;
|
||||
Task::none()
|
||||
|
|
|
|||
|
|
@ -585,6 +585,8 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
|||
if held && moved {
|
||||
sel.right_dragging = true;
|
||||
sel.context_menu = None;
|
||||
// An orbit restarts the right-click cycle.
|
||||
sel.right_click_entered = false;
|
||||
// Start the orbit from the current position so the
|
||||
// view doesn't jump by the pre-threshold movement.
|
||||
sel.right_last_pos = Some(p);
|
||||
|
|
@ -1226,6 +1228,7 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
|||
sel.right_press_time = None;
|
||||
sel.right_last_pos = None;
|
||||
sel.right_dragging = false;
|
||||
sel.right_click_entered = false;
|
||||
sel.middle_down = false;
|
||||
sel.middle_last_pos = None;
|
||||
sel.box_anchor = None;
|
||||
|
|
@ -1440,6 +1443,10 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
|
|||
|
||||
pub(super) fn on_viewport_left_press(&mut self) -> Task<Message> {
|
||||
let i = self.active_tab;
|
||||
// A left-click during a command resets the right-click cycle, so
|
||||
// the next right-click acts as Enter again rather than opening
|
||||
// the context menu.
|
||||
self.tabs[i].scene.selection.borrow_mut().right_click_entered = false;
|
||||
// A click in the viewport dismisses any open ribbon dropdown
|
||||
// (e.g. the annotation style combo), which has no backdrop of
|
||||
// its own to catch outside clicks.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@ pub struct SelectionState {
|
|||
pub right_press_time: Option<Instant>,
|
||||
pub right_dragging: bool,
|
||||
pub right_last_pos: Option<Point>,
|
||||
/// While a command is active, a right-click acts as Enter; the *next*
|
||||
/// consecutive right-click opens the context menu instead. This tracks
|
||||
/// whether the previous right-click already fired Enter. Reset by any
|
||||
/// other interaction (left-click pick, a new command) and on viewport exit.
|
||||
pub right_click_entered: bool,
|
||||
pub middle_down: bool,
|
||||
pub middle_last_pos: Option<Point>,
|
||||
pub middle_last_press_time: Option<Instant>,
|
||||
|
|
|
|||
Loading…
Reference in a new issue