filechooser.cpp

Go to the documentation of this file.
00001 /* $Id: filechooser.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 - 2012 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 as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "global.hpp"
00017 
00018 #define GETTEXT_DOMAIN "wesnoth-lib"
00019 
00020 #include "display.hpp"
00021 #include "gettext.hpp"
00022 #include "gui/dialogs/folder_create.hpp"
00023 #include "gui/dialogs/transient_message.hpp"
00024 #include "filechooser.hpp"
00025 #include "widgets/file_menu.hpp"
00026 
00027 
00028 namespace dialogs
00029 {
00030 
00031 int show_file_chooser_dialog(display &disp, std::string &filename,
00032                              std::string const &title, bool show_directory_buttons,
00033                              const std::string& type_a_head,
00034                              int xloc, int yloc) {
00035 
00036     file_dialog d(disp, filename, title, show_directory_buttons);
00037     if (!type_a_head.empty())
00038         d.select_file(type_a_head);
00039     if(d.show(xloc, yloc) >= 0) {
00040         filename = d.get_choice();
00041     }
00042     return d.result();
00043 }
00044 
00045 int show_file_chooser_dialog_save(display &disp, std::string &filename,
00046                              std::string const &title, bool show_directory_buttons,
00047                              const std::string& type_a_head,
00048                              int xloc, int yloc) {
00049 
00050     file_dialog d(disp, filename, title, show_directory_buttons);
00051     d.set_autocomplete(false);
00052     if (!type_a_head.empty())
00053         d.select_file(type_a_head);
00054     if(d.show(xloc, yloc) >= 0) {
00055         filename = d.get_choice();
00056     }
00057     return d.result();
00058 }
00059 
00060 file_dialog::file_dialog(display &disp, const std::string& file_path,
00061         const std::string& title, bool show_directory_buttons) :
00062     gui::dialog(disp, title, file_path, gui::OK_CANCEL),
00063     show_directory_buttons_(show_directory_buttons),
00064     files_list_(NULL),
00065     last_selection_(-1),
00066     last_textbox_text_(),
00067     chosen_file_(".."),
00068     autocomplete_(true)
00069 {
00070     files_list_ = new gui::file_menu(disp.video(), file_path);
00071     const unsigned file_list_height = (disp.h() / 2);
00072     const unsigned file_list_width = std::min<unsigned>(files_list_->width(), (disp.w() / 4));
00073     files_list_->set_measurements(file_list_width, file_list_height);
00074     files_list_->set_max_height(file_list_height);
00075     set_menu(files_list_);
00076     get_message().set_text(format_dirname(files_list_->get_directory()));
00077     set_textbox(_("File: "), format_filename(file_path), 100);
00078     if (show_directory_buttons_)
00079     {
00080         add_button( new gui::dialog_button(disp.video(), _("Delete File"),
00081                     gui::button::TYPE_PRESS, gui::DELETE_ITEM), dialog::BUTTON_EXTRA);
00082         add_button( new gui::dialog_button(disp.video(), _("New Folder"),
00083                     gui::button::TYPE_PRESS, gui::CREATE_ITEM), dialog::BUTTON_EXTRA_LEFT);
00084     }
00085 }
00086 
00087 gui::dialog::dimension_measurements file_dialog::layout(int xloc, int yloc)
00088 {
00089     gui::dialog::dimension_measurements dim = dialog::layout(xloc, yloc);
00090 
00091     //shift the menu up
00092     unsigned y_shift = dim.menu_y - std::min<int>(dim.label_y, dim.textbox.y);
00093     int y_max = dim.menu_y + get_menu().height();
00094     dim.menu_y -= y_shift;
00095 
00096     //shift the extra buttons up
00097     if (show_directory_buttons_)
00098     {
00099         std::map<gui::dialog_button *const, std::pair<int,int> >::iterator i;
00100         for(i = dim.buttons.begin(); i != dim.buttons.end(); ++i)
00101         {
00102             const int btn_h = i->first->height();
00103             int& btn_y = i->second.second;
00104             y_max = std::max<int>(y_max, btn_y + btn_h);
00105             btn_y -= y_shift;
00106         }
00107     }
00108 
00109     //shift the textbox down
00110     const int textbox_bottom_y = dim.textbox.y + get_textbox().height();
00111     const int label_bottom_y = dim.label_y + get_textbox().get_label()->height();
00112     y_shift = y_max - std::max<int>(textbox_bottom_y, label_bottom_y);
00113     dim.textbox.y += y_shift;
00114     dim.label_y += y_shift;
00115 
00116     set_layout(dim);
00117     return dim;
00118 }
00119 
00120 std::string file_dialog::unformat_filename(const std::string& filename) const
00121 {
00122     return files_list_->add_path(files_list_->get_directory(), filename);
00123 }
00124 
00125 std::string file_dialog::format_filename(const std::string& filename) const
00126 {
00127     if(files_list_->is_directory(filename)) {
00128         return "";
00129     }
00130     std::string::size_type last_delim = filename.find_last_of(gui::file_menu::path_delim);
00131     if(last_delim != std::string::npos) {
00132         return filename.substr(last_delim + 1);
00133     }
00134     return filename;
00135 }
00136 
00137 void file_dialog::select_file(const std::string& file)
00138 {
00139     chosen_file_ = file;
00140     get_textbox().set_text(format_filename(chosen_file_));
00141     files_list_->select_file(file);
00142 }
00143 
00144 std::string file_dialog::format_dirname(const std::string& dirname) const
00145 {
00146     int menu_font_size = font::SIZE_NORMAL;
00147     std::string tmp = files_list_->strip_last_delim(dirname);
00148 
00149     // If the text get out of bounds, make it shorter;
00150     // Take the prefix of the dir (ie. /home/ or c:/) put three dot's behind it
00151     // and shorten the rest of the dir:
00152     // /home/.../rest_of_the_dir
00153     // Note that this is a dirty hack and fundemental changes in the widget subdir
00154     // needs to be made...
00155     if(font::line_width(tmp, menu_font_size) <= 390) {
00156         return tmp;
00157     }
00158     static const int filler_width = font::line_width("...", menu_font_size);
00159 
00160     // Find the first part of the dir
00161     std::string dir_prefix = "/";
00162     std::string::size_type pos_first = 0;
00163     if((pos_first = tmp.find_first_of("\\/", 1)) != std::string::npos)
00164     {
00165         dir_prefix = tmp.substr(0, pos_first) + "/...";
00166         tmp = tmp.substr(pos_first);
00167     }
00168 
00169     static const int prefix_width = font::line_width(dir_prefix, menu_font_size);
00170 
00171     // Try to cut off text at the '/' or '\' tokens
00172     while(font::line_width(tmp, menu_font_size) + filler_width + prefix_width > 390 && tmp.length() != 0)
00173     {
00174         std::string::size_type pos;
00175         if((pos = tmp.find_first_of("\\/", 1)) != std::string::npos)
00176             tmp = tmp.substr(pos, tmp.length());
00177         else
00178             tmp = tmp.substr(1, tmp.length());
00179     }
00180 
00181     return dir_prefix + tmp;
00182 }
00183 
00184 
00185 void file_dialog::action(gui::dialog_process_info &dp_info) {
00186     if(result() == gui::CLOSE_DIALOG)
00187         return;
00188 
00189     //handle "delete item" requests
00190     if(result() == gui::DELETE_ITEM)
00191     {
00192         if(!chosen_file_.empty())
00193         {
00194             if(files_list_->delete_chosen_file() == -1) {
00195                 gui2::show_transient_error_message(get_display().video()
00196                         , _("Deletion of the file failed."));
00197                 dp_info.clear_buttons();
00198             } else {
00199                 dp_info.first_time = true;
00200             }
00201         }
00202         set_result(gui::CONTINUE_DIALOG);
00203     }
00204     //handle "create item" requests
00205     else if(result() == gui::CREATE_ITEM)
00206     {
00207         std::string new_dir_name = "";
00208         if(gui2::tfolder_create::execute(new_dir_name, get_display().video()))
00209         {
00210             if( !files_list_->make_directory(new_dir_name) ) {
00211                 gui2::show_transient_error_message(get_display().video()
00212                         , _("Creation of the directory failed."));
00213             } else {
00214                 dp_info.first_time = true;
00215             }
00216         }
00217         dp_info.clear_buttons();
00218         set_result(gui::CONTINUE_DIALOG);
00219     }
00220 
00221     //update the chosen file
00222     if((dp_info.selection != last_selection_
00223         || dp_info.first_time
00224         || dp_info.double_clicked)
00225             && (!files_list_->type_a_head()
00226                 || dp_info.new_left_button))
00227     {
00228         files_list_->reset_type_a_head();
00229 
00230         chosen_file_ = files_list_->get_choice();
00231         get_textbox().set_text(format_filename(chosen_file_));
00232         last_selection_ = (dp_info.double_clicked) ? -1 : dp_info.selection;
00233         last_textbox_text_ = textbox_text();
00234     }
00235     else if(textbox_text() != last_textbox_text_)
00236     {
00237         chosen_file_ = unformat_filename(textbox_text());
00238         last_textbox_text_ = textbox_text();
00239 
00240         // Do type-a-head search in listbox
00241         if (autocomplete_) {
00242             files_list_->select_file(textbox_text());
00243         }
00244     }
00245 
00246     if(result() >=0) {
00247         //if a directory has been chosen, enter it
00248         if(files_list_->is_directory(chosen_file_))
00249         {
00250             files_list_->change_directory(chosen_file_);
00251             get_message().set_text(format_dirname(files_list_->get_directory()));
00252 
00253             //reset the chosen file
00254             chosen_file_ = "..";
00255             get_textbox().set_text(format_filename(chosen_file_));
00256             set_result(gui::CONTINUE_DIALOG);
00257         }
00258         //if a file has been chosen, return button index "Ok"
00259         else
00260         {
00261             set_result(0);
00262         }
00263     }
00264 }
00265 
00266 } //end namespace dialogs
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:36 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs