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

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

  1. android 自定义view控件,Android 自定义View——自定义View控件

    Android给我们提供了大量的View控件,但这还是远远满足不了我们的要求,有时候开发所需要的控件形式是在Android提供的控件中是不存在,这就需要我们自己去定义一个.那么如何自定义控件? 学习自 ...

  2. iOS自定义View 控件自动计算size能力

    iOS自定义View 控件自动计算size能力 背景 在使用 UILabel 和 UIImage 的时候,不用指定宽高约束,控件也不会报约束缺失,还可以根据内容自己确定适合的宽高,特别适合 Xib 和 ...

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

    本来是写完线程池就结束多线程总结之旅系列的,但是想想平时在项目中用到线程仅仅不够的,为什么这么说呢?举个例子:我们有一个函数,它的功能就是加载数据,然后绑定到datagridview.现在我们开启一个 ...

  4. android 自定义控件的宽高_巧用Handler获取View控件信息

    众所周知,在Android实际开发中,对于某些复杂多变的情况,控件的位置摆放.大小控制并非是xml类型的layout文件完全可以搞定的.此时,我们通常会使用Java代码来通过动态计算,将指定的控件摆放 ...

  5. Android 打造完美的侧滑菜单/侧滑View控件

    概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...

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

    一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上 咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: ...

  7. 安卓中自定义view控件代替radiogroup实现颜色渐变效果的写法

    利用自定义控件代替radiogroup,同时实现在使用viewpager进行翻页的时候,实现颜色渐变的效果. 一: 首先创建一个自定义view类继承自View类,所有的控件均用canvas绘制出来(包 ...

  8. ViewPager的使用及获取子view控件的操作(inflate)

    Step 1: 布局文件中添加viewpager和切换页面button <span style="font-size:18px;"><RelativeLayout ...

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

    首先这个问题我没有找到解决的办法,不知道问题出现在哪里,所以在这里贴个博文,看看有大神路过能把问题给解决了. 问题描述: 首先建立了一个新的项目,在stroyboard中添加collection vi ...

最新文章

  1. 算力不是王道,强化学习之父Rich Sutton的六点错误
  2. Eclipse_Eclipse下配置Maven
  3. Httpd之检测与安装
  4. [转] 以 async/await 为例,说明 babel 插件怎么搭
  5. 解构里面再次解构_解构后的咖啡:焙炒,研磨和分层,以获得更浓的意式浓缩咖啡
  6. js添加关闭功能_微信小程序开发之添加夜间模式功能
  7. [渝粤教育] 山东财经大学 国际经济学 参考 资料
  8. 宗成庆《自然语言理解》第二章作业
  9. 多卡聚合路由器在视频直播中的解决方案
  10. 微信更换绑定手机人工服务器,微信更换已绑定手机号码的操作方法
  11. Mac下无法拷贝文件到移动硬盘
  12. 软件Craft.io指导
  13. 大话卫星导航中的信号处理系列文章——目录
  14. 数独终局游戏(数独终局生成,数独问题求解,数独题目生成)
  15. PyScripter显示行号
  16. Apsara Clouder云计算专项技能认证:云服务器ECS入门[考试真题]
  17. 《人性的弱点》(一)
  18. Mybatis Plus最新代码生成器AutoGenerator,更简单更高效!
  19. 数据分析案例-足球运动员分析
  20. 中科院声学所ZJ-3型压电测试仪

热门文章

  1. 麻省理工学院推出数据美国大数据可视化工具
  2. [论文摘录] Web Service QoS的几个研究方向
  3. 炒股要学会向动物学习
  4. Android 软键盘盖住输入框的问题
  5. 实体属性变更历史记录框架(一)-变更历史记录从此无忧
  6. 如何在Android中设置铃声+震动
  7. TabActivity,LocalActivityManager,TabHost,TabWidget深度分析(一)
  8. Javascript -- 精通String
  9. 用Nginx分流绕开Github反爬机制
  10. 获取 python import模块的路径