Skip to content

Commit

Permalink
Allow to switch to fill or pick segment tool when eraser is active (#…
Browse files Browse the repository at this point in the history
…8314)

* implement shift and ctrl-shift modifier for the eraser (switch to pick or fill tool)

* tweak highlighted color in tree and segments tab for light theme

* update changelog

* prepare merge for import sorting pr
  • Loading branch information
philippotto authored Jan 9, 2025
1 parent e007e41 commit 466ce63
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 23 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Added the option for "Selective Segment Visibility" for segmentation layers. Select this option in the left sidebar to only show segments that are currently active or hovered. [#8281](https://github.com/scalableminds/webknossos/pull/8281)
- A segment can be activated with doubleclick now. [#8281](https://github.com/scalableminds/webknossos/pull/8281)
- It is now possible to select the magnification of the layers on which an AI model will be trained. [#8266](https://github.com/scalableminds/webknossos/pull/8266)
- When the eraser tool is active, one can switch temporarily to the fill-segment tool by pressing shift and ctrl. Only pressing shift, switches to the pick-segment tool. [#8314](https://github.com/scalableminds/webknossos/pull/8314)
- Enabled auto sorting of Typescript imports in Biome linter. [#8313](https://github.com/scalableminds/webknossos/pull/8313)


### Changed
- Renamed "resolution" to "magnification" in more places within the codebase, including local variables. [#8168](https://github.com/scalableminds/webknossos/pull/8168)
- Layer names are now allowed to contain `$` as special characters. [#8241](https://github.com/scalableminds/webknossos/pull/8241)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,12 +497,26 @@ export class EraseTool {
leftDownMove: (_delta: Point2, pos: Point2) => {
VolumeHandlers.handleMoveForDrawOrErase(pos);
},
leftMouseDown: (pos: Point2, plane: OrthoView, _event: MouseEvent) => {
leftMouseDown: (pos: Point2, plane: OrthoView, event: MouseEvent) => {
if (event.shiftKey || event.ctrlKey || event.metaKey) {
return;
}

VolumeHandlers.handleEraseStart(pos, plane);
},
leftMouseUp: () => {
VolumeHandlers.handleEndForDrawOrErase();
},
leftClick: (pos: Point2, plane: OrthoView, event: MouseEvent) => {
const isControlOrMetaPressed = event.ctrlKey || event.metaKey;
if (event.shiftKey) {
if (isControlOrMetaPressed) {
VolumeHandlers.handleFloodFill(pos, plane);
} else {
VolumeHandlers.handlePickCell(pos);
}
}
},
rightClick: (pos: Point2, plane: OrthoView, event: MouseEvent, isTouch: boolean) => {
SkeletonHandlers.handleOpenContextMenu(planeView, pos, plane, isTouch, event);
},
Expand Down
41 changes: 25 additions & 16 deletions frontend/javascripts/oxalis/model/accessors/tool_accessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,47 +350,56 @@ export const getDisabledInfoForTools = reuseInstanceOnEquality(_getDisabledInfoF
export function adaptActiveToolToShortcuts(
activeTool: AnnotationTool,
isShiftPressed: boolean,
isControlPressed: boolean,
isControlOrMetaPressed: boolean,
isAltPressed: boolean,
): AnnotationTool {
if (!isShiftPressed && !isControlPressed && !isAltPressed) {
if (!isShiftPressed && !isControlOrMetaPressed && !isAltPressed) {
// No modifier is pressed
return activeTool;
}

if (
activeTool === AnnotationToolEnum.MOVE ||
activeTool === AnnotationToolEnum.ERASE_BRUSH ||
activeTool === AnnotationToolEnum.ERASE_TRACE ||
activeTool === AnnotationToolEnum.QUICK_SELECT ||
activeTool === AnnotationToolEnum.PROOFREAD ||
activeTool === AnnotationToolEnum.LINE_MEASUREMENT ||
activeTool === AnnotationToolEnum.AREA_MEASUREMENT
) {
// These tools do not have any modifier-related behavior currently (except for ALT
// which is already handled below)
} else if (
activeTool === AnnotationToolEnum.ERASE_BRUSH ||
activeTool === AnnotationToolEnum.ERASE_TRACE
) {
if (isShiftPressed) {
if (isControlOrMetaPressed) {
return AnnotationToolEnum.FILL_CELL;
} else {
return AnnotationToolEnum.PICK_CELL;
}
}
} else {
if (activeTool === AnnotationToolEnum.SKELETON) {
// The "skeleton" tool is not changed right now (since actions such as moving a node
// don't have a dedicated tool). The only exception is "Alt" which switches to the move tool.
if (isAltPressed && !isControlPressed && !isShiftPressed) {
if (isAltPressed && !isControlOrMetaPressed && !isShiftPressed) {
return AnnotationToolEnum.MOVE;
}

return activeTool;
}

if (isShiftPressed && !isControlPressed && !isAltPressed) {
// Only shift is pressed. Switch to the picker
return AnnotationToolEnum.PICK_CELL;
}

if (isControlPressed && isShiftPressed && !isAltPressed) {
// Control and shift switch to the eraser
if (activeTool === AnnotationToolEnum.BRUSH) {
return AnnotationToolEnum.ERASE_BRUSH;
} else if (activeTool === AnnotationToolEnum.TRACE) {
return AnnotationToolEnum.ERASE_TRACE;
if (isShiftPressed && !isAltPressed) {
if (!isControlOrMetaPressed) {
// Only shift is pressed. Switch to the picker
return AnnotationToolEnum.PICK_CELL;
} else {
// Control and shift switch to the eraser
if (activeTool === AnnotationToolEnum.BRUSH) {
return AnnotationToolEnum.ERASE_BRUSH;
} else if (activeTool === AnnotationToolEnum.TRACE) {
return AnnotationToolEnum.ERASE_TRACE;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import type {
Vector2,
Vector3,
} from "oxalis/constants";
import Constants, { FillModeEnum, Unicode } from "oxalis/constants";
import Constants, { AnnotationToolEnum, FillModeEnum, Unicode } from "oxalis/constants";

import _ from "lodash";
import { getDatasetBoundingBox, getMagInfo } from "oxalis/model/accessors/dataset_accessor";
import { getActiveMagIndexForLayer } from "oxalis/model/accessors/flycam_accessor";
import { getDisabledInfoForTools } from "oxalis/model/accessors/tool_accessor";
import { enforceActiveVolumeTracing } from "oxalis/model/accessors/volumetracing_accessor";
import { addUserBoundingBoxAction } from "oxalis/model/actions/annotation_actions";
import { setBusyBlockingInfoAction } from "oxalis/model/actions/ui_actions";
Expand Down Expand Up @@ -117,8 +118,9 @@ function* getBoundingBoxForFloodFill(

function* handleFloodFill(floodFillAction: FloodFillAction): Saga<void> {
const allowUpdate = yield* select((state) => state.tracing.restrictions.allowUpdate);
const disabledInfosForTools = yield* select(getDisabledInfoForTools);

if (!allowUpdate) {
if (!allowUpdate || disabledInfosForTools[AnnotationToolEnum.FILL_CELL].isDisabled) {
return;
}

Expand Down
9 changes: 7 additions & 2 deletions frontend/javascripts/oxalis/view/input_catcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,20 @@ function InputCatcher({
const activeTool = useSelector((state: OxalisState) => state.uiInformation.activeTool);

const isShiftPressed = useKeyPress("Shift");
const isControlPressed = useKeyPress("ControlOrMeta");
const isControlOrMetaPressed = useKeyPress("ControlOrMeta");
const isAltPressed = useKeyPress("Alt");

const adaptedTool =
viewportID === ArbitraryViews.arbitraryViewport
? AnnotationToolEnum.SKELETON
: viewportID === OrthoViews.TDView
? AnnotationToolEnum.MOVE
: adaptActiveToolToShortcuts(activeTool, isShiftPressed, isControlPressed, isAltPressed);
: adaptActiveToolToShortcuts(
activeTool,
isShiftPressed,
isControlOrMetaPressed,
isAltPressed,
);

return (
<div
Expand Down
7 changes: 6 additions & 1 deletion frontend/javascripts/theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const globalDesignToken: Partial<AliasToken> = {
'"Nunito", "Monospaced Number", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;',
};

const lightGlobalToken = theme.getDesignToken({
token: globalDesignToken,
algorithm: theme.defaultAlgorithm,
});

const darkGlobalToken = theme.getDesignToken({
token: globalDesignToken,
algorithm: theme.darkAlgorithm,
Expand Down Expand Up @@ -87,7 +92,7 @@ export function getAntdTheme(userTheme: Theme) {
},
Tree: {
colorBgContainer: "transparent",
directoryNodeSelectedBg: ColorWKBlue,
nodeSelectedBg: lightGlobalToken.blue3,
titleHeight: 20, // default is 24px,
marginXXS: 2, // default is 4px; adjust to match checkboxes because of smaller titleHeight
},
Expand Down

0 comments on commit 466ce63

Please sign in to comment.