Improve column resizing robustness (#2588)

Also:

* Add staticWidth and minWidth column properties
This commit is contained in:
Adomas Ven 2022-05-03 10:00:23 +03:00 committed by GitHub
parent 01645c5e51
commit c49a05d486
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 25 additions and 33 deletions

View file

@ -36,6 +36,9 @@ const { IconDownChevron, getDOMElement } = require('components/icons');
const TYPING_TIMEOUT = 1000;
const MINIMUM_ROW_HEIGHT = 20; // px
const RESIZER_WIDTH = 5; // px
const COLUMN_MIN_WIDTH = 20;
const COLUMN_NORMALIZATION_WIDTH = 8192;
const COLUMN_PADDING = 10; // N.B. MUST BE INLINE WITH CSS!!!
const noop = () => 0;
@ -760,21 +763,6 @@ class VirtualizedTable extends React.Component {
// ------------------------ Column Methods ------------------------- //
/**
* A public function to update the column CSS flex widths. To be used
* upon window resize and similar. Especially important on macOS where
* column borders are used and get out of sync with column headers.
*/
updateColumnWidths = Zotero.Utilities.debounce(() => {
let resizeData = {};
const columns = this._getVisibleColumns();
for (const column of columns) {
const elem = document.querySelector(`#${this.props.id} .virtualized-table-header .cell.${column.dataKey}`)
resizeData[column.dataKey] = elem.getBoundingClientRect().width;
}
this._columns.onResize(resizeData, true);
}, 200)
_handleResizerDragStart = (index, event) => {
if (event.button !== 0) return false;
event.stopPropagation();
@ -811,8 +799,9 @@ class VirtualizedTable extends React.Component {
offset += resizingRect.width;
}
const widthSum = aRect.width + bRect.width;
// Column min-width: 20px;
const aColumnWidth = Math.min(widthSum - 20, Math.max(20, event.clientX - (RESIZER_WIDTH / 2) - offset));
const aSpacingOffset = (aColumn.minWidth ? aColumn.minWidth : COLUMN_MIN_WIDTH) + COLUMN_PADDING;
const bSpacingOffset = (bColumn.minWidth ? bColumn.minWidth : COLUMN_MIN_WIDTH) + COLUMN_PADDING;
const aColumnWidth = Math.min(widthSum - bSpacingOffset, Math.max(aSpacingOffset, event.clientX - (RESIZER_WIDTH / 2) - offset));
const bColumnWidth = widthSum - aColumnWidth;
let onResizeData = {};
onResizeData[aColumn.dataKey] = aColumnWidth;
@ -1477,6 +1466,8 @@ var Columns = class {
if (storePrefs) {
var prefs = this._getPrefs();
}
const header = document.querySelector(`#${this._styleKey} .virtualized-table-header`);
const headerWidth = header ? header.getBoundingClientRect().width : 300;
for (let [dataKey, width] of Object.entries(columnWidths)) {
if (typeof dataKey == "number") {
dataKey = this._columns[dataKey].dataKey;
@ -1487,11 +1478,15 @@ var Columns = class {
column.width = width;
prefs[dataKey] = this._getColumnPrefsToPersist(column);
}
if (column.fixedWidth && column.width) {
if (column.fixedWidth) {
width = column.width;
}
if (column.fixedWidth && column.width || column.staticWidth) {
this._stylesheet.sheet.cssRules[styleIndex].style.setProperty('flex', `0 0`, `important`);
this._stylesheet.sheet.cssRules[styleIndex].style.setProperty('max-width', `${column.width}px`, 'important');
this._stylesheet.sheet.cssRules[styleIndex].style.setProperty('min-width', `${column.width}px`, 'important');
this._stylesheet.sheet.cssRules[styleIndex].style.setProperty('max-width', `${width}px`, 'important');
this._stylesheet.sheet.cssRules[styleIndex].style.setProperty('min-width', `${width}px`, 'important');
} else {
width = (width - COLUMN_PADDING) * COLUMN_NORMALIZATION_WIDTH / headerWidth;
this._stylesheet.sheet.cssRules[styleIndex].style.setProperty('flex-basis', `${width}px`);
}
}

View file

@ -2734,7 +2734,7 @@ var ItemTree = class ItemTree extends LibraryTree {
const depth = this.getLevel(index);
let firstChildIndent = 0;
if (column.ordinal == 0) {
firstChildIndent = 6;
firstChildIndent = 5;
}
span.style.paddingInlineStart = ((CHILD_INDENT * depth) + firstChildIndent) + 'px';

View file

@ -38,6 +38,9 @@ const Icons = require('components/icons');
* flex: number, // Default: 1. When the column is added to the tree how much space it should occupy as a flex ratio
* width: string, // A column width instead of flex ratio. See above.
* fixedWidth: boolean // Default: false. Set to true to disable column resizing
* staticWidth: boolean // Default: false. Set to true to prevent columns from changing width when
* // the width of the tree increases or decreases
* minWidth: number, // Override the default [20px] column min-width for resizing
*
* label: string, // The column label. Either a string or the id to an i18n string.
* iconLabel: React.Component, // Set an Icon label instead of a text-based one
@ -86,6 +89,7 @@ const COLUMNS = [
defaultSort: -1,
label: "zotero.items.year_column",
flex: 1,
staticWidth: true,
zoteroPersist: new Set(["width", "hidden", "sortDirection"])
},
{
@ -298,6 +302,8 @@ const COLUMNS = [
label: "zotero.tabs.notes.label",
iconLabel: <Icons.IconTreeitemNoteSmall />,
width: "14",
minWidth: 14,
staticWidth: true,
zoteroPersist: new Set(["width", "hidden", "sortDirection"])
}
];

View file

@ -108,7 +108,6 @@ var ZoteroPane = new function()
if (!tabsDeck || tabsDeck.getAttribute('selectedIndex') == 0) {
this.updateToolbarPosition();
this.updateTagsBoxSize();
this.updateItemTreeColumnWidths();
}
});
window.setTimeout(this.updateToolbarPosition.bind(this), 0);
@ -5485,11 +5484,6 @@ var ZoteroPane = new function()
}
};
this.updateItemTreeColumnWidths = function() {
if (!ZoteroPane.itemsView || !ZoteroPane.itemsView.tree) return;
ZoteroPane.itemsView.tree.updateColumnWidths();
};
/**
* Opens the about dialog
*/

View file

@ -39,10 +39,6 @@
}
}
.cell:first-child {
padding-inline-start: 6px;
}
.cell {
min-width: 30px;
cursor: default;
@ -63,7 +59,7 @@
flex-shrink: 1;
text-overflow: ellipsis;
overflow: hidden;
margin-inline-start: 6px;
margin-inline-start: 5px;
}
.twisty + .cell-text, .spacer-twisty + .cell-text {
@ -178,6 +174,7 @@
position: relative;
height: 100%;
align-items: center;
padding: 0 5px;
&:hover {
background: #fff;
@ -199,7 +196,7 @@
}
.label {
margin-inline-start: 10px;
margin-inline-start: 5px;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;