gui: Remove GUI1 filechooser

This switches all existing callsites to using gui2::tfile_dialog, and
fixes a build issue due to editor/controller/editor_controller.cpp
relying on an indirect include from gui/dialogs/editor/custom_tod.hpp
for a full type declaration.
This commit is contained in:
Ignacio R. Morelle 2016-10-03 05:38:14 -03:00
parent 8056d638f1
commit 285bbe7237
13 changed files with 84 additions and 849 deletions

View File

@ -322,8 +322,6 @@
<Unit filename="../../src/fake_unit_manager.hpp" />
<Unit filename="../../src/fake_unit_ptr.cpp" />
<Unit filename="../../src/fake_unit_ptr.hpp" />
<Unit filename="../../src/filechooser.cpp" />
<Unit filename="../../src/filechooser.hpp" />
<Unit filename="../../src/filesystem.hpp" />
<Unit filename="../../src/filesystem_boost.cpp" />
<Unit filename="../../src/filesystem_common.cpp" />
@ -1153,8 +1151,6 @@
<Unit filename="../../src/widgets/combo_drag.hpp" />
<Unit filename="../../src/widgets/drop_target.cpp" />
<Unit filename="../../src/widgets/drop_target.hpp" />
<Unit filename="../../src/widgets/file_menu.cpp" />
<Unit filename="../../src/widgets/file_menu.hpp" />
<Unit filename="../../src/widgets/label.cpp" />
<Unit filename="../../src/widgets/label.hpp" />
<Unit filename="../../src/widgets/menu.cpp" />

View File

@ -726,7 +726,6 @@ set(wesnoth-main_SRC
editor/map/context_manager.cpp
fake_unit_manager.cpp
fake_unit_ptr.cpp
filechooser.cpp
filesystem_sdl.cpp
game_initialization/flg_manager.cpp
floating_textbox.cpp
@ -1026,7 +1025,6 @@ set(libwesnoth-game_STAT_SRC
video.cpp
theme.cpp
widgets/button.cpp
widgets/file_menu.cpp
widgets/label.cpp
widgets/menu.cpp
widgets/menu_style.cpp

View File

@ -131,7 +131,6 @@ libwesnoth_sources = Split("""
utils/make_enum.cpp
video.cpp
widgets/button.cpp
widgets/file_menu.cpp
widgets/label.cpp
widgets/menu_style.cpp
widgets/menu.cpp
@ -284,7 +283,6 @@ wesnoth_sources = Split("""
editor/toolkit/editor_toolkit.cpp
fake_unit_manager.cpp
fake_unit_ptr.cpp
filechooser.cpp
filesystem_sdl.cpp
floating_textbox.cpp
formula/callable_objects.cpp

View File

@ -42,6 +42,7 @@
#include "reports.hpp"
#include "desktop/clipboard.hpp"
#include "floating_label.hpp"
#include "game_board.hpp"
#include "game_preferences.hpp"
#include "gettext.hpp"

View File

@ -19,7 +19,6 @@
#include "context_manager.hpp"
#include "display.hpp"
#include "filesystem.hpp"
#include "filechooser.hpp"
#include "formula/string_utils.hpp"
#include "game_board.hpp"
#include "gettext.hpp"
@ -35,6 +34,7 @@
#include "gui/dialogs/editor/new_map.hpp"
#include "gui/dialogs/editor/resize_map.hpp"
#include "gui/dialogs/edit_text.hpp"
#include "gui/dialogs/file_dialog.hpp"
#include "gui/dialogs/message.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "gui/widgets/window.hpp"
@ -190,9 +190,14 @@ void context_manager::load_map_dialog(bool force_same_context /* = false */)
if (fn.empty()) {
fn = default_dir_;
}
int res = dialogs::show_file_chooser_dialog(gui_.video(), fn, _("Choose a File to Open"));
if (res == 0) {
load_map(fn, !force_same_context);
gui2::tfile_dialog dlg;
dlg.set_title(_("Choose a File to Open"))
.set_path(fn);
if(dlg.show(gui_.video())) {
load_map(dlg.path(), !force_same_context);
}
}
@ -444,10 +449,15 @@ void context_manager::apply_mask_dialog()
if (fn.empty()) {
fn = default_dir_;
}
int res = dialogs::show_file_chooser_dialog(gui_.video(), fn, _("Choose a Mask to Apply"));
if (res == 0) {
gui2::tfile_dialog dlg;
dlg.set_title(_("Choose a Mask to Apply"))
.set_path(fn);
if(dlg.show(gui_.video())) {
try {
map_context mask(game_config_, fn, gui_);
map_context mask(game_config_, dlg.path(), gui_);
editor_action_apply_mask a(mask.get_map());
perform_refresh(a);
} catch (editor_map_load_exception& e) {
@ -481,10 +491,15 @@ void context_manager::create_mask_to_dialog()
if (fn.empty()) {
fn = default_dir_;
}
int res = dialogs::show_file_chooser_dialog(gui_.video(), fn, _("Choose Target Map"));
if (res == 0) {
gui2::tfile_dialog dlg;
dlg.set_title(_("Choose Target Map"))
.set_path(fn);
if(dlg.show(gui_.video())) {
try {
map_context map(game_config_, fn, gui_);
map_context map(game_config_, dlg.path(), gui_);
editor_action_create_mask a(map.get_map());
perform_refresh(a);
} catch (editor_map_load_exception& e) {
@ -605,10 +620,20 @@ void context_manager::save_map_as_dialog()
int overwrite_res = 1;
do {
input_name = old_input_name;
int res = dialogs::show_file_chooser_dialog_save(gui_.video(), input_name, _("Save the Map As"), ".map");
if (res == 0) {
gui2::tfile_dialog dlg;
dlg.set_title(_("Save the Map As"))
.set_ok_label(_("Save"))
.set_save_mode(true)
.set_path(input_name)
.set_extension(".map");
if(dlg.show(gui_.video())) {
input_name = dlg.path();
if (filesystem::file_exists(input_name)) {
res = gui2::show_message(gui_.video(), "",
int res = gui2::show_message(gui_.video(), "",
_("The file already exists. Do you want to overwrite it?"), gui2::tmessage::yes_no_buttons);
overwrite_res = gui2::twindow::CANCEL == res ? 1 : 0;
} else {
@ -633,10 +658,20 @@ void context_manager::save_scenario_as_dialog()
int overwrite_res = 1;
do {
input_name = old_input_name;
int res = dialogs::show_file_chooser_dialog_save(gui_.video(), input_name, _("Save the Scenario As"), ".cfg");
if (res == 0) {
gui2::tfile_dialog dlg;
dlg.set_title(_("Save the Scenario As"))
.set_ok_label(_("Save"))
.set_save_mode(true)
.set_path(input_name)
.set_extension(".cfg");
if(dlg.show(gui_.video())) {
input_name = dlg.path();
if (filesystem::file_exists(input_name)) {
res = gui2::show_message(gui_.video(), "",
int res = gui2::show_message(gui_.video(), "",
_("The file already exists. Do you want to overwrite it?"), gui2::tmessage::yes_no_buttons);
overwrite_res = gui2::twindow::CANCEL == res ? 1 : 0;
} else {

View File

@ -1,303 +0,0 @@
/*
Copyright (C) 2003 - 2016 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "global.hpp"
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "video.hpp"
#include "gettext.hpp"
#include "gui/dialogs/file_dialog.hpp"
#include "gui/dialogs/folder_create.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "filechooser.hpp"
#include "widgets/file_menu.hpp"
namespace dialogs
{
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)
{
if(true) {
gui2::tfile_dialog dlg;
dlg.set_path(filename).set_title(title).set_read_only(!show_directory_buttons).set_filename(type_a_head);
if(dlg.show(video)) {
filename = dlg.path();
std::cerr << filename << '\n';
return 0;
}
return -1;
}
file_dialog d(video, filename, title, "", show_directory_buttons);
if (!type_a_head.empty())
d.select_file(type_a_head);
if(d.show(xloc, yloc) >= 0) {
filename = d.get_choice();
}
return d.result();
}
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)
{
if(true) {
gui2::tfile_dialog dlg;
dlg.set_path(filename).set_title(title).set_read_only(!show_directory_buttons).set_filename(type_a_head).set_save_mode(true);
if(dlg.show(video)) {
filename = dlg.path();
std::cerr << filename << '\n';
return 0;
}
return -1;
}
file_dialog d(video, filename, title, default_file_name, show_directory_buttons);
d.set_autocomplete(false);
if (!type_a_head.empty())
d.select_file(type_a_head);
if(d.show(xloc, yloc) >= 0) {
filename = d.get_choice();
}
return d.result();
}
file_dialog::file_dialog(CVideo& video, const std::string& file_path,
const std::string& title, const std::string& default_file_name,
bool show_directory_buttons) :
gui::dialog(video, title, file_path, gui::OK_CANCEL),
show_directory_buttons_(show_directory_buttons),
files_list_(nullptr),
last_selection_(-1),
last_textbox_text_(),
chosen_file_(".."),
autocomplete_(true)
{
files_list_ = new gui::file_menu(video, file_path);
const unsigned file_list_height = (video.gety() / 2);
const unsigned file_list_width = std::min<unsigned>(files_list_->width(), (video.gety() / 4));
files_list_->set_measurements(file_list_width, file_list_height);
files_list_->set_max_height(file_list_height);
set_menu(files_list_);
default_file_name_ = default_file_name;
get_message().set_text(format_dirname(files_list_->get_directory()));
set_textbox(_("File: "), format_filename(file_path), 100);
if (show_directory_buttons_)
{
add_button( new gui::dialog_button(video, _("Delete File"),
gui::button::TYPE_PRESS, gui::DELETE_ITEM), dialog::BUTTON_EXTRA);
add_button( new gui::dialog_button(video, _("New Folder"),
gui::button::TYPE_PRESS, gui::CREATE_ITEM), dialog::BUTTON_EXTRA_LEFT);
}
}
gui::dialog::dimension_measurements file_dialog::layout(int xloc, int yloc)
{
gui::dialog::dimension_measurements dim = dialog::layout(xloc, yloc);
//shift the menu up
unsigned y_shift = dim.menu_y - std::min<int>(dim.label_y, dim.textbox.y);
int y_max = dim.menu_y + get_menu().height();
dim.menu_y -= y_shift;
//shift the extra buttons up
if (show_directory_buttons_)
{
std::map<gui::dialog_button *, std::pair<int,int> >::iterator i;
for(i = dim.buttons.begin(); i != dim.buttons.end(); ++i)
{
const int btn_h = i->first->height();
int& btn_y = i->second.second;
y_max = std::max<int>(y_max, btn_y + btn_h);
btn_y -= y_shift;
}
}
//shift the textbox down
const int textbox_bottom_y = dim.textbox.y + get_textbox().height();
const int label_bottom_y = dim.label_y + get_textbox().get_label()->height();
y_shift = y_max - std::max<int>(textbox_bottom_y, label_bottom_y);
dim.textbox.y += y_shift;
dim.label_y += y_shift;
set_layout(dim);
return dim;
}
std::string file_dialog::unformat_filename(const std::string& filename) const
{
return files_list_->add_path(files_list_->get_directory(), filename);
}
std::string file_dialog::format_filename(const std::string& filename) const
{
if(files_list_->is_directory(filename)) {
return default_file_name_;
}
std::string::size_type last_delim = filename.find_last_of(gui::file_menu::path_delim);
if(last_delim != std::string::npos) {
return filename.substr(last_delim + 1);
}
return filename;
}
void file_dialog::select_file(const std::string& file)
{
chosen_file_ = file;
get_textbox().set_text(format_filename(chosen_file_));
files_list_->select_file(file);
}
std::string file_dialog::format_dirname(const std::string& dirname) const
{
int menu_font_size = font::SIZE_NORMAL;
std::string tmp = files_list_->strip_last_delim(dirname);
// If the text get out of bounds, make it shorter;
// Take the prefix of the dir (ie. /home/ or c:/) put three dot's behind it
// and shorten the rest of the dir:
// /home/.../rest_of_the_dir
// Note that this is a dirty hack and fundamental changes in the widget subdir
// needs to be made...
if(font::line_width(tmp, menu_font_size) <= 390) {
return tmp;
}
static const int filler_width = font::line_width("...", menu_font_size);
// Find the first part of the dir
std::string dir_prefix = "/";
std::string::size_type pos_first = 0;
if((pos_first = tmp.find_first_of("\\/", 1)) != std::string::npos)
{
dir_prefix = tmp.substr(0, pos_first) + "/...";
tmp = tmp.substr(pos_first);
}
static const int prefix_width = font::line_width(dir_prefix, menu_font_size);
// Try to cut off text at the '/' or '\' tokens
while(font::line_width(tmp, menu_font_size) + filler_width + prefix_width > 390 && tmp.length() != 0)
{
std::string::size_type pos;
if((pos = tmp.find_first_of("\\/", 1)) != std::string::npos)
tmp = tmp.substr(pos, tmp.length());
else
tmp = tmp.substr(1, tmp.length());
}
return dir_prefix + tmp;
}
void file_dialog::set_save_text(const std::string& filename)
{
const std::string fn = format_filename(filename);
const size_t filename_dot = fn.find_last_of('.');
get_textbox().set_text(fn);
get_textbox().set_selection(0, filename_dot != std::string::npos ? filename_dot : fn.length());
get_textbox().set_cursor_pos(0);
}
void file_dialog::action(gui::dialog_process_info &dp_info)
{
if(result() == gui::CLOSE_DIALOG)
return;
//handle "delete item" requests
if(result() == gui::DELETE_ITEM)
{
if(!chosen_file_.empty())
{
if(files_list_->delete_chosen_file() == -1) {
gui2::show_transient_error_message(get_video()
, _("Deletion of the file failed."));
dp_info.clear_buttons();
} else {
dp_info.first_time = true;
}
}
set_result(gui::CONTINUE_DIALOG);
}
//handle "create item" requests
else if(result() == gui::CREATE_ITEM)
{
std::string new_dir_name = "";
if(gui2::tfolder_create::execute(new_dir_name, get_video()))
{
if( !files_list_->make_directory(new_dir_name) ) {
gui2::show_transient_error_message(get_video()
, _("Creation of the directory failed."));
} else {
dp_info.first_time = true;
}
}
dp_info.clear_buttons();
set_result(gui::CONTINUE_DIALOG);
}
//update the chosen file
if((dp_info.selection != last_selection_
|| dp_info.first_time
|| dp_info.double_clicked)
&& (!files_list_->type_a_head()
|| dp_info.new_left_button))
{
files_list_->reset_type_a_head();
chosen_file_ = files_list_->get_choice();
set_save_text(chosen_file_);
last_selection_ = (dp_info.double_clicked) ? -1 : dp_info.selection;
last_textbox_text_ = textbox_text();
}
else if(textbox_text() != last_textbox_text_)
{
chosen_file_ = unformat_filename(textbox_text());
last_textbox_text_ = textbox_text();
// Do type-a-head search in listbox
if (autocomplete_) {
files_list_->select_file(textbox_text());
}
}
if(result() >=0) {
//if a directory has been chosen, enter it
if(files_list_->is_directory(chosen_file_))
{
files_list_->change_directory(chosen_file_);
get_message().set_text(format_dirname(files_list_->get_directory()));
//reset the chosen file
chosen_file_ = "..";
get_textbox().set_text(format_filename(chosen_file_));
set_result(gui::CONTINUE_DIALOG);
}
//if a file has been chosen, return button index "Ok"
else
{
set_result(0);
}
}
}
} //end namespace dialogs

View File

@ -1,80 +0,0 @@
/*
Copyright (C) 2003 - 2016 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef FILE_CHOOSER_H_INCLUDED
#define FILE_CHOOSER_H_INCLUDED
class config;
class CVideo;
#include "construct_dialog.hpp"
namespace gui
{
class file_menu;
}
namespace dialogs
{
class file_dialog : public gui::dialog {
public:
file_dialog(CVideo& video, const std::string& file_path, const std::string& title, const std::string& default_file_name, bool show_directory_buttons);
virtual gui::dialog::dimension_measurements layout(int xloc=-1, int yloc=-1);
/// Return the chosen file.
std::string get_choice() const { return chosen_file_; }
void select_file(const std::string& file);
void set_autocomplete(bool value) { autocomplete_ = value; }
protected:
void action(gui::dialog_process_info &dp_info);
void set_save_text(const std::string& filename);
std::string unformat_filename(const std::string& filename) const;
std::string format_filename(const std::string& filename) const;
std::string format_dirname(const std::string& dirname) const;
private:
bool show_directory_buttons_;
gui::file_menu *files_list_;
int last_selection_;
std::string last_textbox_text_;
std::string chosen_file_;
std::string default_file_name_;
bool autocomplete_;
};
/// Show a dialog where the user can navigate through files and select a
/// file. The filename is used as a starting point in the navigation and
/// contains the chosen file when the function returns. Return the
/// index of the button pressed, or -1 if the dialog was canceled
/// through keypress.
int show_file_chooser_dialog(CVideo& video, std::string &filename,
std::string const &title, bool show_directory_buttons = true,
const std::string& file_to_search = "",
int xloc = -1, int yloc = -1);
/// Show a filechooser dialog in a "save" mode, that is, without relying
/// on autocomplete to allow saving under any filename
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 = true,
const std::string& file_to_search = "",
int xloc = -1, int yloc = -1);
} // end of dialogs namespace
#endif

View File

@ -17,10 +17,10 @@
#include "gui/dialogs/editor/custom_tod.hpp"
#include "filesystem.hpp"
#include "filechooser.hpp"
#include "editor/editor_preferences.hpp"
#include "editor/editor_display.hpp"
#include "gui/auxiliary/field.hpp"
#include "gui/dialogs/file_dialog.hpp"
#include "gui/dialogs/helper.hpp"
#include "gui/widgets/button.hpp"
#include "gui/widgets/label.hpp"
@ -114,9 +114,15 @@ void tcustom_tod::select_file(const std::string& filename,
dn = default_dir;
}
int res = dialogs::show_file_chooser_dialog(
display_.video(), dn, _("Choose File"));
if(res == 0) {
gui2::tfile_dialog dlg;
dlg.set_title(_("Choose File"))
.set_ok_label(_("Select"))
.set_path(dn);
if(dlg.show(display_.video())) {
dn = dlg.path();
if(attribute == "image") {
tods_[current_tod_].image = dn;
} else if(attribute == "mask") {

View File

@ -15,7 +15,6 @@
#ifndef GUI_DIALOGS_CUSTOM_TOD_HPP_INCLUDED
#define GUI_DIALOGS_CUSTOM_TOD_HPP_INCLUDED
#include "filechooser.hpp"
#include "time_of_day.hpp"
#include "gui/widgets/image.hpp"
#include "gui/widgets/text_box.hpp"

View File

@ -30,7 +30,6 @@
#include "chat_command_handler.hpp"
#include "config_assign.hpp"
#include "display_chat_manager.hpp"
#include "filechooser.hpp"
#include "formatter.hpp"
#include "formula/string_utils.hpp"
#include "game_board.hpp"
@ -43,6 +42,7 @@
#include "gettext.hpp"
#include "gui/dialogs/chat_log.hpp"
#include "gui/dialogs/edit_label.hpp"
#include "gui/dialogs/file_dialog.hpp"
#include "gui/dialogs/label_settings.hpp"
#include "gui/dialogs/message.hpp"
#include "gui/dialogs/transient_message.hpp"
@ -166,8 +166,15 @@ void menu_handler::save_map()
int res = 0;
int overwrite = 1;
do {
res = dialogs::show_file_chooser_dialog_save(gui_->video(), input_name, _("Save the Map As"), ".map");
if (res == 0) {
gui2::tfile_dialog dlg;
dlg.set_title(_("Save the Map As"))
.set_save_mode(true)
.set_path(input_name)
.set_extension(".map");
if(dlg.show(gui_->video())) {
input_name = dlg.path();
if (filesystem::file_exists(input_name)) {
const int res = gui2::show_message((*gui_).video(), "", _("The map already exists. Do you want to overwrite it?"), gui2::tmessage::yes_no_buttons);

View File

@ -23,12 +23,12 @@
#include "preferences_display.hpp"
#include "display.hpp"
#include "filechooser.hpp"
#include "filesystem.hpp"
#include "formatter.hpp"
#include "formula/string_utils.hpp"
#include "game_preferences.hpp"
#include "gettext.hpp"
#include "gui/dialogs/file_dialog.hpp"
#include "gui/dialogs/message.hpp"
#include "gui/dialogs/preferences_dialog.hpp"
#include "gui/dialogs/theme_list.hpp"
@ -164,16 +164,20 @@ void show_wesnothd_server_search(CVideo& video)
path = old_path;
}
utils::string_map symbols;
const std::string msg = vgettext(
"The <b>$filename</b> server application provides multiplayer server functionality and is required for hosting local network games. It will normally be found in the same folder where the game executable is installed.", {{"filename", filename}});
symbols["filename"] = filename;
gui2::tfile_dialog dlg;
const std::string title = utils::interpolate_variables_into_string(
_("Find $filename server binary")
, &symbols);
dlg.set_title(_("Find Server Application"))
.set_message(msg)
.set_ok_label(_("Select"))
.set_read_only(true)
.set_filename(filename)
.set_path(path);
int res = dialogs::show_file_chooser_dialog(video, path, title, false, filename);
if (res == 0) {
if(dlg.show(video)) {
path = dlg.path();
preferences::set_mp_server_program_name(path);
}
}

View File

@ -1,325 +0,0 @@
/*
Copyright (C) 2003 - 2016 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "global.hpp"
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "filesystem.hpp"
#include "marked-up_text.hpp"
#include "wml_separators.hpp"
#include "widgets/file_menu.hpp"
namespace {
std::vector<std::string> empty_string_vector;
std::string uniform_path(const std::string& path)
{
#ifdef _WIN32
std::string res = path;
std::replace(res.begin(), res.end(), '/', '\\');
return res;
#else
return path;
#endif
}
}
namespace gui {
static const std::string dir_picture("misc/folder-icon.png");
static const std::string path_up("..");
#ifdef _WIN32
const char file_menu::path_delim('\\');
#else
const char file_menu::path_delim('/');
#endif
file_menu::file_menu(CVideo &disp, std::string start_file)
: menu(disp, empty_string_vector, false),
current_dir_(uniform_path(get_path(start_file))),
chosen_file_(start_file), last_selection_(-1),
type_a_head_(-1)
{
// If the start file is not a file or directory, use the root.
if((!filesystem::file_exists(chosen_file_) && !::filesystem::is_directory(chosen_file_))
|| !::filesystem::is_directory(current_dir_)) {
current_dir_ = path_delim;
chosen_file_ = current_dir_;
}
// FIXME: quick hack
// on a high-res screen the initial max_items_onscreen is based
// on .66 of y dimension, eg. 17 menu items, exceeding the
// starting box which can only take 13 or so: force it to be smaller
// set_measurements(400, 384);
update_file_lists();
}
void file_menu::display_current_files() {
std::vector<std::string> to_show;
if (!is_root(current_dir_)) {
to_show.push_back(path_up);
}
std::vector<std::string>::iterator it;
for (it = dirs_in_current_dir_.begin(); it != dirs_in_current_dir_.end(); ++it) {
// Add an image to show that these are directories.
std::stringstream ss;
ss << font::IMAGE << dir_picture << COLUMN_SEPARATOR << font::NULL_MARKUP << *it;
to_show.push_back(ss.str());
}
for (it = files_in_current_dir_.begin(); it != files_in_current_dir_.end(); ++it) {
const std::string display_string = COLUMN_SEPARATOR + std::string(1, font::NULL_MARKUP) + *it;
to_show.push_back(display_string);
}
const int menu_font_size = font::SIZE_NORMAL; // Known from menu.cpp.
for (it = to_show.begin(); it != to_show.end(); ++it) {
// Make sure that all lines fit.
// Guess the width of the scrollbar to be 30 since it is not accessible from here.
// -25 to compensate for the picture column.
if (get_max_width() != -1) {
while(font::line_width(*it, menu_font_size) > width() - 30 - 25) {
//we cannot decrease its size if its empty.
assert(!(*it).empty());
(*it).resize((*it).size() - 1);
}
}
}
set_items(to_show);
}
int file_menu::delete_chosen_file() {
const int ret = filesystem::delete_file(chosen_file_);
if (ret == -1) {
// gui2::show_transient_message(disp_.video(), "", _("Deletion of the file failed."));
}
else {
last_selection_ = -1;
update_file_lists();
chosen_file_ = current_dir_;
}
return ret;
}
bool file_menu::make_directory(const std::string& subdir_name) {
bool ret = ::filesystem::make_directory(add_path(current_dir_, subdir_name));
if (ret == false) {
// gui2::show_transient_message(disp_.video(), "", _("Creation of the directory failed."));
}
else {
last_selection_ = -1;
update_file_lists();
chosen_file_ = current_dir_;
}
return ret;
}
void file_menu::handle_event(const SDL_Event& event) {
menu::handle_event(event);
if(selection() != last_selection_
&& !type_a_head()) {
type_a_head_ = -1;
entry_selected(selection());
last_selection_ = selection();
}
}
void file_menu::entry_selected(const unsigned entry) {
const int entry_index = entry - (is_root(current_dir_) ? 0 : 1);
if (entry_index >= 0) {
std::string selected;
if(static_cast<unsigned>(entry_index) < dirs_in_current_dir_.size()) {
const int dir_index = entry_index;
selected = dirs_in_current_dir_[dir_index];
}
else {
const int file_index = entry_index - dirs_in_current_dir_.size();
if(file_index >= 0 && size_t(file_index) < files_in_current_dir_.size()) {
selected = files_in_current_dir_[file_index];
} else {
return;
}
}
chosen_file_ = add_path(current_dir_, selected);
} else {
chosen_file_ = path_up;
}
}
bool file_menu::is_directory(const std::string& fname) const {
if(fname == path_up)
return true;
return ::filesystem::is_directory(fname);
}
void file_menu::change_directory(const std::string& path) {
if(path == path_up)
{
// Parent dir wanted.
if (!is_root(current_dir_)) {
current_dir_ = get_path_up(current_dir_);
last_selection_ = -1;
update_file_lists();
chosen_file_ = current_dir_;
}
else {
return;
}
} else {
current_dir_ = uniform_path(path);
chosen_file_ = current_dir_;
last_selection_ = -1;
update_file_lists();
}
}
std::string file_menu::get_choice() const {
return chosen_file_;
}
std::string file_menu::get_path(const std::string& file_or_dir) const {
std::string res_path = file_or_dir;
if (!::filesystem::is_directory(file_or_dir)) {
size_t index = file_or_dir.find_last_of(path_delim);
if (index != std::string::npos) {
res_path = file_or_dir.substr(0, index);
}
}
return res_path;
}
std::string file_menu::get_path_up(const std::string& path, const unsigned levels) const {
std::string curr_path = get_path(path);
for (unsigned i = 0; i < levels; i++) {
if (is_root(curr_path)) {
break;
}
curr_path = strip_last_delim(curr_path);
size_t index = curr_path.find_last_of(path_delim);
if (index != std::string::npos) {
curr_path = curr_path.substr(0, index);
}
else {
break;
}
}
if (curr_path.empty()) {
// The root was reached, represent this as one delimiter only.
curr_path = path_delim;
}
#ifdef _WIN32
if (curr_path.size() == 2 && curr_path[1] == ':') curr_path += path_delim;
#endif
return curr_path;
}
std::string file_menu::strip_last_delim(const std::string& path) const {
std::string res_string = path;
if (path[path.size() - 1] == path_delim) {
res_string = path.substr(0, path.size() - 1);
}
return res_string;
}
bool file_menu::is_root(const std::string& path) const {
return path.empty() || (path.size() == 1 && path[0] == path_delim);
}
std::string file_menu::add_path(const std::string& path, const std::string& to_add) const
{
std::string joined_path = strip_last_delim(path);
if (!to_add.empty()) {
if (to_add == path_up) {
return get_path_up(path);
}
#ifdef _WIN32
else if (to_add.size() > 1 && to_add[1] == ':') {
joined_path = to_add;
}
#else
else if (to_add[0] == path_delim) {
joined_path = to_add;
}
#endif
else {
joined_path += "/" + to_add;
}
}
return joined_path;
}
struct match_begin {
match_begin(const std::string& begin) : begin_(begin)
{}
bool operator()(const std::string& o) const
{
return o.compare(0, begin_.size(), begin_) == 0;
}
private:
const std::string& begin_;
};
bool file_menu::type_a_head() const
{
return selection() == type_a_head_;
}
void file_menu::reset_type_a_head()
{
if (type_a_head_ >= 0)
{
entry_selected(type_a_head_);
last_selection_ = type_a_head_;
}
type_a_head_ = -1;
}
void file_menu::select_file(const std::string& begin_of_filename)
{
size_t additional_index = is_root(current_dir_) ? 0 : 1;
std::vector<std::string>::iterator it;
it = std::find_if(dirs_in_current_dir_.begin(), dirs_in_current_dir_.end(), match_begin(begin_of_filename));
if (it != dirs_in_current_dir_.end())
{
type_a_head_ = additional_index + it - dirs_in_current_dir_.begin();
move_selection(type_a_head_);
return;
}
additional_index += dirs_in_current_dir_.size();
it = std::find_if(files_in_current_dir_.begin(), files_in_current_dir_.end(), match_begin(begin_of_filename));
if (it != files_in_current_dir_.end())
{
type_a_head_ = it - files_in_current_dir_.begin() + additional_index;
move_selection(type_a_head_);
return;
}
}
void file_menu::update_file_lists() {
files_in_current_dir_.clear();
dirs_in_current_dir_.clear();
filesystem::get_files_in_dir(current_dir_, &files_in_current_dir_,
&dirs_in_current_dir_, filesystem::FILE_NAME_ONLY);
display_current_files();
}
}

View File

@ -1,101 +0,0 @@
/*
Copyright (C) 2003 - 2016 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef FILE_MENU_H_INCLUDED
#define FILE_MENU_H_INCLUDED
#include "construct_dialog.hpp"
namespace gui {
/// A widget where the user may navigate through directories and choose
/// a file.
class file_menu : public menu {
public:
//Static members
static const char path_delim;
/// Initialize the file menu. start_file is the file that will be
/// selected initially. The current directory will be
/// the one the file is in.
file_menu(CVideo &disp, std::string start_file="");
/// Return the chosen file.
std::string get_choice() const;
int delete_chosen_file();
std::string get_directory() const { return current_dir_; }
/// Return path with to_add added, using a path delimiter between them.
std::string add_path(const std::string& path, const std::string& to_add) const;
/// Return the string with the last path delimiter removed, if one
/// was there.
std::string strip_last_delim(const std::string& path) const;
bool is_directory(const std::string& fname) const;
void change_directory(const std::string& path);
bool make_directory(const std::string& subdir_name);
/**
* Selects file (type-a-head search)
**/
void select_file(const std::string& begin_of_filename);
bool type_a_head() const;
void reset_type_a_head();
protected:
void handle_event(const SDL_Event& event);
private:
/// If file_or_dir is a file, return the directory the file is in,
/// if it is a directory, return the directory name. If no path
/// delimiters could be found, return the unchanged argument.
std::string get_path(const std::string& file_or_dir) const;
/// Return the path that is the specified number of levels up from
/// the path. If the movement could not proceed due to being at the
/// root or having an invalid argument, return the path that the
/// movement ended on.
std::string get_path_up(const std::string& path,
const unsigned levels=1) const;
/// Return true if the path is the root of the filesystem.
bool is_root(const std::string& path) const;
/// Show the files in the current directory.
void display_current_files();
/// Updated the locally maintained lists of files and directories in
/// the current directory.
void update_file_lists();
/// Set the textbox to reflect the selected file.
void entry_selected(const unsigned entry);
std::string current_dir_;
std::string chosen_file_;
std::vector<std::string> files_in_current_dir_, dirs_in_current_dir_;
int last_selection_;
int type_a_head_;
};
} //end namespace gui
#endif // FILE_MENU_H_INCLUDED