Skip to content

Commit 94efbb3

Browse files
author
Loïc Mangeonjean
committed
fix: rework view rendering
parts need to be rendered immediately to fully work (because of extensionService.onDidRegisterExtensions). So now we render them in an invisible container until the user needs it
1 parent 27f09b1 commit 94efbb3

File tree

2 files changed

+76
-108
lines changed

2 files changed

+76
-108
lines changed

src/service-override/layout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class LayoutService implements ILayoutService, Pick<IWorkbenchLayoutServi
5858
return this.getPart(part).getContainer()
5959
}
6060

61-
protected getPart (key: Parts): Part {
61+
public getPart (key: Parts): Part {
6262
const part = this.parts.get(key)
6363
if (part == null) {
6464
throw new Error(`Unknown part ${key}`)

src/service-override/views.ts

Lines changed: 75 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@ import { ViewsService } from 'vs/workbench/browser/parts/views/viewsService'
66
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'
77
import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart'
88
import { ViewDescriptorService } from 'vs/workbench/services/views/browser/viewDescriptorService'
9-
import { IActivityService, IBadge } from 'vs/workbench/services/activity/common/activity'
9+
import { IActivityService } from 'vs/workbench/services/activity/common/activity'
1010
import { ActivityService } from 'vs/workbench/services/activity/browser/activityService'
1111
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'
12-
import { Event } from 'vs/base/common/event'
13-
import { IPaneComposite } from 'vs/workbench/common/panecomposite'
14-
import { IPaneCompositePart, IPaneCompositeSelectorPart } from 'vs/workbench/browser/parts/paneCompositePart'
12+
import { PaneCompositeParts } from 'vs/workbench/browser/parts/paneCompositePart'
1513
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart'
1614
import { DisposableStore, IDisposable, IReference } from 'vs/base/common/lifecycle'
17-
import { IProgressIndicator } from 'vs/platform/progress/common/progress'
1815
import { IHoverService } from 'vs/workbench/services/hover/browser/hover'
1916
import { HoverService } from 'vs/workbench/services/hover/browser/hoverService'
2017
import { ExplorerService } from 'vs/workbench/contrib/files/browser/explorerService'
@@ -98,67 +95,13 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'
9895
import { IStorageService } from 'vs/platform/storage/common/storage'
9996
import { IThemeService } from 'vs/platform/theme/common/themeService'
10097
import { ConfirmResult } from 'vs/platform/dialogs/common/dialogs'
98+
import { ILayoutService } from 'vs/platform/layout/browser/layoutService'
10199
import { OpenEditor, wrapOpenEditor } from './tools/editor'
102100
import getBulkEditServiceOverride from './bulkEdit'
103-
import getLayoutServiceOverride from './layout'
101+
import getLayoutServiceOverride, { LayoutService } from './layout'
104102
import { changeUrlDomain } from './tools/url'
105103
import { registerAssets } from '../assets'
106-
107-
const paneCompositeParts = new Map<ViewContainerLocation, IPaneCompositePart>()
108-
const paneCompositeSelectorParts = new Map<ViewContainerLocation, IPaneCompositeSelectorPart>()
109-
110-
class PaneCompositePartService implements IPaneCompositePartService {
111-
_serviceBrand: undefined
112-
onDidPaneCompositeOpen = Event.None
113-
onDidPaneCompositeClose = Event.None
114-
async openPaneComposite (id: string | undefined, viewContainerLocation: ViewContainerLocation, focus?: boolean): Promise<IPaneComposite | undefined> {
115-
return this.getPartByLocation(viewContainerLocation)?.openPaneComposite(id, focus)
116-
}
117-
118-
getActivePaneComposite (viewContainerLocation: ViewContainerLocation) {
119-
return this.getPartByLocation(viewContainerLocation)?.getActivePaneComposite()
120-
}
121-
122-
getPaneComposite (id: string, viewContainerLocation: ViewContainerLocation) {
123-
return this.getPartByLocation(viewContainerLocation)?.getPaneComposite(id)
124-
}
125-
126-
getPaneComposites (viewContainerLocation: ViewContainerLocation) {
127-
return this.getPartByLocation(viewContainerLocation)?.getPaneComposites() ?? []
128-
}
129-
130-
getPinnedPaneCompositeIds (viewContainerLocation: ViewContainerLocation): string[] {
131-
return this.getSelectorPartByLocation(viewContainerLocation)?.getPinnedPaneCompositeIds() ?? []
132-
}
133-
134-
getVisiblePaneCompositeIds (viewContainerLocation: ViewContainerLocation): string[] {
135-
return this.getSelectorPartByLocation(viewContainerLocation)?.getVisiblePaneCompositeIds() ?? []
136-
}
137-
138-
getProgressIndicator (id: string, viewContainerLocation: ViewContainerLocation): IProgressIndicator | undefined {
139-
return this.getPartByLocation(viewContainerLocation)?.getProgressIndicator(id)
140-
}
141-
142-
hideActivePaneComposite (viewContainerLocation: ViewContainerLocation): void {
143-
this.getPartByLocation(viewContainerLocation)?.hideActivePaneComposite()
144-
}
145-
146-
getLastActivePaneCompositeId (viewContainerLocation: ViewContainerLocation): string {
147-
return this.getPartByLocation(viewContainerLocation)!.getLastActivePaneCompositeId()
148-
}
149-
150-
showActivity (id: string, viewContainerLocation: ViewContainerLocation, badge: IBadge, clazz?: string, priority?: number): IDisposable {
151-
return this.getSelectorPartByLocation(viewContainerLocation)!.showActivity(id, badge, clazz, priority)
152-
}
153-
154-
private getPartByLocation (viewContainerLocation: ViewContainerLocation): IPaneCompositePart | undefined {
155-
return paneCompositeParts.get(viewContainerLocation)
156-
}
157-
158-
private getSelectorPartByLocation (viewContainerLocation: ViewContainerLocation): IPaneCompositeSelectorPart | undefined {
159-
return paneCompositeSelectorParts.get(viewContainerLocation)
160-
}
161-
}
104+
import { registerServiceInitializePostParticipant } from '../services'
162105

163106
function createPart (id: string, role: string, classes: string[]): HTMLElement {
164107
const part = document.createElement(role === 'status' ? 'footer' /* Use footer element for status bar #98376 */ : 'div')
@@ -172,25 +115,38 @@ function createPart (id: string, role: string, classes: string[]): HTMLElement {
172115
return part
173116
}
174117

175-
function renderPart (id: string, role: string, classes: string[], part: Part, container: HTMLElement): IDisposable {
176-
const partContainer = createPart(id, role, classes)
177-
container.append(partContainer)
118+
function layoutPart (part: Part) {
119+
const parent = part.getContainer()?.parentNode
120+
if (parent == null) {
121+
return
122+
}
123+
part.layout(
124+
Math.max(part.minimumWidth, Math.min(part.maximumWidth, (parent as HTMLElement).offsetWidth)),
125+
Math.max(part.minimumHeight, Math.min(part.maximumHeight, (parent as HTMLElement).offsetHeight)),
126+
0, 0
127+
)
128+
}
129+
130+
function renderPart (partContainer: HTMLElement, part: Part): void {
178131
partContainer.oncontextmenu = () => false
179-
part.create(partContainer)
180132
function layout () {
181-
part.layout(
182-
Math.max(part.minimumWidth, Math.min(part.maximumWidth, container.offsetWidth)),
183-
Math.max(part.minimumHeight, Math.min(part.maximumHeight, container.offsetHeight)),
184-
0, 0
185-
)
133+
layoutPart(part)
186134
}
187135
part.onDidVisibilityChange((visible) => {
188136
if (visible) {
189137
layout()
190138
}
191139
})
192140
layout()
193-
const observer = new ResizeObserver(layout)
141+
}
142+
143+
function getPart (part: Parts): Part {
144+
return (StandaloneServices.get(ILayoutService) as LayoutService).getPart(part)
145+
}
146+
147+
function attachPart (part: Part, container: HTMLElement) {
148+
container.append(part.getContainer()!)
149+
const observer = new ResizeObserver(() => layoutPart(part))
194150
observer.observe(container)
195151

196152
return {
@@ -201,54 +157,27 @@ function renderPart (id: string, role: string, classes: string[], part: Part, co
201157
}
202158

203159
function renderActivitybarPar (container: HTMLElement): IDisposable {
204-
const activitybarPart = StandaloneServices.get(IInstantiationService).createInstance(ActivitybarPart, paneCompositeParts.get(ViewContainerLocation.Sidebar)!)
205-
paneCompositeSelectorParts.set(ViewContainerLocation.Sidebar, activitybarPart)
206-
207-
// eslint-disable-next-line dot-notation
208-
activitybarPart['_register'](renderPart(Parts.ACTIVITYBAR_PART, 'none', ['activitybar', 'left'], activitybarPart, container))
209-
210-
return activitybarPart
160+
return attachPart(getPart(Parts.ACTIVITYBAR_PART), container)
211161
}
212162

213163
function renderSidebarPart (container: HTMLElement): IDisposable {
214-
const sidebarPart = StandaloneServices.get(IInstantiationService).createInstance(SidebarPart)
215-
paneCompositeParts.set(ViewContainerLocation.Sidebar, sidebarPart)
216-
217-
// eslint-disable-next-line dot-notation
218-
sidebarPart['_register'](renderPart(Parts.SIDEBAR_PART, 'none', ['sidebar', 'left'], sidebarPart, container))
219-
220-
if (sidebarPart.getPaneComposites().length > 0) {
221-
void sidebarPart.openPaneComposite(sidebarPart.getPaneComposites()[0]!.id)
222-
}
223-
224-
return sidebarPart
164+
return attachPart(getPart(Parts.SIDEBAR_PART), container)
225165
}
226166

227167
function renderPanelPart (container: HTMLElement): IDisposable {
228-
const panelPart = StandaloneServices.get(IInstantiationService).createInstance(PanelPart)
229-
paneCompositeSelectorParts.set(ViewContainerLocation.Panel, panelPart)
230-
paneCompositeParts.set(ViewContainerLocation.Panel, panelPart)
231-
232-
// eslint-disable-next-line dot-notation
233-
panelPart['_register'](renderPart(Parts.PANEL_PART, 'none', ['panel', 'basepanel', positionToString(Position.LEFT)], panelPart, container))
234-
235-
if (panelPart.getPaneComposites().length > 0) {
236-
void panelPart.openPaneComposite(panelPart.getPaneComposites()[0]!.id)
237-
}
168+
return attachPart(getPart(Parts.PANEL_PART), container)
169+
}
238170

239-
return panelPart
171+
function renderAuxiliaryPart (container: HTMLElement): IDisposable {
172+
return attachPart(getPart(Parts.AUXILIARYBAR_PART), container)
240173
}
241174

242175
function renderEditorPart (container: HTMLElement): IDisposable {
243-
const editorPart = StandaloneServices.get(IEditorGroupsService) as EditorPart
244-
245-
return renderPart(Parts.EDITOR_PART, 'main', ['editor'], editorPart, container)
176+
return attachPart(getPart(Parts.EDITOR_PART), container)
246177
}
247178

248179
function renderStatusBarPart (container: HTMLElement): IDisposable {
249-
const statusBarPart = StandaloneServices.get(IStatusbarService) as StatusbarPart
250-
251-
return renderPart(Parts.STATUSBAR_PART, 'status', ['statusbar'], statusBarPart, container)
180+
return attachPart(getPart(Parts.STATUSBAR_PART), container)
252181
}
253182

254183
type Label = string | {
@@ -568,6 +497,44 @@ registerAssets({
568497
'vs/workbench/contrib/webview/browser/pre/fake.html': () => changeUrlDomain(new URL('../../vscode/vs/workbench/contrib/webview/browser/pre/fake.html', import.meta.url).href, webviewIframeAlternateDomains)
569498
})
570499

500+
registerServiceInitializePostParticipant(async (accessor) => {
501+
const paneCompositePartService = accessor.get(IPaneCompositePartService)
502+
const viewDescriptorService = accessor.get(IViewDescriptorService)
503+
504+
// force service instantiation
505+
accessor.get(IStatusbarService)
506+
paneCompositePartService.getPaneComposites(ViewContainerLocation.Panel)
507+
508+
const layoutService = accessor.get(ILayoutService) as LayoutService
509+
510+
const invisibleContainer = document.createElement('div')
511+
invisibleContainer.style.display = 'none'
512+
document.body.append(invisibleContainer)
513+
514+
// Create Parts
515+
for (const { id, role, classes, options } of [
516+
{ id: Parts.ACTIVITYBAR_PART, role: 'none', classes: ['activitybar', 'left'] },
517+
{ id: Parts.SIDEBAR_PART, role: 'none', classes: ['sidebar', 'left'] },
518+
{ id: Parts.EDITOR_PART, role: 'main', classes: ['editor'], options: { restorePreviousState: false } },
519+
{ id: Parts.PANEL_PART, role: 'none', classes: ['panel', 'basepanel', positionToString(Position.BOTTOM)] },
520+
{ id: Parts.AUXILIARYBAR_PART, role: 'none', classes: ['auxiliarybar', 'basepanel', 'right'] },
521+
{ id: Parts.STATUSBAR_PART, role: 'status', classes: ['statusbar'] }
522+
]) {
523+
const partContainer = createPart(id, role, classes)
524+
525+
const part = layoutService.getPart(id)
526+
part.create(partContainer, options)
527+
renderPart(partContainer, part)
528+
529+
// We need the container to be attached for some views to work (like xterm)
530+
invisibleContainer.append(partContainer)
531+
}
532+
533+
await paneCompositePartService.openPaneComposite(viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id, ViewContainerLocation.Sidebar)
534+
await paneCompositePartService.openPaneComposite(viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Panel)?.id, ViewContainerLocation.Panel)
535+
await paneCompositePartService.openPaneComposite(viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.AuxiliaryBar)?.id, ViewContainerLocation.AuxiliaryBar)
536+
})
537+
571538
export default function getServiceOverride (openEditorFallback?: OpenEditor, _webviewIframeAlternateDomains?: string): IEditorOverrideServices {
572539
if (_webviewIframeAlternateDomains != null) {
573540
webviewIframeAlternateDomains = _webviewIframeAlternateDomains
@@ -612,6 +579,7 @@ export {
612579
registerEditorPane,
613580
renderSidebarPart,
614581
renderActivitybarPar,
582+
renderAuxiliaryPart,
615583
renderPanelPart,
616584
renderEditorPart,
617585
renderStatusBarPart,

0 commit comments

Comments
 (0)