The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
filechooser.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "global.hpp"
16 
17 #define GETTEXT_DOMAIN "wesnoth-lib"
18 
19 #include "video.hpp"
20 #include "gettext.hpp"
23 #include "filechooser.hpp"
24 #include "widgets/file_menu.hpp"
25 
26 
27 namespace dialogs
28 {
29 
31  std::string const &title, bool show_directory_buttons,
32  const std::string& type_a_head,
33  int xloc, int yloc) {
34 
35  file_dialog d(video, filename, title, "", show_directory_buttons);
36  if (!type_a_head.empty())
37  d.select_file(type_a_head);
38  if(d.show(xloc, yloc) >= 0) {
39  filename = d.get_choice();
40  }
41  return d.result();
42 }
43 
45  std::string const &title,
46  const std::string& default_file_name,
47  bool show_directory_buttons,
48  const std::string& type_a_head,
49  int xloc, int yloc) {
50 
51  file_dialog d(video, filename, title, default_file_name, show_directory_buttons);
52  d.set_autocomplete(false);
53  if (!type_a_head.empty())
54  d.select_file(type_a_head);
55  if(d.show(xloc, yloc) >= 0) {
56  filename = d.get_choice();
57  }
58  return d.result();
59 }
60 
61 file_dialog::file_dialog(CVideo& video, const std::string& file_path,
62  const std::string& title, const std::string& default_file_name,
63  bool show_directory_buttons) :
64  gui::dialog(video, title, file_path, gui::OK_CANCEL),
65  show_directory_buttons_(show_directory_buttons),
66  files_list_(nullptr),
67  last_selection_(-1),
68  last_textbox_text_(),
69  chosen_file_(".."),
70  autocomplete_(true)
71 {
72  files_list_ = new gui::file_menu(video, file_path);
73  const unsigned file_list_height = (video.gety() / 2);
74  const unsigned file_list_width = std::min<unsigned>(files_list_->width(), (video.gety() / 4));
75  files_list_->set_measurements(file_list_width, file_list_height);
76  files_list_->set_max_height(file_list_height);
78  default_file_name_ = default_file_name;
80  set_textbox(_("File: "), format_filename(file_path), 100);
82  {
83  add_button( new gui::dialog_button(video, _("Delete File"),
84  gui::button::TYPE_PRESS, gui::DELETE_ITEM), dialog::BUTTON_EXTRA);
85  add_button( new gui::dialog_button(video, _("New Folder"),
86  gui::button::TYPE_PRESS, gui::CREATE_ITEM), dialog::BUTTON_EXTRA_LEFT);
87  }
88 }
89 
91 {
92  gui::dialog::dimension_measurements dim = dialog::layout(xloc, yloc);
93 
94  //shift the menu up
95  unsigned y_shift = dim.menu_y - std::min<int>(dim.label_y, dim.textbox.y);
96  int y_max = dim.menu_y + get_menu().height();
97  dim.menu_y -= y_shift;
98 
99  //shift the extra buttons up
101  {
102  std::map<gui::dialog_button *, std::pair<int,int> >::iterator i;
103  for(i = dim.buttons.begin(); i != dim.buttons.end(); ++i)
104  {
105  const int btn_h = i->first->height();
106  int& btn_y = i->second.second;
107  y_max = std::max<int>(y_max, btn_y + btn_h);
108  btn_y -= y_shift;
109  }
110  }
111 
112  //shift the textbox down
113  const int textbox_bottom_y = dim.textbox.y + get_textbox().height();
114  const int label_bottom_y = dim.label_y + get_textbox().get_label()->height();
115  y_shift = y_max - std::max<int>(textbox_bottom_y, label_bottom_y);
116  dim.textbox.y += y_shift;
117  dim.label_y += y_shift;
118 
119  set_layout(dim);
120  return dim;
121 }
122 
124 {
125  return files_list_->add_path(files_list_->get_directory(), filename);
126 }
127 
129 {
130  if(files_list_->is_directory(filename)) {
131  return default_file_name_;
132  }
133  std::string::size_type last_delim = filename.find_last_of(gui::file_menu::path_delim);
134  if(last_delim != std::string::npos) {
135  return filename.substr(last_delim + 1);
136  }
137  return filename;
138 }
139 
141 {
142  chosen_file_ = file;
144  files_list_->select_file(file);
145 }
146 
148 {
149  int menu_font_size = font::SIZE_NORMAL;
150  std::string tmp = files_list_->strip_last_delim(dirname);
151 
152  // If the text get out of bounds, make it shorter;
153  // Take the prefix of the dir (ie. /home/ or c:/) put three dot's behind it
154  // and shorten the rest of the dir:
155  // /home/.../rest_of_the_dir
156  // Note that this is a dirty hack and fundamental changes in the widget subdir
157  // needs to be made...
158  if(font::line_width(tmp, menu_font_size) <= 390) {
159  return tmp;
160  }
161  static const int filler_width = font::line_width("...", menu_font_size);
162 
163  // Find the first part of the dir
164  std::string dir_prefix = "/";
165  std::string::size_type pos_first = 0;
166  if((pos_first = tmp.find_first_of("\\/", 1)) != std::string::npos)
167  {
168  dir_prefix = tmp.substr(0, pos_first) + "/...";
169  tmp = tmp.substr(pos_first);
170  }
171 
172  static const int prefix_width = font::line_width(dir_prefix, menu_font_size);
173 
174  // Try to cut off text at the '/' or '\' tokens
175  while(font::line_width(tmp, menu_font_size) + filler_width + prefix_width > 390 && tmp.length() != 0)
176  {
177  std::string::size_type pos;
178  if((pos = tmp.find_first_of("\\/", 1)) != std::string::npos)
179  tmp = tmp.substr(pos, tmp.length());
180  else
181  tmp = tmp.substr(1, tmp.length());
182  }
183 
184  return dir_prefix + tmp;
185 }
186 
188 {
189  const std::string fn = format_filename(filename);
190  const size_t filename_dot = fn.find_last_of('.');
191  get_textbox().set_text(fn);
192  get_textbox().set_selection(0, filename_dot != std::string::npos ? filename_dot : fn.length());
194 }
195 
197 {
198  if(result() == gui::CLOSE_DIALOG)
199  return;
200 
201  //handle "delete item" requests
202  if(result() == gui::DELETE_ITEM)
203  {
204  if(!chosen_file_.empty())
205  {
206  if(files_list_->delete_chosen_file() == -1) {
208  , _("Deletion of the file failed."));
209  dp_info.clear_buttons();
210  } else {
211  dp_info.first_time = true;
212  }
213  }
215  }
216  //handle "create item" requests
217  else if(result() == gui::CREATE_ITEM)
218  {
219  std::string new_dir_name = "";
220  if(gui2::tfolder_create::execute(new_dir_name, get_video()))
221  {
222  if( !files_list_->make_directory(new_dir_name) ) {
224  , _("Creation of the directory failed."));
225  } else {
226  dp_info.first_time = true;
227  }
228  }
229  dp_info.clear_buttons();
231  }
232 
233  //update the chosen file
234  if((dp_info.selection != last_selection_
235  || dp_info.first_time
236  || dp_info.double_clicked)
237  && (!files_list_->type_a_head()
238  || dp_info.new_left_button))
239  {
241 
244  last_selection_ = (dp_info.double_clicked) ? -1 : dp_info.selection;
246  }
247  else if(textbox_text() != last_textbox_text_)
248  {
251 
252  // Do type-a-head search in listbox
253  if (autocomplete_) {
255  }
256  }
257 
258  if(result() >=0) {
259  //if a directory has been chosen, enter it
261  {
264 
265  //reset the chosen file
266  chosen_file_ = "..";
269  }
270  //if a file has been chosen, return button index "Ok"
271  else
272  {
273  set_result(0);
274  }
275  }
276 }
277 
278 } //end namespace dialogs
int show_file_chooser_dialog_save(CVideo &video, std::string &filename, std::string const &title, const std::string &default_file_name, bool show_directory_buttons, const std::string &type_a_head, int xloc, int yloc)
Show a filechooser dialog in a "save" mode, that is, without relying on autocomplete to allow saving ...
Definition: filechooser.cpp:44
dialog_textbox & get_textbox() const
void set_result(const int result)
void set_autocomplete(bool value)
Definition: filechooser.hpp:41
static const char path_delim
Definition: file_menu.hpp:28
const std::string & set_text(const std::string &text)
Definition: label.cpp:35
void set_textbox(dialog_textbox *const box)
int pos
Definition: formula.cpp:800
void set_save_text(const std::string &filename)
bool make_directory(const std::string &subdir_name)
Definition: file_menu.cpp:117
Definition: video.hpp:58
void show_transient_error_message(CVideo &video, const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
std::string get_choice() const
Return the chosen file.
Definition: filechooser.hpp:37
void add_button(dialog_button *const btn, BUTTON_LOCATION loc)
General purpose widgets.
void set_text(const std::string &text, const SDL_Color &color=font::NORMAL_COLOR)
Definition: textbox.cpp:76
#define d
int show(int xloc, int yloc)
-file util.hpp
std::string textbox_text() const
std::string format_filename(const std::string &filename) const
std::string chosen_file_
Definition: filechooser.hpp:55
const int SIZE_NORMAL
Definition: font.hpp:58
void set_measurements(int w, int h)
Definition: widget.cpp:129
void set_cursor_pos(const int cursor_pos)
Definition: textbox.cpp:155
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
std::string strip_last_delim(const std::string &path) const
Return the string with the last path delimiter removed, if one was there.
Definition: file_menu.cpp:232
int gety() const
Definition: video.cpp:481
bool is_directory(const std::string &fname) const
Definition: file_menu.cpp:163
void set_menu(menu *const m)
virtual gui::dialog::dimension_measurements layout(int xloc=-1, int yloc=-1)
Definition: filechooser.cpp:90
void reset_type_a_head()
Definition: file_menu.cpp:285
int show_file_chooser_dialog(CVideo &video, std::string &filename, std::string const &title, bool show_directory_buttons, const std::string &type_a_head, int xloc, int yloc)
Show a dialog where the user can navigate through files and select a file.
Definition: filechooser.cpp:30
std::string get_choice() const
Return the chosen file.
Definition: file_menu.cpp:191
void select_file(const std::string &file)
std::string get_directory() const
Definition: file_menu.hpp:40
Various uncategorised dialogs.
Definition: dialogs.cpp:85
void action(gui::dialog_process_info &dp_info)
std::string last_textbox_text_
Definition: filechooser.hpp:54
void set_selection(const int selstart, const int selend)
Definition: textbox.cpp:140
file_dialog(CVideo &video, const std::string &file_path, const std::string &title, const std::string &default_file_name, bool show_directory_buttons)
Definition: filechooser.cpp:61
std::string unformat_filename(const std::string &filename) const
static bool execute(std::string &folder_name, CVideo &video)
The execute function; see tdialog for more information.
int result() const
CVideo & get_video()
void select_file(const std::string &begin_of_filename)
Selects file (type-a-head search)
Definition: file_menu.cpp:295
std::map< dialog_button *, std::pair< int, int > > buttons
size_t i
Definition: function.cpp:1057
gui::file_menu * files_list_
Definition: filechooser.hpp:52
label * get_label() const
std::string default_file_name_
Definition: filechooser.hpp:56
std::string add_path(const std::string &path, const std::string &to_add) const
Return path with to_add added, using a path delimiter between them.
Definition: file_menu.cpp:244
A widget where the user may navigate through directories and choose a file.
Definition: file_menu.hpp:25
std::string format_dirname(const std::string &dirname) const
bool type_a_head() const
Definition: file_menu.cpp:280
int delete_chosen_file()
Definition: file_menu.cpp:104
void change_directory(const std::string &path)
Definition: file_menu.cpp:169
int width() const
Definition: widget.cpp:134
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
GLsizei const GLcharARB ** string
Definition: glew.h:4503
void set_max_height(const int new_max_height)
Set a new max height for this menu.
Definition: menu.cpp:477
int line_width(const std::string &line, int font_size, int style)
Determine the width of a line of text given a certain font size.
Definition: font.cpp:969
void set_layout(dimension_measurements &new_dim)
label & get_message() const
int height() const
Definition: widget.cpp:139