1 // Copyright (c) 2009 Yanagi Asakura
3 // This software is provided 'as-is', without any express or implied
4 // warranty. In no event will the authors be held liable for any damages
5 // arising from the use of this software.
7 // Permission is granted to anyone to use this software for any purpose,
8 // including commercial applications, and to alter it and redistribute it
9 // freely, subject to the following restrictions:
11 // 1. The origin of this software must not be misrepresented; you must not
12 // claim that you wrote the original software. If you use this software
13 // in a product, an acknowledgment in the product documentation would be
14 // appreciated but is not required.
16 // 2. Altered source versions must be plainly marked as such, and must not be
17 // misrepresented as being the original software.
19 // 3. This notice may not be removed or altered from any source
23 // ElisMediaBrowserController.m
26 // Created by 柳 on 09/09/17.
27 // Copyright 2009 __MyCompanyName__. All rights reserved.
30 #import "ElisMediaBrowserController.h"
32 /* openFiles is a simple C function that open an NSOpenPanel and return an array of selected filepath */
33 static NSArray *openFiles()
37 panel = [NSOpenPanel openPanel];
38 [panel setFloatingPanel:YES];
39 [panel setCanChooseDirectories:YES];
40 [panel setCanChooseFiles:YES];
41 [panel setAllowsMultipleSelection:YES];
42 int i = [panel runModalForTypes:nil];
44 return [panel filenames];
51 @implementation myImageObject
59 /* our datasource object is just a filepath representation */
60 - (void) setPath:(NSString *) path
66 - (void)setMoviePath:(NSString*)path
73 /* required methods of the IKImageBrowserItem protocol */
75 #pragma mark item data source protocol
77 /* let the image browser knows we use a path representation */
78 - (NSString *) imageRepresentationType
81 return IKImageBrowserQTMoviePathRepresentationType;
83 return IKImageBrowserQuickLookPathRepresentationType;
84 // return IKImageBrowserPathRepresentationType;
87 /* give our representation to the image browser */
88 - (id) imageRepresentation
93 /* use the absolute filepath as identifier */
94 - (NSString *) imageUID
99 - (NSString *)imageTitle
101 return [_path lastPathComponent];
109 @implementation ElisMediaBrowserController
114 [_importedImages release];
118 - (void) awakeFromNib
120 /* create two arrays : the first one is our datasource representation, the second one are temporary imported images (for thread safeness )
122 _images = [[NSMutableArray alloc] init];
123 _importedImages = [[NSMutableArray alloc] init];
124 _tempArray = [[NSMutableArray alloc] init];
126 //allow reordering, animations et set draggind destination delegate
127 [_mediaBrowser setAllowsReordering:YES];
128 [_mediaBrowser setAnimates:YES];
129 [_mediaBrowser setDraggingDestinationDelegate:self];
130 // [_mediaBrowser setBackgroundColor:[NSColor grayColor]];
132 lock = [[NSRecursiveLock alloc] init];
135 /* entry point for reloading image-browser's data and setNeedsDisplay */
136 - (void) updateDatasource
138 //-- update our datasource, add recently imported items
139 [_images addObjectsFromArray:_importedImages];
141 //-- empty our temporary array
142 [_importedImages removeAllObjects];
144 //-- reload the image browser and set needs display
145 [_mediaBrowser reloadData];
149 #pragma mark import images from file system
151 /* code that parse a repository and add all items in an independant array,
152 When done, call updateDatasource, add these items to our datasource array
153 This code is performed in an independant thread.
156 - (BOOL)canInitQT:(NSString*)path
158 canRead = [QTMovie canInitWithFile:path];
161 - (void) addAnImageWithPath:(NSString *) path
164 NSWorkspace* sharedWorkspace = [NSWorkspace sharedWorkspace];
169 if([sharedWorkspace type:[sharedWorkspace typeOfFile:path error:nil]
170 conformsToType:@"public.image"]) {
172 /* add a path to our temporary array */
173 CIImage* ci = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:path]];
174 if(ci == nil) return;
175 p = [[myImageObject alloc] init];
177 [_importedImages addObject:p];
181 [self performSelectorOnMainThread:@selector(canInitQT:) withObject:path waitUntilDone:YES];
184 // [sharedWorkspace type:[sharedWorkspace typeOfFile:path error:nil]
185 // conformsToType:@"public.movie"] ||
186 // [sharedWorkspace type:[sharedWorkspace typeOfFile:path error:nil]
187 // conformsToType:@"public.audio"] ||
188 // [sharedWorkspace type:[sharedWorkspace typeOfFile:path error:nil]
189 // conformsToType:@"com.apple.quartz-composer-composition"]
192 p = [[myImageObject alloc] init];
193 [p setMoviePath:path];
194 [_importedImages addObject:p];
199 - (void) addImagesWithPath:(NSString *) path recursive:(BOOL) recursive
204 [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&dir];
207 NSArray *content = [[NSFileManager defaultManager] directoryContentsAtPath:path];
211 /* parse the directory content*/
215 [self addImagesWithPath:[path stringByAppendingPathComponent:[content objectAtIndex:i]] recursive:YES];
217 [self addAnImageWithPath:[path stringByAppendingPathComponent:[content objectAtIndex:i]]];
221 [self addAnImageWithPath:path];
224 /* performed in an independant thread, parse all paths in "paths" and add these paths in our temporary array */
225 - (void) addImagesWithPaths:(NSArray *) paths
229 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
233 NSString *path = [paths objectAtIndex:i];
234 [self addImagesWithPath:path recursive:NO];
237 /* update the datasource in the main thread */
238 [self performSelectorOnMainThread:@selector(updateDatasource) withObject:nil waitUntilDone:YES];
240 _tempArray = [_images copy];
248 /* "add" button was clicked */
249 - (IBAction) addImageMenuClicked:(id) sender
251 NSArray *path = openFiles();
254 NSLog(@"No path selected, return...");
258 /* launch import in an independent thread */
259 [NSThread detachNewThreadSelector:@selector(addImagesWithPaths:) toTarget:self withObject:path];
262 /* action called when the zoom slider did change */
263 - (IBAction) zoomSliderDidChange:(id)sender
265 /* update the zoom value to scale images */
266 [_mediaBrowser setZoomValue:[sender floatValue]];
269 [_mediaBrowser setNeedsDisplay:YES];
273 #pragma mark IKImageBrowserDataSource
275 /* implement image-browser's datasource protocol
276 Our datasource representation is a simple mutable array
279 - (int) numberOfItemsInImageBrowser:(IKImageBrowserView *) view
281 /* item count to display is our datasource item count */
282 return [_images count];
285 - (id) imageBrowser:(IKImageBrowserView *) view itemAtIndex:(int) index
287 return [_images objectAtIndex:index];
290 /* implement some optional methods of the image-browser's datasource protocol to be able to remove and reoder items */
293 The user wants to delete images, so remove these entries from our datasource.
295 - (void) imageBrowser:(IKImageBrowserView *) view removeItemsAtIndexes: (NSIndexSet *) indexes
297 [_images removeObjectsAtIndexes:indexes];
301 The user wants to reorder images, update our datasource and the browser will reflect our changes
303 - (BOOL) imageBrowser:(IKImageBrowserView *) view moveItemsAtIndexes: (NSIndexSet *)indexes toIndex:(unsigned int)destinationIndex
306 NSMutableArray *temporaryArray;
308 temporaryArray = [[[NSMutableArray alloc] init] autorelease];
310 /* first remove items from the datasource and keep them in a temporary array */
311 for(index=[indexes lastIndex]; index != NSNotFound; index = [indexes indexLessThanIndex:index]){
312 if (index < destinationIndex)
315 id obj = [_images objectAtIndex:index];
316 [temporaryArray addObject:obj];
317 [_images removeObjectAtIndex:index];
320 /* then insert removed items at the good location */
321 int n = [temporaryArray count];
322 for(index=0; index < n; index++){
323 [_images insertObject:[temporaryArray objectAtIndex:index] atIndex:destinationIndex];
330 #pragma mark drag n drop
332 /* Drag'n drop support, accept any kind of drop */
333 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
335 return NSDragOperationCopy;
338 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
340 return NSDragOperationCopy;
343 - (BOOL) performDragOperation:(id <NSDraggingInfo>)sender
346 NSString *errorDescription;
348 NSPasteboard *pasteboard = [sender draggingPasteboard];
350 /* look for paths in pasteboard */
351 if ([[pasteboard types] containsObject:NSFilenamesPboardType])
352 data = [pasteboard dataForType:NSFilenamesPboardType];
355 /* retrieves paths */
356 NSArray *filenames = [NSPropertyListSerialization propertyListFromData:data
357 mutabilityOption:kCFPropertyListImmutable
359 errorDescription:&errorDescription];
362 /* add paths to our datasource */
364 int n = [filenames count];
366 [self addAnImageWithPath:[filenames objectAtIndex:i]];
369 /* make the image browser reload our datasource */
370 [self updateDatasource];
373 /* we accepted the drag operation */
377 - (IBAction)searchFieldUpdate:(id)sender
379 NSMutableArray* tempArray = [[NSMutableArray alloc] init];
380 NSString* searchString = [sender stringValue];
385 if([searchString length] == 0){
386 // _importedImages = _tempArray;
387 // [self updateDatasource];
388 _images = _tempArray;
389 [_mediaBrowser reloadData];
393 for(image in _tempArray){
394 r = [[image imageTitle] rangeOfString:searchString];
396 [_importedImages addObject:image];
399 [_images removeAllObjects];
400 _images = [_importedImages copy];
401 // [_importedImages removeAllObjects];
402 [_mediaBrowser reloadData];
403 // [self updateDatasource];