forked from cellularmitosis/ADC-reference-library-2009-july
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlisting2.html
executable file
·414 lines (351 loc) · 18.5 KB
/
listing2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<!-- BEGIN META TAG INFO -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="home" href="http://developer.apple.com/">
<link rel="find" href="http://developer.apple.com/search/">
<link rel="stylesheet" type="text/css" href="../../documentation/css/adcstyle.css" title="fonts">
<script language="JavaScript" src="../../documentation/js/adc.js" type="text/javascript"></script>
<!-- END META TAG INFO -->
<!-- BEGIN TITLE -->
<title>DeskPictAppDockMenu - /AppDelegate.m</title>
<!-- END TITLE -->
<script language="JavaScript">
function JumpToNewPage() {
window.location=document.scpopupmenu.gotop.value;
return true;
}
</script>
</head>
<!-- BEGIN BODY OPEN -->
<body>
<!--END BODY OPEN -->
<!-- START CENTER OPEN -->
<center>
<!-- END CENTER OPEN -->
<!-- BEGIN LOGO AND SEARCH -->
<!--#include virtual="/includes/adcnavbar"-->
<!-- END LOGO AND SEARCH -->
<!-- START BREADCRUMB -->
<div id="breadcrumb">
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td scope="row"><img width="340" height="10" src="images/1dot.gif" alt=""></td>
<td><img width="340" height="10" src="images/1dot.gif" alt=""></td>
</tr>
<tr valign="middle">
<td align="left" colspan="2">
<a href="http://developer.apple.com/">ADC Home</a> > <a href="../../referencelibrary/index.html">Reference Library</a> > <a href="../../samplecode/index.html">Sample Code</a> > <a href="../../samplecode/Cocoa/index.html">Cocoa</a> > <a href="../../samplecode/Cocoa/idxUserExperience-date.html">User Experience</a> > <A HREF="javascript:location.replace('index.html');">DeskPictAppDockMenu</A> >
</td>
</tr>
<tr>
<td colspan="2" scope="row"><img width="680" height="35" src="images/1dot.gif" alt=""></td>
</tr>
</table>
</div>
<!-- END BREADCRUMB -->
<!-- START MAIN CONTENT -->
<!-- START TITLE GRAPHIC AND INTRO-->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td><h1><div id="pagehead">DeskPictAppDockMenu</div></h1></td>
</tr>
</table>
<!-- END TITLE GRAPHIC AND INTRO -->
<!-- START WIDE COLUMN -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td id="scdetails">
<h2>/AppDelegate.m</h2>
<form name="scpopupmenu" onSubmit="return false;" method=post>
<p><strong>View Source Code:</strong>
<select name="gotop" onChange="JumpToNewPage();" style="width:340px"><option selected value="ingnore">Select File</option>
<option value="listing1.html">/AppDelegate.h</option>
<option value="listing2.html">/AppDelegate.m</option>
<option value="listing3.html">/DesktopPicture.m</option>
<option value="listing4.html">/main.m</option></select>
</p>
</form>
<p><strong><a href="DeskPictAppDockMenu.zip">Download Sample</a></strong> (“DeskPictAppDockMenu.zip”, 49.3K)<BR>
<strong><a href="DeskPictAppDockMenu.dmg">Download Sample</a></strong> (“DeskPictAppDockMenu.dmg”, 103.6K)</p>
<!--
<p><strong><a href="#">Download Sample</a></strong> (“filename.sit”, 500K)</p>
-->
</td>
</tr>
<tr>
<td scope="row"><img width="680" height="10" src="images/1dot.gif" alt=""><br>
<img height="1" width="680" src="images/1dot_919699.gif" alt=""><br>
<img width="680" height="20" src="images/1dot.gif" alt=""></td>
</tr>
<tr>
<td scope="row">
<!--googleon: index -->
<pre class="sourcecodebox">/*
File: AppDelegate.m
Description: This is the implementation for the main controller class. Most of the interesting work of this sample is done here.
Author: MCF
Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under Apple's
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Version History:
1.0 - 03/2002 Initial Release
*/
#import "AppDelegate.h"
#include <Carbon/Carbon.h>
// This sample shows how to have many dock menu items hooked up to one action method.
// Because of bug #2751274, on Mac OS X 10.1.x the sender for this action method when called from
// a dock menu item is always the NSApplication object, not the actual menu item. This ordinarily
// makes it impossible to take action based on which menu item was selected, because we don't know
// which menu item called our action method. We have a workaround
// in this sample for the bug (using NSInvocations), but we set up a #define here for the AppKit
// version that is fixed (in a future release of Mac OS X) so that the code can automatically switch
// over to doing things the right way when the time comes.
#define kFixedDockMenuAppKitVersion 632
extern OSErr SetDesktopPicture(NSString *picturePath,SInt32 pIndex);
@implementation AppDelegate
// We save out as a preference the path to the folder to search for pictures in,
// and so we want to register some default settings to use in case this is the first
// time we've ever run. +initialize will be called when the class initializes at program
// launch time, before any instances of AppDelegate are created.
+(void)initialize
{
NSMutableDictionary *dict;
NSUserDefaults *defaults;
defaults=[NSUserDefaults standardUserDefaults];
dict=[NSMutableDictionary dictionary];
// We pick the Pictures folder in the user's home directory as the default
// when DesktopPictureAppMenu is run for the first time - the pref set up here
// will be automatically overridden by anything saved out to a pref file from previous runs
[dict setObject:@"~/Pictures" forKey:@"picturesFolderPath"];
[defaults registerDefaults:dict];
}
// initialize some things
- (void) awakeFromNib
{
// setup the path to the folder to scan for pictures by checking what's been
// saved in preferences - if this is the first run of this app, the settings
// from +initialize (above) will be used automatically. Note that
// we expand "~" and follow symlinks when working with the path we saved by calling
// -stringByResolvingSymlinksInPath.
picturesFolderPath=[[[[NSUserDefaults standardUserDefaults] stringForKey:@"picturesFolderPath"] stringByResolvingSymlinksInPath] retain];
// create the appDockMenu and build it for the first time. We want to offload as much
// work as possible from the -applicationDockMenu routine, because that is the most timebound
// (the user is waiting to see their menu). Thus, we generate the menu initially here
// when the app first launches.
appDockMenu=[[NSMenu alloc] initWithTitle:@"DockMenu"];
// We want all menu items to be valid, and we can't rely on -validateMenuItem: being
// implemented on the target (if an NSInvocation is used, it won't be), so we turn
// off autoenabling so that we can just enable everything by fiat.
[appDockMenu setAutoenablesItems:NO];
[self buildMenu];
}
// Before we quit, we save out the picturesFolderPath in preferences again so it'll be there
// the next time
- (void)applicationWillTerminate:(NSNotification *)notification
{
[[NSUserDefaults standardUserDefaults] setObject:picturesFolderPath forKey:@"picturesFolderPath"];
}
// Respond to the user chosing the Preferences menu item by setting up and displaying our
// preferences panel
- (IBAction)preferences:(id)sender
{
[picturesFolderField setStringValue:picturesFolderPath];
[prefWin makeKeyAndOrderFront:nil];
}
// This action method is called when the user clicks the "Set Folder..." button in prefs
- (IBAction)pickPictureFolder:(id)sender
{
NSOpenPanel *op=[NSOpenPanel openPanel];
[op setCanChooseDirectories:YES];
[op setCanChooseFiles:NO];
// get a sheet going to let the user pick a folder to scan for pictures
[op beginSheetForDirectory:[picturesFolderField stringValue] file:NULL types:NULL modalForWindow:prefWin modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
// The picture folder selection sheet just went away, so let's setup the pictureFolderPath
// again
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[picturesFolderPath release];
picturesFolderPath=[[[sheet filenames] objectAtIndex:0] retain];
[picturesFolderField setStringValue:picturesFolderPath];
}
// This NSApplication delegate method is called when the user clicks and holds on the application
// icon in the dock. You can also instead use a static NSMenu in your nib and wire it up to the
// NSApplication object if your dock menu doesn't change, but if you need a dynamic dock menu,
// you'll need to implement this method. If at all possible, avoid calculating/creating the menu
// on the fly here (esp. if it'll be slow), because the user is waiting to see your menu.
// Have your menu sitting around and just return it unless you really need just-in-time content
// to be there.
- (NSMenu *)applicationDockMenu:(NSApplication *)sender
{
NSString *newModDate;
// The only time we want to actually go and recreate the menu of pictures here
// is if the folder we scan for pictures has changed (content or otherwise). So we
// do a quick mod date check.
newModDate=[[[NSFileManager defaultManager] fileAttributesAtPath:picturesFolderPath traverseLink:YES] objectForKey:NSFileModificationDate];
// If we're out of date with the folder, go rebuild the menu
if (![newModDate isEqual:picturesFolderModDate])
[self buildMenu];
return appDockMenu;
}
// This is the action method that will be called whenever one of our dock menu items is selected.
// The sender will be the menu item that was picked.
- (IBAction)menuSelected:(id)sender
{
OSErr err;
// We go set the desktop picture to the picture whose path we stored in the menu item's
// representedObject field.
err=SetDesktopPicture([sender representedObject],0);
if (err!=noErr)
NSLog(@"Failed to set the desktop picture!");
}
// This method is called when we actually have to go through and rebuild the dock menu.
// It can be fairly time consuming, so we try not to call it unless we really need to.
- (void)buildMenu
{
NSDirectoryEnumerator *picturesFolderEnum;
NSString *relativeFilePath,*fullPath;
// grab all picture formats NSImage knows about - we'll assume that if we can read them,
// we can set them to be the desktop picture
NSArray *imageFormats=[NSImage imageFileTypes];
// clear out old menu items first, since we're rebuilding the menu
int numItems = [appDockMenu numberOfItems];
while (numItems--)
{
// if we're running on a broken OS version, then we've been using NSInvocations
// to get around the sender-is-NSApplication bug and we need to go release them here
if (NSAppKitVersionNumber<kFixedDockMenuAppKitVersion)
[[[appDockMenu itemAtIndex: 0] target] release];
[appDockMenu removeItemAtIndex: 0];
}
if (picturesFolderModDate)
[picturesFolderModDate release];
// store off the modification date of the folder, so that if the user adds new pictures to it,
// changes the name of one of the pictures, or changes picture folders, we'll notice
picturesFolderModDate=[[[[NSFileManager defaultManager] fileAttributesAtPath:picturesFolderPath traverseLink:YES] objectForKey:NSFileModificationDate] retain];
// now we need to go scan the folder chosen, enumerating through to find all picture files
picturesFolderEnum=[[NSFileManager defaultManager] enumeratorAtPath:picturesFolderPath];
relativeFilePath=[picturesFolderEnum nextObject];
while (relativeFilePath)
{
fullPath=[NSString stringWithFormat:@"%@/%@",picturesFolderPath,relativeFilePath];
// If the file's extension or type matches a format that NSImage understands,
// then we're good to go, and we add a new menu item, using the display name
// (which may have a hidden extension) for the menu item's title and passing
// the full path to the picture to store with the menu item
if ([imageFormats containsObject:[relativeFilePath pathExtension]] ||
[imageFormats containsObject:NSHFSTypeOfFile(fullPath)])
[appDockMenu addItem:[self constructMenuItem:[[NSFileManager defaultManager] displayNameAtPath:fullPath] action:@selector(menuSelected:) realPath:fullPath]];
relativeFilePath=[picturesFolderEnum nextObject];
}
}
// This method constructs a new menu item for our dock menu, using NSInvocations if we're on
// an OS version that has broken Cocoa app dock menu support. An NSInvocation is basically
// a freeze-dried complete method call to a particular object, parameters and all, encapsulated into an object.
// Using NSInvocations allows us to set up the sender parameter to -menuSelected: to be the
// NSMenuItem as it should be.
- (NSMenuItem *)constructMenuItem:(NSString *)title action:(SEL)aSelector realPath:(NSString *)path
{
NSMenuItem *item;
// This is the "correct" way to create the menu items - this code is used if we're
// running on a fixed system
if (NSAppKitVersionNumber>=kFixedDockMenuAppKitVersion)
{
item=[[[NSMenuItem alloc] initWithTitle:title action:aSelector keyEquivalent:@""] autorelease];
[item setTarget:self];
// store the real path to the picture in the menu item so we can fetch it later
[item setRepresentedObject:path];
[item setEnabled:YES];
}
else //we're running on an OS version that isn't fixed; use NSInvocation
{
//This invocation is going to be of the form aSelector
NSInvocation *myInv=[NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:aSelector]];
item=[[[NSMenuItem alloc] initWithTitle:title action:@selector(invoke) keyEquivalent:@""] autorelease];
//This invocation is going to be an invocation of aSelector
[myInv setSelector:aSelector];
//This invocation is going to send its message to self
[myInv setTarget:self];
// The parameter to this invocation will be item, i.e. the NSMenuItem that should
// be the sender to -menuSelected: Note that we pass it at index 2 - indices 0 and 1
// are taken by the hidden arguments self and _cmd, accessible through -setTarget:
// and -setSelector:
[myInv setArgument:&item atIndex:2];
// here we retain the invocation so it won't go away. Later on we'll have to
// release it to avoid leaking
[item setTarget:[myInv retain]];
// store the real path to the picture in the menu item so we can fetch it later
[item setRepresentedObject:path];
[item setEnabled:YES];
}
return item;
}
@end
</pre>
<!--googleoff: index -->
</td>
</tr>
</table>
<!-- END WIDE COLUMN -->
<!-- END MAIN CONTENT -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td><div style="width: 100%; height: 1px; background-color: #919699; margin-top: 5px; margin-bottom: 15px"></div></td>
</tr>
<tr>
<td align="center"><br/>
<table border="0" cellpadding="0" cellspacing="0" class="graybox">
<tr>
<th>Did this document help you?</th>
</tr>
<tr>
<td>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=1&url=/samplecode/DeskPictAppDockMenu/listing2.html%3Fid%3DDTS10000389-1.0&media=dvd" target=_new>Yes</a>: Tell us what works for you.</div>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=2&url=/samplecode/DeskPictAppDockMenu/listing2.html%3Fid%3DDTS10000389-1.0&media=dvd" target=_new>It’s good, but:</a> Report typos, inaccuracies, and so forth.</div>
<div><a href="http://developer.apple.com/feedback/?v=3&url=/samplecode/DeskPictAppDockMenu/listing2.html%3Fid%3DDTS10000389-1.0&media=dvd" target=_new>It wasn’t helpful</a>: Tell us what would have helped.</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- START BOTTOM APPLE NAVIGATION -->
<!--#include virtual="/includes/footer"-->
<!-- END BOTTOM APPLE NAVIGATION -->
<!-- START CENTER CLOSE -->
</center>
<!-- END CENTER CLOSE -->
</body>
</html>