eee_alarm_clock/clock/ui/add_alarm.py

220 lines
8.2 KiB
Python

import curses
from datetime import datetime
from .utils import init_colors, draw_big_digit
def draw_add_alarm(stdscr, context):
"""Draw the add alarm screen"""
# Ensure context is a dictionary with default values
if context is None:
context = {}
# Provide default values with more explicit checks
context = {
'new_alarm_selected': context.get('new_alarm_selected', 0),
'new_alarm_name': context.get('new_alarm_name', 'New Alarm'),
'new_alarm_hour': context.get('new_alarm_hour', datetime.now().hour),
'new_alarm_minute': context.get('new_alarm_minute', datetime.now().minute),
'new_alarm_enabled': context.get('new_alarm_enabled', True),
'new_alarm_date': context.get('new_alarm_date') or None,
'new_alarm_weekdays': context.get('new_alarm_weekdays', []) or [],
'weekday_names': context.get('weekday_names', ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']),
'date_edit_pos': context.get('date_edit_pos', 2) # 0 = year, 1 = month, 2 = day
}
init_colors()
height, width = stdscr.getmaxyx()
# Center the form vertically with good spacing
form_y = height // 2 - 8
# Title with green color and bold
title = "Add New Alarm"
stdscr.attron(curses.color_pair(1) | curses.A_BOLD)
stdscr.addstr(form_y, width // 2 - len(title) // 2, title)
stdscr.attroff(curses.color_pair(1) | curses.A_BOLD)
# Helper function to draw a labeled field
def draw_field(y, label, value, is_selected, center_offset=0):
label_str = f"{label}: "
total_width = len(label_str) + len(str(value))
x = width // 2 - total_width // 2 + center_offset
# Draw label in green
stdscr.attron(curses.color_pair(1))
stdscr.addstr(y, x, label_str)
stdscr.attroff(curses.color_pair(1))
# Draw value (highlighted if selected)
if is_selected:
stdscr.attron(curses.color_pair(2)) # Yellow for selected
stdscr.addstr(y, x + len(label_str), str(value))
stdscr.attroff(curses.color_pair(2))
else:
stdscr.attron(curses.color_pair(1)) # Green for normal
stdscr.addstr(y, x + len(label_str), str(value))
stdscr.attroff(curses.color_pair(1))
# Name field with proper spacing
name_str = str(context['new_alarm_name'])
draw_field(form_y + 2, "Name", name_str, context['new_alarm_selected'] == 4)
# Time selection with centered layout
time_y = form_y + 4
time_label = "Time: "
hour_str = f"{int(context['new_alarm_hour']):02d}"
minute_str = f"{int(context['new_alarm_minute']):02d}"
# Calculate center position for time
time_total_width = len(time_label) + 5 # 5 = HH:MM
time_x = width // 2 - time_total_width // 2
# Draw time label
stdscr.attron(curses.color_pair(1))
stdscr.addstr(time_y, time_x, time_label)
stdscr.attroff(curses.color_pair(1))
# Draw hour
if context['new_alarm_selected'] == 0:
stdscr.attron(curses.color_pair(2))
else:
stdscr.attron(curses.color_pair(1))
stdscr.addstr(time_y, time_x + len(time_label), hour_str)
if context['new_alarm_selected'] == 0:
stdscr.attroff(curses.color_pair(2))
else:
stdscr.attroff(curses.color_pair(1))
# Draw colon
stdscr.attron(curses.color_pair(1))
stdscr.addstr(time_y, time_x + len(time_label) + 2, ":")
stdscr.attroff(curses.color_pair(1))
# Draw minute
if context['new_alarm_selected'] == 1:
stdscr.attron(curses.color_pair(2))
else:
stdscr.attron(curses.color_pair(1))
stdscr.addstr(time_y, time_x + len(time_label) + 3, minute_str)
if context['new_alarm_selected'] == 1:
stdscr.attroff(curses.color_pair(2))
else:
stdscr.attroff(curses.color_pair(1))
# Draw weekdays
weekday_y = form_y + 6
weekdays_label = "Repeat: "
weekday_x = width // 2 - (len(weekdays_label) + len(context['weekday_names']) * 4) // 2
# Draw label
stdscr.attron(curses.color_pair(1))
stdscr.addstr(weekday_y, weekday_x, weekdays_label)
stdscr.attroff(curses.color_pair(1))
# Draw each weekday
for i, day in enumerate(context['weekday_names']):
x_pos = weekday_x + len(weekdays_label) + i * 4
is_selected = context['new_alarm_selected'] == 3 and i == context.get('weekday_edit_pos', 0)
is_active = i in context['new_alarm_weekdays']
if is_selected:
stdscr.attron(curses.color_pair(2))
elif is_active:
stdscr.attron(curses.color_pair(1) | curses.A_BOLD)
else:
stdscr.attron(curses.color_pair(1))
stdscr.addstr(weekday_y, x_pos, day)
if is_selected:
stdscr.attroff(curses.color_pair(2))
elif is_active:
stdscr.attroff(curses.color_pair(1) | curses.A_BOLD)
else:
stdscr.attroff(curses.color_pair(1))
# Date selection
date_y = form_y + 8
if context['new_alarm_weekdays']:
draw_field(date_y, "Date", "Repeating weekly", context['new_alarm_selected'] == 2)
else:
date_label = "Date: "
if context.get('new_alarm_date'):
date = context['new_alarm_date']
date_edit_pos = context.get('date_edit_pos', 0)
# Calculate center position
total_width = len(date_label) + len("YYYY-MM-DD")
date_x = width // 2 - total_width // 2
# Draw label
stdscr.attron(curses.color_pair(1))
stdscr.addstr(date_y, date_x, date_label)
stdscr.attroff(curses.color_pair(1))
# Draw date components
year_str = f"{date.year}"
month_str = f"{date.month:02d}"
day_str = f"{date.day:02d}"
current_x = date_x + len(date_label)
# Draw year
if context['new_alarm_selected'] == 2 and date_edit_pos == 0:
stdscr.attron(curses.color_pair(2))
else:
stdscr.attron(curses.color_pair(1))
stdscr.addstr(date_y, current_x, year_str)
if context['new_alarm_selected'] == 2 and date_edit_pos == 0:
stdscr.attroff(curses.color_pair(2))
else:
stdscr.attroff(curses.color_pair(1))
current_x += len(year_str)
# Draw first dash
stdscr.attron(curses.color_pair(1))
stdscr.addstr(date_y, current_x, "-")
stdscr.attroff(curses.color_pair(1))
current_x += 1
# Draw month
if context['new_alarm_selected'] == 2 and date_edit_pos == 1:
stdscr.attron(curses.color_pair(2))
else:
stdscr.attron(curses.color_pair(1))
stdscr.addstr(date_y, current_x, month_str)
if context['new_alarm_selected'] == 2 and date_edit_pos == 1:
stdscr.attroff(curses.color_pair(2))
else:
stdscr.attroff(curses.color_pair(1))
current_x += len(month_str)
# Draw second dash
stdscr.attron(curses.color_pair(1))
stdscr.addstr(date_y, current_x, "-")
stdscr.attroff(curses.color_pair(1))
current_x += 1
# Draw day
if context['new_alarm_selected'] == 2 and date_edit_pos == 2:
stdscr.attron(curses.color_pair(2))
else:
stdscr.attron(curses.color_pair(1))
stdscr.addstr(date_y, current_x, day_str)
if context['new_alarm_selected'] == 2 and date_edit_pos == 2:
stdscr.attroff(curses.color_pair(2))
else:
stdscr.attroff(curses.color_pair(1))
else:
draw_field(date_y, "Date", "No specific date", context['new_alarm_selected'] == 2)
# Enabled/Disabled toggle with visual indicator
status_y = form_y + 10
enabled_str = "● Enabled" if context['new_alarm_enabled'] else "○ Disabled"
draw_field(status_y, "Status", enabled_str, context['new_alarm_selected'] == 5, -2)
# Instructions in green at the bottom
instructions = "j/k: Change h/l: Switch Space: Toggle Enter: Save Esc: Cancel"
stdscr.attron(curses.color_pair(1))
stdscr.addstr(height - 2, width // 2 - len(instructions) // 2, instructions)
stdscr.attroff(curses.color_pair(1))