-
Notifications
You must be signed in to change notification settings - Fork 3.9k
feat!: Make everything ISelectable focusable #9004
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
Changes from 6 commits
94d8c02
cadf7d6
3775759
1f5a6f0
f2bd02c
befa680
fa7117c
79cf32c
d62a6a3
386b762
f133908
b7c6aca
66aaba3
6227b4a
a574b3c
0a6e716
ac6f74b
d431d8e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,12 @@ | |
| // Former goog.module ID: Blockly.common | ||
|
|
||
| import type {Block} from './block.js'; | ||
| import {ISelectable} from './blockly.js'; | ||
| import { | ||
| BlockSvg, | ||
| ISelectable, | ||
| getFocusManager, | ||
| isSelectable, | ||
| } from './blockly.js'; | ||
|
BenHenning marked this conversation as resolved.
Outdated
|
||
| import {BlockDefinition, Blocks} from './blocks.js'; | ||
| import type {Connection} from './connection.js'; | ||
| import {EventType} from './events/type.js'; | ||
|
|
@@ -86,38 +91,58 @@ export function setMainWorkspace(workspace: Workspace) { | |
| } | ||
|
|
||
| /** | ||
| * Currently selected copyable object. | ||
| * Returns the current selection. | ||
| */ | ||
| let selected: ISelectable | null = null; | ||
| export function getSelected(): ISelectable | null { | ||
| const focused = getFocusManager().getFocusedNode(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am curious about how well this will work. One scenario is that in context menu items sometimes the callback would use getSelected, because the block is still selected when the menu is open. But the block won’t be focused when the menu is open. So we would need to call this out as a breaking change. I am curious if there are other situations where a block would have been selected but not (active) focused and I’m not sure I can think of any, maybe in some widget div scenarios
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the scenario you describe would be broken as of #8938 not this change, but it's equally relevant. It's definitely the case now that right clicking will not maintain block selection since the selection highlight is cleared on focus loss. It's something worth discussing, I think. Does something really have selection if it doesn't have input focus? My assumption is no which is why the change moved in this direction. If the answer should be yes, then we need to approach the auto-selection differently.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think logically it's fine, but it is a big behavior change that the block isn't selected anymore while you're interacting with non-Blockly parts of the UI (e.g. context menu or dev console) so we just need to be super clear about that in our communication.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the best way for me to indicate that bit (per being super clear)?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update the PR description of this PR (and/or any others you've made that are breaking) to include a So for the issue about the block not being selected anymore, provide workarounds like using the (now passively-) focused block instead of selected block, using the scope for context menu items and shortcuts instead of selected, etc. For this PR, you might need other details like what new methods need to be implemented if any for bubbles, etc. Then remind me to call this out in the handwritten release notes we'll attach to the github release/forum announcement as well. |
||
| if (focused && isSelectable(focused)) return focused; | ||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the currently selected copyable object. | ||
| * @internal | ||
| */ | ||
|
BenHenning marked this conversation as resolved.
Outdated
|
||
| export function getSelected(): ISelectable | null { | ||
| return selected; | ||
| export function getSelectedBlock(): BlockSvg | null { | ||
|
maribethb marked this conversation as resolved.
Outdated
|
||
| const selected = getSelected(); | ||
| if (!selected || !(selected instanceof BlockSvg)) return null; | ||
| let nonShadow: BlockSvg | null = selected; | ||
| while (nonShadow && nonShadow instanceof BlockSvg && nonShadow.isShadow()) { | ||
| nonShadow = nonShadow.getParent(); | ||
| } | ||
| return nonShadow; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the currently selected block. This function does not visually mark the | ||
| * block as selected or fire the required events. If you wish to | ||
| * programmatically select a block, use `BlockSvg#select`. | ||
| * Sets the current selection. | ||
| * | ||
| * To clear the current selection, select another ISelectable or focus a | ||
| * non-selectable (like the workspace root node). | ||
| * | ||
| * @param newSelection The newly selected block. | ||
| * @param newSelection The new selection to make. | ||
| * @internal | ||
| */ | ||
| export function setSelected(newSelection: ISelectable | null) { | ||
| if (selected === newSelection) return; | ||
| export function setSelected(newSelection: ISelectable) { | ||
| getFocusManager().focusNode(newSelection); | ||
| } | ||
|
|
||
| /** | ||
| * Fires a selection change event based on the new selection. | ||
| * | ||
| * This is only expected to be called by ISelectable implementations and should | ||
| * always be called before updating the current selection state. It does not | ||
| * change focus or selection state. | ||
| * | ||
| * @param newSelection The new selection. | ||
| * @internal | ||
| */ | ||
| export function fireSelectedEvent(newSelection: ISelectable | null) { | ||
| const selected = getSelected(); | ||
| const event = new (eventUtils.get(EventType.SELECTED))( | ||
| selected?.id ?? null, | ||
| newSelection?.id ?? null, | ||
| newSelection?.workspace.id ?? selected?.workspace.id ?? '', | ||
| ); | ||
| eventUtils.fire(event); | ||
|
|
||
| selected?.unselect(); | ||
| selected = newSelection; | ||
| selected?.select(); | ||
| } | ||
|
|
||
| /** | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.