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

Fixed detection of focus in LabelSlotsStructure #382

Merged
merged 1 commit into from
Jan 23, 2025
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
12 changes: 7 additions & 5 deletions src/components/LabelSlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,7 @@ export default Vue.extend({
},

focused(): boolean {
// We need to keep update of the label slots structure's "isFocused" flag, because using the keyboard to navigate will not
// update this flag -- but we always end up here when the focus (for slots) is updated.
const isSlotFocused = this.appStore.isEditableFocused(this.coreSlotInfo);
(this.$parent as InstanceType<typeof LabelSlotsStructure>).isFocused = isSlotFocused;
return isSlotFocused;
return this.appStore.isEditableFocused(this.coreSlotInfo);
},

UID(): string {
Expand Down Expand Up @@ -337,6 +333,9 @@ export default Vue.extend({
// Event callback equivalent to what would happen for a focus event callback
// (the spans don't get focus anymore because the containg editable div grab it)
onGetCaret(event: MouseEvent): void {
let parent = this.$parent as InstanceType<typeof LabelSlotsStructure>;
Vue.nextTick(() => parent.updatePrependText());

// If the user's code is being executed, or if the frame is disabled, we don't focus any slot, but we make sure we show the adequate frame cursor instead.
if(this.isPythonExecuting || this.isDisabled){
event.stopImmediatePropagation();
Expand Down Expand Up @@ -508,6 +507,9 @@ export default Vue.extend({
// Event callback equivalent to what would happen for a blur event callback
// (the spans don't get focus anymore because the containg editable div grab it)
onLoseCaret(keepIgnoreKeyEventFlagOn?: boolean): void {
let parent = this.$parent as InstanceType<typeof LabelSlotsStructure>;
Vue.nextTick(() => parent.updatePrependText());

// Before anything, we make sure that the current frame still exists.
if(this.appStore.frameObjects[this.frameId] != undefined){
if(!this.debugAC) {
Expand Down
19 changes: 14 additions & 5 deletions src/components/LabelSlotsStructure.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export default Vue.extend({
data: function() {
return {
ignoreBracketEmphasisCheck: false, // cf. isSlotEmphasised()
isFocused: false,
prependText: "", // This is updated properly in updatePrependText()
};
},
Expand Down Expand Up @@ -101,7 +100,7 @@ export default Vue.extend({
if (this.subSlots.length == 1) {
// If we are on an optional label slots structure that doesn't contain anything yet, we only show the placeholder if we're focused
const isOptionalEmpty = (this.appStore.frameObjects[this.frameId].frameType.labels[this.labelIndex].optionalSlot??false) && this.subSlots.length == 1 && this.subSlots[0].code.length == 0;
if(isOptionalEmpty && !this.isFocused){
if(isOptionalEmpty && !this.isFocused()){
return [" "];
}
return [(isFuncCallFrame) ? getFunctionCallDefaultText(this.frameId) : this.defaultText];
Expand Down Expand Up @@ -394,7 +393,6 @@ export default Vue.extend({
},

onFocus(){
this.isFocused = true;
this.updatePrependText();
// When the application gains focus again, the browser might try to give the first span of a div the focus (because the div may have been focused)
// even if we have the blue caret showing. We do not let this happen.
Expand All @@ -405,7 +403,6 @@ export default Vue.extend({
},

blurEditableSlot(){
this.isFocused = false;
this.updatePrependText();
// If a flag to ignore editable slot focus is set, we just revert it and do nothing else
if(this.appStore.bypassEditableSlotBlurErrorCheck){
Expand Down Expand Up @@ -456,6 +453,18 @@ export default Vue.extend({
}, 200);
},

isFocused() {
// We check if we are the parent of the currently focused element, as it may be a contenteditable item within us:
var selectedElement = window.getSelection()?.focusNode;
while (selectedElement != null) {
if (selectedElement instanceof Element && selectedElement.id === this.labelSlotsStructDivId) {
return true;
}
selectedElement = selectedElement.parentNode;
}
return false;
},

updatePrependText() {
if (this.prependSelfWhenInClass) {
const isInClass = useStore().frameObjects[getParentId(useStore().frameObjects[this.frameId])]?.frameType.type == DefIdentifiers.classdef;
Expand All @@ -464,7 +473,7 @@ export default Vue.extend({
}
else {
const empty = this.subSlots.length == 0 || !this.subSlots.some((s) => s.code !== "");
this.prependText = (this.isFocused || !empty) ? "self," : "self";
this.prependText = (this.isFocused() || !empty) ? "self," : "self";
}
}
else {
Expand Down
Loading