diff --git a/src/components/floorplan-editor/FloorplanEditorView.tsx b/src/components/floorplan-editor/FloorplanEditorView.tsx index c57ff6c..2e27638 100644 --- a/src/components/floorplan-editor/FloorplanEditorView.tsx +++ b/src/components/floorplan-editor/FloorplanEditorView.tsx @@ -234,7 +234,7 @@ export const FloorplanEditorView: FC = () => onUndo={ undo } onRedo={ redo } panMode={ panMode } - onTogglePanMode={ () => setPanMode(v => !v) } + setPanMode={ setPanMode } /> diff --git a/src/components/floorplan-editor/views/FloorplanToolbar.tsx b/src/components/floorplan-editor/views/FloorplanToolbar.tsx index d941722..8f24f9a 100644 --- a/src/components/floorplan-editor/views/FloorplanToolbar.tsx +++ b/src/components/floorplan-editor/views/FloorplanToolbar.tsx @@ -12,7 +12,14 @@ type Props = { onUndo?: () => void; onRedo?: () => void; panMode?: boolean; - onTogglePanMode?: () => void; + /** + * Imperative setter for pan mode. Receiving the explicit + * value (not a toggle) lets every tool button switch the + * hand off on click without needing to know its current + * state — the hand is part of the same exclusive tool group + * as the brushes, so picking any brush has to clear it. + */ + setPanMode?: (next: boolean) => void; }; const BRUSH_BUTTONS: { id: string; mode: FloorActionMode; iconClass: string }[] = [ @@ -23,45 +30,71 @@ const BRUSH_BUTTONS: { id: string; mode: FloorActionMode; iconClass: string }[] { id: 'tool-door', mode: 'DOOR', iconClass: 'icon-set-door' } ]; -export const FloorplanToolbar: FC = ({ state, dispatch, canUndo, canRedo, onUndo, onRedo, panMode, onTogglePanMode }) => +export const FloorplanToolbar: FC = ({ state, dispatch, canUndo, canRedo, onUndo, onRedo, panMode, setPanMode }) => { + // The hand and the brush buttons form a single exclusive tool + // group. Picking ANY other tool clears pan mode so the user + // never ends up in 'I clicked SET but the canvas still pans'. + const exitPan = () => + { + if(panMode && setPanMode) setPanMode(false); + }; + return ( - { LocalizeText('floor.plan.editor.draw.mode') } - { BRUSH_BUTTONS.map(b => ( - dispatch({ type: 'BRUSH_SET', action: b.mode }) } - /> - )) } - 0 ? 'icon-set-deselect' : 'icon-set-select' }` } - onClick={ () => dispatch({ type: 'SELECT_ALL' }) } - /> - dispatch({ type: 'SQUARE_SELECT_TOGGLE' }) } - /> - { onTogglePanMode && ( + { setPanMode && ( setPanMode(!panMode) } > ) } + { LocalizeText('floor.plan.editor.draw.mode') } + { BRUSH_BUTTONS.map(b => + { + const active = state.brush.action === b.mode && !panMode; + + return ( + + { + exitPan(); + dispatch({ type: 'BRUSH_SET', action: b.mode }); + } } + /> + ); + }) } + 0 ? 'icon-set-deselect' : 'icon-set-select' }` } + onClick={ () => + { + exitPan(); + dispatch({ type: 'SELECT_ALL' }); + } } + /> + + { + exitPan(); + dispatch({ type: 'SQUARE_SELECT_TOGGLE' }); + } } + /> { (onUndo || onRedo) && (