eee_alarm_clock/clock/ui/input_handlers.py

203 lines
8.7 KiB
Python

import curses
from datetime import datetime, date, timedelta
class InputHandling:
def _handle_active_alarms_input(self, key):
"""Handle input for active alarms view"""
if not self.active_alarms:
# No active alarms, return to clock view
self.current_view = 'CLOCK'
return
# Get the first (or only) active alarm
alarm_id = list(self.active_alarms.keys())[0]
if key == ord('s'): # Snooze
# Send snooze command to control queue
self.control_queue.put({
'type': 'snooze',
'alarm_id': alarm_id
})
# Remove from active alarms
del self.active_alarms[alarm_id]
# Optional: show a snooze confirmation
self._show_error("Alarm Snoozed")
elif key == ord('d'): # Dismiss
# Send dismiss command to control queue
self.control_queue.put({
'type': 'dismiss',
'alarm_id': alarm_id
})
# Remove from active alarms
del self.active_alarms[alarm_id]
# Return to clock view
self.current_view = 'CLOCK'
def _handle_clock_input(self, key):
"""Handle input on the clock view"""
if key == ord('a'):
self.current_view = 'ADD_ALARM'
elif key == ord('s'):
self.current_view = 'LIST_ALARMS'
self.alarm_list = self.storage.get_saved_alerts()
def _handle_add_alarm_input(self, key):
"""Handle input for alarm creation"""
if not hasattr(self, 'alarm_draft'):
self.alarm_draft = {
'hour': datetime.now().hour,
'minute': datetime.now().minute,
'name': 'New Alarm',
'enabled': True,
'date': None,
'weekdays': [],
'current_weekday': 0, # Add this to track currently selected weekday
'editing_name': False,
'temp_name': ''
}
alarm = self.alarm_draft
# Escape key handling
if key == 27: # ESC
if alarm['editing_name']:
# Cancel name editing
alarm['name'] = alarm['temp_name']
alarm['editing_name'] = False
else:
# Return to clock view
self.current_view = 'CLOCK'
return
# Enter key handling
if key == 10: # ENTER
if alarm['editing_name']:
# Finish name editing
alarm['editing_name'] = False
self.selected_item = 0
else:
# Save alarm
try:
alarm_data = {
"name": alarm['name'],
"time": f"{alarm['hour']:02d}:{alarm['minute']:02d}:00",
"enabled": alarm['enabled'],
"repeat_rule": {
"type": "weekly" if alarm['weekdays'] else "once",
"days_of_week": [self.weekday_names[day].lower() for day in alarm['weekdays']],
"at": alarm['date'].strftime("%Y-%m-%d") if alarm['date'] and not alarm['weekdays'] else None
}
}
self.storage.save_new_alert(alarm_data)
self.current_view = 'CLOCK'
except Exception as e:
self._show_error(str(e))
return
# Move selection using Left (h) and Right (l)
if not alarm['editing_name']:
if key in [ord('h'), curses.KEY_LEFT]:
self.selected_item = (self.selected_item - 1) % 6
elif key in [ord('l'), curses.KEY_RIGHT]:
self.selected_item = (self.selected_item + 1) % 6
# Handle numeric values (Hour, Minute, Date)
if key in [ord('k'), curses.KEY_UP, ord('j'), curses.KEY_DOWN]:
is_up = key in [ord('k'), curses.KEY_UP]
delta = 1 if is_up else -1
if self.selected_item == 0: # Hour
alarm['hour'] = (alarm['hour'] + delta) % 24
elif self.selected_item == 1: # Minute
alarm['minute'] = (alarm['minute'] + delta) % 60
elif self.selected_item == 2: # Date
if not alarm['date']:
alarm['date'] = datetime.now().date()
else:
try:
if not hasattr(self, 'date_edit_pos'):
self.date_edit_pos = 2 # Default to editing the day
current_date = alarm['date']
if self.date_edit_pos == 0: # Year
alarm['date'] = current_date.replace(year=max(current_date.year + delta, datetime.now().year))
elif self.date_edit_pos == 1: # Month
new_month = max(1, min(12, current_date.month + delta))
max_day = (datetime(current_date.year, new_month, 1) + timedelta(days=31)).replace(day=1) - timedelta(days=1)
alarm['date'] = current_date.replace(month=new_month, day=min(current_date.day, max_day.day))
elif self.date_edit_pos == 2: # Day
max_day = (datetime(current_date.year, current_date.month, 1) + timedelta(days=31)).replace(day=1) - timedelta(days=1)
alarm['date'] = current_date.replace(day=max(1, min(max_day.day, current_date.day + delta)))
except ValueError as e:
self._show_error(str(e))
# Weekday Selection
elif self.selected_item == 3: # When weekdays are selected
if key in [ord('h'), curses.KEY_LEFT]:
# Move selection left
alarm['current_weekday'] = (alarm['current_weekday'] - 1) % 7
elif key in [ord('l'), curses.KEY_RIGHT]:
# Move selection right
alarm['current_weekday'] = (alarm['current_weekday'] + 1) % 7
elif key == 32: # SPACE to toggle selection
current_day = alarm['current_weekday']
if current_day in alarm['weekdays']:
alarm['weekdays'].remove(current_day)
else:
alarm['weekdays'].append(current_day)
alarm['weekdays'].sort()
# Clear date if weekdays are selected
if alarm['weekdays']:
alarm['date'] = None
# Name Editing
elif self.selected_item == 4:
if key == 32: # SPACE to start editing
if not alarm['editing_name']:
alarm['editing_name'] = True
alarm['temp_name'] = alarm['name']
alarm['name'] = ''
elif alarm['editing_name']:
if key == curses.KEY_BACKSPACE or key == 127:
alarm['name'] = alarm['name'][:-1]
elif 32 <= key <= 126: # Printable ASCII
alarm['name'] += chr(key)
# Enabled/Disabled Toggle
elif self.selected_item == 5 and key == 32:
alarm['enabled'] = not alarm['enabled']
def _handle_list_alarms_input(self, key):
"""Handle input for alarm list view"""
total_items = len(self.alarm_list) + 1 # +1 for "Add new alarm" option
if key == 27: # ESC
self.current_view = 'CLOCK'
elif key in [ord('j'), curses.KEY_DOWN]:
self.selected_item = (self.selected_item + 1) % total_items
elif key in [ord('k'), curses.KEY_UP]:
self.selected_item = (self.selected_item - 1) % total_items
elif key == ord('d'):
# Only delete if a real alarm is selected (not the "Add new" option)
if self.selected_item < len(self.alarm_list) and self.alarm_list:
try:
alarm_to_delete = self.alarm_list[self.selected_item]
self.storage.remove_saved_alert(alarm_to_delete['id'])
self.alarm_list = self.storage.get_saved_alerts()
# Adjust selected item if needed
if self.selected_item >= len(self.alarm_list):
self.selected_item = len(self.alarm_list)
except Exception as e:
self._show_error(f"Failed to delete alarm: {e}")
elif key in [ord('a'), 10]: # 'a' or Enter
if self.selected_item == len(self.alarm_list):
# "Add new alarm" option selected
self.current_view = 'ADD_ALARM'
else:
# TODO: Implement alarm editing
self._show_error("Alarm editing not implemented yet")