-
-
Notifications
You must be signed in to change notification settings - Fork 557
fix(Happy Hare): Fixes display of gate-context menus with right-click action #1757
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 all commits
4b29e2b
94e2462
c22aaf4
a9a9571
334747e
ebc6b53
b56b052
89e393a
f051e1b
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 |
|---|---|---|
|
|
@@ -5,14 +5,19 @@ | |
| v-for="(g, index) in unitGateRange" | ||
| :key="`gate_${g}`" | ||
| class="gate" | ||
| @contextmenu.prevent="openContextMenu(g, $event)" | ||
| @click="selectGate(g)" | ||
| > | ||
| <div :class="clipSpoolClass"> | ||
| <v-menu | ||
| v-model="gateMenuVisible[g]" | ||
| :disabled="g === gate || !unitDetails(unitIndex).multiGear" | ||
| :disabled="g === gate" | ||
| :position-x="menuX" | ||
| :position-y="menuY" | ||
| :close-on-content-click="false" | ||
| :open-on-click="false" | ||
| transition="slide-y-transition" | ||
| absolute | ||
| offset-y | ||
| > | ||
| <template #activator="{ attrs: menuAttrs }"> | ||
|
|
@@ -49,51 +54,29 @@ | |
| </v-tooltip> | ||
| </template> | ||
|
|
||
| <v-list dense> | ||
| <v-list | ||
| dense | ||
| @mouseleave="closeContextMenu" | ||
| > | ||
| <v-subheader class="compact-subheader"> | ||
| Gate {{ g }} | ||
| </v-subheader> | ||
| <v-divider /> | ||
| <v-list-item> | ||
| <v-btn | ||
| small | ||
| style="width: 100%" | ||
| :disabled="!klippyReady || !canSend" | ||
| :loading="hasWait($waits.onMmuSelect)" | ||
| @click="sendGcode(`MMU_SELECT GATE=${g}`, $waits.onMmuSelect)" | ||
| > | ||
| <v-icon left> | ||
| $mmuSelectGate | ||
| </v-icon> | ||
| {{ $t('app.mmu.btn.select') }} | ||
| </v-btn> | ||
| </v-list-item> | ||
| <v-list-item> | ||
| <v-btn | ||
| small | ||
| style="width: 100%" | ||
| :disabled="!klippyReady || !canSend || ![GATE_UNKNOWN, GATE_EMPTY].includes(gateDetails(g).status)" | ||
| :loading="hasWait($waits.onMmuPreload)" | ||
| @click="sendGcode(`MMU_PRELOAD GATE=${g}`, $waits.onMmuPreload)" | ||
| > | ||
| <v-icon left> | ||
| $mmuPreload | ||
| </v-icon> | ||
| {{ $t('app.mmu.btn.preload') }} | ||
| </v-btn> | ||
| </v-list-item> | ||
| <v-list-item> | ||
| <v-list-item | ||
| v-for="(item, i) in contextMenuItems" | ||
| :key="i" | ||
| > | ||
| <v-btn | ||
| small | ||
| style="width: 100%" | ||
| :disabled="!klippyReady || !canSend" | ||
| :loading="hasWait($waits.onMmuEject)" | ||
| @click="sendGcode(`MMU_EJECT GATE=${g}`, $waits.onMmuEject)" | ||
| :loading="hasWait(item.loading)" | ||
| @click="contextMenuCommand(item.command, item.loading, g)" | ||
| > | ||
| <v-icon left> | ||
| $mmuEject | ||
| {{ item.icon }} | ||
| </v-icon> | ||
| {{ $t('app.mmu.btn.eject') }} | ||
| {{ item.label }} | ||
| </v-btn> | ||
| </v-list-item> | ||
| </v-list> | ||
|
|
@@ -155,6 +138,7 @@ | |
| <div | ||
| v-if="showBypass" | ||
| class="gate" | ||
| @contextmenu.prevent="openContextMenu(-2, $event)" | ||
| @click="selectBypass()" | ||
| > | ||
| <div :class="clipSpoolClass"> | ||
|
|
@@ -278,10 +262,15 @@ export default class MmuUnit extends Mixins(BrowserMixin, StateMixin, MmuMixin) | |
| @Prop({ required: false, default: -1 }) | ||
| readonly editGateSelected!: number | ||
|
|
||
| @Prop({ required: false, default: true }) | ||
| readonly showContextMenu!: boolean | ||
|
|
||
| gateMenuVisible: Record<number, boolean> = {} | ||
| gateMenuTimer: ReturnType<typeof setTimeout> | null = null | ||
|
|
||
| vendorLogo = '' | ||
| closeTimeout: number | null = null | ||
pedrolamas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| menuX = 0 | ||
| menuY = 0 | ||
|
|
||
| @Watch('unit', { immediate: true }) | ||
| onUnit (value: number) { | ||
|
|
@@ -428,22 +417,7 @@ export default class MmuUnit extends Mixins(BrowserMixin, StateMixin, MmuMixin) | |
| if (this.editGateMap) { | ||
| this.$emit('select-gate', gate) | ||
| } else if (!this.isPrinting) { | ||
| if ( | ||
| this.unitDetails(this.unitIndex).multiGear && | ||
| gate !== this.gate && | ||
| ![this.FILAMENT_POS_UNLOADED, this.FILAMENT_POS_UNKNOWN].includes(this.filamentPos) | ||
| ) { | ||
| if (this.gateMenuTimer) clearTimeout(this.gateMenuTimer) | ||
| this.gateMenuTimer = setTimeout(() => { | ||
| Object.keys(this.gateMenuVisible).forEach(key => { | ||
| this.$set(this.gateMenuVisible, Number(key), false) | ||
| }) | ||
| }, 3000) | ||
| this.$set(this.gateMenuVisible, gate, true) | ||
| } else { | ||
| if (this.gateMenuTimer) clearTimeout(this.gateMenuTimer) | ||
| this.sendGcode('MMU_SELECT GATE=' + gate) | ||
| } | ||
| this.sendGcode('MMU_SELECT GATE=' + gate) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -454,6 +428,66 @@ export default class MmuUnit extends Mixins(BrowserMixin, StateMixin, MmuMixin) | |
| this.sendGcode('MMU_SELECT BYPASS=1') | ||
| } | ||
| } | ||
|
|
||
| // Gate context menu handling... | ||
|
|
||
| get contextMenuItems () { | ||
| return [ | ||
| { | ||
| icon: '$mmuSelectGate', | ||
| command: 'MMU_SELECT', | ||
| label: this.$t('app.mmu.btn.select').toString(), | ||
| loading: this.$waits.onMmuSelect | ||
| }, | ||
| { | ||
| icon: '$mmuPreload', | ||
| command: 'MMU_PRELOAD', | ||
| label: this.$t('app.mmu.btn.preload').toString(), | ||
| loading: this.$waits.onMmuPreload | ||
| }, | ||
| { | ||
| icon: '$mmuEject', | ||
| command: 'MMU_EJECT', | ||
| label: this.$t('app.mmu.btn.eject').toString(), | ||
| loading: this.$waits.onMmuEject | ||
| } | ||
| ] | ||
| } | ||
|
|
||
| contextMenuCommand (command: string, loading: string, gate: number) { | ||
| this.sendGcode(`${command} GATE=${gate}`, loading) | ||
| } | ||
|
Comment on lines
+457
to
+459
|
||
|
|
||
| openContextMenu (gate: number, e: MouseEvent) { | ||
| if (gate < 0 || gate === this.gate || !this.showContextMenu) { | ||
| this.closeContextMenu() | ||
| return | ||
| } | ||
| this.menuX = e.clientX - 20 | ||
| this.menuY = e.clientY - 20 | ||
|
Comment on lines
+466
to
+467
|
||
| this.closeContextMenu() | ||
| this.$set(this.gateMenuVisible, gate, true) | ||
| this.closeTimeout = window.setTimeout(() => { | ||
| this.closeContextMenu() | ||
| }, 6000) | ||
|
||
| } | ||
|
|
||
| closeContextMenu () { | ||
| this.clearCloseTimeout() | ||
| Object.keys(this.gateMenuVisible).forEach(key => { | ||
| this.$set(this.gateMenuVisible, Number(key), false) | ||
| }) | ||
| } | ||
|
|
||
| clearCloseTimeout () { | ||
| if (this.closeTimeout === null) return | ||
| clearTimeout(this.closeTimeout) | ||
| this.closeTimeout = null | ||
| } | ||
|
|
||
| beforeDestroy () { | ||
| this.clearCloseTimeout() | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mouseleave event on the v-list will close the menu when the user's cursor briefly leaves the menu bounds, which can be frustrating. This conflicts with the 6-second timeout mechanism. Consider removing the mouseleave handler or add a small delay before closing to prevent accidental closure when the user's cursor momentarily leaves the menu area.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assume intended behavior, so ignore.