Skip to content

Commit

Permalink
Fix drag target processing and update panel background color (#3635)
Browse files Browse the repository at this point in the history
* Update to only confine floating widget to ninezone area on drag end and get proper widget/panel-section id when docking.

* Fix line height of overflow widget tabs when only icons are shown.

* Updates to avoid svg-loader component from loading svg multiple times.

* update unit test

* update panel background to use same as buic-background-control so dispabled itwin ui components display properly

* rush change

* update buic-background-panel to match buic-background-dialog

* fix lint error

* extract api
  • Loading branch information
bsteinbk committed May 20, 2022
1 parent f65ecc1 commit efe4c6f
Show file tree
Hide file tree
Showing 17 changed files with 211 additions and 107 deletions.
6 changes: 6 additions & 0 deletions common/api/appui-layout-react.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,9 @@ export function isHorizontalPanelState(state: PanelState): state is HorizontalPa
// @internal (undocumented)
export function isPanelLocation(location: TabLocation): location is PanelLocation;

// @internal (undocumented)
export function isPanelTarget(target: DragTarget): target is PanelTarget_2;

// @internal (undocumented)
export function isPopoutLocation(location: TabLocation): location is PopoutLocation;

Expand All @@ -1045,6 +1048,9 @@ export function isPopoutWidgetLocation(location: WidgetLocation): location is Po
// @internal (undocumented)
export function isTabTarget(target: DragTarget): target is TabTarget;

// @internal (undocumented)
export function isWidgetTarget(target: DragTarget): target is WidgetTarget_2;

// @beta @deprecated
export class Item extends React.PureComponent<ItemProps> {
// (undocumented)
Expand Down
2 changes: 2 additions & 0 deletions common/api/summary/appui-layout-react.exports.csv
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,11 @@ internal;isFloatingWidgetLocation(location: WidgetLocation): location is Floatin
internal;isHorizontalPanelSide: (side: PanelSide) => side is HorizontalPanelSide
internal;isHorizontalPanelState(state: PanelState): state is HorizontalPanelState
internal;isPanelLocation(location: TabLocation): location is PanelLocation
internal;isPanelTarget(target: DragTarget): target is PanelTarget_2
internal;isPopoutLocation(location: TabLocation): location is PopoutLocation
internal;isPopoutWidgetLocation(location: WidgetLocation): location is PopoutLocation
internal;isTabTarget(target: DragTarget): target is TabTarget
internal;isWidgetTarget(target: DragTarget): target is WidgetTarget_2
beta;Item
deprecated;Item
beta;ItemProps
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/appui-layout-react",
"comment": "Fix processing of widget container dragging to empty panel.",
"type": "none"
}
],
"packageName": "@itwin/appui-layout-react"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/components-react",
"comment": "Fix processing of widget container dragging to empty panel.",
"type": "none"
}
],
"packageName": "@itwin/components-react"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/core-react",
"comment": "Fix svg-loader to only fetch svg data once. Also update buic-background-panel to use buic-background-1 so disabled itwin-ui components are properly displayed.",
"type": "none"
}
],
"packageName": "@itwin/core-react"
}
10 changes: 10 additions & 0 deletions ui/appui-layout-react/src/appui-layout-react/base/DragManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,16 @@ export function isTabTarget(target: DragTarget): target is TabTarget {
return target.type === "tab";
}

/** @internal */
export function isWidgetTarget(target: DragTarget): target is WidgetTarget {
return target.type === "widget";
}

/** @internal */
export function isPanelTarget(target: DragTarget): target is PanelTarget {
return target.type === "panel";
}

interface BaseDragItemInfo {
initialPointerPosition: Point;
lastPointerPosition: Point;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,7 @@ export const NineZoneStateReducer: (state: NineZoneState, action: NineZoneAction
const floatingWidget = state.floatingWidgets.byId[action.floatingWidgetId];
assert(!!floatingWidget);
const newBounds = Rectangle.create(floatingWidget.bounds).offset(action.dragBy);
const nzBounds = Rectangle.createFromSize(state.size);
const newContainedBounds = newBounds.containIn(nzBounds);
setRectangleProps(floatingWidget.bounds, newContainedBounds);
setRectangleProps(floatingWidget.bounds, newBounds);
return;
}
case "WIDGET_DRAG_END": {
Expand Down Expand Up @@ -524,10 +522,11 @@ export const NineZoneStateReducer: (state: NineZoneState, action: NineZoneAction
id: target.newWidgetId,
};
} else {
state.panels[target.side].widgets = [target.newWidgetId];
state.widgets[target.newWidgetId] = {
const panelSectionId = getWidgetPanelSectionId(target.side, 0);
state.panels[target.side].widgets = [panelSectionId];
state.widgets[panelSectionId] = {
...draggedWidget,
id: target.newWidgetId,
id: panelSectionId,
minimized: false,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import "./FloatingTab.scss";
import classnames from "classnames";
import * as React from "react";
import { isTabTarget, useDragTab, UseDragTabArgs } from "../base/DragManager";
import { isPanelTarget, isTabTarget, isWidgetTarget, useDragTab, UseDragTabArgs } from "../base/DragManager";
import { DraggedTabStateContext, getUniqueId, NineZoneDispatchContext, TabsStateContext } from "../base/NineZone";
import { TabTargetState } from "../base/NineZoneState";
import { getWidgetPanelSectionId, TabTargetState } from "../base/NineZoneState";
import { CssProperties } from "../utilities/Css";

/** Component that displays a floating tab.
Expand All @@ -35,9 +35,16 @@ export function FloatingTab() {
...dragTarget,
};
} else if (dragTarget) {
let newWidgetId = getUniqueId();
if (isWidgetTarget(dragTarget)) {
newWidgetId = getWidgetPanelSectionId(dragTarget.side, dragTarget.widgetIndex);
} else /* istanbul ignore else */ if (isPanelTarget(dragTarget)) {
newWidgetId = getWidgetPanelSectionId(dragTarget.side, 0);
}

target = {
...dragTarget,
newWidgetId: getUniqueId(),
newWidgetId,
};
} else {
target = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
line-height: 2em;
padding-left: 0.75em;
padding-right: 0.75em;
height: 1.75em;

>span {
margin-right: 3em;
Expand Down
4 changes: 2 additions & 2 deletions ui/appui-layout-react/src/test/base/NineZoneState.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,12 @@ describe("NineZoneStateReducer", () => {
floatingWidgetId: "fw1",
target: {
type: "panel",
newWidgetId: "newId",
newWidgetId: "leftStart",
side: "left",
},
});
newState.panels.left.widgets.length.should.eq(1);
newState.panels.left.widgets[0].should.eq("newId");
newState.panels.left.widgets[0].should.eq("leftStart");
});
});
});
Expand Down
53 changes: 50 additions & 3 deletions ui/appui-layout-react/src/test/widget/FloatingTab.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe("FloatingTab", () => {
const dispatch = sinon.stub<NineZoneDispatch>();
let nineZone = createNineZoneState();
nineZone = addPanelWidget(nineZone, "left", "leftStart", ["t1"]);
nineZone = addTab(nineZone, "t1", { label: "tab 1", preferredFloatingWidgetSize: {width: 33, height: 33}});
nineZone = addTab(nineZone, "t1", { label: "tab 1", preferredFloatingWidgetSize: { width: 33, height: 33 } });
nineZone = produce(nineZone, (draft) => {
draft.draggedTab = createDraggedTabState("t1", {
position: new Point(10, 20).toProps(),
Expand Down Expand Up @@ -111,7 +111,7 @@ describe("FloatingTab", () => {
const dispatch = sinon.stub<NineZoneDispatch>();
let nineZone = createNineZoneState();
nineZone = addPanelWidget(nineZone, "left", "leftEnd", ["t1"]);
nineZone = addTab(nineZone, "t1", { label: "tab 1", preferredFloatingWidgetSize: {width: 33, height: 33} });
nineZone = addTab(nineZone, "t1", { label: "tab 1", preferredFloatingWidgetSize: { width: 33, height: 33 } });
nineZone = produce(nineZone, (draft) => {
draft.draggedTab = createDraggedTabState("t1", {
position: new Point(10, 20).toProps(),
Expand Down Expand Up @@ -150,7 +150,7 @@ describe("FloatingTab", () => {
const dispatch = sinon.stub<NineZoneDispatch>();
let nineZone = createNineZoneState();
nineZone = addPanelWidget(nineZone, "left", "w1", ["t1"]);
nineZone = addTab(nineZone, "t1", { label: "tab 1", isFloatingStateWindowResizable: true, preferredFloatingWidgetSize: {width: 50, height: 50} });
nineZone = addTab(nineZone, "t1", { label: "tab 1", isFloatingStateWindowResizable: true, preferredFloatingWidgetSize: { width: 50, height: 50 } });
nineZone = produce(nineZone, (draft) => {
draft.draggedTab = createDraggedTabState("t1", {
position: new Point(10, 20).toProps(),
Expand Down Expand Up @@ -231,4 +231,51 @@ describe("FloatingTab", () => {
},
})).should.true;
});

it("should dispatch WIDGET_TAB_DRAG_END with widget target", () => {
const dragManager = React.createRef<DragManager>();
const dispatch = sinon.stub<NineZoneDispatch>();
let nineZone = createNineZoneState();
nineZone = addPanelWidget(nineZone, "left", "w1", ["t1"]);
nineZone = addTab(nineZone, "t1", { label: "tab 1" });
nineZone = produce(nineZone, (draft) => {
draft.draggedTab = createDraggedTabState("t1", {
position: new Point(10, 20).toProps(),
});
});
render(
<TestNineZoneProvider
state={nineZone}
dispatch={dispatch}
dragManagerRef={dragManager}
>
<FloatingTab />
</TestNineZoneProvider>,
);
act(() => {
dragManager.current!.handleDragStart({
info: createDragItemInfo(),
item: {
type: "tab",
id: "t1",
},
});
dragManager.current!.handleTargetChanged({
type: "widget",
side: "right",
widgetIndex: 0,
});
fireEvent.mouseUp(document);
});
dispatch.calledOnceWithExactly(sinon.match({
type: "WIDGET_TAB_DRAG_END",
id: "t1",
target: {
type: "widget",
side: "right",
widgetIndex: 0,
},
})).should.true;
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ exports[`PopoutToggle should render 1`] = `
>
<div>
<svg-loader
id="svg-id"
src="undefined"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export class CustomNumberEditor extends React.PureComponent<PropertyEditorProps,
}

const displayValue = (record.value.displayValue && record.value.displayValue.length > 0) ? record.value.displayValue : /* istanbul ignore next */ (this._formatParams as CustomFormattedNumberParams).formatFunction(record.value.value as number);
propertyValue = this._lastValidValue ? { ...this._lastValidValue } : {
propertyValue = this._lastValidValue ? { ...this._lastValidValue } : /* istanbul ignore next */ {
valueFormat: PropertyValueFormat.Primitive,
value: record.value.value,
displayValue,
Expand Down Expand Up @@ -227,14 +227,14 @@ export class CustomNumberEditor extends React.PureComponent<PropertyEditorProps,
}

private _resetToLastValidDisplayValue() {
const initialDisplayValue = (this._lastValidValue && (this._lastValidValue as PrimitiveValue).displayValue) ?? this._getInitialDisplayValue();
const initialDisplayValue = (this._lastValidValue && (this._lastValidValue as PrimitiveValue).displayValue) ?? (/* istanbul ignore next */ this._getInitialDisplayValue());
this.setState({ inputValue: initialDisplayValue });
}

private _onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
// istanbul ignore else
if (e.key === SpecialKey.Escape) {
const initialDisplayValue = (this._lastValidValue && (this._lastValidValue as PrimitiveValue).displayValue) ?? this._getInitialDisplayValue();
const initialDisplayValue = (this._lastValidValue && (this._lastValidValue as PrimitiveValue).displayValue) ?? (/* istanbul ignore next */ this._getInitialDisplayValue());
if (initialDisplayValue !== this.state.inputValue) {
e.preventDefault();
e.stopPropagation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
exports[`ImageRenderer render renders svg 1`] = `
"<div><i class=\\"icon core-svg-icon\\"><div><svg-loader encoding=\\"UTF-8\\" version=\\"1.0\\" src=\\"<?xml\\">
id=\\"svg-id\\"&gt;</svg-loader></div></i></div>"
&gt;</svg-loader></div></i></div>"
`;
Loading

0 comments on commit efe4c6f

Please sign in to comment.