]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/dirdlg.cpp
scaling for 24x24 and 64x64 sizes
[wxWidgets.git] / src / mac / carbon / dirdlg.cpp
index edfc211caa05465c25cd36acde69e55c778c1d88..96cbb64de2e8ce0ab35855c93b96427bbcde8ddf 100644 (file)
 /////////////////////////////////////////////////////////////////////////////
 // Name:        dirdlg.cpp
 // Purpose:     wxDirDialog
-// Author:      AUTHOR
+// Author:      Stefan Csomor
 // Modified by:
-// Created:     ??/??/98
+// Created:     1998-01-01
 // RCS-ID:      $Id$
-// Copyright:   (c) AUTHOR
-// Licence:    wxWindows licence
+// Copyright:   (c) Stefan Csomor
+// Licence:       wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
 #pragma implementation "dirdlg.h"
 #endif
 
-#include "wx/defs.h"
+#include "wx/wxprec.h"
+
+#if wxUSE_DIRDLG
+
 #include "wx/utils.h"
 #include "wx/dialog.h"
 #include "wx/dirdlg.h"
 
 #include "wx/cmndata.h"
 
+#include "wx/mac/private.h"
+
+#ifdef __DARWIN__
+  #include <Carbon/Carbon.h>
+#else
+  #include <Navigation.h>
+#endif
+
 #if !USE_SHARED_LIBRARY
 IMPLEMENT_CLASS(wxDirDialog, wxDialog)
 #endif
 
-enum {
-       kSelectItem = 10,                       // select button item number
-       kSFGetFolderDlgID = 250,        // dialog resource number
-       kStrListID = 250,                       // our strings
-       kSelectStrNum = 1,                      // word 'Select: ' for button
-       kDesktopStrNum = 2,                     // word 'Desktop' for button
-       kSelectNoQuoteStrNum = 3,       // word 'Select: ' for button
-       
-       kUseQuotes = true,                      // parameter for SetButtonName
-       kDontUseQuotes = false
-};
-
-// 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 UserDataRec {
-       StandardFileReply       *sfrPtr;
-       FSSpec                          oldSelectionFSSpec;
-       DialogPtr                       theDlgPtr;
-};
-typedef struct UserDataRec
-       UserDataRec, *UserDataRecPtr;
-
-static void GetLabelString(StringPtr theStr, short stringNum)
-{
-       GetIndString(theStr, kStrListID, stringNum);
-}
-
-static void CopyPStr(StringPtr src, StringPtr dest)
-{
-       BlockMoveData(src, dest, 1 + src[0]);
-}
-
-static char GetSelectKey(void)
-{
-       // this is the key used to trigger the select button
-       
-       // NOT INTERNATIONAL SAVVY; should at least grab it from resources
-       
-       return 's';
-}
-
-
-// SetButtonName sets the name of the Select button in the dialog
-//
-// To do this, we need to call the Script Manager to truncate the
-// label in the middle to fit the button and to merge the button
-// name with the word Select (possibly followed by quotes).  Using
-// the Script Manager avoids all sorts of problems internationally.
-//
-// buttonName is the name to appear following the word Select
-// quoteFlag should be true if the name is to appear in quotes
-
-static void SetButtonName(DialogPtr theDlgPtr, short buttonID, StringPtr buttonName,
-                                       Boolean quoteFlag)
-{
-       short   buttonType;
-       Handle  buttonHandle;
-       Rect    buttonRect;
-       short   textWidth;
-       Handle  labelHandle;
-       Handle  nameHandle;
-       Str15   keyStr;
-       Str255  labelStr;
-       OSErr   err;
-       
-       nameHandle = nil;
-       labelHandle = nil;
-       
-       // get the details of the button from the dialog
-       
-       GetDialogItem(theDlgPtr, buttonID, &buttonType, &buttonHandle, &buttonRect);
-       
-       // get the string for the select button label, "Select ^0" or "Select Ò^0Ó"
-       
-       GetLabelString(labelStr, (quoteFlag == kUseQuotes) ? kSelectStrNum : kSelectNoQuoteStrNum);
-       
-       // make string handles containing the select button label and the
-       // file name to be stuffed into the button
-       
-       err = PtrToHand(&labelStr[1], &labelHandle, labelStr[0]);
-       if (err != noErr) goto Bail;
-       
-       // cut out the middle of the file name to fit the button
-       //
-       // we'll temporarily use labelStr here to hold the modified button name
-       // since we don't own the buttonName string storage space
-       
-       textWidth = (buttonRect.right - buttonRect.left) - StringWidth(labelStr);
-
-       CopyPStr(buttonName, labelStr);
-       (void) TruncString(textWidth, labelStr, smTruncMiddle);
-       
-       err = PtrToHand(&labelStr[1], &nameHandle, labelStr[0]);
-       if (err != noErr) goto Bail;
-       
-       // replace the ^0 in the Select string with the file name
-       
-       CopyPStr("\p^0", keyStr);
-       
-       (void) ReplaceText(labelHandle, nameHandle, keyStr);
-       
-       labelStr[0] = (unsigned char) GetHandleSize(labelHandle);
-       BlockMoveData(*labelHandle, &labelStr[1], labelStr[0]);
-       
-       // now set the control title, and re-validate the area
-       // above the control to avoid a needless redraw
-       
-       SetControlTitle((ControlHandle) buttonHandle, labelStr);
-       
-       ValidRect(&buttonRect);
-
-Bail:
-       if (nameHandle)         DisposeHandle(nameHandle);
-       if (labelHandle)        DisposeHandle(labelHandle);
-       
-}
-
-// FlashButton briefly highlights the dialog button 
-// as feedback for key equivalents
-
-static void FlashButton(DialogPtr theDlgPtr, short buttonID)
-{
-       short   buttonType;
-       Handle  buttonHandle;
-       Rect    buttonRect;
-       unsigned long   finalTicks;
-       
-       GetDialogItem(theDlgPtr, buttonID, &buttonType, &buttonHandle, &buttonRect);
-       HiliteControl((ControlHandle) buttonHandle, kControlButtonPart);
-       Delay(10, &finalTicks);
-       HiliteControl((ControlHandle) buttonHandle, 0);
-}
-
-static Boolean SameFSSpec(FSSpecPtr spec1, FSSpecPtr spec2)
-{
-       return (spec1->vRefNum == spec2->vRefNum
-                       && spec1->parID == spec2->parID
-                       && EqualString(spec1->name, spec2->name, false, false));
-}
-// MyModalDialogFilter maps a key to the Select button, and handles
-// flashing of the button when the key is hit
-
-static pascal Boolean SFGetFolderModalDialogFilter(DialogPtr theDlgPtr, EventRecord *eventRec,
-                                                                                       short *item, Ptr dataPtr)
-{
-#pragma unused (dataPtr)
-
-       // make certain the proper dialog is showing, 'cause standard file
-       // can nest dialogs but calls the same filter for each
-       
-       if (((WindowPeek) theDlgPtr)->refCon == sfMainDialogRefCon)
-       {
-               // check if the select button was hit
-               
-               if ((eventRec->what == keyDown)
-                       && (eventRec->modifiers & cmdKey) 
-                       && ((eventRec->message & charCodeMask) == GetSelectKey()))
-               {
-                       *item = kSelectItem;
-                       FlashButton(theDlgPtr, kSelectItem);
-                       return true;
-               }
-       }
-               
-       return false;
-}
-
-
-// MyDlgHook is a hook routine that maps the select button to Open
-// and sets the Select button name
-
-static pascal short SFGetFolderDialogHook(short item, DialogPtr theDlgPtr, Ptr dataPtr)
-{
-       UserDataRecPtr  theUserDataRecPtr;
-       long                    desktopDirID;
-       short                   desktopVRefNum;
-       FSSpec                  tempSpec;
-       Str63                   desktopName;
-       OSErr                   err;
-       
-       // be sure Std File is really showing us the intended dialog,
-       // not a nested modal dialog
-       
-       if (((WindowPeek) theDlgPtr)->refCon != sfMainDialogRefCon)
-       {
-               return item;
-       }
-       
-       theUserDataRecPtr = (UserDataRecPtr) dataPtr;
-       
-       // map the Select button to Open
-       
-       if (item == kSelectItem)
-       {
-               item = sfItemOpenButton;
-       }
-       
-       // find the desktop folder
-       
-       err = FindFolder(theUserDataRecPtr->sfrPtr->sfFile.vRefNum,
-                                       kDesktopFolderType, kDontCreateFolder,
-                                       &desktopVRefNum, &desktopDirID);
-       
-       if (err != noErr)
-       {
-               // for errors, get value that won't match any real vRefNum/dirID
-               desktopVRefNum = 0;
-               desktopDirID = 0;
-       }
-       
-       // change the Select button label if the selection has changed or
-       // if this is the first call to the hook
-       
-       if (item == sfHookFirstCall
-               || item == sfHookChangeSelection
-               || item == sfHookRebuildList
-               || ! SameFSSpec(&theUserDataRecPtr->sfrPtr->sfFile,
-                                       &theUserDataRecPtr->oldSelectionFSSpec))
-       {
-               // be sure there is a file name selected
-               
-               if (theUserDataRecPtr->sfrPtr->sfFile.name[0] != '\0')
-               {
-                       SetButtonName(theDlgPtr, kSelectItem, 
-                                                       theUserDataRecPtr->sfrPtr->sfFile.name, 
-                                                       kUseQuotes);    // true -> use quotes
-               }
-               else
-               {
-                       // is the desktop selected?
-                       
-                       if (theUserDataRecPtr->sfrPtr->sfFile.vRefNum == desktopVRefNum
-                               && theUserDataRecPtr->sfrPtr->sfFile.parID == desktopDirID)
-                       {
-                               // set button to "Select Desktop"
-                               
-                               GetLabelString(desktopName, kDesktopStrNum);
-                               SetButtonName(theDlgPtr, kSelectItem, 
-                                                               desktopName, kDontUseQuotes);   // false -> no quotes
-                       }
-                       else
-                       {
-                               // get parent directory's name for the Select button
-                               //
-                               // passing an empty name string to FSMakeFSSpec gets the
-                               // name of the folder specified by the parID parameter
-                               
-                               (void) FSMakeFSSpec(theUserDataRecPtr->sfrPtr->sfFile.vRefNum,
-                                       theUserDataRecPtr->sfrPtr->sfFile.parID, "\p",
-                                       &tempSpec);
-                               SetButtonName(theDlgPtr, kSelectItem, 
-                                                       tempSpec.name, kUseQuotes); // true -> use quotes
-                       }
-               }
-       }
-       
-       // save the current selection as the old selection for comparison next time
-       //
-       // it's not valid on the first call, though, or if we don't have a 
-       // name available from standard file
-       
-       if (item != sfHookFirstCall || theUserDataRecPtr->sfrPtr->sfFile.name[0] != '\0')
-       {
-               theUserDataRecPtr->oldSelectionFSSpec = theUserDataRecPtr->sfrPtr->sfFile;
-       }
-       else
-       {
-               // on first call, empty string won't set the button correctly, 
-               // so invalidate oldSelection
-               
-               theUserDataRecPtr->oldSelectionFSSpec.vRefNum = 999;
-               theUserDataRecPtr->oldSelectionFSSpec.parID = 0;
-       }
-       
-       return item;
-}
-
-void StandardGetFolder( ConstStr255Param message , ConstStr255Param path , FileFilterYDUPP fileFilter, StandardFileReply *theSFR)
-{
-       Point                           thePt;
-       SFTypeList                      mySFTypeList;
-       UserDataRec                     myData;
-       FSSpec                          tempSpec;
-       Boolean                         folderFlag;
-       Boolean                         wasAliasedFlag;
-       DlgHookYDUPP            dlgHookUPP;
-       ModalFilterYDUPP        myModalFilterUPP;
-       OSErr                           err;
-       
-       
-       // presumably we're running System 7 or later so CustomGetFile is
-       // available
-       
-       // set initial contents of Select button to a space
-       
-       CopyPStr("\p ", theSFR->sfFile.name);
-       
-       // point the user data parameter at the reply record so we can get to it later
-       
-       myData.sfrPtr = theSFR;
-       
-       // display the dialog
-       
-       dlgHookUPP = NewDlgHookYDProc(SFGetFolderDialogHook);
-       myModalFilterUPP = NewModalFilterYDProc(SFGetFolderModalDialogFilter);
-       
-       thePt.h = thePt.v = -1; // center dialog
-       
-       ParamText( message , NULL , NULL , NULL ) ;
-       
-       CustomGetFile(  fileFilter, 
-                                       -1,                                     // show all types
-                                       mySFTypeList,
-                                       theSFR,
-                                       kSFGetFolderDlgID,
-                                       thePt,                          // top left point
-                                       dlgHookUPP,
-                                       myModalFilterUPP,
-                                       nil,                            // activate list
-                                       nil,                            // activate proc
-                                       &myData);
-                                       
-       DisposeRoutineDescriptor(dlgHookUPP);
-       DisposeRoutineDescriptor(myModalFilterUPP);
-       
-       // if cancel wasn't pressed and no fatal error occurred...
-       
-       if (theSFR->sfGood)
-       {
-               // if no name is in the reply record file spec,
-               // use the file spec of the parent folder
-               
-               if (theSFR->sfFile.name[0] == '\0')
-               {
-                       err = FSMakeFSSpec(theSFR->sfFile.vRefNum, theSFR->sfFile.parID,
-                                                               "\p", &tempSpec);
-                       if (err == noErr)
-                       {
-                               theSFR->sfFile = tempSpec;
-                       }
-                       else
-                       {
-                               // no name to return, forget it
-                               
-                               theSFR->sfGood = false;
-                       }
-               }
-               
-               // if there is now a name in the file spec, check if it's
-               // for a folder or a volume
-               
-               if (theSFR->sfFile.name[0] != '\0')
-               {
-                       // the parID of the root of a disk is always fsRtParID == 1
-                       
-                       if (theSFR->sfFile.parID == fsRtParID)
-                       {
-                               theSFR->sfIsVolume = true;
-                               theSFR->sfIsFolder = false;     // it would be reasonable for this to be true, too
-                       }
-                       
-                       // we have a valid FSSpec, now let's make sure it's not for an alias file
-                       
-                       err = ResolveAliasFile(&theSFR->sfFile, true, &folderFlag, &wasAliasedFlag);
-                       if (err != noErr)
-                       {
-                               theSFR->sfGood = false;
-                       }
-                       
-                       // did the alias resolve to a folder?
-                       
-                       if (folderFlag  && ! theSFR->sfIsVolume)
-                       {
-                               theSFR->sfIsFolder = true;
-                       }
-               }
-       }
-}
-
-static pascal Boolean OnlyVisibleFoldersCustomFileFilter(CInfoPBPtr myCInfoPBPtr, Ptr dataPtr)
-{
-#pragma unused (dataPtr)
-
-       // return true if this item is invisible or a file
-
-       Boolean visibleFlag;
-       Boolean folderFlag;
-       
-       visibleFlag = ! (myCInfoPBPtr->hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible);
-       folderFlag = (myCInfoPBPtr->hFileInfo.ioFlAttrib & 0x10);
-       
-       // because the semantics of the filter proc are "true means don't show
-       // it" we need to invert the result that we return
-       
-       return !(visibleFlag && folderFlag);
-}
-
-wxDirDialog::wxDirDialog(wxWindow *parent, const wxString& message,
-        const wxString& defaultPath,
-        long style, const wxPoint& pos)
+wxDirDialog::wxDirDialog(wxWindow *parent,
+                         const wxString& message,
+                         const wxString& defaultPath,
+                         long style,
+                         const wxPoint& WXUNUSED(pos),
+                         const wxSize& WXUNUSED(size),
+                         const wxString& WXUNUSED(name))
 {
+    wxASSERT_MSG( NavServicesAvailable() , wxT("Navigation Services are not running") ) ;
     m_message = message;
     m_dialogStyle = style;
     m_parent = parent;
-       m_path = defaultPath;
+    m_path = defaultPath;
 }
 
 int wxDirDialog::ShowModal()
 {
-       {
-               Str255                          prompt ;
-               Str255                          path ;
-
-               strcpy((char *)prompt, m_message) ;
-               c2pstr((char *)prompt ) ;
-       
-               strcpy((char *)path, m_path ) ;
-               c2pstr((char *)path ) ;
-
-               FileFilterYDUPP         invisiblesExcludedCustomFilterUPP;
-               StandardFileReply       reply ;
-               invisiblesExcludedCustomFilterUPP = 
-                       NewFileFilterYDProc(OnlyVisibleFoldersCustomFileFilter);
-
-               StandardGetFolder( prompt , path , invisiblesExcludedCustomFilterUPP, &reply);
-       
-               DisposeRoutineDescriptor(invisiblesExcludedCustomFilterUPP);
-               if ( reply.sfGood == false )
-               {
-                       m_path = "" ;
-                       return wxID_CANCEL ;
-               }
-               else
-               {
-                       m_path = wxMacFSSpec2UnixFilename( &reply.sfFile ) ;
-                       return wxID_OK ;
-               }
-       }
-       return wxID_CANCEL;
+    NavDialogOptions        mNavOptions;
+    NavObjectFilterUPP        mNavFilterUPP = NULL;
+    NavPreviewUPP            mNavPreviewUPP = NULL ;
+    NavReplyRecord            mNavReply;
+    AEDesc*                    mDefaultLocation = NULL ;
+    bool                    mSelectDefault = false ;
+    
+    ::NavGetDefaultDialogOptions(&mNavOptions);
+
+    mNavFilterUPP    = nil;
+    mNavPreviewUPP    = nil;
+    mSelectDefault    = false;
+    mNavReply.validRecord                = false;
+    mNavReply.replacing                    = false;
+    mNavReply.isStationery                = false;
+    mNavReply.translationNeeded            = false;
+    mNavReply.selection.descriptorType = typeNull;
+    mNavReply.selection.dataHandle        = nil;
+    mNavReply.keyScript                    = smSystemScript;
+    mNavReply.fileTranslation            = nil;
+    
+    // Set default location, the location
+    //   that's displayed when the dialog
+    //   first appears
+    
+    if ( mDefaultLocation ) {
+        
+        if (mSelectDefault) {
+            mNavOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
+        } else {
+            mNavOptions.dialogOptionFlags &= ~kNavSelectDefaultLocation;
+        }
+    }
+    
+    OSErr err = ::NavChooseFolder(
+                        mDefaultLocation,
+                        &mNavReply,
+                        &mNavOptions,
+                        NULL,
+                        mNavFilterUPP,
+                        0L);                            // User Data
+    
+    if ( (err != noErr) && (err != userCanceledErr) ) {
+        m_path = wxT("") ;
+        return wxID_CANCEL ;
+    }
+
+    if (mNavReply.validRecord) {        // User chose a folder
+    
+        FSRef folderInfo;
+        AEDesc specDesc ;
+        
+        OSErr err = ::AECoerceDesc( &mNavReply.selection , typeFSRef, &specDesc);
+        if ( err != noErr ) {
+            m_path = wxT("") ;
+            return wxID_CANCEL ;
+        }            
+        folderInfo = **(FSRef**) specDesc.dataHandle;
+        if (specDesc.dataHandle != nil) {
+            ::AEDisposeDesc(&specDesc);
+        }
+
+        m_path = wxMacFSRefToPath( &folderInfo ) ;
+        return wxID_OK ;
+    }
+    return wxID_CANCEL;
 }
 
+#endif