标签:des style io color ar os 使用 sp for
在MAC应用里显示多个图片(IKImageBrowserView控件使用)
在MAC应用里显示多个图片
本文参考的是:ImageViewer.v1.0.zip 从网络下载,并且做了少量整理。
原理:
1.使用的技术是:IKImageBrowserView 这个控件,可以在Object library里面找到
2.然后写一个继承类,就可以使用了。
步骤:从Object Library里面找到IKImageBrowserView这个控件
然后,拖动倒窗口中,也可以放在视图里面
3.然后开始给这个控件绑定数据源DataSource和数据委托类Delegate
4.然后给控件设置变量
5.然后给控件设置图片所在文件夹路径,这样就可以显示文件夹里面的所有图片了。
代码如下:
1。需要一个工具包 Utils文件夹里面的所有类,没有修改
2。需要ImageBrowserView这个文件夹里面的所有文件
并且做了少量修改。
主要是针对标题,当得到图片后,再后期修改。
==========
// FileUtils.h
#import <Cocoa/Cocoa.h>
/**
This class is responsible for interacting with the filesystem. It‘s meant
to be instanciated through a XIB file (I use awakFromNib to initialize it)
*/
@interface FileUtils
: NSObject
{
@private
NSMutableArray * mCutItems;
NSMutableArray * mCopiedItems;
NSString * mDestinationDirectory;
}
@property (copy) NSString * destinationDirectory;
// init / deinit
-(void)awakeFromNib;
-(void)dealloc;
// global accessor
+(FileUtils *)instance;
// misc
+(BOOL)isImage:(NSString *)path;
+(BOOL)isGIF:(NSString *)path;
// delete / copy-cut / paste support
-(void)removeItemAtPath:(NSString *)path;
-(void)copyItems:(NSArray *)items;
-(void)cutItems:(NSArray *)items;
-(void)paste;
-(void)pasteTo:(NSString *)destination;
-(BOOL)canPaste;
-(void)setCanPaste:(BOOL)canPaste;
@end
========
// FileUtils.m
#import "FileUtils.h"
#import "Utils.h"
#import "SimpleProfiler.h"
//#import "../Preferences/Preferences.h"
@implementation FileUtils
static FileUtils * instance = nil;
@synthesize destinationDirectory = mDestinationDirectory;
-(void)awakeFromNib
{
instance = self;
mDestinationDirectory = nil;
mCutItems = [[NSMutableArray alloc] init];
mCopiedItems = [[NSMutableArray alloc] init];
}
-(void)dealloc
{
instance = nil;
[mCutItems release];
[mCopiedItems release];
[mDestinationDirectory release];
[super dealloc];
}
+(FileUtils *)instance
{
return instance;
}
+(BOOL)isImage:(NSString *)path
{
PROFILING_START(@"FileUtils - isImage");
NSString * extension = [[path pathExtension] lowercaseString];
if ([extension isEqualToString:@"jpg"] == YES ||
[extension isEqualToString:@"jpeg"] == YES ||
[extension isEqualToString:@"gif"] == YES ||
[extension isEqualToString:@"png"] == YES ||
[extension isEqualToString:@"psd"] == YES ||
[extension isEqualToString:@"tiff"] == YES ||
[extension isEqualToString:@"tif"] == YES ||
[extension isEqualToString:@"dng"] == YES ||
[extension isEqualToString:@"cr2"] == YES ||
[extension isEqualToString:@"raw"] == YES ||
[extension isEqualToString:@"pdf"] == YES)
{
PROFILING_STOP();
return YES;
}
PROFILING_STOP();
return NO;
}
+(BOOL)isGIF:(NSString *)path
{
NSString * extension = [[path pathExtension] lowercaseString];
return [extension isEqualToString:@"gif"];
}
-(void)removeItemAtPath:(NSString *)path
{
// check the preferences to see if we need to use the recycled bin, or
// permanently delete files
BOOL permanently = YES;
//[[Preferences instance] boolForKey:@"permanentlyDeleteFiles"];
if (permanently == YES)
{
NSFileManager * fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:path error:NULL];
}
else
{
NSInteger tag = 0;
NSString * source = [path stringByDeletingLastPathComponent];
NSArray * files = [NSArray arrayWithObject:[path lastPathComponent]];
NSWorkspace * workspace = [NSWorkspace sharedWorkspace];
[workspace performFileOperation:NSWorkspaceRecycleOperation
source:source
destination:nil
files:files
tag:&tag];
}
}
/**
Private method used to clear previously copied/cut items.
*/
-(void)clear
{
[mCopiedItems removeAllObjects];
[mCutItems removeAllObjects];
}
-(void)copyItems:(NSArray *)items
{
[self clear];
[mCopiedItems addObjectsFromArray:items];
[self setCanPaste:YES];
}
-(void)cutItems:(NSArray *)items
{
[self clear];
[mCutItems addObjectsFromArray:items];
[self setCanPaste:YES];
}
-(BOOL)canPaste
{
if ([mCutItems count] > 0 || [mCopiedItems count] > 0)
return YES;
return NO;
}
-(void)setCanPaste:(BOOL)canPaste
{
// this is just used for binding : when an item is added to the copy or
// cut list, we call [self setCanPaste:whatever] to notify binded objects.
}
-(void)paste
{
if (mDestinationDirectory != nil)
[self pasteTo:mDestinationDirectory];
}
-(void)pasteTo:(NSString *)destination
{
NSFileManager * fileManager = [NSFileManager defaultManager];
// handle cut files
for (NSURL * url in mCutItems)
{
// check if the destination folder is different from the source folder
if ([destination isEqualToString:[[url path] stringByDeletingLastPathComponent]])
continue;
NSURL * destinationURL = [NSURL fileURLWithPath:destination];
destinationURL = [destinationURL URLByAppendingPathComponent:[url lastPathComponent]];
// little hack : if the destination already exists, moving wont work,
// so I remove the destination before moving. This might be a bit
// "unsafe", but I don‘t want to bloat the code for something that will
// happen with a 0.000001% chance.
[fileManager removeItemAtURL:destinationURL error:nil];
[fileManager moveItemAtURL:url toURL:destinationURL error:nil];
}
// handle copied files
for (NSURL * url in mCopiedItems)
{
// check if the destination folder is different from the source folder
if ([destination isEqualToString:[[url path] stringByDeletingLastPathComponent]])
continue;
NSURL * destinationURL = [NSURL fileURLWithPath:destination];
destinationURL = [destinationURL URLByAppendingPathComponent:[url lastPathComponent]];
[fileManager copyItemAtURL:url toURL:destinationURL error:nil];
}
[self clear];
}
@end
====
// FSEventsListener.h
#import <Foundation/Foundation.h>
/**
This defines a little protocol which should be implemented by objects that
want to be notified of file changes (objects set as delegate of the
FSEventsListener class)
*/
@protocol FSEventListenerDelegate< NSObject >
@required
-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;
-(void)directoryWasAdded:(NSString *)directory;
-(void)directoryWasRemoved:(NSString *)directory;
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory;
@end
/**
This class is a little helper to create file system events listeners. It
allow to schedule event watching on a particular directory, and specify a
delegate which will be called on each supported event.
*/
@interface FSEventsListener
: NSObject
{
@private
NSDictionary * mListeners;
FSEventStreamRef mFileStream;
}
@property (assign) NSDictionary * listeners;
-(id)init;
-(void)dealloc;
// singleton handling
+(FSEventsListener *)instance;
+(void)destroy;
// handle listeners
-(void)addListener:(NSObject< FSEventListenerDelegate > *)listener forPath:(NSString *)path;
-(void)removeListener:(NSObject< FSEventListenerDelegate > *)listener forPath:(NSString *)path;
// utils
-(NSString *)formatPath:(NSString *)path;
// used to dispatch events to listeners
-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;
-(void)directoryWasAdded:(NSString *)directory;
-(void)directoryWasRemoved:(NSString *)directory;
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory;
@end
====
// FSEventsListener.m
#import "FSEventsListener.h"
#import "Utils.h"
#import "FileUtils.h"
void fsevents_callback(ConstFSEventStreamRef streamRef,
void * userData,
size_t numEvents,
void * eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[]);
@implementation FSEventsListener
static FSEventsListener * instance = nil;
@synthesize listeners = mListeners;
-(id)init
{
self = [super init];
if (self == nil)
return nil;
mListeners = [[NSMutableDictionary alloc] init];
// create the context that will be associated to the stream. We pass a
// pointer to the FSEventsListener instance as user data.
FSEventStreamContext context = { 0, (void *)self, NULL, NULL, NULL };
// create the event stream, with a flag telling that we want to watch file
// level events. This will allow to directly retrieve the file names in the
// callback, instead of just the name of the directory
mFileStream = FSEventStreamCreate(NULL,
&fsevents_callback,
&context,
(CFArrayRef)[NSArray arrayWithObject:@"/"],
kFSEventStreamEventIdSinceNow,
(CFAbsoluteTime)0.2,
kFSEventStreamCreateFlagFileEvents);
// start the stream on the main event loop
FSEventStreamScheduleWithRunLoop(mFileStream,
CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
FSEventStreamStart(mFileStream);
// init the globally accessible instance
instance = self;
return self;
}
-(void)dealloc
{
// clear the instance
instance = nil;
// stop and clean event stream
FSEventStreamStop(mFileStream);
FSEventStreamUnscheduleFromRunLoop(mFileStream,
CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
FSEventStreamInvalidate(mFileStream);
FSEventStreamRelease(mFileStream);
[mListeners release];
[super dealloc];
}
+(FSEventsListener *)instance
{
if (instance == nil)
{
[[FSEventsListener alloc] init];
}
return instance;
}
+(void)destroy
{
if (instance != nil)
{
[instance release];
instance = nil;
}
}
/**
ensure pathes are always formated the same way : except for the root ‘/‘
path, every path must NOT end with a trailing ‘/‘
*/
-(NSString *)formatPath:(NSString *)path
{
if ([path characterAtIndex:[path length] - 1] == ‘/‘)
{
return [path substringToIndex:[path length] - 1];
}
return [[path copy] autorelease];
}
-(void)addListener:(NSObject< FSEventListenerDelegate > *)listener forPath:(NSString *)path
{
NSString * formatedPath = [self formatPath:path];
NSMutableArray * listeners = [mListeners objectForKey:formatedPath];
if (listeners == nil)
{
[mListeners setValue:[NSMutableArray arrayWithObject:listener] forKey:formatedPath];
}
else
{
[listeners addObject:listener];
}
}
-(void)removeListener:(NSObject< FSEventListenerDelegate > *)listener forPath:(NSString *)path
{
NSString * formatedPath = [self formatPath:path];
NSMutableArray * listeners = [mListeners objectForKey:formatedPath];
if (listeners != nil)
{
[listeners removeObject:listener];
}
}
-(void)fileWasAdded:(NSString *)file
{
NSString * path = [file stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners objectForKey:path];
for (NSObject< FSEventListenerDelegate > * listener in listeners)
[listener fileWasAdded:file];
}
-(void)fileWasRemoved:(NSString *)file
{
NSString * path = [file stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners objectForKey:path];
for (NSObject< FSEventListenerDelegate > * listener in listeners)
[listener fileWasRemoved:file];
}
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile
{
NSString * path = [newFile stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners objectForKey:path];
for (NSObject< FSEventListenerDelegate > * listener in listeners)
[listener fileWasRenamed:oldFile to:newFile];
}
-(void)directoryWasAdded:(NSString *)directory
{
NSString * path = [directory stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners objectForKey:path];
for (NSObject< FSEventListenerDelegate > * listener in listeners)
[listener directoryWasAdded:directory];
}
-(void)directoryWasRemoved:(NSString *)directory
{
NSString * path = [directory stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners objectForKey:path];
for (NSObject< FSEventListenerDelegate > * listener in listeners)
[listener directoryWasRemoved:directory];
}
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory
{
NSString * path = [newDirectory stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners objectForKey:path];
for (NSObject< FSEventListenerDelegate > * listener in listeners)
[listener directoryWasRenamed:oldDirectory to:newDirectory];
}
@end
#define CHECK_STREAM(x, y) if (((x) & (y)) == (y)) NSLog(@" %s", #y);
void fsevents_callback(ConstFSEventStreamRef streamRef,
void * userData,
size_t numEvents,
void * eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
static NSString * previousRenamedPath = nil;
FSEventsListener * eventListener = (FSEventsListener *)userData;
size_t i;
char ** paths = eventPaths;
for (i = 0; i < numEvents; ++i)
{
NSString * newName = [NSString stringWithFormat:@"%s", paths[i]];
// first, we handle events WITHOUT the renamed flag. Those are simple
// event, like "created", "removed". Note that when a device is mounted,
// or unmounted, a corresponding "created" or "removed" event is
// triggered, so we don‘t need to handle mount/unmount event.
if ((eventFlags[i] & kFSEventStreamEventFlagItemRenamed) == 0)
{
if (eventFlags[i] & kFSEventStreamEventFlagItemRemoved)
{
// a file or directory was permanently deleted
//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)
if (eventFlags[i])
{
[eventListener fileWasRemoved:newName];
}
else if (eventFlags[i] & kFSEventStreamEventFlagItemIsDir)
{
[eventListener directoryWasRemoved:newName];
}
}
else if (eventFlags[i] & kFSEventStreamEventFlagItemCreated)
{
// a file or directory was copied/created
//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)
if (eventFlags[i])
{
[eventListener fileWasAdded:newName];
}
else if (eventFlags[i] & kFSEventStreamEventFlagItemIsDir)
{
[eventListener directoryWasAdded:newName];
}
}
}
else
{
// here, the "renamed" flag is present. From what I can guess
// through experiments, when a file is renamed, or moved, or sent
// to the trash, it triggers 2 successive renamed events. The first
// contains the source file, the second the destination file.
// So I just use a static string to store the first event path and
// detect if it‘s the first or second event.
if (previousRenamedPath == nil)
{
previousRenamedPath = [newName retain];
}
else
{
NSString * newDir = [newName stringByDeletingLastPathComponent];
NSString * oldName = previousRenamedPath;
NSString * oldDir = [oldName stringByDeletingLastPathComponent];
//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)
if (eventFlags[i])
{
if ([oldDir isEqualToString:newDir])
{
// both directory are the same : file renamed
[eventListener fileWasRenamed:oldName to:newName];
}
else
{
// directories are different, the file was moved
[eventListener fileWasAdded:newName];
[eventListener fileWasRemoved:oldName];
}
}
else if (eventFlags[i] & kFSEventStreamEventFlagItemIsDir)
{
if ([oldDir isEqualToString:newDir])
{
// both directory are the same : renamed
[eventListener directoryWasRenamed:oldName to:newName];
}
else
{
// directories are different, the directory was moved
[eventListener directoryWasAdded:newName];
[eventListener directoryWasRemoved:oldName];
}
}
// reset the previous renamed path.
SAFE_RELEASE(previousRenamedPath);
}
}
#if defined(DEBUG)
// NSLog(@"event [%d] [%d] [%s]", (int)eventIds[i], eventFlags[i], paths[i]);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagNone);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagMustScanSubDirs);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagUserDropped);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagKernelDropped);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagEventIdsWrapped);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagHistoryDone);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagRootChanged);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagMount);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagUnmount);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemCreated);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemRemoved);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemInodeMetaMod);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemRenamed);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemModified);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemFinderInfoMod);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemChangeOwner);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemXattrMod);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemIsFile);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemIsDir);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemIsSymlink);
#endif // _DEBUG
}
}
======
// SimpleProfiler.h
#import <Cocoa/Cocoa.h>
@class ProfilingEntry;
@interface SimpleProfiler
: NSObject
{
@private
NSMutableDictionary * mEntries;
}
+(SimpleProfiler *)instance;
+(void)destroyInstance;
-(id)init;
-(void)dealloc;
-(void)addEntry:(NSString *)name withTime:(double)time;
-(void)log;
@end
@interface ProfilingEntry
: NSObject
{
@private
NSString * mName;
NSMutableArray * mTimes;
}
@property (copy) NSString * name;
+(ProfilingEntry *)entryWithName:(NSString *)name;
-(id)init;
-(void)dealloc;
-(double)averageTime;
-(void)addTime:(double)time;
@end
#if defined(PROFILING)
# define PROFILING_START(name) \
NSString * __name = name; \
NSDate * __date = [NSDate date]
#else
# define PROFILING_START(name)
#endif
#if defined(PROFILING)
# define PROFILING_STOP() \
[[SimpleProfiler instance] addEntry:__name \
withTime:[[NSDate date] timeIntervalSinceDate:__date]]
#else
# define PROFILING_STOP()
#endif
======
// SimpleProfiler.m
#import "SimpleProfiler.h"
static SimpleProfiler * mSimpleProfilerInstance = nil;
@implementation SimpleProfiler
+(SimpleProfiler *)instance
{
if (mSimpleProfilerInstance == nil)
mSimpleProfilerInstance = [[SimpleProfiler alloc] init];
return mSimpleProfilerInstance;
}
+(void)destroyInstance
{
if (mSimpleProfilerInstance != nil)
{
[mSimpleProfilerInstance release];
mSimpleProfilerInstance = nil;
}
}
-(id)init
{
self = [super init];
if (self)
{
mEntries = [[NSMutableDictionary alloc] init];
}
return self;
}
-(void)dealloc
{
[mEntries removeAllObjects];
[mEntries release];
[super dealloc];
}
-(void)addEntry:(NSString *)name withTime:(double)time
{
ProfilingEntry * entry = nil;
entry = [mEntries objectForKey:name];
if (entry == nil)
{
entry = [ProfilingEntry entryWithName:name];
[mEntries setValue:entry forKey:name];
}
[entry addTime:time];
}
-(void)log
{
if ([mEntries count] == 0)
return;
NSLog(@"Profiling log");
for (ProfilingEntry * entry in [mEntries allValues])
{
NSLog(@"%@ -- %f", [entry name], [entry averageTime]);
}
}
@end
@implementation ProfilingEntry
@synthesize name = mName;
+(ProfilingEntry *)entryWithName:(NSString *)name
{
ProfilingEntry * entry = [[[ProfilingEntry alloc] init] autorelease];
[entry setName:name];
return entry;
}
-(id)init
{
self = [super init];
if (self)
{
mName = nil;
mTimes = [[NSMutableArray alloc] init];
}
return self;
}
-(void)dealloc
{
[mName release];
[mTimes release];
[super dealloc];
}
-(double)averageTime
{
double averageTime = 0.0;
for (NSNumber * number in mTimes)
{
averageTime += [number doubleValue];
}
return averageTime / (double)[mTimes count];
}
-(void)addTime:(double)time
{
[mTimes addObject:[NSNumber numberWithDouble:time]];
}
@end
====
//SlideShow.h
#import <Foundation/Foundation.h>
@interface SlideShow
: NSObject
{
}
+(void)startSlideShow:(NSObject *)target callback:(NSString *)callback;
+(void)stopSlideShow;
+(BOOL)isRunning;
@end
=====
// SlideShow.m
#import "SlideShow.h"
#import "Utils.h"
@implementation SlideShow
static NSTimer * slideshowTimer = nil;
+(void)startSlideShow:(NSObject *)target callback:(NSString *)callback
{
if (slideshowTimer != nil)
[SlideShow stopSlideShow];
// get the slideshow user preferences
NSUserDefaultsController * defaults = [NSUserDefaultsController sharedUserDefaultsController];
BOOL loop = [[[defaults values] valueForKey:@"slideshowLoop"] boolValue];
float interval = [[[defaults values] valueForKey:@"slideshowInterval"] floatValue];
// launch the slideshow. I use a simple NSTimer with scheduledTimerWithTimeInterval.
// This method creates the timer and automatically fire it after "interval" secondes.
slideshowTimer = [NSTimer scheduledTimerWithTimeInterval:interval
target:target
selector:NSSelectorFromString(callback)
userInfo:loop ? @"Y" : @"N"
repeats:YES];
[slideshowTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:interval]];
}
+(void)stopSlideShow
{
if (slideshowTimer != nil)
{
[slideshowTimer invalidate];
[slideshowTimer release];
slideshowTimer = nil;
}
}
+(BOOL)isRunning
{
return slideshowTimer == nil ? NO : YES;
}
@end
=====
//Utils.h
#import <AppKit/AppKit.h>
@interface Utils
: NSObject
{
}
+(void)bind:(id)src
keyPath:(NSString *)srcKey
to:(id)dest
keyPath:(id)destKey
continuous:(BOOL)continuous
twoWay:(BOOL)twoWay;
+(NSMutableParagraphStyle *)defaultParagraphStyle;
+(NSSize)stringSize:(NSString *)string withAttribute:(NSDictionary *)attributes;
@end
// Use this macro to output debug infos and strip them in release
#if defined(DEBUG)
# define DEBUG_LOG(...) NSLog(__VA_ARGS__)
#else
# define DEBUG_LOG(...)
#endif
// Use this macro to do something only in debug
#if defined(DEBUG)
# define DEBUG_ONLY(args) args
#else
# define DEBUG_ONLY(args)
#endif
// This macro is used when launching the ImageViewer from outside XCode :
// since we don‘t have access to the log, we need a way to debug
#if defined(DEBUG)
# define DEBUG_ALERT(...) \
{ \
NSAlert * __alert = [[[NSAlert alloc] init] autorelease]; \
[__alert setMessageText:[NSString stringWithFormat:__VA_ARGS__]]; \
[__alert runModal]; \
}
#else
# define DEBUG_ALERT(...)
#endif
// this macro is used to release an object and re-assign its value to nil, only
// if it‘s different from nil.
#if !defined(SAFE_RELEASE)
# define SAFE_RELEASE(x) if ((x) != nil) { [(x) release]; (x) = nil; }
#endif
=====
// Utils.m
#import "Utils.h"
@implementation Utils
+(void)bind:(id)src
keyPath:(NSString *)srcKey
to:(id)dest
keyPath:(id)destKey
continuous:(BOOL)continuous
twoWay:(BOOL)twoWay
{
NSMutableDictionary * options = nil;
if (continuous == YES)
{
options = [[NSMutableDictionary alloc] init];
[options setObject:[NSNumber numberWithBool:YES]
forKey:NSContinuouslyUpdatesValueBindingOption];
}
[src bind:srcKey toObject:dest withKeyPath:destKey options:options];
if (twoWay == YES)
[dest bind:destKey toObject:src withKeyPath:srcKey options:options];
[options release];
}
+(NSMutableParagraphStyle *)defaultParagraphStyle
{
return [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
}
+(NSSize)stringSize:(NSString *)string withAttribute:(NSDictionary *)attributes
{
NSAttributedString * attributedString = [NSAttributedString alloc];
attributedString = [attributedString initWithString:string];
NSSize size = [attributedString size];
[attributedString release];
return size;
}
@end
===========
以上是Utils里面的类,一共5个类,10个文件,大家拷贝后,分拆的时候不要忘记检查啊。
在文件夹ImageBrowserView里面有4个类,8个文件,总共18个文件。
以下是代码:
// ImageDataSource.h
#import <Cocoa/Cocoa.h>
#import "../Utils/FSEventsListener.h"
@class IKImageBrowserView;
@class ImageBrowser;
/**
This is the image data source. It‘s responsible for giving access to all
the images contained in a single folder.
*/
@interface ImageDataSource
: NSObject< FSEventListenerDelegate >
{
@private
/// the current directory. It‘s bound to the currently selected directory
NSString * mCurrentDirectory;
/// the associated view
ImageBrowser * mImageBrowser;
/// the images‘ paths.
NSMutableArray * mImages;
}
@property (assign) IBOutlet ImageBrowser * imageBrowser;
@property (readonly) NSArray * images;
@property (readwrite) BOOL isEmpty;
-(id)init;
-(void)dealloc;
// implementation of FSEventListenerDelegate protocol
-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;
-(void)directoryWasAdded:(NSString *)directory;
-(void)directoryWasRemoved:(NSString *)directory;
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory;
// this is used to bind the directory browser and the image data source
-(NSString *)currentDirectory;
-(void)setCurrentDirectory:(NSString *)path;
// these are internally used
-(void)addImage:(NSString *)path;
-(void)addImagesInPath:(NSString *)path;
// implementation of IKImageBrowserDataSource protocol
-(NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView *)view;
-(id)imageBrowser:(IKImageBrowserView *)view itemAtIndex:(NSUInteger)index;
// utility
-(NSInteger)indexOfImage:(NSString *)image;
-(NSArray *)imagesAtIndexes:(NSIndexSet *)indexes;
-(void)setImagesPhoneID;
-(void)setImagesPhonePath;
@end
=======
//ImageDataSource.m
#import <Quartz/Quartz.h>
#import "ImageDataSource.h"
#import "ImageItem.h"
#import "ImageBrowser.h"
#import "../Utils/FileUtils.h"
#import "../Utils/FSEventsListener.h"
#import "../Utils/Utils.h"
@implementation ImageDataSource
@synthesize imageBrowser = mImageBrowser;
@synthesize images = mImages;
@synthesize isEmpty;
-(id)init
{
self = [super init];
if (self != nil)
{
mCurrentDirectory = nil;
mImages = [[NSMutableArray alloc] init];
[self setIsEmpty:YES];
}
return self;
}
-(void)dealloc
{
[mCurrentDirectory release];
[mImages release];
[super dealloc];
}
-(NSString *)currentDirectory
{
return mCurrentDirectory;
}
-(void)setCurrentDirectory:(NSString *)path
{
if (path != mCurrentDirectory && path != nil)
{
// unregister from the event listeners
[[FSEventsListener instance] removeListener:self forPath:mCurrentDirectory];
// copy the new path
[mCurrentDirectory release];
mCurrentDirectory = [path copy];
// load images
[self setIsEmpty:YES];
[mImages removeAllObjects];
[self addImagesInPath:mCurrentDirectory];
[mImageBrowser reloadData];
// register with the new path
[[FSEventsListener instance] addListener:self forPath:mCurrentDirectory];
}
}
-(void)addImagesInPath:(NSString *)path
{
// get the content of the directory
NSFileManager * fileManager = [NSFileManager defaultManager];
NSURL * url = [NSURL fileURLWithPath:path];
NSArray * content = [fileManager contentsOfDirectoryAtURL:url
includingPropertiesForKeys:nil
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
// for each item, create an image object and add to the mImportedImages array
for (NSURL * url in content)
{
[self addImage:[url path]];
}
}
-(void)addImage:(NSString *)path
{
// error check
if ([FileUtils isImage:path] == NO)
return;
// add the image item
ImageItem * image = [[ImageItem alloc] init];
[image setPath:path];
[mImages addObject:image];
[image release];
[self setIsEmpty:NO];
}
-(void)setImagesPhoneID
{
int images_count = (int)[mImages count];
NSString *id_value=nil;
for (int i=0; i<images_count;i++)
{
ImageItem *image1 = [mImages objectAtIndex:i];
id_value = image1.title;
id_value = [id_value stringByDeletingPathExtension];
[image1 setPhoto_ID_OnPhone:id_value];
}
}
-(void)setImagesPhonePath
{
int images_count = (int)[mImages count];
NSString *id_value=nil;
for (int i=0; i<images_count;i++)
{
ImageItem *image1 = [mImages objectAtIndex:i];
id_value = [NSString stringWithFormat:@"AAA%d",i];
[image1 setPhoto_Path_OnPhone:id_value];
}
}
-(void)fileWasAdded:(NSString *)file
{
[self addImage:file];
[mImageBrowser reloadDataAndKeepSelection];
}
-(void)fileWasRemoved:(NSString *)file
{
NSInteger index = [self indexOfImage:file];
if (index == -1)
{
DEBUG_LOG(@"ImageDataSource - receive fileWasRemoved, "
@"but couldn‘t find the image [%@]", file);
return;
}
[mImages removeObjectAtIndex:index];
[mImageBrowser reloadDataAndKeepSelection];
[self setIsEmpty:[mImages count] > 0 ? NO : YES];
}
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile
{
NSInteger index = [self indexOfImage:oldFile];
if (index == -1)
{
// check if the newFile is an image, and if it‘s the case, add it.
if ([FileUtils isImage:newFile] == YES)
[self fileWasAdded:newFile];
return;
}
if ([FileUtils isImage:newFile] == YES)
{
ImageItem * image = [self imageBrowser:mImageBrowser itemAtIndex:index];
[image setPath:newFile];
[mImageBrowser reloadDataAndKeepSelection];
}
else
{
[self fileWasRemoved:oldFile];
}
}
-(void)directoryWasAdded:(NSString *)directory
{
}
-(void)directoryWasRemoved:(NSString *)directory
{
}
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory
{
}
-(NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView *)view
{
return [mImages count];
}
-(id)imageBrowser:(IKImageBrowserView *)view itemAtIndex:(NSUInteger)index
{
return [mImages objectAtIndex:index];
}
-(NSInteger)indexOfImage:(NSString *)image
{
NSInteger index = 0;
for (ImageItem * item in mImages)
{
if ([[item path] isEqualToString:image])
return index;
++index;
}
return -1;
}
-(NSArray *)imagesAtIndexes:(NSIndexSet *)indexes
{
NSMutableArray * images = [NSMutableArray arrayWithCapacity:[indexes count]];
NSUInteger index = [indexes firstIndex];
while (index != NSNotFound)
{
[images addObject:[self imageBrowser:nil itemAtIndex:index]];
index = [indexes indexGreaterThanIndex:index];
}
return images;
}
- (IBAction)OnBT_SetPahtAndShowImages:(id)sender
{
NSString *path = @"/Users/mac2/Documents/test_photo";
[self setCurrentDirectory:path];
[self OnBT_ChangeTitle:nil];
}
- (IBAction)OnBT_SetPath2:(id)sender
{
NSString *path = @"/Users/mac2/Documents/photo1";
[self setCurrentDirectory:path];
[self OnBT_ChangeTitle:nil];
}
- (IBAction)OnBT_Selected_All:(id)sender
{
[mImageBrowser selectAll:nil];
}
- (IBAction)OnBT_Selected_None:(id)sender
{
[mImageBrowser deselectAll:nil];
}
- (IBAction)OnBT_GetSelectedList:(id)sender
{
[self setImagesPhoneID];
[self setImagesPhonePath];
NSLog(@"===Path \n==");
NSArray *files_selected ;
files_selected = [mImageBrowser selectedImagesAsURLArray];
NSString *path=nil;
for (int i=0; i<files_selected.count; i++)
{
path = [files_selected objectAtIndex:i] ;
NSLog(@"\n(%d)%@\n",i+1,path);
}
NSLog(@"\n===Title \n==");
files_selected = [mImageBrowser selectedImagesAsTitelArray];
NSString *title=nil;
for (int i=0; i<files_selected.count; i++)
{
title = [files_selected objectAtIndex:i] ;
NSLog(@"\n(%d)%@\n",i+1,title);
}
NSLog(@"\n Photo ID On Phone \n");
files_selected = [mImageBrowser selectedImagesAsPhotoIDArray];
for (int i=0; i<files_selected.count; i++)
{
title = [files_selected objectAtIndex:i] ;
NSLog(@"\n(%d)%@\n",i+1,title);
}
NSLog(@"\n Photo Path On Phone \n");
files_selected = [mImageBrowser selectedImagesAsPhotoPathArray];
for (int i=0; i<files_selected.count; i++)
{
title = [files_selected objectAtIndex:i] ;
NSLog(@"\n(%d)%@\n",i+1,title);
}
}
- (IBAction)OnBT_ChangeTitle:(id)sender
{
[self setImagesPhoneID]; //OK
[self setImagesPhonePath];//OK
// change title
int images_count = (int)[mImages count];
NSString *id_value=nil;
for (int i=0; i<images_count;i++)
{
ImageItem *image1 = [mImages objectAtIndex:i];
id_value = image1.Photo_Path_OnPhone;
[image1 setTitle:id_value];
}
//refresh
[mImageBrowser reloadData];
}
@end
======
// ImageItem.h
#import <Cocoa/Cocoa.h>
/**
This class represents a single image.
*/
@interface ImageItem
: NSObject
{
@private
/// the path to the image file
NSString * mPath;
/// the title of the image. Usually the file name.
NSString * mTitle;
NSString *mPhoto_ID_OnPhone;
NSString *mPhoto_Path_OnPhone;
}
-(void)setPath:(NSString *)path;
-(NSString *)path;
-(void)setTitle:(NSString *)title;
-(NSString *)title;
-(NSString *)Photo_ID_OnPhone;
-(NSString *)Photo_Path_OnPhone;
-(void)setPhoto_ID_OnPhone:(NSString *)photo_id;
-(void)setPhoto_Path_OnPhone:(NSString *)photo_path;
// implementation of IKImageBrowserItem protocol
-(NSString *)imageRepresentationType;
-(id)imageRepresentation;
-(NSString *)imageUID;
-(NSString *)imageTitle;
@end
======
// ImageItem.m
#import "ImageItem.h"
#import <Quartz/Quartz.h>
@implementation ImageItem
-(void)dealloc
{
[mPath release];
[mTitle release];
[mPhoto_Path_OnPhone release];
[mPhoto_ID_OnPhone release];
[super dealloc];
}
-(void)setPath:(NSString *)path
{
if (mPath != path)
{
[mPath release];
[mTitle release];
mPath = [path retain];
mTitle = [[mPath lastPathComponent] copy];
}
}
-(NSString *)Photo_ID_OnPhone;
{
return mPhoto_ID_OnPhone;
}
-(NSString *)Photo_Path_OnPhone
{
return mPhoto_Path_OnPhone;
}
-(NSString *)path
{
return mPath;
}
-(void)setPhoto_ID_OnPhone:(NSString *)photo_id
{
if (mPhoto_ID_OnPhone != photo_id)
{
[mPhoto_ID_OnPhone release];
mPhoto_ID_OnPhone = [photo_id retain];
}
}
-(void)setPhoto_Path_OnPhone:(NSString *)photo_path
{
if (mPhoto_Path_OnPhone != photo_path)
{
[mPhoto_Path_OnPhone release];
mPhoto_Path_OnPhone = [photo_path retain];
}
}
-(void)setTitle:(NSString *)title
{
if (mTitle != title)
{
[mTitle release];
mTitle = [title copy];
}
}
-(NSString *)title
{
return mTitle;
}
-(NSString *)imageRepresentationType
{
return IKImageBrowserPathRepresentationType;
}
-(id)imageRepresentation
{
return mPath;
}
-(NSString *)imageUID
{
return mPath;
}
-(NSString *)imageTitle
{
if (mTitle == nil)
return [mPath lastPathComponent];
return mTitle;
}
@end
=====
//ImageBrowser.h
#import <Quartz/Quartz.h>
@class ImageItem;
/**
Image browser view. Displays thumbnails of the images contained in a single
folder. Fullscreen is binded to the image view, and it implements the
CutCopy protocol.
*/
@interface ImageBrowser : IKImageBrowserView
{
}
-(void)awakeFromNib;
-(void)reloadData;
-(void)reloadDataAndKeepSelection;
// utils
-(BOOL)setFullscreen;
-(void)deleteSelectedImages;
-(void)cutSelectedImages;
-(void)copySelectedImages;
-(IBAction)selectAll:(id)sender;
-(IBAction)deselectAll:(id)sender;
-(void)setSelectedImage:(NSString *)image;
-(ImageItem *)itemAtIndex:(NSUInteger)index;
-(NSArray *)selectedImagesAsURLArray;
-(NSArray *)selectedImagesAsTitelArray;
-(NSArray *)selectedImagesAsPhotoIDArray;
-(NSArray *)selectedImagesAsPhotoPathArray;
// used by the slide show timer
-(void)selectNextImage:(NSTimer *)timer;
// for binding
-(BOOL)showTitles;
-(void)setShowTitles:(BOOL)showTitles;
-(float)thumbnailMargin;
-(void)setThumbnailMargin:(BOOL)margin;
// event methods
-(void)keyDown:(NSEvent *)theEvent;
-(void)otherMouseDown:(NSEvent *)theEvent;
@end
====
//ImageBrowser.m
#import "ImageBrowser.h"
#import "ImageBrowserDelegate.h"
#import "ImageItem.h"
#import "ImageDataSource.h"
#import "../Utils/FileUtils.h"
#import "../Utils/Utils.h"
#import "../Utils/SlideShow.h"
@implementation ImageBrowser
-(void)awakeFromNib
{
// cell spacing
// [LeftRight Margin,UpDown Margin]
[self setIntercellSpacing:NSMakeSize(2.0f, 4.0f)];
// forground color for the cell‘s titles
NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
[options setObject:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
[self setValue:options forKey:IKImageBrowserCellsTitleAttributesKey];
[options release];
[self setShowTitles :YES];
}
-(void)dealloc
{
[super dealloc];
}
/**
This method is used to seemlessly reload data. Since the selected image is
bound to the current image of the image view, when we do the usual
reloadData, the selection is lost. If we‘re in fullscreen, it‘ll break it.
So this method reloads data and select the next available image just after
that.
*/
-(void)reloadDataAndKeepSelection
{
// remember the first selected image
int selectedIndex = (int)[[self selectionIndexes] firstIndex];
// reload the data
[(ImageBrowserDelegate *)[self delegate] setIgnoreSelectionChanges:YES];
[super reloadData];
[(ImageBrowserDelegate *)[self delegate] setIgnoreSelectionChanges:NO];
// restore the selection, taking care of out of bound indexes
int numImages = (int)[[self dataSource] numberOfItemsInImageBrowser:self];
if (numImages != 0)
{
if (selectedIndex >= numImages)
selectedIndex = numImages - 1;
[self setSelectionIndexes:[NSIndexSet indexSetWithIndex:selectedIndex]
byExtendingSelection:NO];
}
else
{
// if there is no more images, we need to explicitely set the image
// property of the delegate to nil.ImageViewer
// This is because [super reloadData] set the current selection to
// nothing, so setting it again to nothing will NOT call the selection
// changed delegate, thus the need to explicitely call setSelectedImage.
[(ImageBrowserDelegate *)[self delegate] setSelectedImage:nil];
}
}
-(void)reloadData
{
[super reloadData];
[self scrollPoint:NSMakePoint(0, [self frame].size.height)];
}
-(void)selectNextImage:(NSTimer *)timer
{
// get the index of the first selected image
int selectedImage = -1;
if ([self selectionIndexes] != nil || [[self selectionIndexes] count] != 0)
selectedImage = (int)[[self selectionIndexes] firstIndex];
// increment it, and check for bound, and loop
++selectedImage;
int numImages = (int)[[self dataSource] numberOfItemsInImageBrowser:nil];
if (selectedImage >= numImages)
{
if ([[timer userInfo] boolValue] == YES)
{
selectedImage = 0;
}
else
{
selectedImage = (int)numImages - 1;
// also stop the slide show
[SlideShow stopSlideShow];
}
}
// finally, set the new image
[self setSelectionIndexes:[NSIndexSet indexSetWithIndex:selectedImage]
byExtendingSelection:NO];
}
-(BOOL)showTitles
{
return [self cellsStyleMask] & IKCellsStyleTitled;
}
-(void)setShowTitles:(BOOL)showTitles
{
if (showTitles == YES)
[self setCellsStyleMask:[self cellsStyleMask] | IKCellsStyleTitled];
else
[self setCellsStyleMask:[self cellsStyleMask] & ~IKCellsStyleTitled];
}
-(float)thumbnailMargin
{
return [self intercellSpacing].width;
}
-(void)setThumbnailMargin:(BOOL)margin
{
[self setIntercellSpacing:NSMakeSize(margin, margin)];
}
-(BOOL)setFullscreen
{
// if still nothing‘s selected, it means we don‘t have any image
// in the image browser, so simply break (launching a slideshow
// on an empty folder has no meaning :)
if ([self selectionIndexes] == nil ||
[[self selectionIndexes] count] == 0)
return NO;
// select only the first one
[self setSelectionIndexes:[NSIndexSet indexSetWithIndex:[[self selectionIndexes] firstIndex]]
byExtendingSelection:NO];
// set the fullscreen property of the delegate (which is binded to the
// image view)
[(ImageBrowserDelegate *)[self delegate] setFullscreen:YES];
return YES;
}
-(ImageItem *)itemAtIndex:(NSUInteger)index
{
return [[self dataSource] imageBrowser:self itemAtIndex:index];
}
-(NSArray *)selectedImagesAsURLArray
{
NSIndexSet * indexes = [self selectionIndexes];
NSUInteger index = [indexes firstIndex];
NSMutableArray * files = [NSMutableArray arrayWithCapacity:[indexes count]];
while (index != NSNotFound)
{
[files addObject:[NSURL fileURLWithPath:[[self itemAtIndex:index] path]]];
index = [indexes indexGreaterThanIndex:index];
}
return files;
}
-(NSArray *)selectedImagesAsTitelArray
{
NSIndexSet * indexes = [self selectionIndexes];
NSUInteger index = [indexes firstIndex];
NSMutableArray * files = [NSMutableArray arrayWithCapacity:[indexes count]];
while (index != NSNotFound)
{
[files addObject:[[self itemAtIndex:index] title]];
index = [indexes indexGreaterThanIndex:index];
}
return files;
}
-(NSArray *)selectedImagesAsPhotoIDArray
{
NSIndexSet * indexes = [self selectionIndexes];
NSUInteger index = [indexes firstIndex];
NSMutableArray * files = [NSMutableArray arrayWithCapacity:[indexes count]];
while (index != NSNotFound)
{
[files addObject:[[self itemAtIndex:index] Photo_ID_OnPhone]];
index = [indexes indexGreaterThanIndex:index];
}
return files;
}
-(NSArray *)selectedImagesAsPhotoPathArray
{
NSIndexSet * indexes = [self selectionIndexes];
NSUInteger index = [indexes firstIndex];
NSMutableArray * files = [NSMutableArray arrayWithCapacity:[indexes count]];
while (index != NSNotFound)
{
[files addObject:[[self itemAtIndex:index] Photo_Path_OnPhone]];
index = [indexes indexGreaterThanIndex:index];
}
return files;
}
-(void)deleteSelectedImages
{
// remove files from the disk
NSArray * files = [self selectedImagesAsURLArray];
for (NSURL * file in files)
[[FileUtils instance] removeItemAtPath:[file path]];
}
-(void)cutSelectedImages
{
[[FileUtils instance] cutItems:[self selectedImagesAsURLArray]];
}
-(void)copySelectedImages
{
[[FileUtils instance] copyItems:[self selectedImagesAsURLArray]];
}
-(void)setSelectedImage:(NSString *)image
{
[(ImageBrowserDelegate *)[self delegate] setSelectedImage:image];
}
-(IBAction)selectAll:(id)sender
{
// check if we‘re not in fullscreen
if ([(ImageBrowserDelegate *)[self delegate] fullscreen] == YES)
return;
int numImages = (int)[[self dataSource] numberOfItemsInImageBrowser:self];
if (numImages == 0)
return;
// ensure the image browser is the first responder when it selects all
[[self window] makeFirstResponder:self];
NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numImages)];
[self setSelectionIndexes:indexSet byExtendingSelection:NO];
}
-(IBAction)deselectAll:(id)sender
{
// check if we‘re not in fullscreen
if ([(ImageBrowserDelegate *)[self delegate] fullscreen] == YES)
return;
[self setSelectionIndexes:nil byExtendingSelection:NO];
}
-(void)keyDown:(NSEvent *)theEvent
{
// get the event and the modifiers
NSString * characters = [theEvent charactersIgnoringModifiers];
unichar event = [characters characterAtIndex:0];
switch (event)
{
// space & p : play / pause slideshow
case ‘ ‘:
case ‘p‘:
if ([SlideShow isRunning] == YES)
{
[SlideShow stopSlideShow];
}
else
{
if ([self setFullscreen] == YES)
[SlideShow startSlideShow:self callback:@"selectNextImage:"];
}
break;
// enter & escape : leave fullscreen
case 13:
case 27:
[self setFullscreen];
break;
default:
[super keyDown:theEvent];
}
}
-(void)otherMouseDown:(NSEvent *)theEvent
{
if ([theEvent clickCount] == 1)
[self setFullscreen];
}
@end
====
//ImageBrowserDelegate.h
#import <Cocoa/Cocoa.h>
@class IKImageBrowserView;
@class ImageBrowser;
@interface ImageBrowserDelegate: NSObject
{
@private
NSString * mSelectedImage;
ImageBrowser * mImageBrowser;
BOOL mIgnoreSelectionChanges;
}
@property BOOL ignoreSelectionChanges;
@property BOOL fullscreen;
@property (assign) IBOutlet ImageBrowser * imageBrowser;
-(id)init;
-(void)dealloc;
// used to bind the image view and the image browser view
-(NSString *)selectedImage;
-(void)setSelectedImage:(NSString *)image;
// implementation of IKImageBrowserDelegate protocol
-(void)imageBrowserSelectionDidChange:(IKImageBrowserView *)aBrowser;
-(void)imageBrowser:(IKImageBrowserView *)aBrowser cellWasDoubleClickedAtIndex:(NSUInteger)index;
-(NSUInteger)imageBrowser:(IKImageBrowserView *)aBrowser writeItemsAtIndexes:(NSIndexSet *)itemIndexes toPasteboard:(NSPasteboard *)pasteboard;
@end
=====
//ImageBrowserDelegate.m
#import <Quartz/Quartz.h>
#import "ImageBrowserDelegate.h"
#import "ImageBrowser.h"
#import "ImageDataSource.h"
#import "ImageItem.h"
#import "../Utils/Utils.h"
@implementation ImageBrowserDelegate
@synthesize fullscreen;
@synthesize ignoreSelectionChanges = mIgnoreSelectionChanges;
@synthesize imageBrowser = mImageBrowser;
-(id)init
{
self = [super init];
if (self != nil)
{
mSelectedImage = nil;
mIgnoreSelectionChanges = NO;
}
return self;
}
-(void)dealloc
{
if (mSelectedImage != nil)
{
[mSelectedImage release];
mSelectedImage = nil;
}
[super dealloc];
}
-(NSString *)selectedImage
{
return mSelectedImage;
}
-(void)setSelectedImage:(NSString *)image
{
if (mSelectedImage != image)
{
// NOTE: here, we check if the image if different from the current one.
// This means that if we reach this point, the selected image was
// set by an external source (by binding or whatever)
// This is also why we need to scroll the view to show the new
// selected image.
if (mSelectedImage != nil)
[mSelectedImage release];
mSelectedImage = [image copy];
// update the selected image of the view
ImageDataSource *dataSource = (ImageDataSource *)[mImageBrowser dataSource];
// get the index corresponding to the image
NSInteger imageIndex = [dataSource indexOfImage:image];
NSIndexSet * indices = [NSIndexSet indexSetWithIndex:imageIndex];
[mImageBrowser setSelectionIndexes:indices byExtendingSelection:NO];
// scroll to selected image
[mImageBrowser scrollIndexToVisible:imageIndex];
}
}
-(void)imageBrowserSelectionDidChange:(IKImageBrowserView *)aBrowser
{
if (mIgnoreSelectionChanges == YES)
return;
// get the selection indexes
NSIndexSet * selectionIndexes = [mImageBrowser selectionIndexes];
// set the first selected image, so that any other view bound to
// selectedImage will be notified
if ([selectionIndexes count] == 0)
{
[self setSelectedImage:nil];
}
else
{
NSUInteger index = [selectionIndexes firstIndex];
ImageItem * item = [[mImageBrowser dataSource] imageBrowser:nil
itemAtIndex:index];
[mSelectedImage release];
mSelectedImage = [[item path] copy];
NSLog(@"\nPath:\n%@",[item path]);
NSLog(@"\nTitel:\n%@",[item title]);
[self setSelectedImage:[item path]];
}
}
-(void)imageBrowser:(IKImageBrowserView *)aBrowser cellWasDoubleClickedAtIndex:(NSUInteger)index
{
// NOTE: the fullscreen property of this instance is bound to the fullscreen
// property of the image view, so this will automatically toggle
// fullscreen without having a direct reference to ImageView
[self setFullscreen:![self fullscreen]];
}
-(NSUInteger)imageBrowser:(IKImageBrowserView *)aBrowser
writeItemsAtIndexes:(NSIndexSet *)itemIndexes
toPasteboard:(NSPasteboard *)pasteboard
{
NSArray * selectedImages = [mImageBrowser selectedImagesAsURLArray];
[pasteboard clearContents];
[pasteboard writeObjects:selectedImages];
return [selectedImages count];
}
@end
代码结束!
需要说明的是:
需要从控件里面找到2个委托图标,然后分别跟ImageDataSource和ImageBrowserDelegate绑定。然后,控件的定义,分别在这两个类里面都要说明。
在数据源里面设置
ImageDataSource *g_ImageDataSource;
这样一个变量,并且在
-(id)init
{
self = [super init];
if (self != nil)
{
mCurrentDirectory = nil;
mImages = [[NSMutableArray alloc] init];
[self setIsEmpty:YES];
g_ImageDataSource = self;
isSelectedAll = NO;
}
return self;
}
初始化,这样在外部,就可以对整个控件调用了,比如动态修改图片路径。
以上测试在MAC的OSX10.8.5的XCode 4.6上测试成功。
注意本应用是OSX应用,不是iOS手机应用。
运行在苹果系统的电脑上。
2014-11-13 Created By Liulili
ShenZhen, China
在MAC应用里显示多个图片(IKImageBrowserView控件使用)
标签:des style io color ar os 使用 sp for
原文地址:http://blog.csdn.net/u013317006/article/details/41075335