1//
2//  PXBackgroundController.m
3//  Pixen-XCode
4//
5//  Created by Joe Osborn on Sun Oct 26 2003.
6//  Copyright (c) 2003 Open Sword Group. All rights reserved.
7//
8
9#import "PXBackgroundController.h"
10#import "PXSlashyBackground.h"
11#import "PXMonotoneBackground.h"
12#import "PXCheckeredBackground.h"
13#import "PXImageBackground.h"
14#import "PXBackground.h"
15#import "PXNamePrompter.h"
16#import "PXCanvas.h"
17
18#ifdef __COCOA__
19static NSString *BACKGROUNDPRESET = @"Application Support/Pixen/Backgrounds/Presets";
20#else
21static NSString *BACKGROUNDPRESET = @"Pixen/Backgrounds/Presets";
22#endif
23
24#define SAVEASPOPUPITEMTAG 1
25#define DELETEPOPUPITEMTAG 2
26
27static NSArray *defaultBackgrounds (void)
28{
29	static NSArray *backgrounds = nil;
30	if (! backgrounds )
31    {
32		backgrounds = [[NSArray alloc] initWithObjects:[[PXSlashyBackground alloc] init],
33			[[PXMonotoneBackground alloc] init],
34			[[PXCheckeredBackground alloc] init],
35			[[PXImageBackground alloc] init] ,
36			nil];
37    }
38	return backgrounds;
39}
40
41
42
43@interface PXBackgroundController ( Private)
44- (void) _populatePopup: (NSPopUpButton *) aPopup withDefaultBackgroundsUsingSelectionAction: (SEL)aSelector;
45- (void) _populatePopup: (NSPopUpButton *) aPopup withUserBackgroundsUsingSelectionAction: (SEL)aSelector;
46- (void) _populateMenu:  (NSPopUpButton *) aPopup selectionAction: (SEL)aSelector;
47- (void) _populateMenus;
48- (void) _setUsesAlternateBackground:(BOOL)newUsesAlternateBackground;
49- (void)_setDefaultBackgroundsFor:(id) aCanvas;
50- (void) _setMainBackground:(id) aBackground;
51- (void) _setAlternateBackground:(id) aBackground;
52@end
53
54
55@implementation PXBackgroundController ( Private )
56
57#define PXBackgroundControllerSetBackground(bg, menu, configView, newBg)\
58{\
59	[[bg configurator] removeFromSuperview];\
60		[newBg retain];\
61			[bg release];\
62				bg = newBg;\
63					[menu selectItemWithTitle:[bg name]];\
64						[configView addSubview:[bg configurator]];\
65}
66
67
68//Defaults backgrounds create by hand
69- (void) _populatePopup:(NSPopUpButton *) aPopup withDefaultBackgroundsUsingSelectionAction:(SEL)aSelector
70{
71	NSEnumerator  *enumerator =  [defaultBackgrounds() objectEnumerator];
72	id current;
73
74	while( ( current = [enumerator nextObject] ) )
75    {
76
77		id item = [[[NSMenuItem alloc] initWithTitle:[current name]
78											  action: aSelector
79									   keyEquivalent: @""]  autorelease];
80#ifndef __COCOA__
81		[item setTarget: self];
82#endif
83
84		[item setRepresentedObject:[[current copy] autorelease]];
85		[[aPopup menu] addItem:item];
86    }
87}
88
89//Users backgrounds  saved by the user usally in ~/Library/Application Support/Pixen/Backgrounds/Presets ( OSX )
90// and  $GNUSTEP_USER_HOME/Library/Pixen/Backgrounds/Presets for GNUstep
91- (void) _populatePopup:(NSPopUpButton*) aPopup withUserBackgroundsUsingSelectionAction:(SEL)aSelector
92{
93	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
94
95	if ( [paths count] > 0)
96    {
97		NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent: BACKGROUNDPRESET];
98		//TODO check if exists ???
99		id enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
100		id current;
101
102		while( ( current = [enumerator nextObject] ) )
103		{
104			if ( [[current pathExtension] isEqualToString:@"pxbgnd"] )
105			{
106				id item = [[[NSMenuItem alloc] initWithTitle:[current stringByDeletingPathExtension]
107													  action: aSelector
108											   keyEquivalent: @""]
109					autorelease];
110#ifndef __COCOA__
111				[item setTarget :self];
112#endif
113
114
115				[item setRepresentedObject:[NSKeyedUnarchiver unarchiveObjectWithFile:
116					[path stringByAppendingPathComponent:current]]];
117				[[aPopup menu] addItem:item];
118			}
119		}
120    }
121}
122
123- (void) _populateMenu: (NSPopUpButton *) aPopup selectionAction: (SEL)aSelector
124{
125	id selected = [[[aPopup titleOfSelectedItem] retain] autorelease];
126	id menu = [aPopup menu];
127
128	//remove all items
129	[aPopup removeAllItems];
130
131	//add defaults backgrounds
132	[self _populatePopup:aPopup withDefaultBackgroundsUsingSelectionAction:aSelector];
133
134	[menu addItem:[NSMenuItem separatorItem]];
135
136	//Add user backgrounds
137	[self _populatePopup:aPopup withUserBackgroundsUsingSelectionAction:aSelector];
138
139	[menu addItem:[NSMenuItem separatorItem]];
140
141	//add "Save As" item
142	id item = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"BACKGROUNDS_SAVE_AS", @"Backgrounds Save As")
143										  action:@selector(saveCurrentConfiguration:)
144								   keyEquivalent:@""]
145		autorelease];
146#ifndef __COCOA__
147	[item setTarget: self];
148#endif
149
150
151	[[aPopup menu] addItem:item];
152
153	//Add "Delete item"
154	item = [[[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"BACKGROUNDS_DELETE", @"Backgrounds Delete")
155									   action:@selector(deleteCurrentConfiguration:)
156								keyEquivalent:@""]
157		autorelease];
158
159#ifndef __COCOA__
160	[item setTarget: self];
161#endif
162
163	[[aPopup menu] addItem:item];
164
165
166	//Display the first item if none is selected or id "Delete current configurator" item is selected
167	//display the selected item if not
168	if( ( ! [[aPopup itemTitles] containsObject:selected] )
169		|| ( [[aPopup selectedItem] tag] == DELETEPOPUPITEMTAG ) )
170    {
171		[aPopup selectItemAtIndex:0];
172    }
173	else
174    {
175		[aPopup selectItemWithTitle:selected];
176    }
177}
178
179
180- (void) _populateMenus
181{
182	[self _populateMenu:mainMenu selectionAction:@selector(selectMainBackground:)];
183	[self _populateMenu:alternateMenu selectionAction:@selector(selectAlternateBackground:)];
184}
185
186
187- (void) _setUsesAlternateBackground:(BOOL)newUsesAlternateBackground
188{
189	usesAlternateBackground = newUsesAlternateBackground;
190	[alternateMenu setEnabled:usesAlternateBackground];
191	[alternateBackground setConfiguratorEnabled:usesAlternateBackground];
192	[delegate setAlternateBackground:(usesAlternateBackground ? alternateBackground : nil)];
193	[alternateCheckbox setState:usesAlternateBackground];
194}
195
196//Display the default Background
197//If there is no defaults select : slashed_background for the main background
198// and flat_background for the alternate background
199- (void)_setDefaultBackgroundsFor:(id) aCanvas
200{
201	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
202	id mainBackgroundName = [defaults objectForKey:@"mainBackgroundName"];
203	id alternateBackgroundName = [defaults objectForKey:@"alternateBackgroundName"];
204
205	if( ! mainBackgroundName )
206    {
207		mainBackgroundName = NSLocalizedString(@"SLASHED_BACKGROUND", @"Slashed Background");
208    }
209	if(! alternateBackgroundName )
210    {
211		alternateBackgroundName = NSLocalizedString(@"FLAT_BACKGROUND", @"Flat Background");
212    }
213
214	[aCanvas setMainBackgroundName:mainBackgroundName];
215	[aCanvas setAlternateBackgroundName:alternateBackgroundName];
216	[self _setMainBackground:[[self class] backgroundNamed:mainBackgroundName]];
217	[self _setAlternateBackground:[[self class] backgroundNamed:alternateBackgroundName]];
218	[self _setUsesAlternateBackground:[defaults boolForKey:@"usesAlternateBackground"]];
219}
220
221
222//  #define PXBackgroundControllerSetBackground(bg, menu, configView, newBg)\
223//  {\
224//      [[bg configurator] removeFromSuperview];\
225//      [newBg retain];\
226//      [bg release];\
227//      bg = newBg;\
228//      [menu selectItemWithTitle:[bg name]];\
229//      [configView addSubview:[bg configurator]];\
230//  }
231
232
233- (void) _setMainBackground:(id) aBackground
234{
235	PXBackgroundControllerSetBackground(mainBackground, mainMenu, mainConfigurator, aBackground);
236	[delegate setMainBackground:mainBackground];
237}
238
239
240- (void) _setAlternateBackground:(id) aBackground
241{
242	PXBackgroundControllerSetBackground(alternateBackground, alternateMenu, alternateConfigurator, aBackground);
243	[delegate setAlternateBackground:alternateBackground];
244}
245
246@end
247
248
249/**********************************/
250/* NamePrompterDelegate categories*/
251/**********************************/
252
253@implementation PXBackgroundController ( NamePrompterDelegate )
254
255- (void)prompter:aPrompter didFinishWithName:name context:contextObject
256{
257	PXBackground * newConfig = [[contextObject copy] autorelease];
258	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
259	NSString *path;
260	if ( [paths count] == 0 )
261    {
262		NSLog(@"WARNING Use Library directory does not exists. Should never happens !!! WARM the user !!!");
263		return;
264    }
265	path = [paths objectAtIndex:0];
266
267	id menu = nil;
268
269	if(contextObject == mainBackground)
270    {
271		menu = mainMenu;
272    }
273	else if( contextObject == alternateBackground)
274    {
275		menu = alternateMenu;
276    }
277
278	[newConfig setName:name];
279#warning Put it in PXAppDelegate
280
281	path = [[paths objectAtIndex:0] stringByAppendingPathComponent:BACKGROUNDPRESET];
282	path = [path stringByAppendingPathComponent:name];
283	path = [path  stringByAppendingPathExtension:@"pxbgnd"];
284	NSLog(@"save FINISH path %@",path);
285
286	[NSKeyedArchiver archiveRootObject:newConfig toFile:path];
287
288	[self _populateMenus];
289
290	[menu selectItemWithTitle:name];
291	[self performSelector:[[menu itemWithTitle:name] action] withObject:[menu itemWithTitle:name]];
292}
293
294
295- (void)prompter:aPrompter didCancelWithContext:contextObject
296{
297	id config = contextObject;
298	id menu = nil;
299
300	if(config == mainBackground)
301		menu = mainMenu;
302	else if (config == alternateBackground)
303		menu = alternateMenu;
304
305	[menu selectItemWithTitle:[config name]];
306}
307
308@end
309
310
311
312
313
314/*******************************************/
315/*  PXBackgroundController implementation **/
316/*******************************************/
317
318@implementation PXBackgroundController
319
320+ backgroundNamed:aName
321{
322	id enumerator = [defaultBackgrounds() objectEnumerator];
323	id current;
324	NSString *path;
325	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
326
327
328	while( ( current = [enumerator nextObject] ) )
329	{
330		if([[current name] isEqualToString:aName])
331		{
332			return [[current copy] autorelease];
333		}
334	}
335
336	if ( [paths count] > 0 )
337	{
338		path = [paths objectAtIndex:0];
339		path = [path stringByAppendingPathComponent:BACKGROUNDPRESET];
340	}
341
342
343	enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
344
345	while(current = [enumerator nextObject])
346	{
347		// .DS_Store not exists into GNUstep -- ok, so it'll do nothing!  why was this a #warning?
348		if( ( ![current isEqualToString:@".DS_Store"] )
349			&& ( [[current stringByDeletingPathExtension] isEqualToString:aName] ) )
350		{
351			return [NSKeyedUnarchiver unarchiveObjectWithFile:[path stringByAppendingPathComponent:current]];
352		}
353	}
354
355	return [[[defaultBackgrounds() objectAtIndex:0] copy] autorelease];
356}
357
358
359-(id)  init
360{
361	if ( ! (self = [super init] ) )
362		return nil;
363
364	if ( ! [NSBundle loadNibNamed:@"PXBackgroundController" owner: self] )
365    {
366		NSLog(@"Warm user here");
367    }
368
369	return self;
370}
371
372
373
374- (void)dealloc
375{
376	if ( mainBackground )
377		[mainBackground release];
378	if ( alternateBackground )
379		[alternateBackground release];
380	//probably  mem leaks here
381	[super dealloc];
382}
383
384
385- (void)awakeFromNib
386{
387	usesAlternateBackground = YES;
388	namePrompter = [[PXNamePrompter alloc] init];
389	[namePrompter setDelegate:self];
390
391	[self _populateMenus];
392	[[NSNotificationCenter defaultCenter] addObserver:self
393											 selector:@selector(backgroundChanged:)
394												 name:@"PXBackgroundChanged"
395											   object:nil];
396}
397
398
399- (void)setDelegate:aDelegate
400{
401	delegate = aDelegate;
402}
403
404
405
406//
407//Actions methods
408//
409
410//Call from PopUp item saveCurrentConfiguration
411- (IBAction)saveCurrentConfiguration: (id) sender
412{
413	id context = nil;
414	id menu = nil;
415	if( [[mainMenu titleOfSelectedItem] isEqualToString:
416		NSLocalizedString(@"BACKGROUNDS_SAVE_AS", @"Backgrounds Save As")])
417    {
418		context = mainBackground;
419		menu = mainMenu;
420    }
421	else if( [[alternateMenu titleOfSelectedItem] isEqualToString:
422						  NSLocalizedString(@"BACKGROUNDS_SAVE_AS", @"Backgrounds Save As")])
423    {
424		context = alternateBackground;
425		menu = alternateMenu;
426    }
427
428	[namePrompter promptInWindow:panel context:context];
429}
430
431
432//Call from PopUp item deleteCurrentConfiguration
433- (IBAction)deleteCurrentConfiguration:(id) sender
434{
435	NSLog(@"deleteCurrentConfiguration");
436	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
437	NSString *path;
438	id config = nil;
439	id menu = nil;
440	if([[mainMenu titleOfSelectedItem] isEqualToString:NSLocalizedString(@"BACKGROUNDS_DELETE", @"Backgrounds Delete")])
441    {
442		menu = mainMenu;
443		config = mainBackground;
444		[self _setMainBackground:[defaultBackgrounds() objectAtIndex:0]];
445    }
446	else if([[alternateMenu titleOfSelectedItem] isEqualToString:NSLocalizedString(@"BACKGROUNDS_DELETE", @"Backgrounds Delete")])
447    {
448		config = alternateBackground;
449		menu = alternateMenu;
450		[self _setAlternateBackground:[ defaultBackgrounds() objectAtIndex:1]];
451    }
452
453	if(![config isKindOfClass:[PXBackground class]])
454    {
455		[menu selectItemAtIndex:0];
456		return;
457    }
458
459	if ( [paths count] == 0 )
460    {
461		NSLog(@"WARNING Use Library directory does not exists. Should never happens !!! WARM the user !!!");
462    }
463
464
465	path = [[paths objectAtIndex:0] stringByAppendingPathComponent:BACKGROUNDPRESET];
466	path = [path stringByAppendingPathComponent:[config name]];
467	path = [path  stringByAppendingPathExtension:@"pxbgnd"];
468
469	if(![[NSFileManager defaultManager] fileExistsAtPath:path])
470    {
471#ifdef __COCOA__
472		NSBeep();
473#endif
474		[menu selectItemAtIndex:0]; return;
475    }
476	[[NSFileManager defaultManager] removeFileAtPath:path handler:nil];
477	[self _populateMenus];
478}
479
480
481// checkBox  IBAction
482- (IBAction)useAlternateBackgroundCheckboxClicked:(id) sender
483{
484	[self _setUsesAlternateBackground:([sender state] == NSOnState)];
485}
486
487
488- (IBAction)selectMainBackground: (id) sender
489{
490
491	[self _setMainBackground:[sender representedObject]];
492#ifndef __COCOA__
493	// [mainMenu selectItemAtIndex: 2];
494#endif
495}
496
497- (IBAction)selectAlternateBackground: (id)sender
498{
499	[self _setAlternateBackground:[sender representedObject]];
500}
501
502
503//sender == NSButton "use these as defaults "
504- (IBAction)useCurrentBackgroundsAsDefaults:(id) sender
505{
506	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
507
508	[defaults setObject:[mainBackground name] forKey:@"mainBackgroundName"];
509	[defaults setObject:[alternateBackground name] forKey:@"alternateBackgroundName"];
510	[defaults setBool:usesAlternateBackground forKey:@"usesAlternateBackground"];
511
512	[defaults synchronize];
513}
514
515
516//Is it really need ?
517- (void)windowDidLoad
518{
519#warning is it really need
520
521	if ( mainBackground )
522		[mainConfigurator addSubview:[mainBackground configurator]];
523
524	if ( alternateBackground )
525		[alternateConfigurator addSubview:[alternateBackground configurator]];
526
527}
528
529- (void)backgroundChanged:notification
530{
531    [delegate backgroundChanged:notification];
532}
533
534
535- (void)useBackgroundsOf:(id) aCanvas
536{
537	//???
538	//   [self window];
539
540	if( ! [aCanvas mainBackgroundName] )
541    {
542		[self _setDefaultBackgroundsFor:aCanvas];
543		return;
544    }
545	NSString * mainName = [[aCanvas mainBackgroundName] retain], * altName = [[aCanvas alternateBackgroundName] retain];
546	[self _setMainBackground:[[self class] backgroundNamed:mainName]];
547	if((altName == nil) || [altName isEqualToString:mainName])
548    {
549		[self _setAlternateBackground:nil];
550		[self _setUsesAlternateBackground:NO];
551    }
552	else
553    {
554		[self _setAlternateBackground:[[self class] backgroundNamed:altName]];
555		[self _setUsesAlternateBackground:YES];
556    }
557	[mainName release];
558	[altName release];
559}
560
561//Accessor
562-(NSPanel *) backgroundPanel
563{
564	return panel;
565}
566
567@end
568
569