]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/dnd.cpp
patch 1306473
[wxWidgets.git] / src / mac / carbon / dnd.cpp
index b9df2ac0049fdbb811a6fcb96d3642ab1b8b3076..49e61ac1098cf923c48dc6286110201c4ecbebb4 100644 (file)
@@ -9,11 +9,7 @@
 // Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "dnd.h"
-#endif
-
-#include "wx/defs.h"
+#include "wx/wxprec.h"
 
 #if wxUSE_DRAG_AND_DROP
 
 #include "wx/gdicmn.h"
 #include "wx/mac/private.h"
 
+#ifndef __DARWIN__
+    #include <Scrap.h>
+#endif
+
 // ----------------------------------------------------------------------------
 // global
 // ----------------------------------------------------------------------------
@@ -182,11 +182,25 @@ bool wxDropTarget::GetData()
             UInt16 flavors = 0 ;
             GetDragItemReferenceNumber((DragReference)m_currentDrag, index, &theItem);
             CountDragItemFlavors( (DragReference)m_currentDrag, theItem , &flavors ) ;
+            bool hasPreferredFormat = false ;
+            wxDataFormat preferredFormat = m_dataObject->GetPreferredFormat( wxDataObject::Set ) ;
+            
+            for ( UInt16 flavor = 1 ; flavor <= flavors ; ++flavor )
+            {
+                result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor , &theType);
+                wxDataFormat format(theType) ;
+                if ( preferredFormat == format )
+                {
+                    hasPreferredFormat = true ;
+                    break ;
+                }
+            }
+            
             for ( UInt16 flavor = 1 ; flavor <= flavors ; ++flavor )
             {
                 result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor , &theType);
                 wxDataFormat format(theType) ;
-                if ( m_dataObject->IsSupportedFormat( format ) )
+                if ( (hasPreferredFormat && format==preferredFormat) || (!hasPreferredFormat && m_dataObject->IsSupportedFormat( format )))
                 {
                     FlavorFlags theFlags;
                     result = GetFlavorFlags((DragReference)m_currentDrag, theItem, theType, &theFlags);
@@ -195,34 +209,45 @@ bool wxDropTarget::GetData()
                         Size dataSize ;
                         Ptr theData ;
                         GetFlavorDataSize((DragReference)m_currentDrag, theItem, theType, &dataSize);
-                        if ( theType == 'TEXT' )
+                        if ( theType == kScrapFlavorTypeText )
                         {
                             // this increment is only valid for allocating, on the next GetFlavorData
                             // call it is reset again to the original value
                             dataSize++ ;
                         }
+                        else if ( theType == kScrapFlavorTypeUnicode )
+                        {
+                            // this increment is only valid for allocating, on the next GetFlavorData
+                            // call it is reset again to the original value
+                            dataSize++ ;
+                            dataSize++ ;
+                        }
                         theData = new char[dataSize];
                         GetFlavorData((DragReference)m_currentDrag, theItem, theType, (void*) theData, &dataSize, 0L); 
-                        if( theType == 'TEXT' )
+                        if( theType == kScrapFlavorTypeText )
                         {
-                            theData[dataSize]=0 ;       
-                            if ( wxApp::s_macDefaultEncodingIsPC )
-                            {
-                                wxMacConvertToPC((char*)theData,(char*)theData,dataSize) ;
-                            }
-                            m_dataObject->SetData( format, dataSize, theData );
+                            theData[dataSize]=0 ; 
+                            m_dataObject->SetData( wxDataFormat(wxDF_TEXT), dataSize , theData );
                         }
+ #if wxUSE_UNICODE
+                        else if ( theType == kScrapFlavorTypeUnicode )
+                        {
+                            theData[dataSize]=0 ; 
+                            theData[dataSize+1]=0 ; 
+                            m_dataObject->SetData( wxDataFormat(wxDF_UNICODETEXT), dataSize , theData );
+                        }
+ #endif
                         else if ( theType == kDragFlavorTypeHFS )
                         {
                             HFSFlavor* theFile = (HFSFlavor*) theData ;
                             wxString name = wxMacFSSpec2MacFilename( &theFile->fileSpec ) ;
-                            if (  firstFileAdded )
-                                ((wxFileDataObject*)m_dataObject)->AddFile( name ) ;
-                            else
+                            if ( !firstFileAdded )
                             {
-                                ((wxFileDataObject*)m_dataObject)->SetData( 0 , name.c_str() ) ;
+                                // reset file list
+                                ((wxFileDataObject*)m_dataObject)->SetData( 0 , "" ) ;
                                 firstFileAdded = true ;    
                             }
+                            ((wxFileDataObject*)m_dataObject)->AddFile( name ) ;
                         }
                         else
                         {
@@ -246,9 +271,10 @@ bool wxDropTarget::GetData()
 // drag request
 
 wxDropSource::wxDropSource(wxWindow *win,
-                           const wxIcon &iconCopy,
-                           const wxIcon &iconMove,
-                           const wxIcon &iconNone)
+                           const wxCursor &cursorCopy,
+                           const wxCursor &cursorMove,
+                           const wxCursor &cursorStop)
+            : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
 {
     wxMacEnsureTrackingHandlersInstalled() ;
     m_window = win;
@@ -256,9 +282,10 @@ wxDropSource::wxDropSource(wxWindow *win,
 
 wxDropSource::wxDropSource(wxDataObject& data,
                            wxWindow *win,
-                           const wxIcon &iconCopy,
-                           const wxIcon &iconMove,
-                           const wxIcon &iconNone)
+                           const wxCursor &cursorCopy,
+                           const wxCursor &cursorMove,
+                           const wxCursor &cursorStop)
+            : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
 {
     wxMacEnsureTrackingHandlersInstalled() ;
     SetData( data );
@@ -270,7 +297,7 @@ wxDropSource::~wxDropSource()
 }
 
 
-wxDragResult wxDropSource::DoDragDrop(int WXUNUSED(flags))
+wxDragResult wxDropSource::DoDragDrop(int flags)
 {
     wxASSERT_MSG( m_data, wxT("Drop source: no data") );
     
@@ -298,14 +325,18 @@ wxDragResult wxDropSource::DoDragDrop(int WXUNUSED(flags))
         Ptr dataPtr = new char[dataSize] ;
         m_data->GetDataHere( formats[i] , dataPtr ) ;
         OSType type = formats[i].GetFormatId() ;
-        if ( type == 'TEXT' )
+        if ( type == 'TEXT' || type == 'utxt' )
         {
-            dataSize-- ;
-            if ( wxApp::s_macDefaultEncodingIsPC )
+            if ( dataSize > 0 )
+                dataSize-- ;
+            dataPtr[ dataSize ] = 0 ;
+            if ( type == 'utxt' )
             {
-                wxMacConvertFromPC((char*)dataPtr,(char*)dataPtr,dataSize) ;
+                if ( dataSize > 0 )
+                    dataSize-- ;
+                dataPtr[ dataSize ] = 0 ;
             }
-            AddDragItemFlavor(theDrag, theItem, type , dataPtr, dataSize, 0);
+            AddDragItemFlavor(theDrag, theItem, type , dataPtr, dataSize, 0);      
         }
         else if (type == kDragFlavorTypeHFS )
         {
@@ -313,7 +344,7 @@ wxDragResult wxDropSource::DoDragDrop(int WXUNUSED(flags))
             OSErr err = noErr;
             CInfoPBRec cat;
             
-            wxMacFilename2FSSpec( dataPtr , &theFlavor.fileSpec ) ;
+            wxMacFilename2FSSpec( wxString( dataPtr , *wxConvCurrent ) , &theFlavor.fileSpec ) ;
             
             cat.hFileInfo.ioNamePtr = theFlavor.fileSpec.name;
             cat.hFileInfo.ioVRefNum = theFlavor.fileSpec.vRefNum;
@@ -380,7 +411,29 @@ wxDragResult wxDropSource::DoDragDrop(int WXUNUSED(flags))
     DisposeDrag(theDrag);
     gTrackingGlobals.m_currentSource = NULL ;
     
-    return wxDragCopy ;
+    bool optionDown = GetCurrentKeyModifiers() & optionKey ;
+    wxDragResult dndresult = wxDragCopy ;
+    if ( flags != wxDrag_CopyOnly ) 
+    {
+        // on mac the option key is always the indication for copy
+        dndresult = optionDown ? wxDragCopy : wxDragMove;
+    }
+    return dndresult;
+}
+
+bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect)
+{
+    const wxCursor& cursor = GetCursor(effect);
+    if ( cursor.Ok() )
+    {
+        cursor.MacInstall() ;
+
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
 }
 
 bool gTrackingGlobalsInstalled = false ;
@@ -416,6 +469,10 @@ pascal OSErr wxMacWindowDragTrackingHandler(DragTrackingMessage theMessage, Wind
     DragAttributes attributes;
     GetDragAttributes(theDrag, &attributes);
     wxTopLevelWindowMac* toplevel = wxFindWinFromMacWindow( theWindow ) ; 
+
+    bool optionDown = GetCurrentKeyModifiers() & optionKey ;
+    wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
+
     switch(theMessage) 
     {
         case kDragTrackingEnterHandler:
@@ -433,16 +490,23 @@ pascal OSErr wxMacWindowDragTrackingHandler(DragTrackingMessage theMessage, Wind
             GetDragMouse(theDrag, &mouse, 0L);
             localMouse = mouse;
             GlobalToLocal(&localMouse);
+
+
             
-//            if (attributes & kDragHasLeftSenderWindow) 
             {
-                wxPoint point(localMouse.h , localMouse.v) ;
                 wxWindow *win = NULL ;
-                toplevel->MacGetWindowFromPointSub( point , &win ) ;
+                ControlPartCode controlPart ;
+                ControlRef control = wxMacFindControlUnderMouse( toplevel , localMouse ,
+                    theWindow , &controlPart ) ;
+                if ( control )
+                    win = wxFindControlFromMacControl( control ) ;
+                else
+                    win = toplevel ;
+                
                 int localx , localy ;
                 localx = localMouse.h ;
                 localy = localMouse.v ;
-                //TODO : should we use client coordinates
+
                 if ( win )
                     win->MacRootWindowToWindow( &localx , &localy ) ;
                 if ( win != trackingGlobals->m_currentTargetWindow )
@@ -464,19 +528,26 @@ pascal OSErr wxMacWindowDragTrackingHandler(DragTrackingMessage theMessage, Wind
                         // this window is entered
                         trackingGlobals->m_currentTargetWindow = win ;
                         trackingGlobals->m_currentTarget = win->GetDropTarget() ;
-                        if ( trackingGlobals->m_currentTarget )
                         {
-                          trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag ) ;
-                           if ( trackingGlobals->m_currentTarget->OnEnter(
-                                localx , localy , wxDragCopy ) != wxDragNone )
+
+                               if ( trackingGlobals->m_currentTarget )
+                               {
+                               trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag ) ;
+                               result = trackingGlobals->m_currentTarget->OnEnter(
+                                       localx , localy , result ) ;
+                            }
+                                
+                           
+                            if ( result != wxDragNone )
                             {
-                              int x , y ;
-                              x = y = 0 ;
-                              win->MacWindowToRootWindow( &x , &y ) ;
-                              RgnHandle hiliteRgn = NewRgn() ;
-                              SetRectRgn( hiliteRgn , x , y , x+win->GetSize().x ,y+win->GetSize().y) ;
-                              ShowDragHilite(theDrag, hiliteRgn, true);
-                              DisposeRgn( hiliteRgn ) ;
+                                int x , y ;
+                                x = y = 0 ;
+                                win->MacWindowToRootWindow( &x , &y ) ;
+                                RgnHandle hiliteRgn = NewRgn() ;
+                                Rect r = { y , x , y+win->GetSize().y , x+win->GetSize().x } ;
+                                RectRgn( hiliteRgn , &r ) ;
+                                ShowDragHilite(theDrag, hiliteRgn, true);
+                                DisposeRgn( hiliteRgn ) ;
                             }
                         }
                     }
@@ -487,12 +558,46 @@ pascal OSErr wxMacWindowDragTrackingHandler(DragTrackingMessage theMessage, Wind
                     {
                         trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag ) ;
                         trackingGlobals->m_currentTarget->OnDragOver(
-                            localx , localy , wxDragCopy ) ;
+                            localx , localy , result ) ;
                     }
                 }
+
+                // set cursor for OnEnter and OnDragOver
+                if ( trackingGlobals->m_currentSource && trackingGlobals->m_currentSource->GiveFeedback( result ) == FALSE )
+                {
+                  if ( trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) == FALSE )
+                  {
+                      switch( result )
+                      {
+                          case wxDragCopy :
+                              {
+                                  wxCursor cursor(wxCURSOR_COPY_ARROW) ;
+                                  cursor.MacInstall() ;
+                              }
+                              break ;
+                          case wxDragMove :
+                              {
+                                  wxCursor cursor(wxCURSOR_ARROW) ;
+                                  cursor.MacInstall() ;
+                              }
+                              break ;
+                          case wxDragNone :
+                              {
+                                  wxCursor cursor(wxCURSOR_NO_ENTRY) ;
+                                  cursor.MacInstall() ;
+                              }
+                              break ;
+
+                          case wxDragError:
+                          case wxDragLink:
+                          case wxDragCancel:
+                              // put these here to make gcc happy
+                              ;
+                      }
+                  }
+                }
                 
-          }
-            // MyTrackItemUnderMouse(localMouse, theWindow);
+            }
             break;
         case kDragTrackingLeaveWindow:
             if (trackingGlobals->m_currentTarget) 
@@ -529,7 +634,9 @@ pascal OSErr wxMacWindowDragReceiveHandler(WindowPtr theWindow,
             trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx , &localy ) ;
         if ( trackingGlobals->m_currentTarget->OnDrop( localx , localy ) )
         {
-            trackingGlobals->m_currentTarget->OnData( localx , localy , wxDragCopy ) ;
+            bool optionDown = GetCurrentKeyModifiers() & optionKey ;
+            wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
+            trackingGlobals->m_currentTarget->OnData( localx , localy , result ) ;
         }
     }
     return(noErr);