summaryrefslogtreecommitdiff
path: root/src/Fl_Native_File_Chooser_FLTK.cxx
diff options
context:
space:
mode:
authorGreg Ercolano <erco@seriss.com>2010-01-13 23:13:59 +0000
committerGreg Ercolano <erco@seriss.com>2010-01-13 23:13:59 +0000
commit1de0988c317c7b916daa7b4f102f0889e026c77d (patch)
treee479de5817a0d0388e1f4c1a62db018ea9f2981f /src/Fl_Native_File_Chooser_FLTK.cxx
parent139c88c618ae6a186c59bde73e05ea93caa3e297 (diff)
Added Fl_Native_File_Chooser widget (with manolo's cocoa mods) to FLTK.
* Source brought into CMP standards compliance * test program added (test/native-filechooser.cxx) * Tested with linux (Ubuntu8) and with OSX (cocoa and non-cocoa builds) TODO: * Needs doxygen docs from Greg's original HTML documentation * Needs mods to Windows build files * Needs mods to cmake, and other build files * Needs Manolo's latest mods (from STR #2298) mentioned on and after "02:05 Jan 13, 2010" git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6997 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_Native_File_Chooser_FLTK.cxx')
-rw-r--r--src/Fl_Native_File_Chooser_FLTK.cxx395
1 files changed, 395 insertions, 0 deletions
diff --git a/src/Fl_Native_File_Chooser_FLTK.cxx b/src/Fl_Native_File_Chooser_FLTK.cxx
new file mode 100644
index 000000000..e77e18700
--- /dev/null
+++ b/src/Fl_Native_File_Chooser_FLTK.cxx
@@ -0,0 +1,395 @@
+// "$Id$"
+//
+// FLTK native OS file chooser widget
+//
+// Copyright 1998-2005 by Bill Spitzak and others.
+// Copyright 2004 Greg Ercolano.
+// API changes + filter improvements by Nathan Vander Wilt 2005
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+// Please report all bugs and problems to:
+//
+// http://www.fltk.org/str.php
+//
+
+#include <FL/Fl_Native_File_Chooser.H>
+#include <FL/Fl_File_Icon.H>
+#define FNFC_CLASS Fl_Native_File_Chooser
+#define FNFC_CTOR Fl_Native_File_Chooser
+#define FLTK_CHOOSER_SINGLE Fl_File_Chooser::SINGLE
+#define FLTK_CHOOSER_DIRECTORY Fl_File_Chooser::DIRECTORY
+#define FLTK_CHOOSER_MULTI Fl_File_Chooser::MULTI
+#define FLTK_CHOOSER_CREATE Fl_File_Chooser::CREATE
+
+#include "Fl_Native_File_Chooser_common.cxx"
+#include <sys/stat.h>
+
+// CTOR
+FNFC_CLASS::FNFC_CTOR(int val) {
+ //// CANT USE THIS -- MESSES UP LINKING/CREATES DEPENDENCY ON fltk_images.
+ //// Have user call this from app instead.
+ ////
+ //// static int init = 0; // 'first time' initialize flag
+ //// if ( init == 0 ) {
+ //// // Initialize when instanced for first time
+ //// Fl_File_Icon::load_system_icons();
+ //// init = 1;
+ //// }
+ _btype = val;
+ _options = NO_OPTIONS;
+ _filter = NULL;
+ _filtvalue = 0;
+ _parsedfilt = NULL;
+ _preset_file = NULL;
+ _prevvalue = NULL;
+ _directory = NULL;
+ _errmsg = NULL;
+ file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL);
+ type(val); // do this after file_chooser created
+ _nfilters = 0;
+
+ // Added by MG
+ Fl_Button *b = file_chooser->previewButton;
+ Fl_Window *w = b->window();
+ Fl_Group::current(w); // adds a "Show hidden files" check button in file_chooser's window
+ show_hidden = new Fl_Check_Button(b->x() + b->w() + 10, b->y(), 145, b->h(), "Show hidden files");
+ show_hidden->callback((Fl_Callback*)show_hidden_cb, this);
+ // This is a hack to bypass the fact that fileList is a private member of file_chooser.
+ // Find it as 1st child of 2nd child of file_chooser's window.
+ Fl_Group *g = (Fl_Group *)w->array()[1];
+ my_fileList = (Fl_File_Browser *)g->array()[0];
+ old_dir[0] = 0; // to detect directory changes
+ prev_filtervalue = file_chooser->filter_value(); // to detect filter changes
+ // Hack to get file_chooser's showChoice widget.
+ // Find it as 1st child of 1st child of file_chooser's window.
+ g = (Fl_Group *)w->array()[0];
+ showChoice = (Fl_Choice *)g->array()[0];
+}
+
+// DTOR
+FNFC_CLASS::~FNFC_CTOR() {
+ delete file_chooser;
+ _filter = strfree(_filter);
+ _parsedfilt = strfree(_parsedfilt);
+ _preset_file = strfree(_preset_file);
+ _prevvalue = strfree(_prevvalue);
+ _directory = strfree(_directory);
+ _errmsg = strfree(_errmsg);
+}
+
+// PRIVATE: SET ERROR MESSAGE
+void FNFC_CLASS::errmsg(const char *msg) {
+ _errmsg = strfree(_errmsg);
+ _errmsg = strnew(msg);
+}
+
+// PRIVATE: translate Native types to Fl_File_Chooser types
+int FNFC_CLASS::type_fl_file(int val) {
+ switch (val) {
+ case BROWSE_FILE:
+ return(FLTK_CHOOSER_SINGLE);
+ case BROWSE_DIRECTORY:
+ return(FLTK_CHOOSER_SINGLE | FLTK_CHOOSER_DIRECTORY);
+ case BROWSE_MULTI_FILE:
+ return(FLTK_CHOOSER_MULTI);
+ case BROWSE_MULTI_DIRECTORY:
+ return(FLTK_CHOOSER_DIRECTORY | FLTK_CHOOSER_MULTI);
+ case BROWSE_SAVE_FILE:
+ return(FLTK_CHOOSER_SINGLE | FLTK_CHOOSER_CREATE);
+ case BROWSE_SAVE_DIRECTORY:
+ return(FLTK_CHOOSER_DIRECTORY | FLTK_CHOOSER_MULTI | FLTK_CHOOSER_CREATE);
+ default:
+ return(FLTK_CHOOSER_SINGLE);
+ }
+}
+
+void FNFC_CLASS::type(int val) {
+ _btype = val;
+ file_chooser->type(type_fl_file(val));
+}
+
+int FNFC_CLASS::type() const {
+ return(_btype);
+}
+
+// SET OPTIONS
+void FNFC_CLASS::options(int val) {
+ _options = val;
+}
+
+// GET OPTIONS
+int FNFC_CLASS::options() const {
+ return(_options);
+}
+
+// Show chooser, blocks until done.
+// RETURNS:
+// 0 - user picked a file
+// 1 - user cancelled
+// -1 - failed; errmsg() has reason
+//
+int FNFC_CLASS::show() {
+ // FILTER
+ if ( _parsedfilt ) {
+ file_chooser->filter(_parsedfilt);
+ }
+
+ // FILTER VALUE
+ // Set this /after/ setting the filter
+ //
+ file_chooser->filter_value(_filtvalue);
+
+ // DIRECTORY
+ if ( _directory && _directory[0] ) {
+ file_chooser->directory(_directory);
+ } else {
+ file_chooser->directory(_prevvalue);
+ }
+
+ // PRESET FILE
+ if ( _preset_file ) {
+ file_chooser->value(_preset_file);
+ }
+
+ // OPTIONS: PREVIEW
+ file_chooser->preview( (options() & PREVIEW) ? 1 : 0);
+
+ // OPTIONS: NEW FOLDER
+ if ( options() & NEW_FOLDER )
+ file_chooser->type(file_chooser->type() | FLTK_CHOOSER_CREATE); // on
+
+ // SHOW
+ file_chooser->show();
+
+ // BLOCK WHILE BROWSER SHOWN
+ while ( file_chooser->shown() ) {
+ if(strcmp(old_dir, file_chooser->directory()) != 0) {
+ strcpy(old_dir, file_chooser->directory());
+ if(!show_hidden->value()) remove_hidden_files(my_fileList);
+ } else if(prev_filtervalue != file_chooser->filter_value() ) {
+ prev_filtervalue = file_chooser->filter_value();
+ if(!show_hidden->value() ) remove_hidden_files(my_fileList);
+ }
+ Fl::wait();
+ }
+
+ if ( file_chooser->value() && file_chooser->value()[0] ) {
+ _prevvalue = strfree(_prevvalue);
+ _prevvalue = strnew(file_chooser->value());
+ _filtvalue = file_chooser->filter_value(); // update filter value
+
+ // HANDLE SHOWING 'SaveAs' CONFIRM
+ if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) {
+ struct stat buf;
+ if ( stat(file_chooser->value(), &buf) != -1 ) {
+ if ( buf.st_mode & S_IFREG ) { // Regular file + exists?
+ if ( exist_dialog() == 0 ) {
+ return(1);
+ }
+ }
+ }
+ }
+ }
+
+ if ( file_chooser->count() ) return(0);
+ else return(1);
+}
+
+// RETURN ERROR MESSAGE
+const char *FNFC_CLASS::errmsg() const {
+ return(_errmsg ? _errmsg : "No error");
+}
+
+// GET FILENAME
+const char* FNFC_CLASS::filename() const {
+ if ( file_chooser->count() > 0 ) return(file_chooser->value());
+ return("");
+}
+
+// GET FILENAME FROM LIST OF FILENAMES
+const char* FNFC_CLASS::filename(int i) const {
+ if ( i < file_chooser->count() )
+ return(file_chooser->value(i+1)); // convert fltk 1 based to our 0 based
+ return("");
+}
+
+// SET TITLE
+// Can be NULL if no title desired.
+//
+void FNFC_CLASS::title(const char *val) {
+ file_chooser->label(val);
+}
+
+// GET TITLE
+// Can return NULL if none set.
+//
+const char *FNFC_CLASS::title() const {
+ return(file_chooser->label());
+}
+
+// SET FILTER
+// Can be NULL if no filter needed
+//
+void FNFC_CLASS::filter(const char *val) {
+ _filter = strfree(_filter);
+ _filter = strnew(val);
+ parse_filter();
+}
+
+// GET FILTER
+const char *FNFC_CLASS::filter() const {
+ return(_filter);
+}
+
+// SET SELECTED FILTER
+void FNFC_CLASS::filter_value(int val) {
+ _filtvalue = val;
+}
+
+// RETURN SELECTED FILTER
+int FNFC_CLASS::filter_value() const {
+ return(_filtvalue);
+}
+
+// GET TOTAL FILENAMES CHOSEN
+int FNFC_CLASS::count() const {
+ return(file_chooser->count());
+}
+
+// PRESET PATHNAME
+// Can be NULL if no preset is desired.
+//
+void FNFC_CLASS::directory(const char *val) {
+ _directory = strfree(_directory);
+ _directory = strnew(val);
+}
+
+// GET PRESET PATHNAME
+// Can return NULL if none set.
+//
+const char *FNFC_CLASS::directory() const {
+ return(_directory);
+}
+
+// Convert our filter format to fltk's chooser format
+// FROM TO (FLTK)
+// ------------------------- --------------------------
+// "*.cxx" "*.cxx Files(*.cxx)"
+// "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})"
+// "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)"
+//
+// Returns a modified version of the filter that the caller is responsible
+// for freeing with strfree().
+//
+void FNFC_CLASS::parse_filter() {
+ _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any)
+ _nfilters = 0;
+ char *in = _filter;
+ if ( !in ) return;
+
+ int has_name = strchr(in, '\t') ? 1 : 0;
+
+ char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard
+ char wildcard[1024] = ""; // parsed wildcard
+ char name[1024] = "";
+
+ // Parse filter user specified
+ for ( ; 1; in++ ) {
+ /*** DEBUG
+ printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n",
+ *in, mode, name, wildcard);
+ ***/
+
+ switch (*in) {
+ // FINISHED PARSING NAME?
+ case '\t':
+ if ( mode != 'n' ) goto regchar;
+ mode = 'w';
+ break;
+ // ESCAPE NEXT CHAR
+ case '\\':
+ ++in;
+ goto regchar;
+ // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
+ case '\r':
+ case '\n':
+ case '\0':
+ // APPEND NEW FILTER TO LIST
+ if ( wildcard[0] ) {
+ // OUT: "name(wild)\tname(wild)"
+ char comp[2048];
+ sprintf(comp, "%s%.511s(%.511s)", ((_parsedfilt)?"\t":""),
+ name, wildcard);
+ _parsedfilt = strapp(_parsedfilt, comp);
+ _nfilters++;
+ //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt);
+ }
+ // RESET
+ wildcard[0] = name[0] = '\0';
+ mode = strchr(in, '\t') ? 'n' : 'w';
+ // DONE?
+ if ( *in == '\0' ) return; // done
+ else continue; // not done yet, more filters
+
+ // Parse all other chars
+ default: // handle all non-special chars
+ regchar: // handle regular char
+ switch ( mode ) {
+ case 'n': chrcat(name, *in); continue;
+ case 'w': chrcat(wildcard, *in); continue;
+ }
+ break;
+ }
+ }
+ //NOTREACHED
+}
+
+// SET PRESET FILENAME
+void FNFC_CLASS::preset_file(const char* val) {
+ _preset_file = strfree(_preset_file);
+ _preset_file = strnew(val);
+}
+
+// GET PRESET FILENAME
+const char* FNFC_CLASS::preset_file() const {
+ return(_preset_file);
+}
+
+void FNFC_CLASS::show_hidden_cb(Fl_Check_Button *o, void *data)
+{
+ Fl_Native_File_Chooser *mychooser = (Fl_Native_File_Chooser *)data;
+ if(o->value()) {
+ mychooser->my_fileList->load(mychooser->file_chooser->directory());
+ } else {
+ remove_hidden_files(mychooser->my_fileList);
+ mychooser->my_fileList->redraw();
+ }
+}
+
+void FNFC_CLASS::remove_hidden_files(Fl_File_Browser *my_fileList)
+{
+ int count = my_fileList->size();
+ for(int num = count; num >= 1; num--) {
+ const char *p = my_fileList->text(num);
+ if(*p == '.' && strcmp(p, "../") != 0) my_fileList->remove(num);
+ }
+ my_fileList->topline(1);
+}
+
+//
+// End of "$Id:".
+//