Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTPlayListWindowController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 126 - (hide annotations) (download)
Tue Sep 30 12:48:19 2008 UTC (15 years, 6 months ago) by masaki
File size: 8794 byte(s)
XspfQTThrowSpacebarKeyDownOutlineViewの名称をXspfQTPlaylistOutlineViewに変更。
1 masaki 2 //
2 masaki 72 // XspfQTPlayListWindowController.m
3 masaki 2 // XspfQT
4     //
5     // Created by Hori,Masaki on 08/08/31.
6     // Copyright 2008 masakih. All rights reserved.
7     //
8    
9 masaki 72 #import "XspfQTPlayListWindowController.h"
10     #import "XspfQTDocument.h"
11     #import "XspfQTComponent.h"
12 masaki 2
13    
14 masaki 72 @interface XspfQTPlayListWindowController(Private)
15 masaki 41 - (void)setObserveObject:(id)new;
16 masaki 96
17     - (void)insertItem:(id)item atIndex:(NSUInteger)index;
18     - (void)removeItem:(id)item;
19     - (void)moveItem:(id)item toIndex:(NSUInteger)index;
20     - (void)insertItemFromURL:(id)item atIndex:(NSUInteger)index;
21 masaki 41 @end
22    
23 masaki 72 @implementation XspfQTPlayListWindowController
24 masaki 2
25 masaki 111 #pragma mark ### Static variables ###
26 masaki 53 static NSString *const XspfQTPlayListItemType = @"XspfQTPlayListItemType";
27    
28 masaki 2 - (id)init
29     {
30 masaki 73 return [super initWithWindowNibName:@"XspfQTPlayList"];
31 masaki 2 }
32 masaki 111 - (void)dealloc
33     {
34     [trackListTree removeObserver:self forKeyPath:@"selection"];
35     [self setObserveObject:nil];
36    
37     [super dealloc];
38     }
39 masaki 2
40     - (void)awakeFromNib
41     {
42     [listView setDoubleAction:@selector(changeCurrentTrack:)];
43 masaki 41 [[self window] setReleasedWhenClosed:NO];
44    
45     [trackListTree addObserver:self
46     forKeyPath:@"selection"
47     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
48     context:NULL];
49     [self setObserveObject:[trackListTree valueForKeyPath:@"selection.self"]];
50 masaki 51
51     [listView expandItem:[listView itemAtRow:0]];
52 masaki 53
53 masaki 90 [listView registerForDraggedTypes:[NSArray arrayWithObjects:
54     XspfQTPlayListItemType,
55     NSFilenamesPboardType,
56     NSURLPboardType,
57     nil]];
58 masaki 2 }
59    
60 masaki 111 #pragma mark ### Actions ###
61 masaki 2 - (IBAction)changeCurrentTrack:(id)sender
62     {
63     id selections = [trackListTree selectedObjects];
64     if([selections count] == 0) return;
65    
66     NSIndexPath *selectionIndexPath = [trackListTree selectionIndexPath];
67    
68     if([selectionIndexPath length] > 1) {
69     [[self document] setPlayTrackindex:[selectionIndexPath indexAtPosition:1]];
70     }
71     }
72 masaki 84 - (IBAction)delete:(id)sender
73     {
74     id selection = [trackListTree valueForKeyPath:@"selection.self"];
75 masaki 96 [self removeItem:selection];
76 masaki 84 }
77 masaki 34 - (void)keyDown:(NSEvent *)theEvent
78     {
79     if([theEvent isARepeat]) return;
80    
81     unsigned short code = [theEvent keyCode];
82     if(code == 49 /* space bar */) {
83     [[self document] togglePlayAndPause:self];
84     }
85 masaki 83 if(code == 51 /* delete key */) {
86 masaki 84 [self delete:self];
87 masaki 83 }
88 masaki 34 }
89    
90 masaki 84 #pragma mark ### NSMenu valivation ###
91     - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
92     {
93     if([menuItem action] == @selector(delete:)) {
94     if([[trackListTree selectedObjects] count] == 0) {
95     return NO;
96     }
97     if(![[trackListTree valueForKeyPath:@"selection.isLeaf"] boolValue]) {
98     return NO;
99     }
100     }
101    
102     return YES;
103     }
104    
105 masaki 111 #pragma mark ### NSWindow Delegate ###
106 masaki 2 - (BOOL)windowShouldClose:(id)sender
107     {
108     [sender orderOut:self];
109    
110     return NO;
111     }
112 masaki 111
113     #pragma mark ### KVO & KVC ###
114 masaki 41 - (void)setObserveObject:(id)new
115     {
116 masaki 111 if(observedObject == new) return;
117 masaki 41
118 masaki 111 [observedObject removeObserver:self forKeyPath:@"title"];
119 masaki 41
120 masaki 111 observedObject = new;
121     [observedObject addObserver:self
122 masaki 41 forKeyPath:@"title"
123     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
124     context:NULL];
125     }
126     - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
127     {
128 masaki 49 if([keyPath isEqualToString:@"selection"]) {
129 masaki 41 id new = [object valueForKeyPath:@"selection.self"];
130     [self setObserveObject:new];
131     }
132    
133 masaki 49 if([keyPath isEqualToString:@"title"]) {
134 masaki 41 id new = [change objectForKey:NSKeyValueChangeNewKey];
135     id old = [change objectForKey:NSKeyValueChangeOldKey];
136    
137     if(new == old) return;
138     if([new isEqualTo:old]) return;
139    
140     id um = [[self document] undoManager];
141 masaki 111 [um registerUndoWithTarget:observedObject
142 masaki 41 selector:@selector(setTitle:)
143     object:old];
144     }
145     }
146 masaki 2
147 masaki 111 #pragma mark ### DataStructure Operations ###
148 masaki 96 - (void)insertItemFromURL:(id)item atIndex:(NSUInteger)index
149     {
150     id doc = [self document];
151     [doc insertComponentFromURL:item atIndex:index];
152     [[doc undoManager] setActionName:NSLocalizedString(@"Insert Movie", @"Undo Action Name Insert Movie")];
153     }
154     - (void)insertItem:(id)item atIndex:(NSUInteger)index
155     {
156     id doc = [self document];
157     [doc insertComponent:item atIndex:index];
158     [[doc undoManager] setActionName:NSLocalizedString(@"Insert Movie", @"Undo Action Name Insert Movie")];
159     }
160     - (void)removeItem:(id)item
161     {
162     id doc = [self document];
163     [doc removeComponent:item];
164     [[doc undoManager] setActionName:NSLocalizedString(@"Remove Movie", @"Undo Action Name Remove Movie")];
165     }
166     - (void)moveItem:(id)item toIndex:(NSUInteger)index
167     {
168     id doc = [self document];
169     [doc removeComponent:item];
170     [doc insertComponent:item atIndex:index];
171     [[doc undoManager] setActionName:NSLocalizedString(@"Move Movie", @"Undo Action Name Move Movie")];
172     }
173    
174 masaki 90 - (void)insertItemURL:(NSURL *)url atIndex:(NSUInteger)index
175     {
176     if(![QTMovie canInitWithURL:url]) {
177     @throw self;
178     }
179    
180     // NSLog(@"URL is %@", url);
181     @try {
182 masaki 96 [self insertItemFromURL:url atIndex:index];
183 masaki 90 }
184     @catch(XspfQTDocument *doc) {
185     @throw self;
186     }
187     }
188     - (BOOL)canInsertItemFromPasteboard:(NSPasteboard *)pb
189     {
190     if([[pb types] containsObject:NSFilenamesPboardType] ||
191     [[pb types] containsObject:NSURLPboardType]) {
192    
193     // ##### Check is playable. #####
194     if([QTMovie canInitWithPasteboard:pb]) {
195     return YES;
196     }
197     }
198    
199     return NO;
200     }
201     - (void)insertItemFromPasteboard:(NSPasteboard *)pb atIndex:(NSUInteger)index
202     {
203     // check filenames.
204     if([[pb types] containsObject:NSFilenamesPboardType]) {
205     BOOL hasSuccesItem = NO;
206    
207     id plist = [pb propertyListForType:NSFilenamesPboardType];
208     if(![plist isKindOfClass:[NSArray class]]) {
209     @throw self;
210     }
211     NSEnumerator *reverse = [plist reverseObjectEnumerator];
212     for(id obj in reverse) {
213     NSURL *fileURL = [NSURL fileURLWithPath:obj];
214     @try {
215     [self insertItemURL:fileURL atIndex:index];
216     }
217     @catch(XspfQTPlayListWindowController *me) {
218     continue;
219     }
220     hasSuccesItem = YES;
221     }
222    
223     if(!hasSuccesItem) {
224     @throw self;
225     }
226     return;
227     }
228    
229     // check URL
230     if([[pb types] containsObject:NSURLPboardType]) {
231     id url = [NSURL URLFromPasteboard:pb];
232     if(url) {
233     [self insertItemURL:url atIndex:index];
234     return;
235     }
236     }
237    
238     @throw self;
239     }
240 masaki 53
241 masaki 111 #pragma mark ### NSOutlineView DataSource ###
242 masaki 53 - (BOOL)outlineView:(NSOutlineView *)outlineView
243     writeItems:(NSArray *)items
244     toPasteboard:(NSPasteboard *)pasteboard
245     {
246     if([items count] > 1) return NO;
247    
248     id item = [[items objectAtIndex:0] representedObject];
249    
250 masaki 72 if(![item isKindOfClass:[XspfQTComponent class]]) {
251 masaki 53 NSLog(@"Ouch! %@", NSStringFromClass([item class]));
252     return NO;
253     }
254     if(![item isLeaf]) return NO;
255    
256     NSData *data = [NSKeyedArchiver archivedDataWithRootObject:item];
257     if(!data) {
258     NSLog(@"Could not archive.");
259     return NO;
260     }
261    
262     [pasteboard declareTypes:[NSArray arrayWithObject:XspfQTPlayListItemType]
263     owner:self];
264     [pasteboard setData:data
265     forType:XspfQTPlayListItemType];
266     return YES;
267     }
268     - (NSDragOperation)outlineView:(NSOutlineView *)outlineView
269     validateDrop:(id <NSDraggingInfo>)info
270     proposedItem:(id)item
271     proposedChildIndex:(NSInteger)index
272     {
273     if([item isLeaf]) {
274     return NSDragOperationNone;
275     }
276    
277     id pb = [info draggingPasteboard];
278    
279     if(![[pb types] containsObject:XspfQTPlayListItemType]) {
280 masaki 88 // ##### insert files? #####
281 masaki 90 if([self canInsertItemFromPasteboard:pb]) {
282     return NSDragOperationCopy;
283     }
284 masaki 53 return NSDragOperationNone;
285     }
286    
287 masaki 80 if(index == -1) return NSDragOperationNone;
288    
289 masaki 53 return NSDragOperationMove;
290     }
291     - (BOOL)outlineView:(NSOutlineView *)outlineView
292     acceptDrop:(id <NSDraggingInfo>)info
293     item:(id)item
294     childIndex:(NSInteger)index
295     {
296     if([item isLeaf]) {
297     return NO;
298     }
299    
300 masaki 98 if(index == -1) {
301     index = [[[self document] trackList] childrenCount];
302     }
303    
304 masaki 53 id pb = [info draggingPasteboard];
305    
306     NSData *data = [pb dataForType:XspfQTPlayListItemType];
307 masaki 88 if(!data) {
308 masaki 90 // ##### insert files? #####
309     @try {
310     [self insertItemFromPasteboard:pb atIndex:index];
311     }
312     @catch(XspfQTPlayListWindowController *me) {
313     return NO;
314     }
315     return YES;
316 masaki 88 }
317 masaki 53
318     id newItem = [NSKeyedUnarchiver unarchiveObjectWithData:data];
319     if(!newItem) return NO;
320    
321 masaki 80 id doc = [self document];
322     NSInteger oldIndex = [[doc trackList] indexOfChild:newItem];
323 masaki 53
324 masaki 88 if(oldIndex == NSNotFound) {
325     // from other list.
326 masaki 96 [self insertItem:newItem atIndex:index];
327 masaki 88 return YES;
328     }
329    
330 masaki 80 if(oldIndex == index) return YES;
331     if(oldIndex < index) {
332     index--;
333     }
334    
335     // change archive to original.
336     newItem = [[doc trackList] childAtIndex:oldIndex];
337    
338     BOOL mustSelectionChange = NO;
339     if([newItem isSelected]) {
340     mustSelectionChange = YES;
341     }
342    
343 masaki 96 [self moveItem:newItem toIndex:index];
344 masaki 80
345     if(mustSelectionChange) {
346     [doc setPlayTrackindex:index];
347     }
348    
349 masaki 59 return YES;
350 masaki 53 }
351    
352 masaki 2 @end
353 masaki 34
354 masaki 126 @implementation XspfQTPlaylistOutlineView
355 masaki 34 - (void)keyDown:(NSEvent *)theEvent
356     {
357 masaki 83 if(_delegate && [_delegate respondsToSelector:@selector(keyDown:)]) {
358     [_delegate keyDown:theEvent];
359 masaki 34 }
360    
361     [super keyDown:theEvent];
362     }
363     @end

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26