Move tool on a locked layer: Photoshop's message (#2249)
* Move tool on a locked layer: Photoshop's message Dragging with the Move tool (or Cmd with another tool) on a layer it can't move showed nothing: the Background or a position-locked layer with no selection, or a locked layer whose selected pixels can't float. Photoshop puts up "Could not use the move tool because the layer is locked." when the drag starts (a plain click says nothing); move_lock.rs does the same with the Error dialog, translated in every catalogue. The float lock rule moves to float_cmds::locked_for_float so the UI can ask before the press goes anywhere. Also in Dutch and Ukrainian. The Cmd-with-a-painting-tool case lands with the Cmd-as-Move change, whichever merges second. * Fix merge: close the lock-message test --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1f84f19caf
commit
6a39da98c8
|
|
@ -130,14 +130,19 @@ fn can_float(s: &Session) -> std::result::Result<(), String> {
|
|||
if !matches!(l.content, LayerContent::Raster(_)) {
|
||||
return Err("the active layer has no pixels to move".into());
|
||||
}
|
||||
let locks = st.doc.effective_locks(l.id);
|
||||
// The Background is position-locked, but its selected pixels move (Photoshop).
|
||||
if locks.all || (locks.position && !crate::extra_cmds::is_background(l)) {
|
||||
if locked_for_float(&st.doc, l) {
|
||||
return Err(format!("layer \"{}\" is locked", l.name));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Do `l`'s locks (its own, or a locked group's: `effective_locks`) stop its selected pixels
|
||||
/// floating? The Background is position-locked, but its selected pixels move (Photoshop).
|
||||
pub fn locked_for_float(doc: &Document, l: &photocraft_doc::Layer) -> bool {
|
||||
let locks = doc.effective_locks(l.id);
|
||||
locks.all || (locks.position && !crate::extra_cmds::is_background(l))
|
||||
}
|
||||
|
||||
fn float(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let (dx, dy) = (int_param(p, "dx"), int_param(p, "dy"));
|
||||
let copy = p.get("copy").and_then(Value::as_bool).unwrap_or(false);
|
||||
|
|
|
|||
|
|
@ -3690,6 +3690,25 @@ pub fn tool_event(app: &mut PhotocraftApp, ev: ToolEvent, mods: egui::Modifiers)
|
|||
ToolEvent::Up { .. } => return,
|
||||
}
|
||||
}
|
||||
// A locked layer (the Background without a selection, say): no drag, and Photoshop's message
|
||||
// once the pointer moves (a click says nothing). ⌘ with a selection tool here (#896); the Move
|
||||
// tool below, once Auto-Select has picked the layer.
|
||||
match ev {
|
||||
ToolEvent::Down { x, y, .. } if tool != Tool::Move && app.ui.transform.is_none() && crate::move_lock::blocked(app, tool, [x, y], mods) => {
|
||||
app.move_blocked = true;
|
||||
return;
|
||||
}
|
||||
ToolEvent::Move { .. } if app.move_blocked => {
|
||||
app.move_blocked = false;
|
||||
crate::move_lock::prompt(app);
|
||||
return;
|
||||
}
|
||||
ToolEvent::Up { .. } if app.move_blocked => {
|
||||
app.move_blocked = false;
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// Move tool over a guide drags the guide (off the canvas deletes it).
|
||||
match ev {
|
||||
ToolEvent::Down { x, y, pressure } if tool == Tool::Move => {
|
||||
|
|
@ -3697,8 +3716,20 @@ pub fn tool_event(app: &mut PhotocraftApp, ev: ToolEvent, mods: egui::Modifiers)
|
|||
app.guide_drag = Some(crate::rulers::GuideDrag { vertical, index: Some(i), pos: if vertical { x } else { y } });
|
||||
return;
|
||||
}
|
||||
// Auto-Select (or ⌘-click while it is off) picks the layer under the pointer first
|
||||
// (not when the selected pixels move: those are the active layer's).
|
||||
if !crate::move_ui::moves_selected_pixels(app) && app.ui.tool_options.move_auto_select != mods.command {
|
||||
let target = app.ui.tool_options.move_target.clone();
|
||||
let mode = if mods.shift { "add" } else { "replace" };
|
||||
let _ = app.run("layer.pickAt", json!({"x": x, "y": y, "target": target, "mode": mode}));
|
||||
}
|
||||
// A locked layer: no drag, and Photoshop's message once the pointer moves (`move_lock`).
|
||||
if crate::move_lock::blocked(app, tool, [x, y], mods) {
|
||||
app.move_blocked = true;
|
||||
return;
|
||||
}
|
||||
// With a selection: cut the selected pixels (⌥ copies them) and drag them as a floating
|
||||
// piece, from anywhere, as a marquee ⌘-drag does (no Auto-Select pick).
|
||||
// piece, from anywhere, as a marquee ⌘-drag does.
|
||||
if crate::move_ui::moves_selected_pixels(app) {
|
||||
if crate::move_ui::float_selected(app, mods.alt, 0.0, 0.0) {
|
||||
let mut d = Drag::new(tool, [x, y], vec![[x, y, pressure as f64]], mods, false);
|
||||
|
|
@ -3707,12 +3738,6 @@ pub fn tool_event(app: &mut PhotocraftApp, ev: ToolEvent, mods: egui::Modifiers)
|
|||
}
|
||||
return;
|
||||
}
|
||||
// Auto-Select (or ⌘-click while it is off) picks the layer under the pointer first.
|
||||
if app.ui.tool_options.move_auto_select != mods.command {
|
||||
let target = app.ui.tool_options.move_target.clone();
|
||||
let mode = if mods.shift { "add" } else { "replace" };
|
||||
let _ = app.run("layer.pickAt", json!({"x": x, "y": y, "target": target, "mode": mode}));
|
||||
}
|
||||
}
|
||||
ToolEvent::Move { x, y, .. } => {
|
||||
if let Some(d) = app.guide_drag.as_mut().filter(|d| d.index.is_some()) {
|
||||
|
|
@ -3953,7 +3978,7 @@ pub fn selection_drag_kind(app: &PhotocraftApp, tool: Tool, p: [f64; 2], mods: e
|
|||
/// Does a ⌘ (⌘⌥) press with selection tool `tool` at `p` move the whole layer (a duplicate with
|
||||
/// ⌥), as the Move tool would? Outside the selection or without one; inside it, ⌘ drags the
|
||||
/// selected pixels instead (`selection_drag_kind`).
|
||||
fn command_moves_layer(app: &PhotocraftApp, tool: Tool, p: [f64; 2], mods: egui::Modifiers) -> bool {
|
||||
pub(crate) fn command_moves_layer(app: &PhotocraftApp, tool: Tool, p: [f64; 2], mods: egui::Modifiers) -> bool {
|
||||
let selection_tool = matches!(tool, Tool::RectMarquee | Tool::EllipseMarquee | Tool::Lasso | Tool::PolygonLasso | Tool::MagicWand);
|
||||
let floating = app.session.active().is_some_and(|st| photocraft_engine::float_cmds::floating(st).is_some());
|
||||
selection_tool && mods.command && !mods.shift && !floating && app.ui.polygon.is_empty() && !inside_selection(app, p)
|
||||
|
|
|
|||
|
|
@ -1636,6 +1636,7 @@
|
|||
Millimeters Milimetry
|
||||
Mobile Mobilní zařízení
|
||||
Move Tool Nástroj přesun
|
||||
Could not use the move tool because the layer is locked. Nástroj Přesun nelze použít, protože vrstva je zamčená.
|
||||
Multiply Násobit
|
||||
My Brushes Moje štětce
|
||||
Neutrals Neutrální
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -1616,6 +1616,7 @@
|
|||
Millimeters Millimeter
|
||||
Mobile Mobil
|
||||
Move Tool Verschieben-Werkzeug
|
||||
Could not use the move tool because the layer is locked. Das Verschieben-Werkzeug konnte nicht verwendet werden, weil die Ebene gesperrt ist.
|
||||
Multiply Multiplizieren
|
||||
My Brushes Meine Pinsel
|
||||
Neutrals Neutrale
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -3215,6 +3215,7 @@ cameraRaw Yellow Κίτρινο
|
|||
Magic Eraser Tool Μαγική γόμα (Magic Eraser Tool)
|
||||
Magic Wand Tool Μαγικό ραβδί (Magic Wand Tool)
|
||||
Move Tool Μετακίνηση (Move Tool)
|
||||
Could not use the move tool because the layer is locked. Δεν ήταν δυνατή η χρήση του εργαλείου Μετακίνηση, επειδή το επίπεδο είναι κλειδωμένο.
|
||||
Note Tool Σημείωση (Note Tool)
|
||||
Object Selection Tool Επιλογή αντικειμένου (Object Selection Tool)
|
||||
Paint Bucket Tool Κουβάς γεμίσματος (Paint Bucket Tool)
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 5.
|
|
|
@ -1620,6 +1620,7 @@
|
|||
Millimeters Milímetros
|
||||
Mobile Móvil
|
||||
Move Tool Herramienta Mover
|
||||
Could not use the move tool because the layer is locked. No se pudo usar la herramienta Mover porque la capa está bloqueada.
|
||||
Multiply Multiplicar
|
||||
My Brushes Mis pinceles
|
||||
Neutrals Neutros
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 4 and column 47.
|
|
|
@ -1599,6 +1599,7 @@
|
|||
Millimeters Millimètres
|
||||
Mobile Mobile
|
||||
Move Tool Outil Déplacement
|
||||
Could not use the move tool because the layer is locked. Impossible d'utiliser l'outil Déplacement, car le calque est verrouillé.
|
||||
Multiply Produit
|
||||
My Brushes Mes pinceaux
|
||||
Neutrals Neutres
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -1593,6 +1593,7 @@
|
|||
Millimeters Milimeter
|
||||
Mobile Seluler
|
||||
Move Tool Alat Pindah
|
||||
Could not use the move tool because the layer is locked. Tidak dapat menggunakan alat Pindahkan karena layer terkunci.
|
||||
Multiply Multiply
|
||||
My Brushes Kuas Saya
|
||||
Neutrals Netral
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 4 and column 47.
|
|
|
@ -1618,6 +1618,7 @@
|
|||
Millimeters Millimetri
|
||||
Mobile Mobile
|
||||
Move Tool Strumento Sposta
|
||||
Could not use the move tool because the layer is locked. Impossibile usare lo strumento Sposta perché il livello è bloccato.
|
||||
Multiply Moltiplica
|
||||
My Brushes I miei pennelli
|
||||
Neutrals Neutri
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 14.
|
|
|
@ -1625,6 +1625,7 @@
|
|||
Millimeters ミリメートル
|
||||
Mobile モバイル
|
||||
Move Tool 移動ツール
|
||||
Could not use the move tool because the layer is locked. レイヤーがロックされているため、移動ツールを使用できません。
|
||||
Multiply 乗算
|
||||
My Brushes マイブラシ
|
||||
Neutrals 中間色系
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -1595,6 +1595,7 @@
|
|||
Millimeters 밀리미터
|
||||
Mobile 모바일
|
||||
Move Tool 이동 도구
|
||||
Could not use the move tool because the layer is locked. 레이어가 잠겨 있어 이동 도구를 사용할 수 없습니다.
|
||||
Multiply 곱하기
|
||||
My Brushes 내 브러시
|
||||
Neutrals 중립색
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 10.
|
|
|
@ -1608,6 +1608,7 @@
|
|||
Millimeters Millimeter
|
||||
Mobile Mobiel
|
||||
Move Tool Verplaatsgereedschap
|
||||
Could not use the move tool because the layer is locked. Kan het verplaatsgereedschap niet gebruiken omdat de laag is vergrendeld.
|
||||
Multiply Vermenigvuldigen
|
||||
My Brushes Mijn penselen
|
||||
Neutrals Neutrale tinten
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 8 and column 34.
|
|
|
@ -1618,6 +1618,7 @@
|
|||
Millimeters Milimetry
|
||||
Mobile Urządzenia mobilne
|
||||
Move Tool Narzędzie Przesunięcie
|
||||
Could not use the move tool because the layer is locked. Nie można użyć narzędzia Przesunięcie, ponieważ warstwa jest zablokowana.
|
||||
Multiply Mnożenie
|
||||
My Brushes Moje pędzle
|
||||
Neutrals Neutralne
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -1598,6 +1598,7 @@
|
|||
Millimeters Milímetros
|
||||
Mobile Dispositivos móveis
|
||||
Move Tool Ferramenta Mover
|
||||
Could not use the move tool because the layer is locked. Não foi possível usar a ferramenta Mover porque a camada está bloqueada.
|
||||
Multiply Multiplicação
|
||||
My Brushes Meus pincéis
|
||||
Neutrals Neutros
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -1500,6 +1500,7 @@
|
|||
Adjustment Layer Корректирующий слой
|
||||
{name} Properties Свойства: {name}
|
||||
Move Tool Перемещение
|
||||
Could not use the move tool because the layer is locked. Не удалось использовать инструмент «Перемещение», потому что слой заблокирован.
|
||||
Rectangular Marquee Tool Прямоугольная область
|
||||
Elliptical Marquee Tool Овальная область
|
||||
Brush Tool Кисть
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -1485,6 +1485,7 @@
|
|||
Adjustment Layer Коригувальний шар
|
||||
{name} Properties Властивості: {name}
|
||||
Move Tool Інструмент «Переміщення»
|
||||
Could not use the move tool because the layer is locked. Не вдалося використати інструмент «Переміщення», бо шар заблоковано.
|
||||
Rectangular Marquee Tool Інструмент «Прямокутне виділення»
|
||||
Elliptical Marquee Tool Інструмент «Еліптичне виділення»
|
||||
Brush Tool Інструмент «Пензель»
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 12.
|
|
|
@ -1633,6 +1633,7 @@
|
|||
Millimeters 毫米
|
||||
Mobile 移动设备
|
||||
Move Tool 移动工具
|
||||
Could not use the move tool because the layer is locked. 无法使用移动工具,因为图层已锁定。
|
||||
Multiply 正片叠底
|
||||
My Brushes 我的画笔
|
||||
Neutrals 中性色
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 14.
|
|
|
@ -1626,6 +1626,7 @@
|
|||
Millimeters 公釐
|
||||
Mobile 行動裝置
|
||||
Move Tool 移動工具
|
||||
Could not use the move tool because the layer is locked. 無法使用移動工具,因為圖層已鎖定。
|
||||
Multiply 色彩增值
|
||||
My Brushes 我的筆刷
|
||||
Neutrals 中間色
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -98,6 +98,7 @@ pub mod menu_catalog;
|
|||
pub mod menu_nav;
|
||||
pub mod menus;
|
||||
pub mod monitor_status;
|
||||
pub mod move_lock;
|
||||
pub mod move_mods;
|
||||
pub mod move_ui;
|
||||
pub mod native_menu;
|
||||
|
|
@ -371,6 +372,9 @@ pub struct PhotocraftApp {
|
|||
monitors: monitor_status::State,
|
||||
checker: Option<egui::TextureHandle>,
|
||||
drag: Option<canvas::Drag>,
|
||||
/// A Move-tool press landed on a locked layer: the first pointer move shows Photoshop's
|
||||
/// message (`move_lock`), a plain click shows nothing.
|
||||
pub(crate) move_blocked: bool,
|
||||
/// The tool pointer events go to this frame when it isn't the selected one: the Move tool
|
||||
/// while ⌘ is held (`hold_keys::cmd_moves`). Set by the canvas for its gestures, never saved.
|
||||
pub(crate) tool_override: Option<state::Tool>,
|
||||
|
|
@ -571,6 +575,7 @@ impl PhotocraftApp {
|
|||
monitors: Default::default(),
|
||||
checker: None,
|
||||
drag: None,
|
||||
move_blocked: false,
|
||||
tool_override: None,
|
||||
live_stroke: None,
|
||||
trail: None,
|
||||
|
|
|
|||
|
|
@ -409,6 +409,93 @@ fn alt_with_nothing_selected_draws_a_new_selection() {
|
|||
assert!(after.is_none_or(|r| r.is_empty() || r != before), "⌥ subtracted: {before:?} -> {after:?}");
|
||||
}
|
||||
|
||||
fn error_dialogs(app: &PhotocraftApp) -> Vec<String> {
|
||||
app.ui.dialogs.iter().filter(|d| d.kind == crate::state::DialogKind::Error).filter_map(|d| d.fields.get("message")?.as_str().map(String::from)).collect()
|
||||
}
|
||||
|
||||
/// Photoshop's "Could not use the move tool because the layer is locked." when a Move-tool drag
|
||||
/// (the Move tool, or ⌘ with a marquee) starts on a layer it can't move: the Background with no
|
||||
/// selection, a position-locked layer; a plain click says nothing, and the drag never starts.
|
||||
#[test]
|
||||
fn move_on_the_background_without_a_selection_shows_photoshops_lock_message() {
|
||||
let mut app = PhotocraftApp::new(photocraft_engine::Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({"width": 80, "height": 60})).unwrap();
|
||||
app.sync_views();
|
||||
app.ui.tool = Tool::Move;
|
||||
app.ui.tool_options.move_auto_select = false;
|
||||
let steps = app.session.active().unwrap().history.past_len();
|
||||
use crate::canvas::{ToolEvent, tool_event};
|
||||
// A click: no message.
|
||||
tool_event(&mut app, ToolEvent::Down { x: 20.0, y: 20.0, pressure: 1.0 }, Modifiers::NONE);
|
||||
tool_event(&mut app, ToolEvent::Up { x: 20.0, y: 20.0 }, Modifiers::NONE);
|
||||
assert!(error_dialogs(&app).is_empty() && !app.move_blocked);
|
||||
// A drag: the message once, nothing moved, no drag in progress.
|
||||
tool_event(&mut app, ToolEvent::Down { x: 20.0, y: 20.0, pressure: 1.0 }, Modifiers::NONE);
|
||||
tool_event(&mut app, ToolEvent::Move { x: 30.0, y: 20.0, pressure: 1.0 }, Modifiers::NONE);
|
||||
tool_event(&mut app, ToolEvent::Move { x: 40.0, y: 20.0, pressure: 1.0 }, Modifiers::NONE);
|
||||
tool_event(&mut app, ToolEvent::Up { x: 40.0, y: 20.0 }, Modifiers::NONE);
|
||||
assert_eq!(error_dialogs(&app), [crate::move_lock::MESSAGE]);
|
||||
assert!(app.drag.is_none(), "no drag started");
|
||||
assert_eq!(app.session.active().unwrap().history.past_len(), steps);
|
||||
app.ui.dialogs.clear();
|
||||
// ⌘-drag with a marquee (the Move tool for the drag, #896): the same.
|
||||
app.ui.tool = Tool::RectMarquee;
|
||||
drag(&mut app, [20.0, 20.0], [40.0, 20.0], Modifiers::COMMAND);
|
||||
assert_eq!(error_dialogs(&app), [crate::move_lock::MESSAGE]);
|
||||
app.ui.dialogs.clear();
|
||||
// A position-locked layer: the same; unlocked, it moves.
|
||||
app.run("layer.new.layer", json!({})).unwrap();
|
||||
app.session
|
||||
.edit("lock", |doc, a| {
|
||||
doc.layer_mut(a.unwrap()).unwrap().locks.position = true;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
drag(&mut app, [20.0, 20.0], [40.0, 20.0], Modifiers::COMMAND);
|
||||
assert_eq!(error_dialogs(&app).len(), 1);
|
||||
app.ui.dialogs.clear();
|
||||
app.session
|
||||
.edit("unlock", |doc, a| {
|
||||
doc.layer_mut(a.unwrap()).unwrap().locks.position = false;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
drag(&mut app, [20.0, 20.0], [40.0, 20.0], Modifiers::COMMAND);
|
||||
assert!(error_dialogs(&app).is_empty());
|
||||
}
|
||||
|
||||
/// With a selection the Background's pixels do move (its lock is partial: transparency and
|
||||
/// position), so no message; a layer locked all over gets it, with the marquee's ⌘-drag inside the
|
||||
/// selection as with the Move tool.
|
||||
#[test]
|
||||
fn selected_pixels_move_off_the_background_but_not_off_a_fully_locked_layer() {
|
||||
let mut app = PhotocraftApp::new(photocraft_engine::Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({"width": 80, "height": 60})).unwrap();
|
||||
app.sync_views();
|
||||
app.ui.extras.snap = false;
|
||||
app.ui.view.show.smart_guides = false;
|
||||
app.ui.tool = Tool::RectMarquee;
|
||||
app.run("select.rect", json!({"x": 10, "y": 10, "width": 20, "height": 20})).unwrap();
|
||||
drag(&mut app, [20.0, 20.0], [50.0, 20.0], Modifiers::COMMAND);
|
||||
assert!(error_dialogs(&app).is_empty());
|
||||
assert_eq!(photocraft_engine::float_cmds::floating(app.session.active().unwrap()).map(|f| f.offset), Some((30, 0)));
|
||||
let (mut app, layer) = painted();
|
||||
app.session
|
||||
.edit("lock", |doc, _| {
|
||||
doc.layer_mut(layer).unwrap().locks.all = true;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
// ⌘ with the Brush is the Move tool too (#2248).
|
||||
for (tool, m) in [(Tool::RectMarquee, Modifiers::COMMAND), (Tool::Move, Modifiers::NONE), (Tool::Brush, Modifiers::COMMAND)] {
|
||||
app.ui.tool = tool;
|
||||
drag(&mut app, [20.0, 20.0], [40.0, 20.0], m);
|
||||
assert_eq!(error_dialogs(&app), [crate::move_lock::MESSAGE], "{tool:?}");
|
||||
assert!(photocraft_engine::float_cmds::floating(app.session.active().unwrap()).is_none(), "{tool:?}");
|
||||
app.ui.dialogs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Photoshop's cursor over a selection: the move cursor where a marquee press moves the outline,
|
||||
/// scissors where ⌘ (or the Move tool) cuts the selected pixels, a double arrow where ⌥ copies
|
||||
/// them, a hollow arrowhead while they are dragged, and a plain arrow over the floating piece.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
//! Photoshop's "Could not use the move tool because the layer is locked." A Move-tool press (the
|
||||
//! Move tool itself, or ⌘ with a selection tool, `canvas::command_moves_layer`) on a layer it
|
||||
//! can't move opens that message in a dialog instead
|
||||
//! of silently doing nothing: the Background and any position-locked layer when there is no
|
||||
//! selection, and a layer whose selected pixels can't float
|
||||
//! (`photocraft_engine::float_cmds::locked_for_float`) when there is one. As in Photoshop the
|
||||
//! message comes when the pointer starts to drag; a plain click says nothing. OK closes it.
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
use crate::PhotocraftApp;
|
||||
use crate::state::{DialogKind, Tool};
|
||||
|
||||
pub const MESSAGE: &str = "Could not use the move tool because the layer is locked.";
|
||||
|
||||
/// Would a press at document point `p` with `tool` in effect and `mods` held be a move that
|
||||
/// fails because of a lock?
|
||||
pub fn blocked(app: &PhotocraftApp, tool: Tool, p: [f64; 2], mods: egui::Modifiers) -> bool {
|
||||
let Some(st) = app.session.active() else { return false };
|
||||
let floating = photocraft_engine::float_cmds::floating(st).is_some();
|
||||
// The selected pixels: only a fresh cut can be refused.
|
||||
let pixels_locked =
|
||||
|| !floating && st.active_layer.and_then(|id| st.doc.layer(id)).is_some_and(|l| photocraft_engine::float_cmds::locked_for_float(&st.doc, l));
|
||||
// The layers: any of them locked in place refuses the whole move.
|
||||
let layers_locked = || {
|
||||
photocraft_engine::layer_multi_cmds::move_targets(&st.doc, &st.selected_layers()).iter().any(|id| {
|
||||
let locks = st.doc.effective_locks(*id);
|
||||
locks.position || locks.all
|
||||
})
|
||||
};
|
||||
if tool == Tool::Move {
|
||||
// `moves_selected_pixels` is false for a layer whose pixels can't float: then the Move tool
|
||||
// moves the layer, which its position lock refuses too.
|
||||
if crate::move_ui::moves_selected_pixels(app) {
|
||||
return pixels_locked();
|
||||
}
|
||||
return !floating && st.doc.selection.is_some() && pixels_locked() || layers_locked();
|
||||
}
|
||||
if crate::canvas::command_moves_layer(app, tool, p, mods) {
|
||||
return layers_locked();
|
||||
}
|
||||
crate::canvas::selection_drag_kind(app, tool, p, mods) == Some(true) && mods.command && pixels_locked()
|
||||
}
|
||||
|
||||
/// Opens the message. The dialog is ordinary UI state (`ui.dialog.confirm` closes it).
|
||||
pub fn prompt(app: &mut PhotocraftApp) {
|
||||
app.ui.open_dialog(DialogKind::Error, json!({"message": tl!(MESSAGE)}).as_object().cloned().unwrap_or_default());
|
||||
}
|
||||
Loading…
Reference in New Issue