filechooser.cpp

Go to the documentation of this file.
00001 /* $Id: filechooser.cpp 23842 2008-02-16 08:47:16Z mordante $ */
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 "gettext.hpp"
00021 #include "file_chooser.hpp"
00022 #include "video.hpp"
00023 #include "widgets/file_menu.hpp"
00024 #include "filesystem.hpp"
00025 
00026 #include <vector>
00027 #include <string>
00028 
00029 namespace dialogs
00030 {
00031 
00032 int show_file_chooser_dialog(display &disp, std::string &filename,
00033                              std::string const &title, int xloc, int yloc) {
00034 
00035     file_dialog d(disp, filename, title);
00036     if(d.show(xloc, yloc) >= 0) {
00037         filename = d.get_choice();
00038     }
00039     return d.result();
00040 }
00041 
00042 file_dialog::file_dialog(display &disp, const std::string& file_path, const std::string& title)
00043 : gui::dialog(disp, title, file_path, gui::OK_CANCEL), files_list_(NULL), last_selection_(0)
00044 {
00045     files_list_ = new gui::file_menu(disp.video(), file_path);
00046     const unsigned file_list_height = (disp.h() / 2);
00047     const unsigned file_list_width = minimum<unsigned>(files_list_->width(), (disp.w() / 4));
00048     files_list_->set_measurements(file_list_width, file_list_height);
00049     files_list_->set_max_height(file_list_height);
00050     set_menu(files_list_);
00051     get_message().set_text(format_dirname(files_list_->get_directory()));
00052     set_textbox(_("File: "), format_filename(file_path), 100);
00053     add_button( new gui::dialog_button(disp.video(), _("Delete File"),
00054         gui::button::TYPE_PRESS, gui::DELETE_ITEM), dialog::BUTTON_EXTRA);
00055     add_button( new gui::dialog_button(disp.video(), _("New Folder"),
00056         gui::button::TYPE_PRESS, gui::CREATE_ITEM), dialog::BUTTON_EXTRA_LEFT);
00057 }
00058 
00059 gui::dialog::dimension_measurements file_dialog::layout(int xloc, int yloc)
00060 {
00061     gui::dialog::dimension_measurements dim = dialog::layout(xloc, yloc);
00062 
00063     //shift the menu up
00064     unsigned y_shift = dim.menu_y - minimum<int>(dim.label_y, dim.textbox.y);
00065     int y_max = dim.menu_y + get_menu().height();
00066     dim.menu_y -= y_shift;
00067 
00068     //shift the extra buttons up
00069     std::map<gui::dialog_button *const, std::pair<int,int> >::iterator i;
00070     for(i = dim.buttons.begin(); i != dim.buttons.end(); ++i)
00071     {
00072         const int btn_h = i->first->height();
00073         int& btn_y = i->second.second;
00074         y_max = maximum<int>(y_max, btn_y + btn_h);
00075         btn_y -= y_shift;
00076     }
00077 
00078     //shift the textbox down
00079     const int textbox_bottom_y = dim.textbox.y + get_textbox().height();
00080     const int label_bottom_y = dim.label_y + get_textbox().get_label()->height();
00081     y_shift = y_max - maximum<int>(textbox_bottom_y, label_bottom_y);
00082     dim.textbox.y += y_shift;
00083     dim.label_y += y_shift;
00084 
00085     set_layout(dim);
00086     return dim;
00087 }
00088 
00089 const std::string file_dialog::unformat_filename(const std::string& filename) const
00090 {
00091     return files_list_->add_path(files_list_->get_directory(), filename);
00092 }
00093 
00094 const std::string file_dialog::format_filename(const std::string& filename) const
00095 {
00096     if(files_list_->is_directory(filename)) {
00097         return "";
00098     }
00099     std::string::size_type last_delim = filename.find_last_of(gui::file_menu::path_delim);
00100     if(last_delim != std::string::npos) {
00101         return filename.substr(last_delim + 1);
00102     }
00103     return filename;
00104 }
00105 
00106 const std::string file_dialog::format_dirname(const std::string& dirname) const
00107 {
00108     int menu_font_size = font::SIZE_NORMAL;
00109     std::string tmp = files_list_->strip_last_delim(dirname);
00110 
00111     // If the text get out of bounds, make it shorter;
00112     // Take the prefix of the dir (ie. /home/ or c:/) put three dot's behind it
00113     // and shorten the rest of the dir:
00114     // /home/.../rest_of_the_dir
00115     // Note that this is a dirty hack and fundemental changes in the widget subdir
00116     // needs to be made...
00117     if(font::line_width(tmp, menu_font_size) <= 390) {
00118         return tmp;
00119     }
00120     static const int filler_width = font::line_width("...", menu_font_size);
00121 
00122     // Find the first part of the dir
00123     std::string dir_prefix = "";
00124     std::string::size_type pos_first = 0;
00125     if((pos_first = tmp.find_first_of("\\/", 1)) != std::string::npos)
00126     {
00127         dir_prefix = tmp.substr(0, pos_first) + "/...";
00128         tmp = tmp.substr(pos_first);
00129     }
00130 
00131     static const int prefix_width = font::line_width(dir_prefix, menu_font_size);
00132 
00133     // Try to cut off text at the '/' or '\' tokens
00134     while(font::line_width(tmp, menu_font_size) + filler_width + prefix_width > 390 && tmp.length() != 0)
00135     {
00136         std::string::size_type pos;
00137         if((pos = tmp.find_first_of("\\/", 1)) != std::string::npos)
00138             tmp = tmp.substr(pos, tmp.length());
00139         else
00140             tmp = tmp.substr(1, tmp.length());
00141     }
00142 
00143     return dir_prefix + tmp;
00144 }
00145 
00146 
00147 void file_dialog::action(gui::dialog_process_info &dp_info) {
00148     if(result() == gui::CLOSE_DIALOG)
00149         return;
00150 
00151     //handle "delete item" requests
00152     if(result() == gui::DELETE_ITEM)
00153     {
00154         if(!chosen_file_.empty())
00155         {
00156             if(files_list_->delete_chosen_file() == -1) {
00157                 gui::message_dialog d(get_display(), _("Deletion of the file failed."));
00158                 d.show();
00159                 dp_info.clear_buttons();
00160             } else {
00161                 dp_info.first_time = true;
00162             }
00163         }
00164         set_result(gui::CONTINUE_DIALOG);
00165     }
00166     //handle "create item" requests
00167     else if(result() == gui::CREATE_ITEM)
00168     {
00169         gui::dialog d(get_display(), _("New Folder"), "", gui::OK_CANCEL);
00170         d.set_textbox(_("Name: "));
00171         d.show();
00172         if(d.result() != gui::CLOSE_DIALOG && !d.textbox_text().empty())
00173         {
00174             if( !files_list_->make_directory(d.textbox_text()) ) {
00175                 gui::message_dialog d2(get_display(), _("Creation of the directory failed."));
00176                 d2.show();
00177             } else {
00178                 dp_info.first_time = true;
00179             }
00180         }
00181         dp_info.clear_buttons();
00182         set_result(gui::CONTINUE_DIALOG);
00183     }
00184 
00185     //update the chosen file
00186     if(dp_info.selection != last_selection_
00187         || dp_info.first_time
00188         || dp_info.double_clicked)
00189     {
00190         chosen_file_ = files_list_->get_choice();
00191         get_textbox().set_text(format_filename(chosen_file_));
00192         last_selection_ = (dp_info.double_clicked) ? -1 : dp_info.selection;
00193     }
00194     else if(textbox_text() != last_textbox_text_)
00195     {
00196         chosen_file_ = unformat_filename(textbox_text());
00197         last_textbox_text_ = textbox_text();
00198     }
00199 
00200     if(result() >=0) {
00201         //if a directory has been chosen, enter it
00202         if(files_list_->is_directory(chosen_file_))
00203         {
00204             files_list_->change_directory(chosen_file_);
00205             get_message().set_text(format_dirname(files_list_->get_directory()));
00206 
00207             //reset the chosen file
00208             chosen_file_ = files_list_->get_choice();
00209             get_textbox().set_text(format_filename(chosen_file_));
00210             set_result(gui::CONTINUE_DIALOG);
00211         }
00212         //if a file has been chosen, return button index "Ok"
00213         else
00214         {
00215             set_result(0);
00216         }
00217     }
00218 }
00219 
00220 } //end namespace dialogs

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