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!: add getContents to IFlyout #8064

Merged
merged 1 commit into from
May 8, 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
11 changes: 1 addition & 10 deletions core/flyout_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,16 +566,7 @@ export abstract class Flyout
* @param contents - The array of items for the flyout.
*/
setContents(contents: FlyoutItem[]): void {
const blocksAndButtons = contents.map((item) => {
if (item.type === 'block' && item.block) {
return item.block as BlockSvg;
}
if (item.type === 'button' && item.button) {
return item.button as FlyoutButton;
}
});

this.contents = blocksAndButtons as FlyoutItem[];
this.contents = contents;
}
/**
* Update the display property of the flyout based whether it thinks it should
Expand Down
11 changes: 11 additions & 0 deletions core/interfaces/i_flyout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {Coordinate} from '../utils/coordinate.js';
import type {FlyoutDefinition} from '../utils/toolbox.js';
import type {Svg} from '../utils/svg.js';
import type {IRegistrable} from './i_registrable.js';
import {FlyoutItem} from '../flyout_base.js';

/**
* Interface for a flyout.
Expand Down Expand Up @@ -117,6 +118,16 @@ export interface IFlyout extends IRegistrable {
*/
show(flyoutDef: FlyoutDefinition | string): void;

/**
* Returns the list of flyout items currently present in the flyout.
* The `show` method parses the flyout definition into a list of actual
* flyout items. This method should return those concrete items, which
* may be used for e.g. keyboard navigation.
*
* @returns List of flyout items.
*/
getContents(): FlyoutItem[];

/**
* Create a copy of this block on the workspace.
*
Expand Down
60 changes: 49 additions & 11 deletions core/keyboard_nav/ast_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/
// Former goog.module ID: Blockly.ASTNode

import type {Block} from '../block.js';
import {Block} from '../block.js';
import type {Connection} from '../connection.js';
import {ConnectionType} from '../connection_type.js';
import type {Field} from '../field.js';
Expand All @@ -23,7 +23,7 @@ import {Coordinate} from '../utils/coordinate.js';
import type {Workspace} from '../workspace.js';
import {FlyoutButton} from '../flyout_button.js';
import {WorkspaceSvg} from '../workspace_svg.js';
import {Flyout} from '../flyout_base.js';
import {FlyoutItem} from '../flyout_base.js';

/**
* Class for an AST node.
Expand Down Expand Up @@ -337,21 +337,59 @@ export class ASTNode {
return null;
}

const flyout = targetWorkspace.getFlyout() as Flyout;
const flyoutContents = flyout.getContents() as (Block | FlyoutButton)[];
const flyout = targetWorkspace.getFlyout();
if (!flyout) return null;

const nextItem = this.findNextLocationInFlyout(
flyout.getContents(),
location,
forward,
);
if (!nextItem) return null;

if (nextItem.type === 'button' && nextItem.button) {
return ASTNode.createButtonNode(nextItem.button);
} else if (nextItem.type === 'block' && nextItem.block) {
return ASTNode.createStackNode(nextItem.block);
}

return null;
}

/**
* Finds the next (or previous if navigating backward) item in the flyout that should be navigated to.
*
* @param flyoutContents Contents of the current flyout.
* @param currentLocation Current ASTNode location.
* @param forward True if we're navigating forward, else false.
* @returns The next (or previous) FlyoutItem, or null if there is none.
*/
private findNextLocationInFlyout(
flyoutContents: FlyoutItem[],
currentLocation: IASTNodeLocation,
forward: boolean,
): FlyoutItem | null {
const currentIndex = flyoutContents.findIndex((item: FlyoutItem) => {
if (currentLocation instanceof Block && item.block === currentLocation) {
return true;
}
if (
currentLocation instanceof FlyoutButton &&
item.button === currentLocation
) {
return true;
}
return false;
});

if (currentIndex < 0) return null;

const currentIndex = flyoutContents.indexOf(location);
const resultIndex = forward ? currentIndex + 1 : currentIndex - 1;
if (resultIndex === -1 || resultIndex === flyoutContents.length) {
return null;
}

const newLocation = flyoutContents[resultIndex];
if (newLocation instanceof FlyoutButton) {
return ASTNode.createButtonNode(newLocation);
} else {
return ASTNode.createStackNode(newLocation);
}
return flyoutContents[resultIndex];
}

/**
Expand Down
Loading