mirror of
https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
synced 2024-06-07 21:20:49 +00:00
Fix dblclick of resize grid handle. Fix resizing bugs.
This commit is contained in:
parent
ecfa65f12a
commit
16495c203e
@ -676,34 +676,24 @@ class ExtraNetworksTab {
|
||||
this.applyFilter(this.txt_search_elem.value);
|
||||
}
|
||||
|
||||
autoSetTreeWidth() {
|
||||
const row = this.container_elem.querySelector(".resize-handle-row");
|
||||
if (!isElementLogError(row)) {
|
||||
autoSetTreeWidth(handle_elem) {
|
||||
const siblings = this.resize_grid.getSiblings(handle_elem);
|
||||
const tree_item = siblings.prev;
|
||||
// Only process if the prev element is our tree view.
|
||||
if (tree_item.elem !== this.tree_list.scroll_elem.closest(".resize-grid--cell")) {
|
||||
return;
|
||||
}
|
||||
let new_size_px = this.tree_list.getMaxRowWidth();
|
||||
if (!isNumber(new_size_px)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const left_col = row.firstElementChild;
|
||||
if (!isElementLogError(left_col)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the left column is hidden then we don't want to do anything.
|
||||
if (left_col.classList.contains("hidden")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pad = parseFloat(row.style.gridTemplateColumns.split(" ")[1]);
|
||||
const min_left_col_width = parseFloat(left_col.style.flexBasis.slice(0, -2));
|
||||
// We know that the tree list is the left column. That is the only one we want to resize.
|
||||
let max_width = this.tree_list.getMaxRowWidth();
|
||||
if (!isNumber(max_width)) {
|
||||
return;
|
||||
}
|
||||
// Add the resize handle's padding to the result and default to minLeftColWidth if necessary.
|
||||
max_width = Math.max(max_width + pad, min_left_col_width);
|
||||
|
||||
// Mimicks resizeHandle.js::setLeftColGridTemplate().
|
||||
row.style.gridTemplateColumns = `${max_width}px ${pad}px 1fr`;
|
||||
// Account for border dims on the container.
|
||||
const div_tree = this.tree_list.scroll_elem.closest(".extra-network-content--tree-view");
|
||||
new_size_px += div_tree.offsetWidth - div_tree.clientWidth;
|
||||
// Clamp the value to the min_size.
|
||||
new_size_px = Math.max(tree_item.min_size, new_size_px);
|
||||
tree_item.parent.resizeItem(tree_item, new_size_px);
|
||||
}
|
||||
|
||||
async clearSelectedButtons({excluded_div_ids} = {}) {
|
||||
@ -1612,11 +1602,12 @@ function extraNetworksSetupEventDelegators() {
|
||||
dbl_press_time_ms = 0;
|
||||
}
|
||||
|
||||
window.addEventListener("resizeHandleDblClick", event => {
|
||||
// See resizeHandle.js::onDoubleClick() for event detail.
|
||||
window.addEventListener("resize_grid_handle_dblclick", event => {
|
||||
// See resizeGrid.js::ResizeGrid.setupEvents() for event detail.
|
||||
event.stopPropagation();
|
||||
const pane = event.target.closest(".extra-network-pane");
|
||||
extra_networks_tabs[pane.dataset.tabnameFull].autoSetTreeWidth();
|
||||
const handle = event.target.closest(".resize-grid--handle");
|
||||
extra_networks_tabs[pane.dataset.tabnameFull].autoSetTreeWidth(handle);
|
||||
});
|
||||
|
||||
// Debounce search text input. This way we only search after user is done typing.
|
||||
|
@ -343,23 +343,33 @@ class ExtraNetworksClusterizeTreeList extends ExtraNetworksClusterize {
|
||||
let row_width = 0;
|
||||
for (let j = 0; j < this.options.cols_in_block; j++) {
|
||||
const child = this.content_elem.children[i + j];
|
||||
const child_style = window.getComputedStyle(child, null);
|
||||
const prev_style = child.style.cssText;
|
||||
const n_cols = child_style.getPropertyValue("grid-template-columns").split(" ").length;
|
||||
child.style.gridTemplateColumns = `repeat(${n_cols}, max-content)`;
|
||||
row_width += child.scrollWidth;
|
||||
// Restore previous style.
|
||||
child.style.cssText = prev_style;
|
||||
// Child first element is the indent div. Just use offset for this
|
||||
// since we do some overlapping with ::after in CSS.
|
||||
row_width += child.children[0].offsetWidth;
|
||||
// Button is second element. We want entire scroll width of this one.
|
||||
// But first we need to allow it to shrink to content.
|
||||
const prev_css_text = child.children[1].cssText;
|
||||
child.children[1].style.flex = "0 1 auto";
|
||||
row_width += child.children[1].scrollWidth;
|
||||
// Add the button label's overflow to the width.
|
||||
const lbl = child.querySelector(".tree-list-item-label");
|
||||
row_width += lbl.scrollWidth - lbl.offsetWidth;
|
||||
// Revert changes to element style.
|
||||
if (!prev_css_text) {
|
||||
child.children[1].removeAttribute("style");
|
||||
} else {
|
||||
child.children[1].cssText = prev_css_text;
|
||||
}
|
||||
}
|
||||
max_width = Math.max(max_width, row_width);
|
||||
max_width = Math.max(row_width, max_width);
|
||||
}
|
||||
if (max_width <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Adds the scroll element's border and the scrollbar's width to the result.
|
||||
// If scrollbar isn't visible, then only the element border is added.
|
||||
max_width += this.scroll_elem.offsetWidth - this.scroll_elem.clientWidth;
|
||||
// Adds the scroll_elem's scrollbar and padding to the result.
|
||||
// If scrollbar isn't visible, then only the element border/padding is added.
|
||||
max_width += this.scroll_elem.offsetWidth - this.content_elem.offsetWidth;
|
||||
return max_width;
|
||||
}
|
||||
|
||||
|
@ -535,26 +535,6 @@ class ResizeGridAxis extends ResizeGridItem {
|
||||
}
|
||||
}
|
||||
|
||||
getSiblings(handle_elem) {
|
||||
/** Returns the nearest visible ResizeGridItems surrounding a ResizeGridHandle.
|
||||
*
|
||||
* Args:
|
||||
* handle_elem (Element): The handle element in the grid to lookup.
|
||||
*
|
||||
* Returns:
|
||||
* Object: Keys=(prev, next). Values are ResizeGridItems.
|
||||
*/
|
||||
let prev = this.getItem({elem: handle_elem.previousElementSibling});
|
||||
if (!prev.visible) {
|
||||
prev = prev.parent.items.slice(0, this.items.indexOf(prev)).findLast(x => x.visible);
|
||||
}
|
||||
let next = this.getItem({elem: handle_elem.nextElementSibling});
|
||||
if (!next.visible) {
|
||||
next = next.parent.items.slice(this.items.indexOf(next) + 1).findLast(x => x.visible);
|
||||
}
|
||||
return {prev: prev, next: next};
|
||||
}
|
||||
|
||||
updateVisibleHandles() {
|
||||
/** Sets the visibility of each ResizeGridHandle based on surrounding items. */
|
||||
for (const item of this.items) {
|
||||
@ -657,6 +637,78 @@ class ResizeGridAxis extends ResizeGridItem {
|
||||
}
|
||||
}
|
||||
|
||||
resizeItem(item, size_px) {
|
||||
// Don't resize invisible items.
|
||||
if (!item.visible) {
|
||||
return;
|
||||
}
|
||||
// Don't resize item if it is the only visible item in the axis.
|
||||
if (this.items.filter(x => x.visible).length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (size_px < item.min_size) {
|
||||
console.error(`Requested size is too small: ${size_px} < ${item.min_size}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const dims = this.elem.getBoundingClientRect();
|
||||
let max_size = parseInt(this.axis === 0 ? dims.width : dims.height);
|
||||
const vis_siblings = this.items.filter(x => x.visible && x !== item);
|
||||
max_size -= vis_siblings.reduce((acc, obj) => {
|
||||
return acc + obj.min_size + (obj.handle.visible ? obj.handle.pad_px : 0);
|
||||
}, 0);
|
||||
|
||||
if (size_px > max_size) {
|
||||
console.error(`Requested size is too large: ${size_px} > ${max_size}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the direct sibling of this item.
|
||||
const idx = this.items.indexOf(item);
|
||||
isNullOrUndefinedThrowError(item); // Indicates programmer error.
|
||||
// Look after item.
|
||||
let sibling = this.items.slice(idx + 1).find(x => x.visible);
|
||||
if (isNullOrUndefined(sibling)) {
|
||||
// No valid siblings after item, look before item.
|
||||
sibling = this.items.slice(0, idx).findLast(x => x.visible);
|
||||
isNullOrUndefinedThrowError(sibling); // Indicates programmer error.
|
||||
}
|
||||
const sibling_idx = this.items.indexOf(sibling);
|
||||
|
||||
const _make_room = (sibling, others, tot_px) => {
|
||||
let rem = tot_px;
|
||||
// Shrink from the sibling first.
|
||||
rem = sibling.shrink(rem, {limit_to_base: false});
|
||||
if (rem <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shrink all other items next, starting from the end.
|
||||
for (const other of others.slice().reverse()) {
|
||||
rem = other.shrink(rem, {limit_to_base: false});
|
||||
if (rem <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// This indicates a programmer error.
|
||||
throw new Error(`No space for item. tot: ${tot_px}, rem: ${rem}`);
|
||||
};
|
||||
|
||||
const curr_size = item.getSize();
|
||||
if (size_px < curr_size) { // shrink
|
||||
item.shrink(curr_size - size_px, {limit_to_base: false});
|
||||
sibling.grow(-1);
|
||||
} else if (size_px > curr_size) { // grow
|
||||
const others = this.items.filter((x, i) => {
|
||||
return x.visible && i !== idx && i !== sibling_idx;
|
||||
});
|
||||
_make_room(sibling, others, size_px - curr_size);
|
||||
item.setSize(size_px);
|
||||
}
|
||||
}
|
||||
|
||||
show({id, idx, elem, item} = {}) {
|
||||
/** Shows an item along this axis.
|
||||
*
|
||||
@ -875,6 +927,7 @@ class ResizeGrid extends ResizeGridAxis {
|
||||
handle.elem.setPointerCapture(event.pointerId);
|
||||
|
||||
// Temporarily set styles for elements. These are cleared on pointerup.
|
||||
// Also cleared if dblclick is fired.
|
||||
// See `onMove()` comments for more info.
|
||||
prev.setSize(prev.getSize());
|
||||
next.setSize(next.getSize());
|
||||
@ -888,6 +941,34 @@ class ResizeGrid extends ResizeGridAxis {
|
||||
} else {
|
||||
document.body.classList.add('resizing-row');
|
||||
}
|
||||
|
||||
if (!dblclick_timer) {
|
||||
handle.elem.dataset.awaitDblClick = '';
|
||||
dblclick_timer = setTimeout(
|
||||
(elem) => {
|
||||
dblclick_timer = null;
|
||||
delete elem.dataset.awaitDblClick;
|
||||
},
|
||||
DBLCLICK_TIME_MS,
|
||||
handle.elem
|
||||
);
|
||||
} else if ('awaitDblClick' in handle.elem.dataset) {
|
||||
clearTimeout(dblclick_timer);
|
||||
dblclick_timer = null;
|
||||
delete handle.elem.dataset.awaitDblClick;
|
||||
handle.elem.dispatchEvent(
|
||||
new CustomEvent('resize_grid_handle_dblclick', {
|
||||
bubbles: true,
|
||||
detail: this,
|
||||
})
|
||||
);
|
||||
prev.render();
|
||||
next.render();
|
||||
|
||||
prev = null;
|
||||
handle = null;
|
||||
next = null;
|
||||
}
|
||||
},
|
||||
{signal: this.event_abort_controller.signal}
|
||||
);
|
||||
@ -918,13 +999,9 @@ class ResizeGrid extends ResizeGridAxis {
|
||||
window.addEventListener(
|
||||
'pointerup',
|
||||
(event) => {
|
||||
if (
|
||||
isNullOrUndefined(prev) ||
|
||||
isNullOrUndefined(handle) ||
|
||||
isNullOrUndefined(next)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
document.body.classList.remove('resizing');
|
||||
document.body.classList.remove('resizing-col');
|
||||
document.body.classList.remove('resizing-row');
|
||||
|
||||
if (event.target.hasPointerCapture(event.pointerId)) {
|
||||
event.target.releasePointerCapture(event.pointerId);
|
||||
@ -933,6 +1010,15 @@ class ResizeGrid extends ResizeGridAxis {
|
||||
if (event.pointerType === 'mouse' && event.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
isNullOrUndefined(prev) ||
|
||||
isNullOrUndefined(handle) ||
|
||||
isNullOrUndefined(next)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.pointerType === 'touch') {
|
||||
touch_count--;
|
||||
}
|
||||
@ -948,31 +1034,6 @@ class ResizeGrid extends ResizeGridAxis {
|
||||
prev.render();
|
||||
next.render();
|
||||
|
||||
document.body.classList.remove('resizing');
|
||||
document.body.classList.remove('resizing-col');
|
||||
document.body.classList.remove('resizing-row');
|
||||
|
||||
if (!dblclick_timer) {
|
||||
handle.elem.dataset.awaitDblClick = '';
|
||||
dblclick_timer = setTimeout(
|
||||
(elem) => {
|
||||
dblclick_timer = null;
|
||||
delete elem.dataset.awaitDblClick;
|
||||
},
|
||||
DBLCLICK_TIME_MS,
|
||||
handle.elem
|
||||
);
|
||||
} else if ('awaitDblClick' in handle.elem.dataset) {
|
||||
clearTimeout(dblclick_timer);
|
||||
dblclick_timer = null;
|
||||
delete handle.elem.dataset.awaitDblClick;
|
||||
handle.elem.dispatchEvent(
|
||||
new CustomEvent('resize_handle_dblclick', {
|
||||
bubbles: true,
|
||||
detail: this,
|
||||
})
|
||||
);
|
||||
}
|
||||
prev = null;
|
||||
handle = null;
|
||||
next = null;
|
||||
@ -1092,6 +1153,26 @@ class ResizeGrid extends ResizeGridAxis {
|
||||
}
|
||||
}
|
||||
|
||||
getSiblings(handle_elem) {
|
||||
/** Returns the nearest visible ResizeGridItems surrounding a ResizeGridHandle.
|
||||
*
|
||||
* Args:
|
||||
* handle_elem (Element): The handle element in the grid to lookup.
|
||||
*
|
||||
* Returns:
|
||||
* Object: Keys=(prev, next). Values are ResizeGridItems.
|
||||
*/
|
||||
let prev = this.getItem({elem: handle_elem.previousElementSibling});
|
||||
if (!prev.visible) {
|
||||
prev = prev.parent.items.slice(0, this.items.indexOf(prev)).findLast(x => x.visible);
|
||||
}
|
||||
let next = this.getItem({elem: handle_elem.nextElementSibling});
|
||||
if (!next.visible) {
|
||||
next = next.parent.items.slice(this.items.indexOf(next) + 1).findLast(x => x.visible);
|
||||
}
|
||||
return {prev: prev, next: next};
|
||||
}
|
||||
|
||||
onMove(event, a, handle, b) {
|
||||
/** Handles pointermove events by calculating and setting new size of elements.
|
||||
*
|
||||
|
81
style.css
81
style.css
@ -1269,6 +1269,7 @@ body.resizing.resize-grid-row {
|
||||
height: 100%;
|
||||
/* Use scroll instead of auto so that content size doesn't change when there is no content. */
|
||||
overflow: clip scroll;
|
||||
padding: var(--spacing-md) 0 var(--spacing-md) var(--spacing-md);
|
||||
}
|
||||
|
||||
.clusterize-content {
|
||||
@ -1277,7 +1278,6 @@ body.resizing.resize-grid-row {
|
||||
/* need to manually set the gap to 0 to fix item dimension calcs. */
|
||||
gap: 0;
|
||||
counter-reset: clusterize-counter;
|
||||
padding: var(--spacing-md);
|
||||
}
|
||||
|
||||
.clusterize-extra-row {
|
||||
@ -1533,33 +1533,33 @@ body.resizing.resize-grid-row {
|
||||
|
||||
/* BUTTON ELEMENTS */
|
||||
.tree-list-item {
|
||||
display: grid;
|
||||
grid-auto-rows: 1fr;
|
||||
grid-template-columns: auto 1fr;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
height: calc(var(--button-large-text-size) + (2 * var(--spacing-sm)));
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
user-select: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* <button> */
|
||||
.tree-list-item button {
|
||||
display: grid;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
border: none !important;
|
||||
user-select: none;
|
||||
grid-template-rows: min-content;
|
||||
grid-template-areas: "leading-action leading-visual label trailing-visual trailing-action";
|
||||
grid-template-columns: min-content min-content minmax(calc(var(--body-text-size) * 1), auto) min-content min-content;
|
||||
grid-gap: var(--spacing-sm);
|
||||
place-items: center stretch;
|
||||
text-align: center;
|
||||
/* prevents height from changing on overflow */
|
||||
}
|
||||
|
||||
.tree-list-item > button {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
gap: var(--spacing-sm);
|
||||
user-select: none;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
border: none !important;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
place-items: center stretch;
|
||||
}
|
||||
|
||||
.tree-list-item:hover {
|
||||
@ -1568,7 +1568,10 @@ body.resizing.resize-grid-row {
|
||||
background: var(--button-secondary-background-fill-hover);
|
||||
}
|
||||
|
||||
.tree-list-item button > span {
|
||||
.tree-list-item > button > span {
|
||||
display: block;
|
||||
flex: 0 0 auto;
|
||||
text-align: center;
|
||||
font-size: var(--button-large-text-size);
|
||||
color: var(--button-secondary-text-color);
|
||||
}
|
||||
@ -1632,10 +1635,8 @@ body.resizing.resize-grid-row {
|
||||
}
|
||||
|
||||
/* Text for button. */
|
||||
.tree-list-item-label {
|
||||
position: relative;
|
||||
grid-area: label;
|
||||
padding-left: 0.25em;
|
||||
.tree-list-item .tree-list-item-label {
|
||||
flex: 0 1 auto;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
@ -1649,39 +1650,30 @@ body.resizing.resize-grid-row {
|
||||
/* Icon for button. */
|
||||
.tree-list-item-visual {
|
||||
pointer-events: none;
|
||||
align-items: right;
|
||||
}
|
||||
|
||||
/* Icon for button when it is before label. */
|
||||
.tree-list-item-visual--leading {
|
||||
grid-area: leading-visual;
|
||||
.tree-list-item .tree-list-item-visual--leading {
|
||||
width: var(--button-large-text-size);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Icon for button when it is after label. */
|
||||
.tree-list-item-visual--trailing {
|
||||
grid-area: trailing-visual;
|
||||
width: var(--button-large-text-size);
|
||||
text-align: right;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Dropdown arrow for button. */
|
||||
.tree-list-item-action--leading {
|
||||
grid-area: leading-action;
|
||||
}
|
||||
.tree-list-item-action--leading {}
|
||||
|
||||
.tree-list-item--file .tree-list-item-action--leading {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Allow trailing action to overlap previous columns when area is too small. */
|
||||
.tree-list-item-action--trailing {
|
||||
z-index: 10;
|
||||
grid-area: 1 / label / 1 / trailing-action;
|
||||
justify-self: end;
|
||||
padding-left: var(--spacing-sm);
|
||||
}
|
||||
.tree-list-item-action--trailing {}
|
||||
|
||||
/* Force background color on hover to hide any overlapped column content. */
|
||||
.tree-list-item:hover .tree-list-item-action--trailing {
|
||||
@ -1799,13 +1791,6 @@ body.resizing.resize-grid-row {
|
||||
outline-offset: calc(-1 * var(--spacing-xs));
|
||||
}
|
||||
|
||||
.tree-list-item {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tree-list-item:not(.pressed):hover {
|
||||
-webkit-transition: all 0.05s ease-in-out;
|
||||
transition: all 0.05s ease-in-out;
|
||||
|
Loading…
Reference in New Issue
Block a user