mirror of
https://github.com/google/blockly.git
synced 2026-01-08 17:40:09 +01:00
fix: make autoclose toggleable for flyouts (#7634)
* fix: add basic autoclose toggling support * fix: drag areas being incorrect * fix: blocks getting bumped around when dragged into flyout area * fix: respect always-open flyouts attached to toolboxes * fix: flyout not hiding on ws click * fix: have all flyouts filter for capacity * chore: cleanup * fix: view metrics not respecting flyout * chore: fix change detectors * fix: trashcan not firing close event on click
This commit is contained in:
@@ -36,6 +36,7 @@ import {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as utilsXml from './utils/xml.js';
|
||||
import * as Xml from './xml.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
import {IAutoHideable} from './interfaces/i_autohideable.js';
|
||||
|
||||
enum FlyoutItemType {
|
||||
BLOCK = 'block',
|
||||
@@ -45,7 +46,10 @@ enum FlyoutItemType {
|
||||
/**
|
||||
* Class for a flyout.
|
||||
*/
|
||||
export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
export abstract class Flyout
|
||||
extends DeleteArea
|
||||
implements IAutoHideable, IFlyout
|
||||
{
|
||||
/**
|
||||
* Position the flyout.
|
||||
*/
|
||||
@@ -385,10 +389,8 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
this.wheel_,
|
||||
),
|
||||
);
|
||||
if (!this.autoClose) {
|
||||
this.filterWrapper = this.filterForCapacity.bind(this);
|
||||
this.targetWorkspace.addChangeListener(this.filterWrapper);
|
||||
}
|
||||
this.filterWrapper = this.filterForCapacity.bind(this);
|
||||
this.targetWorkspace.addChangeListener(this.filterWrapper);
|
||||
|
||||
// Dragging the flyout up and down.
|
||||
this.boundEvents.push(
|
||||
@@ -414,6 +416,7 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
component: this,
|
||||
weight: 1,
|
||||
capabilities: [
|
||||
ComponentManager.Capability.AUTOHIDEABLE,
|
||||
ComponentManager.Capability.DELETE_AREA,
|
||||
ComponentManager.Capability.DRAG_TARGET,
|
||||
],
|
||||
@@ -426,7 +429,7 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
*/
|
||||
dispose() {
|
||||
this.hide();
|
||||
this.workspace_.getComponentManager().removeComponent(this.id);
|
||||
this.targetWorkspace.getComponentManager().removeComponent(this.id);
|
||||
for (const event of this.boundEvents) {
|
||||
browserEvents.unbind(event);
|
||||
}
|
||||
@@ -480,6 +483,26 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
return this.workspace_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this flyout automatically closes when blocks are dragged out,
|
||||
* the workspace is clicked, etc, or not.
|
||||
*/
|
||||
setAutoClose(autoClose: boolean) {
|
||||
this.autoClose = autoClose;
|
||||
this.targetWorkspace.recordDragTargets();
|
||||
this.targetWorkspace.resizeContents();
|
||||
}
|
||||
|
||||
/** Automatically hides the flyout if it is an autoclosing flyout. */
|
||||
autoHide(onlyClosePopups: boolean): void {
|
||||
if (
|
||||
!onlyClosePopups &&
|
||||
this.targetWorkspace.getFlyout(true) === this &&
|
||||
this.autoClose
|
||||
)
|
||||
this.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the flyout visible?
|
||||
*
|
||||
@@ -504,7 +527,7 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
if (!this.autoClose) {
|
||||
// Auto-close flyouts are ignored as drag targets, so only non
|
||||
// auto-close flyouts need to have their drag target updated.
|
||||
this.workspace_.recordDragTargets();
|
||||
this.targetWorkspace.recordDragTargets();
|
||||
}
|
||||
this.updateDisplay();
|
||||
}
|
||||
@@ -624,6 +647,7 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
|
||||
// Parse the Array, Node or NodeList into a a list of flyout items.
|
||||
const parsedContent = toolbox.convertFlyoutDefToJsonArray(flyoutDef);
|
||||
if (!parsedContent.length) return; // No need to show an empty flyout.
|
||||
const flyoutInfo = this.createFlyoutInfo(parsedContent);
|
||||
|
||||
renderManagement.triggerQueuedRenders();
|
||||
|
||||
@@ -382,22 +382,10 @@ export class HorizontalFlyout extends Flyout {
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
this.targetWorkspace!.toolboxPosition === this.toolboxPosition_ &&
|
||||
this.toolboxPosition_ === toolbox.Position.TOP &&
|
||||
!this.targetWorkspace!.getToolbox()
|
||||
) {
|
||||
// This flyout is a simple toolbox. Reposition the workspace so that
|
||||
// (0,0) is in the correct position relative to the new absolute edge
|
||||
// (ie toolbox edge).
|
||||
this.targetWorkspace!.translate(
|
||||
this.targetWorkspace!.scrollX,
|
||||
this.targetWorkspace!.scrollY + flyoutHeight,
|
||||
);
|
||||
}
|
||||
this.height_ = flyoutHeight;
|
||||
this.position();
|
||||
this.targetWorkspace!.recordDragTargets();
|
||||
this.targetWorkspace.resizeContents();
|
||||
this.targetWorkspace.recordDragTargets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,22 +375,10 @@ export class VerticalFlyout extends Flyout {
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
this.targetWorkspace!.toolboxPosition === this.toolboxPosition_ &&
|
||||
this.toolboxPosition_ === toolbox.Position.LEFT &&
|
||||
!this.targetWorkspace!.getToolbox()
|
||||
) {
|
||||
// This flyout is a simple toolbox. Reposition the workspace so that
|
||||
// (0,0) is in the correct position relative to the new absolute edge
|
||||
// (ie toolbox edge).
|
||||
this.targetWorkspace!.translate(
|
||||
this.targetWorkspace!.scrollX + flyoutWidth,
|
||||
this.targetWorkspace!.scrollY,
|
||||
);
|
||||
}
|
||||
this.width_ = flyoutWidth;
|
||||
this.position();
|
||||
this.targetWorkspace!.recordDragTargets();
|
||||
this.targetWorkspace.resizeContents();
|
||||
this.targetWorkspace.recordDragTargets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,26 +111,25 @@ export class MetricsManager implements IMetricsManager {
|
||||
*/
|
||||
getAbsoluteMetrics(): AbsoluteMetrics {
|
||||
let absoluteLeft = 0;
|
||||
let absoluteTop = 0;
|
||||
|
||||
const toolboxMetrics = this.getToolboxMetrics();
|
||||
const flyoutMetrics = this.getFlyoutMetrics(true);
|
||||
const doesToolboxExist = !!this.workspace_.getToolbox();
|
||||
const doesFlyoutExist = !!this.workspace_.getFlyout(true);
|
||||
const toolboxPosition = doesToolboxExist
|
||||
const flyoutMetrics = this.getFlyoutMetrics();
|
||||
const respectToolbox = !!this.workspace_.getToolbox();
|
||||
const respectFlyout = !this.workspace_.getFlyout()?.autoClose;
|
||||
const toolboxPosition = respectToolbox
|
||||
? toolboxMetrics.position
|
||||
: flyoutMetrics.position;
|
||||
|
||||
const atLeft = toolboxPosition === toolboxUtils.Position.LEFT;
|
||||
const atTop = toolboxPosition === toolboxUtils.Position.TOP;
|
||||
if (doesToolboxExist && atLeft) {
|
||||
absoluteLeft = toolboxMetrics.width;
|
||||
} else if (doesFlyoutExist && atLeft) {
|
||||
absoluteLeft = flyoutMetrics.width;
|
||||
if (atLeft) {
|
||||
if (respectToolbox) absoluteLeft += toolboxMetrics.width;
|
||||
if (respectFlyout) absoluteLeft += flyoutMetrics.width;
|
||||
}
|
||||
let absoluteTop = 0;
|
||||
if (doesToolboxExist && atTop) {
|
||||
absoluteTop = toolboxMetrics.height;
|
||||
} else if (doesFlyoutExist && atTop) {
|
||||
absoluteTop = flyoutMetrics.height;
|
||||
if (atTop) {
|
||||
if (respectToolbox) absoluteTop += toolboxMetrics.height;
|
||||
if (respectFlyout) absoluteTop += flyoutMetrics.height;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -152,36 +151,26 @@ export class MetricsManager implements IMetricsManager {
|
||||
const scale = opt_getWorkspaceCoordinates ? this.workspace_.scale : 1;
|
||||
const svgMetrics = this.getSvgMetrics();
|
||||
const toolboxMetrics = this.getToolboxMetrics();
|
||||
const flyoutMetrics = this.getFlyoutMetrics(true);
|
||||
const doesToolboxExist = !!this.workspace_.getToolbox();
|
||||
const toolboxPosition = doesToolboxExist
|
||||
const flyoutMetrics = this.getFlyoutMetrics();
|
||||
const respectToolbox = !!this.workspace_.getToolbox();
|
||||
const respectFlyout = !this.workspace_.getFlyout()?.autoClose;
|
||||
const toolboxPosition = respectToolbox
|
||||
? toolboxMetrics.position
|
||||
: flyoutMetrics.position;
|
||||
|
||||
if (this.workspace_.getToolbox()) {
|
||||
if (
|
||||
toolboxPosition === toolboxUtils.Position.TOP ||
|
||||
toolboxPosition === toolboxUtils.Position.BOTTOM
|
||||
) {
|
||||
svgMetrics.height -= toolboxMetrics.height;
|
||||
} else if (
|
||||
toolboxPosition === toolboxUtils.Position.LEFT ||
|
||||
toolboxPosition === toolboxUtils.Position.RIGHT
|
||||
) {
|
||||
svgMetrics.width -= toolboxMetrics.width;
|
||||
}
|
||||
} else if (this.workspace_.getFlyout(true)) {
|
||||
if (
|
||||
toolboxPosition === toolboxUtils.Position.TOP ||
|
||||
toolboxPosition === toolboxUtils.Position.BOTTOM
|
||||
) {
|
||||
svgMetrics.height -= flyoutMetrics.height;
|
||||
} else if (
|
||||
toolboxPosition === toolboxUtils.Position.LEFT ||
|
||||
toolboxPosition === toolboxUtils.Position.RIGHT
|
||||
) {
|
||||
svgMetrics.width -= flyoutMetrics.width;
|
||||
}
|
||||
const horizToolbox =
|
||||
toolboxPosition === toolboxUtils.Position.TOP ||
|
||||
toolboxPosition === toolboxUtils.Position.BOTTOM;
|
||||
const vertToolbox =
|
||||
toolboxPosition === toolboxUtils.Position.LEFT ||
|
||||
toolboxPosition === toolboxUtils.Position.RIGHT;
|
||||
if (horizToolbox) {
|
||||
if (respectToolbox) svgMetrics.height -= toolboxMetrics.height;
|
||||
if (respectFlyout) svgMetrics.height -= flyoutMetrics.height;
|
||||
}
|
||||
if (vertToolbox) {
|
||||
if (respectToolbox) svgMetrics.width -= toolboxMetrics.width;
|
||||
if (respectFlyout) svgMetrics.width -= flyoutMetrics.width;
|
||||
}
|
||||
return {
|
||||
height: svgMetrics.height / scale,
|
||||
|
||||
Reference in New Issue
Block a user