Skip to content

Commit adbd08f

Browse files
authored
fix: Merge pull request #124 from UniversalDataTool/classification-hotkeys
add classification hotkeys
2 parents 7a8209d + f19e49f commit adbd08f

File tree

4 files changed

+121
-7
lines changed

4 files changed

+121
-7
lines changed

src/Annotator/reducers/general-reducer.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ export default (state: MainLayoutState, action: Action) => {
124124
case "SELECT_IMAGE": {
125125
return setNewImage(action.image, action.imageIndex)
126126
}
127+
case "SELECT_CLASSIFICATION": {
128+
return setIn(state, ["selectedCls"], action.cls)
129+
}
127130
case "CHANGE_REGION": {
128131
const regionIndex = getRegionIndex(action.region)
129132
if (regionIndex === null) return state
@@ -132,6 +135,7 @@ export default (state: MainLayoutState, action: Action) => {
132135
state = saveToHistory(state, "Change Region Classification")
133136
const clsIndex = state.regionClsList.indexOf(action.region.cls)
134137
if (clsIndex !== -1) {
138+
state = setIn(state, ["selectedCls"], action.region.cls)
135139
action.region.color = colors[clsIndex % colors.length]
136140
}
137141
}
@@ -498,14 +502,12 @@ export default (state: MainLayoutState, action: Action) => {
498502
}
499503

500504
let newRegion
501-
let defaultRegionCls = undefined,
505+
let defaultRegionCls = state.selectedCls,
502506
defaultRegionColor = "#ff0000"
503-
if (activeImage && (activeImage.regions || []).length > 0) {
504-
defaultRegionCls = activeImage.regions.slice(-1)[0].cls
505-
const clsIndex = (state.regionClsList || []).indexOf(defaultRegionCls)
506-
if (clsIndex !== -1) {
507-
defaultRegionColor = colors[clsIndex % colors.length]
508-
}
507+
508+
const clsIndex = (state.regionClsList || []).indexOf(defaultRegionCls)
509+
if (clsIndex !== -1) {
510+
defaultRegionColor = colors[clsIndex % colors.length]
509511
}
510512

511513
switch (state.selectedTool) {

src/ClassSelectionMenu/index.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React, { useEffect } from "react"
2+
import { styled } from "@material-ui/core/styles"
3+
import Box from "@material-ui/core/Box"
4+
import * as muiColors from "@material-ui/core/colors"
5+
import SidebarBoxContainer from "../SidebarBoxContainer"
6+
import colors from "../colors"
7+
import BallotIcon from "@material-ui/icons/Ballot"
8+
import capitalize from "lodash/capitalize"
9+
import classnames from "classnames"
10+
11+
const LabelContainer = styled("div")({
12+
display: "flex",
13+
paddingTop: 4,
14+
paddingBottom: 4,
15+
paddingLeft: 16,
16+
paddingRight: 16,
17+
alignItems: "center",
18+
cursor: "pointer",
19+
opacity: 0.7,
20+
backgroundColor: "#fff",
21+
"&:hover": {
22+
opacity: 1,
23+
},
24+
"&.selected": {
25+
opacity: 1,
26+
fontWeight: "bold",
27+
},
28+
})
29+
const Circle = styled("div")({
30+
width: 12,
31+
height: 12,
32+
borderRadius: 12,
33+
marginRight: 8,
34+
})
35+
const Label = styled("div")({
36+
fontSize: 11,
37+
})
38+
const DashSep = styled("div")({
39+
flexGrow: 1,
40+
borderBottom: `2px dotted ${muiColors.grey[300]}`,
41+
marginLeft: 8,
42+
marginRight: 8,
43+
})
44+
const Number = styled("div")({
45+
fontSize: 11,
46+
textAlign: "center",
47+
minWidth: 14,
48+
paddingTop: 2,
49+
paddingBottom: 2,
50+
fontWeight: "bold",
51+
color: muiColors.grey[700],
52+
})
53+
54+
export const ClassSelectionMenu = ({
55+
selectedCls,
56+
regionClsList,
57+
onSelectCls,
58+
}) => {
59+
useEffect(() => {
60+
const keyMapping = {}
61+
for (let i = 0; i < 9 && i < regionClsList.length; i++) {
62+
keyMapping[i + 1] = () => onSelectCls(regionClsList[i])
63+
}
64+
const onKeyDown = (e) => {
65+
if (keyMapping[e.key]) {
66+
keyMapping[e.key]()
67+
e.preventDefault()
68+
e.stopPropagation()
69+
}
70+
}
71+
window.addEventListener("keydown", onKeyDown)
72+
return () => window.removeEventListener("keydown", onKeyDown)
73+
}, [regionClsList, selectedCls])
74+
75+
return (
76+
<SidebarBoxContainer
77+
title="Classifications"
78+
subTitle=""
79+
icon={<BallotIcon style={{ color: muiColors.grey[700] }} />}
80+
expandedByDefault
81+
>
82+
{regionClsList.map((label, index) => (
83+
<LabelContainer
84+
className={classnames({ selected: label === selectedCls })}
85+
onClick={() => onSelectCls(label)}
86+
>
87+
<Circle style={{ backgroundColor: colors[index % colors.length] }} />
88+
<Label className={classnames({ selected: label === selectedCls })}>
89+
{capitalize(label)}
90+
</Label>
91+
<DashSep />
92+
<Number className={classnames({ selected: label === selectedCls })}>
93+
{index < 9 ? `Key [${index + 1}]` : ""}
94+
</Number>
95+
</LabelContainer>
96+
))}
97+
<Box pb={2} />
98+
</SidebarBoxContainer>
99+
)
100+
}
101+
102+
export default ClassSelectionMenu

src/MainLayout/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import ImageSelector from "../ImageSelectorSidebarBox"
2828
import HistorySidebarBox from "../HistorySidebarBox"
2929
import useEventCallback from "use-event-callback"
3030
import getHotkeyHelpText from "../utils/get-hotkey-help-text"
31+
import ClassSelectionMenu from "../ClassSelectionMenu"
3132

3233
const emptyArr = []
3334
const useStyles = makeStyles(styles)
@@ -332,6 +333,13 @@ export const MainLayout = ({
332333
state.taskDescription && (
333334
<TaskDescription description={state.taskDescription} />
334335
),
336+
state.regionClsList && (
337+
<ClassSelectionMenu
338+
selectedCls={state.selectedCls}
339+
regionClsList={state.regionClsList}
340+
onSelectCls={action("SELECT_CLASSIFICATION", "cls")}
341+
/>
342+
),
335343
state.labelImages && (
336344
<TagsSidebarBox
337345
currentImage={activeImage}

src/MainLayout/types.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export type MainLayoutStateBase = {|
6969
showPointDistances?: boolean,
7070
pointDistancePrecision?: number,
7171
selectedTool: ToolEnum,
72+
selectedCls?: string,
7273
mode: Mode,
7374
taskDescription: string,
7475
allowedArea?: { x: number, y: number, w: number, h: number },
@@ -152,3 +153,4 @@ export type Action =
152153
| {| type: "HEADER_BUTTON_CLICKED", buttonName: string |}
153154
| {| type: "SELECT_TOOL", selectedTool: ToolEnum |}
154155
| {| type: "CANCEL" |}
156+
| {| type: "SELECT_CLASSIFICATION", cls: string |}

0 commit comments

Comments
 (0)