source: trunk/Cocoa/Pester/Source/NJRIntervalField.m@ 329

Last change on this file since 329 was 103, checked in by Nicholas Riley, 22 years ago

Localization, bug fixes

File size: 7.2 KB
Line 
1//
2// NJRIntervalField.m
3// Pester
4//
5// Created by Nicholas Riley on Wed Dec 25 2002.
6// Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9#import "NJRIntervalField.h"
10
11// XXX much implementation borrowed from DockCam, then factored; should replace DockCam interval selector with a NJRIntervalField at some point
12
13@implementation NJRIntervalField
14
15- (NSTimeInterval)interval;
16{
17 NSText *editor = [self currentEditor];
18 id obj = nil;
19
20 if (editor != nil) {
21 NSString *stringValue = [editor string];
22 if (![[self formatter] getObjectValue: &obj forString: stringValue errorDescription: NULL])
23 return 0;
24 } else {
25 obj = self;
26 }
27
28 return [obj intValue] * [[intervalUnits selectedItem] tag];
29}
30
31- (BOOL)setInterval:(NSTimeInterval)interval;
32{
33 // we assume that the tags are in ascending order in the array
34 NSEnumerator *e = [[intervalUnits itemArray] reverseObjectEnumerator];
35 NSMenuItem *i;
36 int multiplierTag;
37
38 while ( (i = [e nextObject]) != nil) {
39 multiplierTag = [i tag];
40 if (multiplierTag <= 0) continue;
41 if (((int)interval % multiplierTag) == 0) {
42 NSFormatter *formatter = [self formatter];
43 int intervalValue = interval / multiplierTag;
44 if (formatter != nil) {
45 id ignored;
46 if (![formatter getObjectValue: &ignored forString: [formatter stringForObjectValue: [NSNumber numberWithInt: intervalValue]] errorDescription: NULL]) return NO;
47 }
48 [self setIntValue: intervalValue];
49 [intervalUnits selectItem: i];
50 return YES;
51 }
52 }
53 return NO;
54}
55
56- (BOOL)textView:(NSTextView *)textView shouldChangeTextInRange:(NSRange)range replacementString:(NSString *)string;
57{
58 unsigned length = [string length];
59 if (length != 0) {
60 unichar c;
61 int tag = -1;
62 c = [string characterAtIndex: length - 1];
63 switch (c) {
64 case 's': case 'S': tag = 1; break;
65 case 'm': case 'M': tag = 60; break;
66 case 'h': case 'H': tag = 60 * 60; break;
67 case 'u': case 'U': tag = -2; break;
68 default: break;
69 }
70 if (tag != -1) {
71 int itemIndex = [intervalUnits indexOfItemWithTag: tag];
72 if (itemIndex != -1) {
73 [intervalUnits selectItemAtIndex: itemIndex];
74 [[intervalUnits menu] performActionForItemAtIndex: itemIndex];
75 }
76 if (tag < 0) return NO; // don't send update
77 }
78 }
79 return [super textView: textView shouldChangeTextInRange: range replacementString: string];
80}
81
82- (void)handleDidFailToFormatString:(NSString *)string errorDescription:(NSString *)error label:(NSString *)label;
83{
84 NSString *alertMessage = nil;
85 NSString *alternateButtonString = nil;
86 NSDecimalNumber *proposedValue = nil;
87 NSDictionary *contextInfo;
88
89 NSString *alertInformation = [NSString localizedStringWithFormat:
90 NSLocalizedString(@"The %@ field must be set to a value between %@ and %@.",
91 @"Informative text for alert posed by text field when invalid value entered"),
92 label, [[self formatter] minimum], [[self formatter] maximum]];
93 NSString *defaultButtonString = NSLocalizedString(@"Edit", @"Name of Edit button");
94 NSString *otherButtonString = NSLocalizedString(@"Cancel", @"Name of Cancel button");
95
96 if ([error isEqualToString:
97 NSLocalizedStringFromTableInBundle(@"Fell short of minimum", @"Formatter",
98 [NSBundle bundleForClass:[NSFormatter class]],
99 @"Presented when user value smaller than minimum")]) {
100 proposedValue = [[self formatter] minimum];
101 alertMessage = [NSString stringWithFormat:
102 NSLocalizedString(@"%@ is too small for the %@ field.",
103 @"Message text for alert posed by numeric field when too-small value entered"),
104 string, label];
105 alternateButtonString = [NSString localizedStringWithFormat:
106 NSLocalizedString(@"Set to %@",
107 @"Name of alternate button for alert posed by numeric field when too-small value entered"),
108 proposedValue];
109 } else if ([error isEqualToString:
110 NSLocalizedStringFromTableInBundle(@"Maximum exceeded", @"Formatter",
111 [NSBundle bundleForClass:[NSFormatter class]],
112 @"Presented when user value larger than maximum")]) {
113 proposedValue = [[self formatter] maximum];
114 alertMessage = [NSString stringWithFormat:
115 NSLocalizedString(@"%@ is too large for the %@ field.",
116 @"Message text for alert posed by numeric field when too-large value entered"),
117 string, label];
118 alternateButtonString = [NSString localizedStringWithFormat:
119 NSLocalizedString(@"Set to %@",
120 @"Name of alternate button for alert posed by numeric field when too-large value entered"),
121 proposedValue];
122 } else if ([error isEqualToString:
123 NSLocalizedStringFromTableInBundle(@"Invalid number", @"Formatter",
124 [NSBundle bundleForClass:[NSFormatter class]],
125 @"Presented when user typed illegal characters: no valid object")]) {
126 alertMessage = [NSString stringWithFormat:
127 NSLocalizedString(@"%@ is not a valid entry for the %@ field.",
128 @"Message text for alert posed by text field when invalid value entered"),
129 string, label];
130 alternateButtonString = nil;
131 }
132
133 contextInfo = [NSDictionary dictionaryWithObject: proposedValue forKey: @"proposedValue"];
134 [contextInfo retain];
135 NSBeep();
136 NSBeginAlertSheet(alertMessage, defaultButtonString, alternateButtonString, otherButtonString, [self window],
137 self, @selector(validationFailedSheetDidEnd:returnCode:contextInfo:), NULL, contextInfo,
138 alertInformation);
139}
140
141- (void)_propagateValidationChange;
142{
143 NSText *fieldEditor = [self currentEditor];
144 NSDictionary *userInfo = nil;
145 if (fieldEditor != nil) userInfo = [NSDictionary dictionaryWithObject: fieldEditor forKey: @"NSFieldEditor"];
146 [[NSNotificationCenter defaultCenter] postNotificationName: NSControlTextDidChangeNotification object: self userInfo: userInfo];
147 [self selectText: self];
148}
149
150- (void)validationFailedSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
151 // modal delegate callback method for NSBeginAlertSheet() function; called in the above method
152 if (returnCode == NSAlertOtherReturn) { // cancel
153 [self abortEditing]; // abort edit session and reinstate original value
154 [self _propagateValidationChange];
155 } else if (returnCode == NSAlertAlternateReturn) { // set to min/max/default value
156 [self setObjectValue: [(NSDictionary *)contextInfo objectForKey: @"proposedValue"]];
157 [self validateEditing];
158 [self _propagateValidationChange];
159 }
160 [(NSDictionary *)contextInfo release];
161}
162
163@end
Note: See TracBrowser for help on using the repository browser.