Skip to content

Commit d88a21d

Browse files
feat: Allow flexible column width with percentages and auto-sizing
This commit introduces a more flexible way to define column widths. The 'width' property on a Column can now be a number (for pixels), a string percentage (e.g., "50%"), or a special "*" string to make the column automatically fill the remaining space. This addresses the user's request for more dynamic and responsive column layouts. The settings UI has been updated to accept a string input, and the rendering logic now calculates the final pixel widths for all columns based on these new flexible definitions. Implements #100
1 parent 942a63a commit d88a21d

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

src/App.vue

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,45 @@ const loadColumnsFromLayout = () => {
321321
columns.value = store.layout.columns.filter(col => !col.hidden)
322322
}
323323
324+
const tableWidth = computed(() => {
325+
if (!table.value) {
326+
return 0;
327+
}
328+
return table.value.clientWidth - 20 // 20 for the scrollbar
329+
})
330+
331+
const columnsWithWidth = computed(() => {
332+
if (!table.value) {
333+
return columns.value;
334+
}
335+
let maxWCol = columns.value.find(c => c.width === '*')
336+
337+
if (maxWCol) {
338+
let totalWidth = 0;
339+
columns.value.forEach(c => {
340+
if (c.id !== maxWCol?.id) {
341+
if (typeof c.width === 'string') {
342+
if (c.width.endsWith('%')) {
343+
totalWidth += tableWidth.value * (parseInt(c.width.slice(0, -1)) / 100)
344+
} else {
345+
totalWidth += parseInt(c.width)
346+
}
347+
} else {
348+
totalWidth += c.width || 0
349+
}
350+
}
351+
})
352+
maxWCol.width = (tableWidth.value - totalWidth) + 'px'
353+
}
354+
355+
return columns.value.map(c => {
356+
if (typeof c.width === 'number') {
357+
c.width = c.width + 'px'
358+
}
359+
return c
360+
})
361+
})
362+
324363
const addRawColumn = () => {
325364
columnEdited({
326365
name: "raw",
@@ -703,7 +742,7 @@ const updateSampleLine = () => {
703742
<div class="mid-col" :class="{ freeze: leftColHidden }" @mousedown="startDragging"></div>
704743
</div>
705744
<div class="right-col" ref="table">
706-
<div v-if="columns.length === 0" style="text-align: center; padding-top:100px; font-size: 20px;">
745+
<div v-if="columnsWithWidth.length === 0" style="text-align: center; padding-top:100px; font-size: 20px;">
707746

708747
<div v-if="useMainStore().status == 'not connected'" style="margin: 10px; padding: 5px;">Status: <strong>Not
709748
connected</strong></div>
@@ -723,7 +762,7 @@ const updateSampleLine = () => {
723762
<table class="table" cellspacing="0" cellpadding="0">
724763
<tr>
725764
<th></th>
726-
<th v-for="col in columns" :style="{ width: col.width + 'px', cursor: 'auto' }" class="column-name"
765+
<th v-for="col in columnsWithWidth" :style="{ width: col.width, cursor: 'auto' }" class="column-name"
727766
@contextmenu.prevent="useContextMenuStore().show($event, { type: 'column_header', name: col.name })">
728767
<span style="cursor: auto;">{{ col.name }}</span>
729768
<FilterIcon v-if="col.faceted" :style="{ opacity: store.isFacetActive(col.name) ? 1 : 0.2 }" />
@@ -745,15 +784,15 @@ const updateSampleLine = () => {
745784
746785
</span>
747786
</td>
748-
<td class="cell" v-for="c, k2 in columns" :style="Object.assign(row.cells[k2].style as StyleValue || {},{
787+
<td class="cell" v-for="c, k2 in columnsWithWidth" :style="Object.assign(row.cells[k2].style as StyleValue || {},{
749788
backgroundColor: (store.layout.settings.paintCorrelationIdCell && store.layout.settings.correlationIdField == c.name) ? hashStringToRgb(row.cells[k2].text||'', 40): ''
750789
} as StyleValue)"
751790
:class="{ 'cell-error': row.cells[k2].error }">
752-
<div v-if="row.cells[k2].allowHtmlInText" :style="{ width: columns[k2].width + 'px' }"
791+
<div v-if="row.cells[k2].allowHtmlInText" :style="{ width: columnsWithWidth[k2].width }"
753792
v-html="row.cells[k2].text !== undefined ? row.cells[k2].text : row.cells[k2].error || '&nbsp;'"
754793
@contextmenu.prevent="useContextMenuStore().show($event, { type: 'cell', value: row.cells[k2].text, columnId: c.id, error: row.cells[k2].error })">
755794
</div>
756-
<div v-else :style="{ width: columns[k2].width + 'px' }"
795+
<div v-else :style="{ width: columnsWithWidth[k2].width }"
757796
@contextmenu.prevent="useContextMenuStore().show($event, { type: 'cell', value: row.cells[k2].text, columnId: c.id, error: row.cells[k2].error })">
758797
{{ row.cells[k2].text !== undefined ? row.cells[k2].text : row.cells[k2].error || "&nbsp;" }}
759798
</div>

src/components/SettingsDrawer.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ const addMiddleware = () => {
568568
<div class="row">
569569
<div>Column width</div>
570570
<div>
571-
<input class="input" v-model="selectedColumn.width" type="number" />
571+
<input class="input" v-model="selectedColumn.width" type="text" />
572572
</div>
573573
</div>
574574
</div>

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ export type Column = {
179179
id: string
180180
name: string,
181181
idx?: number,
182-
width?: number
182+
width?: number | string
183183
hidden?: boolean
184184
handler?: CellHandlerFn,
185185
handlerTsCode?: string,

0 commit comments

Comments
 (0)