New wxDataObject etc. Almost works.
[wxWidgets.git] / src / gtk1 / dataobj.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dataobj.cpp
3 // Purpose: wxDataObject class
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "dataobj.h"
12 #endif
13
14 #include "wx/dataobj.h"
15 #include "wx/app.h"
16 #include "wx/debug.h"
17 #include "wx/mstream.h"
18 #include "wx/image.h"
19
20 #include "gdk/gdk.h"
21
22
23 //-------------------------------------------------------------------------
24 // global data
25 //-------------------------------------------------------------------------
26
27 GdkAtom g_textAtom = 0;
28 GdkAtom g_pngAtom = 0;
29 GdkAtom g_fileAtom = 0;
30
31 //-------------------------------------------------------------------------
32 // wxDataFormat
33 //-------------------------------------------------------------------------
34
35 wxDataFormat::wxDataFormat()
36 {
37 PrepareFormats();
38 m_type = wxDF_INVALID;
39 m_format = (GdkAtom) 0;
40 }
41
42 wxDataFormat::wxDataFormat( wxDataFormatId type )
43 {
44 PrepareFormats();
45 SetType( type );
46 }
47
48 wxDataFormat::wxDataFormat( const wxChar *id )
49 {
50 PrepareFormats();
51 SetId( id );
52 }
53
54 wxDataFormat::wxDataFormat( const wxString &id )
55 {
56 PrepareFormats();
57 SetId( id );
58 }
59
60 wxDataFormat::wxDataFormat( NativeFormat format )
61 {
62 PrepareFormats();
63 SetId( format );
64 }
65
66 void wxDataFormat::SetType( wxDataFormatId type )
67 {
68 m_type = type;
69
70 if (m_type == wxDF_TEXT)
71 m_format = g_textAtom;
72 else
73 if (m_type == wxDF_BITMAP)
74 m_format = g_pngAtom;
75 else
76 if (m_type == wxDF_FILENAME)
77 m_format = g_fileAtom;
78 else
79 {
80 wxFAIL_MSG( wxT("invalid dataformat") );
81 }
82 }
83
84 wxDataFormatId wxDataFormat::GetType() const
85 {
86 return m_type;
87 }
88
89 wxString wxDataFormat::GetId() const
90 {
91 wxString ret( gdk_atom_name( m_format ) ); // this will convert from ascii to Unicode
92 return ret;
93 }
94
95 void wxDataFormat::SetId( NativeFormat format )
96 {
97 m_format = format;
98
99 if (m_format == g_textAtom)
100 m_type = wxDF_TEXT;
101 else
102 if (m_format == g_pngAtom)
103 m_type = wxDF_BITMAP;
104 else
105 if (m_format == g_fileAtom)
106 m_type = wxDF_FILENAME;
107 else
108 m_type = wxDF_PRIVATE;
109 }
110
111 void wxDataFormat::SetId( const wxChar *id )
112 {
113 m_type = wxDF_PRIVATE;
114 wxString tmp( id );
115 m_format = gdk_atom_intern( wxMBSTRINGCAST tmp.mbc_str(), FALSE ); // what is the string cast for?
116 }
117
118 void wxDataFormat::PrepareFormats()
119 {
120 if (!g_textAtom)
121 g_textAtom = gdk_atom_intern( "STRING", FALSE );
122 if (!g_pngAtom)
123 g_pngAtom = gdk_atom_intern( "image/png", FALSE );
124 if (!g_fileAtom)
125 g_fileAtom = gdk_atom_intern( "file:ALL", FALSE );
126 }
127
128 //-------------------------------------------------------------------------
129 // wxDataObject
130 //-------------------------------------------------------------------------
131
132 IMPLEMENT_ABSTRACT_CLASS( wxDataObject, wxObject )
133
134 wxDataObject::wxDataObject()
135 {
136 }
137
138 wxDataObject::~wxDataObject()
139 {
140 }
141
142 bool wxDataObject::IsSupportedFormat(const wxDataFormat& format) const
143 {
144 size_t nFormatCount = GetFormatCount();
145 if ( nFormatCount == 1 ) {
146 return format == GetPreferredFormat();
147 }
148 else {
149 wxDataFormat *formats = new wxDataFormat[nFormatCount];
150 GetAllFormats(formats);
151
152 size_t n;
153 for ( n = 0; n < nFormatCount; n++ ) {
154 if ( formats[n] == format )
155 break;
156 }
157
158 delete [] formats;
159
160 // found?
161 return n < nFormatCount;
162 }
163 }
164
165
166 // ----------------------------------------------------------------------------
167 // wxTextDataObject
168 // ----------------------------------------------------------------------------
169
170 IMPLEMENT_DYNAMIC_CLASS( wxTextDataObject, wxDataObject )
171
172 wxTextDataObject::wxTextDataObject()
173 {
174 }
175
176 wxTextDataObject::wxTextDataObject(const wxString& strText)
177 : m_strText(strText)
178 {
179 }
180
181 size_t wxTextDataObject::GetDataSize(const wxDataFormat& format) const
182 {
183 return m_strText.Len() + 1; // +1 for trailing '\0'of course
184 }
185
186 bool wxTextDataObject::GetDataHere(const wxDataFormat& format, void *buf) const
187 {
188 memcpy(buf, m_strText.c_str(), GetDataSize(format));
189 return TRUE;
190 }
191
192 bool wxTextDataObject::SetData(const wxDataFormat& format, const void *buf)
193 {
194 m_strText = (const wxChar *)buf;
195 return TRUE;
196 }
197
198 // ----------------------------------------------------------------------------
199 // wxFileDataObject
200 // ----------------------------------------------------------------------------
201
202 IMPLEMENT_DYNAMIC_CLASS( wxFileDataObject, wxDataObject )
203
204 wxFileDataObject::wxFileDataObject()
205 {
206 }
207
208 void wxFileDataObject::AddFile( const wxString &file )
209 {
210 m_files += file;
211 m_files += (wxChar)0;
212 }
213
214 wxString wxFileDataObject::GetFiles() const
215 {
216 return m_files;
217 }
218
219 bool wxFileDataObject::GetDataHere(const wxDataFormat& format, void *buf) const
220 {
221 if (format == wxDF_FILENAME)
222 {
223 memcpy( buf, m_files.mbc_str(), m_files.Len() + 1 );
224 return TRUE;
225 }
226
227 return FALSE;
228 }
229
230 size_t wxFileDataObject::GetDataSize(const wxDataFormat& format) const
231 {
232 if (format != wxDF_FILENAME) return 0;
233
234 return m_files.Len() + 1;
235 }
236
237 bool wxFileDataObject::SetData(const wxDataFormat& format, const void *buf)
238 {
239 if (format != wxDF_FILENAME)
240 return FALSE;
241
242 m_files = (char*)(buf); // this is so ugly, I cannot look at it
243
244 return TRUE;
245 }
246
247 // ----------------------------------------------------------------------------
248 // wxBitmapDataObject
249 // ----------------------------------------------------------------------------
250
251 IMPLEMENT_DYNAMIC_CLASS( wxBitmapDataObject, wxDataObject )
252
253 wxBitmapDataObject::wxBitmapDataObject()
254 {
255 m_pngData = (void*)NULL;
256 m_pngSize = 0;
257 }
258
259 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& bitmap )
260 {
261 m_pngData = (void*)NULL;
262 m_pngSize = 0;
263 m_bitmap = bitmap;
264 DoConvertToPng();
265 }
266
267 wxBitmapDataObject::~wxBitmapDataObject()
268 {
269 if (m_pngData)
270 delete[] m_pngData;
271 }
272
273 void wxBitmapDataObject::SetBitmap( const wxBitmap &bitmap )
274 {
275 if (m_pngData)
276 delete[] m_pngData;
277 m_pngData = (void*)NULL;
278 m_pngSize = 0;
279
280 m_bitmap = bitmap;
281 DoConvertToPng();
282 }
283
284 size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
285 {
286 if (format != wxDF_BITMAP) return 0;
287
288 return m_pngSize;
289 }
290
291 bool wxBitmapDataObject::GetDataHere(const wxDataFormat& format, void *buf) const
292 {
293 if (format != wxDF_BITMAP) return FALSE;
294
295 if (m_pngSize > 0)
296 {
297 memcpy(buf, m_pngData, m_pngSize);
298 return TRUE;
299 }
300
301 return FALSE;
302 }
303
304 bool wxBitmapDataObject::SetData(const wxDataFormat& format, const void *buf)
305 {
306 if (m_pngData) delete[] m_pngData;
307 m_pngData = (void*) NULL;
308 m_pngSize = 0;
309 m_bitmap = wxNullBitmap;
310
311 return FALSE;
312 }
313
314 void wxBitmapDataObject::SetPngData(const void *buf, size_t size)
315 {
316 if (m_pngData) delete[] m_pngData;
317 m_pngSize = size;
318 m_pngData = (void*) new char[m_pngSize];
319
320 memcpy( m_pngData, buf, m_pngSize );
321
322 wxMemoryInputStream mstream( (char*) m_pngData, m_pngSize );
323 wxImage image;
324 wxPNGHandler handler;
325 handler.LoadFile( &image, mstream );
326 m_bitmap = image.ConvertToBitmap();
327 }
328
329 void wxBitmapDataObject::DoConvertToPng()
330 {
331 if (!m_bitmap.Ok()) return;
332
333 wxImage image( m_bitmap );
334 wxPNGHandler handler;
335
336 wxCountingOutputStream count;
337 handler.SaveFile( &image, count );
338 m_pngSize = count.GetSize() + 100; // sometimes the size seems to vary ???
339 m_pngData = (void*) new char[m_pngSize];
340
341 wxMemoryOutputStream mstream( (char*) m_pngData, m_pngSize );
342 handler.SaveFile( &image, mstream );
343 }
344
345 // ----------------------------------------------------------------------------
346 // wxPrivateDataObject
347 // ----------------------------------------------------------------------------
348
349 IMPLEMENT_CLASS( wxPrivateDataObject, wxDataObject )
350
351 void wxPrivateDataObject::Free()
352 {
353 if ( m_data )
354 free(m_data);
355 }
356
357 wxPrivateDataObject::wxPrivateDataObject()
358 {
359 wxString id = wxT("application/");
360 id += wxTheApp->GetAppName();
361
362 m_format.SetId( id );
363
364 m_size = 0;
365 m_data = (void *)NULL;
366 }
367
368 void wxPrivateDataObject::SetData( const void *data, size_t size )
369 {
370 Free();
371
372 m_size = size;
373 m_data = malloc(size);
374
375 memcpy( m_data, data, size );
376 }
377
378 void wxPrivateDataObject::WriteData( void *dest ) const
379 {
380 WriteData( m_data, dest );
381 }
382
383 size_t wxPrivateDataObject::GetSize() const
384 {
385 return m_size;
386 }
387
388 void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
389 {
390 memcpy( dest, data, GetSize() );
391 }
392