text: #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;
  }
  
  }
  
  
  
  
  
  
  
  