Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTPlayListWindowController.m

Parent Directory Parent Directory | Revision Log Revision Log


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

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