1 // "$Id: Fl_Native_File_Chooser_FLTK.cxx 8282 2011-01-16 18:26:51Z manolo $"
3 // FLTK native OS file chooser widget
5 // Copyright 1998-2010 by Bill Spitzak and others.
6 // Copyright 2004 Greg Ercolano.
7 // API changes + filter improvements by Nathan Vander Wilt 2005
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Library General Public License for more details.
19 // You should have received a copy of the GNU Library General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 // Please report all bugs and problems to:
26 // http://www.fltk.org/str.php
29 #include <FL/Fl_Native_File_Chooser.H>
30 #include <FL/Fl_File_Icon.H>
31 #define FLTK_CHOOSER_SINGLE Fl_File_Chooser::SINGLE
32 #define FLTK_CHOOSER_DIRECTORY Fl_File_Chooser::DIRECTORY
33 #define FLTK_CHOOSER_MULTI Fl_File_Chooser::MULTI
34 #define FLTK_CHOOSER_CREATE Fl_File_Chooser::CREATE
36 #include "Fl_Native_File_Chooser_common.cxx"
41 The constructor. Internally allocates the native widgets.
42 Optional \p val presets the type of browser this will be,
43 which can also be changed with type().
45 Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val
) {
46 //// CANT USE THIS -- MESSES UP LINKING/CREATES DEPENDENCY ON fltk_images.
47 //// Have app call this from main() instead.
49 //// static int init = 0; // 'first time' initialize flag
50 //// if ( init == 0 ) {
51 //// // Initialize when instanced for first time
52 //// Fl_File_Icon::load_system_icons();
56 _options
= NO_OPTIONS
;
64 _file_chooser
= new Fl_File_Chooser(NULL
, NULL
, 0, NULL
);
65 type(val
); // do this after _file_chooser created
71 Deallocates any resources allocated to this widget.
73 Fl_Native_File_Chooser::~Fl_Native_File_Chooser() {
75 _filter
= strfree(_filter
);
76 _parsedfilt
= strfree(_parsedfilt
);
77 _preset_file
= strfree(_preset_file
);
78 _prevvalue
= strfree(_prevvalue
);
79 _directory
= strfree(_directory
);
80 _errmsg
= strfree(_errmsg
);
83 // PRIVATE: SET ERROR MESSAGE
84 void Fl_Native_File_Chooser::errmsg(const char *msg
) {
85 _errmsg
= strfree(_errmsg
);
86 _errmsg
= strnew(msg
);
89 // PRIVATE: translate Native types to Fl_File_Chooser types
90 int Fl_Native_File_Chooser::type_fl_file(int val
) {
93 return(FLTK_CHOOSER_SINGLE
);
94 case BROWSE_DIRECTORY
:
95 return(FLTK_CHOOSER_SINGLE
| FLTK_CHOOSER_DIRECTORY
);
96 case BROWSE_MULTI_FILE
:
97 return(FLTK_CHOOSER_MULTI
);
98 case BROWSE_MULTI_DIRECTORY
:
99 return(FLTK_CHOOSER_DIRECTORY
| FLTK_CHOOSER_MULTI
);
100 case BROWSE_SAVE_FILE
:
101 return(FLTK_CHOOSER_SINGLE
| FLTK_CHOOSER_CREATE
);
102 case BROWSE_SAVE_DIRECTORY
:
103 return(FLTK_CHOOSER_DIRECTORY
| FLTK_CHOOSER_MULTI
| FLTK_CHOOSER_CREATE
);
105 return(FLTK_CHOOSER_SINGLE
);
110 Sets the current Fl_Native_File_Chooser::Type of browser.
112 void Fl_Native_File_Chooser::type(int val
) {
114 _file_chooser
->type(type_fl_file(val
));
118 Gets the current Fl_Native_File_Chooser::Type of browser.
120 int Fl_Native_File_Chooser::type() const {
125 Sets the platform specific chooser options to \p val.
126 \p val is expected to be one or more Fl_Native_File_Chooser::Option flags ORed together.
127 Some platforms have OS-specific functions that can be enabled/disabled via this method.
130 Flag Description Win Mac Other
131 -------------- ----------------------------------------------- ------- ------- -------
132 NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used
133 PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used
134 SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Ignored Used Used
137 void Fl_Native_File_Chooser::options(int val
) {
142 Gets the platform specific Fl_Native_File_Chooser::Option flags.
144 int Fl_Native_File_Chooser::options() const {
149 Post the chooser's dialog. Blocks until dialog has been completed or cancelled.
151 - 0 -- user picked a file
152 - 1 -- user cancelled
153 - -1 -- failed; errmsg() has reason
155 int Fl_Native_File_Chooser::show() {
158 _file_chooser
->filter(_parsedfilt
);
162 // Set this /after/ setting the filter
164 _file_chooser
->filter_value(_filtvalue
);
167 if ( _directory
&& _directory
[0] ) {
168 _file_chooser
->directory(_directory
);
170 _file_chooser
->directory(_prevvalue
);
174 if ( _preset_file
) {
175 _file_chooser
->value(_preset_file
);
179 _file_chooser
->preview( (options() & PREVIEW
) ? 1 : 0);
181 // OPTIONS: NEW FOLDER
182 if ( options() & NEW_FOLDER
)
183 _file_chooser
->type(_file_chooser
->type() | FLTK_CHOOSER_CREATE
); // on
186 _file_chooser
->show();
188 // BLOCK WHILE BROWSER SHOWN
189 while ( _file_chooser
->shown() ) {
193 if ( _file_chooser
->value() && _file_chooser
->value()[0] ) {
194 _prevvalue
= strfree(_prevvalue
);
195 _prevvalue
= strnew(_file_chooser
->value());
196 _filtvalue
= _file_chooser
->filter_value(); // update filter value
198 // HANDLE SHOWING 'SaveAs' CONFIRM
199 if ( options() & SAVEAS_CONFIRM
&& type() == BROWSE_SAVE_FILE
) {
201 if ( stat(_file_chooser
->value(), &buf
) != -1 ) {
202 if ( buf
.st_mode
& S_IFREG
) { // Regular file + exists?
203 if ( exist_dialog() == 0 ) {
211 if ( _file_chooser
->count() ) return(0);
216 Returns a system dependent error message for the last method that failed.
217 This message should at least be flagged to the user in a dialog box, or to some kind of error log.
218 Contents will be valid only for methods that document errmsg() will have info on failures.
220 const char *Fl_Native_File_Chooser::errmsg() const {
221 return(_errmsg
? _errmsg
: "No error");
225 Return the filename the user choose.
226 Use this if only expecting a single filename.
227 If more than one filename is expected, use filename(int) instead.
228 Return value may be "" if no filename was chosen (eg. user cancelled).
230 const char* Fl_Native_File_Chooser::filename() const {
231 if ( _file_chooser
->count() > 0 ) return(_file_chooser
->value());
236 Return one of the filenames the user selected.
237 Use count() to determine how many filenames the user selected.
241 if ( fnfc->show() == 0 ) {
242 // Print all filenames user selected
243 for (int n=0; n<fnfc->count(); n++ ) {
244 printf("%d) '%s'\n", n, fnfc->filename(n));
249 const char* Fl_Native_File_Chooser::filename(int i
) const {
250 if ( i
< _file_chooser
->count() )
251 return(_file_chooser
->value(i
+1)); // convert fltk 1 based to our 0 based
256 Set the title of the file chooser's dialog window.
257 Can be NULL if no title desired.
258 The default title varies according to the platform, so you are advised to set the title explicitly.
260 void Fl_Native_File_Chooser::title(const char *val
) {
261 _file_chooser
->label(val
);
265 Get the title of the file chooser's dialog window.
266 Return value may be NULL if no title was set.
268 const char *Fl_Native_File_Chooser::title() const {
269 return(_file_chooser
->label());
273 Sets the filename filters used for browsing.
274 The default is NULL, which browses all files.
276 The filter string can be any of:
278 - A single wildcard (eg. "*.txt")
279 - Multiple wildcards (eg. "*.{cxx,h,H}")
280 - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt")
281 - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt")
282 - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt")
284 The format of each filter is a wildcard, or an optional user description
285 followed by '\\t' and the wildcard.
287 On most platforms, each filter is available to the user via a pulldown menu
288 in the file chooser. The 'All Files' option is always available to the user.
290 void Fl_Native_File_Chooser::filter(const char *val
) {
291 _filter
= strfree(_filter
);
292 _filter
= strnew(val
);
297 Returns the filter string last set.
298 Can be NULL if no filter was set.
300 const char *Fl_Native_File_Chooser::filter() const {
305 Gets how many filters were available, not including "All Files"
307 int Fl_Native_File_Chooser::filters() const {
312 Sets which filter will be initially selected.
314 The first filter is indexed as 0.
315 If filter_value()==filters(), then "All Files" was chosen.
316 If filter_value() > filters(), then a custom filter was set.
318 void Fl_Native_File_Chooser::filter_value(int val
) {
323 Returns which filter value was last selected by the user.
324 This is only valid if the chooser returns success.
326 int Fl_Native_File_Chooser::filter_value() const {
331 Returns the number of filenames (or directory names) the user selected.
335 if ( fnfc->show() == 0 ) {
336 // Print all filenames user selected
337 for (int n=0; n<fnfc->count(); n++ ) {
338 printf("%d) '%s'\n", n, fnfc->filename(n));
343 int Fl_Native_File_Chooser::count() const {
344 return(_file_chooser
->count());
348 Preset the directory the browser will show when opened.
349 If \p val is NULL, or no directory is specified, the chooser will attempt
350 to use the last non-cancelled folder.
352 void Fl_Native_File_Chooser::directory(const char *val
) {
353 _directory
= strfree(_directory
);
354 _directory
= strnew(val
);
358 Returns the current preset directory() value.
360 const char *Fl_Native_File_Chooser::directory() const {
364 // PRIVATE: Convert our filter format to fltk's chooser format
366 // ------------------------- --------------------------
367 // "*.cxx" "*.cxx Files(*.cxx)"
368 // "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})"
369 // "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)"
371 // Returns a modified version of the filter that the caller is responsible
372 // for freeing with strfree().
374 void Fl_Native_File_Chooser::parse_filter() {
375 _parsedfilt
= strfree(_parsedfilt
); // clear previous parsed filter (if any)
380 int has_name
= strchr(in
, '\t') ? 1 : 0;
382 char mode
= has_name
? 'n' : 'w'; // parse mode: n=title, w=wildcard
383 char wildcard
[1024] = ""; // parsed wildcard
384 char name
[1024] = "";
386 // Parse filter user specified
389 printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n",
390 *in, mode, name, wildcard);
394 // FINISHED PARSING NAME?
396 if ( mode
!= 'n' ) goto regchar
;
403 // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
407 // APPEND NEW FILTER TO LIST
409 // OUT: "name(wild)\tname(wild)"
411 sprintf(comp
, "%s%.511s(%.511s)", ((_parsedfilt
)?"\t":""),
413 _parsedfilt
= strapp(_parsedfilt
, comp
);
415 //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt);
418 wildcard
[0] = name
[0] = '\0';
419 mode
= strchr(in
, '\t') ? 'n' : 'w';
421 if ( *in
== '\0' ) return; // done
422 else continue; // not done yet, more filters
424 // Parse all other chars
425 default: // handle all non-special chars
426 regchar
: // handle regular char
428 case 'n': chrcat(name
, *in
); continue;
429 case 'w': chrcat(wildcard
, *in
); continue;
438 Sets the default filename for the chooser.
439 Use directory() to set the default directory.
440 Mainly used to preset the filename for save dialogs,
441 and on most platforms can be used for opening files as well.
443 void Fl_Native_File_Chooser::preset_file(const char* val
) {
444 _preset_file
= strfree(_preset_file
);
445 _preset_file
= strnew(val
);
449 Get the preset filename.
451 const char* Fl_Native_File_Chooser::preset_file() const {
452 return(_preset_file
);
456 int Fl_Native_File_Chooser::exist_dialog() {
457 return(fl_choice("%s", fl_cancel
, fl_ok
, NULL
, file_exists_message
));
461 // End of "$Id: Fl_Native_File_Chooser_FLTK.cxx 8282 2011-01-16 18:26:51Z manolo $".