📄 dnd.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dnd.cpp
// Purpose: wxDropTarget, wxDropSource implementations
// Author: Stefan Csomor
// Modified by:
// Created: 1998-01-01
// RCS-ID: $Id: dnd.cpp,v 1.54 2006/06/19 20:18:28 ABX Exp $
// Copyright: (c) 1998 Stefan Csomor
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#if wxUSE_DRAG_AND_DROP
#include "wx/dnd.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/window.h"
#include "wx/toplevel.h"
#include "wx/gdicmn.h"
#endif // WX_PRECOMP
#include "wx/mac/private.h"
#ifndef __DARWIN__
#include <Scrap.h>
#endif
// ----------------------------------------------------------------------------
// globals
// ----------------------------------------------------------------------------
typedef struct
{
wxWindow *m_currentTargetWindow;
wxDropTarget *m_currentTarget;
wxDropSource *m_currentSource;
}
MacTrackingGlobals;
MacTrackingGlobals gTrackingGlobals;
void wxMacEnsureTrackingHandlersInstalled();
//----------------------------------------------------------------------------
// wxDropTarget
//----------------------------------------------------------------------------
wxDropTarget::wxDropTarget( wxDataObject *data )
: wxDropTargetBase( data )
{
wxMacEnsureTrackingHandlersInstalled();
}
wxDragResult wxDropTarget::OnDragOver(
wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
wxDragResult def )
{
return CurrentDragHasSupportedFormat() ? def : wxDragNone;
}
bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
{
if (m_dataObject == NULL)
return false;
return CurrentDragHasSupportedFormat();
}
wxDragResult wxDropTarget::OnData(
wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
wxDragResult def )
{
if (m_dataObject == NULL)
return wxDragNone;
if (!CurrentDragHasSupportedFormat())
return wxDragNone;
return GetData() ? def : wxDragNone;
}
bool wxDropTarget::CurrentDragHasSupportedFormat()
{
bool supported = false;
if ( gTrackingGlobals.m_currentSource != NULL )
{
wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
if ( data )
{
size_t formatcount = data->GetFormatCount();
wxDataFormat *array = new wxDataFormat[formatcount];
data->GetAllFormats( array );
for (size_t i = 0; !supported && i < formatcount; i++)
{
wxDataFormat format = array[i];
if ( m_dataObject->IsSupported( format ) )
{
supported = true;
break;
}
}
delete [] array;
}
}
if ( !supported )
{
UInt16 items;
OSErr result;
ItemReference theItem;
FlavorType theType;
UInt16 flavors = 0;
CountDragItems( (DragReference)m_currentDrag, &items );
for (UInt16 index = 1; index <= items && !supported; ++index)
{
flavors = 0;
GetDragItemReferenceNumber( (DragReference)m_currentDrag, index, &theItem );
CountDragItemFlavors( (DragReference)m_currentDrag, theItem, &flavors );
for ( UInt16 flavor = 1; flavor <= flavors; ++flavor )
{
result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
if ( m_dataObject->IsSupportedFormat( wxDataFormat( theType ) ) )
{
supported = true;
break;
}
}
}
}
return supported;
}
bool wxDropTarget::GetData()
{
if (m_dataObject == NULL)
return false;
if ( !CurrentDragHasSupportedFormat() )
return false;
bool transferred = false;
if ( gTrackingGlobals.m_currentSource != NULL )
{
wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
if (data != NULL)
{
size_t formatcount = data->GetFormatCount();
wxDataFormat *array = new wxDataFormat[formatcount];
data->GetAllFormats( array );
for (size_t i = 0; !transferred && i < formatcount; i++)
{
wxDataFormat format = array[i];
if ( m_dataObject->IsSupported( format ) )
{
int size = data->GetDataSize( format );
transferred = true;
if (size == 0)
{
m_dataObject->SetData( format, 0, 0 );
}
else
{
char *d = new char[size];
data->GetDataHere( format, (void*)d );
m_dataObject->SetData( format, size, d );
delete [] d;
}
}
}
delete [] array;
}
}
if ( !transferred )
{
UInt16 items;
OSErr result;
ItemReference theItem;
FlavorType theType;
FlavorFlags theFlags;
UInt16 flavors;
wxString filenamesPassed;
CountDragItems( (DragReference)m_currentDrag, &items );
for (UInt16 index = 1; index <= items; ++index)
{
flavors = 0;
GetDragItemReferenceNumber( (DragReference)m_currentDrag, index, &theItem );
CountDragItemFlavors( (DragReference)m_currentDrag, theItem, &flavors );
wxDataFormat preferredFormat = m_dataObject->GetPreferredFormat( wxDataObject::Set );
bool hasPreferredFormat = false;
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 ((hasPreferredFormat && format == preferredFormat)
|| (!hasPreferredFormat && m_dataObject->IsSupportedFormat( format )))
{
result = GetFlavorFlags( (DragReference)m_currentDrag, theItem, theType, &theFlags );
if (result == noErr)
{
Size dataSize;
Ptr theData;
GetFlavorDataSize( (DragReference)m_currentDrag, theItem, theType, &dataSize );
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++;
}
if (dataSize > 0)
theData = new char[dataSize];
else
theData = NULL;
GetFlavorData( (DragReference)m_currentDrag, theItem, theType, (void*)theData, &dataSize, 0L );
switch (theType)
{
case kScrapFlavorTypeText:
theData[dataSize] = 0;
m_dataObject->SetData( wxDataFormat(wxDF_TEXT), dataSize, theData );
break;
#if wxUSE_UNICODE
case kScrapFlavorTypeUnicode:
theData[dataSize + 0] =
theData[dataSize + 1] = 0;
m_dataObject->SetData( wxDataFormat(wxDF_UNICODETEXT), dataSize, theData );
break;
#endif
case kDragFlavorTypeHFS:
if (theData != NULL)
{
HFSFlavor* theFile = (HFSFlavor*)theData;
wxString name = wxMacFSSpec2MacFilename( &theFile->fileSpec );
if (!name.empty())
filenamesPassed += name + wxT("\n");
}
break;
default:
m_dataObject->SetData( format, dataSize, theData );
break;
}
delete [] theData;
}
break;
}
}
}
if (filenamesPassed.length() > 0)
{
wxCharBuffer buf = filenamesPassed.fn_str();
m_dataObject->SetData( wxDataFormat(wxDF_FILENAME), strlen( buf ), (const char*)buf );
}
}
return true;
}
//-------------------------------------------------------------------------
// wxDropSource
//-------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// drag request
wxDropSource::wxDropSource(wxWindow *win,
const wxCursor &cursorCopy,
const wxCursor &cursorMove,
const wxCursor &cursorStop)
: wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
{
wxMacEnsureTrackingHandlersInstalled();
m_window = win;
}
wxDropSource::wxDropSource(wxDataObject& data,
wxWindow *win,
const wxCursor &cursorCopy,
const wxCursor &cursorMove,
const wxCursor &cursorStop)
: wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
{
wxMacEnsureTrackingHandlersInstalled();
SetData( data );
m_window = win;
}
wxDropSource::~wxDropSource()
{
}
wxDragResult wxDropSource::DoDragDrop(int flags)
{
wxASSERT_MSG( m_data, wxT("Drop source: no data") );
if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
return (wxDragResult)wxDragNone;
OSStatus result;
DragReference theDrag;
RgnHandle dragRegion;
if ((result = NewDrag( &theDrag )) != noErr)
return wxDragNone;
// add data to drag
size_t formatCount = m_data->GetFormatCount();
wxDataFormat *formats = new wxDataFormat[formatCount];
m_data->GetAllFormats( formats );
ItemReference theItem = 1;
for ( size_t i = 0; i < formatCount; ++i )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -