11/10/02 05:34:08 (19 years ago)
Nicholas Riley

Pester 1.1a1.

English.lproj/InfoPlist.strings: Updated for 1.1a1.

English.lproj/MainMenu.nib: Placeholder for day names in popup menu, fixed up by code (this means you can still edit it from IB though). Added command-shift-T to both in/at cells (required, code removes one or the other as appropriate). Fixed up sizes of fields. Default to today (this will need fixing when we localized the word "today", but it's fine for now...).

English.lproj/Notifier.nib: Remove date formatter because we set a string directly now instead (could set formatter from code, but we don't).

NJRDateFormatter: many workarounds for Cocoa bugs: missing AM/PM, incorrect results with space before AM/PM, etc. Added class methods to do format manipulation and return localized formats which work for output (though not always for input; this class has an internal workaround for the AM/PM problem).

NJRFSObjectSelector: properly handle enabled attribute, store internally and report externally as appropriate. Previously, the button would become enabled if you dropped something on it even if it was supposed to be disabled.

NJRQTMediaPopUpButton: stop sound preview when button disabled.

NJRVoicePopUpButton: stop voice preview when button disabled.

PSAlarm: new method -dateString returns long date string. Maintain local copy of long date, short date and time formats, and locale, using NJRDateFormatter.

PSAlarmNotifierController: update to use -[PSAlarm dateString], -[PSAlarm timeString] for localization instead of using broken formatter.

PSAlarmSetController: update documentation for some more Cocoa bugs I need to file. Set time of day and date formatters with localized date formats from NJRDateFormatter (retain/release issue here?) Localize weekday popup for predefined dates. Localize static date display with NJRDateFormatter. Note a solution (thanks to Douglas Davidson) for figuring out which control is editing. Added command-shift-T key equivalent to toggle in/at. Properly work around bugs witih soundRepetitionCount flashing, except where it's impossible to do anything else.

Read Me.rtfd: Updated for 1.1a1.

VERSION: Updated for 1.1a1.

1 edited


  • trunk/Cocoa/Pester/Source/PSAlarmSetController.m

    r41 r43  
    3030¥ NSDate natural language stuff in NSCalendarDate (why?), misspelled category name
    3131¥ NSCalendarDate natural language stuff behaves differently from NSDateFormatter (AM/PM has no effect, shouldn't they share code?)
     32¥ descriptionWithCalendarFormat:, dateWithNaturalLanguageString: does not default to current locale, instead it defaults to US unless you tell it otherwise
    3233¥ NSDateFormatter doc class description gives two examples for natural language that are incorrect, no link to NSDate doc that describes exactly how natural language dates are parsed
    3334¥ NSTimeFormatString does not include %p when it should, meaning that AM/PM is stripped yet 12-hour time is still used
    3435¥ NSNextDayDesignations, NSNextNextDayDesignations are noted as 'a string' in NSUserDefaults docs, but maybe they are actually an array, or either an array or a string, given their names?
    3536¥ "Setting the Format for Dates" does not document how to get 1:15 AM, the answer is %1I - strftime has no exact equivalent; the closest is %l.  strftime does not permit numeric prefixes.  It also refers to "NSCalendar" when no such class exists.
    36 ¥ none of many mentions of NSAMPMDesignation indicates that they include the leading spaces (" AM", " PM").  In "Setting the Format for Dates", needs to mention that the leading spaces are not included in %p with strftime.  But if you use the NSCalendarDate stuff, it appears %p doesn't include the space.
     37¥ none of many mentions of NSAMPMDesignation indicates that they include the leading spaces (" AM", " PM").  In "Setting the Format for Dates", needs to mention that the leading spaces are not included in %p with strftime.  But if you use the NSCalendarDate stuff, it appears %p doesn't include the space (because it doesn't use the locale dictionary).
     38¥ If you feed NSCalendarDate dateWithNaturalLanguageString: an " AM"/" PM" locale, it doesn't accept that date format.
    3739¥ descriptions for %X and %x are reversed (time zone is in %X, not %x)
    3840¥ too hard to implement date-only or time-only formatters
    5254- (void)awakeFromNib;
    54     // XXX bugs prevent this code from working properly on Jaguar
    55     /* NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    56     [timeOfDay setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [defaults objectForKey: NSTimeFormatString] allowNaturalLanguage: YES]];
    57     [timeDate setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [defaults objectForKey: NSShortDateFormatString] allowNaturalLanguage: YES]]; */
    5856    alarm = [[PSAlarm alloc] init];
    5957    [[self window] center];
     58    // XXX excessive retention of formatters?  check later...
     59    [timeOfDay setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [NJRDateFormatter localizedTimeFormatIncludingSeconds: NO] allowNaturalLanguage: YES]];
     60    [timeDate setFormatter: [[NJRDateFormatter alloc] initWithDateFormat: [NJRDateFormatter localizedDateFormatIncludingWeekday: NO] allowNaturalLanguage: YES]];
     61    {
     62        NSArray *dayNames = [[NSUserDefaults standardUserDefaults] arrayForKey:
     63            NSWeekDayNameArray];
     64        NSArray *completions = [timeDateCompletions itemTitles];
     65        NSEnumerator *e = [completions objectEnumerator];
     66        NSString *title;
     67        int itemIndex = 0;
     68        NSRange matchingRange;
     69        while ( (title = [e nextObject]) != nil) {
     70            matchingRange = [title rangeOfString: @"ÇdayÈ"];
     71            if (matchingRange.location != NSNotFound) {
     72                NSMutableString *format = [title mutableCopy];
     73                NSEnumerator *we = [dayNames objectEnumerator];
     74                NSString *dayName;
     75                [format deleteCharactersInRange: matchingRange];
     76                [format insertString: @"%@" atIndex: matchingRange.location];
     77                [timeDateCompletions removeItemAtIndex: itemIndex];
     78                while ( (dayName = [we nextObject]) != nil) {
     79                    [timeDateCompletions insertItemWithTitle: [NSString stringWithFormat: format, dayName] atIndex: itemIndex];
     80                    itemIndex++;
     81                }
     82            } else itemIndex++;
     83        }
     84    }
    6085    [self inAtChanged: nil];
    6186    [self playSoundChanged: nil];
    116141    // NSLog(@"updateDateDisplay: %@", sender);
    117142    if ([alarm isValid]) {
    118         [self setStatus: [[alarm date] descriptionWithCalendarFormat: @"Alarm will be set for %X on %x" timeZone: nil locale: nil]];
     143        [self setStatus: [NSString stringWithFormat: @"Alarm will be set for %@ on %@", [alarm timeString], [alarm dateString]]];
    119144        [setButton setEnabled: YES];
    120145        if (updateTimer == nil || ![updateTimer isValid]) {
    137162// Be careful not to hook up any of the text fields' actions to update: because we handle them in controlTextDidChange: instead.  If we could get the active text field somehow via public API (guess we could use controlTextDidBegin/controlTextDidEndEditing) then we'd not need to overload the update sender for this purpose.  Or, I guess, we could use another method other than update.  It should not be this hard to implement what is essentially standard behavior.  Sigh.
     163// Note: finding out whether a given control is editing is easier.  See: <http://cocoa.mamasam.com/COCOADEV/2002/03/2/28501.php>.
    139165- (IBAction)update:(id)sender;
    146172- (IBAction)inAtChanged:(id)sender;
     174    NSButtonCell *new = [inAtMatrix selectedCell], *old;
    148175    isInterval = ([inAtMatrix selectedTag] == 0);
     176    old = [inAtMatrix cellWithTag: isInterval];
     177    NSAssert(new != old, @"in and at buttons should be distinct!");
     178    [old setKeyEquivalent: [new keyEquivalent]];
     179    [old setKeyEquivalentModifierMask: [new keyEquivalentModifierMask]];
     180    [new setKeyEquivalent: @""];
     181    [new setKeyEquivalentModifierMask: 0];
    149182    [timeInterval setEnabled: isInterval];
    150183    [timeIntervalUnits setEnabled: isInterval];
    173206- (IBAction)setSoundRepetitionCount:(id)sender;
    175     int newReps = [sender intValue], oldReps = [soundRepetitions intValue];
    176     if (newReps != oldReps)
     208    NSTextView *fieldEditor = (NSTextView *)[soundRepetitions currentEditor];
     209    BOOL isEditing = (fieldEditor != nil);
     210    int newReps = [sender intValue], oldReps;
     211    if (isEditing) {
     212        // XXX work around bug where if you ask soundRepetitions for its intValue too often while it's editing, the field begins to flash
     213        oldReps = [[[fieldEditor textStorage] string] intValue];
     214    } else oldReps = [soundRepetitions intValue];
     215    if (newReps != oldReps) {
    177216        [soundRepetitions setIntValue: newReps];
     217        // NSLog(@"updating: new value %d, old value %d%@", newReps, oldReps, isEditing ? @", is editing" : @"");
     218        // XXX work around 10.1 bug, otherwise field only displays every second value
     219        if (isEditing) [soundRepetitions selectText: self];
     220    }
    307350- (void)controlTextDidChange:(NSNotification *)notification;
    309     // NSLog(@"UPDATING FROM controlTextDidChange");
     352    // NSLog(@"UPDATING FROM controlTextDidChange: %@", [notification object]);
    310353    [self update: [notification object]];
Note: See TracChangeset for help on using the changeset viewer.