Scroll View 控件以Thumbnail的方式显示一个文件夹的所有图片,类似图片浏览器

MAC : XCode -> Scroll View 控件以Thumbnail的方式显示一个文件夹的所有图片,类似图片浏览器

STEP1:将两个文件夹拷贝到工程里面ImageBrowserView和Utils,并且在工程里面建立对应组和导入文件

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

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

ImageBrowser 这是上面文件夹里面一个类。

STEP4: 从控件面板里面,找到2个委托类,然后分别对应ImageDataSource 和 ImageBrowserDelegate

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

STEP6:  然后还要对这个控件绑定,代码已经在数据源和委托类写好,只要拖拉对应这个控件就可以。也是一定是ScrollView里面一层的控件。

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

STEP8:然后将主界面增加3个按钮,一个选择文件夹,直接输入:

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

}

}];

}

就可以显示你选择的文件夹了。

另外全选和不全选按钮的函数是:

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

int i_pic_count =
10;//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:@"ID%d",i+1];

picture_path =[NSString
stringWithFormat:@"Path%d",i+1];

picture_file_size=[NSString
stringWithFormat:@"Size%d",i+1];

[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 !=
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]];

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

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

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

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;

}

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

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

for (int i=0; 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];

for (int i=0; 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 =
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,

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

{

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

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

//

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

int i_pic_count =
10;//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:@"ID%d",i+1];

picture_path =[NSString
stringWithFormat:@"Path%d",i+1];

picture_file_size=[NSString
stringWithFormat:@"Size%d",i+1];

[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

操作的时候需要注意:

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

完:

本人测试成功!

以上代码还有不完善之处,请根据自己的需要修改。

2014-11-13 Created By DMD

时间: 2024-10-31 10:27:07

Scroll View 控件以Thumbnail的方式显示一个文件夹的所有图片,类似图片浏览器的相关文章

Picker View控件:

Picker View控件: 中文:单滚轮选择器 自定义选择器需要遵守两个协议:数据源协议和委托协议 UIPickerView有一个实例方法selectRow:(NSInteger)inComponent:(NSInteger)animated:(BOOL),以编程的方式来选择值. UIPickerView必须用代码实现一些协议才能正常显示,而且无法在Attributes Inspector(属性检查)中配置选择器视图的外观 1. 数据源协议 数据源协议(UIPickerViewDataSour

iOS开发UI篇—使用picker View控件完成一个简单的选餐应用 - 文顶顶

原文  http://www.cnblogs.com/wendingding/p/3771047.html iOS开发UI篇—使用picker View控件完成一个简单的选餐应用 一.实现效果 说明: 点击随机按钮,能够自动选取,下方数据自动刷新. 二.实现思路 1.picker view的有默认高度为162,不可修改. 2.显示数据,需要设置数据源,也有两种方式(成为数据源,遵守协议) 3.实现数据源里面的两个方法 1)返回一共有多少列 2)在这一列中一共有多少行 4.通过代理告诉它那一列的哪

使用picker View控件完成一个简单的选餐应用

使用picker View控件完成一个简单的选餐应用 一.实现效果 说明:点击随机按钮,能够自动选取,下方数据自动刷新. 二.实现思路 1.picker view的有默认高度为162,不可修改. 2.显示数据,需要设置数据源,也有两种方式(成为数据源,遵守协议) 3.实现数据源里面的两个方法 1)返回一共有多少列 2)在这一列中一共有多少行 4.通过代理告诉它那一列的哪一行显示哪些数据(设置其代理为控制器) 5.使用懒加载,加载所有的食物 6.完成基本数据的展示(列,行,内容) 7.自动更新选中

IOS中Table View控件练习

之前两篇博客简单学习了Picker view控件的使用,接下来再学习IOS应用中很重要的一个视图--表视图. 在表视图中,每个表视图都是UITableView的一个实例,每个可见行都是UITableViewCell的一个实例. 表视图有两种基本格式,分组的表和普通表,普通表可以实现索引,实现了索引的表成为索引表.(PS.技术上,分组表也可以实现索引,不过好像苹果的设计规范中不支持) 一个简单的表视图应用 界面设计: 向storyboard中拖一个table view控件,他会自动占满屏幕,至于约

自定义View控件(1—xib实例代码)

/** * 1. 设置显示到控制器上的模型数据(根据plist文件设置其属性,然后定义与实现工厂方法来快速实现字典转模型) */   // 1. 模型Shop.h文件 @interface Shop : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *icon; - (Shop *)initWithDict:(NSDictionary *)dict; +

Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件(转)

一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上 咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: 1.对Android中Window类中的DecorView有所了解 2.对Scroller类实现平滑移动效果 3.自定义ViewGroup的实现 首先来看看效果图吧:    下面现在就来说说这里咱们实现侧滑View的基本思路吧,这里我采用的是自定义一个继承于RelativeLayout的控件叫做XC

xcode中用oc代码基本控制view控件

控件代码部分: 编译运行后的结果为: 复杂一点的: 结果为: xcode中用oc代码基本控制view控件,布布扣,bubuko.com

多线程总结之旅(112):跨线程调用控件的几种方式

本来是写完线程池就结束多线程总结之旅系列的,但是想想平时在项目中用到线程仅仅不够的,为什么这么说呢?举个例子:我们有一个函数,它的功能就是加载数据,然后绑定到datagridview.现在我们开启一个线程去执行这个函数.结果可想而知,它会报错:提示线程无法访问...之类的话.为什么报错呢?因为你在开启的线程中操作了datagridview控件,也就是你跨线程调用控件了. 那么我们应该怎么跨线程调用控件呢?下面我就把我总结的几种方法奉献给各位. 跨线程调用控件的几种方法: 1.方法一:Contro

关于xib中添加collection view 控件引起brash

首先这个问题我没有找到解决的办法,不知道问题出现在哪里,所以在这里贴个博文,看看有大神路过能把问题给解决了. 问题描述: 首先建立了一个新的项目,在stroyboard中添加collection view 控件,遵循其中 UICollectionViewDelegateFlowLayout,UICollectionViewDelegate,UICollectionViewDataSource协议,完成collection view 的显示,都很正常,一切OK,然后我添加一个viewcontrol