diff --git a/include/wx/dnd.h b/include/wx/dnd.h index 17ae097d0c..5ba516ade5 100644 --- a/include/wx/dnd.h +++ b/include/wx/dnd.h @@ -32,6 +32,11 @@ enum wxDragResult wxDragCancel // the operation was cancelled by user (not an error) }; +inline WXDLLEXPORT bool wxIsDragResultOk(wxDragResult res) +{ + return res == wxDragCopy || res == wxDragMove; +} + // ---------------------------------------------------------------------------- // wxDropSource is the object you need to create (and call DoDragDrop on it) // to initiate a drag-and-drop operation @@ -127,8 +132,10 @@ public: // called after OnDrop() returns TRUE: you will usually just call // GetData() from here and, probably, also refresh something to update the - // new data - virtual bool OnData(wxCoord x, wxCoord y) = 0; + // new data and, finally, return the code indicating how did the operation + // complete (returning default value in case of success and wxDragError on + // failure is usually ok) + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) = 0; // may be called *only* from inside OnData() and will fill m_dataObject // with the data from the drop source if it returns TRUE @@ -138,11 +145,6 @@ protected: wxDataObject *m_dataObject; }; -// ---------------------------------------------------------------------------- -// the platform-specific headers also define standard wxDropTarget -// implementations wxTextDropTarget and wxFileDropTarget -// ---------------------------------------------------------------------------- - // ---------------------------------------------------------------------------- // include platform dependent class declarations // ---------------------------------------------------------------------------- @@ -164,6 +166,35 @@ protected: #include "wx/stubs/dnd.h" #endif +// ---------------------------------------------------------------------------- +// standard wxDropTarget implementations (implemented in common/dobjcmn.cpp) +// ---------------------------------------------------------------------------- + +// A simple wxDropTarget derived class for text data: you only need to +// override OnDropText() to get something working +class WXDLLEXPORT wxTextDropTarget : public wxDropTarget +{ +public: + wxTextDropTarget(); + + virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text) = 0; + + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def); +}; + +// A drop target which accepts files (dragged from File Manager or Explorer) +class WXDLLEXPORT wxFileDropTarget : public wxDropTarget +{ +public: + wxFileDropTarget(); + + // parameters are the number of files and the array of file names + virtual bool OnDropFiles(wxCoord x, wxCoord y, + const wxArrayString& filenames) = 0; + + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def); +}; + #endif // wxUSE_DRAG_AND_DROP #endif // _WX_DND_H_BASE_ diff --git a/include/wx/generic/choicdgg.h b/include/wx/generic/choicdgg.h index 017ec2a43b..1d8381e090 100644 --- a/include/wx/generic/choicdgg.h +++ b/include/wx/generic/choicdgg.h @@ -16,9 +16,9 @@ #pragma interface "choicdgg.h" #endif -#include "wx/setup.h" #include "wx/dialog.h" -#include "wx/listbox.h" + +class WXDLLEXPORT wxListBox; #define wxCHOICE_HEIGHT 150 #define wxCHOICE_WIDTH 200 diff --git a/include/wx/gtk/dnd.h b/include/wx/gtk/dnd.h index c437f0b3b1..380d5c1d6a 100644 --- a/include/wx/gtk/dnd.h +++ b/include/wx/gtk/dnd.h @@ -44,10 +44,10 @@ class wxDropTarget: public wxDropTargetBase { public: wxDropTarget(wxDataObject *dataObject = (wxDataObject*) NULL ); - + virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def); virtual bool OnDrop(wxCoord x, wxCoord y); - virtual bool OnData(wxCoord x, wxCoord y); + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def); virtual bool GetData(); // implementation @@ -69,37 +69,6 @@ public: void SetDragTime( guint time ) { m_dragTime = time; } }; -// ---------------------------------------------------------------------------- -// A simple wxDropTarget derived class for text data: you only need to -// override OnDropText() to get something working -// ---------------------------------------------------------------------------- - -class wxTextDropTarget : public wxDropTarget -{ -public: - wxTextDropTarget(); - - virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text) = 0; - - virtual bool OnData(wxCoord x, wxCoord y); -}; - -// ---------------------------------------------------------------------------- -// A drop target which accepts files (dragged from File Manager or Explorer) -// ---------------------------------------------------------------------------- - -class wxFileDropTarget : public wxDropTarget -{ -public: - wxFileDropTarget(); - - // parameters are the number of files and the array of file names - virtual bool OnDropFiles(wxCoord x, wxCoord y, - const wxArrayString& filenames) = 0; - - virtual bool OnData(wxCoord x, wxCoord y); -}; - //------------------------------------------------------------------------- // wxDropSource //------------------------------------------------------------------------- @@ -126,15 +95,15 @@ public: void UnregisterWindow(); void PrepareIcon( int hot_x, int hot_y, GdkDragContext *context ); - + GtkWidget *m_widget; GtkWidget *m_iconWindow; GdkDragContext *m_dragContext; wxWindow *m_window; - + wxDragResult m_retValue; wxIcon m_icon; - + bool m_waiting; }; diff --git a/include/wx/gtk1/dnd.h b/include/wx/gtk1/dnd.h index c437f0b3b1..380d5c1d6a 100644 --- a/include/wx/gtk1/dnd.h +++ b/include/wx/gtk1/dnd.h @@ -44,10 +44,10 @@ class wxDropTarget: public wxDropTargetBase { public: wxDropTarget(wxDataObject *dataObject = (wxDataObject*) NULL ); - + virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def); virtual bool OnDrop(wxCoord x, wxCoord y); - virtual bool OnData(wxCoord x, wxCoord y); + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def); virtual bool GetData(); // implementation @@ -69,37 +69,6 @@ public: void SetDragTime( guint time ) { m_dragTime = time; } }; -// ---------------------------------------------------------------------------- -// A simple wxDropTarget derived class for text data: you only need to -// override OnDropText() to get something working -// ---------------------------------------------------------------------------- - -class wxTextDropTarget : public wxDropTarget -{ -public: - wxTextDropTarget(); - - virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text) = 0; - - virtual bool OnData(wxCoord x, wxCoord y); -}; - -// ---------------------------------------------------------------------------- -// A drop target which accepts files (dragged from File Manager or Explorer) -// ---------------------------------------------------------------------------- - -class wxFileDropTarget : public wxDropTarget -{ -public: - wxFileDropTarget(); - - // parameters are the number of files and the array of file names - virtual bool OnDropFiles(wxCoord x, wxCoord y, - const wxArrayString& filenames) = 0; - - virtual bool OnData(wxCoord x, wxCoord y); -}; - //------------------------------------------------------------------------- // wxDropSource //------------------------------------------------------------------------- @@ -126,15 +95,15 @@ public: void UnregisterWindow(); void PrepareIcon( int hot_x, int hot_y, GdkDragContext *context ); - + GtkWidget *m_widget; GtkWidget *m_iconWindow; GdkDragContext *m_dragContext; wxWindow *m_window; - + wxDragResult m_retValue; wxIcon m_icon; - + bool m_waiting; }; diff --git a/include/wx/msw/checklst.h b/include/wx/msw/checklst.h index 25041b8fa8..24003d4d43 100644 --- a/include/wx/msw/checklst.h +++ b/include/wx/msw/checklst.h @@ -16,17 +16,15 @@ #pragma interface "checklst.h" #endif -// No! -// typedef unsigned int size_t; -#include - #include "wx/setup.h" #if !wxUSE_OWNER_DRAWN #error "wxCheckListBox class requires owner-drawn functionality." #endif -class wxCheckListBoxItem; // fwd decl, define in checklst.cpp +#include "wx/listbox.h" + +class wxCheckListBoxItem; // fwd decl, defined in checklst.cpp class WXDLLEXPORT wxCheckListBox : public wxListBox { diff --git a/include/wx/msw/choice.h b/include/wx/msw/choice.h index c098da4a0b..654f1af915 100644 --- a/include/wx/msw/choice.h +++ b/include/wx/msw/choice.h @@ -27,6 +27,7 @@ class WXDLLEXPORT wxChoice : public wxChoiceBase public: // ctors wxChoice() { } + virtual ~wxChoice(); wxChoice(wxWindow *parent, wxWindowID id, @@ -77,6 +78,9 @@ protected: virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); + + // free all memory we have (used by Clear() and dtor) + void Free(); }; #endif // _WX_CHOICE_H_ diff --git a/include/wx/msw/listbox.h b/include/wx/msw/listbox.h index c702b8c1b7..edebfe9907 100644 --- a/include/wx/msw/listbox.h +++ b/include/wx/msw/listbox.h @@ -6,14 +6,14 @@ // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Julian Smart -// Licence: wxWindows licence +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_LISTBOX_H_ #define _WX_LISTBOX_H_ #ifdef __GNUG__ -#pragma interface "listbox.h" + #pragma interface "listbox.h" #endif // ---------------------------------------------------------------------------- @@ -120,6 +120,9 @@ protected: // do we have multiple selections? bool HasMultipleSelection() const; + // free memory (common part of Clear() and dtor) + void Free(); + int m_noItems; int m_selected; diff --git a/include/wx/msw/ole/droptgt.h b/include/wx/msw/ole/droptgt.h index 2e4a4f4f98..a4648b5edf 100644 --- a/include/wx/msw/ole/droptgt.h +++ b/include/wx/msw/ole/droptgt.h @@ -71,35 +71,4 @@ private: IDataObject *m_pIDataSource; // the pointer to the source data object }; -// ---------------------------------------------------------------------------- -// A simple wxDropTarget derived class for text data: you only need to -// override OnDropText() to get something working -// ---------------------------------------------------------------------------- - -class WXDLLEXPORT wxTextDropTarget : public wxDropTarget -{ -public: - wxTextDropTarget(); - - virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text) = 0; - - virtual bool OnData(wxCoord x, wxCoord y); -}; - -// ---------------------------------------------------------------------------- -// A drop target which accepts files (dragged from File Manager or Explorer) -// ---------------------------------------------------------------------------- - -class WXDLLEXPORT wxFileDropTarget : public wxDropTarget -{ -public: - wxFileDropTarget(); - - // parameters are the number of files and the array of file names - virtual bool OnDropFiles(wxCoord x, wxCoord y, - const wxArrayString& filenames) = 0; - - virtual bool OnData(wxCoord x, wxCoord y); -}; - #endif //_WX_OLEDROPTGT_H diff --git a/samples/dnd/dnd.cpp b/samples/dnd/dnd.cpp index 121a5e57be..aadb950d73 100644 --- a/samples/dnd/dnd.cpp +++ b/samples/dnd/dnd.cpp @@ -420,8 +420,6 @@ public: } else { - wxASSERT_MSG( format == wxDF_BITMAP, "unsupported format" ); - if ( !m_hasBitmap ) CreateBitmap(); @@ -544,19 +542,19 @@ public: { m_frame->SetStatusText("Mouse entered the frame"); } virtual void OnLeave() { m_frame->SetStatusText("Mouse left the frame"); } - virtual bool OnData(wxCoord x, wxCoord y) + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) { if ( !GetData() ) { wxLogError("Failed to get drag and drop data"); - return FALSE; + return wxDragNone; } m_frame->OnDrop(x, y, ((DnDShapeDataObject *)GetDataObject())->GetShape()); - return TRUE; + return def; } private: @@ -1299,9 +1297,6 @@ void DnDShapeFrame::OnDrop(wxCoord x, wxCoord y, DnDShape *shape) ms_lastDropTarget = this; wxPoint pt(x, y); -#ifdef __WXMSW__ //temporary hack (FIXME) - pt = ScreenToClient(pt); -#endif wxString s; s.Printf("Shape dropped at (%ld, %ld)", pt.x, pt.y); diff --git a/src/common/clipcmn.cpp b/src/common/clipcmn.cpp index 94f075fc98..85fbacce04 100644 --- a/src/common/clipcmn.cpp +++ b/src/common/clipcmn.cpp @@ -31,14 +31,6 @@ #include "wx/clipbrd.h" #include "wx/module.h" -//-------------------------------------------------------------------------- -// wxClipboardBase -//-------------------------------------------------------------------------- - -wxClipboardBase::wxClipboardBase() -{ -} - // ---------------------------------------------------------------------------- // wxClipboardModule: module responsible for initializing the global clipboard // object @@ -47,12 +39,8 @@ wxClipboardBase::wxClipboardBase() class wxClipboardModule : public wxModule { public: - wxClipboardModule() { } - - bool OnInit() - { wxTheClipboard = new wxClipboard; return TRUE; } - void OnExit() - { delete wxTheClipboard; wxTheClipboard = (wxClipboard *)NULL; } + bool OnInit(); + void OnExit(); private: DECLARE_DYNAMIC_CLASS(wxClipboardModule) @@ -63,3 +51,27 @@ private: // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule, wxModule) + +wxClipboard* wxTheClipboard = (wxClipboard *)NULL; + +// ---------------------------------------------------------------------------- +// implementation +// ---------------------------------------------------------------------------- + +wxClipboardBase::wxClipboardBase() +{ +} + +bool wxClipboardModule::OnInit() +{ + wxTheClipboard = new wxClipboard; + + return TRUE; +} + +void wxClipboardModule::OnExit() +{ + delete wxTheClipboard; + + wxTheClipboard = (wxClipboard *)NULL; +} diff --git a/src/common/dobjcmn.cpp b/src/common/dobjcmn.cpp index 95cfb73bce..50b6fe0718 100644 --- a/src/common/dobjcmn.cpp +++ b/src/common/dobjcmn.cpp @@ -289,3 +289,45 @@ bool wxCustomDataObject::SetData(size_t size, const void *buf) return TRUE; } +// ============================================================================ +// some common dnd related code +// ============================================================================ + +#include "wx/dnd.h" + +// ---------------------------------------------------------------------------- +// wxTextDropTarget +// ---------------------------------------------------------------------------- + +wxTextDropTarget::wxTextDropTarget() + : wxDropTarget(new wxTextDataObject) +{ +} + +wxDragResult wxTextDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult def) +{ + if ( !GetData() ) + return wxDragNone; + + wxTextDataObject *dobj = (wxTextDataObject *)m_dataObject; + return OnDropText(x, y, dobj->GetText()) ? def : wxDragNone; +} + +// ---------------------------------------------------------------------------- +// wxFileDropTarget +// ---------------------------------------------------------------------------- + +wxFileDropTarget::wxFileDropTarget() + : wxDropTarget(new wxFileDataObject) +{ +} + +wxDragResult wxFileDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult def) +{ + if ( !GetData() ) + return wxDragNone; + + wxFileDataObject *dobj = (wxFileDataObject *)m_dataObject; + return OnDropFiles(x, y, dobj->GetFilenames()) ? def : wxDragNone; +} + diff --git a/src/common/docview.cpp b/src/common/docview.cpp index 95b489ee7d..e21cda1fc9 100644 --- a/src/common/docview.cpp +++ b/src/common/docview.cpp @@ -706,7 +706,6 @@ wxDocManager::wxDocManager(long flags, bool initialize) m_currentView = (wxView *) NULL; m_maxDocsOpen = 10000; m_fileHistory = (wxFileHistory *) NULL; - m_lastDirectory = wxT("") ; if (initialize) Initialize(); } @@ -1910,11 +1909,8 @@ void wxFileHistory::RemoveFileFromHistory(int i) { wxMenu* menu = (wxMenu*) node->Data(); - // wxMenu::Delete() is missing from wxGTK, so this can't be done :-( -#if 0 // delete the menu items menu->Delete(wxID_FILE1 + i); -#endif // delete the element from the array (could use memmove() too...) delete [] m_fileHistory[i]; @@ -1933,11 +1929,6 @@ void wxFileHistory::RemoveFileFromHistory(int i) menu->SetLabel(wxID_FILE1 + j, buf); } - // to be removed as soon as wxMenu::Delete() is implemented -#if 1 - menu->SetLabel(wxID_FILE1 + m_fileHistoryN - 1, wxT("")); -#endif - node = node->Next(); } m_fileHistoryN--; @@ -1945,10 +1936,17 @@ void wxFileHistory::RemoveFileFromHistory(int i) wxString wxFileHistory::GetHistoryFile(int i) const { - if (i < m_fileHistoryN) - return wxString(m_fileHistory[i]); + wxString s; + if ( i < m_fileHistoryN ) + { + s = m_fileHistory[i]; + } else - return wxString(""); + { + wxFAIL_MSG( wxT("bad index in wxFileHistory::GetHistoryFile") ); + } + + return s; } void wxFileHistory::UseMenu(wxMenu *menu) diff --git a/src/common/lboxcmn.cpp b/src/common/lboxcmn.cpp index 78cf5a377b..642b324e9b 100644 --- a/src/common/lboxcmn.cpp +++ b/src/common/lboxcmn.cpp @@ -84,7 +84,7 @@ bool wxListBoxBase::SetStringSelection(const wxString& s, bool select) void wxListBoxBase::Command(wxCommandEvent& event) { - SetSelection(event.m_commandInt, event.m_extraLong); + SetSelection(event.m_commandInt, event.m_extraLong != 0); (void)ProcessEvent(event); } diff --git a/src/gtk/clipbrd.cpp b/src/gtk/clipbrd.cpp index 023cdad83c..186f15bcf4 100644 --- a/src/gtk/clipbrd.cpp +++ b/src/gtk/clipbrd.cpp @@ -36,8 +36,6 @@ extern void wxapp_uninstall_thread_wakeup(); // data //----------------------------------------------------------------------------- -wxClipboard *wxTheClipboard = (wxClipboard*) NULL; - GdkAtom g_clipboardAtom = 0; GdkAtom g_targetsAtom = 0; diff --git a/src/gtk/dnd.cpp b/src/gtk/dnd.cpp index cd2143caa4..6ab59511ca 100644 --- a/src/gtk/dnd.cpp +++ b/src/gtk/dnd.cpp @@ -147,8 +147,11 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), this is only valid for the duration of this call */ drop_target->SetDragContext( context ); - wxDragResult result = wxDragMove; - if (context->suggested_action == GDK_ACTION_COPY) result = wxDragCopy; + wxDragResult result; + if ( context->suggested_action == GDK_ACTION_COPY ) + result = wxDragCopy; + else + result = wxDragMove; if (drop_target->m_firstMotion) { @@ -161,11 +164,15 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), result = drop_target->OnDragOver( x, y, result ); } - bool ret = result != wxDragNone; + bool ret = wxIsDragResultOk( result ); if (ret) { - GdkDragAction action = GDK_ACTION_MOVE; - if (result == wxDragCopy) action = GDK_ACTION_COPY; + GdkDragAction action; + if (result == wxDragCopy) + action = GDK_ACTION_COPY; + else + action = GDK_ACTION_MOVE; + gdk_drag_status( context, action, time ); } @@ -224,7 +231,7 @@ static gboolean target_drag_drop( GtkWidget *widget, if (!ret) { wxLogDebug( wxT( "Drop target: OnDrop returned TRUE") ); - + /* cancel the whole thing */ gtk_drag_finish( context, FALSE, /* no success */ @@ -234,7 +241,7 @@ static gboolean target_drag_drop( GtkWidget *widget, else { wxLogDebug( wxT( "Drop target: OnDrop returned TRUE") ); - + #if wxUSE_THREADS /* disable GUI threads */ wxapp_uninstall_thread_wakeup(); @@ -242,11 +249,11 @@ static gboolean target_drag_drop( GtkWidget *widget, GdkAtom format = drop_target->GetMatchingPair(); wxASSERT( format ); - + /* GdkDragAction action = GDK_ACTION_MOVE; - if (result == wxDragCopy) action == GDK_ACTION_COPY; - context->action = action; + if (result == wxDragCopy) action == GDK_ACTION_COPY; + context->action = action; */ /* this should trigger an "drag_data_received" event */ gtk_drag_get_data( widget, @@ -290,7 +297,6 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), /* Owen Taylor: "call gtk_drag_finish() with success == TRUE" */ - if ((data->length <= 0) || (data->format != 8)) { /* negative data length and non 8-bit data format @@ -301,22 +307,28 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), } wxLogDebug( wxT( "Drop target: data received event") ); - + /* inform the wxDropTarget about the current GtkSelectionData. this is only valid for the duration of this call */ drop_target->SetDragData( data ); - if (drop_target->OnData( x, y )) + wxDragResult result; + if ( context->suggested_action == GDK_ACTION_COPY ) + result = wxDragCopy; + else + result = wxDragMove; + + if ( wxIsDragResultOk( drop_target->OnData( x, y, result ) ) ) { wxLogDebug( wxT( "Drop target: OnData returned TRUE") ); - + /* tell GTK that data transfer was successfull */ gtk_drag_finish( context, TRUE, FALSE, time ); } else { wxLogDebug( wxT( "Drop target: OnData returned FALSE") ); - + /* tell GTK that data transfer was not successfull */ gtk_drag_finish( context, FALSE, FALSE, time ); } @@ -329,8 +341,8 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), // wxDropTarget //---------------------------------------------------------------------------- -wxDropTarget::wxDropTarget( wxDataObject *data ) - : wxDropTargetBase( data ) +wxDropTarget::wxDropTarget( wxDataObject *data ) + : wxDropTargetBase( data ) { m_firstMotion = TRUE; m_dragContext = (GdkDragContext*) NULL; @@ -343,7 +355,7 @@ wxDragResult wxDropTarget::OnDragOver( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResult def ) { - // GetMatchingPair() checks for m_dataObject too, no need to do it here + // GetMatchingPair() checks for m_dataObject too, no need to do it here // disable the debug message from GetMatchingPair() - there are too many // of them otherwise @@ -358,27 +370,28 @@ bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) ) { if (!m_dataObject) return FALSE; - + return (GetMatchingPair() != (GdkAtom) 0); } -bool wxDropTarget::OnData( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) ) +wxDragResult wxDropTarget::OnData( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), + wxDragResult def ) { if (!m_dataObject) return FALSE; - + if (GetMatchingPair() == (GdkAtom) 0) return FALSE; - - return GetData(); + + return GetData() ? def : wxDragNone; } GdkAtom wxDropTarget::GetMatchingPair() { - if (!m_dataObject) + if (!m_dataObject) return (GdkAtom) 0; - if (!m_dragContext) + if (!m_dragContext) return (GdkAtom) 0; GList *child = m_dragContext->targets; @@ -403,14 +416,14 @@ GdkAtom wxDropTarget::GetMatchingPair() bool wxDropTarget::GetData() { - if (!m_dragData) + if (!m_dragData) return FALSE; - if (!m_dataObject) + if (!m_dataObject) return FALSE; wxDataFormat dragFormat( m_dragData->target ); - + if (!m_dataObject->IsSupportedFormat( dragFormat )) return FALSE; @@ -485,41 +498,6 @@ void wxDropTarget::RegisterWidget( GtkWidget *widget ) GTK_SIGNAL_FUNC(target_drag_data_received), (gpointer) this ); } -// ---------------------------------------------------------------------------- -// wxTextDropTarget -// ---------------------------------------------------------------------------- - -wxTextDropTarget::wxTextDropTarget() - : wxDropTarget(new wxTextDataObject) -{ -} - -bool wxTextDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText()); -} - -// ---------------------------------------------------------------------------- -// wxFileDropTarget -// ---------------------------------------------------------------------------- - -wxFileDropTarget::wxFileDropTarget() - : wxDropTarget(new wxFileDataObject) -{ -} - -bool wxFileDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropFiles(x, y, - ((wxFileDataObject *)m_dataObject)->GetFilenames()); -} - //---------------------------------------------------------------------------- // "drag_data_get" //---------------------------------------------------------------------------- @@ -535,13 +513,13 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), if (g_isIdle) wxapp_install_idle_handler(); wxDataFormat format( selection_data->target ); - + wxLogDebug( wxT("Drop source: format requested: %s"), format.GetId().c_str() ); drop_source->m_retValue = wxDragCancel; - + wxDataObject *data = drop_source->GetDataObject(); - + if (!data) { wxLogDebug( wxT("Drop source: no data object") ); @@ -559,13 +537,13 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), wxLogDebug( wxT("Drop source: empty data") ); return; } - + size_t size = data->GetDataSize(format); // printf( "data size: %d.\n", (int)data_size ); guchar *d = new guchar[size]; - + if (!data->GetDataHere( format, (void*)d )) { delete[] d; @@ -589,7 +567,7 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), #endif delete[] d; - + /* so far only copy, no moves. TODO. */ drop_source->m_retValue = wxDragCopy; } @@ -641,10 +619,10 @@ static void source_drag_end( GtkWidget *WXUNUSED(widget), // "configure_event" from m_iconWindow //----------------------------------------------------------------------------- -static gint +static gint gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxDropSource *source ) { - if (g_isIdle) + if (g_isIdle) wxapp_install_idle_handler(); wxDragResult action = wxDragNone; @@ -652,7 +630,7 @@ gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigur if (source->m_dragContext->action == GDK_ACTION_MOVE) action = wxDragMove; source->GiveFeedback( action, FALSE ); - + return 0; } @@ -666,7 +644,7 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &icon ) m_waiting = TRUE; m_iconWindow = (GtkWidget*) NULL; - + m_window = win; m_widget = win->m_widget; if (win->m_wxwindow) m_widget = win->m_wxwindow; @@ -680,15 +658,15 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &icon ) wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &icon ) { m_waiting = TRUE; - + SetData( data ); m_iconWindow = (GtkWidget*) NULL; - + m_window = win; m_widget = win->m_widget; if (win->m_wxwindow) m_widget = win->m_wxwindow; - + m_retValue = wxDragCancel; m_icon = icon; @@ -725,9 +703,9 @@ void wxDropSource::PrepareIcon( int hot_x, int hot_y, GdkDragContext *context ) gtk_signal_connect( GTK_OBJECT(m_iconWindow), "configure_event", GTK_SIGNAL_FUNC(gtk_dnd_window_configure_callback), (gpointer)this ); - + gdk_window_set_back_pixmap (m_iconWindow->window, pixmap, FALSE); - + if (mask) gtk_widget_shape_combine_mask (m_iconWindow, mask, 0, 0); @@ -738,12 +716,12 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) ) { wxASSERT_MSG( m_data, wxT("wxDragSource: no data") ); - if (!m_data) + if (!m_data) return (wxDragResult) wxDragNone; - if (m_data->GetFormatCount() == 0) + if (m_data->GetFormatCount() == 0) return (wxDragResult) wxDragNone; - + g_blockEventsOnDrag = TRUE; RegisterWindow(); @@ -751,7 +729,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) ) m_waiting = TRUE; GtkTargetList *target_list = gtk_target_list_new( (GtkTargetEntry*) NULL, 0 ); - + wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; m_data->GetAllFormats( array ); for (size_t i = 0; i < m_data->GetFormatCount(); i++) @@ -792,9 +770,9 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) ) (GdkDragAction)(GDK_ACTION_COPY|GDK_ACTION_MOVE), button_number, /* number of mouse button which started drag */ (GdkEvent*) &event ); - - m_dragContext = context; - + + m_dragContext = context; + PrepareIcon( 0, 0, context ); while (m_waiting) gtk_main_iteration();; diff --git a/src/gtk1/clipbrd.cpp b/src/gtk1/clipbrd.cpp index 023cdad83c..186f15bcf4 100644 --- a/src/gtk1/clipbrd.cpp +++ b/src/gtk1/clipbrd.cpp @@ -36,8 +36,6 @@ extern void wxapp_uninstall_thread_wakeup(); // data //----------------------------------------------------------------------------- -wxClipboard *wxTheClipboard = (wxClipboard*) NULL; - GdkAtom g_clipboardAtom = 0; GdkAtom g_targetsAtom = 0; diff --git a/src/gtk1/dnd.cpp b/src/gtk1/dnd.cpp index cd2143caa4..6ab59511ca 100644 --- a/src/gtk1/dnd.cpp +++ b/src/gtk1/dnd.cpp @@ -147,8 +147,11 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), this is only valid for the duration of this call */ drop_target->SetDragContext( context ); - wxDragResult result = wxDragMove; - if (context->suggested_action == GDK_ACTION_COPY) result = wxDragCopy; + wxDragResult result; + if ( context->suggested_action == GDK_ACTION_COPY ) + result = wxDragCopy; + else + result = wxDragMove; if (drop_target->m_firstMotion) { @@ -161,11 +164,15 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), result = drop_target->OnDragOver( x, y, result ); } - bool ret = result != wxDragNone; + bool ret = wxIsDragResultOk( result ); if (ret) { - GdkDragAction action = GDK_ACTION_MOVE; - if (result == wxDragCopy) action = GDK_ACTION_COPY; + GdkDragAction action; + if (result == wxDragCopy) + action = GDK_ACTION_COPY; + else + action = GDK_ACTION_MOVE; + gdk_drag_status( context, action, time ); } @@ -224,7 +231,7 @@ static gboolean target_drag_drop( GtkWidget *widget, if (!ret) { wxLogDebug( wxT( "Drop target: OnDrop returned TRUE") ); - + /* cancel the whole thing */ gtk_drag_finish( context, FALSE, /* no success */ @@ -234,7 +241,7 @@ static gboolean target_drag_drop( GtkWidget *widget, else { wxLogDebug( wxT( "Drop target: OnDrop returned TRUE") ); - + #if wxUSE_THREADS /* disable GUI threads */ wxapp_uninstall_thread_wakeup(); @@ -242,11 +249,11 @@ static gboolean target_drag_drop( GtkWidget *widget, GdkAtom format = drop_target->GetMatchingPair(); wxASSERT( format ); - + /* GdkDragAction action = GDK_ACTION_MOVE; - if (result == wxDragCopy) action == GDK_ACTION_COPY; - context->action = action; + if (result == wxDragCopy) action == GDK_ACTION_COPY; + context->action = action; */ /* this should trigger an "drag_data_received" event */ gtk_drag_get_data( widget, @@ -290,7 +297,6 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), /* Owen Taylor: "call gtk_drag_finish() with success == TRUE" */ - if ((data->length <= 0) || (data->format != 8)) { /* negative data length and non 8-bit data format @@ -301,22 +307,28 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), } wxLogDebug( wxT( "Drop target: data received event") ); - + /* inform the wxDropTarget about the current GtkSelectionData. this is only valid for the duration of this call */ drop_target->SetDragData( data ); - if (drop_target->OnData( x, y )) + wxDragResult result; + if ( context->suggested_action == GDK_ACTION_COPY ) + result = wxDragCopy; + else + result = wxDragMove; + + if ( wxIsDragResultOk( drop_target->OnData( x, y, result ) ) ) { wxLogDebug( wxT( "Drop target: OnData returned TRUE") ); - + /* tell GTK that data transfer was successfull */ gtk_drag_finish( context, TRUE, FALSE, time ); } else { wxLogDebug( wxT( "Drop target: OnData returned FALSE") ); - + /* tell GTK that data transfer was not successfull */ gtk_drag_finish( context, FALSE, FALSE, time ); } @@ -329,8 +341,8 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget), // wxDropTarget //---------------------------------------------------------------------------- -wxDropTarget::wxDropTarget( wxDataObject *data ) - : wxDropTargetBase( data ) +wxDropTarget::wxDropTarget( wxDataObject *data ) + : wxDropTargetBase( data ) { m_firstMotion = TRUE; m_dragContext = (GdkDragContext*) NULL; @@ -343,7 +355,7 @@ wxDragResult wxDropTarget::OnDragOver( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResult def ) { - // GetMatchingPair() checks for m_dataObject too, no need to do it here + // GetMatchingPair() checks for m_dataObject too, no need to do it here // disable the debug message from GetMatchingPair() - there are too many // of them otherwise @@ -358,27 +370,28 @@ bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) ) { if (!m_dataObject) return FALSE; - + return (GetMatchingPair() != (GdkAtom) 0); } -bool wxDropTarget::OnData( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) ) +wxDragResult wxDropTarget::OnData( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), + wxDragResult def ) { if (!m_dataObject) return FALSE; - + if (GetMatchingPair() == (GdkAtom) 0) return FALSE; - - return GetData(); + + return GetData() ? def : wxDragNone; } GdkAtom wxDropTarget::GetMatchingPair() { - if (!m_dataObject) + if (!m_dataObject) return (GdkAtom) 0; - if (!m_dragContext) + if (!m_dragContext) return (GdkAtom) 0; GList *child = m_dragContext->targets; @@ -403,14 +416,14 @@ GdkAtom wxDropTarget::GetMatchingPair() bool wxDropTarget::GetData() { - if (!m_dragData) + if (!m_dragData) return FALSE; - if (!m_dataObject) + if (!m_dataObject) return FALSE; wxDataFormat dragFormat( m_dragData->target ); - + if (!m_dataObject->IsSupportedFormat( dragFormat )) return FALSE; @@ -485,41 +498,6 @@ void wxDropTarget::RegisterWidget( GtkWidget *widget ) GTK_SIGNAL_FUNC(target_drag_data_received), (gpointer) this ); } -// ---------------------------------------------------------------------------- -// wxTextDropTarget -// ---------------------------------------------------------------------------- - -wxTextDropTarget::wxTextDropTarget() - : wxDropTarget(new wxTextDataObject) -{ -} - -bool wxTextDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText()); -} - -// ---------------------------------------------------------------------------- -// wxFileDropTarget -// ---------------------------------------------------------------------------- - -wxFileDropTarget::wxFileDropTarget() - : wxDropTarget(new wxFileDataObject) -{ -} - -bool wxFileDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropFiles(x, y, - ((wxFileDataObject *)m_dataObject)->GetFilenames()); -} - //---------------------------------------------------------------------------- // "drag_data_get" //---------------------------------------------------------------------------- @@ -535,13 +513,13 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), if (g_isIdle) wxapp_install_idle_handler(); wxDataFormat format( selection_data->target ); - + wxLogDebug( wxT("Drop source: format requested: %s"), format.GetId().c_str() ); drop_source->m_retValue = wxDragCancel; - + wxDataObject *data = drop_source->GetDataObject(); - + if (!data) { wxLogDebug( wxT("Drop source: no data object") ); @@ -559,13 +537,13 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), wxLogDebug( wxT("Drop source: empty data") ); return; } - + size_t size = data->GetDataSize(format); // printf( "data size: %d.\n", (int)data_size ); guchar *d = new guchar[size]; - + if (!data->GetDataHere( format, (void*)d )) { delete[] d; @@ -589,7 +567,7 @@ source_drag_data_get (GtkWidget *WXUNUSED(widget), #endif delete[] d; - + /* so far only copy, no moves. TODO. */ drop_source->m_retValue = wxDragCopy; } @@ -641,10 +619,10 @@ static void source_drag_end( GtkWidget *WXUNUSED(widget), // "configure_event" from m_iconWindow //----------------------------------------------------------------------------- -static gint +static gint gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxDropSource *source ) { - if (g_isIdle) + if (g_isIdle) wxapp_install_idle_handler(); wxDragResult action = wxDragNone; @@ -652,7 +630,7 @@ gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigur if (source->m_dragContext->action == GDK_ACTION_MOVE) action = wxDragMove; source->GiveFeedback( action, FALSE ); - + return 0; } @@ -666,7 +644,7 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &icon ) m_waiting = TRUE; m_iconWindow = (GtkWidget*) NULL; - + m_window = win; m_widget = win->m_widget; if (win->m_wxwindow) m_widget = win->m_wxwindow; @@ -680,15 +658,15 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &icon ) wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &icon ) { m_waiting = TRUE; - + SetData( data ); m_iconWindow = (GtkWidget*) NULL; - + m_window = win; m_widget = win->m_widget; if (win->m_wxwindow) m_widget = win->m_wxwindow; - + m_retValue = wxDragCancel; m_icon = icon; @@ -725,9 +703,9 @@ void wxDropSource::PrepareIcon( int hot_x, int hot_y, GdkDragContext *context ) gtk_signal_connect( GTK_OBJECT(m_iconWindow), "configure_event", GTK_SIGNAL_FUNC(gtk_dnd_window_configure_callback), (gpointer)this ); - + gdk_window_set_back_pixmap (m_iconWindow->window, pixmap, FALSE); - + if (mask) gtk_widget_shape_combine_mask (m_iconWindow, mask, 0, 0); @@ -738,12 +716,12 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) ) { wxASSERT_MSG( m_data, wxT("wxDragSource: no data") ); - if (!m_data) + if (!m_data) return (wxDragResult) wxDragNone; - if (m_data->GetFormatCount() == 0) + if (m_data->GetFormatCount() == 0) return (wxDragResult) wxDragNone; - + g_blockEventsOnDrag = TRUE; RegisterWindow(); @@ -751,7 +729,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) ) m_waiting = TRUE; GtkTargetList *target_list = gtk_target_list_new( (GtkTargetEntry*) NULL, 0 ); - + wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; m_data->GetAllFormats( array ); for (size_t i = 0; i < m_data->GetFormatCount(); i++) @@ -792,9 +770,9 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) ) (GdkDragAction)(GDK_ACTION_COPY|GDK_ACTION_MOVE), button_number, /* number of mouse button which started drag */ (GdkEvent*) &event ); - - m_dragContext = context; - + + m_dragContext = context; + PrepareIcon( 0, 0, context ); while (m_waiting) gtk_main_iteration();; diff --git a/src/msw/choice.cpp b/src/msw/choice.cpp index ee3e511515..9c7c335392 100644 --- a/src/msw/choice.cpp +++ b/src/msw/choice.cpp @@ -85,6 +85,11 @@ bool wxChoice::Create(wxWindow *parent, return TRUE; } +wxChoice::~wxChoice() +{ + Free(); +} + // ---------------------------------------------------------------------------- // adding/deleting items to/from the list // ---------------------------------------------------------------------------- @@ -113,6 +118,13 @@ void wxChoice::Delete(int n) } void wxChoice::Clear() +{ + Free(); + + SendMessage(GetHwnd(), CB_RESETCONTENT, 0, 0); +} + +void wxChoice::Free() { if ( HasClientObjectData() ) { @@ -122,8 +134,6 @@ void wxChoice::Clear() delete GetClientObject(n); } } - - SendMessage(GetHwnd(), CB_RESETCONTENT, 0, 0); } // ---------------------------------------------------------------------------- @@ -216,7 +226,7 @@ void* wxChoice::DoGetItemClientData( int n ) const wxLogLastError(wxT("CB_GETITEMDATA")); // unfortunately, there is no way to return an error code to the user - rc = (LPARAM) NULL; + rc = (LPARAM) NULL; } return (void *)rc; diff --git a/src/msw/clipbrd.cpp b/src/msw/clipbrd.cpp index ee67329e42..ba954e8263 100644 --- a/src/msw/clipbrd.cpp +++ b/src/msw/clipbrd.cpp @@ -419,8 +419,6 @@ bool wxGetClipboardFormatName(wxDataFormat dataFormat, IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject) -wxClipboard* wxTheClipboard = (wxClipboard *)NULL; - wxClipboard::wxClipboard() { m_clearOnExit = FALSE; diff --git a/src/msw/listbox.cpp b/src/msw/listbox.cpp index 4eb467f503..71d0b7c75e 100644 --- a/src/msw/listbox.cpp +++ b/src/msw/listbox.cpp @@ -230,12 +230,7 @@ bool wxListBox::Create(wxWindow *parent, wxListBox::~wxListBox() { -#if wxUSE_OWNER_DRAWN - size_t uiCount = m_aItems.Count(); - while ( uiCount-- != 0 ) { - delete m_aItems[uiCount]; - } -#endif // wxUSE_OWNER_DRAWN + Free(); } void wxListBox::SetupColours() @@ -353,6 +348,15 @@ int wxListBox::FindString(const wxString& s) const void wxListBox::Clear() { + Free(); + + ListBox_ResetContent(GetHwnd()); + + m_noItems = 0; + SetHorizontalExtent(); +} + +void wxListBox::Free() #if wxUSE_OWNER_DRAWN size_t uiCount = m_aItems.Count(); while ( uiCount-- != 0 ) { @@ -369,11 +373,6 @@ void wxListBox::Clear() } } #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN - - ListBox_ResetContent(GetHwnd()); - - m_noItems = 0; - SetHorizontalExtent(); } void wxListBox::SetSelection(int N, bool select) @@ -655,44 +654,39 @@ wxSize wxListBox::DoGetBestSize() bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) { - /* - if (param == LBN_SELCANCEL) - { - event.extraLong = FALSE; - } - */ - if (param == LBN_SELCHANGE) + if ( param == LBN_SELCHANGE ) { wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId); + event.SetEventObject( this ); + wxArrayInt aSelections; - int count = GetSelections(aSelections); + int n, count = GetSelections(aSelections); if ( count > 0 ) { - event.m_commandInt = aSelections[0]; - event.m_clientData = GetClientData(event.m_commandInt); - wxString str(GetString(event.m_commandInt)); - if (str != wxT("")) - { - event.m_commandString = str; - } + n = aSelections[0]; + if ( HasClientObjectData() ) + event.SetClientObject( GetClientObject(n) ); + else if ( HasClientUntypedData() ) + event.SetClientData( GetClientData(n) ); + event.SetString( GetString(n) ); } else { - event.m_commandInt = -1; - event.m_commandString.Empty(); + n = -1; } - event.SetEventObject( this ); - ProcessCommand(event); - return TRUE; + event.m_commandInt = n; + + return GetEventHandler()->ProcessEvent(event); } - else if (param == LBN_DBLCLK) + else if ( param == LBN_DBLCLK ) { wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId); event.SetEventObject( this ); - GetEventHandler()->ProcessEvent(event); - return TRUE; + + return GetEventHandler()->ProcessEvent(event); } + //else: return FALSE; } diff --git a/src/msw/ole/dataobj.cpp b/src/msw/ole/dataobj.cpp index d29dd539fb..ded97ac472 100644 --- a/src/msw/ole/dataobj.cpp +++ b/src/msw/ole/dataobj.cpp @@ -463,6 +463,12 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc, size = 0; break; + case CF_DIB: + // the handler will calculate size itself (it's too + // complicated to do it here) + size = 0; + break; + default: { // we suppose that the size precedes the data @@ -944,64 +950,122 @@ bool wxFileDataObject::SetData(size_t WXUNUSED(size), const void *pData) // private functions // ---------------------------------------------------------------------------- -// otherwise VC++ would give here: -// "local variable 'bi' may be used without having been initialized" -// even though in fact it may not -#ifdef __VISUALC__ - #pragma warning(disable:4701) -#endif // __VISUALC__ +static size_t wxGetNumOfBitmapColors(size_t bitsPerPixel) +{ + switch ( bitsPerPixel ) + { + case 1: + // monochrome bitmap, 2 entries + return 2; + + case 4: + return 16; + + case 8: + return 256; + + case 24: + // may be used with 24bit bitmaps, but we don't use it here - fall + // through + + case 16: + case 32: + // bmiColors not used at all with these bitmaps + return 0; + + default: + wxFAIL_MSG( wxT("unknown bitmap format") ); + return 0; + } +} size_t wxConvertBitmapToDIB(BITMAPINFO *pbi, const wxBitmap& bitmap) { + wxASSERT_MSG( bitmap.Ok(), wxT("invalid bmp can't be converted to DIB") ); + // shouldn't be selected into a DC or GetDIBits() would fail wxASSERT_MSG( !bitmap.GetSelectedInto(), wxT("can't copy bitmap selected into wxMemoryDC") ); + // prepare all the info we need + BITMAP bm; HBITMAP hbmp = (HBITMAP)bitmap.GetHBITMAP(); + if ( !GetObject(hbmp, sizeof(bm), &bm) ) + { + wxLogLastError("GetObject(bitmap)"); - BITMAPINFO bi; + return 0; + } - // first get the info + // calculate the number of bits per pixel and the number of items in + // bmiColors array (whose meaning depends on the bitmap format) + WORD biBits = bm.bmPlanes * bm.bmBitsPixel; + WORD biColors = wxGetNumOfBitmapColors(biBits); + + BITMAPINFO bi2; + + bool wantSizeOnly = pbi == NULL; + if ( wantSizeOnly ) + pbi = &bi2; + + // just for convenience + BITMAPINFOHEADER& bi = pbi->bmiHeader; + + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = bm.bmWidth; + bi.biHeight = bm.bmHeight; + bi.biPlanes = 1; + bi.biBitCount = biBits; + bi.biCompression = BI_RGB; + bi.biSizeImage = 0; + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; + bi.biClrImportant = 0; + + // memory we need for BITMAPINFO only + DWORD dwLen = bi.biSize + biColors * sizeof(RGBQUAD); + + // first get the image size ScreenHDC hdc; - if ( !GetDIBits(hdc, hbmp, 0, 0, NULL, pbi ? pbi : &bi, DIB_RGB_COLORS) ) + if ( !GetDIBits(hdc, hbmp, 0, bi.biHeight, NULL, pbi, DIB_RGB_COLORS) ) { wxLogLastError("GetDIBits(NULL)"); return 0; } - if ( !pbi ) + if ( wantSizeOnly ) { - // we were only asked for size needed for the buffer, not to actually - // copy the data - return sizeof(BITMAPINFO) + bi.bmiHeader.biSizeImage; + // size of the header + size of the image + return dwLen + bi.biSizeImage; } // and now copy the bits - if ( !GetDIBits(hdc, hbmp, 0, pbi->bmiHeader.biHeight, pbi + 1, - pbi, DIB_RGB_COLORS) ) + void *image = (char *)pbi + dwLen; + if ( !GetDIBits(hdc, hbmp, 0, bi.biHeight, image, pbi, DIB_RGB_COLORS) ) { wxLogLastError("GetDIBits"); return 0; } - return sizeof(BITMAPINFO) + pbi->bmiHeader.biSizeImage; + return dwLen + bi.biSizeImage; } -#ifdef __VISUALC__ - #pragma warning(default:4701) -#endif // __VISUALC__ - wxBitmap wxConvertDIBToBitmap(const BITMAPINFO *pbmi) { // here we get BITMAPINFO struct followed by the actual bitmap bits and // BITMAPINFO starts with BITMAPINFOHEADER followed by colour info const BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader; + // offset of image from the beginning of the header + DWORD ofs = wxGetNumOfBitmapColors(pbmih->biBitCount) * sizeof(RGBQUAD); + void *image = (char *)pbmih + sizeof(BITMAPINFOHEADER) + ofs; + ScreenHDC hdc; HBITMAP hbmp = CreateDIBitmap(hdc, pbmih, CBM_INIT, - pbmi + 1, pbmi, DIB_RGB_COLORS); + image, pbmi, DIB_RGB_COLORS); if ( !hbmp ) { wxLogLastError("CreateDIBitmap"); diff --git a/src/msw/ole/droptgt.cpp b/src/msw/ole/droptgt.cpp index 260ccecc8c..b6d353d98c 100644 --- a/src/msw/ole/droptgt.cpp +++ b/src/msw/ole/droptgt.cpp @@ -60,23 +60,28 @@ class wxIDropTarget : public IDropTarget { public: - wxIDropTarget(wxDropTarget *p); - ~wxIDropTarget(); + wxIDropTarget(wxDropTarget *p); + ~wxIDropTarget(); - // IDropTarget methods - STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD); - STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD); - STDMETHODIMP DragLeave(void); - STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD); + // accessors for wxDropTarget + void SetHwnd(HWND hwnd) { m_hwnd = hwnd; } - DECLARE_IUNKNOWN_METHODS; + // IDropTarget methods + STDMETHODIMP DragEnter(LPDATAOBJECT, DWORD, POINTL, LPDWORD); + STDMETHODIMP DragOver(DWORD, POINTL, LPDWORD); + STDMETHODIMP DragLeave(); + STDMETHODIMP Drop(LPDATAOBJECT, DWORD, POINTL, LPDWORD); + + DECLARE_IUNKNOWN_METHODS; protected: - IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop - wxDropTarget *m_pTarget; // the real target (we're just a proxy) + IDataObject *m_pIDataObject; // !NULL between DragEnter and DragLeave/Drop + wxDropTarget *m_pTarget; // the real target (we're just a proxy) -private: - static inline DWORD GetDropEffect(DWORD flags); + HWND m_hwnd; // window we're associated with + + // get default drop effect for given keyboard flags + static inline DWORD GetDropEffect(DWORD flags); }; // ---------------------------------------------------------------------------- @@ -90,7 +95,7 @@ static DWORD ConvertDragResultToEffect(wxDragResult result); // wxIDropTarget implementation // ============================================================================ -// Name : static wxDropTarget::GetDropEffect +// Name : static wxIDropTarget::GetDropEffect // Purpose : determine the drop operation from keyboard/mouse state. // Returns : DWORD combined from DROPEFFECT_xxx constants // Params : [in] DWORD flags kbd & mouse flags as passed to @@ -134,31 +139,35 @@ STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource, POINTL pt, DWORD *pdwEffect) { - wxLogDebug(wxT("IDropTarget::DragEnter")); + wxLogDebug(wxT("IDropTarget::DragEnter")); - wxASSERT( m_pIDataObject == NULL ); + wxASSERT( m_pIDataObject == NULL ); - if ( !m_pTarget->IsAcceptedData(pIDataSource) ) { - // we don't accept this kind of data - *pdwEffect = DROPEFFECT_NONE; + if ( !m_pTarget->IsAcceptedData(pIDataSource) ) { + // we don't accept this kind of data + *pdwEffect = DROPEFFECT_NONE; + + return S_OK; + } + + // get hold of the data object + m_pIDataObject = pIDataSource; + m_pIDataObject->AddRef(); + + // we need client coordinates to pass to wxWin functions + if ( !ScreenToClient(m_hwnd, (POINT *)&pt) ) + { + wxLogLastError("ScreenToClient"); + } + + // give some visual feedback + *pdwEffect = ConvertDragResultToEffect( + m_pTarget->OnEnter(pt.x, pt.y, + ConvertDragEffectToResult(GetDropEffect(grfKeyState)) + ) + ); return S_OK; - } - - // get hold of the data object - m_pIDataObject = pIDataSource; - m_pIDataObject->AddRef(); - - // give some visual feedback - *pdwEffect = ConvertDragResultToEffect( - m_pTarget->OnEnter(pt.x, pt.y, - ConvertDragEffectToResult( - GetDropEffect(grfKeyState) - ) - ) - ); - - return S_OK; } // Name : wxIDropTarget::DragOver @@ -174,22 +183,28 @@ STDMETHODIMP wxIDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { - // there are too many of them... wxLogDebug("IDropTarget::DragOver"); + // there are too many of them... wxLogDebug("IDropTarget::DragOver"); - wxDragResult result; - if ( m_pIDataObject ) { - result = ConvertDragEffectToResult(GetDropEffect(grfKeyState)); - } - else { - // can't accept data anyhow normally - result = wxDragNone; - } + wxDragResult result; + if ( m_pIDataObject ) { + result = ConvertDragEffectToResult(GetDropEffect(grfKeyState)); + } + else { + // can't accept data anyhow normally + result = wxDragNone; + } - *pdwEffect = ConvertDragResultToEffect( - m_pTarget->OnDragOver(pt.x, pt.y, result) - ); + // we need client coordinates to pass to wxWin functions + if ( !ScreenToClient(m_hwnd, (POINT *)&pt) ) + { + wxLogLastError("ScreenToClient"); + } - return S_OK; + *pdwEffect = ConvertDragResultToEffect( + m_pTarget->OnDragOver(pt.x, pt.y, result) + ); + + return S_OK; } // Name : wxIDropTarget::DragLeave @@ -232,15 +247,23 @@ STDMETHODIMP wxIDropTarget::Drop(IDataObject *pIDataSource, // by default, nothing happens *pdwEffect = DROPEFFECT_NONE; + // we need client coordinates to pass to wxWin functions + if ( !ScreenToClient(m_hwnd, (POINT *)&pt) ) + { + wxLogLastError("ScreenToClient"); + } + // first ask the drop target if it wants data if ( m_pTarget->OnDrop(pt.x, pt.y) ) { // it does, so give it the data source m_pTarget->SetDataSource(pIDataSource); // and now it has the data - if ( m_pTarget->OnData(pt.x, pt.y) ) { + wxDragResult rc = ConvertDragEffectToResult(GetDropEffect(grfKeyState)); + rc = m_pTarget->OnData(pt.x, pt.y, rc); + if ( wxIsDragResultOk(rc) ) { // operation succeeded - *pdwEffect = GetDropEffect(grfKeyState); + *pdwEffect = ConvertDragResultToEffect(rc); } //else: *pdwEffect is already DROPEFFECT_NONE } @@ -294,6 +317,9 @@ bool wxDropTarget::Register(WXHWND hwnd) return FALSE; } + // we will need the window handle for coords transformation later + m_pIDropTarget->SetHwnd((HWND)hwnd); + return TRUE; } @@ -306,6 +332,8 @@ void wxDropTarget::Revoke(WXHWND hwnd) } ::CoLockObjectExternal(m_pIDropTarget, FALSE, TRUE); + + m_pIDropTarget->SetHwnd(0); } // ---------------------------------------------------------------------------- @@ -420,41 +448,6 @@ wxDataFormat wxDropTarget::GetSupportedFormat(IDataObject *pIDataSource) const return n < nFormats ? format : wxFormatInvalid; } -// ---------------------------------------------------------------------------- -// wxTextDropTarget -// ---------------------------------------------------------------------------- - -wxTextDropTarget::wxTextDropTarget() - : wxDropTarget(new wxTextDataObject) -{ -} - -bool wxTextDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropText(x, y, ((wxTextDataObject *)m_dataObject)->GetText()); -} - -// ---------------------------------------------------------------------------- -// wxFileDropTarget -// ---------------------------------------------------------------------------- - -wxFileDropTarget::wxFileDropTarget() - : wxDropTarget(new wxFileDataObject) -{ -} - -bool wxFileDropTarget::OnData(wxCoord x, wxCoord y) -{ - if ( !GetData() ) - return FALSE; - - return OnDropFiles(x, y, - ((wxFileDataObject *)m_dataObject)->GetFilenames()); -} - // ---------------------------------------------------------------------------- // private functions // ----------------------------------------------------------------------------