Files
GDevelop/Extensions/CommonDialogs/nwidgets/OpenFile.cpp
T
2015-06-04 23:15:27 +12:00

457 lines
11 KiB
C++

#include "OpenFile.h"
#include "nStyle.h"
using namespace dlib;
namespace nw
{
OpenFile::OpenFile( const std::string& title, bool has_text_field, string & file_ ) :
lbl_dirs( *this ),
lbl_files( *this ),
lbl_file_name( *this ),
lb_dirs( *this ),
lb_files( *this ),
btn_ok( *this ),
btn_cancel( *this ),
btn_root( *this ),
tf_file_name( *this ),
result(file_)
{
if ( has_text_field == false )
{
tf_file_name.hide();
lbl_file_name.hide();
}
else
{
lbl_file_name.set_text( "File: " );
}
BtStyle btStyle;
TBtStyle tBtStyle;
LbStyle lbStyle;
cur_dir = -1;
set_size( 500, 300 );
lbl_dirs.set_text( "Directories:" );
lbl_files.set_text( "Files:" );
btn_ok.set_name( "Ok" );
btn_ok.set_style(btStyle);
btn_cancel.set_name( "Cancel" );
btn_cancel.set_style(btStyle);
btn_root.set_name( "/" );
btn_root.set_style(tBtStyle);
btn_root.set_click_handler( *this, &OpenFile::on_root_click );
btn_cancel.set_click_handler( *this, &OpenFile::on_cancel_click );
btn_ok.set_click_handler( *this, &OpenFile::on_open_click );
lb_dirs.set_double_click_handler( *this, &OpenFile::on_dirs_click );
lb_dirs.set_style(lbStyle);
lb_files.set_click_handler( *this, &OpenFile::on_files_click );
lb_files.set_double_click_handler( *this, &OpenFile::on_files_double_click );
lb_files.set_style(lbStyle);
btn_root.set_pos( 5, 5 );
set_sizes();
set_title( title );
on_root_click();
// make it so that the file box starts out in our current working
// directory
std::string full_name( get_current_dir() );
while ( full_name.size() > 0 )
{
std::string::size_type pos = full_name.find_first_of( "\\/" );
std::string left( full_name.substr( 0, pos ) );
if ( pos != std::string::npos )
full_name = full_name.substr( pos + 1 );
else
full_name.clear();
if ( left.size() > 0 )
enter_folder( left );
}
set_background_color( 240, 240, 240 );
show();
}
// ------------------------------------------------------------------------------------
OpenFile::
~OpenFile(
)
{
close_window();
}
// ------------------------------------------------------------------------------------
void OpenFile::
set_sizes(
)
{
unsigned long width, height;
get_size( width, height );
if ( lbl_file_name.is_hidden() )
{
lbl_dirs.set_pos( 0, btn_root.bottom() + 5 );
lb_dirs.set_pos( 0, lbl_dirs.bottom() );
lb_dirs.set_size( width / 2, height - lb_dirs.top() - btn_cancel.height() - 10 );
lbl_files.set_pos( lb_dirs.right(), btn_root.bottom() + 5 );
lb_files.set_pos( lb_dirs.right(), lbl_files.bottom() );
lb_files.set_size( width - lb_files.left(), height - lb_files.top() - btn_cancel.height() - 10 );
btn_ok.set_pos( width - btn_ok.width() - 25, lb_files.bottom() + 5 );
btn_cancel.set_pos( btn_ok.left() - btn_cancel.width() - 5, lb_files.bottom() + 5 );
}
else
{
lbl_dirs.set_pos( 0, btn_root.bottom() + 5 );
lb_dirs.set_pos( 0, lbl_dirs.bottom() );
lb_dirs.set_size( width / 2, height - lb_dirs.top() - btn_cancel.height() - 10 - tf_file_name.height() );
lbl_files.set_pos( lb_dirs.right(), btn_root.bottom() + 5 );
lb_files.set_pos( lb_dirs.right(), lbl_files.bottom() );
lb_files.set_size( width - lb_files.left(), height - lb_files.top() - btn_cancel.height() - 10 - tf_file_name.height() );
lbl_file_name.set_pos( lb_files.left(), lb_files.bottom() + 8 );
tf_file_name.set_pos( lbl_file_name.right(), lb_files.bottom() + 5 );
tf_file_name.set_width( width - tf_file_name.left() - 5 );
btn_ok.set_pos( width - btn_ok.width() - 25, tf_file_name.bottom() + 5 );
btn_cancel.set_pos( btn_ok.left() - btn_cancel.width() - 5, tf_file_name.bottom() + 5 );
}
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_window_resized(
)
{
set_sizes();
}
// ------------------------------------------------------------------------------------
void OpenFile::
deleter_thread(
)
{
close_window();
delete this;
}
// ------------------------------------------------------------------------------------
void OpenFile::
enter_folder(
const std::string& folder_name
)
{
if ( btn_root.is_checked() )
btn_root.set_unchecked();
if ( cur_dir != -1 )
sob[cur_dir]->set_unchecked();
const std::string old_path = path;
const long old_cur_dir = cur_dir;
scoped_ptr<toggle_button> new_btn( new toggle_button( *this ) );
new_btn->set_name( folder_name );
TBtStyle tBtStyle;
new_btn->set_style(tBtStyle);
new_btn->set_click_handler( *this, &OpenFile::on_path_button_click );
// remove any path buttons that won't be part of the path anymore
if ( sob.size() )
{
while ( sob.size() > ( unsigned long )( cur_dir + 1 ) )
{
scoped_ptr<toggle_button> junk;
sob.remove( cur_dir + 1, junk );
}
}
if ( sob.size() )
new_btn->set_pos( sob[sob.size()-1]->right() + 5, sob[sob.size()-1]->top() );
else
new_btn->set_pos( btn_root.right() + 5, btn_root.top() );
cur_dir = sob.size();
sob.add( sob.size(), new_btn );
path += folder_name + directory::get_separator();
if ( set_dir( prefix + path ) == false )
{
sob.remove( sob.size() - 1, new_btn );
path = old_path;
cur_dir = old_cur_dir;
}
else
{
sob[cur_dir]->set_checked();
}
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_dirs_click(
unsigned long idx
)
{
enter_folder( lb_dirs[idx] );
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_files_click(
unsigned long idx
)
{
if ( tf_file_name.is_hidden() == false )
{
tf_file_name.set_text( lb_files[idx] );
}
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_files_double_click(
unsigned long
)
{
on_open_click();
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_cancel_click(
)
{
hide();
create_new_thread<OpenFile, &OpenFile::deleter_thread>( *this );
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_open_click(
)
{
if ( lb_files.get_selected() != lb_files.size() || tf_file_name.text().size() > 0 )
{
if ( event_handler.is_set() )
{
if ( tf_file_name.is_hidden() )
event_handler( prefix + path + lb_files[lb_files.get_selected()] );
else if ( tf_file_name.text().size() > 0 )
event_handler( prefix + path + tf_file_name.text() );
}
if ( tf_file_name.is_hidden() )
result = prefix + path + lb_files[lb_files.get_selected()];
else if ( tf_file_name.text().size() > 0 )
result = prefix + path + tf_file_name.text();
hide();
create_new_thread<OpenFile, &OpenFile::deleter_thread>( *this );
}
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_path_button_click(
toggle_button& btn
)
{
if ( btn_root.is_checked() )
btn_root.set_unchecked();
if ( cur_dir != -1 )
sob[cur_dir]->set_unchecked();
std::string new_path;
for ( unsigned long i = 0; i < sob.size(); ++i )
{
new_path += sob[i]->name() + directory::get_separator();
if ( sob[i].get() == &btn )
{
cur_dir = i;
sob[i]->set_checked();
break;
}
}
if ( path != new_path )
{
path = new_path;
set_dir( prefix + path );
}
}
// ------------------------------------------------------------------------------------
struct case_insensitive_compare
{
bool operator()(
const std::string& a,
const std::string& b
) const
{
std::string::size_type i, size;
size = std::min( a.size(), b.size() );
for ( i = 0; i < size; ++i )
{
if ( std::tolower( a[i] ) < std::tolower( b[i] ) )
return true;
else if ( std::tolower( a[i] ) > std::tolower( b[i] ) )
return false;
}
if ( a.size() < b.size() )
return true;
else
return false;
}
};
// ------------------------------------------------------------------------------------
bool OpenFile::
set_dir(
const std::string& dir
)
{
try
{
directory d( dir );
dlib::queue<directory>::kernel_1a_c qod;
dlib::queue<file>::kernel_1a_c qof;
dlib::queue<std::string>::sort_1a_c qos;
d.get_dirs( qod );
d.get_files( qof );
qod.reset();
while ( qod.move_next() )
{
std::string temp = qod.element().name();
qos.enqueue( temp );
}
qos.sort( case_insensitive_compare() );
lb_dirs.load( qos );
qos.clear();
qof.reset();
while ( qof.move_next() )
{
std::string temp = qof.element().name();
qos.enqueue( temp );
}
qos.sort( case_insensitive_compare() );
lb_files.load( qos );
return true;
}
catch ( directory::listing_error& )
{
return false;
}
catch ( directory::dir_not_found& )
{
return false;
}
}
// ------------------------------------------------------------------------------------
void OpenFile::
on_root_click(
)
{
btn_root.set_checked();
if ( cur_dir != -1 )
sob[cur_dir]->set_unchecked();
dlib::queue<directory>::kernel_1a_c qod, qod2;
dlib::queue<file>::kernel_1a_c qof;
dlib::queue<std::string>::sort_1a_c qos;
get_filesystem_roots( qod );
path.clear();
cur_dir = -1;
if ( qod.size() == 1 )
{
qod.current().get_files( qof );
qod.current().get_dirs( qod2 );
prefix = qod.current().full_name();
qod2.reset();
while ( qod2.move_next() )
{
std::string temp = qod2.element().name();
qos.enqueue( temp );
}
qos.sort( case_insensitive_compare() );
lb_dirs.load( qos );
qos.clear();
qof.reset();
while ( qof.move_next() )
{
std::string temp = qof.element().name();
qos.enqueue( temp );
}
qos.sort( case_insensitive_compare() );
lb_files.load( qos );
}
else
{
prefix.clear();
qod.reset();
while ( qod.move_next() )
{
std::string temp = qod.element().full_name();
temp = temp.substr( 0, temp.size() - 1 );
qos.enqueue( temp );
}
qos.sort( case_insensitive_compare() );
lb_dirs.load( qos );
qos.clear();
lb_files.load( qos );
}
}
// ------------------------------------------------------------------------------------
base_window::on_close_return_code OpenFile::
on_window_close(
)
{
delete this;
return CLOSE_WINDOW;
}
}