Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "global.hpp"
00017
00018 #define GETTEXT_DOMAIN "wesnoth-lib"
00019
00020 #include "filesystem.hpp"
00021 #include "marked-up_text.hpp"
00022 #include "wml_separators.hpp"
00023 #include "widgets/file_menu.hpp"
00024
00025
00026 namespace {
00027 std::vector<std::string> empty_string_vector;
00028 }
00029
00030 namespace gui {
00031
00032 static const std::string dir_picture("misc/folder-icon.png");
00033 static const std::string path_up("..");
00034 const char file_menu::path_delim('/');
00035
00036 file_menu::file_menu(CVideo &disp, std::string start_file)
00037 : menu(disp, empty_string_vector, false),
00038 current_dir_(get_path(start_file)),
00039 chosen_file_(start_file), last_selection_(-1),
00040 type_a_head_(-1)
00041 {
00042
00043 if((!file_exists(chosen_file_) && !::is_directory(chosen_file_))
00044 || !::is_directory(current_dir_)) {
00045 current_dir_ = path_delim;
00046 chosen_file_ = current_dir_;
00047 }
00048
00049
00050
00051
00052
00053 update_file_lists();
00054 }
00055
00056 void file_menu::display_current_files() {
00057 std::vector<std::string> to_show;
00058 if (!is_root(current_dir_)) {
00059 to_show.push_back(path_up);
00060 }
00061 std::vector<std::string>::iterator it;
00062 for (it = dirs_in_current_dir_.begin(); it != dirs_in_current_dir_.end(); ++it) {
00063
00064 std::stringstream ss;
00065 ss << font::IMAGE << dir_picture << COLUMN_SEPARATOR << *it;
00066 to_show.push_back(ss.str());
00067 }
00068 for (it = files_in_current_dir_.begin(); it != files_in_current_dir_.end(); ++it) {
00069 const std::string display_string = COLUMN_SEPARATOR + *it;
00070 to_show.push_back(display_string);
00071 }
00072 const int menu_font_size = font::SIZE_NORMAL;
00073 for (it = to_show.begin(); it != to_show.end(); ++it) {
00074
00075
00076
00077 while(static_cast<unsigned int>(
00078 font::line_width(*it, menu_font_size)) > width() - 30 - 25) {
00079
00080 (*it).resize((*it).size() - 1);
00081 }
00082 }
00083 set_items(to_show);
00084 }
00085
00086 int file_menu::delete_chosen_file() {
00087 const int ret = remove(chosen_file_.c_str());
00088 if (ret == -1) {
00089
00090 }
00091 else {
00092 last_selection_ = -1;
00093 update_file_lists();
00094 chosen_file_ = current_dir_;
00095 }
00096 return ret;
00097 }
00098
00099 bool file_menu::make_directory(const std::string& subdir_name) {
00100 bool ret = ::make_directory(add_path(current_dir_, subdir_name));
00101 if (ret == false) {
00102
00103 }
00104 else {
00105 last_selection_ = -1;
00106 update_file_lists();
00107 chosen_file_ = current_dir_;
00108 }
00109 return ret;
00110 }
00111
00112 void file_menu::handle_event(const SDL_Event& event) {
00113 menu::handle_event(event);
00114
00115 if(selection() != last_selection_
00116 && !type_a_head()) {
00117 type_a_head_ = -1;
00118 entry_selected(selection());
00119 last_selection_ = selection();
00120 }
00121 }
00122
00123 void file_menu::entry_selected(const unsigned entry) {
00124 const int entry_index = entry - (is_root(current_dir_) ? 0 : 1);
00125 if (entry_index >= 0) {
00126 std::string selected;
00127 if(static_cast<unsigned>(entry_index) < dirs_in_current_dir_.size()) {
00128 const int dir_index = entry_index;
00129 selected = dirs_in_current_dir_[dir_index];
00130 }
00131 else {
00132 const int file_index = entry_index - dirs_in_current_dir_.size();
00133 if(file_index >= 0 && size_t(file_index) < files_in_current_dir_.size()) {
00134 selected = files_in_current_dir_[file_index];
00135 } else {
00136 return;
00137 }
00138 }
00139 chosen_file_ = add_path(current_dir_, selected);
00140 } else {
00141 chosen_file_ = path_up;
00142 }
00143 }
00144
00145 bool file_menu::is_directory(const std::string& fname) const {
00146 if(fname == path_up)
00147 return true;
00148 return ::is_directory(fname);
00149 }
00150
00151 void file_menu::change_directory(const std::string& path) {
00152 if(path == path_up)
00153 {
00154
00155 if (!is_root(current_dir_)) {
00156 current_dir_ = get_path_up(current_dir_);
00157 last_selection_ = -1;
00158 update_file_lists();
00159 chosen_file_ = current_dir_;
00160 }
00161 else {
00162 return;
00163 }
00164
00165 } else {
00166 current_dir_ = path;
00167 chosen_file_ = current_dir_;
00168 last_selection_ = -1;
00169 update_file_lists();
00170 }
00171 }
00172
00173 std::string file_menu::get_choice() const {
00174 return chosen_file_;
00175 }
00176
00177
00178 std::string file_menu::get_path(const std::string& file_or_dir) const {
00179 std::string res_path = file_or_dir;
00180 if (!::is_directory(file_or_dir)) {
00181 size_t index = file_or_dir.find_last_of(path_delim);
00182 if (index != std::string::npos) {
00183 res_path = file_or_dir.substr(0, index);
00184 }
00185 }
00186 return res_path;
00187 }
00188
00189 std::string file_menu::get_path_up(const std::string& path, const unsigned levels) const {
00190 std::string curr_path = get_path(path);
00191 for (unsigned i = 0; i < levels; i++) {
00192 if (is_root(curr_path)) {
00193 break;
00194 }
00195 curr_path = strip_last_delim(curr_path);
00196 size_t index = curr_path.find_last_of(path_delim);
00197 if (index != std::string::npos) {
00198 curr_path = curr_path.substr(0, index);
00199 }
00200 else {
00201 #ifdef __AMIGAOS4__
00202 index = curr_path.find_last_of(':');
00203 if (index != std::string::npos) index++;
00204 #endif
00205 break;
00206 }
00207 }
00208 if (curr_path.empty()) {
00209
00210 curr_path = path_delim;
00211 }
00212 #ifdef _WIN32
00213 if (curr_path.size() == 2 && curr_path[1] == ':') curr_path += path_delim;
00214 #endif
00215 return curr_path;
00216 }
00217
00218 std::string file_menu::strip_last_delim(const std::string& path) const {
00219 std::string res_string = path;
00220 if (path[path.size() - 1] == path_delim) {
00221 res_string = path.substr(0, path.size() - 1);
00222 }
00223 return res_string;
00224 }
00225
00226 bool file_menu::is_root(const std::string& path) const {
00227 #ifdef __AMIGAOS4__
00228 return path.empty() || path[path.size()-1] == ':';
00229 #else
00230 return path.empty() || (path.size() == 1 && path[0] == path_delim);
00231 #endif
00232 }
00233
00234 std::string file_menu::add_path(const std::string& path, const std::string& to_add) const
00235 {
00236 std::string joined_path = strip_last_delim(path);
00237 if (!to_add.empty()) {
00238 if (to_add == path_up) {
00239 return get_path_up(path);
00240 }
00241 #ifdef __AMIGAOS4__
00242 else if (joined_path.empty() || joined_path[joined_path.size()-1] == ':') {
00243 if (to_add[0] == path_delim)
00244 joined_path += to_add.substr(1);
00245 else
00246 joined_path += to_add;
00247 }
00248 #endif
00249 #ifdef _WIN32
00250 else if (to_add.size() > 1 && to_add[1] == ':') {
00251 joined_path = to_add;
00252 }
00253 #else
00254 else if (to_add[0] == path_delim) {
00255 joined_path = to_add;
00256 }
00257 #endif
00258 else {
00259 joined_path += "/" + to_add;
00260 }
00261 }
00262 return joined_path;
00263 }
00264
00265 struct match_begin {
00266 match_begin(const std::string& begin) : begin_(begin)
00267 {}
00268
00269 bool operator()(const std::string& o) const
00270 {
00271 return o.compare(0, begin_.size(), begin_) == 0;
00272 }
00273
00274 private:
00275 const std::string& begin_;
00276 };
00277
00278 bool file_menu::type_a_head() const
00279 {
00280 return selection() == type_a_head_;
00281 }
00282
00283 void file_menu::reset_type_a_head()
00284 {
00285 if (type_a_head_ >= 0)
00286 {
00287 entry_selected(type_a_head_);
00288 last_selection_ = type_a_head_;
00289 }
00290 type_a_head_ = -1;
00291 }
00292
00293 void file_menu::select_file(const std::string& begin_of_filename)
00294 {
00295 size_t additional_index = is_root(current_dir_) ? 0 : 1;
00296 std::vector<std::string>::iterator it;
00297 it = std::find_if(dirs_in_current_dir_.begin(), dirs_in_current_dir_.end(), match_begin(begin_of_filename));
00298 if (it != dirs_in_current_dir_.end())
00299 {
00300 type_a_head_ = additional_index + it - dirs_in_current_dir_.begin();
00301 move_selection(type_a_head_);
00302 return;
00303 }
00304 additional_index += dirs_in_current_dir_.size();
00305
00306 it = std::find_if(files_in_current_dir_.begin(), files_in_current_dir_.end(), match_begin(begin_of_filename));
00307 if (it != files_in_current_dir_.end())
00308 {
00309 type_a_head_ = it - files_in_current_dir_.begin() + additional_index;
00310 move_selection(type_a_head_);
00311 return;
00312 }
00313 }
00314
00315 void file_menu::update_file_lists() {
00316 files_in_current_dir_.clear();
00317 dirs_in_current_dir_.clear();
00318 get_files_in_dir(current_dir_, &files_in_current_dir_,
00319 &dirs_in_current_dir_, FILE_NAME_ONLY);
00320 display_current_files();
00321 }
00322
00323 }