1/* emacs buffer mode hint -*- objc -*- */
2
3#import <AppKit/AppKit.h>
4#import "TaskEditor.h"
5#import "StoreManager.h"
6#import "Task.h"
7#import "AlarmEditor.h"
8#import "HourFormatter.h"
9#import "Date.h"
10
11static NSMutableDictionary *editors;
12
13@implementation TaskEditor
14- (BOOL)canBeModified
15{
16  id <MemoryStore> selectedStore = [[StoreManager globalManager] storeForName:[store titleOfSelectedItem]];
17  return [selectedStore enabled] && [selectedStore writable];
18}
19
20- (id)init
21{
22  HourFormatter *formatter;
23  NSDateFormatter *dateFormatter;
24
25  if (![NSBundle loadNibNamed:@"Task" owner:self])
26    return nil;
27  if ((self = [super init])) {
28    formatter = AUTORELEASE([[HourFormatter alloc] init]);
29    dateFormatter = AUTORELEASE([[NSDateFormatter alloc] initWithDateFormat:[[NSUserDefaults standardUserDefaults] objectForKey:NSShortDateFormatString] allowNaturalLanguage:NO]);
30    [dueTime setFormatter:formatter];
31    [dueDate setFormatter:dateFormatter];
32  }
33  return self;
34}
35
36- (id)initWithTask:(Task *)task
37{
38  StoreManager *sm = [StoreManager globalManager];
39  NSEnumerator *list = [sm storeEnumerator];
40  id <MemoryStore> aStore;
41  id <MemoryStore> originalStore;
42
43  self = [self init];
44  if (self) {
45    ASSIGN(_task, task);
46    ASSIGNCOPY(_modifiedAlarms, [task alarms]);
47    [summary setStringValue:[task summary]];
48
49    [[description textStorage] deleteCharactersInRange:NSMakeRange(0, [[description textStorage] length])];
50    [[description textStorage] appendAttributedString:[task text]];
51
52    [window makeFirstResponder:summary];
53
54    originalStore = [task store];
55    [store removeAllItems];
56    while ((aStore = [list nextObject])) {
57      if ([aStore enabled] && ([aStore writable] || aStore == originalStore))
58	[store addItemWithTitle:[aStore description]];
59    }
60    if ([task store])
61      [store selectItemWithTitle:[[task store] description]];
62    else
63      [store selectItemWithTitle:[[sm defaultStore] description]];
64
65    [state removeAllItems];
66    [state addItemsWithTitles:[Task stateNamesArray]];
67    [state selectItemWithTitle:[task stateAsString]];
68    [ok setEnabled:[self canBeModified]];
69    if ([task dueDate]) {
70      [dueDate setObjectValue:[[task dueDate] calendarDate]];
71      [dueTime setIntValue:[[task dueDate] hourOfDay] * 3600 + [[task dueDate] minuteOfHour] * 60];
72      [toggleDueDate setState:YES];
73    }
74    [dueDate setEnabled:[toggleDueDate state]];
75    [dueTime setEnabled:[toggleDueDate state]];
76    [window makeKeyAndOrderFront:self];
77  }
78  return self;
79}
80
81- (void)dealloc
82{
83  RELEASE(_task);
84  RELEASE(_modifiedAlarms);
85  [super dealloc];
86}
87
88+ (void)initialize
89{
90  editors = [[NSMutableDictionary alloc] initWithCapacity:2];
91}
92
93+ (TaskEditor *)editorForTask:(Task *)task
94{
95  TaskEditor *editor;
96
97  if ((editor = [editors objectForKey:[task UID]])) {
98    [editor->window makeKeyAndOrderFront:self];
99    return editor;
100  }
101  editor = [[TaskEditor alloc] initWithTask:task];
102  [editors setObject:editor forKey:[task UID]];
103  return AUTORELEASE(editor);
104}
105
106- (void)validate:(id)sender
107{
108  StoreManager *sm = [StoreManager globalManager];
109  id <MemoryStore> originalStore = [_task store];
110  id <MemoryStore> aStore;
111  Date *date;
112
113  [_task setSummary:[summary stringValue]];
114  [_task setText:[[description textStorage] copy]];
115  [_task setState:[state indexOfSelectedItem]];
116  [_task setAlarms:_modifiedAlarms];
117  if ([toggleDueDate state]) {
118    date = [Date dateWithCalendarDate:[dueDate objectValue] withTime:NO];
119    date = [Date dateWithTimeInterval:[dueTime intValue] sinceDate:date];
120    [_task setDueDate:date];
121  } else {
122    [_task setDueDate:nil];
123  }
124  aStore = [sm storeForName:[store titleOfSelectedItem]];
125  if (!originalStore)
126    [aStore add:_task];
127  else if (originalStore == aStore)
128    [aStore update:_task];
129  else {
130    [originalStore remove:_task];
131    [aStore add:_task];
132  }
133  [window close];
134  [editors removeObjectForKey:[_task UID]];
135}
136
137- (void)cancel:(id)sender
138{
139  [window close];
140  [editors removeObjectForKey:[_task UID]];
141}
142
143- (void)editAlarms:(id)sender
144{
145  NSArray *alarmArray;
146
147  alarmArray = [AlarmEditor editAlarms:_modifiedAlarms];
148  if (alarmArray)
149    ASSIGN(_modifiedAlarms, alarmArray);
150  [window makeKeyAndOrderFront:self];
151}
152
153- (void)toggleDueDate:(id)sender
154{
155  Date *date;
156
157  [dueDate setEnabled:[toggleDueDate state]];
158  [dueTime setEnabled:[toggleDueDate state]];
159  if ([toggleDueDate state]) {
160    date = [Date now];
161    [date changeDayBy:7];
162    [dueDate setObjectValue:[date calendarDate]];
163    [dueTime setIntValue:[date hourOfDay] * 3600 + [date minuteOfHour] * 60];
164  } else {
165    [dueDate setObjectValue:nil];
166    [dueTime setObjectValue:nil];
167  }
168}
169
170- (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)aSelector
171{
172  if ([NSStringFromSelector(aSelector) isEqualToString:@"insertTab:"]) {
173    [[description window] selectNextKeyView:self];
174    return YES;
175  }
176  return [description tryToPerform:aSelector with:aTextView];
177}
178@end
179