Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,相似图片浏览器
MAC : XCode -> Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,类似图片浏览器
STEP1:将两个目录复制到project里面ImageBrowserView和Utils,而且在project里面建立相应组和导入文件
STEP2:将Quartz.framework 和QuartzCore.framework库 导入到project里面,这两个库是系统库
STEP3: 找到控件Scroll View 控件,上面写着“Scroll View”拖入到project里面,然后将其里面的类改动为:
ImageBrowser 这是上面目录里面一个类。
STEP4: 从控件面板里面。找到2个托付类。然后分别相应ImageDataSource 和 ImageBrowserDelegate
STEP5: 然后将控件(里面的)按住Ctrl拖拉到托付控件上,然后分别相应数据源Datasource和Delegate
STEP6: 然后还要对这个控件绑定,代码已经在数据源和托付类写好,仅仅要拖拉相应这个控件就能够。
也是一定是ScrollView里面一层的控件。
STEP7: 然后查看1下。是否DataSource和delegate。还有2个定义是否绑定好
STEP8:然后将主界面添加3个button。一个选择目录。直接输入:
- (IBAction)OnBT_SelectFolder:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel
openPanel];
NSString *msg=[NSString
stringWithFormat:@"Select a folder"];
//不让新打开的窗体在新窗体出现标题
[panel setMessage:msg];
[panel setPrompt:@"OK"];
[panel setCanChooseDirectories:YES];
[panel setCanCreateDirectories:YES];
[panel setCanChooseFiles:NO];
[panel beginSheetModalForWindow:[NSApp
mainWindow] completionHandler:^(NSInteger result)
{
NSString *selected_folder=@"";
if (result ==
NSFileHandlingPanelOKButton)
{
selected_folder=[[panel URL]
path];
[g_ImageDataSource
Show_ThumbnailImages:selected_folder];
}
}];
}
就能够显示你选择的目录了。
另外全选和不全选button的函数是:
[g_ImageDataSource
SetSelected_All_or_None];
有时候你可能想改动标题
能够用下面代码实现
- (IBAction)OnBT_ChangeTitle:(id)sender
{
//picture_id
[g_ImageDataSource
setID];
//picture_path
NSMutableArray *array_image_id = [[NSMutableArray
alloc] init];
NSMutableArray *array_image_path = [[NSMutableArray
alloc] init];
NSMutableArray *array_image_file_size = [[NSMutableArray
alloc] init];
;
int i_pic_count =
;//file_count, need you change
NSString *picture_id=nil;
NSString *picture_path=nil;
NSString *picture_file_size =
nil;
for (; i<i_pic_count; i++)
{
picture_id =[NSString
stringWithFormat:];
picture_path =[NSString
stringWithFormat:];
picture_file_size=[NSString
stringWithFormat:];
[array_image_id addObject:picture_id];
[array_image_path addObject:picture_path];
[array_image_file_size addObject:picture_file_size];
}
[g_ImageDataSource
setImagesPath:array_image_id
PhotoPath:array_image_path
PhotoFileSize:array_image_file_size];
}
特别注意:
当写好了图片数据源。须要外部引用
仅仅须要做:
#import "ImageDataSource.h"
extern ImageDataSource *g_ImageDataSource;
用这个指针就能够调用全部的函数
假设在控件里面。须要当选中的时候,显示当前选中的文件名称
Document *g_Document;
然后在调用的图片托付类里面
#import "Document.h"
extern Document *g_Document;
这样就能够在选择里面写入:
-(void)imageBrowserSelectionDidChange:(IKImageBrowserView *)aBrowser
{
。。
。
。。
。
[g_Document
ShowMessageInBottom:msg];
}
这样就达到了选择一个目录,然后在以下显示选择的目录全路径
以上须要的两个程序包类,一共18个文件。9个类。
代码例如以下:
能够依据自己实际情况再酌情改动。
=============================================================
//ImageBrowser.h
#import <Quartz/Quartz.h>
@class ImageItem;
/**
Image browser view. Displays thumbnails of the images contained in a single
folder. Fullscreen is binded to the image view, and it implements the
CutCopy protocol.
*/
@interface ImageBrowser :
IKImageBrowserView
{
}
-(void)awakeFromNib;
-(void)reloadData;
-(void)reloadDataAndKeepSelection;
// utils
-(BOOL)setFullscreen;
-(void)deleteSelectedImages;
-(void)cutSelectedImages;
-(void)copySelectedImages;
-(IBAction)selectAll:(id)sender;
-(IBAction)deselectAll:(id)sender;
-(void)setSelectedImage:(NSString *)image;
-(ImageItem *)itemAtIndex:(NSUInteger)index;
-(NSArray *)selectedImagesAsURLArray;
-(NSArray *)selectedImagesAsTitelArray;
-(NSArray *)selectedImagesAsPhotoPathArray;
-(NSArray *)selectedImagesAsPhotoIDArray;
// used by the slide show timer
-(void)selectNextImage:(NSTimer *)timer;
// for binding
-(BOOL)showTitles;
-(void)setShowTitles:(BOOL)showTitles;
-(float)thumbnailMargin;
-(void)setThumbnailMargin:(BOOL)margin;
// event methods
-(void)keyDown:(NSEvent *)theEvent;
-(void)otherMouseDown:(NSEvent *)theEvent;
-(NSArray *)selectedImagesAsPhotoIDArray;
@end
=============================================================
//ImageBrowser.m
#import "ImageBrowser.h"
#import "ImageBrowserDelegate.h"
#import "ImageItem.h"
#import "ImageDataSource.h"
#import "../Utils/FileUtils.h"
#import "../Utils/Utils.h"
#import "../Utils/SlideShow.h"
@implementation ImageBrowser
-(void)awakeFromNib
{
// cell spacing
// [LeftRight Margin,UpDown Margin]
[self
setIntercellSpacing:NSMakeSize(3.0f,
5.0f)];
// forground color for the cell's titles
NSMutableDictionary * options = [[NSMutableDictionary
alloc]
init];
[options
setObject:[NSColor
blackColor]
forKey:NSForegroundColorAttributeName];
[self
setValue:options
forKey:IKImageBrowserCellsTitleAttributesKey];
[options release];
[self
setShowTitles :YES];
}
-(void)dealloc
{
[super
dealloc];
}
/**
This method is used to seemlessly reload data. Since the selected image is
bound to the current image of the image view, when we do the usual
reloadData, the selection is lost. If we're in fullscreen, it'll break it.
So this method reloads data and select the next available image just after
that.
*/
-(void)reloadDataAndKeepSelection
{
// remember the first selected image
int selectedIndex = (int)[[self
selectionIndexes]
firstIndex];
// reload the data
[(ImageBrowserDelegate *)[self
delegate]
setIgnoreSelectionChanges:YES];
[super
reloadData];
[(ImageBrowserDelegate *)[self
delegate]
setIgnoreSelectionChanges:NO];
// restore the selection, taking care of out of bound indexes
int numImages = (int)[[self
dataSource] numberOfItemsInImageBrowser:self];
if (numImages !=
)
{
if (selectedIndex >= numImages)
selectedIndex = numImages - ;
[self
setSelectionIndexes:[NSIndexSet
indexSetWithIndex:selectedIndex]
byExtendingSelection:NO];
}
else
{
// if there is no more images, we need to explicitely set the image
// property of the delegate to nil.ImageViewer
// This is because [super reloadData] set the current selection to
// nothing, so setting it again to nothing will NOT call the selection
// changed delegate, thus the need to explicitely call setSelectedImage.
[(ImageBrowserDelegate *)[self
delegate]
setSelectedImage:nil];
}
}
-(void)reloadData
{
[super
reloadData];
[self
scrollPoint, [self
frame].size.height)];
}
-(void)selectNextImage:(NSTimer *)timer
{
// get the index of the first selected image
;
if ([self
selectionIndexes] != nil || [[self
selectionIndexes] count] !=
)
selectedImage = (int)[[self
selectionIndexes]
firstIndex];
// increment it, and check for bound, and loop
++selectedImage;
int numImages = (int)[[self
dataSource] numberOfItemsInImageBrowser:nil];
if (selectedImage >= numImages)
{
if ([[timer
userInfo] boolValue] ==
YES)
{
selectedImage = ;
}
else
{
selectedImage = (int)numImages -
;
// also stop the slide show
[SlideShow
stopSlideShow];
}
}
// finally, set the new image
[self
setSelectionIndexes:[NSIndexSet
indexSetWithIndex:selectedImage]
byExtendingSelection:NO];
}
-(BOOL)showTitles
{
return [self
cellsStyleMask] & IKCellsStyleTitled;
}
-(void)setShowTitles:(BOOL)showTitles
{
if (showTitles ==
YES)
[self
setCellsStyleMask:[self
cellsStyleMask] | IKCellsStyleTitled];
else
[self
setCellsStyleMask:[self
cellsStyleMask] & ~IKCellsStyleTitled];
}
-(float)thumbnailMargin
{
return [self
intercellSpacing].width;
}
-(void)setThumbnailMargin:(BOOL)margin
{
[self
setIntercellSpacing:NSMakeSize(margin, margin)];
}
-(BOOL)setFullscreen
{
// if still nothing's selected, it means we don't have any image
// in the image browser, so simply break (launching a slideshow
// on an empty folder has no meaning :)
if ([self
selectionIndexes] == nil ||
[[self
selectionIndexes] count] ==
)
return
NO;
// select only the first one
[self
setSelectionIndexes:[NSIndexSet
indexSetWithIndex:[[self
selectionIndexes] firstIndex]]
byExtendingSelection:NO];
// set the fullscreen property of the delegate (which is binded to the
// image view)
[(ImageBrowserDelegate *)[self
delegate]
setFullscreen:YES];
return
YES;
}
-(ImageItem *)itemAtIndex:(NSUInteger)index
{
return [[self
dataSource] imageBrowser:self
itemAtIndex:index];
}
-(NSArray *)selectedImagesAsURLArray
{
NSIndexSet * indexes = [self
selectionIndexes];
NSUInteger index = [indexes
firstIndex];
NSMutableArray * files = [NSMutableArray
arrayWithCapacity:[indexes
count]];
while (index !=
NSNotFound)
{
[files addObject:[NSURL
fileURLWithPath:[[self
itemAtIndex:index]
path]]];
index = [indexes
indexGreaterThanIndex:index];
}
return files;
}
-(NSArray *)selectedImagesAsTitelArray
{
NSIndexSet * indexes = [self
selectionIndexes];
NSUInteger index = [indexes
firstIndex];
NSMutableArray * files = [NSMutableArray
arrayWithCapacity:[indexes
count]];
while (index !=
NSNotFound)
{
[files addObject:[[self
itemAtIndex:index]
title]];
index = [indexes
indexGreaterThanIndex:index];
}
return files;
}
-(NSArray *)selectedImagesAsPhotoIDArray
{
NSIndexSet * indexes = [self
selectionIndexes];
NSUInteger index = [indexes
firstIndex];
NSMutableArray * files = [NSMutableArray
arrayWithCapacity:[indexes
count]];
while (index !=
NSNotFound)
{
[files addObject:[[self
itemAtIndex:index]
photo_id]];
index = [indexes
indexGreaterThanIndex:index];
}
return files;
}
-(NSArray *)selectedImagesAsPhotoPathArray
{
NSIndexSet * indexes = [self
selectionIndexes];
NSUInteger index = [indexes
firstIndex];
NSMutableArray * files = [NSMutableArray
arrayWithCapacity:[indexes
count]];
while (index !=
NSNotFound)
{
[files addObject:[[self
itemAtIndex:index]
photo_path]];
index = [indexes
indexGreaterThanIndex:index];
}
return files;
}
-(void)deleteSelectedImages
{
// remove files from the disk
NSArray * files = [self
selectedImagesAsURLArray];
for (NSURL * file
in files)
[[FileUtils
instance] removeItemAtPath:[file
path]];
}
-(void)cutSelectedImages
{
[[FileUtils
instance] cutItems:[self
selectedImagesAsURLArray]];
}
-(void)copySelectedImages
{
[[FileUtils
instance] copyItems:[self
selectedImagesAsURLArray]];
}
-(void)setSelectedImage:(NSString *)image
{
[(ImageBrowserDelegate *)[self
delegate]
setSelectedImage:image];
}
-(IBAction)selectAll:(id)sender
{
// check if we're not in fullscreen
if ([(ImageBrowserDelegate *)[self
delegate]
fullscreen] ==
YES)
return;
int numImages = (int)[[self
dataSource] numberOfItemsInImageBrowser:self];
if (numImages ==
)
return;
// ensure the image browser is the first responder when it selects all
[[self
window] makeFirstResponder:self];
NSIndexSet * indexSet = [NSIndexSet
indexSetWithIndexesInRange, numImages)];
[self
setSelectionIndexes:indexSet byExtendingSelection:NO];
}
-(IBAction)deselectAll:(id)sender
{
// check if we're not in fullscreen
if ([(ImageBrowserDelegate *)[self
delegate]
fullscreen] ==
YES)
return;
[self
setSelectionIndexes:nil
byExtendingSelection:NO];
}
-(void)keyDown:(NSEvent *)theEvent
{
// get the event and the modifiers
NSString * characters = [theEvent
charactersIgnoringModifiers];
unichar event = [characters
];
switch (event)
{
// space & p : play / pause slideshow
case
' ':
case
'p':
if ([SlideShow
isRunning] == YES)
{
[SlideShow
stopSlideShow];
}
else
{
if ([self
setFullscreen] ==
YES)
[SlideShow
startSlideShow:self
callback:@"selectNextImage:"];
}
break;
// enter & escape : leave fullscreen
:
:
[self
setFullscreen];
break;
default:
[super
keyDown:theEvent];
}
}
-(void)otherMouseDown:(NSEvent *)theEvent
{
if ([theEvent
)
[self
setFullscreen];
}
@end
=============================================================
//ImageBrowserDelegate.h
#import <Cocoa/Cocoa.h>
@class IKImageBrowserView;
@class ImageBrowser;
@interface ImageBrowserDelegate:
NSObject
{
@private
NSString *
mSelectedImage;
ImageBrowser *
mImageBrowser;
BOOL
mIgnoreSelectionChanges;
BOOL
fullscreen;
}
@property BOOL
ignoreSelectionChanges;
@property BOOL
fullscreen;
@property (assign)
IBOutlet ImageBrowser *
imageBrowser;
-(id)init;
-(void)dealloc;
// used to bind the image view and the image browser view
-(NSString *)selectedImage;
-(void)setSelectedImage:(NSString *)image;
// implementation of IKImageBrowserDelegate protocol
-(void)imageBrowserSelectionDidChange:(IKImageBrowserView *)aBrowser;
-(void)imageBrowser:(IKImageBrowserView *)aBrowser cellWasDoubleClickedAtIndex:(NSUInteger)index;
-(NSUInteger)imageBrowser:(IKImageBrowserView *)aBrowser writeItemsAtIndexes:(NSIndexSet *)itemIndexes toPasteboard:(NSPasteboard
*)pasteboard;
@end
=============================================================
//ImageBrowserDelegate.mm
#import <Quartz/Quartz.h>
#import "ImageBrowserDelegate.h"
#import "ImageBrowser.h"
#import "ImageDataSource.h"
#import "ImageItem.h"
#import "../Utils/Utils.h"
#import "Document.h"
extern Document *g_Document;
@implementation ImageBrowserDelegate
@synthesize fullscreen;
@synthesize ignoreSelectionChanges
= mIgnoreSelectionChanges;
@synthesize imageBrowser
= mImageBrowser;
-(id)init
{
self = [super
init];
if (self !=
nil)
{
mSelectedImage
= nil;
mIgnoreSelectionChanges
= NO;
}
return
self;
}
-(void)dealloc
{
if (mSelectedImage !=
nil)
{
[mSelectedImage
release];
mSelectedImage =
nil;
}
[super
dealloc];
}
-(NSString *)selectedImage
{
return
mSelectedImage;
}
-(void)setSelectedImage:(NSString *)image
{
if (mSelectedImage != image)
{
// NOTE: here, we check if the image if different from the current one.
//
This means that if we reach this point, the selected image was
//
set by an external source (by binding or whatever)
//
This is also why we need to scroll the view to show the new
//
selected image.
if (mSelectedImage !=
nil)
[mSelectedImage
release];
mSelectedImage = [image
copy];
// update the selected image of the view
ImageDataSource *dataSource = (ImageDataSource *)[mImageBrowser
dataSource];
// get the index corresponding to the image
NSInteger imageIndex = [dataSource
indexOfImage:image];
NSIndexSet * indices = [NSIndexSet
indexSetWithIndex:imageIndex];
[mImageBrowser
setSelectionIndexes:indices byExtendingSelection:NO];
// scroll to selected image
[mImageBrowser
scrollIndexToVisible:imageIndex];
}
}
-(void)imageBrowserSelectionDidChange:(IKImageBrowserView *)aBrowser
{
if (mIgnoreSelectionChanges ==
YES)
return;
// get the selection indexes
NSIndexSet * selectionIndexes = [mImageBrowser
selectionIndexes];
// set the first selected image, so that any other view bound to
// selectedImage will be notified
if ([selectionIndexes
)
{
[self
setSelectedImage:nil];
}
else
{
NSUInteger index = [selectionIndexes
firstIndex];
ImageItem * item = [[mImageBrowser
dataSource]
imageBrowser:nil
itemAtIndex:index];
[mSelectedImage
release];
mSelectedImage = [[item
path] copy];
NSLog(@"\nPath:\n%@",[item
path]);
NSLog(@"\nTitel:\n%@",[item
title]);
NSLog(@"\nPhoto_ID:\n%@",[item
photo_id]);
NSLog(@"\nPhoto_Path:\n%@",[item
photo_path]);
[self
setSelectedImage:[item path]];
NSString *msg=[NSString
stringWithFormat:@"File: \"%@\". ",[item
path]];
[g_Document
ShowMessageInBottom:msg];
}
}
-(void)imageBrowser:(IKImageBrowserView *)aBrowser cellWasDoubleClickedAtIndex:(NSUInteger)index
{
// NOTE: the fullscreen property of this instance is bound to the fullscreen
//
property of the image view, so this will automatically toggle
//
fullscreen without having a direct reference to ImageView
[self
setFullscreen:![self
fullscreen]];
}
-(NSUInteger)imageBrowser:(IKImageBrowserView *)aBrowser
writeItemsAtIndexes:(NSIndexSet *)itemIndexes
toPasteboard:(NSPasteboard *)pasteboard
{
NSArray * selectedImages = [mImageBrowser
selectedImagesAsURLArray];
[pasteboard clearContents];
[pasteboard writeObjects:selectedImages];
return [selectedImages
count];
}
@end
=============================================================
//ImageDataSource.h
#import <Cocoa/Cocoa.h>
#import "../Utils/FSEventsListener.h"
@class IKImageBrowserView;
@class ImageBrowser;
typedef struct ImageItemStruct
{
NSString *picture_id;
NSString *picture_name;
NSString *picture_file_size;
} A_ImageItemStruct;
/**
This is the image data source. It's responsible for giving access to all
the images contained in a single folder.
*/
@interface ImageDataSource:
NSObject<
FSEventListenerDelegate >
{
@private
/// the current directory. It's bound to the currently selected directory
NSString * mCurrentDirectory;
/// the associated view
ImageBrowser * mImageBrowser;
/// the images' paths.
NSMutableArray * mImages;
BOOL
isEmpty;
BOOL isSelectedAll;
}
@property (assign)
IBOutlet ImageBrowser *
imageBrowser;
@property (readonly)
NSArray *
images;
@property (readwrite)
BOOL
isEmpty;
@property (readwrite)
BOOL
isSelectedAll;
-(id)init;
-(void)dealloc;
// implementation of FSEventListenerDelegate protocol
-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;
-(void)directoryWasAdded:(NSString *)directory;
-(void)directoryWasRemoved:(NSString *)directory;
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory;
// this is used to bind the directory browser and the image data source
-(NSString *)currentDirectory;
-(void)setCurrentDirectory:(NSString *)path;
// these are internally used
-(void)addImage:(NSString *)path;
-(void)addImagesInPath:(NSString *)path;
// implementation of IKImageBrowserDataSource protocol
-(NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView *)view;
-(id)imageBrowser:(IKImageBrowserView *)view itemAtIndex:(NSUInteger)index;
// utility
-(NSInteger)indexOfImage:(NSString *)image;
-(NSArray *)imagesAtIndexes:(NSIndexSet *)indexes;
-(void)Show_ThumbnailImages:(NSString *)pic_folder;
-(void)SetSelected_All_or_None;
-(NSArray *)GetThumbnailImagesPaths:(id)sender;
-(NSArray *)GetThumbnailImagesTitles:(id)sender;
-(void) setID;
-(void) setImagesPath:(NSMutableArray *)data_Picture_ID
PhotoPath:(NSMutableArray *)data_Picture_Path
PhotoFileSize:(NSMutableArray *)data_File_Size;
-(A_ImageItemStruct) getPicturePath:(NSMutableArray *)data_Picture_ID
Picture_Path:(NSMutableArray *)data_Picture_Path
PhotoFileSize:(NSMutableArray *)data_File_Size
PictureID:(NSString *)strPhoto_ID;
-(NSArray *)get_selectedImagesAsPhotoIDArray;
-(NSArray *)get_selectedImagesAsPhotoPathArray;
@end
=============================================================
//ImageDataSource.mm
#import <Quartz/Quartz.h>
#import "ImageDataSource.h"
#import "ImageItem.h"
#import "ImageBrowser.h"
#import "../Utils/FileUtils.h"
#import "../Utils/FSEventsListener.h"
#import "../Utils/Utils.h"
ImageDataSource *g_ImageDataSource;
@implementation ImageDataSource
@synthesize imageBrowser
= mImageBrowser;
@synthesize images
= mImages;
@synthesize isEmpty;
@synthesize isSelectedAll;
-(id)init
{
self = [super
init];
if (self !=
nil)
{
mCurrentDirectory
= nil;
mImages
= [[NSMutableArray
alloc] init];
[self
setIsEmpty:YES];
g_ImageDataSource =
self;
isSelectedAll =
NO;
}
return
self;
}
-(void)dealloc
{
[mCurrentDirectory
release];
[mImages
release];
[super
dealloc];
}
-(NSString *)currentDirectory
{
return
mCurrentDirectory;
}
-(void)setCurrentDirectory:(NSString *)path
{
if (path !=
mCurrentDirectory && path !=
nil)
{
// unregister from the event listeners
[[FSEventsListener
instance]
removeListener:self
forPath:mCurrentDirectory];
// copy the new path
[mCurrentDirectory
release];
mCurrentDirectory = [path
copy];
// load images
[self
setIsEmpty:YES];
[mImages
removeAllObjects];
[self
addImagesInPath:mCurrentDirectory];
[mImageBrowser
reloadData];
// register with the new path
[[FSEventsListener
instance]
addListener:self
forPath:mCurrentDirectory];
}
}
-(void)addImagesInPath:(NSString *)path
{
// get the content of the directory
NSFileManager * fileManager = [NSFileManager
defaultManager];
NSURL * url = [NSURL
fileURLWithPath:path];
NSArray * content = [fileManager
contentsOfDirectoryAtURL:url
includingPropertiesForKeys:nil
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
// for each item, create an image object and add to the mImportedImages array
for (NSURL * url
in content)
{
[self
addImage:[url path]];
}
}
-(void)addImage:(NSString *)path
{
// error check
if ([FileUtils
isImage:path] == NO)
return;
// add the image item
ImageItem * image = [[ImageItem
alloc] init];
[image setPath:path];
[mImages
addObject:image];
[image release];
[self
setIsEmpty:NO];
}
-(void)fileWasAdded:(NSString *)file
{
[self
addImage:file];
[mImageBrowser
reloadDataAndKeepSelection];
}
-(void)fileWasRemoved:(NSString *)file
{
NSInteger index = [self
indexOfImage:file];
)
{
DEBUG_LOG(@"ImageDataSource - receive fileWasRemoved, "
@"but couldn't find the image [%@]", file);
return;
}
[mImages
removeObjectAtIndex:index];
[mImageBrowser
reloadDataAndKeepSelection];
[self
setIsEmpty:[mImages
count] > ?
NO : YES];
}
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile
{
NSInteger index = [self
indexOfImage:oldFile];
)
{
// check if the newFile is an image, and if it's the case, add it.
if ([FileUtils
isImage:newFile] ==
YES)
[self
fileWasAdded:newFile];
return;
}
if ([FileUtils
isImage:newFile] ==
YES)
{
ImageItem * image = [self
imageBrowser:mImageBrowser
itemAtIndex:index];
[image setPath:newFile];
[mImageBrowser
reloadDataAndKeepSelection];
}
else
{
[self
fileWasRemoved:oldFile];
}
}
-(void)directoryWasAdded:(NSString *)directory
{
}
-(void)directoryWasRemoved:(NSString *)directory
{
}
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory
{
}
-(NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView *)view
{
return [mImages
count];
}
-(id)imageBrowser:(IKImageBrowserView *)view itemAtIndex:(NSUInteger)index
{
return [mImages
objectAtIndex:index];
}
-(NSInteger)indexOfImage:(NSString *)image
{
NSInteger index =
;
for (ImageItem * item
in mImages)
{
if ([[item
path] isEqualToString:image])
return index;
++index;
}
;
}
-(NSArray *)imagesAtIndexes:(NSIndexSet *)indexes
{
NSMutableArray * images = [NSMutableArray
arrayWithCapacity:[indexes
count]];
NSUInteger index = [indexes
firstIndex];
while (index !=
NSNotFound)
{
[images addObject:[self
imageBrowser:nil
itemAtIndex:index]];
index = [indexes
indexGreaterThanIndex:index];
}
return images;
}
-(void)Show_ThumbnailImages:(NSString *)pic_folder
{
//NSString *path = @"/Users/mac2/Documents/test_photo/thumbnail_template_photo";
[self setCurrentDirectory:pic_folder];
}
-(void)SetSelectedAll
{
[mImageBrowser
selectAll:nil];
isSelectedAll =
TRUE;
}
-(void)SetSelectedNone
{
[mImageBrowser
deselectAll:nil];
isSelectedAll =
FALSE;
}
-(void)SetSelected_All_or_None
{
if (YES ==
isSelectedAll)
{
[self
SetSelectedNone];
}
else
{
[self
SetSelectedAll];
}
}
- (NSArray *)GetThumbnailImagesPaths:(id)sender
{
NSArray *files_selected ;
files_selected = [mImageBrowser
selectedImagesAsURLArray];
return files_selected;
}
- (NSArray *)GetThumbnailImagesTitles:(id)sender
{
NSArray *files_selected ;
files_selected = [mImageBrowser
selectedImagesAsTitelArray];
return files_selected;
}
-(void)setID
{
int images_count = (int)[mImages
count];
NSString *id_value=nil;
; i<images_count;i++)
{
ImageItem *image1 = [mImages
objectAtIndex:i];
id_value = image1.title;
id_value = [id_value stringByDeletingPathExtension];
[image1 setPhoto_ID:id_value];
}
}
/*
给这个函数传递当前全部的Photo的信息,然后通过给全部的ID找到实际相应在手机里的Path
*/
-(void) setImagesPath:(NSMutableArray *)data_Picture_ID
PhotoPath:(NSMutableArray *)data_Picture_Path
PhotoFileSize:(NSMutableArray *)data_File_Size
{
int images_count = (int)[mImages
count];
NSString *id_value=nil;
; i<images_count;i++)
{
ImageItem *image1 = [mImages
objectAtIndex:i];
id_value = image1.title;
id_value = [id_value stringByDeletingPathExtension];
id_value = [id_value stringByTrimmingCharactersInSet:[NSCharacterSet
whitespaceCharacterSet]];
//
使用id 从数组中找到
A_ImageItemStruct a_record;
a_record =[self
getPicturePath:data_Picture_ID
Picture_Path:data_Picture_Path
PhotoFileSize:data_File_Size
PictureID:id_value];
[image1 setPhoto_Path:a_record.picture_name];
[image1 setFile_Size:a_record.picture_file_size];
[image1 setTitle:[[a_record.picture_name
lastPathComponent] stringByDeletingPathExtension]];
}
[mImageBrowser
reloadData ];
}
-(A_ImageItemStruct) getPicturePath:(NSMutableArray *)data_Picture_ID
Picture_Path:(NSMutableArray *)data_Picture_Path
PhotoFileSize:(NSMutableArray *)data_File_Size
PictureID:(NSString *)strPhoto_ID
{
A_ImageItemStruct a_record;
NSString *photo_path =
nil;
NSString *photo_id =
nil;
NSString *photo_file_size =
nil;
int count =(int)[data_Picture_ID
count];
; i<count; i++)
{
photo_id = [data_Picture_ID objectAtIndex:i];
photo_path = [data_Picture_Path objectAtIndex:i];
photo_file_size = [data_File_Size objectAtIndex:i];
a_record.picture_file_size = photo_file_size;
a_record.picture_id = photo_id ;
a_record.picture_name = photo_path;
if (YES == [strPhoto_ID
isEqualToString:photo_id])
{
break;
}
}
return a_record;
}
-(NSArray *)get_selectedImagesAsPhotoIDArray
{
NSArray *files_selected;
files_selected = [mImageBrowser
selectedImagesAsPhotoIDArray];
return files_selected;
}
-(NSArray *)get_selectedImagesAsPhotoPathArray
{
NSArray *files_selected;
files_selected = [mImageBrowser
selectedImagesAsPhotoPathArray];
return files_selected;
}
@end
=============================================================
//ImageItem.h
#import <Cocoa/Cocoa.h>
/**
This class represents a single image.
*/
@interface ImageItem:
NSObject
{
@private
/// the path to the image file
NSString * mPath;
/// the title of the image. Usually the file name.
NSString * mTitle;
NSString *m_Photo_ID;
NSString *m_Photo_Path;
NSString *m_File_Size;
}
-(void)setPhoto_ID:(NSString *)photo_id;
-(NSString *)photo_id;
-(void)setFile_Size:(NSString *)photo_file_size;
-(NSString *)photo_file_size;
-(void)setPhoto_Path:(NSString *)photo_path;
-(NSString *)photo_path;
-(void)setPath:(NSString *)path;
-(NSString *)path;
-(void)setTitle:(NSString *)title;
-(NSString *)title;
-(NSString *)imageRepresentationType;
-(id)imageRepresentation;
-(NSString *)imageUID;
-(NSString *)imageTitle;
@end
=============================================================
//ImageItem.m
#import "ImageItem.h"
#import <Quartz/Quartz.h>
@implementation ImageItem
-(void)dealloc
{
[mPath
release];
[mTitle
release];
[m_Photo_Path
release];
[m_Photo_ID
release];
[m_File_Size
release];
[super
dealloc];
}
-(void)setPath:(NSString *)path
{
if (mPath != path)
{
[mPath
release];
[mTitle
release];
mPath
= [path retain];
mTitle
= [[mPath
lastPathComponent] copy];
}
}
-(NSString *)path
{
return
mPath;
}
-(void)setTitle:(NSString *)title
{
if (mTitle != title)
{
[mTitle
release];
mTitle = [title
copy];
}
}
-(void)setFile_Size:(NSString *)photo_file_size
{
if (m_File_Size != photo_file_size)
{
[m_File_Size
release];
m_File_Size = [photo_file_size
retain];
}
}
-(NSString *)photo_file_size
{
return
m_File_Size;
}
-(void)setPhoto_ID:(NSString *)photo_id
{
if (m_Photo_ID!= photo_id)
{
[m_Photo_ID
release];
m_Photo_ID = [photo_id
retain];
}
}
-(NSString *)photo_id
{
return
m_Photo_ID;
}
-(void)setPhoto_Path:(NSString *)photo_path
{
if (m_Photo_Path != photo_path)
{
[m_Photo_Path
release];
m_Photo_Path = [photo_path
retain];
}
}
-(NSString *)photo_path
{
return
m_Photo_Path;
}
-(NSString *)title
{
return
mTitle;
}
-(NSString *)imageRepresentationType
{
return
IKImageBrowserPathRepresentationType;
}
-(id)imageRepresentation
{
return
mPath;
}
-(NSString *)imageUID
{
return
mPath;
}
-(NSString *)imageTitle
{
if (mTitle ==
nil)
return [mPath
lastPathComponent];
return
mTitle;
}
@end
=============================================================
// FileUtils.h
#import <Cocoa/Cocoa.h>
/**
This class is responsible for interacting with the filesystem. It's meant
to be instanciated through a XIB file (I use awakFromNib to initialize it)
*/
@interface FileUtils:
NSObject
{
@private
NSMutableArray *
mCutItems;
NSMutableArray *
mCopiedItems;
NSString *
mDestinationDirectory;
}
@property (copy)
NSString *
destinationDirectory;
// init / deinit
-(void)awakeFromNib;
-(void)dealloc;
// global accessor
+(FileUtils *)instance;
// misc
+(BOOL)isImage:(NSString *)path;
+(BOOL)isGIF:(NSString *)path;
// delete / copy-cut / paste support
-(void)removeItemAtPath:(NSString *)path;
-(void)copyItems:(NSArray *)items;
-(void)cutItems:(NSArray *)items;
-(void)paste;
-(void)pasteTo:(NSString *)destination;
-(BOOL)canPaste;
-(void)setCanPaste:(BOOL)canPaste;
@end
=============================================================
// FileUtils.m
#import "FileUtils.h"
#import "Utils.h"
#import "SimpleProfiler.h"
@implementation FileUtils
static FileUtils * instance =
nil;
@synthesize destinationDirectory =
mDestinationDirectory;
-(void)awakeFromNib
{
instance
= self;
mDestinationDirectory
= nil;
mCutItems
= [[NSMutableArray
alloc] init];
mCopiedItems
= [[NSMutableArray alloc]
init];
}
-(void)dealloc
{
instance =
nil;
[mCutItems
release];
[mCopiedItems
release];
[mDestinationDirectory
release];
[super
dealloc];
}
+(FileUtils *)instance
{
return
instance;
}
+(BOOL)isImage:(NSString *)path
{
PROFILING_START(@"FileUtils - isImage");
NSString * extension = [[path
pathExtension] lowercaseString];
if ([extension
isEqualToString:@"jpg"] ==
YES ||
[extension isEqualToString:@"jpeg"] ==
YES ||
[extension isEqualToString:@"gif"] ==
YES ||
[extension isEqualToString:@"png"] ==
YES ||
[extension isEqualToString:@"psd"] ==
YES ||
[extension isEqualToString:@"tiff"] ==
YES ||
[extension isEqualToString:@"tif"] ==
YES ||
[extension isEqualToString:@"dng"] ==
YES ||
[extension isEqualToString:@"cr2"] ==
YES ||
[extension isEqualToString:@"raw"] ==
YES ||
[extension isEqualToString:@"pdf"] ==
YES)
{
PROFILING_STOP();
return
YES;
}
PROFILING_STOP();
return
NO;
}
+(BOOL)isGIF:(NSString *)path
{
NSString * extension = [[path
pathExtension] lowercaseString];
return [extension
isEqualToString:@"gif"];
}
-(void)removeItemAtPath:(NSString *)path
{
// check the preferences to see if we need to use the recycled bin, or
// permanently delete files
BOOL permanently =
YES;
//[[Preferences instance] boolForKey:@"permanentlyDeleteFiles"];
if (permanently ==
YES)
{
NSFileManager * fileManager = [NSFileManager
defaultManager];
[fileManager removeItemAtPath:path
error:NULL];
}
else
{
NSInteger tag =
;
NSString * source = [path
stringByDeletingLastPathComponent];
NSArray * files = [NSArray
arrayWithObject:[path lastPathComponent]];
NSWorkspace * workspace = [NSWorkspace
sharedWorkspace];
[workspace
performFileOperation:NSWorkspaceRecycleOperation
source:source
destination:nil
files:files
tag:&tag];
}
}
/**
Private method used to clear previously copied/cut items.
*/
-(void)clear
{
[mCopiedItems
removeAllObjects];
[mCutItems
removeAllObjects];
}
-(void)copyItems:(NSArray *)items
{
[self
clear];
[mCopiedItems
addObjectsFromArray:items];
[self
setCanPaste:YES];
}
-(void)cutItems:(NSArray *)items
{
[self
clear];
[mCutItems
addObjectsFromArray:items];
[self
setCanPaste:YES];
}
-(BOOL)canPaste
{
if ([mCutItems
count] >
|| [mCopiedItems
count] >
)
return
YES;
return
NO;
}
-(void)setCanPaste:(BOOL)canPaste
{
// this is just used for binding : when an item is added to the copy or
// cut list, we call [self setCanPaste:whatever] to notify binded objects.
}
-(void)paste
{
if (mDestinationDirectory !=
nil)
[self
pasteTo:mDestinationDirectory];
}
-(void)pasteTo:(NSString *)destination
{
NSFileManager * fileManager = [NSFileManager
defaultManager];
// handle cut files
for (NSURL * url
in mCutItems)
{
// check if the destination folder is different from the source folder
if ([destination
isEqualToString:[[url path]
stringByDeletingLastPathComponent]])
continue;
NSURL * destinationURL = [NSURL
fileURLWithPath:destination];
destinationURL = [destinationURL
URLByAppendingPathComponent:[url lastPathComponent]];
// little hack : if the destination already exists, moving wont work,
// so I remove the destination before moving. This might be a bit
// "unsafe", but I don't want to bloat the code for something that will
// happen with a 0.000001% chance.
[fileManager removeItemAtURL:destinationURL
error:nil];
[fileManager moveItemAtURL:url
toURL:destinationURL
error:nil];
}
// handle copied files
for (NSURL * url
in mCopiedItems)
{
// check if the destination folder is different from the source folder
if ([destination
isEqualToString:[[url path]
stringByDeletingLastPathComponent]])
continue;
NSURL * destinationURL = [NSURL
fileURLWithPath:destination];
destinationURL = [destinationURL
URLByAppendingPathComponent:[url lastPathComponent]];
[fileManager copyItemAtURL:url
toURL:destinationURL
error:nil];
}
[self
clear];
}
@end
=============================================================
// FSEventsListener.h
#import <Foundation/Foundation.h>
/**
This defines a little protocol which should be implemented by objects that
want to be notified of file changes (objects set as delegate of the
FSEventsListener class)
*/
@protocol FSEventListenerDelegate<
NSObject >
@required
-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;
-(void)directoryWasAdded:(NSString *)directory;
-(void)directoryWasRemoved:(NSString *)directory;
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory;
@end
/**
This class is a little helper to create file system events listeners. It
allow to schedule event watching on a particular directory, and specify a
delegate which will be called on each supported event.
*/
@interface FSEventsListener
: NSObject
{
@private
NSDictionary *
mListeners;
FSEventStreamRef
mFileStream;
}
@property (assign)
NSDictionary *
listeners;
-(id)init;
-(void)dealloc;
// singleton handling
+(FSEventsListener *)instance;
+(void)destroy;
// handle listeners
-(void)addListener:(NSObject<
FSEventListenerDelegate > *)listener forPath:(NSString *)path;
-(void)removeListener:(NSObject<
FSEventListenerDelegate > *)listener forPath:(NSString *)path;
// utils
-(NSString *)formatPath:(NSString *)path;
// used to dispatch events to listeners
-(void)fileWasAdded:(NSString *)file;
-(void)fileWasRemoved:(NSString *)file;
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile;
-(void)directoryWasAdded:(NSString *)directory;
-(void)directoryWasRemoved:(NSString *)directory;
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory;
@end
=============================================================
// FSEventsListener.m
#import "FSEventsListener.h"
#import "Utils.h"
#import "FileUtils.h"
void fsevents_callback(ConstFSEventStreamRef streamRef,
void * userData,
size_t numEvents,
void * eventPaths,
const
FSEventStreamEventFlags eventFlags[],
const
FSEventStreamEventId eventIds[]);
@implementation FSEventsListener
static FSEventsListener * instance =
nil;
@synthesize listeners
= mListeners;
-(id)init
{
self = [super
init];
if (self ==
nil)
return
nil;
mListeners = [[NSMutableDictionary
alloc]
init];
// create the context that will be associated to the stream. We pass a
// pointer to the FSEventsListener instance as user data.
FSEventStreamContext context = {
, (void *)self,
NULL, NULL,
NULL };
// create the event stream, with a flag telling that we want to watch file
// level events. This will allow to directly retrieve the file names in the
// callback, instead of just the name of the directory
mFileStream =
FSEventStreamCreate(NULL,
&fsevents_callback,
&context,
(CFArrayRef)[NSArray
arrayWithObject:@"/"],
kFSEventStreamEventIdSinceNow,
(CFAbsoluteTime)0.2,
kFSEventStreamCreateFlagNoDefer);
// start the stream on the main event loop
FSEventStreamScheduleWithRunLoop(mFileStream,
CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
FSEventStreamStart(mFileStream);
// init the globally accessible instance
instance =
self;
return
self;
}
-(void)dealloc
{
// clear the instance
instance =
nil;
// stop and clean event stream
FSEventStreamStop(mFileStream);
FSEventStreamUnscheduleFromRunLoop(mFileStream,
CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
FSEventStreamInvalidate(mFileStream);
FSEventStreamRelease(mFileStream);
[mListeners
release];
[super
dealloc];
}
+(FSEventsListener *)instance
{
if (instance ==
nil)
{
[[FSEventsListener
alloc]
init];
}
return
instance;
}
+(void)destroy
{
if (instance !=
nil)
{
[instance
release];
instance =
nil;
}
}
/**
ensure pathes are always formated the same way : except for the root '/'
path, every path must NOT end with a trailing '/'
*/
-(NSString *)formatPath:(NSString *)path
{
if ([path
characterAtIndex:[path
length] - ] ==
'/')
{
return [path
substringToIndex:[path
length] - ];
}
return [[path
copy] autorelease];
}
-(void)addListener:(NSObject<
FSEventListenerDelegate > *)listener forPath:(NSString *)path
{
NSString * formatedPath = [self
formatPath:path];
NSMutableArray * listeners = [mListeners
objectForKey:formatedPath];
if (listeners ==
nil)
{
[mListeners
setValue:[NSMutableArray
arrayWithObject:listener]
forKey:formatedPath];
}
else
{
[listeners addObject:listener];
}
}
-(void)removeListener:(NSObject<
FSEventListenerDelegate > *)listener forPath:(NSString *)path
{
NSString * formatedPath = [self
formatPath:path];
NSMutableArray * listeners = [mListeners
objectForKey:formatedPath];
if (listeners !=
nil)
{
[listeners removeObject:listener];
}
}
-(void)fileWasAdded:(NSString *)file
{
NSString * path = [file
stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners
objectForKey:path];
for (NSObject<
FSEventListenerDelegate > * listener
in listeners)
[listener fileWasAdded:file];
}
-(void)fileWasRemoved:(NSString *)file
{
NSString * path = [file
stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners
objectForKey:path];
for (NSObject<
FSEventListenerDelegate > * listener
in listeners)
[listener fileWasRemoved:file];
}
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile
{
NSString * path = [newFile
stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners
objectForKey:path];
for (NSObject<
FSEventListenerDelegate > * listener
in listeners)
[listener fileWasRenamed:oldFile
to:newFile];
}
-(void)directoryWasAdded:(NSString *)directory
{
NSString * path = [directory
stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners
objectForKey:path];
for (NSObject<
FSEventListenerDelegate > * listener
in listeners)
[listener directoryWasAdded:directory];
}
-(void)directoryWasRemoved:(NSString *)directory
{
NSString * path = [directory
stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners
objectForKey:path];
for (NSObject<
FSEventListenerDelegate > * listener
in listeners)
[listener directoryWasRemoved:directory];
}
-(void)directoryWasRenamed:(NSString *)oldDirectory to:(NSString *)newDirectory
{
NSString * path = [newDirectory
stringByDeletingLastPathComponent];
NSArray * listeners = [mListeners
objectForKey:path];
for (NSObject<
FSEventListenerDelegate > * listener
in listeners)
[listener directoryWasRenamed:oldDirectory
to:newDirectory];
}
@end
#define CHECK_STREAM(x, y) if (((x) & (y)) == (y)) NSLog(@" %s", #y);
void fsevents_callback(ConstFSEventStreamRef streamRef,
void * userData,
size_t numEvents,
void * eventPaths,
const
FSEventStreamEventFlags eventFlags[],
const
FSEventStreamEventId eventIds[])
{
static
NSString * previousRenamedPath = nil;
FSEventsListener * eventListener = (FSEventsListener *)userData;
size_t
i;
char ** paths
= eventPaths;
; i < numEvents; ++i)
{
NSString * newName = [NSString
stringWithFormat:@"%s", paths[i]];
// first, we handle events WITHOUT the renamed flag. Those are simple
// event, like "created", "removed". Note that when a device is mounted,
// or unmounted, a corresponding "created" or "removed" event is
// triggered, so we don't need to handle mount/unmount event.
if ((eventFlags[i] &
kFSEventStreamEventFlagUserDropped) ==
)
{
if (eventFlags[i] &
kFSEventStreamEventFlagUserDropped)
{
// a file or directory was permanently deleted
//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)
if (eventFlags[i])
{
[eventListener fileWasRemoved:newName];
}
else
if (eventFlags[i] &
kFSEventStreamEventFlagUnmount)
{
[eventListener directoryWasRemoved:newName];
}
}
else
if (eventFlags[i] &
kFSEventStreamEventFlagUserDropped)
{
// a file or directory was copied/created
//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)
if (eventFlags[i])
{
[eventListener fileWasAdded:newName];
}
else
if (eventFlags[i] &
kFSEventStreamEventFlagUnmount)
{
[eventListener directoryWasAdded:newName];
}
}
}
else
{
// here, the "renamed" flag is present. From what I can guess
// through experiments, when a file is renamed, or moved, or sent
// to the trash, it triggers 2 successive renamed events. The first
// contains the source file, the second the destination file.
// So I just use a static string to store the first event path and
// detect if it's the first or second event.
if (previousRenamedPath ==
nil)
{
previousRenamedPath = [newName
retain];
}
else
{
NSString * newDir = [newName
stringByDeletingLastPathComponent];
NSString * oldName = previousRenamedPath;
NSString * oldDir = [oldName
stringByDeletingLastPathComponent];
//if (eventFlags[i] & kFSEventStreamEventFlagItemIsFile)
if (eventFlags[i])
{
if ([oldDir
isEqualToString:newDir])
{
// both directory are the same : file renamed
[eventListener fileWasRenamed:oldName
to:newName];
}
else
{
// directories are different, the file was moved
[eventListener fileWasAdded:newName];
[eventListener fileWasRemoved:oldName];
}
}
else
if (eventFlags[i] &
kFSEventStreamEventFlagUnmount)
{
if ([oldDir
isEqualToString:newDir])
{
// both directory are the same : renamed
[eventListener directoryWasRenamed:oldName
to:newName];
}
else
{
// directories are different, the directory was moved
[eventListener directoryWasAdded:newName];
[eventListener directoryWasRemoved:oldName];
}
}
// reset the previous renamed path.
SAFE_RELEASE(previousRenamedPath);
}
}
#if defined(DEBUG)
// NSLog(@"event [%d] [%d] [%s]", (int)eventIds[i], eventFlags[i], paths[i]);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagNone);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagMustScanSubDirs);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagUserDropped);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagKernelDropped);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagEventIdsWrapped);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagHistoryDone);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagRootChanged);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagMount);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagUnmount);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemCreated);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemRemoved);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemInodeMetaMod);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemRenamed);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemModified);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemFinderInfoMod);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemChangeOwner);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemXattrMod);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemIsFile);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemIsDir);
// CHECK_STREAM(eventFlags[i], kFSEventStreamEventFlagItemIsSymlink);
#endif // _DEBUG
}
}
=============================================================
//SimpleProfiler.h
#import <Cocoa/Cocoa.h>
@class ProfilingEntry;
@interface SimpleProfiler:
NSObject
{
@private
NSMutableDictionary *
mEntries;
}
+(SimpleProfiler *)instance;
+(void)destroyInstance;
-(id)init;
-(void)dealloc;
-(void)addEntry:(NSString *)name withTime:(double)time;
-(void)log;
@end
@interface ProfilingEntry
: NSObject
{
@private
NSString *
mName;
NSMutableArray *
mTimes;
}
@property (copy)
NSString * name;
+(ProfilingEntry *)entryWithName:(NSString *)name;
-(id)init;
-(void)dealloc;
-(double)averageTime;
-(void)addTime:(double)time;
@end
#if defined(PROFILING)
# define PROFILING_START(name) \
NSString * __name = name; \
NSDate * __date = [NSDate date]
#else
# define PROFILING_START(name)
#endif
#if defined(PROFILING)
# define PROFILING_STOP() \
[[SimpleProfiler instance] addEntry:__name \
withTime:[[NSDate date] timeIntervalSinceDate:__date]]
#else
# define PROFILING_STOP()
#endif
=============================================================
// SimpleProfiler.m
#import "SimpleProfiler.h"
static SimpleProfiler * mSimpleProfilerInstance =
nil;
@implementation SimpleProfiler
+(SimpleProfiler *)instance
{
if (mSimpleProfilerInstance ==
nil)
mSimpleProfilerInstance = [[SimpleProfiler
alloc]
init];
return
mSimpleProfilerInstance;
}
+(void)destroyInstance
{
if (mSimpleProfilerInstance !=
nil)
{
[mSimpleProfilerInstance
release];
mSimpleProfilerInstance =
nil;
}
}
-(id)init
{
self = [super
init];
if (self)
{
mEntries = [[NSMutableDictionary
alloc]
init];
}
return
self;
}
-(void)dealloc
{
[mEntries
removeAllObjects];
[mEntries
release];
[super
dealloc];
}
-(void)addEntry:(NSString *)name withTime:(double)time
{
ProfilingEntry * entry =
nil;
entry = [mEntries
objectForKey:name];
if (entry ==
nil)
{
entry = [ProfilingEntry
entryWithName:name];
[mEntries
setValue:entry forKey:name];
}
[entry addTime:time];
}
-(void)log
{
if ([mEntries
)
return;
NSLog(@"Profiling log");
for (ProfilingEntry * entry
in [mEntries
allValues])
{
NSLog(@"%@ -- %f", [entry
name], [entry averageTime]);
}
}
@end
@implementation ProfilingEntry
@synthesize name = mName;
+(ProfilingEntry *)entryWithName:(NSString *)name
{
ProfilingEntry * entry = [[[ProfilingEntry
alloc]
init] autorelease];
[entry setName:name];
return entry;
}
-(id)init
{
self = [super
init];
if (self)
{
mName =
nil;
mTimes = [[NSMutableArray
alloc]
init];
}
return
self;
}
-(void)dealloc
{
[mName
release];
[mTimes
release];
[super
dealloc];
}
-(double)averageTime
{
double averageTime =
0.0;
for (NSNumber * number
in mTimes)
{
averageTime += [number
doubleValue];
}
return averageTime / (double)[mTimes
count];
}
-(void)addTime:(double)time
{
[mTimes
addObject:[NSNumber
numberWithDouble:time]];
}
@end
=============================================================
// SlideShow.h
#import <Foundation/Foundation.h>
@interface SlideShow
: NSObject
{
}
+(void)startSlideShow:(NSObject *)target callback:(NSString *)callback;
+(void)stopSlideShow;
+(BOOL)isRunning;
@end
=============================================================
// SlideShow.m
#import "SlideShow.h"
#import "Utils.h"
@implementation SlideShow
static NSTimer * slideshowTimer =
nil;
+(void)startSlideShow:(NSObject *)target callback:(NSString *)callback
{
if (slideshowTimer !=
nil)
[SlideShow
stopSlideShow];
// get the slideshow user preferences
NSUserDefaultsController * defaults = [NSUserDefaultsController
sharedUserDefaultsController];
BOOL loop = [[[defaults
values] valueForKey:@"slideshowLoop"]
boolValue];
float interval = [[[defaults
values] valueForKey:@"slideshowInterval"]
floatValue];
// launch the slideshow. I use a simple NSTimer with scheduledTimerWithTimeInterval.
// This method creates the timer and automatically fire it after "interval" secondes.
slideshowTimer = [NSTimer
scheduledTimerWithTimeInterval:interval
target:target
selector:NSSelectorFromString(callback)
userInfo:loop ?
@"Y" : @"N"
repeats:YES];
[slideshowTimer
setFireDate:[NSDate
dateWithTimeIntervalSinceNow:interval]];
}
+(void)stopSlideShow
{
if (slideshowTimer !=
nil)
{
[slideshowTimer
invalidate];
[slideshowTimer
release];
slideshowTimer =
nil;
}
}
+(BOOL)isRunning
{
return
slideshowTimer == nil ?
NO :
YES;
}
@end
=============================================================
// Utils.h
#import <AppKit/AppKit.h>
@interface Utils
: NSObject
{
}
+(void)bind:(id)src
keyPath:(NSString *)srcKey
to:(id)dest
keyPath:(id)destKey
continuous:(BOOL)continuous
twoWay:(BOOL)twoWay;
+(NSMutableParagraphStyle *)defaultParagraphStyle;
+(NSSize)stringSize:(NSString *)string withAttribute:(NSDictionary *)attributes;
@end
// Use this macro to output debug infos and strip them in release
#if defined(DEBUG)
# define DEBUG_LOG(...) NSLog(__VA_ARGS__)
#else
# define DEBUG_LOG(...)
#endif
// Use this macro to do something only in debug
#if defined(DEBUG)
# define DEBUG_ONLY(args) args
#else
# define DEBUG_ONLY(args)
#endif
// This macro is used when launching the ImageViewer from outside XCode :
// since we don't have access to the log, we need a way to debug
#if defined(DEBUG)
# define DEBUG_ALERT(...) \
{ \
NSAlert * __alert = [[[NSAlert alloc] init] autorelease]; \
[__alert setMessageText:[NSString stringWithFormat:__VA_ARGS__]]; \
[__alert runModal]; \
}
#else
# define DEBUG_ALERT(...)
#endif
// this macro is used to release an object and re-assign its value to nil, only
// if it's different from nil.
#if !defined(SAFE_RELEASE)
# define SAFE_RELEASE(x) if ((x) != nil) { [(x) release]; (x) = nil; }
#endif
=============================================================
// Utils.m
#import "Utils.h"
@implementation Utils
+(void)bind:(id)src
keyPath:(NSString *)srcKey
to:(id)dest
keyPath:(id)destKey
continuous:(BOOL)continuous
twoWay:(BOOL)twoWay
{
NSMutableDictionary * options =
nil;
if (continuous ==
YES)
{
options = [[NSMutableDictionary
alloc] init];
[options
setObject:[NSNumber
numberWithBool:YES]
forKey:NSContinuouslyUpdatesValueBindingOption];
}
[src bind:srcKey
toObject:dest withKeyPath:destKey
options:options];
if (twoWay ==
YES)
[dest bind:destKey
toObject:src withKeyPath:srcKey
options:options];
[options release];
}
+(NSMutableParagraphStyle *)defaultParagraphStyle
{
return [[[NSParagraphStyle
defaultParagraphStyle] mutableCopy]
autorelease];
}
+(NSSize)stringSize:(NSString *)string withAttribute:(NSDictionary *)attributes
{
NSAttributedString * attributedString = [NSAttributedString
alloc];
attributedString = [attributedString
initWithString:string];
NSSize size = [attributedString
size];
[attributedString
release];
return size;
}
@end
=============================================================
//
// Document.h
#import <Cocoa/Cocoa.h>
@interface Document :
NSPersistentDocument
@property (assign)
IBOutlet NSTextField *m_LB1;
-(void)ShowMessageInBottom:(NSString *)msg;
@end
=============================================================
//
// Document.m
// Created 2014-11-13 by DMD
// ShenZhen In China
#import "Document.h"
#import "ImageDataSource.h"
extern ImageDataSource *g_ImageDataSource;
Document *g_Document;
@implementation Document
@synthesize m_LB1;
- (id)init
{
self = [super
init];
if (self)
{
g_Document =
self;
}
return
self;
}
- (NSString *)windowNibName
{
// Override returning the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
return
@"Document";
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super
windowControllerDidLoadNib:aController];
// Add any code here that needs to be executed once the windowController has loaded the document's window.
}
+ (BOOL)autosavesInPlace
{
return
YES;
}
- (IBAction)OnBT_SelectFolder:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel
openPanel];
NSString *msg=[NSString
stringWithFormat:@"Select a folder"];
//不让新打开的窗体在新窗体出现标题
[panel setMessage:msg];
[panel setPrompt:@"OK"];
[panel setCanChooseDirectories:YES];
[panel setCanCreateDirectories:YES];
[panel setCanChooseFiles:NO];
[panel beginSheetModalForWindow:[NSApp
mainWindow] completionHandler:^(NSInteger result)
{
NSString *selected_folder=@"";
if (result ==
NSFileHandlingPanelOKButton)
{
selected_folder=[[panel URL]
path];
[g_ImageDataSource
Show_ThumbnailImages:selected_folder];
}
}];
}
- (IBAction)OnBT_SelectedAll:(id)sender
{
[g_ImageDataSource
SetSelected_All_or_None];
}
- (IBAction)OnBT_ChangeTitle:(id)sender
{
//picture_id
[g_ImageDataSource
setID];
//picture_path
NSMutableArray *array_image_id = [[NSMutableArray
alloc] init];
NSMutableArray *array_image_path = [[NSMutableArray
alloc] init];
NSMutableArray *array_image_file_size = [[NSMutableArray
alloc] init];
;
int i_pic_count =
;//file_count, need you change
NSString *picture_id=nil;
NSString *picture_path=nil;
NSString *picture_file_size =
nil;
for (; i<i_pic_count; i++)
{
picture_id =[NSString
stringWithFormat:];
picture_path =[NSString
stringWithFormat:];
picture_file_size=[NSString
stringWithFormat:];
[array_image_id addObject:picture_id];
[array_image_path addObject:picture_path];
[array_image_file_size addObject:picture_file_size];
}
[g_ImageDataSource
setImagesPath:array_image_id
PhotoPath:array_image_path
PhotoFileSize:array_image_file_size];
}
-(void)ShowMessageInBottom:(NSString *)msg
{
m_LB1.stringValue = msg;
}
@end
操作的时候须要注意:
=============================================================
完:
本人測试成功!
以上代码还有不完好之处,请依据自己的须要改动。
2014-11-13 Created By DMD
Scroll View 控件以Thumbnail的方式显示一个目录的全部图片,相似图片浏览器的更多相关文章
- iOS开发UI篇—使用picker View控件完成一个简单的选餐应用
iOS开发UI篇—使用picker View控件完成一个简单的选餐应用 一.实现效果 说明:点击随机按钮,能够自动选取,下方数据自动刷新. 二.实现思路 1.picker view的有默认高度为162 ...
- 定制自己的动画 View 控件(Canvas 使用)
定制自己的动画 View 控件(Canvas 使用) 如果要定义自己的 View 控件,则需要新建一个类继承 android.view.View.然后在 onDraw 中写自己需要实现的方式. 这里定 ...
- Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件
一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上 咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: ...
- 巧用Handler获取View控件信息
众所周知,在Android实际开发中,对于某些复杂多变的情况,控件的位置摆放.大小控制并非是xml类型的layout文件完全可以搞定的.此时,我们通常会使用Java代码来通过动态计算,将指定的控件摆放 ...
- Android 打造完美的侧滑菜单/侧滑View控件
概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...
- easyUI的datagrid控件日期列不能正确显示Json格式数据的解决方案
EasyUI是一套比较轻巧易用的Jquery控件,在使用过程中遇到一个问题,它的列表控件——datagrid, 在显示日期列的时候,由于后台返回给页面的数据是Json格式的,其中的日期字段,在后台是正 ...
- WinForm控件TreeView 只部分节点显示 CheckBox
WinForm控件TreeView 只部分节点显示 CheckBox 用过asp.net的应该知道,要在treeview中实现上述功能可以使用ShowCheckBox 属性指定那些节点显示check ...
- 在TreeView 控件上,如果双击任何一个节点的checkbox 只会收到一次After_Check事件 但是check属性变化两次(从false到true 再从true到false),请问该如何解决,谢谢!
在TreeView 控件上,如果双击任何一个节点的checkbox 只会收到一次After_Check事件 但是check属性变化两次(从false到true 再从true到false),请问该如何解 ...
- Android自定义view控件
转载自: http://blog.163.com/ppy2790@126/blog/static/103242241201382210910473/ 开发自定义控件的步骤: 1.了解View的工作原理 ...
随机推荐
- 基础知识(10)- 部署应用程序和applet
10.1 JAR文件 10.1.1 清单文件 10.1.2 可运行JAR文件 10.1.3 资源 10.1.4 密封 10.2 Java Web Start 10.2.1 沙箱 10.2. ...
- session对象和applicatione对象
ASP.NET 的常用对象有:response对象.request对象.application对象.server对象.session对象.下面主要讨论session对象和cookie对象. sessi ...
- 显示器 Linux 性能 18 (一个命令行工具传递)
对于系统和网络管理员来说每天监控和调试Linux系统的性能问题是一项繁重的工作.在IT领域作为一名Linux系统的管理员工作5年后,我逐渐认识到监控和保持系统启动并执行是多么的不easy.基于此原因. ...
- HttpSession具体解释
session的机制 http是无状态的协议,客户每次读取web页面时,server都打开新的会话,并且server也不会自己主动维护客户的上下文信息,那么要怎么才干实现会话跟踪呢?session就是 ...
- C语言中输入输出重定,freopen()妙用。
使用的理由(范围):如果输入数据很庞大,需要一次又一次的重新输入和调试时可采用本函数. freopen ()函数: 1.格式 FILE * freopen ( const char * filenam ...
- 使用XML的五种场合,XML基本规则,XML的术语,结构与语法
在很多研讨会和培训班上我遇到过许多人,他们还不明白为什么要使用XML也不知道如何 在他们的应用中使用XML.一些来自诸如Gartner公司的报告建议说,商业公司不能再做 局外人了,不能对XML置之不理 ...
- 使用git微命令深入理解git工作机制
首先.这篇不是真正意义上的翻译,所以大家在看的时候不要找相应的英文文章相应着看.这篇文章之所以归类为翻译.是由于最開始有一篇英文文章让我对git内部机制有了清楚的认识,它能够说是我git的启蒙老师吧. ...
- rzsz不能大于4G,securefx传5.2G没有问题,
rzsz不能大于4G,securefx传5.2G没有问题, 查看系统限制: $ulimit -acore file size (blocks, -c) 0data seg size ...
- HP MSA2312 ERROR
司在用的hp MAS2312存储其中一台每天都会报一个错误 EVENT:Vdisk verification failed. Command failed. (error code: 1) 2 err ...
- jenkins 通过批处理自动构建 非标准项目
之前介绍了java和vs2010的项目构建,这些都是比较常见的,所以都用专门的工具.但但难免会遇到一些不常见的项目,下面介绍通过批处理进行构建,并用jenkins调用.我们这里使用plc语言,没有标准 ...