Skip to content

Commit

Permalink
Auto-focus AccuDraw distance field (#753)
Browse files Browse the repository at this point in the history
* Render distance field before angle field.

* Update getInputRef

* Auto-focus distance field in polar mode.

* NextVersion

* rush change

* Add PR number
  • Loading branch information
GerardasB authored Mar 5, 2024
1 parent bb3f30f commit 7ddc375
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/appui-react",
"comment": "Fix polar mode AccuDraw input focus by correctly focusing the distance field.",
"type": "none"
}
],
"packageName": "@itwin/appui-react"
}
4 changes: 3 additions & 1 deletion docs/changehistory/NextVersion.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Table of contents:
### Changes

- Removed arrow from status bar popup. [#750](https://github.com/iTwin/appui/pull/750)
- Render AccuDraw Distance field above Angle field when in Polar mode. [#753](https://github.com/iTwin/appui/pull/753)

### Fixes

- Fix the issue when right-click + left-click starts a widget drag interaction. #730
- Fix the issue when right-click + left-click starts a widget drag interaction. [#730](https://github.com/iTwin/appui/pull/730)
- Fix polar mode AccuDraw input focus by correctly focusing the distance field. [#753](https://github.com/iTwin/appui/pull/753)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion e2e-tests/tests/accudraw/accudraw-widget.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ test("accudraw widget test", async ({ page, baseURL }) => {

const accudrawWidget = page
.locator("div")
.filter({ hasText: /^angledistance$/ })
.filter({ hasText: /^distanceangle$/ })
.first();
await expect(accudrawWidget).toHaveScreenshot();
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
106 changes: 66 additions & 40 deletions ui/appui-react/src/appui-react/accudraw/AccuDrawFieldContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,28 +118,59 @@ export function AccuDrawFieldContainer(props: AccuDrawFieldContainerProps) {
React.CSSProperties | undefined
>(undefined);

const getInputRef = (field: ItemField): React.RefObject<HTMLInputElement> => {
let inputRef: React.RefObject<HTMLInputElement>;
const getFieldInput = (field: ItemField) => {
switch (field) {
case ItemField.X_Item:
inputRef = xInputRef;
break;
return getCurrent(xInputRef);
case ItemField.Y_Item:
inputRef = yInputRef;
break;
return getCurrent(yInputRef);
case ItemField.Z_Item:
inputRef = zInputRef;
break;
return getCurrent(zInputRef);
case ItemField.ANGLE_Item:
inputRef = angleInputRef;
break;
return getCurrent(angleInputRef);
case ItemField.DIST_Item:
inputRef = distanceInputRef;
break;
return getCurrent(distanceInputRef);
}
return inputRef;
};

const getInputToFocus = React.useCallback((field: ItemField | undefined) => {
const fieldInput = field === undefined ? undefined : getFieldInput(field);
if (fieldInput) {
if (document.activeElement === fieldInput) return undefined;
return fieldInput;
}

const focusedInput = [
xInputRef,
yInputRef,
zInputRef,
angleInputRef,
distanceInputRef,
].find((inputRef) => document.activeElement === inputRef.current);

// One of AccuDraw input fields is focused already.
if (focusedInput) return undefined;

// Focus one of fallback fields.
let fallbackInput = getFieldInput(ItemField.DIST_Item);
if (fallbackInput) return fallbackInput;

fallbackInput = getFieldInput(ItemField.X_Item);
return fallbackInput;
}, []);

// Moves focus to `field` input if not focused OR fallbacks to default field if none of accudraw fields are focused.
const setFocusToField = React.useCallback(
(field: ItemField | undefined) => {
const input = getInputToFocus(field);
if (!input) return;

input.focus();
input.select();
},
[getInputToFocus]
);

React.useEffect(() => {
return FrameworkAccuDraw.onAccuDrawSetFieldLockEvent.addListener((args) => {
switch (args.field) {
Expand All @@ -162,16 +193,6 @@ export function AccuDrawFieldContainer(props: AccuDrawFieldContainerProps) {
});
}, []);

const setFocusToField = React.useCallback((field: ItemField) => {
const inputRef = getInputRef(field);

// istanbul ignore else
if (inputRef.current && document.activeElement !== inputRef.current) {
inputRef.current.focus();
inputRef.current.select();
}
}, []);

React.useEffect(() => {
return FrameworkAccuDraw.onAccuDrawSetFieldFocusEvent.addListener(
(args) => {
Expand All @@ -183,7 +204,7 @@ export function AccuDrawFieldContainer(props: AccuDrawFieldContainerProps) {

React.useEffect(() => {
return FrameworkAccuDraw.onAccuDrawGrabInputFocusEvent.addListener(() => {
if (focusField.current) setFocusToField(focusField.current);
setFocusToField(focusField.current);
});
}, [setFocusToField]);

Expand Down Expand Up @@ -426,22 +447,6 @@ export function AccuDrawFieldContainer(props: AccuDrawFieldContainerProps) {
)}
{mode === CompassMode.Polar && (
<>
<AccuDrawInputField
ref={angleInputRef}
isLocked={angleLock}
className="uifw-accudraw-angle-value"
style={angleStyle}
field={ItemField.ANGLE_Item}
id={`uifw-accudraw-angle-${containerIndex}`}
data-testid="uifw-accudraw-angle"
label={angleLabel}
iconSpec={angleIcon}
valueChangedDelay={delay}
onValueChanged={(stringValue) =>
handleValueChanged(ItemField.ANGLE_Item, stringValue)
}
onEscPressed={handleEscPressed}
/>
<AccuDrawInputField
ref={distanceInputRef}
isLocked={distanceLock}
Expand All @@ -458,8 +463,29 @@ export function AccuDrawFieldContainer(props: AccuDrawFieldContainerProps) {
}
onEscPressed={handleEscPressed}
/>
<AccuDrawInputField
ref={angleInputRef}
isLocked={angleLock}
className="uifw-accudraw-angle-value"
style={angleStyle}
field={ItemField.ANGLE_Item}
id={`uifw-accudraw-angle-${containerIndex}`}
data-testid="uifw-accudraw-angle"
label={angleLabel}
iconSpec={angleIcon}
valueChangedDelay={delay}
onValueChanged={(stringValue) =>
handleValueChanged(ItemField.ANGLE_Item, stringValue)
}
onEscPressed={handleEscPressed}
/>
</>
)}
</div>
);
}

function getCurrent<T>(ref: React.RefObject<T>) {
if (ref.current === null) return undefined;
return ref.current;
}

0 comments on commit 7ddc375

Please sign in to comment.