Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix bug that caused fields in the flyout to use the main workspace's scale. #8607

Merged
merged 2 commits into from
Oct 2, 2024
Merged
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
2 changes: 1 addition & 1 deletion core/field_input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ export abstract class FieldInput<T extends InputTypes> extends Field<
'spellcheck',
this.spellcheck_ as AnyDuringMigration,
);
const scale = this.workspace_!.getScale();
const scale = this.workspace_!.getAbsoluteScale();
const fontSize = this.getConstants()!.FIELD_TEXT_FONTSIZE * scale + 'pt';
div!.style.fontSize = fontSize;
htmlInput.style.fontSize = fontSize;
Expand Down
62 changes: 57 additions & 5 deletions core/workspace_svg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import * as ContextMenu from './contextmenu.js';
import {ContextMenuRegistry} from './contextmenu_registry.js';
import * as dropDownDiv from './dropdowndiv.js';
import * as eventUtils from './events/utils.js';
import {Flyout} from './flyout_base.js';
import type {FlyoutButton} from './flyout_button.js';
import {Gesture} from './gesture.js';
import {Grid} from './grid.js';
Expand Down Expand Up @@ -2022,18 +2023,69 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg {
}

/**
* Get the workspace's zoom factor. If the workspace has a parent, we call
* into the parent to get the workspace scale.
* Get the workspace's zoom factor.
*
* @returns The workspace zoom factor. Units: (pixels / workspaceUnit).
*/
getScale(): number {
if (this.options.parentWorkspace) {
return this.options.parentWorkspace.getScale();
}
return this.scale;
}

/**
* Returns the absolute scale of the workspace.
*
* Workspace scaling is multiplicative; if a workspace B (e.g. a mutator editor)
* with scale Y is nested within a root workspace A with scale X, workspace B's
* effective scale is X * Y, because, as a child of A, it is already transformed
* by A's scaling factor, and then further transforms itself by its own scaling
* factor. Normally this Just Works, but for global elements (e.g. field
* editors) that are visually associated with a particular workspace but live at
* the top level of the DOM rather than being a child of their associated
* workspace, the absolute/effective scale may be needed to render
* appropriately.
*
* @returns The absolute/effective scale of the given workspace.
*/
getAbsoluteScale() {
// Returns a workspace's own scale, without regard to multiplicative scaling.
const getLocalScale = (workspace: WorkspaceSvg): number => {
// Workspaces in flyouts may have a distinct scale; use this if relevant.
if (workspace.isFlyout) {
const flyout = workspace.targetWorkspace?.getFlyout();
if (flyout instanceof Flyout) {
return flyout.getFlyoutScale();
}
}

return workspace.getScale();
};

const computeScale = (workspace: WorkspaceSvg, scale: number): number => {
// If the workspace has no parent, or it does have a parent but is not
// actually a child of its parent workspace in the DOM (this is the case for
// flyouts in the main workspace), we're done; just return the scale so far
// multiplied by the workspace's own scale.
if (
!workspace.options.parentWorkspace ||
!workspace.options.parentWorkspace
.getSvgGroup()
.contains(workspace.getSvgGroup())
) {
return scale * getLocalScale(workspace);
}

// If there is a parent workspace, and this workspace is a child of it in
// the DOM, scales are multiplicative, so recurse up the workspace
// hierarchy.
return computeScale(
workspace.options.parentWorkspace,
scale * getLocalScale(workspace),
);
};

return computeScale(this, 1);
}

/**
* Scroll the workspace to a specified offset (in pixels), keeping in the
* workspace bounds. See comment on workspaceSvg.scrollX for more detail on
Expand Down
2 changes: 1 addition & 1 deletion tests/mocha/field_textinput_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ suite('Text Input Fields', function () {
setup(function () {
this.prepField = function (field) {
const workspace = {
getScale: function () {
getAbsoluteScale: function () {
return 1;
},
getRenderer: function () {
Expand Down