Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resize Popout to fit content on popout #557

Merged
merged 47 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
205c46b
Resize popout widgets to fit content
joehenry9498 Oct 24, 2023
e3e37c9
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Oct 24, 2023
db0da91
Changelogs
joehenry9498 Oct 24, 2023
6724b99
Move size calculation to internal method
joehenry9498 Oct 25, 2023
56b3ad8
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Oct 25, 2023
0087bde
Update ui/appui-react/src/appui-react/childwindow/InternalChildWindow…
joehenry9498 Oct 25, 2023
e4f1a20
Resize only takes effect on intial popout
joehenry9498 Oct 26, 2023
f512cca
Merge branch 'joeh/resizePopout' of https://github.com/iTwin/appui in…
joehenry9498 Oct 26, 2023
bf0081e
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Oct 26, 2023
7ff80ff
extract-api
joehenry9498 Oct 26, 2023
8719f3e
Rush audit fixes
joehenry9498 Oct 27, 2023
d5e103c
Extract Api
joehenry9498 Oct 27, 2023
c74aee4
Revert "Rush audit fixes"
joehenry9498 Oct 30, 2023
c908a22
Move size calculation further into nine zone state
joehenry9498 Oct 30, 2023
ddd052f
Update FrontstageDef.tsx
joehenry9498 Oct 30, 2023
afe3d69
Add test coverage
joehenry9498 Oct 30, 2023
91ff25a
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Oct 30, 2023
61a851e
extract-api
joehenry9498 Oct 30, 2023
9ae5003
Rush change
joehenry9498 Oct 30, 2023
cf5ddde
Delete common/changes/@itwin/appui-layout-react/joeh-resizePopout_202…
joehenry9498 Oct 30, 2023
764d116
Delete common/changes/@itwin/appui-react/joeh-resizePopout_2023-10-24…
joehenry9498 Oct 30, 2023
33732fa
Update NextVersion.md
joehenry9498 Oct 30, 2023
9170265
Change playwright test
joehenry9498 Oct 30, 2023
ada6798
Merge branch 'master' into joeh/resizePopout
joehenry9498 Oct 30, 2023
0aaac0e
Uneeded test changes
joehenry9498 Oct 30, 2023
383bcd1
Set min width for error boundary so that it appears in content renderer
joehenry9498 Oct 31, 2023
a301adf
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Oct 31, 2023
f8fc3ab
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Oct 31, 2023
7619f57
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Nov 1, 2023
17a9e8e
Check size of popout when fitting to container in test
joehenry9498 Nov 1, 2023
80f5216
Delete common/changes/@itwin/appui-layout-react/joeh-resizePopout_202…
joehenry9498 Nov 2, 2023
a36078b
Delete common/changes/@itwin/appui-react/joeh-resizePopout_2023-10-30…
joehenry9498 Nov 2, 2023
8e7d4d4
Remove popout container and popout to floating widget bounds
joehenry9498 Nov 2, 2023
d297cad
Merge branch 'joeh/resizePopout' of https://github.com/iTwin/appui in…
joehenry9498 Nov 2, 2023
d91c609
Refactor changelogs
joehenry9498 Nov 2, 2023
13c14a7
When preferredFloatingWidgetSize not set, will popout to content cont…
joehenry9498 Nov 2, 2023
6b217a1
Update ui/appui-layout-react/src/appui-layout-react/state/NineZoneSta…
joehenry9498 Nov 6, 2023
81b3eea
Merge remote-tracking branch 'origin/master' into joeh/resizePopout
joehenry9498 Nov 6, 2023
d92fe8e
Update joeh-resizePopout_2023-11-02-18-19.json
joehenry9498 Nov 6, 2023
b01fcba
Update NextVersion.md
joehenry9498 Nov 6, 2023
7f84fb3
Change inital size of popout in test
joehenry9498 Nov 6, 2023
cf24351
Update joeh-resizePopout_2023-11-02-18-19.json
joehenry9498 Nov 6, 2023
db0f0a4
Update joeh-resizePopout_2023-11-02-18-19.json
joehenry9498 Nov 6, 2023
90df9dc
Update NextVersion.md
joehenry9498 Nov 6, 2023
88913a1
Update NextVersion.md
joehenry9498 Nov 6, 2023
899004c
Updated screenshot for failing test
joehenry9498 Nov 6, 2023
9ad6104
Fix broken screenshot
joehenry9498 Nov 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/appui-layout-react",
"comment": "",
"type": "none"
}
],
"packageName": "@itwin/appui-layout-react"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/appui-react",
"comment": "Popout Widgets will now size to content on popout",
"type": "none"
}
],
"packageName": "@itwin/appui-react"
}
1 change: 1 addition & 0 deletions docs/changehistory/NextVersion.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Table of contents:
### Changes

- `AppNotificationManager` no longer requires `StatusBar` to be rendered in the active frontstage to show messages.
- Popout Widgets will now size to content on popout.

### Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,14 @@ export function WidgetContentRenderer(props: WidgetContentRendererProps) {
};
}, [renderTo, widgetContentManager, props.tabId]);
return ReactDOM.createPortal(
<TabIdContext.Provider value={props.tabId}>
{props.children}
</TabIdContext.Provider>,
<div
id={`content-container:${props.tabId}`}
style={{ width: "fit-content", height: "fit-content" }}
>
<TabIdContext.Provider value={props.tabId}>
{props.children}
</TabIdContext.Provider>
</div>,
container.current
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,25 @@ export class InternalChildWindowManager implements FrameworkChildWindows {
return false;
}

const nineZoneState =
UiFramework.frontstages.activeFrontstageDef?.nineZoneState;

if (nineZoneState === undefined) return false;

const popoutContentContainer = document.getElementById(
`content-container:${nineZoneState.widgets[childWindowId].activeTabId}`
);
if (popoutContentContainer === null) return false;

const contentWidth = popoutContentContainer.offsetWidth + 20;
const contentHeight = popoutContentContainer.offsetHeight + 20;
joehenry9498 marked this conversation as resolved.
Show resolved Hide resolved

location = this.adjustWidowLocation(location);
const url = useDefaultPopoutUrl ? "/iTwinPopup.html" : "";
const childWindow = window.open(
url,
"",
`width=${location.width},height=${location.height},left=${location.left},top=${location.top},menubar=no,resizable=yes,scrollbars=no,status=no,location=no`
`width=${contentWidth},height=${contentHeight},left=${location.left},top=${location.top},menubar=no,resizable=yes,scrollbars=no,status=no,location=no`
);
if (!childWindow) return false;
if (0 === url.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface PopoutWidgetProps {
widgetDef: WidgetDef;
}

/** Component used to wrap a widget for use is a child window.
/** Component used to wrap a widget for use in a child window.
* @internal
*/
export function PopoutWidget({
Expand Down
145 changes: 81 additions & 64 deletions ui/appui-react/src/test/frontstage/FrontstageDef.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ class BadGroupFrontstage extends FrontstageProvider {
}
}

class EmptyFrontstageProvider extends FrontstageProvider {
public static stageId = "TestFrontstageUi2";
public override get id(): string {
return EmptyFrontstageProvider.stageId;
}

public override frontstageConfig(): FrontstageConfig {
return {
id: this.id,
version: 1,
contentGroup: TestUtils.TestContentGroup1,
};
}
}

export const defaultFrontstageConfig: FrontstageConfig = {
id: "test-frontstage",
contentGroup: TestUtils.TestContentGroup1,
Expand Down Expand Up @@ -322,21 +337,6 @@ describe("FrontstageDef", () => {
}
}

class EmptyFrontstageProvider extends FrontstageProvider {
public static stageId = "TestFrontstageUi2";
public override get id(): string {
return EmptyFrontstageProvider.stageId;
}

public override frontstageConfig(): FrontstageConfig {
return {
id: this.id,
version: 1,
contentGroup: TestUtils.TestContentGroup1,
};
}
}

beforeEach(() => {
UiItemsManager.register(new WidgetsProvider());
});
Expand Down Expand Up @@ -548,36 +548,41 @@ describe("FrontstageDef", () => {
});
});
it("should handle multiple popoutWidgets being set for empty 'oldState' (For electron initialization)", async () => {
let state = createNineZoneState({ size: { height: 1000, width: 1600 } });
const frontstageProvider = new EmptyFrontstageProvider();
UiFramework.frontstages.addFrontstageProvider(frontstageProvider);
const frontstageDef = await UiFramework.frontstages.getFrontstageDef(
EmptyFrontstageProvider.stageId
);
if (frontstageDef === undefined) return;
let state = createNineZoneState();
state = addTab(state, "t1");
state = addTab(state, "t2");
state = addPopoutWidget(state, "fw1", ["t1"]);
state = addPopoutWidget(state, "fw2", ["t2"]);
state = addPopoutWidget(state, "w1", ["t1"]);
state = addPopoutWidget(state, "w2", ["t2"]);

const frontstageDef = new FrontstageDef();
await frontstageDef.initializeFromConfig({
...defaultFrontstageConfig,
leftPanel: {
sections: {
start: [
{
id: "t1",
},
],
},
},
rightPanel: {
sections: {
start: [
{
id: "t2",
},
],
},
},
const widgetDef1 = WidgetDef.create({
id: "t1",
defaultState: WidgetState.Open,
});

const widgetDef2 = WidgetDef.create({
id: "t2",
defaultState: WidgetState.Open,
});

const findWidgetStub = sinon.stub(frontstageDef, "findWidgetDef");

findWidgetStub.withArgs("t1").returns(widgetDef1);
findWidgetStub.withArgs("t2").returns(widgetDef2);

await UiFramework.frontstages.setActiveFrontstageDef(frontstageDef);

const spy = sinon.spy(window, "open");

const blankHTML = document.createElement("div");

sinon.stub(document, "getElementById").returns(blankHTML);

frontstageDef.nineZoneState = state;

expect(frontstageDef.nineZoneState).to.be.eq(state);
Expand All @@ -587,23 +592,36 @@ describe("FrontstageDef", () => {

describe("openPopoutWidgetContainer", () => {
it("should open a popout window", async () => {
const frontstageDef = new FrontstageDef();
await frontstageDef.initializeFromConfig({
...defaultFrontstageConfig,
leftPanel: {
sections: {
start: [
{
id: "t1",
},
],
},
},
const frontstageProvider = new EmptyFrontstageProvider();
UiFramework.frontstages.addFrontstageProvider(frontstageProvider);
const frontstageDef = await UiFramework.frontstages.getFrontstageDef(
EmptyFrontstageProvider.stageId
);
if (frontstageDef === undefined) return;
let state = createNineZoneState();
state = addTab(state, "t1");
state = addPopoutWidget(state, "w1", ["t1"]);

const widgetDef = WidgetDef.create({
id: "t1",
defaultState: WidgetState.Open,
});
frontstageDef.nineZoneState = initializeNineZoneState(frontstageDef);
frontstageDef.popoutWidget("t1");

sinon
.stub(frontstageDef, "findWidgetDef")
.withArgs("t1")
.returns(widgetDef);
frontstageDef.nineZoneState = state;
await UiFramework.frontstages.setActiveFrontstageDef(frontstageDef);

const spy = sinon.spy(window, "open");

const blankHTML = document.createElement("div");

sinon
.stub(document, "getElementById")
.withArgs("content-container:t1")
.returns(blankHTML);
const popoutWidgets = frontstageDef.nineZoneState.popoutWidgets;
const popoutWidget = popoutWidgets.byId[popoutWidgets.allIds[0]];
frontstageDef.openPopoutWidgetContainer(
Expand All @@ -616,17 +634,16 @@ describe("FrontstageDef", () => {

describe("dockWidgetContainer", () => {
it("should dock popout widget", async () => {
const frontstageDef = new FrontstageDef();
await frontstageDef.initializeFromConfig({
...defaultFrontstageConfig,
leftPanel: {
sections: {
start: [{ id: "t1" }],
},
},
});
frontstageDef.nineZoneState = initializeNineZoneState(frontstageDef);
frontstageDef.popoutWidget("t1");
const frontstageProvider = new EmptyFrontstageProvider();
UiFramework.frontstages.addFrontstageProvider(frontstageProvider);
const frontstageDef = await UiFramework.frontstages.getFrontstageDef(
EmptyFrontstageProvider.stageId
);
if (frontstageDef === undefined) return;
let state = createNineZoneState();
state = addTab(state, "t1");
state = addPopoutWidget(state, "w1", ["t1"]);
frontstageDef.nineZoneState = state;

frontstageDef.dockWidgetContainer("t1");
expect(frontstageDef.nineZoneState.popoutWidgets.allIds).lengthOf(0);
Expand Down