Windows: Alt-click clone hint and Ctrl+N channel errors (#251 follow-up) (#336) (#336)

This commit is contained in:
JGF authored and GitHub committed 2026-10-06 10:46:41 -04:00
1 parent 4e2a83ddbd
commit f091c7fbf0
5 files changed
+30 -3

No files matched your search

+5 -2
View File
@@ -1067,6 +1067,9 @@ fn target_cmd(s: &mut Session, p: &Value) -> Result<Value> {
Ok(list(s))
}
/// The channel shortcuts' modifier as the platform writes it, for error messages (`⌘4`, `Ctrl+4`).
const SLOT_KEY: &str = if cfg!(target_os = "macos") { "⌘" } else { "Ctrl+" };
/// ⌘2 composite, ⌘3… colour channels then alpha channels (Photoshop CC defaults).
fn target_slot(s: &mut Session, slot: usize) -> Result<Value> {
let doc = &s.active().ok_or(EngineError::NoDocument)?.doc;
@@ -1076,7 +1079,7 @@ fn target_slot(s: &mut Session, slot: usize) -> Result<Value> {
2 => ChannelTarget::Composite,
n if n - 3 < shown_colors => ChannelTarget::Color(n - 3),
n if n - 3 - shown_colors < doc.channels.len() => ChannelTarget::Alpha(n - 3 - shown_colors),
_ => return Err(EngineError::Other(format!("no channel for ⌘{slot}"))),
_ => return Err(EngineError::Other(format!("no channel for {SLOT_KEY}{slot}"))),
};
target(s, t);
Ok(list(s))
@@ -1595,7 +1598,7 @@ fn slot_ok<const N: usize>(s: &Session) -> std::result::Result<(), String> {
let d = s.active().ok_or("no document open")?;
let colors = color_count(&d.doc);
let shown = if colors > 1 { colors } else { 0 };
if N - 3 < shown + d.doc.channels.len() { Ok(()) } else { Err(format!("no channel for ⌘{N}")) }
if N - 3 < shown + d.doc.channels.len() { Ok(()) } else { Err(format!("no channel for {SLOT_KEY}{N}")) }
}
fn has_apply_target(s: &Session) -> std::result::Result<(), String> {
+3
View File
@@ -177,6 +177,9 @@ fn shortcut_slots_target_channels() {
s.execute("channel.target.slot6", json!({})).unwrap();
assert_eq!(s.active().unwrap().channel_view.target, ChannelTarget::Alpha(0));
assert!(!s.is_enabled("channel.target.slot7"));
// The reason names the shortcut in the platform's notation (⌘7 on the Mac, Ctrl+7 elsewhere).
let err = s.execute("channel.target.slot7", json!({})).unwrap_err().to_string();
assert!(err.contains(if cfg!(target_os = "macos") { "no channel for ⌘7" } else { "no channel for Ctrl+7" }), "{err}");
s.execute("channel.target.composite", json!({})).unwrap();
assert_eq!(s.active().unwrap().channel_view.target, ChannelTarget::Composite);
// Grayscale: ⌘3 is the first alpha channel.
+1
View File
@@ -727,6 +727,7 @@
All User Slices すべてのユーザースライス
All shortcuts reset to Photoshop defaults. すべてのショートカットを初期状態に戻しました。
Alt Alt
Alt-click to define a source point to clone from Alt+クリックでコピー元を指定
Always use pressure for opacity 常に筆圧を不透明度に使う
Always use pressure for size 常に筆圧をサイズに使う
Amount 量
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -725,6 +725,7 @@
All User Slices 所有用户切片
All shortcuts reset to Photoshop defaults. 所有快捷键已重置为 Photoshop 默认值。
Alt Alt
Alt-click to define a source point to clone from 按 Alt 单击以定义仿制源点
Always use pressure for opacity 始终用压感控制不透明度
Always use pressure for size 始终用压感控制大小
Amount 数量
1 # Simplified Chinese (zh-hans) catalog. UTF-8, TAB-separated columns:
725
726
727
728
729
730
731
+20 -1
View File
@@ -26,7 +26,13 @@ pub fn finish_stroke(app: &mut PhotocraftApp, tool: Tool, points: &[[f64; 3]], m
(Some(off), _) => p["offset"] = json!(off),
(None, Some(src)) => p["source"] = json!(src),
(None, None) => {
app.ui.status = tl!("Option-click to define a source point to clone from").into();
// Photoshop says Option-click on the Mac and Alt-click on Windows.
app.ui.status = if cfg!(target_os = "macos") {
tl!("Option-click to define a source point to clone from")
} else {
tl!("Alt-click to define a source point to clone from")
}
.into();
app.ui.status_error = true;
return true;
}
@@ -237,6 +243,19 @@ mod tests {
}
}
#[test]
fn clone_without_a_source_names_the_platform_modifier() {
// Option-click on the Mac, Alt-click elsewhere (#251).
for tool in [Tool::CloneStamp, Tool::Healing] {
let mut app = app();
app.ui.tool = tool;
assert!(finish_stroke(&mut app, tool, &[[10.0, 30.0, 1.0], [50.0, 30.0, 1.0]], egui::Modifiers::NONE));
assert!(app.ui.status_error, "{tool:?}");
let want = if cfg!(target_os = "macos") { "Option-click" } else { "Alt-click" };
assert!(app.ui.status.starts_with(want), "{tool:?}: {}", app.ui.status);
}
}
#[test]
fn retouch_strokes_paint_the_targeted_mask() {
// #207: with the mask targeted, retouching changes the mask, never the pixels.