Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,相似图片浏览器

时间:2023-12-25 10:15:58

MAC : XCode -> Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,类似图片浏览器

STEP1:将两个目录复制到project里面ImageBrowserView和Utils,而且在project里面建立相应组和导入文件

STEP2:将Quartz.framework 和QuartzCore.framework库 导入到project里面,这两个库是系统库

STEP3:   找到控件Scroll View 控件,上面写着“Scroll View”拖入到project里面,然后将其里面的类改动为:

ImageBrowser 这是上面目录里面一个类。

STEP4: 从控件面板里面。找到2个托付类。然后分别相应ImageDataSource 和 ImageBrowserDelegate

STEP5:  然后将控件(里面的)按住Ctrl拖拉到托付控件上,然后分别相应数据源Datasource和Delegate

STEP6:  然后还要对这个控件绑定,代码已经在数据源和托付类写好,仅仅要拖拉相应这个控件就能够。

也是一定是ScrollView里面一层的控件。

STEP7:  然后查看1下。是否DataSource和delegate。还有2个定义是否绑定好

STEP8:然后将主界面添加3个button。一个选择目录。直接输入:

- (IBAction)OnBT_SelectFolder:(id)sender

{

NSOpenPanel *panel = [NSOpenPanel
openPanel];

NSString *msg=[NSString
stringWithFormat:@"Select a folder"];

//不让新打开的窗体在新窗体出现标题

[panel setMessage:msg];

[panel setPrompt:@"OK"];

[panel setCanChooseDirectories:YES];

[panel setCanCreateDirectories:YES];

[panel setCanChooseFiles:NO];

[panel beginSheetModalForWindow:[NSApp
mainWindow] completionHandler:^(NSInteger result)

{

NSString *selected_folder=@"";

if (result ==
NSFileHandlingPanelOKButton)

{

selected_folder=[[panel URL]
path];

[g_ImageDataSource
Show_ThumbnailImages:selected_folder];

}

}];

}

就能够显示你选择的目录了。

另外全选和不全选button的函数是:

[g_ImageDataSource
SetSelected_All_or_None];

有时候你可能想改动标题

能够用下面代码实现

- (IBAction)OnBT_ChangeTitle:(id)sender

{

//picture_id

[g_ImageDataSource
setID];

//picture_path

NSMutableArray *array_image_id = [[NSMutableArray
alloc] init];

NSMutableArray *array_image_path = [[NSMutableArray
alloc] init];

NSMutableArray *array_image_file_size = [[NSMutableArray
alloc] init];

;

int i_pic_count =
;//file_count, need you change

NSString *picture_id=nil;

NSString *picture_path=nil;

NSString *picture_file_size =
nil;

for (; i<i_pic_count; i++)

{

picture_id =[NSString
stringWithFormat:];

picture_path =[NSString
stringWithFormat:];

picture_file_size=[NSString
stringWithFormat:];

[array_image_id addObject:picture_id];

[array_image_path addObject:picture_path];

[array_image_file_size addObject:picture_file_size];

}

[g_ImageDataSource
setImagesPath:array_image_id

PhotoPath:array_image_path

PhotoFileSize:array_image_file_size];

}

特别注意:

当写好了图片数据源。须要外部引用

仅仅须要做:

#import "ImageDataSource.h"

extern ImageDataSource *g_ImageDataSource;

用这个指针就能够调用全部的函数

假设在控件里面。须要当选中的时候,显示当前选中的文件名称

Document *g_Document;

然后在调用的图片托付类里面

#import "Document.h"

extern Document *g_Document;

这样就能够在选择里面写入:

-(void)imageBrowserSelectionDidChange:(IKImageBrowserView *)aBrowser

。。

。。

[g_Document
ShowMessageInBottom:msg];

这样就达到了选择一个目录,然后在以下显示选择的目录全路径

以上须要的两个程序包类,一共18个文件。9个类。

代码例如以下:

能够依据自己实际情况再酌情改动。

=============================================================

//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 *)selectedImagesAsPhotoPathArray;

-(NSArray *)selectedImagesAsPhotoIDArray;

// 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;

-(NSArray *)selectedImagesAsPhotoIDArray;

@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(3.0f,
5.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 !=
)

{

if (selectedIndex >= numImages)

selectedIndex = numImages - ;

[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, [self
frame].size.height)];

}

-(void)selectNextImage:(NSTimer *)timer

{

// get the index of the first selected image

;

if ([self
selectionIndexes] != nil || [[self
selectionIndexes] count] !=
)

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 = ;

}

else

{

selectedImage = (int)numImages -
;

// 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] ==
)

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]];

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]];

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 ==
)

return;

// ensure the image browser is the first responder when it selects all

[[self
window] makeFirstResponder:self];

NSIndexSet * indexSet = [NSIndexSet
indexSetWithIndexesInRange, 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
];

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

:

:

[self
setFullscreen];

break;

default:

[super
keyDown:theEvent];

}

}

-(void)otherMouseDown:(NSEvent *)theEvent

{

if ([theEvent
)

[self
setFullscreen];

}

@end

=============================================================

//ImageBrowserDelegate.h

#import <Cocoa/Cocoa.h>

@class IKImageBrowserView;

@class ImageBrowser;

@interface ImageBrowserDelegate:
NSObject

{

@private

NSString *
mSelectedImage;

ImageBrowser *
mImageBrowser;

BOOL
mIgnoreSelectionChanges;

BOOL
fullscreen;

}

@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.mm

#import <Quartz/Quartz.h>

#import "ImageBrowserDelegate.h"

#import "ImageBrowser.h"

#import "ImageDataSource.h"

#import "ImageItem.h"

#import "../Utils/Utils.h"

#import "Document.h"

extern Document *g_Document;

@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
)

{

[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]);

NSLog(@"\nPhoto_ID:\n%@",[item
photo_id]);

NSLog(@"\nPhoto_Path:\n%@",[item
photo_path]);

[self
setSelectedImage:[item path]];

NSString *msg=[NSString
stringWithFormat:@"File:  \"%@\".   ",[item
path]];

[g_Document
ShowMessageInBottom:msg];

}

}

-(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

=============================================================

//ImageDataSource.h

#import <Cocoa/Cocoa.h>

#import "../Utils/FSEventsListener.h"

@class IKImageBrowserView;

@class ImageBrowser;

typedef struct ImageItemStruct

{

NSString *picture_id;

NSString *picture_name;

NSString *picture_file_size;

} A_ImageItemStruct;

/**

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;

BOOL
isEmpty;

BOOL isSelectedAll;

}

@property (assign)
IBOutlet ImageBrowser *
imageBrowser;

@property (readonly)
NSArray *
images;

@property (readwrite)
BOOL
isEmpty;

@property (readwrite)
BOOL
isSelectedAll;

-(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)Show_ThumbnailImages:(NSString *)pic_folder;

-(void)SetSelected_All_or_None;

-(NSArray *)GetThumbnailImagesPaths:(id)sender;

-(NSArray *)GetThumbnailImagesTitles:(id)sender;

-(void) setID;

-(void) setImagesPath:(NSMutableArray *)data_Picture_ID

PhotoPath:(NSMutableArray *)data_Picture_Path

PhotoFileSize:(NSMutableArray *)data_File_Size;

-(A_ImageItemStruct) getPicturePath:(NSMutableArray *)data_Picture_ID

Picture_Path:(NSMutableArray *)data_Picture_Path

PhotoFileSize:(NSMutableArray *)data_File_Size

PictureID:(NSString *)strPhoto_ID;

-(NSArray *)get_selectedImagesAsPhotoIDArray;

-(NSArray *)get_selectedImagesAsPhotoPathArray;

@end

=============================================================

//ImageDataSource.mm

#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"

ImageDataSource *g_ImageDataSource;

@implementation ImageDataSource

@synthesize imageBrowser
= mImageBrowser;

@synthesize images
= mImages;

@synthesize isEmpty;

@synthesize isSelectedAll;

-(id)init

{

self = [super
init];

if (self !=
nil)

{

mCurrentDirectory
= nil;

mImages
= [[NSMutableArray
alloc] init];

[self
setIsEmpty:YES];

g_ImageDataSource =
self;

isSelectedAll =
NO;

}

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)fileWasAdded:(NSString *)file

{

[self
addImage:file];

[mImageBrowser
reloadDataAndKeepSelection];

}

-(void)fileWasRemoved:(NSString *)file

{

NSInteger index = [self
indexOfImage:file];

)

{

DEBUG_LOG(@"ImageDataSource - receive fileWasRemoved, "

@"but couldn't find the image [%@]", file);

return;

}

[mImages
removeObjectAtIndex:index];

[mImageBrowser
reloadDataAndKeepSelection];

[self
setIsEmpty:[mImages
count] > ?

NO : YES];

}

-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile

{

NSInteger index = [self
indexOfImage:oldFile];

)

{

// 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 =
;

for (ImageItem * item
in mImages)

{

if ([[item
path] isEqualToString:image])

return index;

++index;

}

;

}

-(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;

}

-(void)Show_ThumbnailImages:(NSString *)pic_folder

{

//NSString *path = @"/Users/mac2/Documents/test_photo/thumbnail_template_photo";

[self setCurrentDirectory:pic_folder];

}

-(void)SetSelectedAll

{

[mImageBrowser
selectAll:nil];

isSelectedAll =
TRUE;

}

-(void)SetSelectedNone

{

[mImageBrowser
deselectAll:nil];

isSelectedAll =
FALSE;

}

-(void)SetSelected_All_or_None

{

if (YES ==
isSelectedAll)

{

[self
SetSelectedNone];

}

else

{

[self
SetSelectedAll];

}

}

- (NSArray *)GetThumbnailImagesPaths:(id)sender

{

NSArray *files_selected ;

files_selected = [mImageBrowser
selectedImagesAsURLArray];

return files_selected;

}

- (NSArray *)GetThumbnailImagesTitles:(id)sender

{

NSArray *files_selected ;

files_selected = [mImageBrowser
selectedImagesAsTitelArray];

return files_selected;

}

-(void)setID

{

int images_count = (int)[mImages
count];

NSString *id_value=nil;

; i<images_count;i++)

{

ImageItem *image1 = [mImages
objectAtIndex:i];

id_value = image1.title;

id_value = [id_value stringByDeletingPathExtension];

[image1 setPhoto_ID:id_value];

}

}

/*

给这个函数传递当前全部的Photo的信息,然后通过给全部的ID找到实际相应在手机里的Path

*/

-(void) setImagesPath:(NSMutableArray *)data_Picture_ID

PhotoPath:(NSMutableArray *)data_Picture_Path

PhotoFileSize:(NSMutableArray *)data_File_Size

{

int images_count = (int)[mImages
count];

NSString *id_value=nil;

; i<images_count;i++)

{

ImageItem *image1 = [mImages
objectAtIndex:i];

id_value = image1.title;

id_value = [id_value stringByDeletingPathExtension];

id_value = [id_value stringByTrimmingCharactersInSet:[NSCharacterSet
whitespaceCharacterSet]];

//
使用id 从数组中找到

A_ImageItemStruct a_record;

a_record =[self
getPicturePath:data_Picture_ID

Picture_Path:data_Picture_Path

PhotoFileSize:data_File_Size

PictureID:id_value];

[image1 setPhoto_Path:a_record.picture_name];

[image1 setFile_Size:a_record.picture_file_size];

[image1 setTitle:[[a_record.picture_name
lastPathComponent] stringByDeletingPathExtension]];

}

[mImageBrowser
reloadData ];

}

-(A_ImageItemStruct) getPicturePath:(NSMutableArray *)data_Picture_ID

Picture_Path:(NSMutableArray *)data_Picture_Path

PhotoFileSize:(NSMutableArray *)data_File_Size

PictureID:(NSString *)strPhoto_ID

{

A_ImageItemStruct a_record;

NSString *photo_path =
nil;

NSString *photo_id =
nil;

NSString *photo_file_size =
nil;

int count =(int)[data_Picture_ID
count];

; i<count; i++)

{

photo_id =  [data_Picture_ID objectAtIndex:i];

photo_path = [data_Picture_Path objectAtIndex:i];

photo_file_size = [data_File_Size objectAtIndex:i];

a_record.picture_file_size = photo_file_size;

a_record.picture_id = photo_id ;

a_record.picture_name = photo_path;

if (YES == [strPhoto_ID
isEqualToString:photo_id])

{

break;

}

}

return a_record;

}

-(NSArray *)get_selectedImagesAsPhotoIDArray

{

NSArray *files_selected;

files_selected = [mImageBrowser
selectedImagesAsPhotoIDArray];

return  files_selected;

}

-(NSArray *)get_selectedImagesAsPhotoPathArray

{

NSArray *files_selected;

files_selected = [mImageBrowser
selectedImagesAsPhotoPathArray];

return  files_selected;

}

@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 *m_Photo_ID;

NSString *m_Photo_Path;

NSString *m_File_Size;

}

-(void)setPhoto_ID:(NSString *)photo_id;

-(NSString *)photo_id;

-(void)setFile_Size:(NSString *)photo_file_size;

-(NSString *)photo_file_size;

-(void)setPhoto_Path:(NSString *)photo_path;

-(NSString *)photo_path;

-(void)setPath:(NSString *)path;

-(NSString *)path;

-(void)setTitle:(NSString *)title;

-(NSString *)title;

-(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];

[m_Photo_Path
release];

[m_Photo_ID
release];

[m_File_Size
release];

[super
dealloc];

}

-(void)setPath:(NSString *)path

{

if (mPath != path)

{

[mPath
release];

[mTitle
release];

mPath
= [path retain];

mTitle
= [[mPath
lastPathComponent] copy];

}

}

-(NSString *)path

{

return
mPath;

}

-(void)setTitle:(NSString *)title

{

if (mTitle != title)

{

[mTitle
release];

mTitle = [title
copy];

}

}

-(void)setFile_Size:(NSString *)photo_file_size

{

if (m_File_Size != photo_file_size)

{

[m_File_Size
release];

m_File_Size = [photo_file_size
retain];

}

}

-(NSString *)photo_file_size

{

return
m_File_Size;

}

-(void)setPhoto_ID:(NSString *)photo_id

{

if (m_Photo_ID!= photo_id)

{

[m_Photo_ID
release];

m_Photo_ID = [photo_id
retain];

}

}

-(NSString *)photo_id

{

return
m_Photo_ID;

}

-(void)setPhoto_Path:(NSString *)photo_path

{

if (m_Photo_Path != photo_path)

{

[m_Photo_Path
release];

m_Photo_Path = [photo_path
retain];

}

}

-(NSString *)photo_path

{

return
m_Photo_Path;

}

-(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

=============================================================

// 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"

@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 =
;

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] >
|| [mCopiedItems
count] >
)

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 = {
, (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,

kFSEventStreamCreateFlagNoDefer);

// 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] - ] ==
'/')

{

return [path
substringToIndex:[path
length] - ];

}

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;

; 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] &
kFSEventStreamEventFlagUserDropped) ==
)

{

if (eventFlags[i] &
kFSEventStreamEventFlagUserDropped)

{

// a file or directory was permanently deleted

//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)

if (eventFlags[i])

{

[eventListener fileWasRemoved:newName];

}

else
if (eventFlags[i] &
kFSEventStreamEventFlagUnmount)

{

[eventListener directoryWasRemoved:newName];

}

}

else
if (eventFlags[i] &
kFSEventStreamEventFlagUserDropped)

{

// a file or directory was copied/created

//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)

if (eventFlags[i])

{

[eventListener fileWasAdded:newName];

}

else
if (eventFlags[i] &
kFSEventStreamEventFlagUnmount)

{

[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] &
kFSEventStreamEventFlagUnmount)

{

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
)

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

=============================================================

//

//  Document.h

#import <Cocoa/Cocoa.h>

@interface Document :
NSPersistentDocument

@property (assign)
IBOutlet NSTextField *m_LB1;

-(void)ShowMessageInBottom:(NSString *)msg;

@end

=============================================================

//

//  Document.m

// Created 2014-11-13 by DMD

// ShenZhen In China

#import "Document.h"

#import "ImageDataSource.h"

extern ImageDataSource *g_ImageDataSource;

Document *g_Document;

@implementation Document

@synthesize m_LB1;

- (id)init

{

self = [super
init];

if (self)

{

g_Document =
self;

}

return
self;

}

- (NSString *)windowNibName

{

// Override returning the nib file name of the document

// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.

return
@"Document";

}

- (void)windowControllerDidLoadNib:(NSWindowController *)aController

{

[super
windowControllerDidLoadNib:aController];

// Add any code here that needs to be executed once the windowController has loaded the document's window.

}

+ (BOOL)autosavesInPlace

{

return
YES;

}

- (IBAction)OnBT_SelectFolder:(id)sender

{

NSOpenPanel *panel = [NSOpenPanel
openPanel];

NSString *msg=[NSString
stringWithFormat:@"Select a folder"];

//不让新打开的窗体在新窗体出现标题

[panel setMessage:msg];

[panel setPrompt:@"OK"];

[panel setCanChooseDirectories:YES];

[panel setCanCreateDirectories:YES];

[panel setCanChooseFiles:NO];

[panel beginSheetModalForWindow:[NSApp
mainWindow] completionHandler:^(NSInteger result)

{

NSString *selected_folder=@"";

if (result ==
NSFileHandlingPanelOKButton)

{

selected_folder=[[panel URL]
path];

[g_ImageDataSource
Show_ThumbnailImages:selected_folder];

}

}];

}

- (IBAction)OnBT_SelectedAll:(id)sender

{

[g_ImageDataSource
SetSelected_All_or_None];

}

- (IBAction)OnBT_ChangeTitle:(id)sender

{

//picture_id

[g_ImageDataSource
setID];

//picture_path

NSMutableArray *array_image_id = [[NSMutableArray
alloc] init];

NSMutableArray *array_image_path = [[NSMutableArray
alloc] init];

NSMutableArray *array_image_file_size = [[NSMutableArray
alloc] init];

;

int i_pic_count =
;//file_count, need you change

NSString *picture_id=nil;

NSString *picture_path=nil;

NSString *picture_file_size =
nil;

for (; i<i_pic_count; i++)

{

picture_id =[NSString
stringWithFormat:];

picture_path =[NSString
stringWithFormat:];

picture_file_size=[NSString
stringWithFormat:];

[array_image_id addObject:picture_id];

[array_image_path addObject:picture_path];

[array_image_file_size addObject:picture_file_size];

}

[g_ImageDataSource
setImagesPath:array_image_id

PhotoPath:array_image_path

PhotoFileSize:array_image_file_size];

}

-(void)ShowMessageInBottom:(NSString *)msg

{

m_LB1.stringValue = msg;

}

@end

操作的时候须要注意:

Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,相似图片浏览器

=============================================================

完:

Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,相似图片浏览器

本人測试成功!

以上代码还有不完好之处,请依据自己的须要改动。

2014-11-13 Created By DMD