]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/filectrl.cpp
Also update cursor when over toolbar and titlebar
[wxWidgets.git] / src / gtk / filectrl.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/filectrl.cpp
3 // Purpose:     wxGtkFileCtrl Implementation
4 // Author:      Diaa M. Sami
5 // Created:     2007-08-10
6 // RCS-ID:      $Id$
7 // Copyright:   (c) Diaa M. Sami
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #include "wx/filectrl.h"
18
19 #if wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)
20
21 #ifndef WX_PRECOMP
22 #    include "wx/sizer.h"
23 #    include "wx/debug.h"
24 #endif
25
26 #include "wx/gtk/private.h"
27 #include "wx/filedlg.h"
28 #include "wx/filename.h"
29 #include "wx/tokenzr.h"
30
31 //-----------------------------------------------------------------------------
32 // wxGtkFileChooser implementation
33 //-----------------------------------------------------------------------------
34
35 void wxGtkFileChooser::SetWidget(GtkFileChooser *w)
36 {
37     // check arguments
38     wxASSERT( w );
39     wxASSERT( GTK_FILE_CHOOSER( w ) );
40
41     this->m_widget = w;
42 }
43
44 wxString wxGtkFileChooser::GetPath() const
45 {
46     wxGtkString str( gtk_file_chooser_get_filename( m_widget ) );
47
48     wxString string;
49     if (str.c_str() != NULL)
50         string = wxConvFileName->cMB2WX(str);
51     return string;
52 }
53
54 void wxGtkFileChooser::GetFilenames( wxArrayString& files ) const
55 {
56     GetPaths( files );
57     for ( size_t n = 0; n < files.GetCount(); ++n )
58     {
59         const wxFileName file( files[n] );
60         files[n] = file.GetFullName();
61     }
62 }
63
64 void wxGtkFileChooser::GetPaths( wxArrayString& paths ) const
65 {
66     paths.Empty();
67     if ( gtk_file_chooser_get_select_multiple( m_widget ) )
68     {
69         GSList *gpathsi = gtk_file_chooser_get_filenames( m_widget );
70         GSList *gpaths = gpathsi;
71         while ( gpathsi )
72         {
73             wxString file( wxConvFileName->cMB2WX( ( gchar* ) gpathsi->data ) );
74             paths.Add( file );
75             g_free( gpathsi->data );
76             gpathsi = gpathsi->next;
77         }
78
79         g_slist_free( gpaths );
80     }
81     else
82         paths.Add( GetPath() );
83 }
84
85 bool wxGtkFileChooser::SetPath( const wxString& path )
86 {
87     if ( path.empty() ) return true;
88
89     return gtk_file_chooser_set_filename( m_widget,
90                                           wxConvFileName->cWX2MB( path.c_str() ) );
91 }
92
93 bool wxGtkFileChooser::SetDirectory( const wxString& dir )
94 {
95     const gboolean b =
96         gtk_file_chooser_set_current_folder( m_widget,
97                                              wxConvFileName->cWX2MB( dir.c_str() ) );
98     return b != 0;
99 }
100
101 wxString wxGtkFileChooser::GetDirectory() const
102 {
103     const wxGtkString str( gtk_file_chooser_get_current_folder( m_widget ) );
104     return wxString( str, *wxConvFileName );
105 }
106
107 wxString wxGtkFileChooser::GetFilename() const
108 {
109     return wxFileName( GetPath() ).GetFullName();
110 }
111
112 void wxGtkFileChooser::SetWildcard( const wxString& wildCard )
113 {
114     m_wildcards.Empty();
115
116     // parse filters
117     wxArrayString wildDescriptions, wildFilters;
118
119     if ( !wxParseCommonDialogsFilter( wildCard, wildDescriptions, wildFilters ) )
120     {
121         wxFAIL_MSG( wxT( "wxGtkFileChooser::SetWildcard - bad wildcard string" ) );
122     }
123     else
124     {
125         // Parsing went fine. Set m_wildCard to be returned by wxGtkFileChooserBase::GetWildcard
126         GtkFileChooser* chooser = m_widget;
127
128         // empty current filter list:
129         GSList* ifilters = gtk_file_chooser_list_filters( chooser );
130         GSList* filters = ifilters;
131
132         while ( ifilters )
133         {
134             gtk_file_chooser_remove_filter( chooser, GTK_FILE_FILTER( ifilters->data ) );
135             ifilters = ifilters->next;
136         }
137         g_slist_free( filters );
138
139         if (!wildCard.empty())
140         {
141             // add parsed to GtkChooser
142             for ( size_t n = 0; n < wildFilters.GetCount(); ++n )
143             {
144                 GtkFileFilter* filter = gtk_file_filter_new();
145
146                 gtk_file_filter_set_name( filter, wxGTK_CONV_SYS( wildDescriptions[n] ) );
147
148                 wxStringTokenizer exttok( wildFilters[n], wxT( ";" ) );
149                 
150                 int n1 = 1;
151                 while ( exttok.HasMoreTokens() )
152                 {
153                     wxString token = exttok.GetNextToken();
154                     gtk_file_filter_add_pattern( filter, wxGTK_CONV_SYS( token ) );
155                     
156                     if (n1 == 1)
157                         m_wildcards.Add( token ); // Only add first pattern to list, used later when saving
158                     n1++;
159                 }
160
161                 gtk_file_chooser_add_filter( chooser, filter );
162             }
163
164             // Reset the filter index
165             SetFilterIndex( 0 );
166         }
167     }
168 }
169
170 void wxGtkFileChooser::SetFilterIndex( int filterIndex )
171 {
172     gpointer filter;
173     GtkFileChooser *chooser = m_widget;
174     GSList *filters = gtk_file_chooser_list_filters( chooser );
175
176     filter = g_slist_nth_data( filters, filterIndex );
177
178     if ( filter != NULL )
179     {
180         gtk_file_chooser_set_filter( chooser, GTK_FILE_FILTER( filter ) );
181     }
182     else
183     {
184         wxFAIL_MSG( wxT( "wxGtkFileChooser::SetFilterIndex - bad filter index" ) );
185     }
186
187     g_slist_free( filters );
188 }
189
190 int wxGtkFileChooser::GetFilterIndex() const
191 {
192     GtkFileChooser *chooser = m_widget;
193     GtkFileFilter *filter = gtk_file_chooser_get_filter( chooser );
194     GSList *filters = gtk_file_chooser_list_filters( chooser );
195     const gint index = g_slist_index( filters, filter );
196     g_slist_free( filters );
197
198     if ( index == -1 )
199     {
200         wxFAIL_MSG( wxT( "wxGtkFileChooser::GetFilterIndex - bad filter index returned by gtk+" ) );
201         return 0;
202     }
203     else
204         return index;
205 }
206
207 //-----------------------------------------------------------------------------
208 // end wxGtkFileChooser Implementation
209 //-----------------------------------------------------------------------------
210
211 #if wxUSE_FILECTRL
212
213 // gtk signal handlers
214
215 extern "C"
216 {
217     static void
218     gtkfilechooserwidget_file_activated_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
219     {
220         GenerateFileActivatedEvent( fileCtrl, fileCtrl );
221     }
222 }
223
224 extern "C"
225 {
226     static void
227     gtkfilechooserwidget_selection_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
228     {
229         // check next selection event and ignore it if it has 0 files
230         // because such events are redundantly generated by gtk.
231         if ( fileCtrl->m_checkNextSelEvent )
232         {
233             wxArrayString filenames;
234             fileCtrl->GetFilenames( filenames );
235
236             if ( filenames.Count() != 0 )
237                 fileCtrl->m_checkNextSelEvent = false;
238         }
239
240         if ( !fileCtrl->m_checkNextSelEvent )
241             GenerateSelectionChangedEvent( fileCtrl, fileCtrl );
242     }
243 }
244
245 extern "C"
246 {
247     static void
248     gtkfilechooserwidget_folder_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
249     {
250         if ( fileCtrl->m_ignoreNextFolderChangeEvent )
251         {
252             fileCtrl->m_ignoreNextFolderChangeEvent = false;
253         }
254         else
255         {
256             GenerateFolderChangedEvent( fileCtrl, fileCtrl );
257         }
258
259         fileCtrl->m_checkNextSelEvent = true;
260     }
261 }
262
263 // wxGtkFileCtrl implementation
264
265 IMPLEMENT_DYNAMIC_CLASS( wxGtkFileCtrl, wxControl )
266
267 void wxGtkFileCtrl::Init()
268 {
269     m_checkNextSelEvent = false;
270
271     // ignore the first folder change event which is fired upon startup.
272     m_ignoreNextFolderChangeEvent = true;
273 }
274
275 bool wxGtkFileCtrl::Create( wxWindow *parent,
276                             wxWindowID id,
277                             const wxString& defaultDirectory,
278                             const wxString& defaultFileName,
279                             const wxString& wildCard,
280                             long style,
281                             const wxPoint& pos,
282                             const wxSize& size,
283                             const wxString& name )
284 {
285     if ( !PreCreation( parent, pos, size ) ||
286             !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ) )
287     {
288         wxFAIL_MSG( wxT( "wxGtkFileCtrl creation failed" ) );
289         return false;
290     }
291
292     GtkFileChooserAction gtkAction = GTK_FILE_CHOOSER_ACTION_OPEN;
293
294     if ( style & wxFC_SAVE )
295         gtkAction = GTK_FILE_CHOOSER_ACTION_SAVE;
296
297     m_widget =  gtk_alignment_new ( 0, 0, 1, 1 );
298     g_object_ref(m_widget);
299     m_fcWidget = GTK_FILE_CHOOSER( gtk_file_chooser_widget_new(gtkAction) );
300     gtk_widget_show ( GTK_WIDGET( m_fcWidget ) );
301     gtk_container_add ( GTK_CONTAINER ( m_widget ), GTK_WIDGET( m_fcWidget ) );
302
303     m_focusWidget = GTK_WIDGET( m_fcWidget );
304
305     g_signal_connect ( m_fcWidget, "file-activated",
306                        G_CALLBACK ( gtkfilechooserwidget_file_activated_callback ),
307                        this );
308
309     g_signal_connect ( m_fcWidget, "current-folder-changed",
310                        G_CALLBACK ( gtkfilechooserwidget_folder_changed_callback ),
311                        this );
312
313     g_signal_connect ( m_fcWidget, "selection-changed",
314                        G_CALLBACK ( gtkfilechooserwidget_selection_changed_callback ),
315                        this );
316
317     m_fc.SetWidget( m_fcWidget );
318
319     if ( style & wxFC_MULTIPLE )
320         gtk_file_chooser_set_select_multiple( m_fcWidget, true );
321
322     SetWildcard( wildCard );
323
324     // if defaultDir is specified it should contain the directory and
325     // defaultFileName should contain the default name of the file, however if
326     // directory is not given, defaultFileName contains both
327     wxFileName fn;
328     if ( defaultDirectory.empty() )
329         fn.Assign( defaultFileName );
330     else if ( !defaultFileName.empty() )
331         fn.Assign( defaultDirectory, defaultFileName );
332     else
333         fn.AssignDir( defaultDirectory );
334
335     // set the initial file name and/or directory
336     const wxString dir = fn.GetPath();
337     if ( !dir.empty() )
338     {
339         gtk_file_chooser_set_current_folder( m_fcWidget,
340                                              dir.fn_str() );
341     }
342
343     const wxString fname = fn.GetFullName();
344     if ( style & wxFC_SAVE )
345     {
346         if ( !fname.empty() )
347         {
348             gtk_file_chooser_set_current_name( m_fcWidget,
349                                                fname.fn_str() );
350         }
351     }
352     else // wxFC_OPEN
353     {
354         if ( !fname.empty() )
355         {
356             gtk_file_chooser_set_filename( m_fcWidget,
357                                            fn.GetFullPath().fn_str() );
358         }
359     }
360
361     m_parent->DoAddChild( this );
362
363     PostCreation( size );
364
365     return TRUE;
366 }
367
368 bool wxGtkFileCtrl::SetPath( const wxString& path )
369 {
370     return m_fc.SetPath( path );
371 }
372
373 bool wxGtkFileCtrl::SetDirectory( const wxString& dir )
374 {
375     return m_fc.SetDirectory( dir );
376 }
377
378 bool wxGtkFileCtrl::SetFilename( const wxString& name )
379 {
380     if ( HasFlag( wxFC_SAVE ) )
381     {
382         gtk_file_chooser_set_current_name( m_fcWidget, wxGTK_CONV( name ) );
383         return true;
384     }
385     else
386         return SetPath( wxFileName( GetDirectory(), name ).GetFullPath() );
387 }
388
389 void wxGtkFileCtrl::SetWildcard( const wxString& wildCard )
390 {
391     m_wildCard = wildCard;
392
393     m_fc.SetWildcard( wildCard );
394 }
395
396 void wxGtkFileCtrl::SetFilterIndex( int filterIndex )
397 {
398     m_fc.SetFilterIndex( filterIndex );
399 }
400
401 wxString wxGtkFileCtrl::GetPath() const
402 {
403     return m_fc.GetPath();
404 }
405
406 void wxGtkFileCtrl::GetPaths( wxArrayString& paths ) const
407 {
408     m_fc.GetPaths( paths );
409 }
410
411 wxString wxGtkFileCtrl::GetDirectory() const
412 {
413     return m_fc.GetDirectory();
414 }
415
416 wxString wxGtkFileCtrl::GetFilename() const
417 {
418     return m_fc.GetFilename();
419 }
420
421 void wxGtkFileCtrl::GetFilenames( wxArrayString& files ) const
422 {
423     m_fc.GetFilenames( files );
424 }
425
426 void wxGtkFileCtrl::ShowHidden(bool show)
427 {
428     // gtk_file_chooser_set_show_hidden() is new in 2.6
429     g_object_set (G_OBJECT (m_fcWidget), "show-hidden", show, NULL);
430 }
431
432 #endif // wxUSE_FILECTRL
433
434 #endif // wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)