diff --git a/include/wx/dataview.h b/include/wx/dataview.h index 0d7f46cd8f..624fbc3526 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -535,6 +535,10 @@ private: // wxDataViewCtrlBase // --------------------------------------------------------- +#if wxUSE_DRAG_AND_DROP +WX_DEFINE_ARRAY(wxDataFormat,wxDataFormatArray); +#endif + #define wxDV_SINGLE 0x0000 // for convenience #define wxDV_MULTIPLE 0x0001 // can select multiple items @@ -760,8 +764,21 @@ public: #if wxUSE_DRAG_AND_DROP virtual bool EnableDragSource(const wxDataFormat& WXUNUSED(format)) { return false; } - virtual bool EnableDropTarget(const wxDataFormat& WXUNUSED(format)) - { return false; } + + bool EnableDropTarget(const wxDataFormatArray& formats) + { return DoEnableDropTarget(formats); } + + bool EnableDropTarget(const wxDataFormat& format) + { + wxDataFormatArray formats; + if (format.GetType() != wxDF_INVALID) + { + formats.Add(format); + } + + return EnableDropTarget(formats); + } + #endif // wxUSE_DRAG_AND_DROP // define control visual attributes @@ -792,6 +809,14 @@ protected: virtual void DoSetExpanderColumn() = 0 ; virtual void DoSetIndent() = 0; +#if wxUSE_DRAG_AND_DROP + virtual wxDataObject* CreateDataObject(const wxDataFormatArray& formats); + + virtual bool DoEnableDropTarget(const wxDataFormatArray& WXUNUSED(formats)) + { return false; } + +#endif // wxUSE_DRAG_AND_DROP + // Just expand this item assuming it is already shown, i.e. its parent has // been already expanded using ExpandAncestors(). // diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index 262d318696..f8636336d8 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -284,7 +284,7 @@ public: #if wxUSE_DRAG_AND_DROP virtual bool EnableDragSource( const wxDataFormat &format ) wxOVERRIDE; - virtual bool EnableDropTarget( const wxDataFormat &format ) wxOVERRIDE; + virtual bool DoEnableDropTarget(const wxDataFormatArray& formats) wxOVERRIDE; #endif // wxUSE_DRAG_AND_DROP virtual wxBorder GetDefaultBorder() const wxOVERRIDE; diff --git a/include/wx/gtk/dataview.h b/include/wx/gtk/dataview.h index b5933cd33a..718ae843c4 100644 --- a/include/wx/gtk/dataview.h +++ b/include/wx/gtk/dataview.h @@ -166,7 +166,7 @@ public: virtual bool IsExpanded( const wxDataViewItem & item ) const wxOVERRIDE; virtual bool EnableDragSource( const wxDataFormat &format ) wxOVERRIDE; - virtual bool EnableDropTarget( const wxDataFormat &format ) wxOVERRIDE; + virtual bool DoEnableDropTarget( const wxDataFormatArray& formats ) wxOVERRIDE; virtual wxDataViewColumn *GetCurrentColumn() const wxOVERRIDE; diff --git a/include/wx/osx/cocoa/dataview.h b/include/wx/osx/cocoa/dataview.h index 90be1a8ae0..7d63ed0208 100644 --- a/include/wx/osx/cocoa/dataview.h +++ b/include/wx/osx/cocoa/dataview.h @@ -541,10 +541,6 @@ public: virtual void StartEditor( const wxDataViewItem & item, unsigned int column ) wxOVERRIDE; - // drag & drop helper methods - wxDataFormat GetDnDDataFormat(wxDataObjectComposite* dataObjects); - wxDataObjectComposite* GetDnDDataObjects(NSData* dataObject) const; - // Cocoa-specific helpers id GetItemAtRow(int row) const; diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index 48d4675acb..d35a452254 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -480,7 +480,8 @@ public: // this enum declares which methods should not be overridden in the native view classes enum wxOSXSkipOverrides { wxOSXSKIP_NONE = 0x0, - wxOSXSKIP_DRAW = 0x1 + wxOSXSKIP_DRAW = 0x1, + wxOSXSKIP_DND = 0x2 }; void WXDLLIMPEXP_CORE wxOSXCocoaClassAddWXMethods(Class c, wxOSXSkipOverrides skipFlags = wxOSXSKIP_NONE); diff --git a/include/wx/osx/dataview.h b/include/wx/osx/dataview.h index 457eddbebd..6a3e2197ec 100644 --- a/include/wx/osx/dataview.h +++ b/include/wx/osx/dataview.h @@ -208,6 +208,10 @@ public: virtual void EditItem(const wxDataViewItem& item, const wxDataViewColumn *column) wxOVERRIDE; +#if wxUSE_DRAG_AND_DROP + virtual bool DoEnableDropTarget( const wxDataFormatArray& formats ) wxOVERRIDE; +#endif // wxUSE_DRAG_AND_DROP + // returns the n-th pointer to a column; // this method is different from GetColumn(unsigned int pos) because here 'n' is not a position in the control but the n-th // position in the internal list/array of column pointers diff --git a/include/wx/qt/dataview.h b/include/wx/qt/dataview.h index 778bda4d67..a8b51ab7d2 100644 --- a/include/wx/qt/dataview.h +++ b/include/wx/qt/dataview.h @@ -119,7 +119,7 @@ public: virtual bool IsExpanded( const wxDataViewItem & item ) const; virtual bool EnableDragSource( const wxDataFormat &format ); - virtual bool EnableDropTarget( const wxDataFormat &format ); + virtual bool DoEnableDropTarget( const wxDataFormatArray& formats ) wxOVERRIDE; static wxVisualAttributes GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL); diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h index c1c4327c20..de76145267 100644 --- a/interface/wx/dataview.h +++ b/interface/wx/dataview.h @@ -1390,9 +1390,23 @@ public: virtual bool EnableDragSource( const wxDataFormat &format ); /** - Enable drop operations using the given @a format. + Enable drop operations for each @a format from passed array. + Currently this is fully implemented in the generic and native macOS versions. + On GTK the only first element of array will be used. + + @note Passing empty array disables drop operations at all. + + @since 3.1.5 */ - virtual bool EnableDropTarget( const wxDataFormat &format ); + bool EnableDropTarget(const wxDataFormatArray& formats); + + /** + Enable drop operations using the given @a format. + Under the hood just calls overloaded EnableDropTarget() with an array holds single passed format. + + @note Since 3.1.5 wxDF_INVALID can be passed to disable drop operations at all. + */ + bool EnableDropTarget( const wxDataFormat &format ); /** Call this to ensure that the given item is visible. diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 6eb1cb388b..b679cf91c0 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -1430,21 +1430,20 @@ void MyFrame::OnDrop( wxDataViewEvent &event ) return; } - wxTextDataObject obj; - obj.SetData( wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer() ); + const wxTextDataObject* const obj = static_cast(event.GetDataObject()); if ( item.IsOk() ) { if (m_music_model->IsContainer(item)) { wxLogMessage("Text '%s' dropped in container '%s' (proposed index = %i)", - obj.GetText(), m_music_model->GetTitle(item), event.GetProposedDropIndex()); + obj->GetText(), m_music_model->GetTitle(item), event.GetProposedDropIndex()); } else - wxLogMessage("Text '%s' dropped on item '%s'", obj.GetText(), m_music_model->GetTitle(item)); + wxLogMessage("Text '%s' dropped on item '%s'", obj->GetText(), m_music_model->GetTitle(item)); } else - wxLogMessage("Text '%s' dropped on background (proposed index = %i)", obj.GetText(), event.GetProposedDropIndex()); + wxLogMessage("Text '%s' dropped on background (proposed index = %i)", obj->GetText(), event.GetProposedDropIndex()); } #endif // wxUSE_DRAG_AND_DROP diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index cd070d2870..1eaa975bc6 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -1688,6 +1688,64 @@ void wxDataViewCtrlBase::StartEditor(const wxDataViewItem& item, unsigned int co EditItem(item, GetColumn(column)); } +#if wxUSE_DRAG_AND_DROP + +wxDataObject* wxDataViewCtrlBase::CreateDataObject(const wxDataFormatArray& formats) +{ + if (formats.GetCount() == 0) + { + return NULL; + } + + wxDataObjectComposite *dataObject(new wxDataObjectComposite); + for (size_t i = 0; i < formats.GetCount(); ++i) + { + switch (formats.Item(i).GetType()) + { + case wxDF_TEXT: + case wxDF_OEMTEXT: + case wxDF_UNICODETEXT: + dataObject->Add(new wxTextDataObject); + break; + + case wxDF_BITMAP: + dataObject->Add(new wxBitmapDataObject); + break; + + case wxDF_FILENAME: + dataObject->Add(new wxFileDataObject); + break; + + case wxDF_HTML: + dataObject->Add(new wxHTMLDataObject); + break; + + case wxDF_METAFILE: + case wxDF_SYLK: + case wxDF_DIF: + case wxDF_TIFF: + case wxDF_DIB: + case wxDF_PALETTE: + case wxDF_PENDATA: + case wxDF_RIFF: + case wxDF_WAVE: + case wxDF_ENHMETAFILE: + case wxDF_LOCALE: + case wxDF_PRIVATE: + dataObject->Add(new wxCustomDataObject(formats.Item(i))); + break; + + case wxDF_INVALID: + case wxDF_MAX: + break; + } + } + + return dataObject; +} + +#endif // wxUSE_DRAG_AND_DROP + // --------------------------------------------------------- // wxDataViewEvent // --------------------------------------------------------- diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 2712368c6f..2568a72fba 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -922,7 +922,6 @@ public: }; bool EnableDragSource( const wxDataFormat &format ); - bool EnableDropTarget( const wxDataFormat &format ); void RefreshDropHint(); void RemoveDropHint(); @@ -1032,8 +1031,6 @@ private: bool m_dragEnabled; wxDataFormat m_dragFormat; - bool m_dropEnabled; - wxDataFormat m_dropFormat; DropItemInfo m_dropItemInfo; #endif // wxUSE_DRAG_AND_DROP @@ -2076,7 +2073,6 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i m_dragStart = wxPoint(0,0); m_dragEnabled = false; - m_dropEnabled = false; m_dropItemInfo = DropItemInfo(); #endif // wxUSE_DRAG_AND_DROP @@ -2132,17 +2128,6 @@ bool wxDataViewMainWindow::EnableDragSource( const wxDataFormat &format ) return true; } -bool wxDataViewMainWindow::EnableDropTarget( const wxDataFormat &format ) -{ - m_dropFormat = format; - m_dropEnabled = format != wxDF_INVALID; - - if (m_dropEnabled) - SetDropTarget( new wxDataViewDropTarget( new wxCustomDataObject( format ), this ) ); - - return true; -} - void wxDataViewMainWindow::RefreshDropHint() { const unsigned row = m_dropItemInfo.m_row; @@ -2389,18 +2374,18 @@ bool wxDataViewMainWindow::OnDrop( wxDataFormat format, wxCoord x, wxCoord y ) return true; } -wxDragResult wxDataViewMainWindow::OnData( wxDataFormat format, wxCoord x, wxCoord y, - wxDragResult def ) +wxDragResult wxDataViewMainWindow::OnData(wxDataFormat format, wxCoord x, wxCoord y, + wxDragResult def) { DropItemInfo dropItemInfo = GetDropItemInfo(x, y); - wxCustomDataObject *obj = (wxCustomDataObject *) GetDropTarget()->GetDataObject(); + wxDataObjectComposite *obj = static_cast(GetDropTarget()->GetDataObject()); wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_DROP, m_owner, dropItemInfo.m_item); event.SetProposedDropIndex(dropItemInfo.m_proposedDropIndex); event.SetDataFormat( format ); - event.SetDataSize( obj->GetSize() ); - event.SetDataBuffer( obj->GetData() ); + event.SetDataSize(obj->GetDataSize(format)); + event.SetDataObject(obj->GetObject(format)); event.SetDropEffect( def ); if ( !m_owner->HandleWindowEvent( event ) || !event.IsAllowed() ) return wxDragNone; @@ -5816,9 +5801,17 @@ bool wxDataViewCtrl::EnableDragSource( const wxDataFormat &format ) return m_clientArea->EnableDragSource( format ); } -bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat &format ) +bool wxDataViewCtrl::DoEnableDropTarget( const wxDataFormatArray &formats ) { - return m_clientArea->EnableDropTarget( format ); + wxDataViewDropTarget* dt = NULL; + if (wxDataObject* dataObject = CreateDataObject(formats)) + { + dt = new wxDataViewDropTarget(dataObject, m_clientArea); + } + + m_clientArea->SetDropTarget(dt); + + return true; } #endif // wxUSE_DRAG_AND_DROP diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 7d8140d153..48b871272d 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -211,7 +211,7 @@ public: // dnd iface bool EnableDragSource( const wxDataFormat &format ); - bool EnableDropTarget( const wxDataFormat &format ); + bool EnableDropTarget( const wxDataFormatArray &formats ); gboolean row_draggable( GtkTreeDragSource *drag_source, GtkTreePath *path ); gboolean drag_data_delete( GtkTreeDragSource *drag_source, GtkTreePath* path ); @@ -3794,9 +3794,16 @@ bool wxDataViewCtrlInternal::EnableDragSource( const wxDataFormat &format ) return true; } -bool wxDataViewCtrlInternal::EnableDropTarget( const wxDataFormat &format ) +bool wxDataViewCtrlInternal::EnableDropTarget( const wxDataFormatArray& formats ) { - wxGtkString atom_str( gdk_atom_name( format ) ); + if (formats.GetCount() == 0) + { + gtk_tree_view_unset_rows_drag_dest(GTK_TREE_VIEW(m_owner->GtkGetTreeView())); + + return true; + } + + wxGtkString atom_str( gdk_atom_name( formats.Item(0) ) ); m_dropTargetTargetEntryTarget = wxCharBuffer( atom_str ); m_dropTargetTargetEntry.target = m_dropTargetTargetEntryTarget.data(); @@ -4922,10 +4929,10 @@ bool wxDataViewCtrl::EnableDragSource( const wxDataFormat &format ) return m_internal->EnableDragSource( format ); } -bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat &format ) +bool wxDataViewCtrl::DoEnableDropTarget( const wxDataFormatArray& formats ) { wxCHECK_MSG( m_internal, false, "model must be associated before calling EnableDragTarget" ); - return m_internal->EnableDropTarget( format ); + return m_internal->EnableDropTarget( formats ); } bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col ) diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 06bbddf9cc..09e1286e25 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -26,6 +26,7 @@ #include "wx/osx/private.h" #include "wx/osx/private/available.h" +#include "wx/osx/private/datatransfer.h" #include "wx/osx/cocoa/dataview.h" #include "wx/renderer.h" #include "wx/stopwatch.h" @@ -708,71 +709,77 @@ outlineView:(NSOutlineView*)outlineView return [self setupAndCallDataViewEvents:wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE dropInfo:info item:item proposedChildIndex:index]; } --(NSDragOperation) callDataViewEvents:(wxEventType)eventType dataObjects:(wxDataObjectComposite*)dataObjects item:(id)item - proposedChildIndex:(NSInteger)index +-(NSDragOperation) setupAndCallDataViewEvents:(wxEventType)eventType dropInfo:(id)info item:(id)item + proposedChildIndex:(NSInteger)index { - NSDragOperation dragOperation = NSDragOperationNone; wxDataViewCtrl* const dvc(implementation->GetDataViewCtrl()); + + wxDropTarget* dt = dvc->GetDropTarget(); + if (!dt) + return NSDragOperationNone; + + NSPasteboard* pasteboard([info draggingPasteboard]); + wxOSXPasteboard wxPastboard(pasteboard); + dt->SetCurrentDragSource(&wxPastboard); + + wxDataFormat format = dt->GetMatchingPair(); + if (format == wxDF_INVALID) + return NSDragOperationNone; + + // Create event wxDataViewEvent event(eventType, dvc, wxDataViewItemFromItem(item)); - if (dataObjects && (dataObjects->GetFormatCount() > 0)) + + // Retrieve data info if user released mouse buttton (drop occured) + if (eventType == wxEVT_DATAVIEW_ITEM_DROP) { - // copy data into data object: - event.SetDataObject(dataObjects); - event.SetDataFormat(implementation->GetDnDDataFormat(dataObjects)); - event.SetProposedDropIndex(index); - if (index == -1) - { - event.SetDropEffect(wxDragCopy); - } - else - { - //if index is not -1, we're going to set the default - //for the drop effect to None to be compatible with - //the other wxPlatforms that don't support it. In the - //user code for for the event, they can set this to - //copy/move or similar to support it. - event.SetDropEffect(wxDragNone); - } - wxDataFormatId formatId = event.GetDataFormat().GetType(); - wxMemoryBuffer buffer; + if (!dt->GetData()) + return NSDragOperationNone; - // copy data into buffer: - if ( formatId != wxDF_INVALID) - { - size_t size = dataObjects->GetDataSize(formatId); + wxDataObjectComposite *obj = static_cast(dt->GetDataObject()); + event.SetDataSize(obj->GetDataSize(format)); + event.SetDataObject(obj->GetObject(format)); + } - event.SetDataSize(size); - dataObjects->GetDataHere(formatId,buffer.GetWriteBuf(size)); - buffer.UngetWriteBuf(size); - event.SetDataBuffer(buffer.GetData()); - } + // Setup other event properties + event.SetProposedDropIndex(index); + event.SetDataFormat(format); + if (index == -1) + { + event.SetDropEffect(wxDragCopy); + } + else + { + //if index is not -1, we're going to set the default + //for the drop effect to None to be compatible with + //the other wxPlatforms that don't support it. In the + //user code for for the event, they can set this to + //copy/move or similar to support it. + event.SetDropEffect(wxDragNone); + } - // finally, send event: - if (dvc->HandleWindowEvent(event) && event.IsAllowed()) + NSDragOperation dragOperation = NSDragOperationNone; + + // finally, send event: + if (dvc->HandleWindowEvent(event) && event.IsAllowed()) + { + switch (event.GetDropEffect()) { - switch (event.GetDropEffect()) - { - case wxDragCopy: - dragOperation = NSDragOperationCopy; - break; - case wxDragMove: - dragOperation = NSDragOperationMove; - break; - case wxDragLink: - dragOperation = NSDragOperationLink; - break; - case wxDragNone: - case wxDragCancel: - case wxDragError: - dragOperation = NSDragOperationNone; - break; - default: - dragOperation = NSDragOperationEvery; - } - } - else - { - dragOperation = NSDragOperationNone; + case wxDragCopy: + dragOperation = NSDragOperationCopy; + break; + case wxDragMove: + dragOperation = NSDragOperationMove; + break; + case wxDragLink: + dragOperation = NSDragOperationLink; + break; + case wxDragNone: + case wxDragCancel: + case wxDragError: + dragOperation = NSDragOperationNone; + break; + default: + dragOperation = NSDragOperationEvery; } } else @@ -783,201 +790,40 @@ outlineView:(NSOutlineView*)outlineView return dragOperation; } --(NSDragOperation) setupAndCallDataViewEvents:(wxEventType)eventType dropInfo:(id)info item:(id)item - proposedChildIndex:(NSInteger)index -{ - NSArray* supportedTypes( - [NSArray arrayWithObjects:DataViewPboardType,NSStringPboardType,nil] - ); - - NSPasteboard* pasteboard([info draggingPasteboard]); - - NSString* bestType([pasteboard availableTypeFromArray:supportedTypes]); - - if ( bestType == nil ) - return NSDragOperationNone; - - NSDragOperation dragOperation = NSDragOperationNone; - wxDataViewCtrl* const dvc(implementation->GetDataViewCtrl()); - - wxCHECK_MSG(dvc, false, "Pointer to data view control not set correctly."); - wxCHECK_MSG(dvc->GetModel(), false, "Pointer to model not set correctly."); - - // wxDataViewEvent event(eventType, dvc, wxDataViewItemFromItem(item)); - if ([bestType compare:DataViewPboardType] == NSOrderedSame) - { - NSArray* dataArray((NSArray*)[pasteboard propertyListForType:DataViewPboardType]); - NSUInteger indexDraggedItem, noOfDraggedItems([dataArray count]); - - indexDraggedItem = 0; - while (indexDraggedItem < noOfDraggedItems) - { - wxDataObjectComposite* dataObjects(implementation->GetDnDDataObjects((NSData*)[dataArray objectAtIndex:indexDraggedItem])); - - dragOperation = [self callDataViewEvents:eventType dataObjects:dataObjects item:item proposedChildIndex:index]; - - if ( dragOperation != NSDragOperationNone ) - ++indexDraggedItem; - else - indexDraggedItem = noOfDraggedItems; - - // clean-up: - delete dataObjects; - } - } - else - { - // needed to convert internally used UTF-16 representation to a UTF-8 - // representation - CFDataRef osxData; - wxDataObjectComposite* dataObjects (new wxDataObjectComposite()); - wxTextDataObject* textDataObject(new wxTextDataObject()); - - osxData = ::CFStringCreateExternalRepresentation(kCFAllocatorDefault,(CFStringRef)[pasteboard stringForType:NSStringPboardType], -#if defined(wxNEEDS_UTF16_FOR_TEXT_DATAOBJ) - kCFStringEncodingUTF16, -#else - kCFStringEncodingUTF8, -#endif - 32); - if (textDataObject->SetData(::CFDataGetLength(osxData),::CFDataGetBytePtr(osxData))) - dataObjects->Add(textDataObject); - else - delete textDataObject; - // send event if data could be copied: - - dragOperation = [self callDataViewEvents:eventType dataObjects:dataObjects item:item proposedChildIndex:index]; - - // clean up: - ::CFRelease(osxData); - delete dataObjects; - } - - return dragOperation; -} - -(BOOL) outlineView:(NSOutlineView*)outlineView writeItems:(NSArray*)writeItems toPasteboard:(NSPasteboard*)pasteboard { wxUnusedVar(outlineView); - // the pasteboard will be filled up with an array containing the data as - // returned by the events (including the data type) and a concatenation of - // text (string) data; the text data will only be put onto the pasteboard - // if for all items a string representation exists wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl(); - wxDataViewItemArray dataViewItems; - - wxCHECK_MSG(dvc, false,"Pointer to data view control not set correctly."); wxCHECK_MSG(dvc->GetModel(),false,"Pointer to model not set correctly."); + BOOL result = NO; if ([writeItems count] > 0) { - bool dataStringAvailable(true); // a flag indicating if for all items a data string is available - NSMutableArray* dataArray = [NSMutableArray arrayWithCapacity:[writeItems count]]; // data of all items - wxString dataString; // contains the string data of all items + // Send a begin drag event for the first selected item and send wxEVT_DATAVIEW_ITEM_BEGIN_DRAG. + // If there are several items selected, user can process each in event handler and + // fill up the corresponding wxDataObject the way he wants. + const wxDataViewItem item = wxDataViewItemFromItem([writeItems objectAtIndex:0]); + wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, dvc, item); - // send a begin drag event for all selected items and proceed with - // dragging unless the event is vetoed: - for (size_t itemCounter=0; itemCounter<[writeItems count]; ++itemCounter) + // check if event has not been vetoed: + if (dvc->HandleWindowEvent(event) && event.IsAllowed() && event.GetDataObject()) { - bool itemStringAvailable(false); // a flag indicating if for the current item a string is available - wxDataObjectComposite* itemObject(new wxDataObjectComposite()); // data object for current item - wxString itemString; // contains the TAB concatenated data of an item + wxDataObject *dataObject = event.GetDataObject(); - const wxDataViewItem item = wxDataViewItemFromItem([writeItems objectAtIndex:itemCounter]); - wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, dvc, item); - itemString = ::ConcatenateDataViewItemValues(dvc, item); - itemObject->Add(new wxTextDataObject(itemString)); - event.SetDataObject(itemObject); - // check if event has not been vetoed: - if (dvc->HandleWindowEvent(event) && event.IsAllowed() && (event.GetDataObject()->GetFormatCount() > 0)) - { - size_t const noOfFormats = event.GetDataObject()->GetFormatCount(); - wxDataFormat* dataFormats(new wxDataFormat[noOfFormats]); + wxOSXPasteboard wxPastboard(pasteboard); - event.GetDataObject()->GetAllFormats(dataFormats,wxDataObject::Get); - for (size_t formatCounter=0; formatCounterGetDataSize(idDataFormat); - size_t const dataBufferSize = sizeof(wxDataFormatId)+dataSize; - // variable definitions (used in all case statements): - // give additional headroom for trailing NULL - wxMemoryBuffer dataBuffer(dataBufferSize+4); + wxPastboard.Clear(); + dataObject->WriteToSink(&wxPastboard); + wxPastboard.Flush(); - dataBuffer.AppendData(&idDataFormat,sizeof(wxDataFormatId)); - switch (idDataFormat) - { - case wxDF_TEXT: - // otherwise wxDF_UNICODETEXT already filled up - // the string; and the UNICODE representation has - // priority - if (!itemStringAvailable) - { - event.GetDataObject()->GetDataHere(wxDF_TEXT,dataBuffer.GetAppendBuf(dataSize)); - dataBuffer.UngetAppendBuf(dataSize); - [dataArray addObject:[NSData dataWithBytes:dataBuffer.GetData() length:dataBufferSize]]; - itemString = wxString(static_cast(dataBuffer.GetData())+sizeof(wxDataFormatId),wxConvLocal); - itemStringAvailable = true; - } - break; - case wxDF_UNICODETEXT: - { - event.GetDataObject()->GetDataHere(wxDF_UNICODETEXT,dataBuffer.GetAppendBuf(dataSize)); - dataBuffer.UngetAppendBuf(dataSize); - if (itemStringAvailable) // does an object already exist as an ASCII text (see wxDF_TEXT case statement)? - [dataArray replaceObjectAtIndex:itemCounter withObject:[NSData dataWithBytes:dataBuffer.GetData() length:dataBufferSize]]; - else - [dataArray addObject:[NSData dataWithBytes:dataBuffer.GetData() length:dataBufferSize]]; - itemString = wxString::FromUTF8(static_cast(dataBuffer.GetData())+sizeof(wxDataFormatId),dataSize); - itemStringAvailable = true; - } /* block */ - break; - default: - wxFAIL_MSG("Data object has invalid or unsupported data format"); - return NO; - } - } - delete[] dataFormats; - delete itemObject; - if (dataStringAvailable) - { - if (itemStringAvailable) - { - if (itemCounter > 0) - dataString << wxT('\n'); - dataString << itemString; - } - else - dataStringAvailable = false; - } - } - else - { - delete itemObject; - return NO; // dragging was vetoed or no data available - } + result = YES; } - if (dataStringAvailable) - { - wxCFStringRef osxString(dataString); - - [pasteboard declareTypes:[NSArray arrayWithObjects:DataViewPboardType,NSStringPboardType,nil] owner:nil]; - [pasteboard setPropertyList:dataArray forType:DataViewPboardType]; - [pasteboard setString:osxString.AsNSString() forType:NSStringPboardType]; - } - else - { - [pasteboard declareTypes:[NSArray arrayWithObject:DataViewPboardType] owner:nil]; - [pasteboard setPropertyList:dataArray forType:DataViewPboardType]; - } - return YES; } - else - return NO; // no items to drag (should never occur) + + return result; } // @@ -1639,7 +1485,7 @@ outlineView:(NSOutlineView*)outlineView if (!initialized) { initialized = YES; - wxOSXCocoaClassAddWXMethods( self ); + wxOSXCocoaClassAddWXMethods(self, wxOSXSKIP_DND); } } @@ -1654,8 +1500,6 @@ outlineView:(NSOutlineView*)outlineView currentlyEditedColumn = currentlyEditedRow = -1; - [self setAutoresizesOutlineColumn:NO]; - [self registerForDraggedTypes:[NSArray arrayWithObjects:DataViewPboardType,NSStringPboardType,nil]]; [self setDelegate:self]; [self setDoubleAction:@selector(actionDoubleClick:)]; [self setDraggingSourceOperationMask:NSDragOperationEvery forLocal:NO]; @@ -2501,9 +2345,20 @@ bool wxCocoaDataViewControl::Update(const wxDataViewColumn *columnPtr) return false; } -bool wxCocoaDataViewControl::Update(const wxDataViewItem& WXUNUSED(parent), const wxDataViewItem& item) +bool wxCocoaDataViewControl::Update(const wxDataViewItem& parent, const wxDataViewItem& item) { - [m_OutlineView reloadItem:[m_DataSource getDataViewItemFromBuffer:item]]; + if (GetSortingColumn()) + { + if (parent.IsOk()) + [m_OutlineView reloadItem:[m_DataSource getDataViewItemFromBuffer:parent] reloadChildren:YES]; + else + [m_OutlineView reloadData]; + } + else + { + [m_OutlineView reloadItem:[m_DataSource getDataViewItemFromBuffer:item]]; + } + return true; } @@ -2718,96 +2573,6 @@ void wxCocoaDataViewControl::OnSize() [m_OutlineView sizeLastColumnToFit]; } -// -// drag & drop helper methods -// -wxDataFormat wxCocoaDataViewControl::GetDnDDataFormat(wxDataObjectComposite* dataObjects) -{ - wxDataFormat resultFormat; - if ( !dataObjects ) - return resultFormat; - - bool compatible(true); - - size_t const noOfFormats = dataObjects->GetFormatCount(); - size_t indexFormat; - - wxDataFormat* formats; - - // get all formats and check afterwards if the formats are compatible; if - // they are compatible the preferred format is returned otherwise - // wxDF_INVALID is returned; - // currently compatible types (ordered by priority are): - // - wxDF_UNICODETEXT - wxDF_TEXT - formats = new wxDataFormat[noOfFormats]; - dataObjects->GetAllFormats(formats); - indexFormat = 0; - while ((indexFormat < noOfFormats) && compatible) - { - switch (resultFormat.GetType()) - { - case wxDF_INVALID: - resultFormat.SetType(formats[indexFormat].GetType()); // first format (should only be reached if indexFormat == 0) - break; - case wxDF_TEXT: - if (formats[indexFormat].GetType() == wxDF_UNICODETEXT) - resultFormat.SetType(wxDF_UNICODETEXT); - else // incompatible - { - resultFormat.SetType(wxDF_INVALID); - compatible = false; - } - break; - case wxDF_UNICODETEXT: - if (formats[indexFormat].GetType() != wxDF_TEXT) - { - resultFormat.SetType(wxDF_INVALID); - compatible = false; - } - break; - default: - resultFormat.SetType(wxDF_INVALID); // not (yet) supported format - compatible = false; - } - ++indexFormat; - } - - delete[] formats; - - return resultFormat; -} - -wxDataObjectComposite* wxCocoaDataViewControl::GetDnDDataObjects(NSData* dataObject) const -{ - wxDataFormatId dataFormatID; - - - [dataObject getBytes:&dataFormatID length:sizeof(wxDataFormatId)]; - switch (dataFormatID) - { - case wxDF_TEXT: - case wxDF_UNICODETEXT: - { - wxTextDataObject* textDataObject(new wxTextDataObject()); - - if (textDataObject->SetData(wxDataFormat(dataFormatID),[dataObject length]-sizeof(wxDataFormatId),static_cast([dataObject bytes])+sizeof(wxDataFormatId))) - { - wxDataObjectComposite* dataObjectComposite(new wxDataObjectComposite()); - - dataObjectComposite->Add(textDataObject); - return dataObjectComposite; - } - else - { - delete textDataObject; - return NULL; - } - } - default: - return NULL; - } -} - id wxCocoaDataViewControl::GetItemAtRow(int row) const { return [m_OutlineView itemAtRow:row]; diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 537d091595..82efa9ae54 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -2484,10 +2484,13 @@ void wxOSXCocoaClassAddWXMethods(Class c, wxOSXSkipOverrides skipFlags) wxOSX_CLASS_ADD_METHOD(c, @selector(controlDoubleAction:), (IMP) wxOSX_controlDoubleAction, "v@:@" ) #if wxUSE_DRAG_AND_DROP - wxOSX_CLASS_ADD_METHOD(c, @selector(draggingEntered:), (IMP) wxOSX_draggingEntered, "I@:@" ) - wxOSX_CLASS_ADD_METHOD(c, @selector(draggingUpdated:), (IMP) wxOSX_draggingUpdated, "I@:@" ) - wxOSX_CLASS_ADD_METHOD(c, @selector(draggingExited:), (IMP) wxOSX_draggingExited, "v@:@" ) - wxOSX_CLASS_ADD_METHOD(c, @selector(performDragOperation:), (IMP) wxOSX_performDragOperation, "c@:@" ) + if ( !(skipFlags & wxOSXSKIP_DND) ) + { + wxOSX_CLASS_ADD_METHOD(c, @selector(draggingEntered:), (IMP) wxOSX_draggingEntered, "I@:@" ) + wxOSX_CLASS_ADD_METHOD(c, @selector(draggingUpdated:), (IMP) wxOSX_draggingUpdated, "I@:@" ) + wxOSX_CLASS_ADD_METHOD(c, @selector(draggingExited:), (IMP) wxOSX_draggingExited, "v@:@" ) + wxOSX_CLASS_ADD_METHOD(c, @selector(performDragOperation:), (IMP) wxOSX_performDragOperation, "c@:@" ) + } #endif #if OBJC_API_VERSION < 2 diff --git a/src/osx/dataview_osx.cpp b/src/osx/dataview_osx.cpp index def9d099d4..8f885de027 100644 --- a/src/osx/dataview_osx.cpp +++ b/src/osx/dataview_osx.cpp @@ -687,6 +687,23 @@ void wxDataViewCtrl::EditItem(const wxDataViewItem& item, const wxDataViewColumn GetDataViewPeer()->StartEditor(item, GetColumnPosition(column)); } +#if wxUSE_DRAG_AND_DROP + +bool wxDataViewCtrl::DoEnableDropTarget(const wxDataFormatArray &formats) +{ + wxDropTarget* dt = NULL; + if (wxDataObject* dataObject = CreateDataObject(formats)) + { + dt = new wxDropTarget(dataObject); + } + + SetDropTarget(dt); + + return true; +} + +#endif // wxUSE_DRAG_AND_DROP + void wxDataViewCtrl::FinishCustomItemEditing() { if (GetCustomRendererItem().IsOk()) diff --git a/src/qt/dataview.cpp b/src/qt/dataview.cpp index 61cf681ca0..fd1b4b280e 100644 --- a/src/qt/dataview.cpp +++ b/src/qt/dataview.cpp @@ -285,7 +285,7 @@ bool wxDataViewCtrl::EnableDragSource( const wxDataFormat &format ) return false; } -bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat &format ) +bool wxDataViewCtrl::DoEnableDropTarget( const wxDataFormatArray &formats ) { return false; }