osxfilesavedialog.cpp

来自「这是VCF框架的代码」· C++ 代码 · 共 474 行

CPP
474
字号
/*Copyright 2000-2004 The VCF Project.Please see License.txt in the top level directorywhere you installed the VCF.*/#include "vcf/ApplicationKit/ApplicationKit.h"#include "vcf/ApplicationKit/ApplicationKitPrivate.h"#include "vcf/ApplicationKit/OSXFileSaveDialog.h"#include "vcf/FoundationKit/StringTokenizer.h"namespace VCF {OSXFileSaveDialog::OSXFileSaveDialog( Control* owner ) :	fileMustExist_(false),	owner_(owner),	selectedFileTypeIndex_(0){	}OSXFileSaveDialog::~OSXFileSaveDialog() {}void OSXFileSaveDialog::setTitle( const String& title ) {	title_ = title;}void OSXFileSaveDialog::buildFileTypesMap(){	//Can you say "Royal Pain In the Ass"? Yes? I knew you could!	fileTypesFilterMap_.clear();		ICInstance inst;	ICStart( &inst, 'VCF ' );	Handle entries = NewHandle(0);	ICAttr attr;	OSStatus err = ICFindPrefHandle(inst, "\pMapping", &attr, entries);	if ( noErr != err ) {		printf( "ICFindPrefHandle failed! Err: %d", err );		filter_.clear();		return;	}													ICMapEntry entry;		std::vector<String> filters;			//we are assuming that the filter_ has been populated with the following format:	//FilterPair.first = a descriptive name for the file mask	//FilterPair.second = a series of 1 or more masks of the form [*].<extension>	//multiple masks MUST be separated by a ";" character	//Example "Foo files", "*.foo;*.bar"		std::vector<FilterPair>::iterator it = filter_.begin();	while ( it != filter_.end() ) {		String filt = (*it).second;				//loop through multiple extensions if we have any		//and remove extraneous "*" chars		StringTokenizer tok( filt, ";");		if ( tok.hasMoreElements() ) {			while ( tok.hasMoreElements() ) {				String ext = tok.nextElement();				int pos = ext.find( "*" );								filters.push_back( ext );			}		}		else {			filters.push_back( filt );		}		it ++;	}		std::vector<String>::iterator it2 = filters.begin();	while ( it2 != filters.end() ) {		String ext = *it2;		int pos = ext.find( "*" );		if ( pos != String::npos ) {			ext.erase( pos, 1 );		}				//convert our Unicode string to a Pascal style string		Str255 pstrExt;		CopyCStringToPascal( ext.ansi_c_str(), pstrExt );				//clear out entry		memset( &entry, 0, sizeof(entry) );				//get entry info for the extension				err = ICMapEntriesFilename( inst, entries, pstrExt, &entry );		if ( noErr == err ) {			//add entry to map			fileTypesFilterMap_[ext] = entry.fileType;		}		it2 ++;	}		DisposeHandle( entries );		ICStop( inst );}bool OSXFileSaveDialog::execute() {	bool result = false;	fileName_ = "";	selectedFilter_ = "";	selectedFileExt_ = "";					buildFileTypesMap();		NavDialogCreationOptions saveDlgOptions;		NavGetDefaultDialogCreationOptions (&saveDlgOptions );		NavDialogRef saveDlg;	CFTextString title;	title = title_;	saveDlgOptions.modality = kWindowModalityAppModal;	saveDlgOptions.windowTitle = title;	CFStringRef* descriptionArray = NULL;		if ( !filter_.empty() ) {		descriptionArray = new CFStringRef[filter_.size()];		int index = 0;				//create the CFArray of file filter descriptions!		std::vector<FilterPair>::iterator it = filter_.begin();		while ( it != filter_.end() ) {			String description = (*it).first;			descriptionArray[index] = CFStringCreateWithCharacters( NULL, description.c_str(), description.size() );			index ++;			it ++;		}				saveDlgOptions.popupExtension = CFArrayCreate( NULL, 														(const void**) descriptionArray, 														filter_.size(), NULL);					saveDlgOptions.optionFlags &= ~kNavNoTypePopup;																	}		if ( filter_.empty() ) {		saveDlgOptions.optionFlags |= kNavSupportPackages;	}			//Finally!!! Create our goddamn dialog....		OSStatus err = NavCreatePutFileDialog (&saveDlgOptions, 												kNavGenericSignature,												kNavGenericSignature,												OSXFileSaveDialog::saveNavEventProc,												this,												&saveDlg);													if ( noErr != err ) {		throw RuntimeException( MAKE_ERROR_MSG_2("NavCreateGetFileDialog failed!") );	}			//set the directory	if ( !directory_.empty() ) {		CFTextString dir;		dir = directory_;		CFRefObject<CFURLRef> url;		url = (CFURLRef)dir;		FSRef fsRef;		if ( CFURLGetFSRef( url, &fsRef ) ) {			FSSpec fsSpec;			if ( noErr == FSGetCatalogInfo( &fsRef, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL ) ) {				AEDesc desc;				if ( AECreateDesc( typeFSS, &fsSpec, sizeof(FSSpec), &desc ) == noErr ) {					NavCustomControl( saveDlg, kNavCtlSetLocation, (void*)&desc );				}			}		}	}		//Holy Crap Batman - it's time to run the stupid dialog!!		err = NavDialogRun( saveDlg );			//free up the CFStringRefs and the CFArray	if ( NULL != saveDlgOptions.popupExtension ) {		CFRelease( saveDlgOptions.popupExtension );	}		int i=0;	for ( i=0;i<filter_.size();i++ ) {		CFRelease( descriptionArray[i] );	}		delete [] descriptionArray;	//now check the response	NavReplyRecord reply;	err = NavDialogGetReply(saveDlg, &reply);	if ( err == noErr ) {				CFTextString fileName;		fileName = NavDialogGetSaveFileName( saveDlg );		if ( fileName.length() > 0 ) {						long numItems;			AEKeyword   theKeyword;			DescType    actualType;			::Size        actualSize;			FSRef       theFSRef;			err = AEGetNthPtr(&(reply.selection), i, typeFSRef, &theKeyword, &actualType,							  &theFSRef, sizeof(theFSRef), &actualSize);						CFRefObject<CFURLRef> url = CFURLCreateFromFSRef( NULL, &theFSRef );  			char buf[256];			if ( CFURLGetFileSystemRepresentation( url, true, (UInt8*)buf, sizeof(buf) ) ) {				fileName_ = buf;				if ( fileName_[fileName_.size()-1] != '/' ) {					fileName_ += "/";				}			}			fileName_ += fileName.c_str();						result = !fileName_.empty();		}	}			NavDialogDispose( saveDlg );														return result;}bool OSXFileSaveDialog::matchFileType( NavFileOrFolderInfo* info, FSRef* fileRef ){	bool result = false;		if ( filter_.empty() ) {		return true;	}		LSItemInfoRecord itemInfo;	LSCopyItemInfoForRef( fileRef, kLSRequestAllInfo, &itemInfo );	String ext;	FilterPair filterEntry = filter_[ selectedFileTypeIndex_ ];					if ( info->fileAndFolder.fileInfo.finderInfo.fdType != 0 ) {		std::map<String,OSType>::iterator found = fileTypesFilterMap_.begin();		while ( found != fileTypesFilterMap_.end() )  {			//find and match in the filer entry for the extension						if ( filterEntry.second.find( found->first ) != String::npos ) {				//check the OSType				if ( found->second == info->fileAndFolder.fileInfo.finderInfo.fdType ) {					result = true;				}				break;			}			found ++;		}	}		if ( !result ) {		if ( itemInfo.extension ) {			CFTextString tmp;			tmp = itemInfo.extension;			ext = tmp;			ext.insert( 0, "." );		}				if ( !ext.empty() ) {			if ( filterEntry.second.find( ext ) != String::npos ) {				OSType type = fileTypesFilterMap_[ext];				if ( type != 0 ) {					if ( type == itemInfo.filetype ) {						result = true;					} 				}				else {					//no type, so since we are in the filterEntry mask, then assume true!					result = true;				}								if ( !result ) {					//damn STILL no match, well again resort to the fact that					//our file extension was in our filter mask					result = true;				}			}		}	}			return result;}pascal void OSXFileSaveDialog::saveNavEventProc( NavEventCallbackMessage inSelector, NavCBRecPtr ioParams, 													NavCallBackUserData	ioUserData){	OSXFileSaveDialog* thisPtr = (OSXFileSaveDialog*)ioUserData;	VCF_ASSERT( thisPtr != NULL );	switch( inSelector ) {		case kNavCBStart : {			// Initialize the popup menu			NavMenuItemSpec menuItem;			menuItem.version = kNavMenuItemSpecVersion;			menuItem.menuCreator = 0;			menuItem.menuType = thisPtr->selectedFileTypeIndex_;			menuItem.menuItemName[0] = 0;			OSErr error = NavCustomControl(ioParams->context, kNavCtlSelectCustomType, &menuItem);				}		break;				case kNavCBPopupMenuSelect : {			/**			This gets called when the user selects something in the popup menu.			 It would *appear* (and I put this in quotes because Nav Services is apparently								kind of buggy on OS X) that the menuType field represents the index of the 			 array of menu popup names that we pass in to the NavCreateGetFileDialog			 in the saveDlgOptions.popupExtension. Other code on the internet apparently relies 			 on this as well, so hopefully this won't change (knock on wood) in the near future.			 */			NavMenuItemSpec* menuItemSpec = (NavMenuItemSpec *)ioParams->eventData.eventDataParms.param;			thisPtr->selectedFileTypeIndex_ = menuItemSpec->menuType;			FilterPair filt = thisPtr->filter_[thisPtr->selectedFileTypeIndex_];			thisPtr->selectedFilter_ = filt.second;			thisPtr->selectedFileExt_ = filt.second;			int pos =  thisPtr->selectedFileExt_.find( "*" );			if ( pos != String::npos ) {				thisPtr->selectedFileExt_.erase( 0, pos+1 );			}		}		break;				case kNavCtlGetLocation : {			AEDesc* desc = (AEDesc *)ioParams->eventData.eventDataParms.param;			if ( NULL != desc ) {				if ( desc->descriptorType == typeFSS ) {								FSSpec fileSpec;					if ( AEGetDescData(desc, &fileSpec, sizeof(FSSpec)) == noErr ) {						FSRef fileRef;						FSGetCatalogInfo(&fileRef, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL);						CFRefObject<CFURLRef> url = CFURLCreateFromFSRef(kCFAllocatorDefault, &fileRef);						if ( NULL != url ) {							//finally, set our directory_ member							char buf[256];							if ( CFURLGetFileSystemRepresentation( url, true, (UInt8*)buf, sizeof(buf) ) ) {								thisPtr->directory_ = buf;							}						}					}				}			}		}		break;	}	}																				void OSXFileSaveDialog::addFilter( const String & description, const String & extension ) {	FilterPair entry(description,extension);		std::vector<FilterPair>::iterator found = std::find( filter_.begin(), filter_.end(), entry );	if ( found == filter_.end() ) {		filter_.push_back( entry );	}}void OSXFileSaveDialog::setDirectory( const String & directory ) {	directory_ = directory;}void OSXFileSaveDialog::setFileName( const String & filename ) {	fileName_ = filename;}String OSXFileSaveDialog::getFileName() {	return fileName_;}String OSXFileSaveDialog::getDirectory() {	return directory_;}String OSXFileSaveDialog::getFileExtension() {	return selectedFileExt_;}uint32 OSXFileSaveDialog::getSelectedFileCount() {	return 0;}Enumerator<String>* OSXFileSaveDialog::getSelectedFiles() {	return NULL;}void OSXFileSaveDialog::setAllowsMultiSelect( const bool& allowsMultiSelect ) {}void OSXFileSaveDialog::setSelectedFilter( const String& selectedFilter ) {	//FilterPair entry(description,extension);		std::vector<FilterPair>::iterator found = filter_.begin();	while ( found != filter_.end() ) {			found ++;	}		//selectedFileTypeIndex_}void OSXFileSaveDialog::setFileMustExist( const bool& fileMustExist ) {}};/***CVS Log info*$Log$*Revision 1.4  2006/04/07 02:35:24  ddiego*initial checkin of merge from 0.6.9 dev branch.**Revision 1.3.2.1  2005/11/27 23:55:44  ddiego*more osx updates.**Revision 1.3  2005/07/09 23:14:54  ddiego*merging in changes from devmain-0-6-7 branch.**Revision 1.2.2.1  2005/05/08 19:55:31  ddiego*osx updates, not yet functional.**Revision 1.2  2004/12/01 04:31:37  ddiego*merged over devmain-0-6-6 code. Marcello did a kick ass job*of fixing a nasty bug (1074768VCF application slows down modal dialogs.)*that he found. Many, many thanks for this Marcello.**Revision 1.1.2.1  2004/11/10 06:16:40  ddiego*started adding osx menu code***/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?