file_menu.cpp

Go to the documentation of this file.
00001 /* $Id: file_menu.cpp 24836 2008-03-19 16:07:56Z brunowolff $ */
00002 /*
00003    Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 #include "global.hpp"
00016 
00017 #define GETTEXT_DOMAIN "wesnoth-lib"
00018 
00019 #include "display.hpp"
00020 #include "events.hpp"
00021 #include "filesystem.hpp"
00022 #include "gettext.hpp"
00023 #include "key.hpp"
00024 #include "marked-up_text.hpp"
00025 #include "show_dialog.hpp"
00026 #include "wml_separators.hpp"
00027 #include "widgets/file_menu.hpp"
00028 
00029 #include <sstream>
00030 #include <cstdio>
00031 
00032 namespace {
00033     std::vector<std::string> empty_string_vector;
00034 }
00035 
00036 namespace gui {
00037 
00038 static const std::string dir_picture("misc/folder-icon.png");
00039 static const std::string path_up("..");
00040 const char file_menu::path_delim('/');
00041 
00042 file_menu::file_menu(CVideo &disp, std::string start_file)
00043     : menu(disp, empty_string_vector, false),
00044       current_dir_(get_path(start_file)),
00045       chosen_file_(start_file), last_selection_(-1)
00046 {
00047     // If the start file is not a file or directory, use the root.
00048     if((!file_exists(chosen_file_) && !::is_directory(chosen_file_))
00049         || !::is_directory(current_dir_)) {
00050         current_dir_ = path_delim;
00051         chosen_file_ = current_dir_;
00052     }
00053     // FIXME: quick hack
00054     // on a high-res screen the initial max_items_onscreen is based
00055     // on .66 of y dimension, eg. 17 menu items, exceeding the
00056     // starting box which can only take 13 or so: force it to be smaller
00057 //  set_measurements(400, 384);
00058     update_file_lists();
00059 }
00060 
00061 void file_menu::display_current_files() {
00062     std::vector<std::string> to_show;
00063     if (!is_root(current_dir_)) {
00064         to_show.push_back(path_up);
00065     }
00066     std::vector<std::string>::iterator it;
00067     for (it = dirs_in_current_dir_.begin(); it != dirs_in_current_dir_.end(); it++) {
00068         // Add an image to show that these are directories.
00069         std::stringstream ss;
00070         ss << font::IMAGE << dir_picture << COLUMN_SEPARATOR << *it;
00071         to_show.push_back(ss.str());
00072     }
00073     for (it = files_in_current_dir_.begin(); it != files_in_current_dir_.end(); it++) {
00074         const std::string display_string = COLUMN_SEPARATOR + *it;
00075         to_show.push_back(display_string);
00076     }
00077     const int menu_font_size = font::SIZE_NORMAL; // Known from menu.cpp.
00078     for (it = to_show.begin(); it != to_show.end(); it++) {
00079         // Make sure that all lines fit.
00080         // Guess the width of the scrollbar to be 30 since it is not accessible from here.
00081         // -25 to compensate for the picture column.
00082         while(static_cast<unsigned int>(
00083                 font::line_width(*it, menu_font_size)) > width() - 30 - 25) {
00084 
00085             (*it).resize((*it).size() - 1);
00086         }
00087     }
00088     set_items(to_show);
00089 }
00090 
00091 int file_menu::delete_chosen_file() {
00092     const int ret = remove(chosen_file_.c_str());
00093     if (ret == -1) {
00094     //  gui::message_dialog(disp_, "", _("Deletion of the file failed.")).show();
00095     }
00096     else {
00097         last_selection_ = -1;
00098         update_file_lists();
00099         chosen_file_ = current_dir_;
00100     }
00101     return ret;
00102 }
00103 
00104 bool file_menu::make_directory(const std::string& subdir_name) {
00105     bool ret = ::make_directory(add_path(current_dir_, subdir_name));
00106     if (ret == false) {
00107     //  gui::message_dialog(disp_, "", _("Creation of the directory failed.")).show();
00108     }
00109     else {
00110         last_selection_ = -1;
00111         update_file_lists();
00112         chosen_file_ = current_dir_;
00113     }
00114     return ret;
00115 }
00116 
00117 void file_menu::handle_event(const SDL_Event& event) {
00118     menu::handle_event(event);
00119     if(selection() != last_selection_) {
00120         entry_selected(selection());
00121         last_selection_ = selection();
00122     }
00123 }
00124 
00125 void file_menu::entry_selected(const unsigned entry) {
00126     const int entry_index = entry - (is_root(current_dir_) ? 0 : 1);
00127     if (entry_index >= 0) {
00128         std::string selected;
00129         if(static_cast<unsigned>(entry_index) < dirs_in_current_dir_.size()) {
00130             const int dir_index = entry_index;
00131             selected = dirs_in_current_dir_[dir_index];
00132         }
00133         else {
00134             const int file_index = entry_index - dirs_in_current_dir_.size();
00135             if(file_index >= 0 && size_t(file_index) < files_in_current_dir_.size()) {
00136                 selected = files_in_current_dir_[file_index];
00137             } else {
00138                 return;
00139             }
00140         }
00141         chosen_file_ = add_path(current_dir_, selected);
00142     } else {
00143         chosen_file_ = path_up;
00144     }
00145 }
00146 
00147 bool file_menu::is_directory(const std::string& fname) const {
00148     if(fname == path_up)
00149         return true;
00150     return ::is_directory(fname);
00151 }
00152 
00153 void file_menu::change_directory(const std::string path) {
00154     if(path == path_up)
00155     {
00156         // Parent dir wanted.
00157         if (!is_root(current_dir_)) {
00158             current_dir_ = get_path_up(current_dir_);
00159             last_selection_ = -1;
00160             update_file_lists();
00161             chosen_file_ = current_dir_;
00162         }
00163         else {
00164             return;
00165         }
00166 
00167     } else {
00168         current_dir_ = path;
00169         chosen_file_ = current_dir_;
00170         last_selection_ = -1;
00171         update_file_lists();
00172     }
00173 }
00174 
00175 std::string file_menu::get_choice() const {
00176     return chosen_file_;
00177 }
00178 
00179 
00180 std::string file_menu::get_path(const std::string file_or_dir) const {
00181     std::string res_path = file_or_dir;
00182     if (!::is_directory(file_or_dir)) {
00183         size_t index = file_or_dir.find_last_of(path_delim);
00184         if (index != std::string::npos) {
00185             res_path = file_or_dir.substr(0, index);
00186         }
00187     }
00188     return res_path;
00189 }
00190 
00191 std::string file_menu::get_path_up(const std::string path, const unsigned levels) const {
00192     std::string curr_path = get_path(path);
00193     for (unsigned i = 0; i < levels; i++) {
00194         if (is_root(curr_path)) {
00195             break;
00196         }
00197         curr_path = strip_last_delim(curr_path);
00198         size_t index = curr_path.find_last_of(path_delim);
00199         if (index != std::string::npos) {
00200             curr_path = curr_path.substr(0, index);
00201         }
00202         else {
00203 #ifdef __AMIGAOS4__
00204             index = curr_path.find_last_of(':');
00205             if (index != std::string::npos) index++;
00206 #endif
00207             break;
00208         }
00209     }
00210     if (curr_path.size() == 0) {
00211         // The root was reached, represent this as one delimiter only.
00212         curr_path = path_delim;
00213     }
00214     return curr_path;
00215 }
00216 
00217 std::string file_menu::strip_last_delim(const std::string path) const {
00218     std::string res_string = path;
00219     if (path[path.size() - 1] == path_delim) {
00220         res_string = path.substr(0, path.size() - 1);
00221     }
00222     return res_string;
00223 }
00224 
00225 bool file_menu::is_root(const std::string path) const {
00226 #ifdef __AMIGAOS4__
00227     return path.size() == 0 || path[path.size()-1] == ':';
00228 #else
00229     return path.size() == 0 || (path.size() == 1 && path[0] == path_delim);
00230 #endif
00231 }
00232 
00233 std::string file_menu::add_path(const std::string path, const std::string to_add) const
00234 {
00235     std::string joined_path = strip_last_delim(path);
00236     if (to_add.size() > 0) {
00237         if (to_add == path_up) {
00238             return get_path_up(path);
00239         }
00240 #ifdef __AMIGAOS4__
00241         else if (joined_path.empty() || joined_path[joined_path.size()-1] == ':') {
00242             if (to_add[0] == path_delim)
00243                 joined_path += to_add.substr(1);
00244             else
00245                 joined_path += to_add;
00246         }
00247 #endif
00248         else if (to_add[0] == path_delim) {
00249             joined_path += to_add;
00250         }
00251         else {
00252             joined_path += "/" + to_add;
00253         }
00254     }
00255     return joined_path;
00256 }
00257 
00258 void file_menu::update_file_lists() {
00259     files_in_current_dir_.clear();
00260     dirs_in_current_dir_.clear();
00261     get_files_in_dir(current_dir_, &files_in_current_dir_,
00262                      &dirs_in_current_dir_, FILE_NAME_ONLY);
00263     display_current_files();
00264 }
00265 
00266 }

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs