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

Dynamic actions sharing the same keybinding #4755

Closed
xavierog opened this issue Jul 15, 2024 · 6 comments · Fixed by #4850
Closed

Dynamic actions sharing the same keybinding #4755

xavierog opened this issue Jul 15, 2024 · 6 comments · Fixed by #4850

Comments

@xavierog
Copy link
Contributor

xavierog commented Jul 15, 2024

Dynamic bindings/actions do not allow changing the description of a "toggle" action (e.g. dark mode / light mode, expand / collapse, lock / unlock) without also changing its key.

MRE

./DarkLight.py successfully implements a toggle action using two actual actions with different keys (d: Light mode, e: Dark mode)
SAME_BINDINGS= ./DarkLight.py does the same but declares the two actual actions with the same key (d). Result: only the "quit" action is retained.

Code

#!/usr/bin/env python3
from os import environ
from textual.app import App, ComposeResult
from textual.binding import Binding
from textual.widgets import Header, Footer

class DarkLight(App):
	if 'SAME_BINDINGS' in environ:
		BINDINGS = [
			('d', 'light', 'Light mode'),
			('d', 'dark', 'Dark  mode'),
			('q', 'quit', 'Quit'),
		]
	else:
		BINDINGS = [
			('d', 'light', 'Light mode'),
			('e', 'dark', 'Dark  mode'),
			('q', 'quit', 'Quit'),
		]

	def action_light(self):
		self.dark = False
		self.refresh_bindings()

	def action_dark(self):
		self.dark = True
		self.refresh_bindings()

	def check_action(self, action, _parameters):
		if action == 'light':
			return self.dark
		if action == 'dark':
			return not self.dark
		return True
		
	def compose(self) -> ComposeResult:
		yield Header()
		yield Footer()

if __name__ == "__main__":
	app = DarkLight()
	app.run()

Textual Diagnostics

Versions

Name Value
Textual 0.72.0
Rich 13.7.1

Python

Name Value
Version 3.12.4
Implementation CPython
Compiler GCC 13.2.0
Executable /path/to/venv/bin/python3

Operating System

Name Value
System Linux
Release 6.9.9-amd64
Version #1 SMP PREEMPT_DYNAMIC Debian 6.9.9-1 (2024-07-13)

Terminal

Name Value
Terminal Application tmux (3.4)
TERM tmux-256color
COLORTERM truecolor
FORCE_COLOR Not set
NO_COLOR Not set

Rich Console options

Name Value
size width=104, height=31
legacy_windows False
min_width 1
max_width 104
is_terminal False
encoding utf-8
max_height 31
justify None
overflow None
no_wrap False
highlight None
markup None
height None
Copy link

Thank you for your issue. Give us a little time to review it.

PS. You might want to check the FAQ if you haven't done so already.

This is an automated reply, generated by FAQtory

@merriam
Copy link
Contributor

merriam commented Jul 16, 2024

I think this the description of your bug, but let me know if I missed it.

  1. Run the program
  2. Press 'd' for dark mode, then 'e' for the light mode.
  3. The screen is now dark mode, but the footer says 'e Dark' meaning the footer did not update
  4. Move the mouse to trigger the footer to update.

So, the issue is that request to update the footer somehow gets stuck in a queue waiting for any other event to pop it out?

@TomJGooding
Copy link
Contributor

@merriam Not quite, though if the footer isn't updating for you in the first example, you might try updating your version of Textual.

This boils down to a fairly common question about how to change the description of a binding. For example, where the d key toggles dark mode, update the description to display 'Light Mode' when in dark mode and 'Dark' when in light mode.

There's not currently a way of updating the binding description AFAIK. You can't bind a key to multiple actions so trying to use check_actions as a workaround isn't going to work.

@MeadBarrel
Copy link

The issue is that you cannot change an action's description depending on the current state. For instance you can have "toggle dark mode" but not "enable dark mode" and "disable dark mode" on the same key, switching between the two depending on whether dark mode is currently active.

@Textualize Textualize deleted a comment from merriam Aug 8, 2024
@Textualize Textualize deleted a comment from merriam Aug 8, 2024
@willmcgugan
Copy link
Collaborator

I can see why this happens. The code makes the erroneous assumption that there is one binding per key.

The fix is non-trivial, but required for such dynamic bindings!

Copy link

github-actions bot commented Aug 9, 2024

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants