fix: constraints persistence and precedence issues

Resolves issue #869 where setConstraints calls would not persist after refresh
and could not override addPanel constraints.

Changes:
- Fix critical bug in DockviewGroupPanel constructor (minimumWidth was using maximumHeight)
- Restore setConstraints method to DockviewPanelApi by removing from Omit list
- Implement explicit constraint tracking to allow group constraints to override panel constraints
- Add constraint change listener to track when setConstraints is called explicitly
- Update constraint getter precedence: explicit setConstraints > panel constraints > defaults
- Update tests to reflect new behavior where group constraints can override panel constraints

The new constraint hierarchy ensures that:
1. Explicit setConstraints calls take highest priority
2. Panel constraints from addPanel are used when no explicit group constraints exist
3. Group defaults are used as fallback
4. Constraints persist properly after page refresh

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
mathuo 2025-07-18 22:16:11 +01:00
parent 23a5d84020
commit eec2ae04f3
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
3 changed files with 61 additions and 13 deletions

View File

@ -132,12 +132,12 @@ describe('dockviewGroupPanel', () => {
cut.model.openPanel(panel); cut.model.openPanel(panel);
// active panel constraints // explicit group constraints now override panel constraints
expect(cut.minimumWidth).toBe(21); expect(cut.minimumWidth).toBe(20); // group constraint overrides panel constraint
expect(cut.minimumHeight).toBe(11); expect(cut.minimumHeight).toBe(10); // group constraint overrides panel constraint
expect(cut.maximumHeight).toBe(101); expect(cut.maximumHeight).toBe(100); // group constraint overrides panel constraint
expect(cut.maximumWidth).toBe(201); expect(cut.maximumWidth).toBe(200); // group constraint overrides panel constraint
const panel2 = new DockviewPanel( const panel2 = new DockviewPanel(
'panel_id', 'panel_id',
@ -158,12 +158,12 @@ describe('dockviewGroupPanel', () => {
cut.model.openPanel(panel2); cut.model.openPanel(panel2);
// active panel constraints // explicit group constraints still override panel constraints
expect(cut.minimumWidth).toBe(22); expect(cut.minimumWidth).toBe(20); // group constraint overrides panel constraint
expect(cut.minimumHeight).toBe(12); expect(cut.minimumHeight).toBe(10); // group constraint overrides panel constraint
expect(cut.maximumHeight).toBe(102); expect(cut.maximumHeight).toBe(100); // group constraint overrides panel constraint
expect(cut.maximumWidth).toBe(202); expect(cut.maximumWidth).toBe(200); // group constraint overrides panel constraint
const panel3 = new DockviewPanel( const panel3 = new DockviewPanel(
'panel_id', 'panel_id',

View File

@ -33,7 +33,7 @@ export interface DockviewPanelApi
extends Omit< extends Omit<
GridviewPanelApi, GridviewPanelApi,
// omit properties that do not make sense here // omit properties that do not make sense here
'setVisible' | 'onDidConstraintsChange' | 'setConstraints' 'setVisible' | 'onDidConstraintsChange'
> { > {
/** /**
* The id of the tab component renderer * The id of the tab component renderer

View File

@ -7,12 +7,13 @@ import {
IHeader, IHeader,
DockviewGroupPanelLocked, DockviewGroupPanelLocked,
} from './dockviewGroupPanelModel'; } from './dockviewGroupPanelModel';
import { GridviewPanel, IGridviewPanel } from '../gridview/gridviewPanel'; import { GridviewPanel, IGridviewPanel, Contraints } from '../gridview/gridviewPanel';
import { IDockviewPanel } from '../dockview/dockviewPanel'; import { IDockviewPanel } from '../dockview/dockviewPanel';
import { import {
DockviewGroupPanelApi, DockviewGroupPanelApi,
DockviewGroupPanelApiImpl, DockviewGroupPanelApiImpl,
} from '../api/dockviewGroupPanelApi'; } from '../api/dockviewGroupPanelApi';
// GridConstraintChangeEvent2 is not exported, so we'll type it manually
const MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH = 100; const MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH = 100;
const MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT = 100; const MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT = 100;
@ -34,7 +35,15 @@ export class DockviewGroupPanel
{ {
private readonly _model: DockviewGroupPanelModel; private readonly _model: DockviewGroupPanelModel;
// Track explicitly set constraints to override panel constraints
private _explicitConstraints: Partial<Contraints> = {};
override get minimumWidth(): number { override get minimumWidth(): number {
// Check for explicitly set group constraint first
if (typeof this._explicitConstraints.minimumWidth === 'number') {
return this._explicitConstraints.minimumWidth;
}
const activePanelMinimumWidth = this.activePanel?.minimumWidth; const activePanelMinimumWidth = this.activePanel?.minimumWidth;
if (typeof activePanelMinimumWidth === 'number') { if (typeof activePanelMinimumWidth === 'number') {
return activePanelMinimumWidth; return activePanelMinimumWidth;
@ -43,6 +52,11 @@ export class DockviewGroupPanel
} }
override get minimumHeight(): number { override get minimumHeight(): number {
// Check for explicitly set group constraint first
if (typeof this._explicitConstraints.minimumHeight === 'number') {
return this._explicitConstraints.minimumHeight;
}
const activePanelMinimumHeight = this.activePanel?.minimumHeight; const activePanelMinimumHeight = this.activePanel?.minimumHeight;
if (typeof activePanelMinimumHeight === 'number') { if (typeof activePanelMinimumHeight === 'number') {
return activePanelMinimumHeight; return activePanelMinimumHeight;
@ -51,6 +65,11 @@ export class DockviewGroupPanel
} }
override get maximumWidth(): number { override get maximumWidth(): number {
// Check for explicitly set group constraint first
if (typeof this._explicitConstraints.maximumWidth === 'number') {
return this._explicitConstraints.maximumWidth;
}
const activePanelMaximumWidth = this.activePanel?.maximumWidth; const activePanelMaximumWidth = this.activePanel?.maximumWidth;
if (typeof activePanelMaximumWidth === 'number') { if (typeof activePanelMaximumWidth === 'number') {
return activePanelMaximumWidth; return activePanelMaximumWidth;
@ -59,6 +78,11 @@ export class DockviewGroupPanel
} }
override get maximumHeight(): number { override get maximumHeight(): number {
// Check for explicitly set group constraint first
if (typeof this._explicitConstraints.maximumHeight === 'number') {
return this._explicitConstraints.maximumHeight;
}
const activePanelMaximumHeight = this.activePanel?.maximumHeight; const activePanelMaximumHeight = this.activePanel?.maximumHeight;
if (typeof activePanelMaximumHeight === 'number') { if (typeof activePanelMaximumHeight === 'number') {
return activePanelMaximumHeight; return activePanelMaximumHeight;
@ -107,7 +131,7 @@ export class DockviewGroupPanel
options.constraints?.minimumHeight ?? options.constraints?.minimumHeight ??
MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT, MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT,
minimumWidth: minimumWidth:
options.constraints?.maximumHeight ?? options.constraints?.minimumWidth ??
MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH, MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH,
maximumHeight: options.constraints?.maximumHeight, maximumHeight: options.constraints?.maximumHeight,
maximumWidth: options.constraints?.maximumWidth, maximumWidth: options.constraints?.maximumWidth,
@ -128,6 +152,30 @@ export class DockviewGroupPanel
this.addDisposables( this.addDisposables(
this.model.onDidActivePanelChange((event) => { this.model.onDidActivePanelChange((event) => {
this.api._onDidActivePanelChange.fire(event); this.api._onDidActivePanelChange.fire(event);
}),
this.api.onDidConstraintsChangeInternal((event: any) => {
// Track explicitly set constraints to override panel constraints
// Extract numeric values from functions or values
if (event.minimumWidth !== undefined) {
this._explicitConstraints.minimumWidth = typeof event.minimumWidth === 'function'
? event.minimumWidth()
: event.minimumWidth;
}
if (event.minimumHeight !== undefined) {
this._explicitConstraints.minimumHeight = typeof event.minimumHeight === 'function'
? event.minimumHeight()
: event.minimumHeight;
}
if (event.maximumWidth !== undefined) {
this._explicitConstraints.maximumWidth = typeof event.maximumWidth === 'function'
? event.maximumWidth()
: event.maximumWidth;
}
if (event.maximumHeight !== undefined) {
this._explicitConstraints.maximumHeight = typeof event.maximumHeight === 'function'
? event.maximumHeight()
: event.maximumHeight;
}
}) })
); );
} }