mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-15 15:49:36 +02:00
Round 3 of wx3 changes
FileDialog updated to embed the file type options.
This commit is contained in:
parent
b8872a4a02
commit
d1594cdca5
@ -1,795 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: filedlg.cpp
|
||||
// Purpose: wxFileDialog
|
||||
// Author: Stefan Csomor
|
||||
// Modified by: Leland Lucius
|
||||
// Created: 1998-01-01
|
||||
// RCS-ID: $Id: FileDialogPrivate.cpp,v 1.6 2009-07-26 08:58:50 llucius Exp $
|
||||
// Copyright: (c) Stefan Csomor
|
||||
// Licence: wxWindows licence
|
||||
//
|
||||
// Modified for Audacity to support an additional button on Save dialogs
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#include "wx/app.h"
|
||||
#include "wx/utils.h"
|
||||
#include "wx/dialog.h"
|
||||
#include "wx/filedlg.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/filename.h"
|
||||
|
||||
#include "../FileDialog.h"
|
||||
|
||||
#ifndef __DARWIN__
|
||||
#include "PLStringFuncs.h"
|
||||
#endif
|
||||
|
||||
IMPLEMENT_CLASS(FileDialog, wxFileDialogBase)
|
||||
|
||||
// begin wxmac
|
||||
|
||||
#include "wx/mac/private.h"
|
||||
|
||||
#ifndef __DARWIN__
|
||||
#include <Navigation.h>
|
||||
#endif
|
||||
|
||||
extern bool gUseNavServices ;
|
||||
|
||||
#define kCustom 'cstm'
|
||||
#define kChoice 1
|
||||
#define kButton 2
|
||||
|
||||
static ControlID kChoiceID = { kCustom, kChoice };
|
||||
static ControlID kButtonID = { kCustom, kButton };
|
||||
|
||||
// the data we need to pass to our standard file hook routine
|
||||
// includes a pointer to the dialog, a pointer to the standard
|
||||
// file reply record (so we can inspect the current selection)
|
||||
// and a copy of the "previous" file spec of the reply record
|
||||
// so we can see if the selection has changed
|
||||
|
||||
struct CustomData {
|
||||
FileDialog *me;
|
||||
NavDialogRef context;
|
||||
WindowRef window;
|
||||
Rect bounds;
|
||||
ControlRef userpane;
|
||||
ControlRef choice;
|
||||
ControlRef button;
|
||||
MenuRef menu;
|
||||
wxArrayString name;
|
||||
wxArrayString extensions;
|
||||
wxArrayLong filtermactypes;
|
||||
wxString defaultLocation;
|
||||
int currentfilter;
|
||||
bool saveMode;
|
||||
bool showing;
|
||||
};
|
||||
|
||||
typedef struct CustomData
|
||||
CustomData, *CustomDataPtr;
|
||||
|
||||
static pascal void NavEventProc(
|
||||
NavEventCallbackMessage inSelector,
|
||||
NavCBRecPtr ioParams,
|
||||
NavCallBackUserData ioUserData);
|
||||
|
||||
static NavEventUPP sStandardNavEventFilter = NewNavEventUPP(NavEventProc);
|
||||
|
||||
static void HandleAdjustRect(NavCBRecPtr callBackParms, CustomData * data)
|
||||
{
|
||||
Rect rect;
|
||||
|
||||
if (!data->userpane)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetControlBounds(data->userpane, &rect);
|
||||
|
||||
SInt16 w = rect.right - rect.left;
|
||||
SInt16 h = rect.bottom - rect.top;
|
||||
SInt16 cw = callBackParms->customRect.right - callBackParms->customRect.left;
|
||||
SInt16 ch = callBackParms->customRect.bottom - callBackParms->customRect.top;
|
||||
|
||||
MoveControl(data->userpane,
|
||||
callBackParms->customRect.left + ((cw-w) / 2),
|
||||
callBackParms->customRect.top + ((ch-h) / 2));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HandleCarbonCustomizeEvent(NavCBRecPtr callBackParms, CustomData * data)
|
||||
{
|
||||
if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))
|
||||
{
|
||||
callBackParms->customRect.right = callBackParms->customRect.left +
|
||||
(data->bounds.right - data->bounds.left);
|
||||
callBackParms->customRect.bottom = callBackParms->customRect.top +
|
||||
(data->bounds.bottom - data->bounds.top);
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleCustomMouseDown(NavCBRecPtr callBackParms, CustomData *data)
|
||||
{
|
||||
EventRecord *evt = callBackParms->eventData.eventDataParms.event;
|
||||
Point where = evt->where;
|
||||
|
||||
GlobalToLocal(&where);
|
||||
|
||||
ControlRef control = FindControlUnderMouse(where, callBackParms->window, NULL);
|
||||
if (control != NULL)
|
||||
{
|
||||
HandleControlClick(control, where, evt->modifiers, (ControlActionUPP)-1L);
|
||||
NavCustomControl(callBackParms->context, kNavCtlBrowserRedraw, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleNormalEvents(NavCBRecPtr callBackParms, CustomData *data)
|
||||
{
|
||||
switch (callBackParms->eventData.eventDataParms.event->what)
|
||||
{
|
||||
case mouseDown:
|
||||
{
|
||||
HandleCustomMouseDown(callBackParms, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const EventTypeSpec namedAttrsList[] =
|
||||
{
|
||||
{ kEventClassAccessibility , kEventAccessibleGetNamedAttribute },
|
||||
{ kEventClassControl , kEventControlHit },
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
static OSStatus SetElement(wxMacCarbonEvent & event, HIObjectRef objectRef,
|
||||
UInt64 id, int parm)
|
||||
{
|
||||
OSStatus result = eventNotHandledErr;
|
||||
AXUIElementRef elem;
|
||||
|
||||
elem = AXUIElementCreateWithHIObjectAndIdentifier(objectRef, id);
|
||||
if (elem)
|
||||
{
|
||||
result = event.SetParameter(parm,
|
||||
typeCFTypeRef,
|
||||
sizeof(elem),
|
||||
&elem);
|
||||
CFRelease(elem);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static pascal OSStatus HandlePaneEvents(EventHandlerCallRef handlerRef, EventRef eventRef, void *data)
|
||||
{
|
||||
wxMacCarbonEvent event(eventRef);
|
||||
CustomData *dt = (CustomData *) data;
|
||||
OSStatus result = eventNotHandledErr;
|
||||
|
||||
switch (event.GetClass())
|
||||
{
|
||||
case kEventClassControl:
|
||||
{
|
||||
ControlRef control;
|
||||
ControlID cid;
|
||||
|
||||
control = event.GetParameter<ControlRef>(kEventParamDirectObject, typeControlRef);
|
||||
if (control == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
GetControlID(control, &cid);
|
||||
if (cid.signature != kCustom)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cid.id)
|
||||
{
|
||||
case kChoice:
|
||||
{
|
||||
MenuRef menu = GetControlPopupMenuRef(control);
|
||||
UInt32 v = GetControl32BitValue(control) - 1;
|
||||
const size_t numFilters = dt->extensions.GetCount();
|
||||
|
||||
if (v < (UInt32) dt->extensions.GetCount())
|
||||
{
|
||||
dt->currentfilter = v;
|
||||
|
||||
NavCustomControl(dt->context, kNavCtlBrowserRedraw, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kButton:
|
||||
{
|
||||
dt->me->ClickButton(GetControl32BitValue(dt->choice) - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kEventClassAccessibility:
|
||||
{
|
||||
switch (event.GetKind())
|
||||
{
|
||||
case kEventAccessibleGetNamedAttribute:
|
||||
{
|
||||
CFStringRef attr;
|
||||
|
||||
require_noerr(event.GetParameter(kEventParamAccessibleAttributeName,
|
||||
typeCFTypeRef,
|
||||
sizeof(attr),
|
||||
&attr), ParameterError);
|
||||
|
||||
if (false)
|
||||
{
|
||||
}
|
||||
else if (CFStringCompare(attr, kAXRoleAttribute, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFStringRef role = kAXGroupRole;
|
||||
|
||||
result = event.SetParameter(kEventParamAccessibleAttributeValue,
|
||||
typeCFStringRef,
|
||||
sizeof(role),
|
||||
&role);
|
||||
|
||||
require_noerr(result, ParameterError);
|
||||
}
|
||||
else if (CFStringCompare(attr, kAXRoleDescriptionAttribute, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFStringRef role = kAXGroupRole;
|
||||
CFStringRef desc;
|
||||
|
||||
desc = HICopyAccessibilityRoleDescription(role, NULL);
|
||||
if (desc)
|
||||
{
|
||||
result = event.SetParameter(kEventParamAccessibleAttributeValue,
|
||||
typeCFStringRef,
|
||||
sizeof(desc),
|
||||
&desc);
|
||||
|
||||
CFRelease(desc);
|
||||
|
||||
require_noerr(result, ParameterError);
|
||||
}
|
||||
}
|
||||
else if (CFStringCompare(attr, kAXParentAttribute, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
HIViewRef viewRef = HIViewGetSuperview(dt->userpane);
|
||||
if (viewRef)
|
||||
{
|
||||
result = SetElement(event, (HIObjectRef) viewRef, 0,
|
||||
kEventParamAccessibleAttributeValue);
|
||||
|
||||
require_noerr(result, ParameterError);
|
||||
}
|
||||
}
|
||||
else if (CFStringCompare(attr, kAXWindowAttribute, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
WindowRef winRef = HIViewGetWindow((HIViewRef) dt->userpane);
|
||||
|
||||
if (winRef)
|
||||
{
|
||||
result = SetElement(event, (HIObjectRef) winRef, 0,
|
||||
kEventParamAccessibleAttributeValue);
|
||||
|
||||
require_noerr(result, ParameterError);
|
||||
}
|
||||
}
|
||||
else if (CFStringCompare(attr, kAXTopLevelUIElementAttribute, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
if (dt->window)
|
||||
{
|
||||
result = SetElement(event, (HIObjectRef) dt->window, 0,
|
||||
kEventParamAccessibleAttributeValue);
|
||||
|
||||
require_noerr(result, ParameterError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = eventNotHandledErr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ParameterError:
|
||||
return result;
|
||||
}
|
||||
|
||||
DEFINE_ONE_SHOT_HANDLER_GETTER(HandlePaneEvents);
|
||||
|
||||
static void HandleStartEvent(NavCBRecPtr callBackParms, CustomData *data)
|
||||
{
|
||||
data->context = callBackParms->context;
|
||||
|
||||
CreateUserPaneControl(callBackParms->window, &data->bounds, kControlSupportsEmbedding, &data->userpane);
|
||||
|
||||
InstallControlEventHandler(data->userpane,
|
||||
GetHandlePaneEventsUPP(),
|
||||
GetEventTypeCount(namedAttrsList),
|
||||
namedAttrsList,
|
||||
data,
|
||||
NULL);
|
||||
|
||||
EmbedControl(data->choice, data->userpane);
|
||||
EmbedControl(data->button, data->userpane);
|
||||
|
||||
NavCustomControl(callBackParms->context, kNavCtlAddControl, data->userpane);
|
||||
|
||||
HandleAdjustRect(callBackParms, data);
|
||||
|
||||
if (data && !(data->defaultLocation).IsEmpty())
|
||||
{
|
||||
// Set default location for the modern Navigation APIs
|
||||
// Apple Technical Q&A 1151
|
||||
FSSpec theFSSpec;
|
||||
wxMacFilename2FSSpec(data->defaultLocation, &theFSSpec);
|
||||
AEDesc theLocation = {typeNull, NULL};
|
||||
if (noErr == ::AECreateDesc(typeFSS, &theFSSpec, sizeof(FSSpec), &theLocation))
|
||||
::NavCustomControl(callBackParms->context, kNavCtlSetLocation, (void *) &theLocation);
|
||||
}
|
||||
}
|
||||
|
||||
static pascal void NavEventProc(NavEventCallbackMessage inSelector,
|
||||
NavCBRecPtr ioParams,
|
||||
NavCallBackUserData ioUserData)
|
||||
{
|
||||
CustomData * data = (CustomData *) ioUserData ;
|
||||
|
||||
switch (inSelector)
|
||||
{
|
||||
case kNavCBCustomize:
|
||||
{
|
||||
HandleCarbonCustomizeEvent(ioParams, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case kNavCBStart:
|
||||
{
|
||||
HandleStartEvent(ioParams, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case kNavCBAdjustRect:
|
||||
{
|
||||
HandleAdjustRect(ioParams, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case kNavCBEvent:
|
||||
{
|
||||
HandleNormalEvents(ioParams, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case kNavCBTerminate:
|
||||
{
|
||||
data->showing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MakeUserDataRec(CustomData *myData, const wxString& filter)
|
||||
{
|
||||
myData->currentfilter = 0 ;
|
||||
|
||||
if (!filter.IsEmpty())
|
||||
{
|
||||
wxString filter2(filter) ;
|
||||
int filterIndex = 0;
|
||||
bool isName = true ;
|
||||
wxString current ;
|
||||
for( unsigned int i = 0; i < filter2.Len() ; i++ )
|
||||
{
|
||||
if( filter2.GetChar(i) == wxT('|') )
|
||||
{
|
||||
if( isName )
|
||||
{
|
||||
myData->name.Add( current ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
myData->extensions.Add( current.MakeUpper() ) ;
|
||||
++filterIndex ;
|
||||
}
|
||||
isName = !isName ;
|
||||
current = wxEmptyString ;
|
||||
}
|
||||
else
|
||||
{
|
||||
current += filter2.GetChar(i) ;
|
||||
}
|
||||
}
|
||||
// we allow for compatibility reason to have a single filter expression (like *.*) without
|
||||
// an explanatory text, in that case the first part is name and extension at the same time
|
||||
|
||||
wxASSERT_MSG( filterIndex == 0 || !isName , wxT("incorrect format of format string") ) ;
|
||||
if ( current.IsEmpty() )
|
||||
myData->extensions.Add( myData->name[filterIndex] ) ;
|
||||
else
|
||||
myData->extensions.Add( current.MakeUpper() ) ;
|
||||
if ( filterIndex == 0 || isName )
|
||||
myData->name.Add( current.MakeUpper() ) ;
|
||||
|
||||
++filterIndex ;
|
||||
|
||||
const size_t extCount = myData->extensions.GetCount();
|
||||
for ( size_t i = 0 ; i < extCount; i++ )
|
||||
{
|
||||
wxUint32 fileType;
|
||||
wxUint32 creator;
|
||||
wxString extension = myData->extensions[i];
|
||||
|
||||
if (extension.GetChar(0) == '*')
|
||||
extension = extension.Mid(1); // Remove leading *
|
||||
|
||||
if (extension.GetChar(0) == '.')
|
||||
{
|
||||
extension = extension.Mid(1); // Remove leading .
|
||||
}
|
||||
|
||||
if (wxFileName::MacFindDefaultTypeAndCreator( extension, &fileType, &creator ))
|
||||
{
|
||||
myData->filtermactypes.Add( (OSType)fileType );
|
||||
}
|
||||
else
|
||||
{
|
||||
myData->filtermactypes.Add( '****' ) ; // We'll fail safe if it's not recognized
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean CheckFile( const wxString &filename , OSType type , CustomDataPtr data)
|
||||
{
|
||||
wxString file(filename) ;
|
||||
file.MakeUpper() ;
|
||||
|
||||
if ( data->extensions.GetCount() > 0 )
|
||||
{
|
||||
int i = data->currentfilter ;
|
||||
if ( data->extensions[i].Right(2) == wxT(".*") )
|
||||
return true ;
|
||||
|
||||
{
|
||||
if ( type == (OSType)data->filtermactypes[i] )
|
||||
return true ;
|
||||
|
||||
wxStringTokenizer tokenizer( data->extensions[i] , wxT(";") ) ;
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
{
|
||||
wxString extension = tokenizer.GetNextToken() ;
|
||||
if ( extension.GetChar(0) == '*' )
|
||||
extension = extension.Mid(1) ;
|
||||
|
||||
if ( file.Len() >= extension.Len() && extension == file.Right(extension.Len() ) )
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
// end wxmac
|
||||
|
||||
FileDialog::FileDialog(wxWindow *parent,
|
||||
const wxString& message,
|
||||
const wxString& defaultDir,
|
||||
const wxString& defaultFileName,
|
||||
const wxString& wildCard,
|
||||
long style,
|
||||
const wxPoint& pos)
|
||||
:wxFileDialogBase(parent, message, defaultDir, defaultFileName, wildCard, style, pos)
|
||||
{
|
||||
wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ;
|
||||
m_callback = NULL;
|
||||
m_cbdata = NULL;
|
||||
m_dialogStyle = style;
|
||||
}
|
||||
|
||||
static pascal Boolean CrossPlatformFilterCallback (
|
||||
AEDesc *theItem,
|
||||
void *info,
|
||||
void *callBackUD,
|
||||
NavFilterModes filterMode
|
||||
)
|
||||
{
|
||||
bool display = true;
|
||||
CustomDataPtr data = (CustomDataPtr) callBackUD ;
|
||||
|
||||
if (filterMode == kNavFilteringBrowserList)
|
||||
{
|
||||
NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*) info ;
|
||||
if ( !theInfo->isFolder )
|
||||
{
|
||||
if (theItem->descriptorType == typeFSS )
|
||||
{
|
||||
FSSpec spec;
|
||||
memcpy( &spec , *theItem->dataHandle , sizeof(FSSpec) ) ;
|
||||
wxString file = wxMacMakeStringFromPascal( spec.name ) ;
|
||||
display = CheckFile( file , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ;
|
||||
}
|
||||
else if ( theItem->descriptorType == typeFSRef )
|
||||
{
|
||||
FSRef fsref ;
|
||||
memcpy( &fsref , *theItem->dataHandle , sizeof(FSRef) ) ;
|
||||
wxString file = wxMacFSRefToPath( &fsref ) ;
|
||||
display = CheckFile( file , theInfo->fileAndFolder.fileInfo.finderInfo.fdType , data ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
int FileDialog::ShowModal()
|
||||
{
|
||||
OSErr err;
|
||||
NavDialogCreationOptions dialogCreateOptions;
|
||||
// set default options
|
||||
::NavGetDefaultDialogCreationOptions(&dialogCreateOptions);
|
||||
|
||||
// this was always unset in the old code
|
||||
dialogCreateOptions.optionFlags &= ~kNavSelectDefaultLocation;
|
||||
|
||||
wxMacCFStringHolder message(m_message, GetFont().GetEncoding());
|
||||
dialogCreateOptions.windowTitle = message;
|
||||
|
||||
wxMacCFStringHolder defaultFileName(m_fileName, GetFont().GetEncoding());
|
||||
dialogCreateOptions.saveFileName = defaultFileName;
|
||||
|
||||
NavDialogRef dialog;
|
||||
NavObjectFilterUPP navFilterUPP = NULL;
|
||||
CustomData myData;
|
||||
|
||||
SetRect(&myData.bounds, 0, 0, 0, 0);
|
||||
myData.me = this;
|
||||
myData.window = NULL;
|
||||
myData.defaultLocation = m_dir;
|
||||
myData.userpane = NULL;
|
||||
myData.choice = NULL;
|
||||
myData.button = NULL;
|
||||
myData.saveMode = false;
|
||||
myData.showing = true;
|
||||
|
||||
Rect r;
|
||||
SInt16 base;
|
||||
SInt16 margin = 3;
|
||||
SInt16 gap = 0;
|
||||
|
||||
MakeUserDataRec(&myData , m_wildCard);
|
||||
myData.currentfilter = m_filterIndex;
|
||||
size_t numFilters = myData.extensions.GetCount();
|
||||
if (numFilters)
|
||||
{
|
||||
CreateNewMenu(0, 0, &myData.menu);
|
||||
|
||||
for ( size_t i = 0 ; i < numFilters ; ++i )
|
||||
{
|
||||
::AppendMenuItemTextWithCFString(myData.menu,
|
||||
wxMacCFStringHolder(myData.name[i],
|
||||
GetFont().GetEncoding()),
|
||||
4,
|
||||
i,
|
||||
NULL);
|
||||
}
|
||||
|
||||
SetRect(&r, 0, margin, 0, 0);
|
||||
CreatePopupButtonControl(NULL, &r, CFSTR("Format:"), -12345, true, -1, teJustLeft, normal, &myData.choice);
|
||||
SetControlID(myData.choice, &kChoiceID);
|
||||
SetControlPopupMenuRef(myData.choice, myData.menu);
|
||||
SetControl32BitMinimum(myData.choice, 1);
|
||||
SetControl32BitMaximum(myData.choice, myData.name.GetCount());
|
||||
SetControl32BitValue(myData.choice, myData.currentfilter + 1);
|
||||
GetBestControlRect(myData.choice, &r, &base);
|
||||
SizeControl(myData.choice, r.right - r.left, r.bottom - r.top);
|
||||
UnionRect(&myData.bounds, &r, &myData.bounds);
|
||||
gap = 15;
|
||||
|
||||
HIObjectSetAuxiliaryAccessibilityAttribute((HIObjectRef)myData.choice, 0, kAXDescriptionAttribute, CFSTR("Format"));
|
||||
}
|
||||
|
||||
if (!m_buttonlabel.IsEmpty())
|
||||
{
|
||||
wxMacCFStringHolder cfString(wxStripMenuCodes(m_buttonlabel).c_str(), wxFONTENCODING_DEFAULT);
|
||||
SetRect(&r, myData.bounds.right + gap, margin, 0, 0);
|
||||
CreatePushButtonControl(NULL, &r, cfString, &myData.button);
|
||||
SetControlID(myData.button, &kButtonID);
|
||||
GetBestControlRect(myData.button, &r, &base);
|
||||
SizeControl(myData.button, r.right - r.left, r.bottom - r.top);
|
||||
UnionRect(&myData.bounds, &r, &myData.bounds);
|
||||
}
|
||||
|
||||
// Expand bounding rectangle to include a top and bottom margin
|
||||
myData.bounds.top -= margin;
|
||||
myData.bounds.bottom += margin;
|
||||
|
||||
dialogCreateOptions.optionFlags |= kNavNoTypePopup;
|
||||
|
||||
if (m_dialogStyle & wxFD_SAVE)
|
||||
{
|
||||
dialogCreateOptions.modality = kWindowModalityWindowModal;
|
||||
dialogCreateOptions.parentWindow = (WindowRef) GetParent()->MacGetTopLevelWindowRef();
|
||||
|
||||
myData.saveMode = true;
|
||||
|
||||
if (!numFilters)
|
||||
{
|
||||
dialogCreateOptions.optionFlags |= kNavNoTypePopup;
|
||||
}
|
||||
dialogCreateOptions.optionFlags |= kNavDontAutoTranslate;
|
||||
dialogCreateOptions.optionFlags |= kNavDontAddTranslateItems;
|
||||
|
||||
// The extension is important
|
||||
if (numFilters < 2)
|
||||
dialogCreateOptions.optionFlags |= kNavPreserveSaveFileExtension;
|
||||
|
||||
#if TARGET_API_MAC_OSX
|
||||
if (!(m_dialogStyle & wxFD_OVERWRITE_PROMPT))
|
||||
{
|
||||
dialogCreateOptions.optionFlags |= kNavDontConfirmReplacement;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = ::NavCreatePutFileDialog(&dialogCreateOptions,
|
||||
// Suppresses the 'Default' (top) menu item
|
||||
kNavGenericSignature, kNavGenericSignature,
|
||||
sStandardNavEventFilter,
|
||||
&myData, // for defaultLocation
|
||||
&dialog);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//let people select bundles/programs in dialogs
|
||||
dialogCreateOptions.optionFlags |= kNavSupportPackages;
|
||||
|
||||
navFilterUPP = NewNavObjectFilterUPP(CrossPlatformFilterCallback);
|
||||
err = ::NavCreateGetFileDialog(&dialogCreateOptions,
|
||||
NULL, // NavTypeListHandle
|
||||
sStandardNavEventFilter,
|
||||
NULL, // NavPreviewUPP
|
||||
navFilterUPP,
|
||||
(void *) &myData, // inClientData
|
||||
&dialog);
|
||||
}
|
||||
|
||||
if (err == noErr)
|
||||
err = ::NavDialogRun(dialog);
|
||||
|
||||
if (err == noErr)
|
||||
{
|
||||
myData.window = NavDialogGetWindow(dialog);
|
||||
Rect r;
|
||||
|
||||
// This creates our "fake" dialog with the same dimensions as the sheet so
|
||||
// that Options dialogs will center properly on the sheet. The "fake" dialog
|
||||
// is never actually seen.
|
||||
GetWindowBounds(myData.window, kWindowStructureRgn, &r);
|
||||
wxDialog::Create(NULL, // no parent...otherwise strange things happen
|
||||
wxID_ANY,
|
||||
wxEmptyString,
|
||||
wxPoint(r.left, r.top),
|
||||
wxSize(r.right - r.left, r.bottom - r.top));
|
||||
|
||||
BeginAppModalStateForWindow(myData.window);
|
||||
|
||||
while (myData.showing)
|
||||
{
|
||||
wxTheApp->MacDoOneEvent();
|
||||
}
|
||||
|
||||
EndAppModalStateForWindow(myData.window);
|
||||
}
|
||||
|
||||
// clean up filter related data, etc.
|
||||
if (navFilterUPP)
|
||||
::DisposeNavObjectFilterUPP(navFilterUPP);
|
||||
|
||||
if (err != noErr)
|
||||
return wxID_CANCEL;
|
||||
|
||||
NavReplyRecord navReply;
|
||||
err = ::NavDialogGetReply(dialog, &navReply);
|
||||
if (err == noErr && navReply.validRecord)
|
||||
{
|
||||
AEKeyword theKeyword;
|
||||
DescType actualType;
|
||||
Size actualSize;
|
||||
FSRef theFSRef;
|
||||
wxString thePath ;
|
||||
|
||||
m_filterIndex = myData.currentfilter;
|
||||
|
||||
long count;
|
||||
::AECountItems(&navReply.selection , &count);
|
||||
for (long i = 1; i <= count; ++i)
|
||||
{
|
||||
err = ::AEGetNthPtr(&(navReply.selection), i, typeFSRef, &theKeyword, &actualType,
|
||||
&theFSRef, sizeof(theFSRef), &actualSize);
|
||||
if (err != noErr)
|
||||
break;
|
||||
|
||||
if (m_dialogStyle & wxFD_SAVE)
|
||||
thePath = wxMacFSRefToPath( &theFSRef , navReply.saveFileName ) ;
|
||||
else
|
||||
thePath = wxMacFSRefToPath( &theFSRef ) ;
|
||||
|
||||
if (!thePath)
|
||||
{
|
||||
::NavDisposeReply(&navReply);
|
||||
return wxID_CANCEL;
|
||||
}
|
||||
|
||||
wxFileName fn = ConvertSlashInFileName(thePath);
|
||||
if (!fn.HasExt())
|
||||
{
|
||||
if (!(m_dialogStyle & FD_NO_ADD_EXTENSION))
|
||||
{
|
||||
wxStringTokenizer tokenizer( myData.extensions[m_filterIndex], wxT(";"));
|
||||
if (tokenizer.HasMoreTokens())
|
||||
{
|
||||
wxString extension = tokenizer.GetNextToken().AfterFirst(wxT('.'));
|
||||
if (extension.Right(2) == wxT("*"))
|
||||
{
|
||||
extension = wxEmptyString;
|
||||
}
|
||||
fn.SetExt(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_path = fn.GetFullPath();
|
||||
m_paths.Add(m_path);
|
||||
m_fileName = wxFileNameFromPath(m_path);
|
||||
m_fileNames.Add(m_fileName);
|
||||
}
|
||||
// set these to the first hit
|
||||
m_path = m_paths[0];
|
||||
m_fileName = wxFileNameFromPath(m_path);
|
||||
m_dir = wxPathOnly(m_path);
|
||||
}
|
||||
::NavDisposeReply(&navReply);
|
||||
|
||||
return (err == noErr) ? wxID_OK : wxID_CANCEL;
|
||||
}
|
||||
|
||||
wxString FileDialog::ConvertSlashInFileName(const wxString& filePath)
|
||||
{
|
||||
#if TARGET_API_MAC_OSX
|
||||
wxString path = filePath;
|
||||
wxString filename;
|
||||
wxString newPath = filePath;
|
||||
int pathLen = 1;
|
||||
while (!wxDirExists(wxPathOnly(newPath)) && ! path.IsEmpty())
|
||||
{
|
||||
path = newPath.BeforeLast('/');
|
||||
filename = newPath.AfterLast('/');
|
||||
newPath = path;
|
||||
newPath += ':';
|
||||
newPath += filename;
|
||||
}
|
||||
return newPath;
|
||||
#else
|
||||
return filePath;
|
||||
#endif
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: filedlg.h
|
||||
// Purpose: wxFileDialog class
|
||||
// Author: Stefan Csomor
|
||||
// Modified by: Leland Lucius
|
||||
// Created: 1998-01-01
|
||||
// RCS-ID: $Id: FileDialogPrivate.h,v 1.3 2008-05-24 02:57:39 llucius Exp $
|
||||
// Copyright: (c) Stefan Csomor
|
||||
// Licence: wxWindows licence
|
||||
//
|
||||
// Modified for Audacity to support an additional button on Save dialogs
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _FILEDIALOGMAC_H_
|
||||
#define _FILEDIALOGMAC_H_
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// FileDialog
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class FileDialog: public wxFileDialogBase
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(FileDialog)
|
||||
protected:
|
||||
long m_dialogStyle;
|
||||
wxArrayString m_fileNames;
|
||||
wxArrayString m_paths;
|
||||
|
||||
wxString m_buttonlabel;
|
||||
fdCallback m_callback;
|
||||
void *m_cbdata;
|
||||
static wxString ConvertSlashInFileName(const wxString& filePath);
|
||||
|
||||
public:
|
||||
FileDialog(wxWindow *parent,
|
||||
const wxString& message = wxFileSelectorPromptStr,
|
||||
const wxString& defaultDir = wxEmptyString,
|
||||
const wxString& defaultFile = wxEmptyString,
|
||||
const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
|
||||
long style = 0,
|
||||
const wxPoint& pos = wxDefaultPosition);
|
||||
|
||||
virtual void GetPaths(wxArrayString& paths) const { paths = m_paths; }
|
||||
virtual void GetFilenames(wxArrayString& files) const { files = m_fileNames ; }
|
||||
|
||||
virtual int ShowModal();
|
||||
|
||||
// not supported for file dialog, RR
|
||||
virtual void DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
|
||||
int WXUNUSED(width), int WXUNUSED(height),
|
||||
int WXUNUSED(sizeFlags) = wxSIZE_AUTO) {}
|
||||
|
||||
virtual void EnableButton(wxString label, fdCallback cb, void *cbdata);
|
||||
virtual void ClickButton(int index);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user