Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTPlayListWindowController.m

Parent Directory Parent Directory | Revision Log Revision Log


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

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