1//
2//  PXAppDelegate.m
3//  Pixen-XCode
4//
5// Copyright (c) 2003,2004 Open Sword Group
6
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use,copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11//  of the Software, and to permit persons to whom the Software is furnished to
12// do so, subject to the following conditions:
13
14// The above copyright notice and this permission notice shall be included in all copies
15// or substantial portions of the Software.
16
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
18// BUT NOT LIMITED TO THE WARRANTIES
19// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
20// OR COPYRIGHT HOLDERS
21// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22// ARISING FROM,  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24//  Author : Andy Matuschak
25//  Created  on Tue Dec 09 2003.
26
27
28
29
30//This class is the application delegate.
31//it respond as delegate for  applicationShouldOpenUntitledFile: applicationDidFinishLaunching: applicationWillTerminate:
32//methods (see NSApplication documentation)
33// it also responds to message from menu (only menu ??)
34// TODO : finish that
35
36#import "PXAppDelegate.h"
37
38#import "PXAboutController.h"
39#import "PXWelcomeController.h"
40#import "PXPreferencesController.h"
41#import "PXUserWarmer.h"
42
43#import <Foundation/NSFileManager.h>
44#import <AppKit/NSAlert.h>
45
46extern BOOL isTiling;
47
48/***********************************/
49/******** Private method ***********/
50/***********************************/
51
52@interface PXAppDelegate (Private)
53//Call from applicationDidFinishLaunching:
54- (void) _checkForUncleanCrash;
55- (void) _createApplicationSupportSubdirectories;
56@end
57
58@implementation PXAppDelegate (Private)
59
60- (void) _checkForUncleanCrash
61{
62	NSArray *dirtyFiles = [[[[NSUserDefaults standardUserDefaults] objectForKey:@"PXDirtyFiles"] copy] autorelease];
63
64	if ( (! dirtyFiles )  || [dirtyFiles count] < 1)
65		return;
66	else
67    {
68		[[NSUserDefaults standardUserDefaults] setObject:[NSArray array] forKey:@"PXDirtyFiles"];
69		NSEnumerator *dirtyFileEnumerator = [dirtyFiles objectEnumerator];
70		NSString *dirtyFile;
71
72		while ( ( dirtyFile = [dirtyFileEnumerator nextObject] ) ) {
73			if ([[NSFileManager defaultManager] fileExistsAtPath:dirtyFile]) {
74				id document = [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile:dirtyFile
75																									  display:YES];
76				[document setFileName:nil];
77				[[NSFileManager defaultManager] removeFileAtPath:dirtyFile handler:nil];
78			}
79		}
80
81		[[NSAlert alertWithMessageText:NSLocalizedString(@"CRASH_RECOVERY", @"Crash Recover")
82						 defaultButton:@"OK"
83					   alternateButton:nil
84						   otherButton:nil
85			 informativeTextWithFormat:NSLocalizedString(@"CRASH_TEXT", @"Crash Text")] runModal];
86    }
87}
88
89//TODO Create Subdirectories for colors too
90
91- (void) _createApplicationSupportSubdirectory:(NSString *)sub inDirectory:(NSString *)root
92{
93	NSFileManager *fileManager = [NSFileManager defaultManager];
94	BOOL isDir;
95	NSString *path = [root stringByAppendingPathComponent:sub];
96	if  ( ! [fileManager fileExistsAtPath:path isDirectory:&isDir] )
97    {
98		if ( ! [fileManager createDirectoryAtPath:path attributes:nil] )
99		{
100			[PXUserWarmer warmTheUser:@"I couldn't create a directory in your library or application support directory!  That's kind of... not good.  Please adjust permissions or something."]; // localize?
101			return;
102		}
103    }
104	else
105    {
106		if ( ! isDir )
107		{
108			[PXUserWarmer warmTheUser:[NSString stringWithFormat:@"Um, there's a file named %@ in %@... were you trying to make me crash, or what?", sub, root]]; // localize?
109			return;
110		}
111    }
112}
113
114- (void) _createApplicationSupportSubdirectories
115{
116	//Check the Library user path
117	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
118	NSFileManager *fileManager = [NSFileManager defaultManager];
119	BOOL isDir;
120	NSString *path;
121
122	if (  [paths count] == 0 )
123    {
124		[PXUserWarmer warmTheUser:@"The Library directory does not exist.  This is highly irregular.  Get thee to your nearest Apple retailer and demand a refund!"]; // localize?
125		return;
126    }
127	path = [paths objectAtIndex:0];
128	//Application Support
129#ifdef __COCOA__
130	path = [path stringByAppendingPathComponent: @"Application Support"];
131
132	if ( ( ! [fileManager fileExistsAtPath:path isDirectory:&isDir] )
133		 || ( ! isDir ) )
134    {
135		[PXUserWarmer warmTheUser:@"There's no Application Support directory!  That blows and sucks, at the same time!"]; // localize?
136		return;
137    }
138#endif
139	[self _createApplicationSupportSubdirectory:@"Pixen" inDirectory:path];                            // ./Pixen
140	path = [path stringByAppendingPathComponent:@"Pixen"];
141	[self _createApplicationSupportSubdirectory:@"Backgrounds" inDirectory:path];                      // ./Pixen/Backgrounds
142	[self _createApplicationSupportSubdirectory:@"Presets"
143									inDirectory:[path stringByAppendingPathComponent:@"Backgrounds"]]; // ./Pixen/Backgrounds/Presets
144	[self _createApplicationSupportSubdirectory:@"Palettes" inDirectory:path];                         // ./Pixen/Palettes
145	[self _createApplicationSupportSubdirectory:@"Presets"
146									inDirectory:[path stringByAppendingPathComponent:@"Palettes"]];    // ./Pixen/Palettes/Presets
147}
148@end
149
150
151@implementation PXAppDelegate
152
153//
154// Delegate methods
155//
156- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
157{
158	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
159
160	//Create some directories needs to store backgrounds and Colors
161	[self _createApplicationSupportSubdirectories];
162
163
164	//init all palettes
165	toolPaletteController = [PXToolPaletteController sharedToolPaletteController];
166	colorPaletteController = [PXColorPaletteController sharedPaletteController];
167	leftToolPropertiesController = [PXToolPropertiesController leftToolPropertiesController];
168	rightToolPropertiesController = [PXToolPropertiesController rightToolPropertiesController];
169	infoPanelController = [PXInfoPanelController sharedInfoPanelController];
170
171	// Open some panels if the user have let them open the last time
172	if ( [defaults boolForKey:@"PXLeftToolPropertiesIsOpen"] ) {
173		[[leftToolPropertiesController propertiesPanel] makeKeyAndOrderFront:self];
174	}
175	if ( [defaults boolForKey:@"PXRightToolPropertiesIsOpen"] ) {
176		[[rightToolPropertiesController propertiesPanel] makeKeyAndOrderFront:self];
177	}
178
179	if ( [defaults boolForKey:@"PXInfoPanelIsOpen"] )
180		[[infoPanelController infoPanel] makeKeyAndOrderFront:self];
181
182	if (  [defaults boolForKey:@"PXColorPaletteIsOpen"] )
183		[[colorPaletteController palettePanel] makeKeyAndOrderFront:self];
184
185	//Always display toolPanel
186	[[toolPaletteController toolPanel] display];
187	// Please keep this line AFTER the tool properties' creation, so everything will update properly.
188
189	[self  _checkForUncleanCrash];
190
191	//If it is the first time Pixen run launch the welcome Panel
192	//TODO (could be cleaner) : Fabien
193	if (! [defaults boolForKey:@"PXHasRunBefore"] )
194    {
195		id welcome = [[PXWelcomeController alloc] init];
196
197		isTiling = NO;
198		[defaults setBool:NO forKey:@"PXShouldTile"];
199		[defaults setBool:YES forKey:@"UKUpdateCheckerCheckAtStartup"];
200		[defaults setInteger:120 forKey:@"PXAutosaveInterval"];
201		[defaults setBool:YES forKey:@"PXInfoPanelIsOpen"];
202		[defaults setBool:YES forKey:@"PXHasRunBefore"];
203		[welcome showWindow:self];
204    }
205
206
207}
208
209- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
210{
211	return NO;
212}
213
214- (void)applicationWillTerminate:(NSNotification *)aNotification
215{
216	if ( [[leftToolPropertiesController propertiesPanel] isVisible] )
217		[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PXLeftToolPropertiesIsOpen"];
218	else
219		[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"PXLeftToolPropertiesIsOpen"];
220
221	if ( [[rightToolPropertiesController propertiesPanel] isVisible] )
222		[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PXRightToolPropertiesIsOpen"];
223	else
224		[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"PXRightToolPropertiesIsOpen"];
225
226	if ( [[infoPanelController infoPanel] isVisible] )
227		[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PXInfoPanelIsOpen"];
228	else
229		[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"PXInfoPanelIsOpen"];
230
231	if ( [[colorPaletteController palettePanel] isVisible] )
232		[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PXColorPaletteIsOpen"];
233	else
234		[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"PXColorPaletteIsOpen"];
235
236	[[NSUserDefaults standardUserDefaults] synchronize];
237}
238
239
240//
241// Actions methods
242//
243- (void)showAboutPanel:(id) sender
244{
245	[[PXAboutController sharedAboutController] showPanel:self];
246}
247
248- (IBAction)donate:(id) sender
249{
250	[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.opensword.org/donate.php"]];
251}
252
253- (IBAction)showLeftToolProperties:(id) sender;
254{
255	[[leftToolPropertiesController  propertiesPanel] makeKeyAndOrderFront:self];
256}
257
258- (IBAction)showRightToolProperties:(id) sender;
259{
260	[[rightToolPropertiesController  propertiesPanel] makeKeyAndOrderFront:self];
261}
262
263- (IBAction)showColorPalette:(id) sender
264{
265	[[colorPaletteController palettePanel] makeKeyAndOrderFront:self];
266}
267
268- (IBAction)showPreferences:(id) sender
269{
270	[[PXPreferencesController sharedPreferencesController] showWindow:self];
271}
272
273- (IBAction)showInfoPanel:(id) sender
274{
275	[[[PXInfoPanelController sharedInfoPanelController] infoPanel] makeKeyAndOrderFront:self];
276}
277
278//BUG : Could be call twice ! Should be a singleton (Fabien)
279- (IBAction)discoverPixen:(id) sender
280{
281	id welcome = [[PXWelcomeController alloc] init];
282	[welcome showWindow:self];
283}
284
285@end
286
287