Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/blockly/core/bubbles/mini_workspace_bubble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,10 @@ export class MiniWorkspaceBubble extends Bubble {
/**
* Updates the size of this bubble to account for the size of the
* mini workspace.
*
* @internal
*/
private updateBubbleSize() {
updateBubbleSize() {
if (this.miniWorkspace.isDragging() && !KeyboardMover.mover.isMoving()) {
return;
}
Expand Down
8 changes: 6 additions & 2 deletions packages/blockly/core/bubbles/text_bubble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,12 @@ export class TextBubble extends Bubble {
}
}

/** Updates the size of this bubble to account for the size of the text. */
private updateBubbleSize() {
/**
* Updates the size of this bubble to account for the size of the text.
*
* @internal
*/
updateBubbleSize() {
const bbox = this.paragraph.getBBox();
this.setSize(
new Size(
Expand Down
4 changes: 4 additions & 0 deletions packages/blockly/core/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,10 @@ export abstract class Field<T = any>
if (this.textElement_) {
contentWidth = dom.getTextWidth(this.textElement_);
totalWidth += contentWidth;
totalHeight = Math.max(
totalHeight,
this.textElement_.getBoundingClientRect().height,
);
}
if (this.borderRect_) {
totalHeight = Math.max(totalHeight, constants!.FIELD_BORDER_RECT_HEIGHT);
Expand Down
13 changes: 6 additions & 7 deletions packages/blockly/core/flyout_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -628,13 +628,6 @@ export abstract class Flyout

this.setContents(flyoutInfo);

this.layout_(flyoutInfo);

if (this.horizontalLayout) {
this.height_ = 0;
} else {
this.width_ = 0;
}
this.reflow();
this.updateAriaContext();
eventUtils.setRecordUndo(true);
Expand Down Expand Up @@ -829,6 +822,12 @@ export abstract class Flyout
* Reflow flyout contents.
*/
reflow() {
this.layout_(this.getContents());
if (this.horizontalLayout) {
this.height_ = 0;
} else {
this.width_ = 0;
}
this.inhibitReflowWrapper = true;
this.reflowInternal_();
this.inhibitReflowWrapper = false;
Expand Down
5 changes: 4 additions & 1 deletion packages/blockly/core/flyout_horizontal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,10 @@ export class HorizontalFlyout extends Flyout {
for (const item of contents) {
const rect = item.getElement().getBoundingRectangle();
const moveX = this.RTL ? cursorX + rect.getWidth() : cursorX;
item.getElement().moveBy(moveX, cursorY);
const origin = item.getElement().getBoundingRectangle();
const deltaX = moveX - origin.left;
const deltaY = cursorY - origin.top;
item.getElement().moveBy(deltaX, deltaY);
cursorX += item.getElement().getBoundingRectangle().getWidth();
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/blockly/core/flyout_vertical.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,10 @@ export class VerticalFlyout extends Flyout {
let cursorY = margin;

for (const item of contents) {
item.getElement().moveBy(cursorX, cursorY);
const origin = item.getElement().getBoundingRectangle();
const deltaX = cursorX - origin.left;
const deltaY = cursorY - origin.top;
item.getElement().moveBy(deltaX, deltaY);
cursorY += item.getElement().getBoundingRectangle().getHeight();
}
}
Expand Down
20 changes: 14 additions & 6 deletions packages/blockly/core/renderers/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ export function isNotch(shape: Shape): shape is Notch {
);
}

const injectionSites = new Map<string, WeakSet<Document | ShadowRoot>>();
const injectionSites = new Map<
string,
WeakMap<Document | ShadowRoot, HTMLStyleElement>
>();

/**
* An object that provides constants for rendering blocks.
Expand Down Expand Up @@ -1126,11 +1129,15 @@ export class ConstantProvider {
*/
protected injectCSS_(root: Document | ShadowRoot, selector: string) {
if (typeof window === 'undefined') return;
if (injectionSites.get(selector)?.has(root)) return;

const styleEl = document.createElement('style');
const styleEl =
injectionSites.get(selector)?.get(root) ??
document.createElement('style');
const styles = this.getCSS_(selector).join('\n');
if (styleEl.textContent === styles) return;

styleEl.className = 'blockly-renderer-style';
styleEl.textContent = this.getCSS_(selector).join('\n');
styleEl.textContent = styles;
// See css.ts inject() for the rationale on prepending and shadow root
// handling.
(typeof globalThis.ShadowRoot !== 'undefined' && root instanceof ShadowRoot
Expand All @@ -1139,8 +1146,9 @@ export class ConstantProvider {
).prepend(styleEl);

const sitesForSelector =
injectionSites.get(selector) ?? new WeakSet<Document | ShadowRoot>();
sitesForSelector.add(root);
injectionSites.get(selector) ??
new WeakMap<Document | ShadowRoot, HTMLStyleElement>();
sitesForSelector.set(root, styleEl);
injectionSites.set(selector, sitesForSelector);
}

Expand Down
22 changes: 21 additions & 1 deletion packages/blockly/core/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ export function getTextWidth(textElement: SVGTextElement): number {
style.fontSize,
style.fontWeight,
style.fontFamily,
style.letterSpacing,
style.wordSpacing,
);

// Cache the computed width and return.
Expand All @@ -245,19 +247,25 @@ export function getTextWidth(textElement: SVGTextElement): number {
* @param fontSize The font size to use.
* @param fontWeight The font weight to use.
* @param fontFamily The font family to use.
* @param letterSpacing The letter spacing to use.
* @param wordSpacing The word spacing to use.
* @returns Width of element.
*/
export function getFastTextWidth(
textElement: SVGTextElement,
fontSize: number,
fontWeight: string,
fontFamily: string,
letterSpacing?: string,
wordSpacing?: string,
): number {
return getFastTextWidthWithSizeString(
textElement,
fontSize + 'pt',
fontWeight,
fontFamily,
letterSpacing,
wordSpacing,
);
}

Expand All @@ -272,16 +280,23 @@ export function getFastTextWidth(
* @param fontSize The font size to use.
* @param fontWeight The font weight to use.
* @param fontFamily The font family to use.
* @param letterSpacing The letter spacing to use.
* @param wordSpacing The word spacing to use.
* @returns Width of element.
*/
export function getFastTextWidthWithSizeString(
textElement: SVGTextElement,
fontSize: string,
fontWeight: string,
fontFamily: string,
letterSpacing?: string,
wordSpacing?: string,
): number {
const text = textElement.textContent;
const key = text + '\n' + textElement.className.baseVal;
const key =
text +
'\n' +
`${fontSize}-${fontWeight}-${fontFamily}-${letterSpacing}-${wordSpacing}`;
let width;

// Return the cached width if it exists.
Expand All @@ -308,6 +323,11 @@ export function getFastTextWidthWithSizeString(
if (text && canvasContext) {
// Set the desired font size and family.
canvasContext.font = fontWeight + ' ' + fontSize + ' ' + fontFamily;
// Canvas doesn't understand 'normal', so map to 0px in that case (or when not specified)
canvasContext.letterSpacing =
letterSpacing && letterSpacing !== 'normal' ? letterSpacing : '0px';
canvasContext.wordSpacing =
wordSpacing && wordSpacing !== 'normal' ? wordSpacing : '0px';
width = Math.ceil(canvasContext.measureText(text).width);
} else {
width = 0;
Expand Down
44 changes: 41 additions & 3 deletions packages/blockly/core/workspace_svg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import type {Block} from './block.js';
import type {BlockSvg} from './block_svg.js';
import type {BlocklyOptions} from './blockly_options.js';
import * as browserEvents from './browser_events.js';
import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js';
import {TextBubble} from './bubbles/text_bubble.js';
import {TextInputBubble} from './bubbles/textinput_bubble.js';
import {COMMENT_COLLAPSE_BAR_BUTTON_FOCUS_IDENTIFIER} from './comments/collapse_comment_bar_button.js';
import {COMMENT_EDITOR_FOCUS_IDENTIFIER} from './comments/comment_editor.js';
Expand All @@ -37,6 +39,7 @@ import {getFocusManager} from './focus_manager.js';
import {Gesture} from './gesture.js';
import {Grid} from './grid.js';
import * as hints from './hints.js';
import {IconType} from './icons/icon_types.js';
import {isAutoHideable} from './interfaces/i_autohideable.js';
import type {IBoundedElement} from './interfaces/i_bounded_element.js';
import type {IComponent} from './interfaces/i_component.js';
Expand All @@ -58,6 +61,7 @@ import {Msg} from './msg.js';
import {Options} from './options.js';
import * as Procedures from './procedures.js';
import * as registry from './registry.js';
import * as renderManagement from './render_management.js';
import * as blockRendering from './renderers/common/block_rendering.js';
import type {Renderer} from './renderers/common/renderer.js';
import type {ScrollbarPair} from './scrollbar_pair.js';
Expand Down Expand Up @@ -527,10 +531,35 @@ export class WorkspaceSvg
);
}

const stylishBlocks: BlockSvg[] = [];

this.getAllBlocks(false).forEach((block) => {
if (block.getStyleName()) {
stylishBlocks.push(block);
}
// Clear cached field sizes and rerender the block.
block.markDirty();
block.queueRender();

const warningIcon = block.getIcon(IconType.WARNING);
if (warningIcon?.bubbleIsVisible()) {
const bubble = warningIcon.getBubble();
if (bubble instanceof TextBubble) {
bubble.updateBubbleSize();
}
}

const mutatorIcon = block.getIcon(IconType.MUTATOR);
if (mutatorIcon?.bubbleIsVisible()) {
const bubble = mutatorIcon.getBubble();
if (bubble instanceof MiniWorkspaceBubble) {
bubble.updateBubbleSize();
}
}
});

// Update all blocks in workspace that have a style name.
this.updateBlockStyles(
this.getAllBlocks(false).filter((block) => !!block.getStyleName()),
);
this.updateBlockStyles(stylishBlocks);

// Update current toolbox selection.
this.refreshToolboxSelection();
Expand All @@ -543,6 +572,15 @@ export class WorkspaceSvg
this.setVisible(true);
}

// If this workspace is inside a flyout, reflow the flyout to accommodate
// changes in block dimensions based on theme text size.
if (this.isFlyout && !this.targetWorkspace?.getToolbox()) {
renderManagement.finishQueuedRenders().then(() => {
const flyout = this.targetWorkspace?.getFlyout();
flyout?.reflow();
});
}

const event = new (eventUtils.get(EventType.THEME_CHANGE))(
this.getTheme().name,
this.id,
Expand Down
Loading