source: trunk/ICeCoffEE/ICeCoffEE/ICeCoffEEServicePrefController.m@ 431

Last change on this file since 431 was 431, checked in by Nicholas Riley, 16 years ago

Handle NSUserKeyEquivalents; disable conflict resolution; fix keyEquivalents invalidation crasher

File size: 19.9 KB
RevLine 
[142]1//
2// ICeCoffEEServicePrefController.m
3// ICeCoffEE APE
4//
5// Created by Nicholas Riley on Fri Jun 06 2003.
6// Copyright (c) 2003 Nicholas Riley. All rights reserved.
7//
8
9#import "ICeCoffEEShared.h"
[320]10#import "ICeCoffEEServices.h"
[142]11#import "ICeCoffEEServicePrefController.h"
12#import "ICeCoffEENonHighlightingButtonCell.h"
[425]13#import "ICeCoffEEInvertingTextFieldCell.h"
[319]14#import "ICeCoffEELabeledIconCell.h"
[142]15#import <objc/objc.h>
16#import <ApplicationEnhancer/ApplicationEnhancer.h>
[428]17#import <QuartzCore/QuartzCore.h>
[142]18
[425]19const int ICCF_SERVICE_UNKNOWN = 0;
20const int ICCF_SERVICE_SHOWN = 1;
21const int ICCF_SERVICE_HIDDEN = 2;
22const int ICCF_SERVICE_MIXED = 3;
23
[142]24static NSDictionary *ICCF_SERVICE_OPTION_HIDDEN;
25
26static float ICCF_TableViewCellHeight(NSTableView *tableView) {
27 return ([tableView rowHeight] + [tableView intercellSpacing].height);
28}
29
[319]30static NSMutableDictionary *keyEquivalents;
[431]31static NSDictionary *userKeyEquivalents;
[319]32
33static void ICCF_RemoveSingleKeyEquivalents() {
34 NSMutableArray *singleKeys = [[NSMutableArray alloc] init];
35 NSEnumerator *e = [[keyEquivalents allKeys] objectEnumerator];
36 NSString *keyEquivalent;
37 ICLog(@"before ICCF_RemoveSingleKeyEquivalents: %@", keyEquivalents);
38 while ( (keyEquivalent = [e nextObject]) != nil) {
39 if ([[keyEquivalents objectForKey: keyEquivalent] count] == 1)
40 [singleKeys addObject: keyEquivalent];
41 }
42 [keyEquivalents removeObjectsForKeys: singleKeys];
43 [singleKeys release];
44 ICLog(@"after ICCF_RemoveSingleKeyEquivalents: %@", keyEquivalents);
45}
46
47static inline unsigned ICCF_CountForKeyEquivalent(NSString *keyEquivalent) {
48 if (keyEquivalent == nil) return 0;
49 NSMutableSet *setOrNil = (NSMutableSet *)[keyEquivalents objectForKey: keyEquivalent];
[428]50 return (setOrNil == nil) ? 0 : [setOrNil count];
[319]51}
52
53static inline void ICCF_AddKeyEquivalentForItem(NSMenuItem *item) {
54 NSString *keyEquivalent = [item toolTip];
55 if (keyEquivalent == nil) return;
56 NSMutableSet *setOrNil = (NSMutableSet *)[keyEquivalents objectForKey: keyEquivalent];
57 if (setOrNil == nil) return;
58 [setOrNil addObject: item];
59}
60
61static inline void ICCF_RemoveKeyEquivalentForItem(NSMenuItem *item) {
62 NSString *keyEquivalent = [item toolTip];
63 if (keyEquivalent == nil) return;
64 NSMutableSet *setOrNil = (NSMutableSet *)[keyEquivalents objectForKey: keyEquivalent];
65 if (setOrNil == nil) return;
66 [setOrNil removeObject: item];
67}
68
[425]69static int ICCF_GetServiceState(NSMenuItem *item) {
70 return [item tag];
71}
72
73static void ICCF_SetServiceState(NSMenuItem *item, int state) {
74 [item setTag: state];
75}
76
77static inline void ICCF_UpdateKeyEquivalentForItem(NSMenuItem *item, int state) {
[431]78 return; // XXX disabled until we can affect menubar Services menu(s)
[425]79 int oldState = ICCF_GetServiceState(item);
80 if ((oldState == ICCF_SERVICE_UNKNOWN || oldState == ICCF_SERVICE_SHOWN) && state == ICCF_SERVICE_HIDDEN)
[319]81 ICCF_RemoveKeyEquivalentForItem(item);
[425]82 else if (oldState == ICCF_SERVICE_HIDDEN && (state == ICCF_SERVICE_SHOWN || state == ICCF_SERVICE_UNKNOWN))
[319]83 ICCF_AddKeyEquivalentForItem(item);
84}
85
[425]86
[319]87static inline NSCellStateValue ICCF_ServiceItemState(NSMenuItem *item) {
[425]88 int state = ICCF_GetServiceState(item);
89 if (state == ICCF_SERVICE_HIDDEN)
90 return NSOffState;
91 if (state == ICCF_SERVICE_MIXED)
92 return NSMixedState;
93 return NSOnState;
[142]94}
95
[425]96static void ICCF_PropagateServiceStateChange(NSMenu *menu, int state) {
[142]97 NSEnumerator *e = [[menu itemArray] objectEnumerator];
98 NSMenuItem *item;
99 NSMenu *submenu;
100
101 while ( (item = [e nextObject]) != nil) {
102 submenu = [item submenu];
[319]103 if (submenu != nil)
104 ICCF_PropagateServiceStateChange(submenu, state);
105 else
106 ICCF_UpdateKeyEquivalentForItem(item, state);
107
[425]108 ICCF_SetServiceState(item, state);
[142]109 }
110}
111
[319]112static NSCellStateValue ICCF_PropagateServiceState(NSMenuItem *item, NSMenuItem *changedItem) {
[142]113 NSMenu *submenu = [item submenu];
114 if (submenu == nil) return ICCF_ServiceItemState(item);
115
[425]116 if (item == changedItem) ICCF_PropagateServiceStateChange(submenu, [item tag]);
[142]117
118 BOOL areOn = NO, areOff = NO;
119 NSEnumerator *e = [[submenu itemArray] objectEnumerator];
120 NSMenuItem *subItem;
121 while ( (subItem = [e nextObject]) != nil) {
122 switch (ICCF_PropagateServiceState(subItem, changedItem)) {
123 case NSOnState: if (!areOff) { areOn = YES; continue; }
124 break;
125 case NSOffState: if (!areOn) { areOff = YES; continue; }
126 break;
127 case NSMixedState:
128 break;
129 }
[425]130 ICCF_SetServiceState(item, ICCF_SERVICE_MIXED);
[142]131 return NSMixedState;
132 }
133 if (areOn) {
[425]134 ICCF_SetServiceState(item, ICCF_SERVICE_SHOWN);
[142]135 return NSOnState;
136 } else {
[425]137 ICCF_SetServiceState(item, ICCF_SERVICE_HIDDEN);
[142]138 return NSOffState;
139 }
140}
141
142static NSMutableDictionary *ICCF_RetainedServiceOptionsDictionary(NSMenu *menu) {
143 NSEnumerator *e = [[menu itemArray] objectEnumerator];
144 NSMenuItem *item;
145 NSMenu *submenu;
146 NSMutableDictionary *dict = nil, *subDict = nil, *submenuDict = nil;
147
148 while ( (item = [e nextObject]) != nil) {
149 submenu = [item submenu];
150 if (ICCF_ServiceItemState(item) == NSOffState) {
151 subDict = [ICCF_SERVICE_OPTION_HIDDEN retain];
152 } else if (submenu != nil) {
153 submenuDict = ICCF_RetainedServiceOptionsDictionary(submenu);
154 if (submenuDict == nil)
155 continue;
156 subDict = [[NSDictionary alloc] initWithObjectsAndKeys: submenuDict, kICServiceSubmenu, nil];
157 [submenuDict release];
158 } else continue;
159 if (dict == nil) {
160 dict = [[NSMutableDictionary alloc] init];
161 }
162 [dict setObject: subDict forKey: [item title]];
163 [subDict release];
164 }
165 return dict;
166}
167
168static void ICCF_RestoreServiceOptionsDictionary(NSMenu *menu, NSDictionary *dict) {
169 NSEnumerator *e = [dict keyEnumerator];
170 NSString *itemTitle;
171 NSDictionary *subDict, *submenuDict;
[319]172 NSMenuItem *item;
[142]173 NSMenu *submenu;
174
175 // XXX handle exceptions
176 while ( (itemTitle = [e nextObject]) != nil) {
[319]177 item = (NSMenuItem *)[menu itemWithTitle: itemTitle];
[142]178 if (item == nil) continue;
179 subDict = [dict objectForKey: itemTitle];
180 if ([[subDict objectForKey: (NSString *)kICServiceHidden] boolValue]) {
[425]181 ICCF_SetServiceState(item, ICCF_SERVICE_HIDDEN);
[319]182 ICCF_RemoveKeyEquivalentForItem(item);
[142]183 }
184 if ( (submenu = [item submenu]) != nil) {
185 submenuDict = [subDict objectForKey: (NSString *)kICServiceSubmenu];
186 if ([submenuDict count] == 0)
187 ICCF_PropagateServiceStateChange(submenu, ICCF_SERVICE_HIDDEN);
188 else
189 ICCF_RestoreServiceOptionsDictionary(submenu, submenuDict);
190 }
191 }
192}
193
[319]194static void ICCF_AddServiceKeyEquivalentsAndIcons(NSMenu *menu, NSDictionary *serviceInfo) {
195 if (serviceInfo == nil) return;
196 NSEnumerator *enumerator = [[menu itemArray] objectEnumerator];
197 NSMenuItem *menuItem;
198 NSMenu *submenu;
199 NSDictionary *itemInfo = nil;
200 while ( (menuItem = [enumerator nextObject]) != nil) {
201 itemInfo = [serviceInfo objectForKey: [menuItem title]];
202 if (itemInfo == nil) continue;
203
204 if ( (submenu = [menuItem submenu]) != nil) {
[320]205 ICCF_AddServiceKeyEquivalentsAndIcons(submenu, [itemInfo objectForKey: (NSString *)kICServiceSubmenu]);
[319]206 } else {
207 NSString *keyEquivalent = (NSString *)[itemInfo objectForKey: (NSString *)kICServiceShortcut];
[431]208 if (keyEquivalent == nil) {
209 keyEquivalent = [userKeyEquivalents objectForKey: [menuItem title]];
210 } else if ([keyEquivalent length] != 1) {
211 keyEquivalent = nil;
212 } else {
213 // XXX Inconsistency between Cocoa and Carbon: always command-shift in Carbon, not in Cocoa. Since we only patch Cocoa for the moment, keep as is.
214 unichar key = [keyEquivalent characterAtIndex: 0];
215 if ([[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember: key])
216 keyEquivalent = [NSString stringWithFormat: @"$@%c", key];
217 else
218 keyEquivalent = [NSString stringWithFormat: @"@%c", key];
219 }
[319]220 if (keyEquivalent != nil) {
221 [menuItem setToolTip: keyEquivalent];
222 NSMutableSet *equivalentItems = (NSMutableSet *)[keyEquivalents objectForKey: keyEquivalent];
223 if (equivalentItems == nil) {
224 equivalentItems = [[NSMutableSet alloc] initWithObjects: menuItem, nil];
225 [keyEquivalents setObject: equivalentItems forKey: keyEquivalent];
226 [equivalentItems release];
227 } else {
228 [equivalentItems addObject: menuItem];
229 }
230 }
231 }
232
233 NSString *bundlePath = (NSString *)[itemInfo objectForKey: (NSString *)kICServiceBundlePath];
234 if (bundlePath == NULL) continue;
235 IconRef serviceIcon = ICCF_CopyIconRefForPath(bundlePath);
236 if (serviceIcon == NULL) continue;
237 [menuItem _setIconRef: serviceIcon];
238 ReleaseIconRef(serviceIcon);
239 }
240}
241
[142]242@implementation ICeCoffEEServicePrefController
243
244#pragma mark class initialization
245
246+ (void)initialize;
247{
248 ICCF_SERVICE_OPTION_HIDDEN = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithBool: YES], kICServiceHidden, nil];
249}
250
251#pragma mark initialize-release
252
253- (id)initWithParentWindow:(NSWindow *)parent;
254{
255 if ( (self = [self initWithWindowNibName: @"Select services"])) {
256 NSWindow *window = [self window]; // connect outlets
[319]257 [serviceOutline setAutoresizesOutlineColumn: NO];
258
[142]259 NSButtonCell *checkBoxCell = [[ICeCoffEENonHighlightingButtonCell alloc] init];
260 [checkBoxCell setButtonType: NSSwitchButton];
261 [checkBoxCell setImagePosition: NSImageOnly];
262 [checkBoxCell setAllowsMixedState: YES];
[428]263
[142]264 [[serviceOutline tableColumnWithIdentifier: @"show"] setDataCell: checkBoxCell];
265 [checkBoxCell release];
266
267 NSTextFieldCell *textFieldCell = [[serviceOutline tableColumnWithIdentifier: @"service"] dataCell];
[319]268 [textFieldCell setWraps: YES];
269 [[serviceOutline tableColumnWithIdentifier: @"service"] setDataCell:
270 [ICeCoffEELabeledIconCell copyFromTextFieldCell: textFieldCell]];
[425]271
[142]272 textFieldCell = [[serviceOutline tableColumnWithIdentifier: @"key"] dataCell];
[425]273 ((struct objc_object *)textFieldCell)->isa = [ICeCoffEEInvertingTextFieldCell class];
274
275 [serviceOutline noteNumberOfRowsChanged]; // or we get no active scroll bar or initial selection
[142]276
277 [window setResizeIncrements: NSMakeSize(1, ICCF_TableViewCellHeight(serviceOutline))];
278 if (parent != nil) {
279 [NSApp beginSheet: window modalForWindow: parent modalDelegate: self didEndSelector: nil contextInfo: nil];
280 } else {
281 [window center];
282 [window makeKeyAndOrderFront: nil];
283 }
284 }
285 return self;
286}
287
288- (void)dealloc;
289{
[431]290 [keyEquivalents release]; keyEquivalents = nil;
291 [userKeyEquivalents release]; userKeyEquivalents = nil;
292 [servicesMenu release]; servicesMenu = nil;
293 [closedTriangle release]; closedTriangle = nil;
294 [selectedClosedTriangle release]; selectedClosedTriangle = nil;
295 [openTriangle release]; openTriangle = nil;
296 [selectedOpenTriangle release]; selectedOpenTriangle = nil;
[142]297 [super dealloc];
298}
299
300#pragma mark actions
301
302- (IBAction)showAll:(NSButton *)sender;
303{
[428]304 ICCF_PropagateServiceStateChange(servicesMenu, 0);
[142]305 [serviceOutline reloadData];
306}
307
308- (IBAction)hideAll:(NSButton *)sender;
309{
310 ICCF_PropagateServiceStateChange(servicesMenu, ICCF_SERVICE_HIDDEN);
311 [serviceOutline reloadData];
312}
313
314- (void)closeWithReturnCode:(int)returnCode;
315{
316 if ([[self window] isSheet]) {
317 [NSApp endSheet: [self window] returnCode: NSRunAbortedResponse];
318 }
319 [self close];
320}
321
322- (IBAction)cancel:(NSButton *)sender;
323{
324 [self closeWithReturnCode: NSRunAbortedResponse];
325}
326
327- (IBAction)saveChanges:(NSButton *)sender;
328{
329 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
330 NSMutableDictionary *icDefaults = [[defaults persistentDomainForName: (NSString *)kICBundleIdentifier] mutableCopy];
331 NSDictionary *serviceOptions = ICCF_RetainedServiceOptionsDictionary(servicesMenu);
332 if (serviceOptions != nil) {
333 [icDefaults setObject: serviceOptions forKey: (NSString *)kICServiceOptions];
334 [serviceOptions release];
335 } else {
336 [icDefaults removeObjectForKey: (NSString *)kICServiceOptions];
337 }
338 [defaults setPersistentDomain: icDefaults forName: (NSString *)kICBundleIdentifier];
339 [defaults synchronize];
340 APEMessageBroadcast(kICBundleIdentifier, kICPreferencesChanged, NULL);
341 [icDefaults release];
342 [self closeWithReturnCode: NSRunStoppedResponse];
343}
344
345@end
346
347@implementation ICeCoffEEServicePrefController (NSOutlineViewDataSource)
348
349- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item;
350{
351 if (servicesMenu == nil) {
[319]352 keyEquivalents = [[NSMutableDictionary alloc] init];
[431]353 userKeyEquivalents = [[[NSUserDefaults standardUserDefaults] dictionaryForKey: @"NSUserKeyEquivalents"] retain];
[182]354 servicesMenu = [[NSMenu alloc] initWithTitle: @""];
355 ICCF_SetServicesMenu(servicesMenu);
[319]356 ICCF_AddServiceKeyEquivalentsAndIcons(servicesMenu, ICCF_GetServicesInfo());
357 ICCF_RemoveSingleKeyEquivalents();
358
[142]359 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
360 NSDictionary *icDefaults = [defaults persistentDomainForName: (NSString *)kICBundleIdentifier];
361 NSDictionary *serviceOptions = [icDefaults objectForKey: (NSString *)kICServiceOptions];
362 ICCF_RestoreServiceOptionsDictionary(servicesMenu, serviceOptions);
363 }
364 return [(item == nil ? servicesMenu : [item submenu]) numberOfItems];
365}
366
367- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;
368{
369 return (item == nil ? YES : [item submenu] != nil);
370}
371
372- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item;
373{
374 return [(item == nil ? servicesMenu : [item submenu]) itemAtIndex: index];
375}
376
[431]377NSAttributedString *ICCF_KeyEquivalentAttributedString(NSString *self, unsigned count);
[142]378
379- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
380{
381 if ([[tableColumn identifier] isEqualToString: @"service"]) {
[319]382 static NSDictionary *attrDict = nil;
383 if (attrDict == nil) { // XXX we leak this, but so does the Apple sample code...
384 NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
385 [style setLineBreakMode: NSLineBreakByTruncatingMiddle];
386 attrDict = [[NSDictionary alloc] initWithObjectsAndKeys: style, NSParagraphStyleAttributeName, nil];
387 [style release];
388 }
389 return [[[NSAttributedString alloc] initWithString: [item title] attributes: attrDict] autorelease];
[142]390 } else if ([[tableColumn identifier] isEqualToString: @"show"]) {
[425]391 int state = ICCF_GetServiceState(item);
392 if ([item submenu] != nil && state == ICCF_SERVICE_UNKNOWN) {
[142]393 return [NSNumber numberWithInt: ICCF_PropagateServiceState(item, nil)];
394 }
[425]395 return [NSNumber numberWithInt: ICCF_ServiceItemState(item)];
[142]396 } else if ([[tableColumn identifier] isEqualToString: @"key"]) {
[319]397 NSString *equivalent = [item toolTip];
[431]398 if (equivalent == nil)
399 return nil;
400 return ICCF_KeyEquivalentAttributedString(equivalent, ICCF_CountForKeyEquivalent(equivalent));
[142]401 }
402 return nil;
403}
404
405- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
406{
407 if ([[tableColumn identifier] isEqualToString: @"show"]) {
[425]408 int newState = [object boolValue] ? ICCF_SERVICE_SHOWN : ICCF_SERVICE_HIDDEN;
[319]409 ICCF_UpdateKeyEquivalentForItem(item, newState);
[425]410 ICCF_SetServiceState(item, newState);
[142]411
412 NSMenu *submenu = [item menu];
413 if (submenu == servicesMenu) {
414 ICCF_PropagateServiceState(item, item);
415 } else {
416 NSMenu *supermenu;
417 while ( (supermenu = [submenu supermenu]) != servicesMenu) {
418 submenu = supermenu;
419 }
[319]420 ICCF_PropagateServiceState((NSMenuItem *)[supermenu itemAtIndex: [supermenu indexOfItemWithSubmenu: submenu]], item);
[142]421 }
422 [outlineView reloadData];
423 }
424}
425
426@end
427
[319]428@implementation ICeCoffEEServicePrefController (NSOutlineViewDelegate)
429
430- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item;
431{
432 if (![[tableColumn identifier] isEqualToString: @"service"])
433 return;
434 [(ICeCoffEELabeledIconCell *)cell setIconRef: [item _iconRef]];
435}
436
[428]437static NSImage *ICCF_InvertedImage(NSImage *image) {
438 NSImage *invertedImage = [[NSImage alloc] initWithSize: [image size]];
439 NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData: [image TIFFRepresentation]];
440 CIImage *source = [[CIImage alloc] initWithBitmapImageRep: imageRep];
441 CIColor *black = [[CIColor alloc] initWithColor: [NSColor blackColor]];
442
443 CIFilter *monochromeFilter = [CIFilter filterWithName: @"CIColorMonochrome"];
444 [monochromeFilter setValue: source forKey: @"inputImage"];
445 [monochromeFilter setValue: [NSNumber numberWithFloat: 1.0] forKey: @"inputIntensity"];
446 [monochromeFilter setValue: black forKey: @"inputColor"];
447
448 CIFilter *invertFilter = [CIFilter filterWithName: @"CIColorInvert"];
449 [invertFilter setValue: [monochromeFilter valueForKey: @"outputImage"] forKey: @"inputImage"];
450
451 CIFilter *maskToAlphaFilter = [CIFilter filterWithName: @"CIMaskToAlpha"];
452 [maskToAlphaFilter setValue: [invertFilter valueForKey: @"outputImage"] forKey: @"inputImage"];
453
454 [invertedImage lockFocus];
455 CIContext *context = [CIContext contextWithCGContext: [[NSGraphicsContext currentContext] graphicsPort]
456 options: nil];
457 CIImage *result = [maskToAlphaFilter valueForKey: @"outputImage"];
458 [context drawImage: result atPoint: CGPointZero fromRect: [result extent]];
459 [invertedImage unlockFocus];
460
461 [source release];
462 [black release];
463
464 return invertedImage;
465}
466
467- (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item;
468{
469 static BOOL isInverted = NO;
470
471 if (closedTriangle == nil) {
472 closedTriangle = [[cell image] retain];
473 openTriangle = [[cell alternateImage] retain];
474 selectedClosedTriangle = ICCF_InvertedImage(closedTriangle);
475 selectedOpenTriangle = ICCF_InvertedImage(openTriangle);
476 }
477
478 if (![outlineView isRowSelected: [outlineView rowForItem: item]] ||
479 [[outlineView window] firstResponder] != outlineView || ![[outlineView window] isKeyWindow]) {
480 if (!isInverted)
481 return;
482
483 [cell setImage: closedTriangle];
484 [cell setAlternateImage: openTriangle];
485 isInverted = NO;
486 return;
487 }
488
489 // not checking for isInverted is intentional - images reset when triangle is flipped
490 [cell setImage: selectedClosedTriangle];
491 [cell setAlternateImage: selectedOpenTriangle];
492 isInverted = YES;
493}
494
[319]495@end
496
[142]497@implementation ICeCoffEEServicePrefController (NSWindowDelegate)
498
499- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame;
500{
501 NSWindow *window = [serviceOutline window];
502 NSRect frame = [window frame];
503 NSScrollView *scrollView = [serviceOutline enclosingScrollView];
504 float displayedHeight = [[scrollView contentView] bounds].size.height;
505 float heightChange = [[scrollView documentView] bounds].size.height - displayedHeight;
506 float heightExcess;
507
508 if (heightChange >= 0 && heightChange <= 1) {
509 // either the window is already optimal size, or it's too big
510 float rowHeight = ICCF_TableViewCellHeight(serviceOutline);
511 heightChange = (rowHeight * [serviceOutline numberOfRows]) - displayedHeight;
512 }
513
514 frame.size.height += heightChange;
515
516 if ( (heightExcess = [window minSize].height - frame.size.height) > 1 ||
517 (heightExcess = [window maxSize].height - frame.size.height) < 1) {
518 heightChange += heightExcess;
519 frame.size.height += heightExcess;
520 }
521
522 frame.origin.y -= heightChange;
523
524 return frame;
525}
526
527@end
528
529@implementation ICeCoffEEServicePrefController (NSWindowNotifications)
530
531- (void)windowWillClose:(NSNotification *)notification;
532{
533 [self autorelease];
534}
535
536@end
Note: See TracBrowser for help on using the repository browser.