Merge lp:~widelands-dev/widelands/bug-1610507-disallowed-filename-characters into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 8722
Proposed branch: lp:~widelands-dev/widelands/bug-1610507-disallowed-filename-characters
Merge into: lp:widelands
Diff against target: 473 lines (+148/-56)
16 files modified
src/editor/ui_menus/main_menu_save_map.cc (+5/-2)
src/editor/ui_menus/main_menu_save_map.h (+1/-0)
src/editor/ui_menus/main_menu_save_map_make_directory.cc (+6/-3)
src/editor/ui_menus/main_menu_save_map_make_directory.h (+1/-0)
src/graphic/text_layout.cc (+7/-0)
src/graphic/text_layout.h (+4/-0)
src/io/CMakeLists.txt (+0/-21)
src/io/filesystem/CMakeLists.txt (+23/-0)
src/io/filesystem/filesystem.cc (+70/-0)
src/io/filesystem/filesystem.h (+4/-0)
src/io/filesystem/layered_filesystem.cc (+0/-16)
src/io/filesystem/layered_filesystem.h (+1/-2)
src/ui_basic/panel.cc (+20/-9)
src/ui_basic/panel.h (+1/-1)
src/wui/game_main_menu_save_game.cc (+4/-2)
src/wui/game_main_menu_save_game.h (+1/-0)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-1610507-disallowed-filename-characters
Reviewer Review Type Date Requested Status
Notabilis Approve
Review via email: mp+346442@code.launchpad.net

Commit message

Added tooltip to file save and make directory edit boxes if illegal filename is being entered. Also, some refactoring:

- New function as_listitem in text layout
- Fixed tooltip drawing for modal panels
- Some code style tweaks to Panel
- Filename checks now live directly in Filesystem

To post a comment you must log in.
Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3534. State: failed. Details: https://travis-ci.org/widelands/widelands/builds/382014340.
Appveyor build 3338. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1610507_disallowed_filename_characters-3338.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 3540. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/382500797.
Appveyor build 3344. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_1610507_disallowed_filename_characters-3344.

Revision history for this message
Notabilis (notabilis27) wrote :

Nice change, I like the tooltip! Works as intended and code is looking good.

Some remarks:
- Maybe add the tooltip to the OK button as well? At least for me that would be the more likely place where I would notice it.
- Is the smaller font for the list in the tooltip intentional?
- Maybe calculate the tooltip text only once and store it as static string in the file system class?

Not really related: I noticed that in the editor->make directory dialog the OK button is initially disabled, even though it should (?) be enabled. This is done intentionally by calling set_enabled(false) when creating the dialog, even though the directory name is valid and can be used. Is there a reason for disabling it?

review: Approve
Revision history for this message
GunChleoc (gunchleoc) wrote :

It is disabled because the text is always empty at the start, and empty names aren't allowed.

I like your suggestions and we should implement them before merging this.

The smaller text in the list is intentional - I have another branch for the editor info tool that uses the new listitem function too, and I wanted a consistent look.

Revision history for this message
Notabilis (notabilis27) wrote :

In the case of the "make directory" dialog the default value of the edit box is "unnamed". This is a valid name (changing and changing it back is accepted) but the OK button is initially disabled anyway.

Revision history for this message
GunChleoc (gunchleoc) wrote :

OK, that's a bug then.

Revision history for this message
GunChleoc (gunchleoc) wrote :

OK button is fixed. Thanks for the review and testing :)

@bunnybot merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc 2018-05-22 06:54:12 +0000
+++ src/editor/ui_menus/main_menu_save_map.cc 2018-05-31 17:12:19 +0000
@@ -68,7 +68,8 @@
68 UI::ButtonStyle::kWuiPrimary,68 UI::ButtonStyle::kWuiPrimary,
69 _("Map Options")),69 _("Map Options")),
70 editbox_label_(70 editbox_label_(
71 this, padding_, tabley_ + tableh_ + 3 * padding_, butw_, buth_, _("Filename:")) {71 this, padding_, tabley_ + tableh_ + 3 * padding_, butw_, buth_, _("Filename:")),
72 illegal_filename_tooltip_(FileSystem::illegal_filename_tooltip()) {
72 set_current_directory(curdir_);73 set_current_directory(curdir_);
7374
74 // Make room for edit_options_ button75 // Make room for edit_options_ button
@@ -220,7 +221,9 @@
220 */221 */
221void MainMenuSaveMap::edit_box_changed() {222void MainMenuSaveMap::edit_box_changed() {
222 // Prevent the user from creating nonsense file names, like e.g. ".." or "...".223 // Prevent the user from creating nonsense file names, like e.g. ".." or "...".
223 ok_.set_enabled(LayeredFileSystem::is_legal_filename(editbox_->text()));224 const bool is_legal_filename = FileSystem::is_legal_filename(editbox_->text());
225 ok_.set_enabled(is_legal_filename);
226 editbox_->set_tooltip(is_legal_filename ? "" : illegal_filename_tooltip_);
224}227}
225228
226void MainMenuSaveMap::reset_editbox_or_die(const std::string& current_filename) {229void MainMenuSaveMap::reset_editbox_or_die(const std::string& current_filename) {
227230
=== modified file 'src/editor/ui_menus/main_menu_save_map.h'
--- src/editor/ui_menus/main_menu_save_map.h 2018-05-10 15:57:43 +0000
+++ src/editor/ui_menus/main_menu_save_map.h 2018-05-31 17:12:19 +0000
@@ -55,6 +55,7 @@
5555
56 UI::Textarea editbox_label_;56 UI::Textarea editbox_label_;
57 UI::EditBox* editbox_;57 UI::EditBox* editbox_;
58 const std::string illegal_filename_tooltip_;
58};59};
5960
60#endif // end of include guard: WL_EDITOR_UI_MENUS_MAIN_MENU_SAVE_MAP_H61#endif // end of include guard: WL_EDITOR_UI_MENUS_MAIN_MENU_SAVE_MAP_H
6162
=== modified file 'src/editor/ui_menus/main_menu_save_map_make_directory.cc'
--- src/editor/ui_menus/main_menu_save_map_make_directory.cc 2018-04-27 06:11:05 +0000
+++ src/editor/ui_menus/main_menu_save_map_make_directory.cc 2018-05-31 17:12:19 +0000
@@ -54,7 +54,8 @@
54 butw_,54 butw_,
55 buth_,55 buth_,
56 UI::ButtonStyle::kWuiSecondary,56 UI::ButtonStyle::kWuiSecondary,
57 _("Cancel")) {57 _("Cancel")),
58 illegal_filename_tooltip_(FileSystem::illegal_filename_tooltip()) {
5859
59 vbox_.add(&label_);60 vbox_.add(&label_);
60 vbox_.add_space(padding_);61 vbox_.add_space(padding_);
@@ -66,7 +67,7 @@
66 ok_button_.sigclicked.connect(67 ok_button_.sigclicked.connect(
67 boost::bind(&MainMenuSaveMapMakeDirectory::end_modal<UI::Panel::Returncodes>,68 boost::bind(&MainMenuSaveMapMakeDirectory::end_modal<UI::Panel::Returncodes>,
68 boost::ref(*this), UI::Panel::Returncodes::kOk));69 boost::ref(*this), UI::Panel::Returncodes::kOk));
69 ok_button_.set_enabled(false);70 ok_button_.set_enabled(!dirname_.empty());
70 cancel_button_.sigclicked.connect(71 cancel_button_.sigclicked.connect(
71 boost::bind(&MainMenuSaveMapMakeDirectory::end_modal<UI::Panel::Returncodes>,72 boost::bind(&MainMenuSaveMapMakeDirectory::end_modal<UI::Panel::Returncodes>,
72 boost::ref(*this), UI::Panel::Returncodes::kBack));73 boost::ref(*this), UI::Panel::Returncodes::kBack));
@@ -80,6 +81,8 @@
80void MainMenuSaveMapMakeDirectory::edit_changed() {81void MainMenuSaveMapMakeDirectory::edit_changed() {
81 const std::string& text = edit_.text();82 const std::string& text = edit_.text();
82 // Prevent the user from creating nonsense directory names, like e.g. ".." or "...".83 // Prevent the user from creating nonsense directory names, like e.g. ".." or "...".
83 ok_button_.set_enabled(LayeredFileSystem::is_legal_filename(text));84 const bool is_legal_filename = FileSystem::is_legal_filename(text);
85 ok_button_.set_enabled(is_legal_filename);
86 edit_.set_tooltip(is_legal_filename ? "" : illegal_filename_tooltip_);
84 dirname_ = text;87 dirname_ = text;
85}88}
8689
=== modified file 'src/editor/ui_menus/main_menu_save_map_make_directory.h'
--- src/editor/ui_menus/main_menu_save_map_make_directory.h 2018-04-07 16:59:00 +0000
+++ src/editor/ui_menus/main_menu_save_map_make_directory.h 2018-05-31 17:12:19 +0000
@@ -50,6 +50,7 @@
50 UI::EditBox edit_;50 UI::EditBox edit_;
51 UI::Button ok_button_;51 UI::Button ok_button_;
52 UI::Button cancel_button_;52 UI::Button cancel_button_;
53 const std::string illegal_filename_tooltip_;
53 void edit_changed();54 void edit_changed();
54};55};
5556
5657
=== modified file 'src/graphic/text_layout.cc'
--- src/graphic/text_layout.cc 2018-05-05 17:10:37 +0000
+++ src/graphic/text_layout.cc 2018-05-31 17:12:19 +0000
@@ -141,6 +141,13 @@
141 return f.str();141 return f.str();
142}142}
143143
144/// Bullet list item
145std::string as_listitem(const std::string& txt, int ptsize, const RGBColor& clr) {
146 static boost::format f("<div width=100%%><div><p><font size=%d color=%s>•</font></p></div><div><p><space gap=6></p></div><div width=*><p><font size=%d color=%s>%s<vspace gap=6></font></p></div></div>");
147 f % ptsize % clr.hex_value() % ptsize % clr.hex_value() % txt;
148 return f.str();
149}
150
144std::string as_richtext(const std::string& txt) {151std::string as_richtext(const std::string& txt) {
145 static boost::format f("<rt>%s</rt>");152 static boost::format f("<rt>%s</rt>");
146 f % txt;153 f % txt;
147154
=== modified file 'src/graphic/text_layout.h'
--- src/graphic/text_layout.h 2018-04-07 16:59:00 +0000
+++ src/graphic/text_layout.h 2018-05-31 17:12:19 +0000
@@ -84,6 +84,10 @@
84 const RGBColor& clr = UI_FONT_CLR_FG,84 const RGBColor& clr = UI_FONT_CLR_FG,
85 UI::FontSet::Face face = UI::FontSet::Face::kSans);85 UI::FontSet::Face face = UI::FontSet::Face::kSans);
8686
87std::string as_listitem(const std::string&,
88 int ptsize = UI_FONT_SIZE_SMALL,
89 const RGBColor& clr = UI_FONT_CLR_FG);
90
87std::string as_richtext(const std::string&);91std::string as_richtext(const std::string&);
88std::string as_tooltip(const std::string&);92std::string as_tooltip(const std::string&);
89std::string as_waresinfo(const std::string&);93std::string as_waresinfo(const std::string&);
9094
=== modified file 'src/io/CMakeLists.txt'
--- src/io/CMakeLists.txt 2016-02-06 11:11:24 +0000
+++ src/io/CMakeLists.txt 2018-05-31 17:12:19 +0000
@@ -23,24 +23,3 @@
23 io_filesystem23 io_filesystem
24 io_stream24 io_stream
25)25)
26
27wl_library(io_filesystem
28 SRCS
29 filesystem/disk_filesystem.cc
30 filesystem/disk_filesystem.h
31 filesystem/filesystem.cc
32 filesystem/filesystem.h
33 filesystem/filesystem_exceptions.h
34 filesystem/layered_filesystem.cc
35 filesystem/layered_filesystem.h
36 filesystem/zip_exceptions.h
37 filesystem/zip_filesystem.cc
38 filesystem/zip_filesystem.h
39 DEPENDS
40 base_exceptions
41 base_log
42 base_macros
43 io_fileread
44 io_stream
45 third_party_minizip
46)
4726
=== modified file 'src/io/filesystem/CMakeLists.txt'
--- src/io/filesystem/CMakeLists.txt 2012-02-15 21:25:34 +0000
+++ src/io/filesystem/CMakeLists.txt 2018-05-31 17:12:19 +0000
@@ -1,1 +1,24 @@
1add_subdirectory(test)1add_subdirectory(test)
2
3wl_library(io_filesystem
4 SRCS
5 disk_filesystem.cc
6 disk_filesystem.h
7 filesystem.cc
8 filesystem.h
9 filesystem_exceptions.h
10 layered_filesystem.cc
11 layered_filesystem.h
12 zip_exceptions.h
13 zip_filesystem.cc
14 zip_filesystem.h
15 DEPENDS
16 base_exceptions
17 base_i18n
18 base_log
19 base_macros
20 graphic_text_layout
21 io_fileread
22 io_stream
23 third_party_minizip
24)
225
=== modified file 'src/io/filesystem/filesystem.cc'
--- src/io/filesystem/filesystem.cc 2018-05-12 04:17:53 +0000
+++ src/io/filesystem/filesystem.cc 2018-05-31 17:12:19 +0000
@@ -32,6 +32,9 @@
32#include <string>32#include <string>
33#include <vector>33#include <vector>
3434
35// We have to add Boost to this block to make codecheck happy
36#include <boost/algorithm/string/predicate.hpp>
37#include <boost/format.hpp>
35#ifdef _WIN3238#ifdef _WIN32
36#include <direct.h>39#include <direct.h>
37#include <io.h>40#include <io.h>
@@ -43,8 +46,10 @@
43#include <sys/stat.h>46#include <sys/stat.h>
44#include <unistd.h>47#include <unistd.h>
4548
49#include "base/i18n.h"
46#include "base/log.h"50#include "base/log.h"
47#include "config.h"51#include "config.h"
52#include "graphic/text_layout.h"
48#include "io/filesystem/disk_filesystem.h"53#include "io/filesystem/disk_filesystem.h"
49#include "io/filesystem/layered_filesystem.h"54#include "io/filesystem/layered_filesystem.h"
50#include "io/filesystem/zip_exceptions.h"55#include "io/filesystem/zip_exceptions.h"
@@ -60,6 +65,34 @@
60#define PATH_MAX MAX_PATH65#define PATH_MAX MAX_PATH
61#endif66#endif
6267
68
69namespace {
70// Characters that are allowed in filenames, but not at the beginning
71const std::vector<std::string> illegal_filename_starting_characters{
72 ".",
73 "-",
74 " ", // Keep the blank last
75};
76
77// Characters that are disallowed anywhere in a filename
78// No potential file separators or other potentially illegal characters
79// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
80// http://www.linfo.org/file_name.html
81// https://support.apple.com/en-us/HT202808
82// We can't just regex for word & digit characters here because of non-Latin scripts.
83const std::vector<std::string> illegal_filename_characters{
84 "<",
85 ">",
86 ":",
87 "\"",
88 "|",
89 "?",
90 "*",
91 "/",
92 "\\",
93};
94} // namespace
95
63/**96/**
64 * \param path A file or directory name97 * \param path A file or directory name
65 * \return True if ref path is absolute and within this FileSystem, false otherwise98 * \return True if ref path is absolute and within this FileSystem, false otherwise
@@ -148,6 +181,43 @@
148#endif181#endif
149}182}
150183
184bool FileSystem::is_legal_filename(const std::string& filename) {
185 if (filename.empty()) {
186 return false;
187 }
188 for (const std::string& illegal_start : illegal_filename_starting_characters) {
189 if (boost::starts_with(filename, illegal_start)) {
190 return false;
191 }
192 }
193 for (const std::string& illegal_char : illegal_filename_characters) {
194 if (boost::contains(filename, illegal_char)) {
195 return false;
196 }
197 }
198 return true;
199}
200
201std::string FileSystem::illegal_filename_tooltip() {
202 std::vector<std::string> starting_characters;
203 for (const std::string& character : illegal_filename_starting_characters) {
204 if (character == " ") {
205 /** TRANSLATORS: Part of tooltip entry for characters in illegal filenames. replaces tha blank space in a list of illegal characters */
206 starting_characters.push_back(pgettext("illegal_filename_characters", "blank space"));
207 } else {
208 starting_characters.push_back(character);
209 }
210 }
211 /** TRANSLATORS: Tooltip entry for characters in illegal filenames. %s is a list of illegal characters */
212 const std::string illegal_start(as_listitem((boost::format(pgettext("illegal_filename_characters", "%s at the start of the filename")) % richtext_escape(i18n::localize_list(starting_characters, i18n::ConcatenateWith::OR))).str(), UI_FONT_SIZE_MESSAGE));
213
214 /** TRANSLATORS: Tooltip entry for characters in illegal filenames. %s is a list of illegal characters */
215 const std::string illegal(as_listitem((boost::format(pgettext("illegal_filename_characters", "%s anywhere in the filename")) % richtext_escape(i18n::localize_list(illegal_filename_characters, i18n::ConcatenateWith::OR))).str(), UI_FONT_SIZE_MESSAGE));
216
217 /** TRANSLATORS: Tooltip header for characters in illegal filenames. This is followed by a list of bullet points */
218 return (boost::format("%s%s%s") % pgettext("illegal_filename_characters", "The following characters are not allowed:") % illegal_start % illegal).str();
219}
220
151// TODO(unknown): Write homedir detection for non-getenv-systems221// TODO(unknown): Write homedir detection for non-getenv-systems
152std::string FileSystem::get_homedir() {222std::string FileSystem::get_homedir() {
153 std::string homedir;223 std::string homedir;
154224
=== modified file 'src/io/filesystem/filesystem.h'
--- src/io/filesystem/filesystem.h 2018-04-07 16:59:00 +0000
+++ src/io/filesystem/filesystem.h 2018-05-31 17:12:19 +0000
@@ -108,6 +108,10 @@
108 std::string canonicalize_name(std::string path) const;108 std::string canonicalize_name(std::string path) const;
109 bool is_path_absolute(const std::string& path) const;109 bool is_path_absolute(const std::string& path) const;
110110
111 /// Returns true if the filename is legal in all operating systems
112 static bool is_legal_filename(const std::string& filename);
113 static std::string illegal_filename_tooltip();
114
111 // Returns the path separator, i.e. \ on windows and / everywhere else.115 // Returns the path separator, i.e. \ on windows and / everywhere else.
112 static char file_separator();116 static char file_separator();
113117
114118
=== modified file 'src/io/filesystem/layered_filesystem.cc'
--- src/io/filesystem/layered_filesystem.cc 2018-04-07 16:59:00 +0000
+++ src/io/filesystem/layered_filesystem.cc 2018-05-31 17:12:19 +0000
@@ -22,16 +22,12 @@
22#include <cstdio>22#include <cstdio>
23#include <memory>23#include <memory>
2424
25#include <boost/algorithm/string/predicate.hpp>
26#include <boost/regex.hpp>
27
28#include "base/log.h"25#include "base/log.h"
29#include "base/wexception.h"26#include "base/wexception.h"
30#include "io/fileread.h"27#include "io/fileread.h"
31#include "io/streamread.h"28#include "io/streamread.h"
3229
33LayeredFileSystem* g_fs;30LayeredFileSystem* g_fs;
34
35LayeredFileSystem::LayeredFileSystem() : home_(nullptr) {31LayeredFileSystem::LayeredFileSystem() : home_(nullptr) {
36}32}
3733
@@ -41,18 +37,6 @@
41LayeredFileSystem::~LayeredFileSystem() {37LayeredFileSystem::~LayeredFileSystem() {
42}38}
4339
44bool LayeredFileSystem::is_legal_filename(const std::string& filename) {
45 // No potential file separators or other potentially illegal characters
46 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
47 // http://www.linfo.org/file_name.html
48 // https://support.apple.com/en-us/HT202808
49 // We can't just regex for word & digit characters here because of non-Latin scripts.
50 boost::regex re(".*[<>:\"|?*/\\\\].*");
51 return !filename.empty() && !boost::starts_with(filename, ".") &&
52 !boost::starts_with(filename, " ") && !boost::starts_with(filename, "-") &&
53 !boost::regex_match(filename, re);
54}
55
56/**40/**
57 * Just assume that at least one of our child FSs is writable41 * Just assume that at least one of our child FSs is writable
58 */42 */
5943
=== modified file 'src/io/filesystem/layered_filesystem.h'
--- src/io/filesystem/layered_filesystem.h 2018-04-07 16:59:00 +0000
+++ src/io/filesystem/layered_filesystem.h 2018-05-31 17:12:19 +0000
@@ -58,8 +58,7 @@
5858
59 std::set<std::string> list_directory(const std::string& path) override;59 std::set<std::string> list_directory(const std::string& path) override;
6060
61 /// Returns true if the filename is legal in all operating systems61
62 static bool is_legal_filename(const std::string& filename);
63 bool is_writable() const override;62 bool is_writable() const override;
64 bool file_exists(const std::string& path) override;63 bool file_exists(const std::string& path) override;
65 bool is_directory(const std::string& path) override;64 bool is_directory(const std::string& path) override;
6665
=== modified file 'src/ui_basic/panel.cc'
--- src/ui_basic/panel.cc 2018-05-14 06:59:39 +0000
+++ src/ui_basic/panel.cc 2018-05-31 17:12:19 +0000
@@ -143,8 +143,9 @@
143 app->set_mouse_lock(false); // more paranoia :-)143 app->set_mouse_lock(false); // more paranoia :-)
144144
145 Panel* forefather = this;145 Panel* forefather = this;
146 while (Panel* const p = forefather->parent_)146 while (forefather->parent_ != nullptr) {
147 forefather = p;147 forefather = forefather->parent_;
148 }
148149
149 default_cursor_ = g_gr->images().get("images/ui_basic/cursor.png");150 default_cursor_ = g_gr->images().get("images/ui_basic/cursor.png");
150 default_cursor_click_ = g_gr->images().get("images/ui_basic/cursor_click.png");151 default_cursor_click_ = g_gr->images().get("images/ui_basic/cursor_click.png");
@@ -175,13 +176,16 @@
175 app->handle_input(&input_callback);176 app->handle_input(&input_callback);
176177
177 if (start_time >= next_think_time) {178 if (start_time >= next_think_time) {
178 if (app->should_die())179 if (app->should_die()) {
179 end_modal<Returncodes>(Returncodes::kBack);180 end_modal<Returncodes>(Returncodes::kBack);
181 }
180182
181 do_think();183 do_think();
182184
183 if (flags_ & pf_child_die)185 if (flags_ & pf_child_die) {
184 check_child_death();186 check_child_death();
187 }
188
185 next_think_time = start_time + kGameLogicDelay;189 next_think_time = start_time + kGameLogicDelay;
186 }190 }
187191
@@ -190,7 +194,13 @@
190 forefather->do_draw(rt);194 forefather->do_draw(rt);
191 rt.blit((app->get_mouse_position() - Vector2i(3, 7)),195 rt.blit((app->get_mouse_position() - Vector2i(3, 7)),
192 app->is_mouse_pressed() ? default_cursor_click_ : default_cursor_);196 app->is_mouse_pressed() ? default_cursor_click_ : default_cursor_);
193 forefather->do_tooltip();197
198 if (is_modal()) {
199 do_tooltip();
200 } else {
201 forefather->do_tooltip();
202 }
203
194 g_gr->refresh();204 g_gr->refresh();
195 next_draw_time = start_time + draw_delay;205 next_draw_time = start_time + draw_delay;
196 }206 }
@@ -594,8 +604,7 @@
594 * false otherwise.604 * false otherwise.
595 */605 */
596bool Panel::handle_tooltip() {606bool Panel::handle_tooltip() {
597 RenderTarget& rt = *g_gr->get_render_target();607 return draw_tooltip(tooltip());
598 return draw_tooltip(rt, tooltip());
599}608}
600609
601/**610/**
@@ -1060,13 +1069,15 @@
1060/**1069/**
1061 * Draw the tooltip. Return true on success1070 * Draw the tooltip. Return true on success
1062 */1071 */
1063bool Panel::draw_tooltip(RenderTarget& dst, const std::string& text) {1072bool Panel::draw_tooltip(const std::string& text) {
1064 if (text.empty()) {1073 if (text.empty()) {
1065 return false;1074 return false;
1066 }1075 }
1076
1077 RenderTarget& dst = *g_gr->get_render_target();
1067 std::string text_to_render = text;1078 std::string text_to_render = text;
1068 if (!is_richtext(text_to_render)) {1079 if (!is_richtext(text_to_render)) {
1069 text_to_render = as_tooltip(text);1080 text_to_render = as_tooltip(text_to_render);
1070 }1081 }
10711082
1072 constexpr uint32_t kTipWidthMax = 360;1083 constexpr uint32_t kTipWidthMax = 360;
10731084
=== modified file 'src/ui_basic/panel.h'
--- src/ui_basic/panel.h 2018-04-27 06:11:05 +0000
+++ src/ui_basic/panel.h 2018-05-31 17:12:19 +0000
@@ -311,7 +311,7 @@
311 static void play_new_chat_member();311 static void play_new_chat_member();
312 static void play_new_chat_message();312 static void play_new_chat_message();
313313
314 static bool draw_tooltip(RenderTarget&, const std::string& text);314 static bool draw_tooltip(const std::string& text);
315 void draw_background(RenderTarget& dst, const UI::PanelStyleInfo&);315 void draw_background(RenderTarget& dst, const UI::PanelStyleInfo&);
316 void draw_background(RenderTarget& dst, Recti rect, const UI::PanelStyleInfo&);316 void draw_background(RenderTarget& dst, Recti rect, const UI::PanelStyleInfo&);
317317
318318
=== modified file 'src/wui/game_main_menu_save_game.cc'
--- src/wui/game_main_menu_save_game.cc 2018-05-22 06:54:12 +0000
+++ src/wui/game_main_menu_save_game.cc 2018-05-31 17:12:19 +0000
@@ -65,7 +65,8 @@
65 cancel_(&buttons_box_, "cancel", 0, 0, 0, 0, UI::ButtonStyle::kWuiSecondary, _("Cancel")),65 cancel_(&buttons_box_, "cancel", 0, 0, 0, 0, UI::ButtonStyle::kWuiSecondary, _("Cancel")),
66 ok_(&buttons_box_, "ok", 0, 0, 0, 0, UI::ButtonStyle::kWuiPrimary, _("OK")),66 ok_(&buttons_box_, "ok", 0, 0, 0, 0, UI::ButtonStyle::kWuiPrimary, _("OK")),
6767
68 curdir_(kSaveDir) {68 curdir_(kSaveDir),
69 illegal_filename_tooltip_(FileSystem::illegal_filename_tooltip()) {
6970
70 layout();71 layout();
7172
@@ -133,8 +134,9 @@
133134
134void GameMainMenuSaveGame::edit_box_changed() {135void GameMainMenuSaveGame::edit_box_changed() {
135 // Prevent the user from creating nonsense directory names, like e.g. ".." or "...".136 // Prevent the user from creating nonsense directory names, like e.g. ".." or "...".
136 const bool is_legal_filename = LayeredFileSystem::is_legal_filename(filename_editbox_.text());137 const bool is_legal_filename = FileSystem::is_legal_filename(filename_editbox_.text());
137 ok_.set_enabled(is_legal_filename);138 ok_.set_enabled(is_legal_filename);
139 filename_editbox_.set_tooltip(is_legal_filename ? "" : illegal_filename_tooltip_);
138 load_or_save_.delete_button()->set_enabled(false);140 load_or_save_.delete_button()->set_enabled(false);
139 load_or_save_.clear_selections();141 load_or_save_.clear_selections();
140}142}
141143
=== modified file 'src/wui/game_main_menu_save_game.h'
--- src/wui/game_main_menu_save_game.h 2018-05-10 15:57:43 +0000
+++ src/wui/game_main_menu_save_game.h 2018-05-31 17:12:19 +0000
@@ -79,6 +79,7 @@
79 UI::Button cancel_, ok_;79 UI::Button cancel_, ok_;
8080
81 std::string curdir_;81 std::string curdir_;
82 const std::string illegal_filename_tooltip_;
82};83};
8384
84#endif // end of include guard: WL_WUI_GAME_MAIN_MENU_SAVE_GAME_H85#endif // end of include guard: WL_WUI_GAME_MAIN_MENU_SAVE_GAME_H

Subscribers

People subscribed via source and target branches

to status/vote changes: