// tilefilewin.cpp -- the tile file selection window // // Written by Frederic Bouvier, started April 2003. // // Copyright (C) 2003 Frederic Bouvier - fredb@users.sourceforge.net // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program 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 // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // $Id: tilefilewin.cpp,v 1.11 2005/05/09 07:02:15 fredb Exp $ #include #include "tilefilewin.hpp" #include #include FGSD_TileFileWindow::FGSD_TileFileWindow( const std::list &pathList, const char *current ) : FGSD_Window( 280, 280, "Tile selection dialog" ) , _sceneryList( pathList ) , _level( 0 ) , _curdir( current ) { begin(); if ( current[0] == 0 ) _level = 0; else if ( strchr( current, '/' ) == 0 ) _level = 1; else _level = 2; _browser = new TileBrowser( 10, 30, 260, 160, _level == 0 ? "10x10 chunks :" : ( _level == 1 ? "1x1 chunks :" : "Individual tiles :" ) ); _browser->align( FL_ALIGN_TOP | FL_ALIGN_LEFT ); _browser->callback( &FGSD_TileFileWindow::browserClick, this ); _browser->load( _curdir.c_str(), _level != 0, _sceneryList ); _chunkName = new Fl_Output( 10, 200, 260, 30 ); _close = new Fl_Button( 10, 240, 80, 30, "Close" ); _close->callback( &FGSD_TileFileWindow::closeDialog, this ); _open = new Fl_Button( 100, 240, 80, 30, "Open" ); _open->callback( &FGSD_TileFileWindow::openDir, this ); _select = new Fl_Button( 190, 240, 80, 30, "Select" ); _select->callback( &FGSD_TileFileWindow::select, this ); end(); resizable( _browser ); browserClick(); } void FGSD_TileFileWindow::closeDialog( Fl_Widget *w, void *v ) { static_cast( v )->clear_value(); static_cast( v )->hide(); } void FGSD_TileFileWindow::openDir( Fl_Widget *w, void *v ) { static_cast( v )->openDir(); } void FGSD_TileFileWindow::select( Fl_Widget *w, void *v ) { static_cast( v )->set_value(); static_cast( v )->hide(); } void FGSD_TileFileWindow::browserClick( Fl_Widget *w, void *v ) { static_cast( v )->browserClick(); } void FGSD_TileFileWindow::openDir() { int i = _browser->value(); if ( i == 0 ) return; const char *n = _browser->text( i ); if ( strcmp( n, "" ) == 0 ) { if ( _level > 0 ) { _level -= 1; size_t pos = _curdir.rfind( '/' ); if ( pos == std::string::npos ) { _curdir = ""; } else { _curdir.erase( pos ); } _browser->load( _curdir.c_str(), _level != 0, _sceneryList ); } } else if ( _level == 0 ) { _level = 1; _curdir = n; _browser->load( n, true, _sceneryList ); } else if ( _level == 1 ) { _level = 2; _curdir += "/"; _curdir += n; _browser->load( _curdir.c_str(), true, _sceneryList ); } if ( _level == 0 ) { _browser->label( "10x10 chunks :" ); } else if ( _level == 1 ) { _browser->label( "1x1 chunks :" ); } else { _browser->label( "Individual tiles :" ); } redraw(); } void FGSD_TileFileWindow::browserClick() { if ( Fl::event_clicks() ) { if ( _level == 2 ) { int i = _browser->value(); if ( i > 0 ) { const char *n = _browser->text( i ); if ( strcmp( n, "" ) == 0 ) { openDir(); } else { set_value(); hide(); } } } else { openDir(); } } else { int i = _browser->value(); if ( i == 0 ) { _chunkName->value( "" ); } else { std::string chunk = _curdir; const char *n = _browser->text( i ); if ( strcmp( n, "" ) == 0 ) { _open->activate(); _select->deactivate(); } else if ( _level == 0 ) { chunk = n; _select->activate(); _open->activate(); } else if ( _level == 1 ) { chunk = _curdir + "/" + n; _select->activate(); _open->activate(); } else if ( _level == 2 ) { chunk = _curdir + "/" + n; _select->activate(); _open->deactivate(); } _chunkName->value( chunk.c_str() ); } } } std::vector FGSD_TileFileWindow::selected() const { std::vector ret; int nb = _browser->size(); for ( int i = 1; i <= nb; i++ ) { if ( i != 1 || _level == 0 ) { if ( _browser->selected( i ) ) ret.push_back( _browser->text( i ) ); } } return ret; } FGSD_TileFileWindow::TileBrowser::TileBrowser( int x, int y, int w, int h, const char *l ) : Fl_Multi_Browser( x, y, w, h, l ) { } void FGSD_TileFileWindow::TileBrowser::load( const char *dir, bool up, const std::list &sceneryList ) { std::set elements; for ( std::list::const_iterator it = sceneryList.begin(); it != sceneryList.end(); ++it ) { std::string current = *it; size_t l = current.size(), p = current.rfind( '/' ); if ( p != l-1 ) { current.append( 1, '/' ); p = l; } std::string path[2]; path[0] = current + "Terrain/"; path[1] = current + "Objects/"; if ( !fl_filename_isdir( path[0].c_str() ) ) { path[0] = current; path[1] = ""; } else if ( !fl_filename_isdir( path[1].c_str() ) ) { path[1] = ""; } for ( size_t i = 0; i < 2; i++ ) { if ( !path[i].empty() ) { if ( dir != 0 && dir[0] != 0 ) { path[i] += dir; path[i] += "/"; } dirent **files; int num_files = fl_filename_list( path[i].c_str(), &files ); for ( int j = 0; j < num_files; j++ ) { std::string d_name = files[j]->d_name; size_t l; if ( ( l = d_name.size() ) > 1 && d_name[ l - 1 ] == '/' ) d_name.erase( l - 1 ); if ( d_name != "." && d_name != ".." ) { std::string full = path[i] + d_name; int isdir = fl_filename_isdir( full.c_str() ); if ( ( isdir && fl_filename_match( d_name.c_str(), "[eEwW][0-9][0-9][0-9][sSnN][0-9][0-9]" ) ) || ( !isdir && fl_filename_match( d_name.c_str(), "*.stg" ) ) ) { elements.insert( d_name ); } } } } } } clear(); if ( up ) { add( "" ); } for ( std::set::iterator ii = elements.begin(); ii != elements.end(); ++ii ) { add( ii->c_str() ); } if ( value() >= children() ) value( 0 ); }