The R Project SVN R-packages

Rev

Rev 6063 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
648 iacus 1
//
2
//  AMPreferenceWindowController.m
3
//  PrefPane
4
//
5
//  Created by Andreas on Sat May 31 2003.
6
//  Copyright (c) 2003 Andreas Mayer. All rights reserved.
7
//
8
 
1048 urbaneks 9
#import "../RGUI.h" /* for NLS nacro */
648 iacus 10
#import "AMPreferenceWindowController.h"
11
#import "AMPrefPaneProtocol.h"
12
#import "AMPrefPaneIcon.h"
13
#import "AMPrefPaneIconView.h"
4330 goedman 14
//#import "../RController.h"
648 iacus 15
 
16
 
17
@interface NSToolbar (AMPrivate)
18
- (void)_setCustomizesAlwaysOnClickAndDrag:(BOOL)flag;
19
- (void)_setFirstMoveableItemIndex:(int)index;
20
- (void)setCustomizationSheetWidth:(int)width;
21
@end
22
 
23
 
24
// ============================================================
25
#pragma mark -
26
#pragma mark ━ private interface ━
27
// ============================================================
28
 
29
@interface AMPreferenceWindowController (Private)
30
- (void)setPrefPanes:(NSDictionary *)newPrefPanes;
31
- (void)setActivePane:(AMPreferencePane *)newActivePane;
32
- (void)removeAllPanes;
33
- (NSString *)autosaveName;
34
- (void)setAutosaveName:(NSString *)newAutosaveName;
814 urbaneks 35
- (AMPrefPaneIcon *)iconForPrefPane:(id<AMPrefPaneProtocol>)prefPane;
648 iacus 36
- (void)changeContentView:(NSView *)contentView;
37
- (void)createIconViewPane;
38
- (void)toolbarShowAll;
39
- (NSArray *)validPrefPaneIdentifiers;
40
@end
41
 
42
// ============================================================
43
#pragma mark -
44
#pragma mark ━ implementation ━
45
// ============================================================
46
 
47
@implementation AMPreferenceWindowController
48
 
49
// ============================================================
50
#pragma mark -
51
#pragma mark ━ initialisation ━
52
// ============================================================
53
 
54
- (id)initWithAutosaveName:(NSString *)name
55
{
56
	NSWindow *panel = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 200, 100) styleMask:(NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask) backing:NSBackingStoreBuffered defer:YES] autorelease];
57
		// create a new window
58
	[panel setDelegate:self];
59
	[panel setOpaque:YES];
60
	[panel setContentView:[[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 100)] autorelease]];
61
	[self setPrefPanes:[NSMutableDictionary dictionary]];
62
	[self setAutosaveName:name];
6077 bibiko 63
	[self setTitle:NLS(@"Preferences")];
648 iacus 64
	[self createIconViewPane];
65
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:NSApplicationWillTerminateNotification object:NSApp];
66
	_am_oldContentViewFrame = [[panel contentView] frame];
67
	return [super initWithWindow:panel];
68
}
69
 
70
- (void)dealloc
71
{
72
	[iconView release];
73
	[prefPanes release];
74
	[activePane release];
75
	[super dealloc];
76
}
77
 
78
// ============================================================
79
#pragma mark -
80
#pragma mark ━ setters / getters ━
81
// ============================================================
82
 
83
- (NSWindow *)window
84
{
85
	NSWindow *result = [super window];
86
	if (![result toolbar]) {
87
		NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:AMPPToolbarIdentifier];
88
		[toolbar setDelegate:self];
89
		[toolbar setVisible:YES];
90
		[toolbar setAllowsUserCustomization:usesConfigurationPane];
91
		[toolbar setAutosavesConfiguration:YES];
92
		if (usesConfigurationPane) {
93
			[toolbar _setCustomizesAlwaysOnClickAndDrag:YES];
94
			[toolbar _setFirstMoveableItemIndex:2];
95
		}
96
		[result setToolbar:toolbar];
97
		// select first panel
98
		NSString *selectedItemIdentifier = [[[toolbar items] objectAtIndex:0] itemIdentifier];
99
		[toolbar setSelectedItemIdentifier:selectedItemIdentifier];
100
		[self selectPaneWithIdentifier:selectedItemIdentifier];
101
		// set frame size
102
		// gnnn... we need to extract the saved frame ourselfes, since we want to set the origin only
103
		NSString *frameString = [[NSUserDefaults standardUserDefaults] stringForKey:[NSString stringWithFormat:@"NSWindow Frame %@", autosaveName]];
104
		NSRect frame;
105
		if (frameString) {
106
			NSArray *frameArray = [frameString componentsSeparatedByString:@" "];
107
			frame = NSMakeRect([[frameArray objectAtIndex:0] floatValue], [[frameArray objectAtIndex:1] floatValue], [[frameArray objectAtIndex:2] floatValue], [[frameArray objectAtIndex:3] floatValue]);
108
			NSRect oldFrame = [result frame];
109
			oldFrame.origin.x = frame.origin.x;
110
			oldFrame.origin.y = frame.origin.y+(frame.size.height-oldFrame.size.height);
111
			[result setFrame:oldFrame display:NO];
112
		} else {
113
			[result center];
114
		}
115
	}
116
	return result;
117
}
118
 
119
- (NSDictionary *)prefPanes
120
{
121
    return prefPanes;
122
}
123
 
124
- (id)delegate
125
{
126
    return delegate;
127
}
128
 
129
- (void)setDelegate:(id)newDelegate
130
{
131
	// do not retain delegate
132
	delegate = newDelegate;
133
	_am_delegateRespondsToCategoryForPreferencePane = [delegate respondsToSelector:@selector(categoryForPreferencePane:defaultCategory:)];
134
	_am_delegateRespondsToDisplayNameForCategory = [delegate respondsToSelector:@selector(displayNameForCategory:)];
135
}
136
 
137
- (BOOL)usesConfigurationPane
138
{
139
	return usesConfigurationPane;
140
}
141
 
142
- (void)setUsesConfigurationPane:(BOOL)newUsesConfigurationPane
143
{
144
	usesConfigurationPane = newUsesConfigurationPane;
145
}
146
 
147
- (BOOL)sortByCategory
148
{
149
	return [(AMPrefPaneIconView *)iconView sortByCategory];
150
}
151
 
152
- (void)setSortByCategory:(BOOL)newSortByCategory
153
{
154
	BOOL changed = ([(AMPrefPaneIconView *)iconView sortByCategory] != newSortByCategory);
155
	if (changed) {
156
		[(AMPrefPaneIconView *)iconView setSortByCategory:newSortByCategory];
157
		if (activePane == nil) {
158
			[self toolbarShowAll];
159
		}
160
	}
161
}
162
 
163
- (NSArray *)categorySortOrder
164
{
165
	return [(AMPrefPaneIconView *)iconView categorySortOrder];
166
}
167
 
168
- (void)setCategorySortOrder:(NSArray *)newCategorySortOrder
169
{
170
	[(AMPrefPaneIconView *)iconView setCategorySortOrder:newCategorySortOrder];
171
}
172
 
173
- (NSString *)title
174
{
175
	return title;
176
}
177
 
178
- (void)setTitle:(NSString *)newTitle
179
{
180
	id old = nil;
181
 
182
	if (newTitle != title) {
183
		old = title;
184
		title = [newTitle copy];
185
		[old release];
186
	}
187
}
188
 
189
 
190
// ============================================================
191
#pragma mark -
192
#pragma mark ━ public methods ━
193
// ============================================================
194
 
195
- (void)addPluginsOfType:(NSString *)extension fromPath:(NSString *)path
196
{
197
	NSEnumerator* enumerator = [[NSBundle pathsForResourcesOfType:extension inDirectory:path] objectEnumerator];
198
	NSString* pluginPath;
199
	while ((pluginPath = [enumerator nextObject])) {
200
		[self addPluginFromPath:pluginPath];
201
	}
202
}
203
 
814 urbaneks 204
- (BOOL)addPane:(id<AMPrefPaneProtocol>)newPane withIdentifier:(NSString *)identifier
648 iacus 205
{
206
	BOOL result;
5707 urbaneks 207
	if ((result = ([prefPanes objectForKey:identifier] == nil))) {
648 iacus 208
		if ([delegate respondsToSelector:@selector(shouldLoadPreferencePane:)]) {
209
			result = [delegate shouldLoadPreferencePane:identifier];
210
		}
211
		if (result) {
212
			[prefPanes setObject:newPane forKey:identifier];
814 urbaneks 213
			if ([(NSObject*)newPane respondsToSelector:@selector(mainView)] && [newPane mainView]) {
648 iacus 214
				[(AMPrefPaneIconView *)iconView addIcon:[self iconForPrefPane:newPane]];
215
			}
216
		}
217
	}
218
	return result;
219
}
220
 
221
- (void)addPluginFromPath:(NSString *)path
222
{
223
	NSBundle* pluginBundle = [NSBundle bundleWithPath:path];
224
	if (!pluginBundle) {
225
		NSLog(@"error loading bundle: %@", path);
226
	} else { // loaded successfully
227
		NSLog(@"loaded: %@", [pluginBundle bundlePath]);
228
		NSString* prefPaneIdentifier;
5707 urbaneks 229
		if ((prefPaneIdentifier = [pluginBundle objectForInfoDictionaryKey:CFBundleIdentifierKey])) {
648 iacus 230
			if ([prefPanes objectForKey:prefPaneIdentifier]) {
231
				// pane with same identifier exists
232
				NSLog(@"pref pane already loaded %@", prefPaneIdentifier);
233
			} else {
234
				BOOL load = YES;
235
				if ([delegate respondsToSelector:@selector(shouldLoadPreferencePane:)]) {
236
					load = [delegate shouldLoadPreferencePane:prefPaneIdentifier];
237
				}
238
				if (load) {
239
					AMPreferencePane *newPane;
5707 urbaneks 240
					if ((newPane = [[AMPreferencePane alloc] initWithBundle:pluginBundle])) {
648 iacus 241
						if (newPane)
242
							[self addPane:newPane withIdentifier:prefPaneIdentifier];
243
					}
244
				} else {
245
					NSLog(@"delegate did not approve plugin %@", prefPaneIdentifier);
246
				}
247
			}
248
		} else {
249
			// no identifier
250
		}
251
	}
252
}
253
 
254
- (BOOL)deselectActivePane
255
{
256
	BOOL result = YES;
257
	if (activePane) {
258
		if ([activePane respondsToSelector:@selector(willUnselect)]) {
259
			[(id)activePane willUnselect];
260
		}
261
		if ([delegate respondsToSelector:@selector(didUnselectPreferencePane:)]) {
262
			[delegate didUnselectPreferencePane:[activePane identifier]];
263
		}
264
		if ([activePane respondsToSelector:@selector(didUnselect)]) {
265
			[(id)activePane didUnselect];
266
		}
267
		[self setActivePane:nil];
268
	}
5771 bibiko 269
	[[NSColorPanel sharedColorPanel] close];
648 iacus 270
	return result;
271
}
272
 
273
- (BOOL)selectPaneWithIdentifier:(NSString *)identifier
274
{
275
	BOOL result = NO;
276
	AMPreferencePane *pane = [prefPanes objectForKey:identifier];
277
	if (pane) {
278
		if (pane == activePane) {
279
			// already active
280
			/*
281
			if ([delegate respondsToSelector:@selector(willSelectPreferencePane:)]) {
282
				[delegate willSelectPreferencePane:identifier];
283
			}
284
			 */
285
			result = YES;
286
		} else {
287
			NSView *paneView = [pane mainView];
288
			if (paneView) {
289
				if ([activePane respondsToSelector:@selector(willUnselect)])
290
					[(id)activePane willUnselect];
291
				if ([delegate respondsToSelector:@selector(willSelectPreferencePane:)]) {
292
					[delegate willSelectPreferencePane:identifier];
293
				}
294
				if ([pane respondsToSelector:@selector(willSelect)])
295
					[(id)pane willSelect];
296
				if ([pane respondsToSelector:@selector(loadMainView)])
297
					[(id)pane loadMainView];
5732 urbaneks 298
 
299
				// For some reasons the NSColorPanel pops up while changing the pane;
300
				// thus close it explicitly
301
				[[NSColorPanel sharedColorPanel] close];
302
 
6063 bibiko 303
				// Synchronize selected toolbar item mainly if the
304
				// method was called by the app (like Rconsole colors)
305
				[[[self window] toolbar] setSelectedItemIdentifier:identifier];
306
 
648 iacus 307
				[[self window] setTitle:[[prefPanes objectForKey:identifier] label]];
308
				[self changeContentView:paneView];
309
 
310
				if (activePane) {
311
					if ([delegate respondsToSelector:@selector(didUnselectPreferencePane:)]) {
312
						[delegate didUnselectPreferencePane:[activePane identifier]];
313
					}
314
					if ([activePane respondsToSelector:@selector(didUnselect)])
315
						[(id)activePane didUnselect];
316
				}
317
				if ([pane respondsToSelector:@selector(didSelect)])
318
					[(id)pane didSelect];
319
				[self setActivePane:pane];
320
			} else { // no view?!
321
				NSLog(@"Preference Pane \"%@\" has no view", [pane identifier]);
322
			}
323
		}
324
	}
325
	return result;
326
}
327
 
328
- (BOOL)selectIconViewPane
329
{
330
	BOOL result = [self deselectActivePane];
331
	if (result)
332
		[self toolbarShowAll];
333
	return result;
334
}
335
 
336
- (void)replyToShouldUnselect:(BOOL)shouldUnselect;
337
{}
338
 
339
- (NSString *)categoryForIdentifier:(NSString *)identifier
340
{
341
	NSString *result;
342
	AMPreferencePane *prefPane = [prefPanes objectForKey:identifier];
343
	result = [prefPane category];
344
	if (_am_delegateRespondsToCategoryForPreferencePane) {
345
		result = [delegate performSelector:@selector(categoryForPreferencePane:defaultCategory:) withObject:identifier withObject:result];
346
	}
347
	return result;
348
}
349
 
350
- (NSArray *)categories
351
{
352
	NSArray *result = nil;
353
	NSMutableDictionary *categories = [NSMutableDictionary dictionary];
354
	NSEnumerator *enumerator = [[prefPanes allValues] objectEnumerator];
355
	AMPreferencePane *prefPane;
5707 urbaneks 356
	while ((prefPane = [enumerator nextObject])) {
648 iacus 357
		NSString *category = [prefPane category];
358
		if (_am_delegateRespondsToCategoryForPreferencePane) {
359
			category = [delegate performSelector:@selector(categoryForPreferencePane:defaultCategory:) withObject:[prefPane identifier] withObject:category];
360
		}
361
		[categories setObject:category forKey:category];
362
	}
363
	result = [categories allKeys];
364
	return result;
365
}
366
 
367
- (NSString *)categoryDisplayNameForIdentifier:(NSString *)identifier
368
{
369
	NSString *result = nil;
370
	NSString *category = [self categoryForIdentifier:identifier];
371
	if (_am_delegateRespondsToDisplayNameForCategory) {
372
		result = [delegate displayNameForCategory:category];
373
	}
374
	if (result == nil) {
375
		AMPreferencePane *prefPane = [prefPanes objectForKey:identifier];
376
		if ([prefPane respondsToSelector:@selector(categoryDisplayName)]) {
377
			result = [(id)prefPane categoryDisplayName];
378
		}
379
	}
380
	if (result == nil) {
381
		result = category;
382
	}
383
	return result;
384
}
385
 
386
 
387
// ============================================================
388
#pragma mark -
389
#pragma mark ━ private methods ━
390
// ============================================================
391
 
392
- (void)setPrefPanes:(NSDictionary *)newPrefPanes
393
{
394
	id old = nil;
395
 
396
	if (newPrefPanes != prefPanes) {
397
		old = prefPanes;
398
		prefPanes = [newPrefPanes mutableCopy];
399
		[old release];
400
	}
401
}
402
 
403
- (AMPreferencePane *)activePane
404
{
405
	return activePane;
406
}
407
 
408
- (void)setActivePane:(AMPreferencePane *)newActivePane
409
{
410
	id old = nil;
411
 
412
	if (newActivePane != activePane) {
413
		old = activePane;
414
		activePane = [newActivePane retain];
415
		[old release];
416
	}
417
}
418
 
419
- (void)removeAllPanes
420
{
421
	NSLog(@"at this time (10.2.6) there's no way to unload bundles, sorry");
422
}
423
 
424
- (NSString *)autosaveName
425
{
426
	return autosaveName;
427
}
428
 
429
- (void)setAutosaveName:(NSString *)newAutosaveName
430
{
431
	id old = nil;
432
 
433
	if (newAutosaveName != autosaveName) {
434
		old = autosaveName;
435
		autosaveName = [newAutosaveName copy];
436
		[old release];
437
	}
438
}
439
 
814 urbaneks 440
- (AMPrefPaneIcon *)iconForPrefPane:(id<AMPrefPaneProtocol>)prefPane
648 iacus 441
{
442
	AMPrefPaneIcon *result = [[[AMPrefPaneIcon alloc] initWithIdentifier:[prefPane identifier] image:[prefPane icon] andTitle:[prefPane label]] autorelease];
443
	[result setCategory:[prefPane category]];
444
	[result setTarget:self];
445
	[result setSelector:@selector(toolbarShowPane:)];
446
	return result;
447
}
448
 
449
- (void)createIconViewPane
450
{
451
	if (!iconView) {
452
		NSMutableArray *icons = [NSMutableArray array];
453
		NSEnumerator *enumerator = [prefPanes objectEnumerator];
454
		AMPreferencePane *prefPane;
5707 urbaneks 455
		while ((prefPane = [enumerator nextObject])) {
648 iacus 456
			if ([prefPane respondsToSelector:@selector(mainView)] && [prefPane mainView]) {
457
				[icons addObject:[self iconForPrefPane:prefPane]];
458
			}
459
		}
460
		iconView = [[AMPrefPaneIconView alloc] initWithController:self icons:icons columns:7];
461
	}
462
}
463
 
464
- (void)changeContentView:(NSView *)contentView
465
{
466
	NSRect windowFrame = [[self window] frame];
467
	NSRect newViewFrame = [contentView frame];
468
	float deltaX = (newViewFrame.size.width-_am_oldContentViewFrame.size.width);
469
	float deltaY = (newViewFrame.size.height-_am_oldContentViewFrame.size.height);
470
	windowFrame.size.width += deltaX;
471
	windowFrame.size.height += deltaY;
472
	windowFrame.origin.y -= deltaY;
473
	[[self window] setContentView:contentView];
474
	[[self window] setFrame:windowFrame display:YES animate:YES];
475
	_am_oldContentViewFrame = newViewFrame;
476
}
477
 
478
- (NSArray *)validPrefPaneIdentifiers
479
{
480
	NSMutableArray *result = [NSMutableArray array];
481
	NSEnumerator *enumerator = [prefPanes objectEnumerator];
482
	AMPreferencePane *pane;
5707 urbaneks 483
	while ((pane = [enumerator nextObject])) {
648 iacus 484
		if ([pane respondsToSelector:@selector(mainView)] && [pane mainView]) {
485
			[result addObject:[pane identifier]];
486
		}
487
	}
488
	return result;
489
}
490
 
491
 
492
// ============================================================
493
#pragma mark -
494
#pragma mark ━ toolbar action methods ━
495
// ============================================================
496
 
497
- (void)toolbarShowAll
498
{
499
	[self deselectActivePane];
500
	[[self window] setTitle:[self title]];
501
	[self changeContentView:iconView];
502
}
503
 
504
- (void)toolbarShowPane:(id)sender
505
{
506
	NSString *identifier = [(NSToolbarItem *)sender itemIdentifier];
507
	[[[self window] toolbar] setSelectedItemIdentifier:[(NSToolbarItem *)sender itemIdentifier]];
508
	[self selectPaneWithIdentifier:identifier];
509
}
510
 
511
// ============================================================
512
#pragma mark -
513
#pragma mark ━ toolbar delegate methods ━
514
// ============================================================
515
 
516
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
517
{
518
	NSToolbarItem *result = nil;
519
	AMPreferencePane *pane = nil;
520
	if ([itemIdentifier isEqualToString:AMPPToolbarShowAllItemIdentifier]) {
5707 urbaneks 521
		if ((result = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier])) {
648 iacus 522
			[result setTarget:self];
523
			[result setAction:@selector(toolbarShowAll)];
524
			[result setEnabled:YES];
525
			[result setImage:[NSImage imageNamed:@"Prefs"]];
1048 urbaneks 526
			[result setLabel:NLS(@"Show All")];
648 iacus 527
		}
5707 urbaneks 528
	} else if ((pane = [prefPanes objectForKey:itemIdentifier])) {
529
		if ((result = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier])) {
648 iacus 530
			[result setTarget:self];
531
			[result setAction:@selector(toolbarShowPane:)];
532
			[result setEnabled:YES];
533
			[result setImage:[pane icon]];
534
			[result setLabel:[pane label]];
535
		}
536
	}
5707 urbaneks 537
        if (result) [result autorelease];
648 iacus 538
	return result;
539
}
540
 
541
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
542
{
543
	NSMutableArray *result = [[[NSMutableArray alloc] init] autorelease];
544
	if (usesConfigurationPane) {
545
		[result addObject:AMPPToolbarShowAllItemIdentifier];
546
		[result addObject:NSToolbarSeparatorItemIdentifier];
547
	}
548
	NSMutableArray *prefPaneIdentifiers = [NSMutableArray arrayWithArray:[self validPrefPaneIdentifiers]];
549
	[prefPaneIdentifiers sortUsingSelector:@selector(caseInsensitiveCompare:)];
550
	[result addObjectsFromArray:prefPaneIdentifiers];
551
	return result;
552
}
553
 
554
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
555
{
556
	NSMutableArray *result = [[[NSMutableArray alloc] init] autorelease];
557
	if (usesConfigurationPane) {
558
		[result addObject:AMPPToolbarShowAllItemIdentifier];
559
		[result addObject:NSToolbarSeparatorItemIdentifier];
560
	}
561
	[result addObjectsFromArray:[self validPrefPaneIdentifiers]];
562
	return result;
563
}
564
 
565
- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
566
{
567
	NSMutableArray *result = [[[NSMutableArray alloc] init] autorelease];
568
	if (usesConfigurationPane) {
569
		[result addObject:AMPPToolbarShowAllItemIdentifier];
570
	}
571
	[result addObjectsFromArray:[self validPrefPaneIdentifiers]];
572
	return result;
573
}
574
 
575
- (void)toolbarDidRemoveItem:(NSNotification *)notification
576
{}
577
 
578
- (void)toolbarWillAddItem:(NSNotification *)notification
579
{}
580
 
581
// ============================================================
582
#pragma mark -
583
#pragma mark ━ window delegate methods ━
584
// ============================================================
585
 
586
- (void)windowWillClose:(NSNotification *)aNotification
587
{
4330 goedman 588
//	if (![[[RController sharedController] getRConsoleWindow] isKeyWindow]) {
589
//		[[[RController sharedController] getRConsoleWindow] makeKeyWindow];
590
//		SLog(@" RConsole set to key window");
591
//	}
648 iacus 592
	if ([activePane respondsToSelector:@selector(willUnselect)])
593
		[(id)activePane willUnselect];
5705 urbaneks 594
	// Close opened NSColorPanel if Preferences window will be closed
595
	if([NSColorPanel sharedColorPanelExists])
596
		[[NSColorPanel sharedColorPanel] close];
648 iacus 597
}
598
 
599
- (void)windowDidClose:(NSNotification *)aNotification
600
{
601
	if ([activePane respondsToSelector:@selector(willUnselect)])
602
		[(id)activePane willUnselect];
603
	if ([activePane respondsToSelector:@selector(didUnselect)])
604
		[(id)activePane didUnselect];
605
}
606
 
607
- (void)windowDidMove:(NSNotification *)aNotification
608
{
609
	[[self window] saveFrameUsingName:autosaveName];
610
}
611
 
612
 
613
// ============================================================
614
#pragma mark -
615
#pragma mark ━ notification methods ━
616
// ============================================================
617
 
618
- (void)applicationWillTerminate:(NSNotification *)aNotification
619
{
620
	if ([activePane respondsToSelector:@selector(willUnselect)])
621
		[(id)activePane willUnselect];
622
	if ([activePane respondsToSelector:@selector(didUnselect)])
623
		[(id)activePane didUnselect];
624
}
625
 
626
 
627
@end