Update of /cvsroot/audacity/lib-src/FileDialog/mac
In directory sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv617/FileDialog/mac
Added Files:
FileDialog.h FileDialog.hpp
Log Message:
New FileDialog (modified wx(Generic)FileDialog actually) that adds support
for an extra button. (All this just for one little old button... ;-))
--- NEW FILE: FileDialog.h ---
/////////////////////////////////////////////////////////////////////////////
// Name: filedlg.h
// Purpose: wxFileDialog class
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id: FileDialog.h,v 1.1 2007/04/06 10:16:52 llucius Exp $
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _FILEDIALOGMAC_H_
#define _FILEDIALOGMAC_H_
//-------------------------------------------------------------------------
// FileDialog
//-------------------------------------------------------------------------
class WXDLLEXPORT FileDialog: public wxFileDialogBase
{
DECLARE_DYNAMIC_CLASS(FileDialog)
protected:
wxArrayString m_fileNames;
wxArrayString m_paths;
wxString m_buttonlabel;
fdCallback m_callback;
void *m_cbdata;
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
--- NEW FILE: FileDialog.hpp ---
/////////////////////////////////////////////////////////////////////////////
// Name: filedlg.cpp
// Purpose: wxFileDialog
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id: FileDialog.hpp,v 1.1 2007/04/06 10:16:52 llucius Exp $
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#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"
#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;
Rect bounds;
ControlRef userpane;
ControlRef choice;
ControlRef button;
MenuRef menu;
wxArrayString name;
wxArrayString extensions;
wxArrayLong filtermactypes;
wxString defaultLocation;
int currentfilter;
bool saveMode;
};
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)
{
ControlID cid;
GetControlID(control, &cid);
HandleControlClick(control, where, evt->modifiers,
(ControlActionUPP)-1L);
if (cid.signature == kCustom)
{
switch (cid.id)
{
case kChoice:
{
MenuRef menu;
UInt32 v;
menu = GetControlPopupMenuRef(control);
v = GetControl32BitValue(control) - 1;
const size_t numFilters = data->extensions.GetCount();
if (v < numFilters)
{
data->currentfilter = v;
if (data->saveMode)
{
int i = data->currentfilter;
wxString extension =
data->extensions[i].AfterLast('.') ;
extension.MakeLower() ;
wxString sfilename ;
wxMacCFStringHolder
cfString(NavDialogGetSaveFileName(callBackParms->context), false);
sfilename = cfString.AsString() ;
int pos = sfilename.Find('.', true) ;
if (pos != wxNOT_FOUND)
{
sfilename = sfilename.Left(pos + 1) + extension;
cfString.Assign(sfilename,
wxFONTENCODING_DEFAULT);
NavDialogSetSaveFileName(callBackParms->context, cfString);
}
}
}
break;
}
case kButton:
{
data->me->ClickButton(GetControl32BitValue(data->choice) -
1);
break;
}
}
}
}
}
static void HandleNormalEvents(NavCBRecPtr callBackParms, CustomData *data)
{
switch (callBackParms->eventData.eventDataParms.event->what)
{
case mouseDown:
{
HandleCustomMouseDown(callBackParms, data);
break;
}
}
}
static void HandleStartEvent(NavCBRecPtr callBackParms, CustomData *data)
{
CreateUserPaneControl(callBackParms->window, &data->bounds,
kControlSupportsEmbedding, &data->userpane);
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;
}
}
}
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 )
{
//for ( int i = 0 ; i < data->numfilters ; ++i )
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;
}
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, m_font.GetEncoding());
dialogCreateOptions.windowTitle = message;
wxMacCFStringHolder defaultFileName(m_fileName, m_font.GetEncoding());
dialogCreateOptions.saveFileName = defaultFileName;
NavDialogRef dialog;
NavObjectFilterUPP navFilterUPP = NULL;
CustomData myData;
SetRect(&myData.bounds, 0, 0, 0, 0);
myData.me = this;
myData.defaultLocation = m_dir;
myData.userpane = NULL;
myData.choice = NULL;
myData.button = NULL;
myData.saveMode = false;
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],
m_font.GetEncoding()),
0,
i,
NULL);
}
SetRect(&r, 0, margin, 0, 0);
CreatePopupButtonControl(NULL, &r, CFSTR("Format:"), -12345, false, 50,
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;
}
if (!m_buttonlabel.IsEmpty())
{
wxMacCFStringHolder cfString(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 & wxSAVE)
{
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 & wxOVERWRITE_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);
// 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 & wxSAVE)
thePath = wxMacFSRefToPath( &theFSRef , navReply.saveFileName )
;
else
thePath = wxMacFSRefToPath( &theFSRef ) ;
if (!thePath)
{
::NavDisposeReply(&navReply);
return wxID_CANCEL;
}
m_path = thePath;
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;
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs