Fix #107521 - support Format popup menu in Mac PutFile dialogs. r=pinkerton,ccarlen,sr=scc,a=asa

This commit is contained in:
sdagley%netscape.com 2002-03-15 03:24:50 +00:00
Родитель 44751d55d8
Коммит 088c530c1b
2 изменённых файлов: 201 добавлений и 33 удалений

Просмотреть файл

@ -19,6 +19,7 @@
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Steve Dagley <sdagley@netscape.com>
*/
#include "nsCOMPtr.h"
@ -64,6 +65,8 @@ nsFilePicker::nsFilePicker()
// Zero out the type lists
for (int i = 0; i < kMaxTypeListCount; i++)
mTypeLists[i] = 0L;
mSelectedType = 0;
if (sCurrentProcessSignature == 0)
{
@ -183,31 +186,61 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
}
//
// HandleShowPopupMenuSelect
//
// Figure out which menu item was selected and set mSelectedType accordingly
// We do this by the rather easy/skanky method of using the menuType field of the
// NavMenuItemSpec as the index into the menu items we've added
// And oh so strangely enough Nav Services 3.0 uses the menuType field the same way - as an
// index into CFArray of popupExtension strings so we don't have to special case this
// based on TARGET_CARBON
void nsFilePicker :: HandleShowPopupMenuSelect(NavCBRecPtr callBackParms)
{
if (callBackParms)
{
NavMenuItemSpec menuItemSpec = *(NavMenuItemSpec*)callBackParms->eventData.eventDataParms.param;
mSelectedType = menuItemSpec.menuType;
}
}
//
// FileDialogEventHandlerProc
//
// An event filter proc for NavServices so the dialogs will be movable-modals.
//
static pascal void FileDialogEventHandlerProc( NavEventCallbackMessage msg, NavCBRecPtr cbRec, NavCallBackUserData data )
pascal void nsFilePicker :: FileDialogEventHandlerProc(NavEventCallbackMessage msg, NavCBRecPtr cbRec, NavCallBackUserData callbackUD)
{
switch ( msg ) {
case kNavCBEvent:
switch ( cbRec->eventData.eventDataParms.event->what ) {
case updateEvt:
WindowPtr window = reinterpret_cast<WindowPtr>(cbRec->eventData.eventDataParms.event->message);
nsCOMPtr<nsIEventSink> sink;
nsToolkit::GetWindowEventSink ( window, getter_AddRefs(sink) );
if ( sink ) {
::BeginUpdate(window);
PRBool handled = PR_FALSE;
sink->DispatchEvent(cbRec->eventData.eventDataParms.event, &handled);
::EndUpdate(window);
}
break;
}
break;
}
nsFilePicker* self = NS_REINTERPRET_CAST(nsFilePicker*, callbackUD);
switch (msg)
{
case kNavCBEvent:
switch (cbRec->eventData.eventDataParms.event->what)
{
case updateEvt:
{
WindowPtr window = reinterpret_cast<WindowPtr>(cbRec->eventData.eventDataParms.event->message);
nsCOMPtr<nsIEventSink> sink;
nsToolkit::GetWindowEventSink (window, getter_AddRefs(sink));
if (sink)
{
::BeginUpdate(window);
PRBool handled = PR_FALSE;
sink->DispatchEvent(cbRec->eventData.eventDataParms.event, &handled);
::EndUpdate(window);
}
}
break;
}
break;
case kNavCBPopupMenuSelect:
// Format menu boinked - see what's happening
if (self)
self->HandleShowPopupMenuSelect(cbRec);
break;
}
}
@ -378,7 +411,10 @@ nsFilePicker::GetLocalFile(const nsString & inTitle, /* filter list here later *
}
::NavDialogDispose(dialog);
}
::CFRelease(titleRef);
// Free the CF objects from the dialogCreateOptions struct
if (dialogCreateOptions.windowTitle)
CFRelease(dialogCreateOptions.windowTitle);
if (filterProc)
::DisposeNavObjectFilterUPP(filterProc);
@ -454,7 +490,10 @@ nsFilePicker::GetLocalFolder(const nsString & inTitle, FSSpec* outSpec)
}
::NavDialogDispose(dialog);
}
::CFRelease(titleRef);
// Free the CF objects from the dialogCreateOptions struct
if (dialogCreateOptions.windowTitle)
CFRelease(dialogCreateOptions.windowTitle);
if (eventProc)
::DisposeNavEventUPP(eventProc);
@ -477,9 +516,18 @@ nsFilePicker::PutLocalFile(const nsString & inTitle, const nsString & inDefaultN
if (anErr != noErr)
return retVal;
// Set the options for how the get file dialog will appear
dialogCreateOptions.optionFlags |= kNavNoTypePopup;
// Set the options for how the put file dialog will appear
if (mTitles.Count() == 0)
{ // If we have no filter titles then suppress the save type popup
dialogCreateOptions.optionFlags |= kNavNoTypePopup;
}
else
{
dialogCreateOptions.optionFlags &= ~kNavAllowStationery; // remove Stationery option
creatorToSave = kNavGenericSignature; // This supresses the default format menu items
SetupFormatMenuItems(&dialogCreateOptions);
}
dialogCreateOptions.optionFlags |= kNavDontAutoTranslate;
dialogCreateOptions.optionFlags |= kNavDontAddTranslateItems;
dialogCreateOptions.optionFlags ^= kNavAllowMultipleFiles;
@ -498,7 +546,7 @@ nsFilePicker::PutLocalFile(const nsString & inTitle, const nsString & inDefaultN
typeToSave,
creatorToSave,
eventProc,
NULL, // inClientData
this, // inClientData
&dialog);
if (anErr == noErr) {
@ -559,9 +607,15 @@ nsFilePicker::PutLocalFile(const nsString & inTitle, const nsString & inDefaultN
}
}
::NavDialogDispose(dialog);
}
::CFRelease(titleRef);
::CFRelease(defaultFileNameRef);
}
// Free the CF objects from the dialogCreateOptions struct
if (dialogCreateOptions.windowTitle)
CFRelease(dialogCreateOptions.windowTitle);
if (dialogCreateOptions.saveFileName)
CFRelease(dialogCreateOptions.saveFileName);
if (dialogCreateOptions.popupExtension)
CFRelease(dialogCreateOptions.popupExtension);
if (eventProc)
::DisposeNavEventUPP(eventProc);
@ -725,10 +779,21 @@ nsFilePicker::PutLocalFile(const nsString & inTitle, const nsString & inDefaultN
OSType typeToSave = 'TEXT';
OSType creatorToSave = 'MOZZ';
OSErr anErr = NavGetDefaultDialogOptions(&dialogOptions);
if (anErr == noErr) {
// Set the options for how the get file dialog will appear
dialogOptions.dialogOptionFlags |= kNavNoTypePopup;
OSErr anErr = NavGetDefaultDialogOptions(&dialogOptions);
if (anErr == noErr)
{
// Set the options for how the put file dialog will appear
if (mTitles.Count() == 0)
{ // If we have no filter titles then suppress the save type popup
dialogOptions.dialogOptionFlags |= kNavNoTypePopup;
}
else
{
dialogOptions.dialogOptionFlags &= ~kNavAllowStationery; // remove Stationery option
creatorToSave = kNavGenericSignature; // This supresses the default format menu items
SetupFormatMenuItems(&dialogOptions);
}
dialogOptions.dialogOptionFlags |= kNavDontAutoTranslate;
dialogOptions.dialogOptionFlags |= kNavDontAddTranslateItems;
dialogOptions.dialogOptionFlags ^= kNavAllowMultipleFiles;
@ -747,7 +812,7 @@ nsFilePicker::PutLocalFile(const nsString & inTitle, const nsString & inDefaultN
eventProc,
typeToSave,
creatorToSave,
NULL); // callbackUD
this); // callbackUD
nsWatchTask::GetTask().Resume();
// See if the user has selected save
@ -781,6 +846,9 @@ nsFilePicker::PutLocalFile(const nsString & inTitle, const nsString & inDefaultN
if ( eventProc )
::DisposeNavEventUPP(eventProc);
if ( dialogOptions.popupExtension )
DisposeHandle( (Handle)dialogOptions.popupExtension );
return retVal;
}
#endif // TARGET_CARBON
@ -894,6 +962,66 @@ nsFilePicker :: MapFilterToFileTypes ( )
} // MapFilterToFileTypes
#if TARGET_CARBON
//-------------------------------------------------------------------------
// Util func to take the array of mTitles and make it into something
// Nav Services can use.
// This is the TARGET_CARBON version for Nav Services 3.0
//-------------------------------------------------------------------------
void nsFilePicker::SetupFormatMenuItems (NavDialogCreationOptions* dialogCreateOptions)
{
PRInt32 numMenuItems = mTitles.Count();
PRInt32 index;
CFStringRef itemStr = NULL;
CFArrayCallBacks callBacks = kCFTypeArrayCallBacks;
// Under NavServices 3.0 the popupExtension is actually a CFArray of CFStrings
dialogCreateOptions->popupExtension = CFArrayCreateMutable(kCFAllocatorDefault, numMenuItems, &callBacks);
if (dialogCreateOptions->popupExtension)
{
for (index = 0; index < numMenuItems; ++index)
{
const nsString& titleWide = *mTitles[index];
itemStr = CFStringCreateWithCharacters(NULL, (const unsigned short *)titleWide.get(), titleWide.Length());
CFArrayInsertValueAtIndex((CFMutableArrayRef)dialogCreateOptions->popupExtension, index, (void*)itemStr);
CFRelease(itemStr);
}
}
}
#else
//-------------------------------------------------------------------------
// Util func to take the array of mTitles and make it into something
// Nav Services can use.
// This is the non-TARGET_CARBON version for Nav Services prior to 3.0
//-------------------------------------------------------------------------
void nsFilePicker::SetupFormatMenuItems (NavDialogOptions* dialogOptions)
{
PRInt32 numMenuItems = mTitles.Count();
PRInt32 index;
// The "old" popupExtension is a handle to a plain array of NavMenuItemSpec
dialogOptions->popupExtension =
(NavMenuItemSpecArrayHandle)NewHandleClear(sizeof(NavMenuItemSpec) * numMenuItems);
if (dialogOptions->popupExtension)
{
for (index = 0; index < numMenuItems; ++index)
{
const nsString& titleWide = *mTitles[index];
Str255 title;
nsMacControl::StringToStr255(titleWide, title);
::BlockMoveData(title, (*dialogOptions->popupExtension)[index].menuItemName, *title + 1);
(*dialogOptions->popupExtension)[index].menuCreator = OSType(index);
(*dialogOptions->popupExtension)[index].menuType = OSType(index);
}
}
}
#endif
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetFile(nsILocalFile **aFile)
{
NS_ENSURE_ARG_POINTER(aFile);
@ -972,6 +1100,8 @@ NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsILocalFile **aDirectory)
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsFilePicker::AppendFilter(const PRUnichar *aTitle, const PRUnichar *aFilter)
{
@ -981,3 +1111,26 @@ nsFilePicker::AppendFilter(const PRUnichar *aTitle, const PRUnichar *aFilter)
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the filter index
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
{
*aFilterIndex = mSelectedType;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the filter index - currently not used but here to balance GetFilterIndex
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
{
mSelectedType = aFilterIndex;
return NS_OK;
}

Просмотреть файл

@ -19,6 +19,7 @@
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Steve Dagley <sdagley@netscape.com>
*/
#ifndef nsFilePicker_h__
@ -52,6 +53,8 @@ public:
NS_IMETHOD SetDefaultExtension(const PRUnichar * aDefaultExtension);
NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory);
NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory);
NS_IMETHOD GetFilterIndex(PRInt32 *aFilterIndex);
NS_IMETHOD SetFilterIndex(PRInt32 aFilterIndex);
NS_IMETHOD GetFile(nsILocalFile * *aFile);
NS_IMETHOD GetFileURL(nsIFileURL * *aFileURL);
NS_IMETHOD Show(PRInt16 *_retval);
@ -69,8 +72,19 @@ protected:
PRInt16 GetLocalFile(const nsString & inTitle, FSSpec* outFileSpec);
PRInt16 GetLocalFolder(const nsString & inTitle, FSSpec* outFileSpec);
void MapFilterToFileTypes ( ) ;
#if TARGET_CARBON
void SetupFormatMenuItems (NavDialogCreationOptions* dialogCreateOptions) ;
#else
void SetupFormatMenuItems (NavDialogOptions* dialogOptions) ;
#endif
Boolean IsTypeInFilterList ( ResType inType ) ;
Boolean IsExtensionInFilterList ( StrFileName & inFileName ) ;
void HandleShowPopupMenuSelect( NavCBRecPtr callBackParms ) ;
// filter routine for file dialog events
static pascal void FileDialogEventHandlerProc( NavEventCallbackMessage msg,
NavCBRecPtr cbRec,
NavCallBackUserData callbackUD ) ;
// filter routine for file types
static pascal Boolean FileDialogFilterProc ( AEDesc* theItem, void* info,
@ -92,7 +106,8 @@ protected:
NavTypeListPtr mTypeLists[kMaxTypeListCount];
static OSType sCurrentProcessSignature;
PRInt32 mSelectedType;
};
#endif // nsFilePicker_h__