-
Notifications
You must be signed in to change notification settings - Fork 727
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
feat: add month calendar #3667
base: main
Are you sure you want to change the base?
feat: add month calendar #3667
Conversation
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.
Early review with some comments and general out loud thinking. Good progress!
from textual.widgets import MonthCalendar | ||
|
||
|
||
class MonthCalendarApp(App): |
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.
Adding a CSS
variable containing the following CSS to this app yields better results. I reckon we should add the equivalent CSS to the widget itself to override the default DataTable behaviour (unless you can think of a reason not to).
MonthCalendar { height: auto; width: auto; }
MonthCalendar > DataTable { height: auto; width: auto; }
We don't do this in the DataTable
itself because it's intended to scroll, but this widget has a very constrained height compared to the DataTable
which can be arbitrarily large.
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.
Sorry I should have mentioned, I haven't started looking at the DEFAULT_CSS
yet as I wanted to focus on the core functionality first. Do you think the table/columns widths should just be static, or allow the developer to specify the column width (or perhaps even grow dynamically according to the widget width)?
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.
I haven't started looking at the DEFAULT_CSS yet as I wanted to focus on the core functionality first.
Seems sensible.
Do you think the table/columns widths should just be static, or allow the developer to specify the column width (or perhaps even grow dynamically according to the widget width)?
I think static for now.
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.
I've now added some basic DEFAULT_CSS
in cfcac14. I've flagged min-width
as TODO as this might depend on locale?
class MonthCalendar(Widget): | ||
year: Reactive[int | None] = Reactive[int | None](None) | ||
month: Reactive[int | None] = Reactive[int | None](None) | ||
first_weekday: Reactive[int] = Reactive(0) |
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.
I'm wondering about using Literal["monday", "tuesday", ...]
here to remove any second-guessing about how days are indexed. Will leave it as an open thought here if you or anyone else wants to chip in.
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.
Perhaps this could be an IntEnum
similar to the calendar module in 3.12?
self.first_weekday = first_weekday | ||
|
||
def compose(self) -> ComposeResult: | ||
yield DataTable() |
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.
Open thoughts: I wonder if we should display the month name above the DataTable. I wonder if it should be something that can be toggled.
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.
I'm assuming this would simply display "November 2023" for example, and then if developers wanted something different they would be expected to create a custom widget and set MonthCalendar.month_header
to False?
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.
I'm not sure - I guess the month name would be defined by locale too? @willmcgugan any thoughts?
I'm struggling with handling the reactives for this widget, due to a class of problem explained this issue: I'm afraid I'm blocked on this, unless there's a workaround that would include a cursor reactive. My current |
Hi @TomJGooding, could you try adding a boolean Let me know if I've misunderstood the issue! |
Thanks Darren for your help, it looks like this works: def watch_month(self) -> None:
if not self.is_mounted:
return
self._update_calendar_days() Would it be better to add this new |
No problem! I think separate PR would be great for that. |
My latest commit (334e771) will update the calendar cursor to the same highlighted day when the month changes. Here's a quick demo recording, notice this accounts for when the new month doesn't have 31 days: This requires the The problem with updating the cursor when the month changes is I'm not sure how to handle when the highlighted date is outside the month. For example in the demo recording, on the initial month the cursor could be highlighting the first Monday (31st). Where should the cursor highlight when the month changes? If changed to just the previous month, it probably should just highlight the same date, but what if the updated calendar is months or years different? Perhaps if you don't mind (I appreciate how busy you are), this would a good time for a pre-review review? Tagging @darrenburns and @davep but any feedback would be welcome! Thanks again for your help so far. (Also just to note, the failing test is a keyline snapshot mismatch and not related to this PR!) |
After some mashing of the arrow keys, there's definitely some issues with my current implementation of the calendar as it will start to freeze/lag and CPU usage climbs. Initially I thought just caching the |
Looks like great progress :) did you manage to resolve the performance issues you mentioned previously or would you like some help in that area? |
Unfortunately not. If you try mashing the arrow keys for a few seconds on the |
Hi @TomJGooding Just had a quick look. I can't reproduce any performance problems. Seems to remain responsive for me. Are you on Windows? |
Linux. You really do have to be quickly mashing the arrow keys! |
I suspect the problem is that the textual/src/textual/widgets/_month_calendar.py Lines 108 to 111 in ca82691
But the textual/src/textual/widgets/_month_calendar.py Lines 276 to 279 in ca82691
If you're really mashing the arrow keys, this will probably create a race condition which causes these performance issues? I'm afraid I will need some help to resolve this, but obviously appreciate how busy you are at the moment. |
Description
Add a
MonthCalendar
widget, intended to form part of aDatePicker
widget.Note
Currently very much a work in progress wanting feedback from Textual maintainers and users!
Related Issue
Checklist: