Stacking and Sharecolumn WIP

This commit is contained in:
Janus C. H. Knudsen 2025-10-06 17:05:18 +02:00
parent c788a1695e
commit 6b8c5d4673
7 changed files with 763 additions and 51 deletions

View file

@ -13,6 +13,7 @@ export interface GridGroupLayout {
events: CalendarEvent[];
stackLevel: number;
position: { top: number };
columns: CalendarEvent[][]; // Events grouped by column (events in same array share a column)
}
export interface StackedEventLayout {
@ -60,11 +61,13 @@ export class EventLayoutCoordinator {
const gridStackLevel = this.calculateGridGroupStackLevel(group, columnEvents, allStackLinks);
const earliestEvent = group.events[0];
const position = PositionUtils.calculateEventPosition(earliestEvent.start, earliestEvent.end);
const columns = this.allocateColumns(group.events);
gridGroupLayouts.push({
events: group.events,
stackLevel: gridStackLevel,
position: { top: position.top + 1 }
position: { top: position.top + 1 },
columns
});
group.events.forEach(e => renderedEventIds.add(e.id));
@ -119,4 +122,45 @@ export class EventLayoutCoordinator {
// Grid group should be one level above the highest overlapping event
return maxOverlappingLevel + 1;
}
/**
* Allocate events to columns within a grid group
*
* Events that don't overlap can share the same column.
* Uses a greedy algorithm to minimize the number of columns.
*
* @param events - Events in the grid group (should already be sorted by start time)
* @returns Array of columns, where each column is an array of events
*/
private allocateColumns(events: CalendarEvent[]): CalendarEvent[][] {
if (events.length === 0) return [];
if (events.length === 1) return [[events[0]]];
const columns: CalendarEvent[][] = [];
// For each event, try to place it in an existing column where it doesn't overlap
for (const event of events) {
let placed = false;
// Try to find a column where this event doesn't overlap with any existing event
for (const column of columns) {
const hasOverlap = column.some(colEvent =>
this.stackManager.doEventsOverlap(event, colEvent)
);
if (!hasOverlap) {
column.push(event);
placed = true;
break;
}
}
// If no suitable column found, create a new one
if (!placed) {
columns.push([event]);
}
}
return columns;
}
}