Merge lp:~widelands-dev/widelands/bug-1390793 into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 7538
Proposed branch: lp:~widelands-dev/widelands/bug-1390793
Merge into: lp:widelands
Diff against target: 4352 lines (+1701/-1382)
44 files modified
src/editor/CMakeLists.txt (+3/-1)
src/editor/editorinteractive.h (+2/-1)
src/editor/ui_menus/editor_main_menu.cc (+1/-1)
src/editor/ui_menus/editor_main_menu_load_map.cc (+26/-222)
src/editor/ui_menus/editor_main_menu_load_map.h (+10/-28)
src/editor/ui_menus/editor_main_menu_load_or_save_map.cc (+218/-0)
src/editor/ui_menus/editor_main_menu_load_or_save_map.h (+71/-0)
src/editor/ui_menus/editor_main_menu_map_options.cc (+161/-81)
src/editor/ui_menus/editor_main_menu_map_options.h (+32/-11)
src/editor/ui_menus/editor_main_menu_new_map.cc (+1/-1)
src/editor/ui_menus/editor_main_menu_random_map.cc (+1/-1)
src/editor/ui_menus/editor_main_menu_save_map.cc (+159/-297)
src/editor/ui_menus/editor_main_menu_save_map.h (+14/-25)
src/editor/ui_menus/editor_main_menu_save_map_make_directory.cc (+39/-50)
src/editor/ui_menus/editor_main_menu_save_map_make_directory.h (+13/-9)
src/editor/ui_menus/editor_tool_menu.cc (+8/-1)
src/logic/map.cc (+1/-2)
src/logic/map.h (+4/-3)
src/logic/production_program.cc (+1/-1)
src/ui_basic/helpwindow.cc (+1/-1)
src/ui_basic/messagebox.cc (+2/-2)
src/ui_basic/multilineeditbox.cc (+36/-4)
src/ui_basic/multilineeditbox.h (+3/-1)
src/ui_fsmenu/CMakeLists.txt (+1/-3)
src/ui_fsmenu/campaign_select.cc (+42/-43)
src/ui_fsmenu/campaign_select.h (+9/-3)
src/ui_fsmenu/launch_mpg.h (+1/-1)
src/ui_fsmenu/load_map_or_game.cc (+15/-18)
src/ui_fsmenu/load_map_or_game.h (+9/-39)
src/ui_fsmenu/loadgame.cc (+32/-30)
src/ui_fsmenu/loadgame.h (+4/-2)
src/ui_fsmenu/mapselect.cc (+179/-413)
src/ui_fsmenu/mapselect.h (+34/-66)
src/wlapplication.cc (+1/-12)
src/wui/CMakeLists.txt (+16/-0)
src/wui/login_box.cc (+1/-1)
src/wui/mapdata.h (+197/-0)
src/wui/mapdetails.cc (+154/-0)
src/wui/mapdetails.h (+64/-0)
src/wui/maptable.cc (+82/-0)
src/wui/maptable.h (+45/-0)
src/wui/story_message_box.cc (+1/-1)
src/wui/suggested_teams_box.cc (+4/-4)
src/wui/suggested_teams_box.h (+3/-3)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-1390793
Reviewer Review Type Date Requested Status
TiborB Approve
GunChleoc Needs Resubmitting
Review via email: mp+254558@code.launchpad.net

Description of the change

This branch still has 2 issues:

1. Load/Save Map screens start with a correctly sorted table, but when a table header is clicked, the sorting becomes garbage. I haven't been able to find out why - ideas are welcome.

2. For Map Options -> Suggested Teams, I need images in the Listselect. This will be possible when the fh1 branch has been merged, so I left the implementation of this tab blank with a comment in it. We should create a bug report for this before merging.

Summary:

Reworked the editor's Load/Save Map and Map Origins dialogs. Set Map Origin is now a tool.

General UI Changes:
- New button graphic for main options in the wui.
- Removed some superfluous tooltips.
- Multiline edit boxes now have the same background and borders as edit boxes.

UI Changes for Load/Save Map:
- Added toggle for filenames/Map names.
- Load Map: Added localize/don't localize map names checkbox.
- Save Map: now uses Maptable and always shows the details for the map to be saved rather than the file selected on the list.
- Save Map: Added Map Options button.
- Save Map: Map name is now independent of filename when saving. Changing the directory does no longer affect the editbox.

UI Changes for Map Options:
- Moved "Set origin" tool to Tools menu.
- Map Options now is a tabbed dialog. Everything for the map's elemental packet is now editable (e.g. tags and hints), except for the Suggested Teams, which is still a mockup.

Refactoring:
- Shifted Map list and details into two new classes, which are now used both by the "New Game" and the editor's "Load Map" functions. Shifted common functionality from UI screens into MapData.
- Common Details panel for all load/save map screens, including editor and ui-fsmenu.
- New common super class for Editor Load/Save Map.
- Switched Map Options and Map Details contents to Box layout.

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

I see you spend quite a lot of time on this, I am not able to judge the code, but from user interface point of view - few comments and/or ideas.

1. Why is there the seafaring checkbox - should not be this be recognized from the map itself - if there are portspaces then the map is seafaring, right?

2. "The name of this map" could be changed to "The name of the map. Use the Map Options to change it". Also for Author and Descriptions there could have tooltips "Use the Map Options to update"

3. Load Map dialog window: I could add "File:" item below "Map:" item (right hand column)

4. Generally I dont like positioning of changer "Show filenames/ map names" on the top left corner, but I dont know what would be the better position.

5. How can I say what origins are currently defined? it might be listed in "Map options" window, below "Size: ... x ..." information. Or even better - but more work - it would be nice to have fourth tab available with map preview, that would reflect the selected origins. But this is perhpas out of scope of your work now.

6. If 5 were implemented, the first table of "Map Options" could have a pen on the bookmark and the new tab with preview, could have a map on bookmark (or whatever is it called)

7. re: "Save Map: now uses Maptable and always shows the details for the map to be saved rather than the file selected on the list." - this migh be confusing. List of existing maps is something secondary that might be used and might not. Main part is the Map Options. Could we add "Filename" (or "Current filename") item under "Map:" name - if filename was ever defined and leave "Filename" textbox empty and rename it to "New Filename" - to indicate that no need to bother with this if you are just modifying existing the map?

8. textbox with filename on "Save Map" window could have a tooltip "Type custom name or use above list to everwrite existing map file"

Revision history for this message
GunChleoc (gunchleoc) wrote :

Why don't you try having a look at the code? I don't understand all the GL stuff SirVer is doing either, but I review it anyway, because there is no-one else to do it. Granted, this branch might be a bit too big to start doing your first code review.

1. The seafaring checkbox is for the filter checkbox when players want to select a map to start a new game. Analyzing all the maps there would be to time consuming. So, this is part of the "preload" packet that lets players see information about the map without loading the whole map.

2. I am using the same element for starting new games - I think editors should be able to figure this out? The tooltip is only there to give the player the English or translated name of the map, and only makes a difference if you don't choose English as your interface language.

3. I don't think I have the space on small screens - e.g. set your Widelands to 800x600 resolution, then go to Single Player -> New Game and pick Trident of Fire. The map details used here are the same as in the editor, to cut down on code repetition.

4. I agree, I am open to suggestions :)

5 - 6. Yes, out of scope. Can you open a new bug please? I am chasing deadlines this week.

7. Without the list of maps, you won't be able to pick a directory. I am against displaying map details for anything that you pick on the list, because as you say yourself, the map options for the map to be saved it the information needed here. What would be the use of displaying the file name twice? I'm not sure I understand what you're getting at here :( The filename edit field is pre-filled with the last filename that the map was saved under, so it's the current filename anyway. If it's a new map, it picks "No Name" as a filename.

8. Good idea. I was thinking "Type a new name, or select a map from the list to overwrite an existing map file." This isn't entirely correct though - if this map has been saved before, it will be overwritten (unless the user changes the contents of the edit box) without the need to select something from the list. My brain is mush at the moment, so I'm open to suggestions :)

Revision history for this message
TiborB (tiborb95) wrote :

I am afraid to claim that I have checked something and it looks good when I dont understand it at least to some degree. But of course I see that we have too much branches waiting for review and something should be done with this....

1. I understand seafaring checkbox when loading game - but dont understand it when saving the game. On save this info should be generated automatically and saved into map.

2. Of course everybody will figure it out at the end, but still I think the logic&ergonomy is not as polished as could be. But the situation is not getting workse, so OK....

7. I was partially heading to something like "save" and "save as" in other programs. BTW, does something like ctrl+S work in editor (without invoking any kind of menu)? I meant to distinguish the small edit of a map and significant changes to a map. Just an idea.... Or maybe there could be a "floppy" icon somewhere which would only save the map without any queries or so. Just another idea :)

But OK, at the end there are two outstanding issues : broken sorting of filenames and that "show *names " button. And I noticed, the sorting is broken even also on "Pl." column. And on third column too.

Revision history for this message
GunChleoc (gunchleoc) wrote :

> 1. I understand seafaring checkbox when loading game - but dont understand it when saving the game. On save this info should be generated automatically and saved into map.

Automatially generating this tag is a good idea :)

We should do this in a new branch though, this branch is already big
enough. Time for a new bug.

> 2. Of course everybody will figure it out at the end, but still I think the logic&ergonomy is not as polished as could be. But the situation is not getting workse, so OK....

Maybe we should solicit some feedback on the forum again once this
branch has been merged for a while, to see if it is easy or hard to
figure out.

> 7. I was partially heading to something like "save" and "save as" in other programs. BTW, does something like ctrl+S work in editor (without invoking any kind of menu)? I meant to distinguish the small edit of a map and significant changes to a map. Just an idea.... Or maybe there could be a "floppy" icon somewhere which would only save the map without any queries or so. Just another idea :)

CRTL+S would certainly be nice, and have it pop up something only if the
map is still called "No Name". Time for a new bug.

> But OK, at the end there are two outstanding issues : broken sorting of filenames and that "show *names " button. And I noticed, the sorting is broken even also on "Pl." column. And on third column too.

Yes, the sorting is messed up for any table column. Would you like to
have a go at looking at the sorting algorithm I used? It is probably
someting really stupid and obvious once we spot it.

Revision history for this message
TiborB (tiborb95) wrote :

It would be niced if we could make some UI tests with users that never used/played widelands. But of course also discussion on forum could bring good ideas and feedback.

2 bugreports created :)

I will look at the sorting but this is something brand new for me...

Revision history for this message
TiborB (tiborb95) wrote :

I tried really hard - but it is too complicated for me, sorry

Of course I learned something but still to no avail :(

Revision history for this message
GunChleoc (gunchleoc) wrote :

Thanks for having a look. Glad that you learned something and didn't waste your time :)

If nobody else finds it, I will have a look some other time, after forgetting what the code is about. Forgetting might help me to spot it.

Revision history for this message
GunChleoc (gunchleoc) wrote :

The table sorting bug should be fixed now.

review: Needs Resubmitting
Revision history for this message
TiborB (tiborb95) wrote :

you left one NOCOM in code.

set starting position - you need to click twice to make it work, is it intended?

Revision history for this message
GunChleoc (gunchleoc) wrote :

I have removed the NOCOM, thanks.

I don't know what you mean by set starting position - I tried both map origin and players, and I don't have to click twice.

The map origin tool is a bit confusing, because there is no marker on the map to indicate that it actually has been set. It would be nice to have an "x marks the spot" overlay for it.

Revision history for this message
TiborB (tiborb95) wrote :

GunChleoc, I was wrong with that 0,0 coordinates, it works fine...

I went over the code, I really are not able to completely check&understand it, but it looks good to me..

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

Yep, it's a lot of code. Thanks for the review :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'pics/but5.png'
2Binary files pics/but5.png 1970-01-01 00:00:00 +0000 and pics/but5.png 2015-10-03 07:55:28 +0000 differ
3=== added file 'pics/editor_menu_tool_set_origin.png'
4Binary files pics/editor_menu_tool_set_origin.png 1970-01-01 00:00:00 +0000 and pics/editor_menu_tool_set_origin.png 2015-10-03 07:55:28 +0000 differ
5=== modified file 'src/editor/CMakeLists.txt'
6--- src/editor/CMakeLists.txt 2015-01-31 16:03:59 +0000
7+++ src/editor/CMakeLists.txt 2015-10-03 07:55:28 +0000
8@@ -51,6 +51,8 @@
9 ui_menus/editor_main_menu.h
10 ui_menus/editor_main_menu_load_map.cc
11 ui_menus/editor_main_menu_load_map.h
12+ ui_menus/editor_main_menu_load_or_save_map.cc
13+ ui_menus/editor_main_menu_load_or_save_map.h
14 ui_menus/editor_main_menu_map_options.cc
15 ui_menus/editor_main_menu_map_options.h
16 ui_menus/editor_main_menu_new_map.cc
17@@ -101,7 +103,7 @@
18 ui_basic
19 ui_fsmenu
20 widelands_ball_of_mud
21- wui
22+ wui_common
23 wui_mapview_pixelfunctions
24 wui_overlay_manager
25 )
26
27=== modified file 'src/editor/editorinteractive.h'
28--- src/editor/editorinteractive.h 2014-10-14 06:30:20 +0000
29+++ src/editor/editorinteractive.h 2015-10-03 07:55:28 +0000
30@@ -80,7 +80,8 @@
31 place_immovable(delete_immovable),
32 place_bob(delete_bob),
33 increase_resources(decrease_resources, set_resources),
34- set_port_space(unset_port_space)
35+ set_port_space(unset_port_space),
36+ set_origin()
37 {}
38 EditorTool & current() const {return *current_pointer;}
39 using ToolVector = std::vector<EditorTool *>;
40
41=== modified file 'src/editor/ui_menus/editor_main_menu.cc'
42--- src/editor/ui_menus/editor_main_menu.cc 2015-02-20 11:32:33 +0000
43+++ src/editor/ui_menus/editor_main_menu.cc 2015-10-03 07:55:28 +0000
44@@ -82,7 +82,7 @@
45 m_button_exit_editor
46 (this, "exit",
47 hmargin, vmargin + 6 * (height + vspacing), width, height,
48- g_gr->images().get("pics/but0.png"),
49+ g_gr->images().get("pics/but5.png"),
50 _("Exit Editor"))
51 {
52 m_button_new_map.sigclicked.connect(boost::bind(&EditorMainMenu::new_map_btn, this));
53
54=== modified file 'src/editor/ui_menus/editor_main_menu_load_map.cc'
55--- src/editor/ui_menus/editor_main_menu_load_map.cc 2014-11-30 18:49:38 +0000
56+++ src/editor/ui_menus/editor_main_menu_load_map.cc 2015-10-03 07:55:28 +0000
57@@ -1,5 +1,5 @@
58 /*
59- * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team
60+ * Copyright (C) 2002-2004, 2006-2015 by the Widelands Development Team
61 *
62 * This program is free software; you can redistribute it and/or
63 * modify it under the terms of the GNU General Public License
64@@ -19,134 +19,36 @@
65
66 #include "editor/ui_menus/editor_main_menu_load_map.h"
67
68-#include <cstdio>
69-#include <memory>
70-#include <string>
71-
72-#include <boost/format.hpp>
73-
74 #include "base/i18n.h"
75-#include "base/wexception.h"
76 #include "editor/editorinteractive.h"
77-#include "editor/tools/editor_set_starting_pos_tool.h"
78-#include "graphic/graphic.h"
79 #include "io/filesystem/layered_filesystem.h"
80-#include "logic/building.h"
81-#include "logic/editor_game_base.h"
82-#include "map_io/map_loader.h"
83 #include "map_io/widelands_map_loader.h"
84-#include "profile/profile.h"
85-#include "ui_basic/button.h"
86-#include "ui_basic/editbox.h"
87-#include "ui_basic/listselect.h"
88-#include "ui_basic/multilinetextarea.h"
89-#include "ui_basic/progresswindow.h"
90-#include "ui_basic/textarea.h"
91-#include "wui/overlay_manager.h"
92-
93-using Widelands::WidelandsMapLoader;
94+#include "wui/mapdetails.h"
95+#include "wui/maptable.h"
96
97 /**
98 * Create all the buttons etc...
99 */
100-MainMenuLoadMap::MainMenuLoadMap(EditorInteractive & parent)
101- : UI::Window(&parent, "load_map_menu", 0, 0, 560, 300, _("Load Map"))
102-{
103- int32_t const spacing = 5;
104- int32_t const offsx = spacing;
105- int32_t const offsy = 10;
106- int32_t posx = offsx;
107- int32_t posy = offsy;
108- int32_t const descr_label_w = 100;
109-
110- m_ls = new UI::Listselect<const char *>
111- (this,
112- posx, posy,
113- get_inner_w() / 2 - spacing, get_inner_h() - spacing - offsy - 40);
114- m_ls->selected.connect(boost::bind(&MainMenuLoadMap::selected, this, _1));
115- m_ls->double_clicked.connect(boost::bind(&MainMenuLoadMap::double_clicked, this, _1));
116- m_ls->focus();
117-
118- posx = get_inner_w() / 2 + spacing;
119- new UI::Textarea
120- (this, posx, posy, descr_label_w, 20, _("Name:"), UI::Align_CenterLeft);
121- m_name =
122- new UI::MultilineTextarea
123- (this, posx + descr_label_w, posy, 200, 40, "---", UI::Align_CenterLeft);
124- posy += 40 + spacing;
125-
126- new UI::Textarea
127- (this, posx, posy, 150, 20, _("Authors:"), UI::Align_CenterLeft);
128- m_author =
129- new UI::Textarea
130- (this, posx + descr_label_w, posy, 200, 20, "---", UI::Align_CenterLeft);
131- posy += 20 + spacing;
132-
133- new UI::Textarea
134- (this, posx, posy, descr_label_w, 20, _("Size:"), UI::Align_CenterLeft);
135- m_size =
136- new UI::Textarea
137- (this, posx + descr_label_w, posy, 200, 20, "---", UI::Align_CenterLeft);
138- posy += 20 + spacing;
139-
140- new UI::Textarea
141- (this, posx, posy, descr_label_w, 20, _("Players:"), UI::Align_CenterLeft);
142- m_nrplayers =
143- new UI::Textarea
144- (this, posx + descr_label_w, posy, 200, 20, "---", UI::Align_CenterLeft);
145- posy += 20 + spacing;
146-
147-
148- new UI::Textarea
149- (this, posx, posy, descr_label_w, 20, _("Descr:"), UI::Align_CenterLeft);
150- m_descr =
151- new UI::MultilineTextarea
152- (this,
153- posx + descr_label_w, posy,
154- get_inner_w() - posx - spacing - descr_label_w,
155- get_inner_h() - posy - spacing - 40,
156- "---", UI::Align_CenterLeft);
157-
158- posy = get_inner_h() - 30;
159-
160- m_ok_btn = new UI::Button
161- (this, "ok",
162- posx, posy,
163- get_inner_w() / 4 - 1.5 * spacing, 20,
164- g_gr->images().get("pics/but0.png"),
165- _("OK"),
166- std::string(),
167- false);
168- m_ok_btn->sigclicked.connect(boost::bind(&MainMenuLoadMap::clicked_ok, this));
169-
170- UI::Button * cancelbtn = new UI::Button
171- (this, "cancel",
172- posx + get_inner_w() / 4 - spacing / 2, posy,
173- get_inner_w() / 4 - 1.5 * spacing, 20,
174- g_gr->images().get("pics/but1.png"),
175- _("Cancel"));
176- cancelbtn->sigclicked.connect(boost::bind(&MainMenuLoadMap::die, this));
177-
178- m_basedir = "maps";
179- m_curdir = "maps";
180-
181- fill_list();
182-
183- center_to_parent();
184- move_to_top();
185+MainMenuLoadMap::MainMenuLoadMap(EditorInteractive& parent)
186+ : MainMenuLoadOrSaveMap(parent, "load_map_menu", _("Load Map")) {
187+
188+ table_.selected.connect(boost::bind(&MainMenuLoadMap::entry_selected, this));
189+ table_.double_clicked.connect(boost::bind(&MainMenuLoadMap::clicked_ok, boost::ref(*this)));
190+
191+ ok_.sigclicked.connect(boost::bind(&MainMenuLoadMap::clicked_ok, this));
192+ cancel_.sigclicked.connect(boost::bind(&MainMenuLoadMap::die, this));
193 }
194
195-
196 void MainMenuLoadMap::clicked_ok() {
197- const char * const filename(m_ls->get_selected());
198-
199- if (g_fs->is_directory(filename) && !WidelandsMapLoader::is_widelands_map(filename)) {
200- m_curdir = filename;
201- m_ls->clear();
202- m_mapfiles.clear();
203- fill_list();
204+ assert(ok_.enabled());
205+ assert(table_.has_selection());
206+ const MapData& mapdata = maps_data_[table_.get_selected()];
207+ if (g_fs->is_directory(mapdata.filename) &&
208+ !Widelands::WidelandsMapLoader::is_widelands_map(mapdata.filename)) {
209+ curdir_ = mapdata.filename;
210+ fill_table();
211 } else {
212- dynamic_cast<EditorInteractive&>(*get_parent()).load(filename);
213+ dynamic_cast<EditorInteractive&>(*get_parent()).load(mapdata.filename);
214 die();
215 }
216 }
217@@ -154,110 +56,12 @@
218 /**
219 * Called when a entry is selected
220 */
221-void MainMenuLoadMap::selected(uint32_t) {
222- const char * const name = m_ls->get_selected();
223-
224- m_ok_btn->set_enabled(true);
225-
226- if (!g_fs->is_directory(name) || WidelandsMapLoader::is_widelands_map(name)) {
227- Widelands::Map map;
228- {
229- std::unique_ptr<Widelands::MapLoader> map_loader = map.get_correct_loader(name);
230- map_loader->preload_map(true); // This has worked before, no problem.
231- }
232-
233- // Translate the map data
234- i18n::Textdomain td("maps");
235- m_name ->set_text(map.get_name());
236- m_name ->set_tooltip(map.get_name());
237- m_author->set_text(map.get_author());
238- m_descr ->set_text
239- (_(map.get_description()) +
240- (map.get_hint().empty() ? "" : (std::string("\n\n") + _(map.get_hint()))));
241-
242- m_nrplayers->set_text(std::to_string(static_cast<unsigned int>(map.get_nrplayers())));
243-
244- m_size ->set_text((boost::format(_("%1$ix%2$i"))
245- % map.get_width()
246- % map.get_height()).str());
247+void MainMenuLoadMap::entry_selected() {
248+ bool has_selection = table_.has_selection();
249+ ok_.set_enabled(has_selection);
250+ if (!has_selection) {
251+ map_details_.clear();
252 } else {
253- m_name ->set_text("");
254- m_name ->set_tooltip("");
255- m_author ->set_text("");
256- m_descr ->set_text("");
257- m_nrplayers->set_text("");
258- m_size ->set_text("");
259- }
260-}
261-
262-/**
263- * An entry has been doubleclicked
264- */
265-void MainMenuLoadMap::double_clicked(uint32_t) {clicked_ok();}
266-
267-/**
268- * fill the file list
269- */
270-void MainMenuLoadMap::fill_list() {
271- // Fill it with all files we find.
272- m_mapfiles = g_fs->list_directory(m_curdir);
273-
274- // First, we add all directories. We manually add the parent directory.
275- if (m_curdir != m_basedir) {
276-#ifndef _WIN32
277- m_parentdir = m_curdir.substr(0, m_curdir.rfind('/'));
278-#else
279- m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));
280-#endif
281-
282- m_ls->add
283- /** TRANSLATORS: Parent directory */
284- ((boost::format("\\<%s\\>") % _("parent")).str(),
285- m_parentdir.c_str(),
286- g_gr->images().get("pics/ls_dir.png"));
287- }
288-
289- const FilenameSet::const_iterator mapfiles_end = m_mapfiles.end();
290- for
291- (FilenameSet::const_iterator pname = m_mapfiles.begin();
292- pname != mapfiles_end;
293- ++pname)
294- {
295- const char * const name = pname->c_str();
296- if
297- (strcmp(FileSystem::fs_filename(name), ".") &&
298- strcmp(FileSystem::fs_filename(name), "..") &&
299- g_fs->is_directory(name) &&
300- !WidelandsMapLoader::is_widelands_map(name))
301-
302- m_ls->add
303- (FileSystem::fs_filename(name),
304- name,
305- g_gr->images().get("pics/ls_dir.png"));
306- }
307-
308- Widelands::Map map;
309-
310- for
311- (FilenameSet::const_iterator pname = m_mapfiles.begin();
312- pname != mapfiles_end;
313- ++pname)
314- {
315- char const * const name = pname->c_str();
316- std::unique_ptr<Widelands::MapLoader> map_loader = map.get_correct_loader(name);
317- if (map_loader.get() != nullptr) {
318- try {
319- map_loader->preload_map(true);
320- m_ls->add
321- (FileSystem::filename_without_ext(name),
322- name,
323- g_gr->images().get
324- (dynamic_cast<WidelandsMapLoader*>(map_loader.get())
325- ? "pics/ls_wlmap.png" : "pics/ls_s2map.png"));
326- } catch (const WException &) {} // we simply skip illegal entries
327- }
328- }
329-
330- if (m_ls->size())
331- m_ls->select(0);
332+ map_details_.update(maps_data_[table_.get_selected()], !cb_dont_localize_mapnames_->get_state());
333+ }
334 }
335
336=== modified file 'src/editor/ui_menus/editor_main_menu_load_map.h'
337--- src/editor/ui_menus/editor_main_menu_load_map.h 2014-09-25 08:58:07 +0000
338+++ src/editor/ui_menus/editor_main_menu_load_map.h 2015-10-03 07:55:28 +0000
339@@ -1,5 +1,5 @@
340 /*
341- * Copyright (C) 2002-2004, 2006, 2008-2011 by the Widelands Development Team
342+ * Copyright (C) 2002-2004, 2006, 2008-2015 by the Widelands Development Team
343 *
344 * This program is free software; you can redistribute it and/or
345 * modify it under the terms of the GNU General Public License
346@@ -20,40 +20,22 @@
347 #ifndef WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_LOAD_MAP_H
348 #define WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_LOAD_MAP_H
349
350-#include "io/filesystem/filesystem.h"
351-#include "ui_basic/window.h"
352+#include <string>
353
354-struct EditorInteractive;
355-namespace UI {
356-struct Button;
357-template <typename T> struct Listselect;
358-struct Textarea;
359-struct MultilineTextarea;
360-}
361+#include "editor/editorinteractive.h"
362+#include "editor/ui_menus/editor_main_menu_load_or_save_map.h"
363
364 /**
365 * Choose a filename and save your brand new created map
366 */
367-struct MainMenuLoadMap : public UI::Window {
368- MainMenuLoadMap(EditorInteractive &);
369+struct MainMenuLoadMap : public MainMenuLoadOrSaveMap {
370+ MainMenuLoadMap(EditorInteractive& parent);
371+
372+protected:
373+ void clicked_ok() override;
374
375 private:
376- void clicked_ok();
377- void selected (uint32_t);
378- void double_clicked(uint32_t);
379-
380- void fill_list();
381-
382- UI::MultilineTextarea * m_name;
383- UI::Textarea * m_author, * m_size, * m_nrplayers;
384- UI::MultilineTextarea * m_descr;
385- UI::Listselect<const char *> * m_ls;
386- UI::Button * m_ok_btn;
387-
388- std::string m_basedir;
389- std::string m_curdir;
390- std::string m_parentdir;
391- FilenameSet m_mapfiles;
392+ void entry_selected();
393 };
394
395 #endif // end of include guard: WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_LOAD_MAP_H
396
397=== added file 'src/editor/ui_menus/editor_main_menu_load_or_save_map.cc'
398--- src/editor/ui_menus/editor_main_menu_load_or_save_map.cc 1970-01-01 00:00:00 +0000
399+++ src/editor/ui_menus/editor_main_menu_load_or_save_map.cc 2015-10-03 07:55:28 +0000
400@@ -0,0 +1,218 @@
401+/*
402+ * Copyright (C) 2002-2004, 2006-2015 by the Widelands Development Team
403+ *
404+ * This program is free software; you can redistribute it and/or
405+ * modify it under the terms of the GNU General Public License
406+ * as published by the Free Software Foundation; either version 2
407+ * of the License, or (at your option) any later version.
408+ *
409+ * This program is distributed in the hope that it will be useful,
410+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
411+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
412+ * GNU General Public License for more details.
413+ *
414+ * You should have received a copy of the GNU General Public License
415+ * along with this program; if not, write to the Free Software
416+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
417+ *
418+ */
419+
420+#include "editor/ui_menus/editor_main_menu_load_or_save_map.h"
421+
422+#include <cstdio>
423+#include <memory>
424+
425+#include "base/i18n.h"
426+#include "base/wexception.h"
427+#include "editor/editorinteractive.h"
428+#include "graphic/graphic.h"
429+#include "io/filesystem/filesystem.h"
430+#include "io/filesystem/layered_filesystem.h"
431+#include "map_io/widelands_map_loader.h"
432+
433+MainMenuLoadOrSaveMap::MainMenuLoadOrSaveMap(EditorInteractive& parent,
434+ const std::string& name,
435+ const std::string& title)
436+ : UI::Window(&parent, name, 0, 0, parent.get_inner_w() - 40, parent.get_inner_h() - 40, title),
437+
438+ // Values for alignment and size
439+ padding_(4),
440+ buth_(20),
441+ tablex_(padding_),
442+ tabley_(buth_ + 2 * padding_),
443+ tablew_(get_inner_w() * 7 / 12),
444+ tableh_(get_inner_h() - tabley_ - 3 * buth_ - 2 * padding_),
445+ right_column_x_(tablew_ + 2 * padding_),
446+ butw_((get_inner_w() - right_column_x_ - 2 * padding_) / 2),
447+
448+ table_(this, tablex_, tabley_, tablew_, tableh_, false),
449+ map_details_(
450+ this, right_column_x_, tabley_, get_inner_w() - right_column_x_ - padding_, tableh_),
451+ ok_(this,
452+ "ok",
453+ get_inner_w() / 2 - butw_ - padding_,
454+ get_inner_h() - padding_ - buth_,
455+ butw_,
456+ buth_,
457+ g_gr->images().get("pics/but5.png"),
458+ _("OK")),
459+ cancel_(this,
460+ "cancel",
461+ get_inner_w() / 2 + padding_,
462+ get_inner_h() - padding_ - buth_,
463+ butw_,
464+ buth_,
465+ g_gr->images().get("pics/but1.png"),
466+ _("Cancel")),
467+ basedir_("maps"),
468+ has_translated_mapname_(false),
469+ showing_mapames_(false) {
470+ curdir_ = basedir_;
471+
472+ UI::Box* vbox = new UI::Box(this, tablex_, padding_, UI::Box::Horizontal, padding_, get_w());
473+ show_mapnames_ = new UI::Button(vbox,
474+ "show_mapnames",
475+ 0,
476+ 0,
477+ butw_,
478+ buth_,
479+ g_gr->images().get("pics/but1.png"),
480+ _("Show Map Names"));
481+ vbox->add(show_mapnames_, UI::Box::AlignLeft, true);
482+
483+ cb_dont_localize_mapnames_ = new UI::Checkbox(vbox, Point(0, 0));
484+ cb_dont_localize_mapnames_->set_state(false);
485+ vbox->add_space(2 * padding_);
486+ vbox->add(cb_dont_localize_mapnames_, UI::Box::AlignLeft, true);
487+ vbox->add_space(padding_);
488+ UI::Textarea* ta_dont_localize_mapnames =
489+ /** TRANSLATORS: Checkbox title. If this checkbox is enabled, map names aren't translated. */
490+ new UI::Textarea(vbox, _("Show original map names"), UI::Align_CenterLeft);
491+ vbox->add(ta_dont_localize_mapnames, UI::Box::AlignLeft);
492+ vbox->set_size(get_inner_w(), buth_);
493+
494+ table_.set_column_compare(0, boost::bind(&MainMenuLoadOrSaveMap::compare_players, this, _1, _2));
495+ table_.set_column_compare(1, boost::bind(&MainMenuLoadOrSaveMap::compare_mapnames, this, _1, _2));
496+ table_.set_column_compare(2, boost::bind(&MainMenuLoadOrSaveMap::compare_size, this, _1, _2));
497+
498+
499+ table_.focus();
500+ fill_table();
501+
502+ // We don't need the unlocalizing option if there is nothing to unlocalize.
503+ // We know this after the list is filled.
504+ cb_dont_localize_mapnames_->set_visible(has_translated_mapname_);
505+ ta_dont_localize_mapnames->set_visible(has_translated_mapname_);
506+
507+ cb_dont_localize_mapnames_->changedto.connect(
508+ boost::bind(&MainMenuLoadOrSaveMap::fill_table, boost::ref(*this)));
509+ show_mapnames_->sigclicked.connect(
510+ boost::bind(&MainMenuLoadOrSaveMap::toggle_mapnames, boost::ref(*this)));
511+
512+ center_to_parent();
513+ move_to_top();
514+}
515+
516+
517+bool MainMenuLoadOrSaveMap::compare_players(uint32_t rowa, uint32_t rowb)
518+{
519+ return maps_data_[table_[rowa]].compare_players(maps_data_[table_[rowb]]);
520+}
521+
522+
523+bool MainMenuLoadOrSaveMap::compare_mapnames(uint32_t rowa, uint32_t rowb)
524+{
525+ return maps_data_[table_[rowa]].compare_names(maps_data_[table_[rowb]]);
526+}
527+
528+
529+bool MainMenuLoadOrSaveMap::compare_size(uint32_t rowa, uint32_t rowb)
530+{
531+ return maps_data_[table_[rowa]].compare_size(maps_data_[table_[rowb]]);
532+}
533+
534+
535+void MainMenuLoadOrSaveMap::toggle_mapnames() {
536+ if (showing_mapames_) {
537+ show_mapnames_->set_title(_("Show Map Names"));
538+ } else {
539+ show_mapnames_->set_title(_("Show Filenames"));
540+ }
541+ showing_mapames_ = !showing_mapames_;
542+ fill_table();
543+}
544+
545+/**
546+ * fill the file list
547+ */
548+void MainMenuLoadOrSaveMap::fill_table() {
549+ table_.clear();
550+ maps_data_.clear();
551+ has_translated_mapname_ = false;
552+
553+ // Fill it with all files we find.
554+ FilenameSet files = g_fs->list_directory(curdir_);
555+
556+ // If we are not at the top of the map directory hierarchy (we're not talking
557+ // about the absolute filesystem top!) we manually add ".."
558+ if (curdir_ != basedir_) {
559+ maps_data_.push_back(MapData::create_parent_dir(curdir_));
560+ }
561+
562+ MapData::DisplayType display_type;
563+ if (!showing_mapames_) {
564+ display_type = MapData::DisplayType::kFilenames;
565+ } else if (cb_dont_localize_mapnames_->get_state()) {
566+ display_type = MapData::DisplayType::kMapnames;
567+ } else {
568+ display_type = MapData::DisplayType::kMapnamesLocalized;
569+ }
570+
571+ Widelands::Map map;
572+
573+ for (const std::string& mapfilename : files) {
574+
575+ // Add map file (compressed) or map directory (uncompressed)
576+ if (Widelands::WidelandsMapLoader::is_widelands_map(mapfilename)) {
577+ std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(mapfilename);
578+ if (ml.get() != nullptr) {
579+ try {
580+ ml->preload_map(true);
581+
582+ if (!map.get_width() || !map.get_height()) {
583+ continue;
584+ }
585+
586+ MapData::MapType maptype;
587+
588+ if (map.scenario_types() & Widelands::Map::MP_SCENARIO ||
589+ map.scenario_types() & Widelands::Map::SP_SCENARIO) {
590+ maptype = MapData::MapType::kScenario;
591+ } else if (dynamic_cast<Widelands::WidelandsMapLoader*>(ml.get())) {
592+ maptype = MapData::MapType::kNormal;
593+ } else {
594+ maptype = MapData::MapType::kSettlers2;
595+ }
596+
597+ MapData mapdata(map, mapfilename, maptype, display_type);
598+
599+ has_translated_mapname_ =
600+ has_translated_mapname_ || (mapdata.name != mapdata.localized_name);
601+
602+ maps_data_.push_back(mapdata);
603+
604+ } catch (const WException&) {
605+ } // we simply skip illegal entries
606+ }
607+ } else if (g_fs->is_directory(mapfilename)) {
608+ // Add subdirectory to the list
609+ const char* fs_filename = FileSystem::fs_filename(mapfilename.c_str());
610+ if (!strcmp(fs_filename, ".") || !strcmp(fs_filename, ".."))
611+ continue;
612+ maps_data_.push_back(MapData::create_directory(mapfilename));
613+ }
614+ }
615+
616+ table_.fill(maps_data_, display_type);
617+ ok_.set_enabled(false);
618+}
619
620=== added file 'src/editor/ui_menus/editor_main_menu_load_or_save_map.h'
621--- src/editor/ui_menus/editor_main_menu_load_or_save_map.h 1970-01-01 00:00:00 +0000
622+++ src/editor/ui_menus/editor_main_menu_load_or_save_map.h 2015-10-03 07:55:28 +0000
623@@ -0,0 +1,71 @@
624+/*
625+ * Copyright (C) 2002-2004, 2006, 2008-2015 by the Widelands Development Team
626+ *
627+ * This program is free software; you can redistribute it and/or
628+ * modify it under the terms of the GNU General Public License
629+ * as published by the Free Software Foundation; either version 2
630+ * of the License, or (at your option) any later version.
631+ *
632+ * This program is distributed in the hope that it will be useful,
633+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
634+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
635+ * GNU General Public License for more details.
636+ *
637+ * You should have received a copy of the GNU General Public License
638+ * along with this program; if not, write to the Free Software
639+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
640+ *
641+ */
642+
643+#ifndef WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_LOAD_OR_SAVE_MAP_H
644+#define WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_LOAD_OR_SAVE_MAP_H
645+
646+#include <string>
647+
648+#include "editor/editorinteractive.h"
649+#include "ui_basic/button.h"
650+#include "ui_basic/checkbox.h"
651+#include "ui_basic/window.h"
652+#include "wui/mapdetails.h"
653+#include "wui/maptable.h"
654+
655+/**
656+ * Choose a filename and save your brand new created map
657+*/
658+struct MainMenuLoadOrSaveMap : public UI::Window {
659+ MainMenuLoadOrSaveMap(EditorInteractive& parent,
660+ const std::string& name,
661+ const std::string& title);
662+
663+protected:
664+ virtual void clicked_ok() = 0;
665+ void toggle_mapnames();
666+ void fill_table();
667+
668+ bool compare_players(uint32_t, uint32_t);
669+ bool compare_mapnames(uint32_t, uint32_t);
670+ bool compare_size(uint32_t, uint32_t);
671+
672+ // UI coordinates and spacers
673+ int32_t const padding_; // Common padding between panels
674+ int32_t const buth_; // Button dimensions
675+ int32_t const tablex_, tabley_, tablew_, tableh_;
676+ int32_t const right_column_x_;
677+ int32_t const butw_; // Button dimensions
678+
679+ MapTable table_;
680+ std::vector<MapData> maps_data_;
681+ MapDetails map_details_;
682+
683+ UI::Button ok_, cancel_;
684+
685+ const std::string basedir_;
686+ std::string curdir_;
687+
688+ bool has_translated_mapname_;
689+ UI::Checkbox* cb_dont_localize_mapnames_;
690+ bool showing_mapames_;
691+ UI::Button* show_mapnames_;
692+};
693+
694+#endif // end of include guard: WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_LOAD_OR_SAVE_MAP_H
695
696=== modified file 'src/editor/ui_menus/editor_main_menu_map_options.cc'
697--- src/editor/ui_menus/editor_main_menu_map_options.cc 2014-11-30 18:49:38 +0000
698+++ src/editor/ui_menus/editor_main_menu_map_options.cc 2015-10-03 07:55:28 +0000
699@@ -43,70 +43,116 @@
700 /**
701 * Create all the buttons etc...
702 */
703-MainMenuMapOptions::MainMenuMapOptions(EditorInteractive & parent)
704+MainMenuMapOptions::MainMenuMapOptions(EditorInteractive & parent, bool modal)
705 :
706 UI::Window
707 (&parent, "map_options",
708- 250, (parent.get_h() - 300) / 2, 305, 305,
709- _("Map Options"))
710-{
711-
712- int32_t const offsx = 5;
713- int32_t const offsy = 5;
714- int32_t const spacing = 3;
715- int32_t const height = 20;
716- int32_t posx = offsx;
717- int32_t posy = offsy;
718- UI::Textarea * ta = new UI::Textarea(this, posx, posy - 2, _("Map Name:"));
719- m_name =
720- new UI::EditBox
721- (this,
722- posx + ta->get_w() + spacing, posy,
723- get_inner_w() - (posx + ta->get_w() + spacing) - spacing, 20,
724- g_gr->images().get("pics/but1.png"));
725- m_name->changed.connect(boost::bind(&MainMenuMapOptions::changed, this, 0));
726- posy += height + spacing;
727- ta = new UI::Textarea(this, posx, posy - 2, _("Size:"));
728- m_size =
729- new UI::Textarea
730- (this, posx + ta->get_w() + spacing, posy - 2, "512x512");
731- posy += height + spacing;
732- ta = new UI::Textarea(this, posx, posy - 2, _("Nr Players:"));
733- m_nrplayers =
734- new UI::Textarea(this, posx + ta->get_w() + spacing, posy - 2, "1");
735- posy += height + spacing;
736- ta = new UI::Textarea(this, posx, posy - 2, _("Authors:"));
737- m_author =
738- new UI::EditBox
739- (this,
740- posx + ta->get_w() + spacing, posy,
741- get_inner_w() - (posx + ta->get_w() + spacing) - spacing, 20,
742- g_gr->images().get("pics/but1.png"));
743- m_author->changed.connect(boost::bind(&MainMenuMapOptions::changed, this, 1));
744- posy += height + spacing;
745- m_descr =
746- new UI::MultilineEditbox
747- (this,
748- posx, posy,
749- get_inner_w() - spacing - posx, get_inner_h() - 25 - spacing - posy,
750- parent.egbase().map().get_description());
751- m_descr->changed.connect(boost::bind(&MainMenuMapOptions::editbox_changed, this));
752-
753- UI::Button * btn =
754- new UI::Button
755- (this, "set_origin",
756- 5, get_inner_h() - 25, get_inner_w() - 10, 20,
757- g_gr->images().get("pics/but0.png"),
758- _("Set origin"),
759- _
760- ("Set the position that will have the coordinates (0, 0). This will "
761- "be the top-left corner of a generated minimap."));
762- btn->sigclicked.connect
763- (boost::bind
764- (&EditorInteractive::select_tool, &parent,
765- boost::ref(parent.tools.set_origin), EditorTool::First));
766+ 0, 0, 350, 520,
767+ _("Map Options")),
768+ padding_(4),
769+ indent_(10),
770+ labelh_(20),
771+ checkbox_space_(25),
772+ butw_((get_inner_w() - 3 * padding_) / 2),
773+ buth_(20),
774+ max_w_(get_inner_w() - 2 * padding_),
775+ ok_(
776+ this, "ok",
777+ padding_, get_inner_h() - padding_ - buth_,
778+ butw_, buth_,
779+ g_gr->images().get("pics/but5.png"),
780+ _("OK")),
781+ cancel_(
782+ this, "cancel",
783+ butw_ + 2 * padding_, get_inner_h() - padding_ - buth_,
784+ butw_, buth_,
785+ g_gr->images().get("pics/but1.png"),
786+ _("Cancel")),
787+ tab_box_(this, padding_, padding_, UI::Box::Vertical, max_w_, get_inner_h(), 0),
788+ tabs_(&tab_box_, 0, 0, nullptr),
789+
790+ main_box_(&tabs_, padding_, padding_, UI::Box::Vertical, max_w_, get_inner_h(), 0),
791+ tags_box_(&tabs_, padding_, padding_, UI::Box::Vertical, max_w_, get_inner_h(), 0),
792+ teams_box_(&tabs_, padding_, padding_, UI::Box::Vertical, max_w_, get_inner_h(), 0),
793+
794+ name_(&main_box_, 0, 0, max_w_, labelh_, g_gr->images().get("pics/but1.png")),
795+ author_(&main_box_, 0, 0, max_w_, labelh_, g_gr->images().get("pics/but1.png")),
796+ size_(&main_box_, 0, 0, max_w_ - indent_, labelh_, ""),
797+
798+ teams_list_(&teams_box_, 0, 0, max_w_, 60, UI::Align_Left, true),
799+
800+ modal_(modal) {
801+
802+ descr_ = new UI::MultilineEditbox(
803+ &main_box_, 0, 0, max_w_, 9 * labelh_, "", g_gr->images().get("pics/but1.png"));
804+ hint_ = new UI::MultilineEditbox(
805+ &main_box_, 0, 0, max_w_, 4 * labelh_, "", g_gr->images().get("pics/but1.png"));
806+
807+ main_box_.add(new UI::Textarea(&main_box_, 0, 0, max_w_, labelh_, _("Map Name:")), UI::Box::AlignLeft);
808+ main_box_.add(&name_, UI::Box::AlignLeft);
809+ main_box_.add_space(indent_);
810+
811+ main_box_.add(new UI::Textarea(&main_box_, 0, 0, max_w_, labelh_, _("Authors:")), UI::Box::AlignLeft);
812+ main_box_.add(&author_, UI::Box::AlignLeft);
813+ main_box_.add_space(indent_);
814+
815+ main_box_.add(new UI::Textarea(&main_box_, 0, 0, max_w_, labelh_, _("Description:")), UI::Box::AlignLeft);
816+ main_box_.add(descr_, UI::Box::AlignLeft);
817+ main_box_.add_space(indent_);
818+
819+ main_box_.add(new UI::Textarea(&main_box_, 0, 0, max_w_, labelh_, _("Hint (optional):")),
820+ UI::Box::AlignLeft);
821+ main_box_.add(hint_, UI::Box::AlignLeft);
822+ main_box_.add_space(indent_);
823+
824+ main_box_.add(&size_, UI::Box::AlignLeft);
825+ main_box_.add_space(indent_);
826+
827+ main_box_.set_size(max_w_, get_inner_h() - buth_ - 2 * padding_);
828+
829+ tags_box_.add(new UI::Textarea(&tags_box_, 0, 0, max_w_, labelh_, _("Tags:")), UI::Box::AlignLeft);
830+ add_tag_checkbox(&tags_box_, "unbalanced", _("Unbalanced"));
831+ add_tag_checkbox(&tags_box_, "ffa", _("Free for all"));
832+ add_tag_checkbox(&tags_box_, "1v1", _("1v1"));
833+ add_tag_checkbox(&tags_box_, "2teams", _("Teams of 2"));
834+ add_tag_checkbox(&tags_box_, "3teams", _("Teams of 3"));
835+ add_tag_checkbox(&tags_box_, "4teams", _("Teams of 4"));
836+ tags_box_.set_size(max_w_, get_inner_h() - buth_ - 2 * padding_);
837+
838+ teams_box_.add(new UI::Textarea(&teams_box_, 0, 0, max_w_, labelh_, _("Suggested Teams:")),
839+ UI::Box::AlignLeft);
840+ teams_box_.add(&teams_list_, UI::Box::AlignLeft);
841+ // TODO(GunChleoc): We need team images in the listselect here,
842+ // so map editors will be able to delete entries.
843+ // This is waiting for the new RT renderer.
844+ teams_list_.add("Not implemented yet.", "", nullptr, false);
845+
846+ unsigned int nr_players = static_cast<unsigned int>(eia().egbase().map().get_nrplayers());
847+ std::string players = (boost::format(ngettext("%u Player", "%u Players", nr_players)) % nr_players).str();
848+ teams_box_.add(new UI::Textarea(&teams_box_, 0, 0, max_w_, labelh_, players), UI::Box::AlignLeft);
849+ teams_box_.set_size(max_w_, get_inner_h() - buth_ - 2 * padding_);
850+
851+ tab_box_.add(&tabs_, UI::Box::AlignLeft, true);
852+ tabs_.add("main_map_options",
853+ g_gr->images().get("pics/menu_toggle_minimap.png"), &main_box_, _("Main Options"));
854+ tabs_.add("map_tags", g_gr->images().get("pics/checkbox_checked.png"), &tags_box_, _("Tags"));
855+ tabs_.add("map_teams", g_gr->images().get("pics/editor_menu_player_menu.png"), &teams_box_, _("Teams"));
856+ tabs_.set_size(max_w_, get_inner_h() - buth_ - 2 * padding_);
857+ tab_box_.set_size(max_w_, get_inner_h() - buth_ - 2 * padding_);
858+
859+ name_.changed.connect(boost::bind(&MainMenuMapOptions::changed, this));
860+ author_.changed.connect(boost::bind(&MainMenuMapOptions::changed, this));
861+ descr_->changed.connect(boost::bind(&MainMenuMapOptions::changed, this));
862+
863+ ok_.sigclicked.connect
864+ (boost::bind(&MainMenuMapOptions::clicked_ok, boost::ref(*this)));
865+ ok_.set_enabled(false);
866+ cancel_.sigclicked.connect
867+ (boost::bind(&MainMenuMapOptions::clicked_cancel, boost::ref(*this)));
868
869 update();
870+ center_to_parent();
871+ move_to_top();
872 }
873
874 /**
875@@ -115,34 +161,68 @@
876 */
877 void MainMenuMapOptions::update() {
878 const Widelands::Map & map = eia().egbase().map();
879+ author_.set_text(map.get_author());
880+ name_.set_text(map.get_name());
881+ size_.set_text((boost::format(_("Size: %1% x %2%"))
882+ % map.get_width()
883+ % map.get_height()).str());
884+ descr_->set_text(map.get_description());
885+ hint_->set_text(map.get_hint());
886
887- m_size ->set_text((boost::format(_("%1$ix%2$i"))
888- % map.get_width()
889- % map.get_height()).str());
890- m_author->set_text(map.get_author());
891- m_name ->set_text(map.get_name());
892- m_nrplayers->set_text(std::to_string(static_cast<unsigned int>(map.get_nrplayers())));
893- m_descr ->set_text(map.get_description());
894+ std::set<std::string> tags = map.get_tags();
895+ for (std::pair<std::string, UI::Checkbox*> tag : tags_checkboxes_) {
896+ tag.second->set_state(tags.count(tag.first) > 0);
897+ }
898 }
899
900
901 /**
902 * Called when one of the editboxes are changed
903 */
904-void MainMenuMapOptions::changed(int32_t const id) {
905- if (id == 0) {
906- eia().egbase().map().set_name(m_name->text());
907- } else if (id == 1) {
908- eia().egbase().map().set_author(m_author->text());
909- g_options.pull_section("global").set_string
910- ("realname", m_author->text());
911- }
912- update();
913-}
914-
915-/**
916- * Called when the editbox has changed
917+void MainMenuMapOptions::changed() {
918+ ok_.set_enabled(true);
919+}
920+
921+void MainMenuMapOptions::clicked_ok() {
922+ eia().egbase().map().set_name(name_.text());
923+ eia().egbase().map().set_author(author_.text());
924+ g_options.pull_section("global").set_string("realname", author_.text());
925+ eia().egbase().map().set_description(descr_->get_text());
926+ eia().egbase().map().set_hint(hint_->get_text());
927+
928+ eia().egbase().map().clear_tags();
929+ for (std::pair<std::string, UI::Checkbox*> tag : tags_checkboxes_) {
930+ if (tag.second->get_state()) {
931+ eia().egbase().map().add_tag(tag.first);
932+ }
933+ }
934+
935+ if (modal_) {
936+ end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kOk);
937+ } else {
938+ die();
939+ }
940+}
941+
942+void MainMenuMapOptions::clicked_cancel() {
943+ if (modal_) {
944+ end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack);
945+ } else {
946+ die();
947+ }
948+}
949+
950+/*
951+ * Add a tag to the checkboxes
952 */
953-void MainMenuMapOptions::editbox_changed() {
954- eia().egbase().map().set_description(m_descr->get_text());
955+void MainMenuMapOptions::add_tag_checkbox(UI::Box* parent, std::string tag, std::string displ_name) {
956+ UI::Box* box = new UI::Box(parent, 0, 0, UI::Box::Horizontal, max_w_, checkbox_space_, 0);
957+ UI::Checkbox* cb = new UI::Checkbox(box, Point(0, 0));
958+ box->add(cb, UI::Box::AlignLeft, true);
959+ box->add_space(padding_);
960+ box->add(new UI::Textarea(box, displ_name, UI::Align_CenterLeft), UI::Box::AlignLeft);
961+ box->add_space(checkbox_space_);
962+ parent->add(box, UI::Box::AlignLeft);
963+ parent->add_space(padding_);
964+ tags_checkboxes_.emplace(tag, cb);
965 }
966
967=== modified file 'src/editor/ui_menus/editor_main_menu_map_options.h'
968--- src/editor/ui_menus/editor_main_menu_map_options.h 2014-09-10 14:48:40 +0000
969+++ src/editor/ui_menus/editor_main_menu_map_options.h 2015-10-03 07:55:28 +0000
970@@ -20,15 +20,17 @@
971 #ifndef WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_MAP_OPTIONS_H
972 #define WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_MAP_OPTIONS_H
973
974+#include "ui_basic/box.h"
975 #include "ui_basic/button.h"
976+#include "ui_basic/checkbox.h"
977+#include "ui_basic/editbox.h"
978+#include "ui_basic/listselect.h"
979+#include "ui_basic/multilineeditbox.h"
980+#include "ui_basic/tabpanel.h"
981+#include "ui_basic/textarea.h"
982 #include "ui_basic/window.h"
983
984 struct EditorInteractive;
985-namespace UI {
986-struct EditBox;
987-struct MultilineEditbox;
988-struct Textarea;
989-}
990
991 /**
992 * This is the Main Options Menu. Here, information
993@@ -36,16 +38,35 @@
994 * author, name and description
995 */
996 struct MainMenuMapOptions : public UI::Window {
997- MainMenuMapOptions(EditorInteractive &);
998+ MainMenuMapOptions(EditorInteractive &, bool modal = false);
999
1000 private:
1001 EditorInteractive & eia();
1002- void changed(int32_t);
1003- void editbox_changed();
1004- UI::MultilineEditbox * m_descr;
1005- UI::Textarea * m_nrplayers, * m_size;
1006- UI::EditBox * m_name, * m_author;
1007+ void changed();
1008 void update();
1009+ void clicked_ok();
1010+ void clicked_cancel();
1011+ void add_tag_checkbox(UI::Box* box, std::string tag, std::string displ_name);
1012+
1013+ const int padding_, indent_, labelh_, checkbox_space_, butw_, buth_, max_w_;
1014+
1015+ UI::Button ok_, cancel_;
1016+
1017+ UI::Box tab_box_;
1018+ UI::TabPanel tabs_;
1019+ UI::Box main_box_;
1020+ UI::Box tags_box_;
1021+ UI::Box teams_box_;
1022+
1023+ UI::EditBox name_, author_;
1024+ UI::Textarea size_;
1025+ UI::MultilineEditbox* descr_;
1026+ UI::MultilineEditbox* hint_;
1027+ UI::Listselect<std::string> teams_list_;
1028+
1029+ // Tag, Checkbox
1030+ std::map<std::string, UI::Checkbox*> tags_checkboxes_;
1031+ bool modal_;
1032 };
1033
1034 #endif // end of include guard: WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_MAP_OPTIONS_H
1035
1036=== modified file 'src/editor/ui_menus/editor_main_menu_new_map.cc'
1037--- src/editor/ui_menus/editor_main_menu_new_map.cc 2015-02-28 16:02:49 +0000
1038+++ src/editor/ui_menus/editor_main_menu_new_map.cc 2015-10-03 07:55:28 +0000
1039@@ -105,7 +105,7 @@
1040 UI::Button * createbtn = new UI::Button
1041 (this, "create_map",
1042 posx, posy, width, height,
1043- g_gr->images().get("pics/but0.png"),
1044+ g_gr->images().get("pics/but5.png"),
1045 _("Create Map"));
1046 createbtn->sigclicked.connect(boost::bind(&MainMenuNewMap::clicked_create_map, this));
1047 }
1048
1049=== modified file 'src/editor/ui_menus/editor_main_menu_random_map.cc'
1050--- src/editor/ui_menus/editor_main_menu_random_map.cc 2015-09-04 06:16:58 +0000
1051+++ src/editor/ui_menus/editor_main_menu_random_map.cc 2015-10-03 07:55:28 +0000
1052@@ -328,7 +328,7 @@
1053 m_goButton = new UI::Button
1054 (this, "generate_map",
1055 posx, posy, width, height,
1056- g_gr->images().get("pics/but0.png"),
1057+ g_gr->images().get("pics/but5.png"),
1058 _("Generate Map"));
1059 m_goButton->sigclicked.connect(boost::bind(&MainMenuNewRandomMap::clicked_create_map, this));
1060 posy += height + spacing;
1061
1062=== modified file 'src/editor/ui_menus/editor_main_menu_save_map.cc'
1063--- src/editor/ui_menus/editor_main_menu_save_map.cc 2015-09-25 05:48:06 +0000
1064+++ src/editor/ui_menus/editor_main_menu_save_map.cc 2015-10-03 07:55:28 +0000
1065@@ -31,6 +31,7 @@
1066 #include "base/macros.h"
1067 #include "base/wexception.h"
1068 #include "editor/editorinteractive.h"
1069+#include "editor/ui_menus/editor_main_menu_map_options.h"
1070 #include "editor/ui_menus/editor_main_menu_save_map_make_directory.h"
1071 #include "graphic/graphic.h"
1072 #include "io/filesystem/filesystem.h"
1073@@ -39,172 +40,112 @@
1074 #include "map_io/map_saver.h"
1075 #include "map_io/widelands_map_loader.h"
1076 #include "profile/profile.h"
1077-#include "ui_basic/button.h"
1078-#include "ui_basic/editbox.h"
1079-#include "ui_basic/listselect.h"
1080 #include "ui_basic/messagebox.h"
1081-#include "ui_basic/multilinetextarea.h"
1082-#include "ui_basic/textarea.h"
1083+#include "wui/mapdetails.h"
1084+#include "wui/maptable.h"
1085
1086-inline EditorInteractive & MainMenuSaveMap::eia() {
1087+inline EditorInteractive& MainMenuSaveMap::eia() {
1088 return dynamic_cast<EditorInteractive&>(*get_parent());
1089 }
1090
1091-
1092-MainMenuSaveMap::MainMenuSaveMap(EditorInteractive & parent)
1093- : UI::Window(&parent, "save_map_menu", 0, 0, 560, 330, _("Save Map"))
1094-{
1095- int32_t const spacing = 5;
1096- int32_t const offsx = spacing;
1097- int32_t const offsy = 10;
1098- int32_t posx = offsx;
1099- int32_t posy = offsy;
1100- int32_t const descr_label_w = 100;
1101-
1102- m_ls =
1103- new UI::Listselect<const char *>
1104- (this,
1105- posx, posy,
1106- get_inner_w() / 2 - spacing, get_inner_h() - spacing - offsy - 60);
1107- m_ls->clicked.connect(boost::bind(&MainMenuSaveMap::clicked_item, this, _1));
1108- m_ls->double_clicked.connect(boost::bind(&MainMenuSaveMap::double_clicked_item, this, _1));
1109- m_ls->focus();
1110- m_editbox =
1111- new UI::EditBox
1112- (this,
1113- posx, posy + get_inner_h() - spacing - offsy - 60 + 3,
1114- get_inner_w() / 2 - spacing, 20,
1115- g_gr->images().get("pics/but1.png"), UI::Align::Align_Left);
1116- m_editbox->set_text(parent.egbase().map().get_name());
1117- m_editbox->changed.connect(boost::bind(&MainMenuSaveMap::edit_box_changed, this));
1118-
1119- posx = get_inner_w() / 2 + spacing;
1120- new UI::Textarea
1121- (this, posx, posy, descr_label_w, 20, _("Name:"), UI::Align_CenterLeft);
1122- m_name =
1123- new UI::MultilineTextarea
1124- (this, posx + descr_label_w, posy, 200, 40, "---", UI::Align_CenterLeft);
1125- posy += 40 + spacing;
1126-
1127- new UI::Textarea
1128- (this, posx, posy, descr_label_w, 20, _("Authors:"), UI::Align_CenterLeft);
1129- m_author =
1130- new UI::Textarea
1131- (this, posx + descr_label_w, posy, 200, 20, "---", UI::Align_CenterLeft);
1132- posy += 20 + spacing;
1133-
1134- new UI::Textarea
1135- (this, posx, posy, descr_label_w, 20, _("Size:"), UI::Align_CenterLeft);
1136- m_size =
1137- new UI::Textarea
1138- (this, posx + descr_label_w, posy, 200, 20, "---", UI::Align_CenterLeft);
1139- posy += 20 + spacing;
1140-
1141- new UI::Textarea
1142- (this, posx, posy, descr_label_w, 20, _("Players:"), UI::Align_CenterLeft);
1143- m_nrplayers =
1144- new UI::Textarea
1145- (this, posx + descr_label_w, posy, 200, 20, "---", UI::Align_CenterLeft);
1146- posy += 20 + spacing;
1147-
1148- new UI::Textarea
1149- (this, posx, posy, descr_label_w, 20, _("Descr:"), UI::Align_CenterLeft);
1150- m_descr =
1151- new UI::MultilineTextarea
1152- (this,
1153- posx + descr_label_w, posy,
1154- get_inner_w() - posx - spacing - descr_label_w,
1155- get_inner_h() - posy - spacing - 40,
1156- "---", UI::Align_CenterLeft);
1157-
1158-
1159- posy = get_inner_h() - 30;
1160-
1161- m_ok_btn = new UI::Button
1162- (this, "ok",
1163- posx, posy,
1164- get_inner_w() / 4 - 1.5 * spacing, 20,
1165- g_gr->images().get("pics/but0.png"),
1166- _("OK"));
1167- m_ok_btn->sigclicked.connect(boost::bind(&MainMenuSaveMap::clicked_ok, boost::ref(*this)));
1168-
1169- UI::Button * cancelbtn = new UI::Button
1170- (this, "cancel",
1171- posx + get_inner_w() / 4 - spacing / 2, posy,
1172- get_inner_w() / 4 - 1.5 * spacing, 20,
1173- g_gr->images().get("pics/but1.png"),
1174- _("Cancel"));
1175- cancelbtn->sigclicked.connect(boost::bind(&MainMenuSaveMap::die, boost::ref(*this)));
1176-
1177- UI::Button * make_directorybtn = new UI::Button
1178- (this, "make_directory",
1179- spacing, posy, 185, 20,
1180- g_gr->images().get("pics/but1.png"),
1181- _("Make Directory"));
1182- make_directorybtn->sigclicked.connect
1183- (boost::bind(&MainMenuSaveMap::clicked_make_directory, boost::ref(*this)));
1184-
1185-
1186- m_basedir = "maps";
1187- m_curdir = "maps";
1188-
1189- fill_list();
1190+MainMenuSaveMap::MainMenuSaveMap(EditorInteractive& parent)
1191+ : MainMenuLoadOrSaveMap(parent, "save_map_menu", _("Save Map")),
1192+
1193+ make_directory_(this,
1194+ "make_directory",
1195+ right_column_x_,
1196+ tabley_ + tableh_ + 3 * padding_ - 1,
1197+ get_inner_w() - right_column_x_ - padding_,
1198+ buth_,
1199+ g_gr->images().get("pics/but1.png"),
1200+ _("Make Directory")),
1201+ edit_options_(this,
1202+ "edit_options",
1203+ right_column_x_,
1204+ tabley_ + tableh_ - buth_,
1205+ get_inner_w() - right_column_x_ - padding_,
1206+ buth_,
1207+ g_gr->images().get("pics/but5.png"),
1208+ _("Map Options")),
1209+ editbox_label_(this,
1210+ padding_,
1211+ tabley_ + tableh_ + 3 * padding_,
1212+ butw_,
1213+ buth_,
1214+ _("Filename:"),
1215+ UI::Align::Align_Left) {
1216+
1217+ // Make room for edit_options_
1218+ map_details_.set_size(map_details_.get_w(), map_details_.get_h() - buth_ - padding_);
1219+
1220+ table_.selected.connect(boost::bind(&MainMenuSaveMap::clicked_item, boost::ref(*this)));
1221+ table_.double_clicked.connect(
1222+ boost::bind(&MainMenuSaveMap::double_clicked_item, boost::ref(*this)));
1223+
1224+ editbox_ = new UI::EditBox(this,
1225+ editbox_label_.get_x() + editbox_label_.get_w() + padding_,
1226+ editbox_label_.get_y(),
1227+ tablew_ - editbox_label_.get_w() - padding_ + 1,
1228+ buth_,
1229+ g_gr->images().get("pics/but1.png"),
1230+ UI::Align::Align_Left);
1231+
1232+ editbox_->set_text(parent.egbase().map().get_name());
1233+ editbox_->changed.connect(boost::bind(&MainMenuSaveMap::edit_box_changed, this));
1234 edit_box_changed();
1235
1236- center_to_parent();
1237- move_to_top();
1238+ ok_.sigclicked.connect(boost::bind(&MainMenuSaveMap::clicked_ok, boost::ref(*this)));
1239+ cancel_.sigclicked.connect(boost::bind(&MainMenuSaveMap::die, boost::ref(*this)));
1240+ make_directory_.sigclicked.connect(
1241+ boost::bind(&MainMenuSaveMap::clicked_make_directory, boost::ref(*this)));
1242+ edit_options_.sigclicked.connect(
1243+ boost::bind(&MainMenuSaveMap::clicked_edit_options, boost::ref(*this)));
1244+
1245+ // We always want the current map's data here
1246+ const Widelands::Map& map = parent.egbase().map();
1247+ MapData::MapType maptype;
1248+
1249+ if (map.scenario_types() & Widelands::Map::MP_SCENARIO ||
1250+ map.scenario_types() & Widelands::Map::SP_SCENARIO) {
1251+ maptype = MapData::MapType::kScenario;
1252+ } else {
1253+ maptype = MapData::MapType::kNormal;
1254+ }
1255+
1256+ MapData mapdata(map, "", maptype, MapData::DisplayType::kMapnames);
1257+
1258+ map_details_.update(mapdata, false);
1259 }
1260
1261 /**
1262 * Called when the ok button was pressed or a file in list was double clicked.
1263 */
1264 void MainMenuSaveMap::clicked_ok() {
1265- assert(m_ok_btn->enabled());
1266- std::string filename = m_editbox->text();
1267+ assert(ok_.enabled());
1268+ std::string filename = editbox_->text();
1269 std::string complete_filename;
1270
1271- if (filename == "") // Maybe a directory is selected.
1272- {
1273- complete_filename = filename = m_ls->get_selected();
1274+ if (filename == "" && table_.has_selection()) { // Maybe a directory is selected.
1275+ complete_filename = filename = maps_data_[table_.get_selected()].filename;
1276 } else {
1277- complete_filename = m_curdir + "/" + filename;
1278+ complete_filename = curdir_ + "/" + filename;
1279 }
1280
1281- if
1282- (g_fs->is_directory(complete_filename.c_str())
1283- &&
1284- !Widelands::WidelandsMapLoader::is_widelands_map(complete_filename))
1285- {
1286- m_curdir = complete_filename;
1287- m_ls->clear();
1288- m_mapfiles.clear();
1289- fill_list();
1290- } else { // Ok, save this map
1291- Widelands::Map & map = eia().egbase().map();
1292- if (map.get_name() != _("No Name")) {
1293+ if (g_fs->is_directory(complete_filename.c_str()) &&
1294+ !Widelands::WidelandsMapLoader::is_widelands_map(complete_filename)) {
1295+ curdir_ = complete_filename;
1296+ fill_table();
1297+ } else { // Ok, save this map
1298+ Widelands::Map& map = eia().egbase().map();
1299+ if (map.get_name() == _("No Name")) {
1300 std::string::size_type const filename_size = filename.size();
1301- map.set_name
1302- ((4 <= filename_size
1303- && filename[filename_size - 1] == 'f'
1304- && filename[filename_size - 2] == 'm'
1305- && filename[filename_size - 3] == 'w'
1306- && filename[filename_size - 4] == '.'
1307- ?
1308- filename.substr(0, filename_size - 4) : filename)
1309- .c_str());
1310+ map.set_name(4 <= filename_size && boost::iends_with(filename, WLMF_SUFFIX) ?
1311+ filename.substr(0, filename_size - 4) :
1312+ filename);
1313 }
1314-
1315- // check if map has at least two port spaces that are reachable for each other
1316- if (map.allows_seafaring())
1317- map.add_tag("seafaring");
1318- else
1319- map.delete_tag("seafaring");
1320-
1321- if
1322- (save_map
1323- (filename,
1324- ! g_options.pull_section("global").get_bool("nozip", false)))
1325+ if (save_map(filename, !g_options.pull_section("global").get_bool("nozip", false))) {
1326 die();
1327+ }
1328 }
1329 }
1330
1331@@ -214,149 +155,69 @@
1332 void MainMenuSaveMap::clicked_make_directory() {
1333 MainMenuSaveMapMakeDirectory md(this, _("unnamed"));
1334 if (md.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk) {
1335- g_fs->ensure_directory_exists(m_curdir);
1336+ g_fs->ensure_directory_exists(curdir_);
1337 // create directory
1338- std::string fullname = m_curdir;
1339- fullname += "/";
1340- fullname += md.get_dirname();
1341+ std::string fullname = curdir_;
1342+ fullname += "/";
1343+ fullname += md.get_dirname();
1344 g_fs->make_directory(fullname);
1345- m_ls->clear();
1346- m_mapfiles.clear();
1347- fill_list();
1348+ fill_table();
1349+ }
1350+}
1351+
1352+void MainMenuSaveMap::clicked_edit_options() {
1353+ MainMenuMapOptions mo(eia(), true);
1354+ if (mo.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kOk) {
1355+ const Widelands::Map& map = eia().egbase().map();
1356+ MapData::MapType maptype;
1357+
1358+ if (map.scenario_types() & Widelands::Map::MP_SCENARIO ||
1359+ map.scenario_types() & Widelands::Map::SP_SCENARIO) {
1360+ maptype = MapData::MapType::kScenario;
1361+ } else {
1362+ maptype = MapData::MapType::kNormal;
1363+ }
1364+
1365+ MapData mapdata(map, editbox_->text(), maptype, MapData::DisplayType::kMapnames);
1366+
1367+ map_details_.update(mapdata, false);
1368 }
1369 }
1370
1371 /**
1372 * called when an item was selected
1373 */
1374-void MainMenuSaveMap::clicked_item(uint32_t) {
1375- const char * const name = m_ls->get_selected();
1376-
1377- if (Widelands::WidelandsMapLoader::is_widelands_map(name)) {
1378- Widelands::Map map;
1379- {
1380- std::unique_ptr<Widelands::MapLoader> const ml
1381- (map.get_correct_loader(name));
1382- ml->preload_map(true); // This has worked before, no problem
1383- }
1384-
1385- m_editbox->set_text(FileSystem::fs_filename(name));
1386-
1387- m_name ->set_text(map.get_name ());
1388- m_name ->set_tooltip(map.get_name ());
1389- m_author->set_text(map.get_author ());
1390- m_descr ->set_text(map.get_description());
1391-
1392- m_nrplayers->set_text(std::to_string(static_cast<unsigned int>(map.get_nrplayers())));
1393-
1394- m_size->set_text((boost::format(_("%1$ix%2$i"))
1395- % map.get_width() % map.get_height()).str());
1396- } else {
1397- m_name ->set_text(FileSystem::fs_filename(name));
1398- m_name ->set_tooltip("");
1399- m_author ->set_text("");
1400- m_nrplayers->set_text("");
1401- m_size ->set_text("");
1402- if (g_fs->is_directory(name)) {
1403- m_name->set_tooltip((boost::format(_("Directory: %s"))
1404- % FileSystem::fs_filename(name)).str());
1405- m_descr->set_text((boost::format("\\<%s\\>") % _("directory")).str());
1406- } else {
1407- const std::string not_map_string = _("Not a map file");
1408- m_name->set_tooltip(not_map_string);
1409- m_descr->set_text((boost::format("\\<%s\\>") % not_map_string).str());
1410- }
1411-
1412+void MainMenuSaveMap::clicked_item() {
1413+ // Only change editbox contents
1414+ if (table_.has_selection()) {
1415+ const MapData& mapdata = maps_data_[table_.get_selected()];
1416+ if (mapdata.maptype != MapData::MapType::kDirectory) {
1417+ editbox_->set_text(FileSystem::fs_filename(maps_data_[table_.get_selected()].filename.c_str()));
1418+ edit_box_changed();
1419+ }
1420 }
1421- edit_box_changed();
1422 }
1423
1424 /**
1425 * An Item has been doubleclicked
1426 */
1427-void MainMenuSaveMap::double_clicked_item(uint32_t) {
1428- const char * const name = m_ls->get_selected();
1429-
1430- if (g_fs->is_directory(name) && !Widelands::WidelandsMapLoader::is_widelands_map(name)) {
1431- m_curdir = name;
1432- m_ls->clear();
1433- m_mapfiles.clear();
1434- fill_list();
1435- } else
1436+void MainMenuSaveMap::double_clicked_item() {
1437+ assert(table_.has_selection());
1438+ const MapData& mapdata = maps_data_[table_.get_selected()];
1439+ if (mapdata.maptype == MapData::MapType::kDirectory) {
1440+ curdir_ = mapdata.filename;
1441+ fill_table();
1442+ } else {
1443 clicked_ok();
1444-}
1445-
1446-/**
1447- * fill the file list
1448- */
1449-void MainMenuSaveMap::fill_list() {
1450- // Fill it with all files we find.
1451- m_mapfiles = g_fs->list_directory(m_curdir);
1452-
1453- // First, we add all directories. We manually add the parent directory
1454- if (m_curdir != m_basedir) {
1455-#ifndef _WIN32
1456- m_parentdir = m_curdir.substr(0, m_curdir.rfind('/'));
1457-#else
1458- m_parentdir = m_curdir.substr(0, m_curdir.rfind('\\'));
1459-#endif
1460-
1461- m_ls->add
1462- /** TRANSLATORS: Parent directory */
1463- ((boost::format("\\<%s\\>") % _("parent")).str(),
1464- m_parentdir.c_str(),
1465- g_gr->images().get("pics/ls_dir.png"));
1466- }
1467-
1468- const FilenameSet::const_iterator mapfiles_end = m_mapfiles.end();
1469- for
1470- (FilenameSet::const_iterator pname = m_mapfiles.begin();
1471- pname != mapfiles_end;
1472- ++pname)
1473- {
1474- const char * const name = pname->c_str();
1475- if
1476- (strcmp(FileSystem::fs_filename(name), ".") &&
1477- strcmp(FileSystem::fs_filename(name), "..") &&
1478- g_fs->is_directory(name) &&
1479- !Widelands::WidelandsMapLoader::is_widelands_map(name))
1480-
1481- m_ls->add
1482- (FileSystem::fs_filename(name),
1483- name,
1484- g_gr->images().get("pics/ls_dir.png"));
1485- }
1486-
1487- Widelands::Map map;
1488-
1489- for
1490- (FilenameSet::const_iterator pname = m_mapfiles.begin();
1491- pname != mapfiles_end;
1492- ++pname)
1493- {
1494- char const * const name = pname->c_str();
1495-
1496- // we do not list S2 files since we only write wmf
1497- std::unique_ptr<Widelands::MapLoader> ml(map.get_correct_loader(name));
1498- if (upcast(Widelands::WidelandsMapLoader, wml, ml.get())) {
1499- try {
1500- wml->preload_map(true);
1501- m_ls->add
1502- (FileSystem::filename_without_ext(name),
1503- name,
1504- g_gr->images().get("pics/ls_wlmap.png"));
1505- } catch (const WException &) {} // we simply skip illegal entries
1506- }
1507- }
1508- if (m_ls->size())
1509- m_ls->select(0);
1510+ }
1511+ edit_box_changed();
1512 }
1513
1514 /**
1515 * The editbox was changed. Enable ok button
1516 */
1517 void MainMenuSaveMap::edit_box_changed() {
1518- m_ok_btn->set_enabled(m_editbox->text().size());
1519+ ok_.set_enabled(!editbox_->text().empty());
1520 }
1521
1522 /**
1523@@ -368,59 +229,61 @@
1524 */
1525 bool MainMenuSaveMap::save_map(std::string filename, bool binary) {
1526 // Make sure that the current directory exists and is writeable.
1527- g_fs->ensure_directory_exists(m_curdir);
1528+ g_fs->ensure_directory_exists(curdir_);
1529
1530 // OK, first check if the extension matches (ignoring case).
1531 if (!boost::iends_with(filename, WLMF_SUFFIX))
1532 filename += WLMF_SUFFIX;
1533
1534 // append directory name
1535- std::string complete_filename = m_curdir;
1536- complete_filename += "/";
1537- complete_filename += filename;
1538-
1539- std::string tmpName = "";
1540+ std::string complete_filename = curdir_;
1541+ complete_filename += "/";
1542+ complete_filename += filename;
1543
1544 // Check if file exists. If so, show a warning.
1545 if (g_fs->file_exists(complete_filename)) {
1546- std::string s =
1547- (boost::format(_("A file with the name ‘%s’ already exists. Overwrite?"))
1548- % FileSystem::fs_filename(filename.c_str())).str();
1549- {
1550- UI::WLMessageBox mbox
1551+ const std::string s = (boost::format(_("A file with the name ‘%s’ already exists. Overwrite?")) %
1552+ FileSystem::fs_filename(filename.c_str())).str();
1553+ UI::WLMessageBox mbox
1554 (&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOkCancel);
1555 if (mbox.run<UI::Panel::Returncodes>() == UI::Panel::Returncodes::kBack)
1556 return false;
1557- }
1558+ }
1559
1560- // save to a tmp file/dir first, rename later
1561- // (important to keep script files in the script directory)
1562- tmpName = complete_filename + ".tmp";
1563- if (g_fs->file_exists(tmpName)) {
1564- s = (boost::format(_
1565- ("A file with the name ‘%s.tmp’ already exists. You have to remove it manually."))
1566- % FileSystem::fs_filename(filename.c_str())).str();
1567- UI::WLMessageBox mbox
1568- (&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
1569- mbox.run<UI::Panel::Returncodes>();
1570- return false;
1571- }
1572+ // save to a tmp file/dir first, rename later
1573+ // (important to keep script files in the script directory)
1574+ std::string tmp_name = complete_filename + ".tmp";
1575+ if (g_fs->file_exists(tmp_name)) {
1576+ const std::string s = (boost::format(_
1577+ ("A file with the name ‘%s.tmp’ already exists. You have to remove it manually."))
1578+ % FileSystem::fs_filename(filename.c_str())).str();
1579+ UI::WLMessageBox mbox
1580+ (&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
1581+ mbox.run<UI::Panel::Returncodes>();
1582+ return false;
1583 }
1584
1585 { // fs scope
1586 std::unique_ptr<FileSystem> fs
1587- (g_fs->create_sub_file_system(tmpName.empty() ? complete_filename : tmpName,
1588+ (g_fs->create_sub_file_system(tmp_name.empty() ? complete_filename : tmp_name,
1589 binary ? FileSystem::ZIP : FileSystem::DIR));
1590 Widelands::MapSaver wms(*fs, eia().egbase());
1591
1592+ // Recompute seafaring tag
1593+ if (eia().egbase().map().allows_seafaring()) {
1594+ eia().egbase().map().add_tag("seafaring");
1595+ } else {
1596+ eia().egbase().map().delete_tag("seafaring");
1597+ }
1598+
1599 try {
1600 wms.save();
1601 eia().set_need_save(false);
1602
1603 // if saved to a tmp file earlier, rename now
1604- if (!tmpName.empty()) {
1605+ if (!tmp_name.empty()) {
1606 g_fs->fs_unlink(complete_filename);
1607- g_fs->fs_rename(tmpName, complete_filename);
1608+ g_fs->fs_rename(tmp_name, complete_filename);
1609 // also change fs, as we assign it to the map below
1610 fs.reset(g_fs->make_sub_file_system(complete_filename));
1611 }
1612@@ -440,13 +303,12 @@
1613 mbox.run<UI::Panel::Returncodes>();
1614
1615 // cleanup tmp file if it was created
1616- if (!tmpName.empty()) {
1617- g_fs->fs_unlink(tmpName);
1618+ if (!tmp_name.empty()) {
1619+ g_fs->fs_unlink(tmp_name);
1620 }
1621 }
1622 } // end fs scope, dont use it
1623
1624 die();
1625-
1626 return true;
1627 }
1628
1629=== modified file 'src/editor/ui_menus/editor_main_menu_save_map.h'
1630--- src/editor/ui_menus/editor_main_menu_save_map.h 2015-08-05 10:44:37 +0000
1631+++ src/editor/ui_menus/editor_main_menu_save_map.h 2015-10-03 07:55:28 +0000
1632@@ -20,46 +20,35 @@
1633 #ifndef WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_SAVE_MAP_H
1634 #define WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_SAVE_MAP_H
1635
1636-#include "io/filesystem/filesystem.h"
1637-#include "ui_basic/window.h"
1638+#include <string>
1639
1640-struct EditorInteractive;
1641-namespace UI {
1642-struct Button;
1643-struct EditBox;
1644-template <typename T> struct Listselect;
1645-struct MultilineTextarea;
1646-struct Textarea;
1647-}
1648+#include "editor/editorinteractive.h"
1649+#include "editor/ui_menus/editor_main_menu_load_or_save_map.h"
1650+#include "ui_basic/button.h"
1651+#include "ui_basic/editbox.h"
1652+#include "ui_basic/textarea.h"
1653
1654 /**
1655 * Choose a filename and save your brand new created map
1656 */
1657-struct MainMenuSaveMap : public UI::Window {
1658- MainMenuSaveMap(EditorInteractive &);
1659+struct MainMenuSaveMap : public MainMenuLoadOrSaveMap {
1660+ MainMenuSaveMap(EditorInteractive& parent);
1661
1662 private:
1663 EditorInteractive & eia();
1664 void clicked_ok();
1665 void clicked_make_directory();
1666- void clicked_item(uint32_t);
1667- void double_clicked_item(uint32_t);
1668+ void clicked_edit_options();
1669+ void clicked_item();
1670+ void double_clicked_item();
1671 void edit_box_changed();
1672
1673- void fill_list();
1674 bool save_map(std::string, bool);
1675
1676- UI::EditBox * m_editbox;
1677- UI::MultilineTextarea * m_name;
1678- UI::Textarea * m_author, * m_size, * m_nrplayers;
1679- UI::MultilineTextarea * m_descr;
1680- UI::Listselect<const char *> * m_ls;
1681- UI::Button * m_ok_btn;
1682+ UI::Button make_directory_, edit_options_;
1683
1684- std::string m_basedir;
1685- std::string m_curdir;
1686- std::string m_parentdir;
1687- FilenameSet m_mapfiles;
1688+ UI::Textarea editbox_label_;
1689+ UI::EditBox* editbox_;
1690 };
1691
1692 #endif // end of include guard: WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_SAVE_MAP_H
1693
1694=== modified file 'src/editor/ui_menus/editor_main_menu_save_map_make_directory.cc'
1695--- src/editor/ui_menus/editor_main_menu_save_map_make_directory.cc 2015-08-06 17:14:34 +0000
1696+++ src/editor/ui_menus/editor_main_menu_save_map_make_directory.cc 2015-10-03 07:55:28 +0000
1697@@ -21,56 +21,47 @@
1698
1699 #include "base/i18n.h"
1700 #include "graphic/graphic.h"
1701-#include "ui_basic/button.h"
1702-#include "ui_basic/editbox.h"
1703-#include "ui_basic/textarea.h"
1704-#include "ui_basic/window.h"
1705
1706 MainMenuSaveMapMakeDirectory::MainMenuSaveMapMakeDirectory
1707- (UI::Panel * const parent, char const * dirname)
1708-:
1709-UI::Window(parent, "make_directory", 0, 0, 230, 120, _("Make Directory"))
1710-{
1711- int32_t const spacing = 5;
1712- int32_t const offsy = 30;
1713- int32_t posy = offsy;
1714-
1715- new UI::Textarea(this, spacing, posy, _("Enter Directory Name:"));
1716- posy += 20 + spacing;
1717-
1718- m_edit =
1719- new UI::EditBox
1720- (this, spacing, posy, get_inner_w() - 2 * spacing, 20,
1721- g_gr->images().get("pics/but1.png"));
1722- m_edit->set_text(dirname);
1723- m_dirname = dirname;
1724- m_edit->changed.connect(boost::bind(&MainMenuSaveMapMakeDirectory::edit_changed, this));
1725-
1726- posy = get_inner_h() - 30;
1727-
1728- m_ok_button = new
1729- UI::Button
1730- (this, "ok",
1731- get_inner_w() / 2 - spacing - 80, posy, 80, 20,
1732- g_gr->images().get("pics/but0.png"),
1733- _("OK"),
1734- std::string(),
1735- m_dirname.size());
1736- m_ok_button->sigclicked.connect
1737- (boost::bind(&MainMenuSaveMapMakeDirectory::end_modal<UI::Panel::Returncodes>,
1738- boost::ref(*this),
1739- UI::Panel::Returncodes::kOk));
1740-
1741- UI::Button * cancelbtn = new UI::Button
1742- (this, "cancel",
1743- get_inner_w() / 2 + spacing, posy, 80, 20,
1744- g_gr->images().get("pics/but1.png"),
1745- _("Cancel"));
1746- cancelbtn->sigclicked.connect
1747+ (UI::Panel * const parent, char const * dirname) :
1748+ UI::Window(parent, "make_directory", 0, 0, 330, 100, _("Make Directory")),
1749+ padding_(5),
1750+ butw_(get_inner_w() / 2 - 3 * padding_),
1751+ buth_(20),
1752+ dirname_(dirname),
1753+ vbox_(this, padding_, padding_, UI::Box::Vertical,
1754+ get_inner_w() - 2 * padding_, get_inner_h() - 3 * padding_ - buth_, padding_ / 2),
1755+ label_(&vbox_, 0, 0, get_inner_w() - 2 * padding_, buth_, _("Enter Directory Name: "), UI::Align_Left),
1756+ edit_(&vbox_, 0, 0, get_inner_w() - 2 * padding_, buth_, g_gr->images().get("pics/but1.png")),
1757+ ok_button_(
1758+ this, "ok",
1759+ padding_, get_inner_h() - padding_ - buth_,
1760+ butw_, buth_,
1761+ g_gr->images().get("pics/but5.png"),
1762+ _("OK")),
1763+ cancel_button_(
1764+ this, "cancel",
1765+ get_inner_w() - butw_ - padding_, get_inner_h() - padding_ - buth_,
1766+ butw_, buth_,
1767+ g_gr->images().get("pics/but1.png"),
1768+ _("Cancel")) {
1769+
1770+ vbox_.add(&label_, UI::Box::AlignLeft);
1771+ vbox_.add_space(padding_);
1772+ vbox_.add(&edit_, UI::Box::AlignLeft);
1773+ vbox_.set_size(get_inner_w() - 2 * padding_, get_inner_h() - 3 * padding_ - buth_);
1774+
1775+ edit_.set_text(dirname_);
1776+ edit_.changed.connect(boost::bind(&MainMenuSaveMapMakeDirectory::edit_changed, this));
1777+ ok_button_.sigclicked.connect
1778+ (boost::bind(&MainMenuSaveMapMakeDirectory::end_modal<UI::Panel::Returncodes>,
1779+ boost::ref(*this),
1780+ UI::Panel::Returncodes::kOk));
1781+ ok_button_.set_enabled(false);
1782+ cancel_button_.sigclicked.connect
1783 (boost::bind(&MainMenuSaveMapMakeDirectory::end_modal<UI::Panel::Returncodes>,
1784 boost::ref(*this),
1785 UI::Panel::Returncodes::kBack));
1786-
1787 center_to_parent();
1788 }
1789
1790@@ -79,9 +70,7 @@
1791 * Editbox changed
1792 */
1793 void MainMenuSaveMapMakeDirectory::edit_changed() {
1794- const std::string & text = m_edit->text();
1795- if (text.size()) {
1796- m_ok_button->set_enabled(true);
1797- m_dirname = text;
1798- }
1799+ const std::string& text = edit_.text();
1800+ ok_button_.set_enabled(!text.empty());
1801+ dirname_ = text;
1802 }
1803
1804=== modified file 'src/editor/ui_menus/editor_main_menu_save_map_make_directory.h'
1805--- src/editor/ui_menus/editor_main_menu_save_map_make_directory.h 2014-09-10 14:08:25 +0000
1806+++ src/editor/ui_menus/editor_main_menu_save_map_make_directory.h 2015-10-03 07:55:28 +0000
1807@@ -20,15 +20,14 @@
1808 #ifndef WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_SAVE_MAP_MAKE_DIRECTORY_H
1809 #define WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_SAVE_MAP_MAKE_DIRECTORY_H
1810
1811-#include <cstring>
1812 #include <string>
1813
1814+#include "ui_basic/box.h"
1815+#include "ui_basic/button.h"
1816+#include "ui_basic/editbox.h"
1817+#include "ui_basic/textarea.h"
1818 #include "ui_basic/window.h"
1819
1820-namespace UI {
1821-struct EditBox;
1822-struct Button;
1823-}
1824
1825 /**
1826 * Show a small modal dialog allowing the user to enter
1827@@ -39,12 +38,17 @@
1828 struct MainMenuSaveMapMakeDirectory : public UI::Window {
1829 MainMenuSaveMapMakeDirectory(UI::Panel *, char const *);
1830
1831- char const * get_dirname() {return m_dirname.c_str();}
1832+ char const * get_dirname() {return dirname_.c_str();}
1833
1834 private:
1835- std::string m_dirname;
1836- UI::EditBox * m_edit;
1837- UI::Button * m_ok_button;
1838+ const int padding_;
1839+ const int butw_, buth_;
1840+ std::string dirname_;
1841+ UI::Box vbox_;
1842+ UI::Textarea label_;
1843+ UI::EditBox edit_;
1844+ UI::Button ok_button_;
1845+ UI::Button cancel_button_;
1846 void edit_changed();
1847 };
1848
1849
1850=== modified file 'src/editor/ui_menus/editor_tool_menu.cc'
1851--- src/editor/ui_menus/editor_tool_menu.cc 2014-11-30 18:49:38 +0000
1852+++ src/editor/ui_menus/editor_tool_menu.cc 2015-10-03 07:55:28 +0000
1853@@ -53,7 +53,7 @@
1854 int32_t const height = 34;
1855
1856
1857- int32_t const num_tools = 7;
1858+ int32_t const num_tools = 8;
1859 #define ADD_BUTTON(pic, tooltip) \
1860 m_radioselect.add_button \
1861 (this, \
1862@@ -69,6 +69,8 @@
1863 ADD_BUTTON("place_bob", _("Animals"));
1864 ADD_BUTTON("change_resources", _("Resources"));
1865 ADD_BUTTON("set_port_space", _("Set port space"));
1866+ ADD_BUTTON("set_origin", _("Set the position that will have the coordinates (0, 0). This will "
1867+ "be the top-left corner of a generated minimap."));
1868
1869 set_inner_size
1870 (offs.x + (width + spacing) * num_tools, offs.y + (height + spacing));
1871@@ -82,6 +84,7 @@
1872 &current == &parent.tools.place_bob ? 4 :
1873 &current == &parent.tools.increase_resources ? 5 :
1874 &current == &parent.tools.set_port_space ? 6 :
1875+ &current == &parent.tools.set_origin ? 7 :
1876 0);
1877 }
1878
1879@@ -132,6 +135,10 @@
1880 current_tool_pointer = &parent.tools.set_port_space;
1881 current_registry_pointer = nullptr; // no need for a window
1882 break;
1883+ case 7:
1884+ current_tool_pointer = &parent.tools.set_origin;
1885+ current_registry_pointer = nullptr; // no need for a window
1886+ break;
1887 default:
1888 assert(false);
1889 break;
1890
1891=== modified file 'src/logic/map.cc'
1892--- src/logic/map.cc 2015-09-13 14:16:53 +0000
1893+++ src/logic/map.cc 2015-10-03 07:55:28 +0000
1894@@ -1396,7 +1396,7 @@
1895 }
1896
1897 /// \returns true, if Coordinates are in port space list
1898-bool Map::is_port_space(const Coords& c) {
1899+bool Map::is_port_space(const Coords& c) const {
1900 return m_port_spaces.count(c);
1901 }
1902
1903@@ -1409,7 +1409,6 @@
1904 }
1905 }
1906
1907-
1908 /**
1909 * Calculate the (Manhattan) distance from a to b
1910 * a and b are expected to be normalized!
1911
1912=== modified file 'src/logic/map.h'
1913--- src/logic/map.h 2015-09-08 21:17:02 +0000
1914+++ src/logic/map.h 2015-10-03 07:55:28 +0000
1915@@ -219,7 +219,8 @@
1916
1917 using Tags = std::set<std::string>;
1918 const Tags & get_tags() const {return m_tags;}
1919- bool has_tag(const std::string & s) const {return m_tags.count(s);}
1920+ void clear_tags() {m_tags.clear();}
1921+ bool has_tag(const std::string& s) const {return m_tags.count(s);}
1922
1923 const std::vector<SuggestedTeamLineup>& get_suggested_teams() const {return m_suggested_teams;}
1924
1925@@ -386,9 +387,9 @@
1926 void set_origin(Coords);
1927
1928 /// Port space specific functions
1929- bool is_port_space(const Coords& c);
1930+ bool is_port_space(const Coords& c) const;
1931 void set_port_space(Coords c, bool allowed);
1932- const PortSpacesSet& get_port_spaces() {return m_port_spaces;}
1933+ const PortSpacesSet& get_port_spaces() const {return m_port_spaces;}
1934 std::vector<Coords> find_portdock(const Widelands::Coords& c) const;
1935 bool allows_seafaring();
1936
1937
1938=== modified file 'src/logic/production_program.cc'
1939--- src/logic/production_program.cc 2015-08-02 08:24:52 +0000
1940+++ src/logic/production_program.cc 2015-10-03 07:55:28 +0000
1941@@ -811,7 +811,7 @@
1942 {
1943 switch (m_feature) {
1944 case SEAFARING: {
1945- if (game.map().get_port_spaces().size() > 1) // we need at least two port build spaces
1946+ if (game.map().allows_seafaring())
1947 return ps.program_step(game, 0);
1948 else {
1949 ps.set_production_result("No use for ships on this map!");
1950
1951=== modified file 'src/ui_basic/helpwindow.cc'
1952--- src/ui_basic/helpwindow.cc 2015-08-06 17:14:34 +0000
1953+++ src/ui_basic/helpwindow.cc 2015-10-03 07:55:28 +0000
1954@@ -82,7 +82,7 @@
1955 (this, "ok",
1956 in_width / 3, in_height - but_height * 3 / 2,
1957 in_width / 3, but_height,
1958- g_gr->images().get("pics/but0.png"),
1959+ g_gr->images().get("pics/but5.png"),
1960 _("OK"), std::string(), true, false);
1961 btn->sigclicked.connect(boost::bind(&HelpWindow::clicked_ok, boost::ref(*this)));
1962 btn->set_font(Font::get((UI::g_fh1->fontset()).serif(),
1963
1964=== modified file 'src/ui_basic/messagebox.cc'
1965--- src/ui_basic/messagebox.cc 2015-09-09 18:49:58 +0000
1966+++ src/ui_basic/messagebox.cc 2015-10-03 07:55:28 +0000
1967@@ -86,14 +86,14 @@
1968 UI::Button * okbtn = new Button
1969 (this, "ok",
1970 (get_inner_w() - 120) / 2, get_inner_h() - 30, 120, 20,
1971- g_gr->images().get("pics/but0.png"),
1972+ g_gr->images().get("pics/but5.png"),
1973 _("OK"));
1974 okbtn->sigclicked.connect(boost::bind(&WLMessageBox::clicked_ok, boost::ref(*this)));
1975 } else if (type == MBoxType::kOkCancel) {
1976 UI::Button * okbtn = new Button
1977 (this, "ok",
1978 (get_inner_w() / 2 - 120) / 2, get_inner_h() - 30, 120, 20,
1979- g_gr->images().get("pics/but0.png"),
1980+ g_gr->images().get("pics/but5.png"),
1981 _("OK"));
1982 okbtn->sigclicked.connect(boost::bind(&WLMessageBox::clicked_ok, boost::ref(*this)));
1983 UI::Button * cancelbtn = new Button
1984
1985=== modified file 'src/ui_basic/multilineeditbox.cc'
1986--- src/ui_basic/multilineeditbox.cc 2014-11-27 12:02:08 +0000
1987+++ src/ui_basic/multilineeditbox.cc 2015-10-03 07:55:28 +0000
1988@@ -26,11 +26,11 @@
1989 #include "graphic/rendertarget.h"
1990 #include "graphic/text_layout.h"
1991 #include "graphic/wordwrap.h"
1992+#include "ui_basic/mouse_constants.h"
1993 #include "ui_basic/scrollbar.h"
1994
1995 namespace UI {
1996
1997-static const int32_t ms_darken_value = -20;
1998 static const int32_t ms_scrollbar_w = 24;
1999
2000 struct MultilineEditbox::Data {
2001@@ -39,6 +39,9 @@
2002 /// The text in the edit box
2003 std::string text;
2004
2005+ /// Background tile style.
2006+ const Image* background;
2007+
2008 /// Position of the cursor inside the text.
2009 /// 0 indicates that the cursor is before the first character,
2010 /// text.size() inidicates that the cursor is after the last character.
2011@@ -81,11 +84,13 @@
2012 MultilineEditbox::MultilineEditbox
2013 (Panel * parent,
2014 int32_t x, int32_t y, uint32_t w, uint32_t h,
2015- const std::string & text)
2016+ const std::string & text,
2017+ const Image* background)
2018 :
2019 Panel(parent, x, y, w, h),
2020 d(new Data(*this))
2021 {
2022+ d->background = background;
2023 set_handle_mouse(true);
2024 set_can_focus(true);
2025 set_thinks(false);
2026@@ -444,8 +449,35 @@
2027 */
2028 void MultilineEditbox::draw(RenderTarget & dst)
2029 {
2030- // make the whole area a bit darker
2031- dst.brighten_rect(Rect(Point(0, 0), get_w(), get_h()), ms_darken_value);
2032+ // Draw the background
2033+ dst.tile
2034+ (Rect(Point(0, 0), get_w(), get_h()),
2035+ d->background,
2036+ Point(get_x(), get_y()));
2037+
2038+ // Draw border.
2039+ if (get_w() >= 4 && get_h() >= 4) {
2040+ static const RGBColor black(0, 0, 0);
2041+
2042+ // bottom edge
2043+ dst.brighten_rect
2044+ (Rect(Point(0, get_h() - 2), get_w(), 2),
2045+ BUTTON_EDGE_BRIGHT_FACTOR);
2046+ // right edge
2047+ dst.brighten_rect
2048+ (Rect(Point(get_w() - 2, 0), 2, get_h() - 2),
2049+ BUTTON_EDGE_BRIGHT_FACTOR);
2050+ // top edge
2051+ dst.fill_rect(Rect(Point(0, 0), get_w() - 1, 1), black);
2052+ dst.fill_rect(Rect(Point(0, 1), get_w() - 2, 1), black);
2053+ // left edge
2054+ dst.fill_rect(Rect(Point(0, 0), 1, get_h() - 1), black);
2055+ dst.fill_rect(Rect(Point(1, 0), 1, get_h() - 2), black);
2056+ }
2057+
2058+ if (has_focus())
2059+ dst.brighten_rect
2060+ (Rect(Point(0, 0), get_w(), get_h()), MOUSE_OVER_BRIGHT_FACTOR);
2061
2062 d->refresh_ww();
2063
2064
2065=== modified file 'src/ui_basic/multilineeditbox.h'
2066--- src/ui_basic/multilineeditbox.h 2015-04-18 11:20:53 +0000
2067+++ src/ui_basic/multilineeditbox.h 2015-10-03 07:55:28 +0000
2068@@ -24,6 +24,7 @@
2069
2070 #include <boost/signals2.hpp>
2071
2072+#include "graphic/graphic.h"
2073 #include "ui_basic/panel.h"
2074
2075 namespace UI {
2076@@ -36,7 +37,8 @@
2077 */
2078 struct MultilineEditbox : public Panel {
2079 MultilineEditbox
2080- (Panel *, int32_t x, int32_t y, uint32_t w, uint32_t h, const std::string & text);
2081+ (Panel *, int32_t x, int32_t y, uint32_t w, uint32_t h,
2082+ const std::string & text, const Image* background = g_gr->images().get("pics/but2.png"));
2083
2084 boost::signals2::signal<void ()> changed;
2085
2086
2087=== modified file 'src/ui_fsmenu/CMakeLists.txt'
2088--- src/ui_fsmenu/CMakeLists.txt 2015-01-31 16:03:59 +0000
2089+++ src/ui_fsmenu/CMakeLists.txt 2015-10-03 07:55:28 +0000
2090@@ -32,8 +32,6 @@
2091 options.h
2092 singleplayer.cc
2093 singleplayer.h
2094- suggested_teams_box.cc
2095- suggested_teams_box.h
2096 DEPENDS
2097 base_exceptions
2098 base_i18n
2099@@ -61,6 +59,6 @@
2100 sound
2101 ui_basic
2102 widelands_ball_of_mud
2103- wui
2104 wui_chat_ui
2105+ wui_common
2106 )
2107
2108=== modified file 'src/ui_fsmenu/campaign_select.cc'
2109--- src/ui_fsmenu/campaign_select.cc 2015-08-06 17:14:34 +0000
2110+++ src/ui_fsmenu/campaign_select.cc 2015-10-03 07:55:28 +0000
2111@@ -42,59 +42,59 @@
2112 */
2113 FullscreenMenuCampaignSelect::FullscreenMenuCampaignSelect() :
2114 FullscreenMenuLoadMapOrGame(),
2115+ m_table(this, tablex_, tabley_, tablew_, tableh_, false),
2116
2117 // Main Title
2118 m_title
2119- (this, get_w() / 2, m_tabley / 3,
2120+ (this, get_w() / 2, tabley_ / 3,
2121 _("Choose a campaign"),
2122 UI::Align_HCenter),
2123
2124 // Campaign description
2125 m_label_campname
2126- (this, m_right_column_x, m_tabley,
2127+ (this, right_column_x_, tabley_,
2128 "",
2129 UI::Align_Left),
2130 m_ta_campname(this,
2131- m_right_column_x + m_indent, get_y_from_preceding(m_label_campname) + m_padding,
2132- get_right_column_w(m_right_column_x) - m_indent, m_label_height),
2133+ right_column_x_ + indent_, get_y_from_preceding(m_label_campname) + padding_,
2134+ get_right_column_w(right_column_x_) - indent_, m_label_height),
2135
2136 m_label_tribename
2137- (this, m_right_column_x, get_y_from_preceding(m_ta_campname) + 2 * m_padding,
2138+ (this, right_column_x_, get_y_from_preceding(m_ta_campname) + 2 * padding_,
2139 "",
2140 UI::Align_Left),
2141 m_ta_tribename(this,
2142- m_right_column_x + m_indent, get_y_from_preceding(m_label_tribename) + m_padding,
2143- get_right_column_w(m_right_column_x + m_indent), m_label_height),
2144+ right_column_x_ + indent_, get_y_from_preceding(m_label_tribename) + padding_,
2145+ get_right_column_w(right_column_x_ + indent_), m_label_height),
2146
2147 m_label_difficulty
2148- (this, m_right_column_x, get_y_from_preceding(m_ta_tribename) + 2 * m_padding,
2149+ (this, right_column_x_, get_y_from_preceding(m_ta_tribename) + 2 * padding_,
2150 "",
2151 UI::Align_Left),
2152 m_ta_difficulty(this,
2153- m_right_column_x + m_indent, get_y_from_preceding(m_label_difficulty) + m_padding,
2154- get_right_column_w(m_right_column_x + m_indent), 2 * m_label_height - m_padding),
2155+ right_column_x_ + indent_, get_y_from_preceding(m_label_difficulty) + padding_,
2156+ get_right_column_w(right_column_x_ + indent_), 2 * m_label_height - padding_),
2157
2158 m_label_description
2159- (this, m_right_column_x, get_y_from_preceding(m_ta_difficulty) + 2 * m_padding,
2160+ (this, right_column_x_, get_y_from_preceding(m_ta_difficulty) + 2 * padding_,
2161 _("Description:"),
2162 UI::Align_Left),
2163 m_ta_description
2164 (this,
2165- m_right_column_x + m_indent,
2166- get_y_from_preceding(m_label_description) + m_padding,
2167- get_right_column_w(m_right_column_x + m_indent),
2168- m_buty - get_y_from_preceding(m_label_description) - 4 * m_padding)
2169+ right_column_x_ + indent_,
2170+ get_y_from_preceding(m_label_description) + padding_,
2171+ get_right_column_w(right_column_x_ + indent_),
2172+ m_buty - get_y_from_preceding(m_label_description) - 4 * padding_)
2173 {
2174 m_title.set_textstyle(UI::TextStyle::ui_big());
2175- m_back.set_tooltip(_("Return to the main menu"));
2176- m_ok.set_tooltip(_("Play this campaign"));
2177+ back_.set_tooltip(_("Return to the main menu"));
2178+ ok_.set_tooltip(_("Play this campaign"));
2179 m_ta_campname.set_tooltip(_("The name of this campaign"));
2180 m_ta_tribename.set_tooltip(_("The tribe you will be playing"));
2181 m_ta_difficulty.set_tooltip(_("The difficulty of this campaign"));
2182- m_ta_description.set_tooltip(_("Story and hints"));
2183
2184- m_ok.sigclicked.connect(boost::bind(&FullscreenMenuCampaignSelect::clicked_ok, boost::ref(*this)));
2185- m_back.sigclicked.connect(boost::bind(&FullscreenMenuCampaignSelect::clicked_back, boost::ref(*this)));
2186+ ok_.sigclicked.connect(boost::bind(&FullscreenMenuCampaignSelect::clicked_ok, boost::ref(*this)));
2187+ back_.sigclicked.connect(boost::bind(&FullscreenMenuCampaignSelect::clicked_back, boost::ref(*this)));
2188 m_table.selected.connect(boost::bind(&FullscreenMenuCampaignSelect::entry_selected, this));
2189 m_table.double_clicked.connect(boost::bind(&FullscreenMenuCampaignSelect::clicked_ok, boost::ref(*this)));
2190
2191@@ -137,7 +137,7 @@
2192 bool FullscreenMenuCampaignSelect::set_has_selection()
2193 {
2194 bool has_selection = m_table.has_selection();
2195- FullscreenMenuLoadMapOrGame::set_has_selection();
2196+ ok_.set_enabled(has_selection);
2197
2198 if (!has_selection) {
2199 m_label_campname.set_text(std::string());
2200@@ -281,65 +281,65 @@
2201 */
2202 FullscreenMenuCampaignMapSelect::FullscreenMenuCampaignMapSelect(bool is_tutorial) :
2203 FullscreenMenuLoadMapOrGame(),
2204+ m_table(this, tablex_, tabley_, tablew_, tableh_, false),
2205
2206 // Main title
2207 m_title
2208- (this, get_w() / 2, m_tabley / 3,
2209+ (this, get_w() / 2, tabley_ / 3,
2210 is_tutorial ? _("Choose a tutorial") : _("Choose a scenario"),
2211 UI::Align_HCenter),
2212 m_subtitle
2213- (this, get_w() / 6, get_y_from_preceding(m_title) + 6 * m_padding,
2214+ (this, get_w() / 6, get_y_from_preceding(m_title) + 6 * padding_,
2215 get_w() * 2 / 3, 4 * m_label_height,
2216 "",
2217 UI::Align_HCenter),
2218
2219 // Map description
2220 m_label_mapname
2221- (this, m_right_column_x, m_tabley,
2222+ (this, right_column_x_, tabley_,
2223 "",
2224 UI::Align_Left),
2225 m_ta_mapname(this,
2226- m_right_column_x + m_indent, get_y_from_preceding(m_label_mapname) + m_padding,
2227- get_right_column_w(m_right_column_x + m_indent), m_label_height),
2228+ right_column_x_ + indent_, get_y_from_preceding(m_label_mapname) + padding_,
2229+ get_right_column_w(right_column_x_ + indent_), m_label_height),
2230
2231 m_label_author
2232 (this,
2233- m_right_column_x, get_y_from_preceding(m_ta_mapname) + 2 * m_padding,
2234+ right_column_x_, get_y_from_preceding(m_ta_mapname) + 2 * padding_,
2235 "",
2236 UI::Align_Left),
2237 m_ta_author(this,
2238- m_right_column_x + m_indent, get_y_from_preceding(m_label_author) + m_padding,
2239- get_right_column_w(m_right_column_x + m_indent), 2 * m_label_height),
2240+ right_column_x_ + indent_, get_y_from_preceding(m_label_author) + padding_,
2241+ get_right_column_w(right_column_x_ + indent_), 2 * m_label_height),
2242
2243 m_label_description
2244- (this, m_right_column_x, get_y_from_preceding(m_ta_author) + m_padding,
2245+ (this, right_column_x_, get_y_from_preceding(m_ta_author) + padding_,
2246 "",
2247 UI::Align_Left),
2248 m_ta_description
2249 (this,
2250- m_right_column_x + m_indent,
2251- get_y_from_preceding(m_label_description) + m_padding,
2252- get_right_column_w(m_right_column_x + m_indent),
2253- m_buty - get_y_from_preceding(m_label_description) - 4 * m_padding),
2254+ right_column_x_ + indent_,
2255+ get_y_from_preceding(m_label_description) + padding_,
2256+ get_right_column_w(right_column_x_ + indent_),
2257+ m_buty - get_y_from_preceding(m_label_description) - 4 * padding_),
2258
2259 m_is_tutorial(is_tutorial)
2260 {
2261 m_title.set_textstyle(UI::TextStyle::ui_big());
2262- m_back.set_tooltip(_("Return to the main menu"));
2263+ back_.set_tooltip(_("Return to the main menu"));
2264 if (m_is_tutorial) {
2265- m_ok.set_tooltip(_("Play this tutorial"));
2266+ ok_.set_tooltip(_("Play this tutorial"));
2267 m_ta_mapname.set_tooltip(_("The name of this tutorial"));
2268 m_ta_description.set_tooltip(_("What you will learn in this tutorial"));
2269 } else {
2270- m_ok.set_tooltip(_("Play this scenario"));
2271+ ok_.set_tooltip(_("Play this scenario"));
2272 m_ta_mapname.set_tooltip(_("The name of this scenario"));
2273- m_ta_description.set_tooltip(_("Story and hints"));
2274 }
2275
2276- m_ok.sigclicked.connect
2277+ ok_.sigclicked.connect
2278 (boost::bind
2279 (&FullscreenMenuCampaignMapSelect::clicked_ok, boost::ref(*this)));
2280- m_back.sigclicked.connect
2281+ back_.sigclicked.connect
2282 (boost::bind
2283 (&FullscreenMenuCampaignMapSelect::clicked_back, boost::ref(*this)));
2284 m_table.selected.connect(boost::bind(&FullscreenMenuCampaignMapSelect::entry_selected, this));
2285@@ -380,7 +380,7 @@
2286 bool FullscreenMenuCampaignMapSelect::set_has_selection()
2287 {
2288 bool has_selection = m_table.has_selection();
2289- FullscreenMenuLoadMapOrGame::set_has_selection();
2290+ ok_.set_enabled(has_selection);
2291
2292 if (!has_selection) {
2293 m_label_mapname.set_text(std::string());
2294@@ -414,8 +414,7 @@
2295 map.set_filename(campmapfile);
2296 ml->preload_map(true);
2297
2298- MapAuthorData authors;
2299- authors.parse(map.get_author());
2300+ MapAuthorData authors(map.get_author());
2301
2302 m_ta_author.set_text(authors.get_names());
2303 if (m_is_tutorial) {
2304
2305=== modified file 'src/ui_fsmenu/campaign_select.h'
2306--- src/ui_fsmenu/campaign_select.h 2014-11-13 08:39:14 +0000
2307+++ src/ui_fsmenu/campaign_select.h 2015-10-03 07:55:28 +0000
2308@@ -47,10 +47,11 @@
2309 void clicked_ok() override;
2310 void entry_selected() override;
2311 void fill_table() override;
2312- bool set_has_selection() override;
2313-
2314
2315 private:
2316+ /// Updates buttons and text labels and returns whether a table entry is selected.
2317+ bool set_has_selection();
2318+
2319 /**
2320 * Data about a campaign that we're interested in.
2321 */
2322@@ -67,6 +68,8 @@
2323
2324 bool compare_difficulty(uint32_t, uint32_t);
2325
2326+ UI::Table<uintptr_t const> m_table;
2327+
2328 UI::Textarea m_title;
2329 UI::Textarea m_label_campname;
2330 UI::MultilineTextarea m_ta_campname;
2331@@ -97,9 +100,10 @@
2332 protected:
2333 void entry_selected() override;
2334 void fill_table() override;
2335- bool set_has_selection() override;
2336
2337 private:
2338+ /// Updates buttons and text labels and returns whether a table entry is selected.
2339+ bool set_has_selection();
2340 /**
2341 * Data about a campaign scenario that we're interested in.
2342 */
2343@@ -111,6 +115,8 @@
2344 CampaignScenarioData() : index(0) {}
2345 };
2346
2347+ UI::Table<uintptr_t const> m_table;
2348+
2349 UI::Textarea m_title;
2350 UI::MultilineTextarea m_subtitle;
2351 UI::Textarea m_label_mapname;
2352
2353=== modified file 'src/ui_fsmenu/launch_mpg.h'
2354--- src/ui_fsmenu/launch_mpg.h 2015-08-05 10:44:37 +0000
2355+++ src/ui_fsmenu/launch_mpg.h 2015-10-03 07:55:28 +0000
2356@@ -28,7 +28,7 @@
2357 #include "ui_basic/listselect.h"
2358 #include "ui_basic/multilinetextarea.h"
2359 #include "ui_basic/textarea.h"
2360-#include "ui_fsmenu/suggested_teams_box.h"
2361+#include "wui/suggested_teams_box.h"
2362
2363 struct ChatProvider;
2364 struct GameChatPanel;
2365
2366=== modified file 'src/ui_fsmenu/load_map_or_game.cc'
2367--- src/ui_fsmenu/load_map_or_game.cc 2015-08-05 10:44:37 +0000
2368+++ src/ui_fsmenu/load_map_or_game.cc 2015-10-03 07:55:28 +0000
2369@@ -21,8 +21,6 @@
2370
2371 #include <memory>
2372
2373-#include <boost/algorithm/string.hpp>
2374-
2375 #include "base/i18n.h"
2376 #include "graphic/graphic.h"
2377 #include "io/filesystem/filesystem.h"
2378@@ -35,36 +33,35 @@
2379 /// Select a Map, Saved Game or Replay in Fullscreen Mode.
2380 /// This class defines common coordinates for these UI screens.
2381 /// It also defines common buttons.
2382-FullscreenMenuLoadMapOrGame::FullscreenMenuLoadMapOrGame(bool sort_descending) :
2383+FullscreenMenuLoadMapOrGame::FullscreenMenuLoadMapOrGame() :
2384 FullscreenMenuBase("choosemapmenu.jpg"),
2385
2386 // Values for alignment and size
2387- m_padding(4),
2388- m_indent(10),
2389+ padding_(4),
2390+ indent_(10),
2391 m_label_height(20),
2392- m_tablex(get_w() * 47 / 2500),
2393- m_tabley(get_h() * 17 / 50),
2394- m_tablew(get_w() * 711 / 1250),
2395- m_tableh(get_h() * 6083 / 10000),
2396+ tablex_(get_w() * 47 / 2500),
2397+ tabley_(get_h() * 17 / 50),
2398+ tablew_(get_w() * 711 / 1250),
2399+ tableh_(get_h() * 6083 / 10000),
2400 m_right_column_margin(15),
2401- m_right_column_x(m_tablex + m_tablew + m_right_column_margin),
2402+ right_column_x_(tablex_ + tablew_ + m_right_column_margin),
2403 m_buty (get_h() * 9 / 10),
2404- m_butw ((get_w() - m_right_column_x - m_right_column_margin) / 2 - m_padding),
2405- m_buth (get_h() * 9 / 200),
2406+ m_butw ((get_w() - right_column_x_ - m_right_column_margin) / 2 - padding_),
2407+ buth_ (get_h() * 9 / 200),
2408 m_right_column_tab(get_w() - m_right_column_margin - m_butw),
2409
2410 // Main buttons
2411- m_back
2412+ back_
2413 (this, "back",
2414- m_right_column_x, m_buty, m_butw, m_buth,
2415+ right_column_x_, m_buty, m_butw, buth_,
2416 g_gr->images().get("pics/but0.png"),
2417 _("Back"), std::string(), true, false),
2418- m_ok
2419+ ok_
2420 (this, "ok",
2421- get_w() - m_right_column_margin - m_butw, m_buty, m_butw, m_buth,
2422+ get_w() - m_right_column_margin - m_butw, m_buty, m_butw, buth_,
2423 g_gr->images().get("pics/but2.png"),
2424- _("OK"), std::string(), false, false),
2425- m_table(this, m_tablex, m_tabley, m_tablew, m_tableh, sort_descending)
2426+ _("OK"), std::string(), false, false)
2427 {}
2428
2429 int32_t FullscreenMenuLoadMapOrGame::get_y_from_preceding(UI::Panel& preceding_panel) {
2430
2431=== modified file 'src/ui_fsmenu/load_map_or_game.h'
2432--- src/ui_fsmenu/load_map_or_game.h 2015-08-05 10:44:37 +0000
2433+++ src/ui_fsmenu/load_map_or_game.h 2015-10-03 07:55:28 +0000
2434@@ -34,6 +34,7 @@
2435 #include "ui_basic/multilinetextarea.h"
2436 #include "ui_basic/table.h"
2437 #include "ui_basic/textarea.h"
2438+#include "wui/maptable.h"
2439
2440
2441 namespace Widelands {
2442@@ -47,34 +48,12 @@
2443 class GameController;
2444 struct GameSettingsProvider;
2445
2446-/**
2447- * Author data for a map or scenario.
2448- */
2449-struct MapAuthorData {
2450- const std::string& get_names() const {return m_names;}
2451- size_t get_number() const {return m_number;}
2452-
2453- // Parses author list string into localized contatenated list
2454- // string. Use , as list separator and no whitespaces between
2455- // author names.
2456- void parse(const std::string& author_list) {
2457- std::vector<std::string> authors;
2458- boost::split(authors, author_list, boost::is_any_of(","));
2459- m_names = i18n::localize_list(authors, i18n::ConcatenateWith::AMPERSAND);
2460- m_number = authors.size();
2461- }
2462-
2463-private:
2464- std::string m_names;
2465- size_t m_number;
2466-};
2467-
2468 /// Select a Map, Saved Game or Replay in Fullscreen Mode.
2469 /// This class defines common coordinates for these UI screens.
2470 /// It also defines common buttons.
2471 class FullscreenMenuLoadMapOrGame : public FullscreenMenuBase {
2472 public:
2473- FullscreenMenuLoadMapOrGame(bool sortdesc = false);
2474+ FullscreenMenuLoadMapOrGame();
2475
2476 protected:
2477 // Updates the information display on the right-hand side.
2478@@ -82,13 +61,6 @@
2479 virtual void entry_selected() {}
2480 virtual void fill_table() {}
2481
2482- // Updates buttons and text labels and returns whether a table entry is selected.
2483- virtual bool set_has_selection() {
2484- bool has_selection = m_table.has_selection();
2485- m_ok.set_enabled(has_selection);
2486- return has_selection;
2487- }
2488-
2489 // Returns a y coordinate that can be used to position a Panel below the Panel directly above it
2490 int32_t get_y_from_preceding(UI::Panel& preceding_panel);
2491
2492@@ -96,20 +68,18 @@
2493 int32_t get_right_column_w(int32_t x);
2494
2495 // UI coordinates and spacers
2496- int32_t const m_padding; // Common padding between panels
2497- int32_t const m_indent; // Indent for elements below labels
2498+ int32_t const padding_; // Common padding between panels
2499+ int32_t const indent_; // Indent for elements below labels
2500 int32_t const m_label_height;
2501- int32_t const m_tablex, m_tabley, m_tablew, m_tableh;
2502+ int32_t const tablex_, tabley_, tablew_, tableh_;
2503 int32_t const m_right_column_margin; // X margins of the right column
2504- int32_t const m_right_column_x;
2505- int32_t const m_buty, m_butw, m_buth; // Button dimensions
2506+ int32_t const right_column_x_;
2507+ int32_t const m_buty, m_butw, buth_; // Button dimensions
2508 int32_t const m_right_column_tab;
2509
2510 // Main buttons
2511- UI::Button m_back;
2512- UI::Button m_ok;
2513-
2514- UI::Table<uintptr_t const> m_table;
2515+ UI::Button back_;
2516+ UI::Button ok_;
2517 };
2518
2519
2520
2521=== modified file 'src/ui_fsmenu/loadgame.cc'
2522--- src/ui_fsmenu/loadgame.cc 2015-09-04 11:03:41 +0000
2523+++ src/ui_fsmenu/loadgame.cc 2015-10-03 07:55:28 +0000
2524@@ -79,23 +79,24 @@
2525
2526 FullscreenMenuLoadGame::FullscreenMenuLoadGame
2527 (Widelands::Game & g, GameSettingsProvider * gsp, GameController * gc, bool is_replay) :
2528- FullscreenMenuLoadMapOrGame(true),
2529+ FullscreenMenuLoadMapOrGame(),
2530+ m_table(this, tablex_, tabley_, tablew_, tableh_, true),
2531
2532 m_is_replay(is_replay),
2533 // Main title
2534 m_title
2535- (this, get_w() / 2, m_tabley / 3,
2536+ (this, get_w() / 2, tabley_ / 3,
2537 m_is_replay ? _("Choose a replay") : _("Choose a saved game"), UI::Align_HCenter),
2538
2539 // Savegame description
2540 m_label_mapname
2541- (this, m_right_column_x, m_tabley, "", UI::Align_Left),
2542+ (this, right_column_x_, tabley_, "", UI::Align_Left),
2543 m_ta_mapname(this,
2544- m_right_column_x + m_indent, get_y_from_preceding(m_label_mapname) + m_padding,
2545- get_right_column_w(m_right_column_x + m_indent), 2 * m_label_height - m_padding),
2546+ right_column_x_ + indent_, get_y_from_preceding(m_label_mapname) + padding_,
2547+ get_right_column_w(right_column_x_ + indent_), 2 * m_label_height - padding_),
2548
2549 m_label_gametime
2550- (this, m_right_column_x, get_y_from_preceding(m_ta_mapname) + 2 * m_padding,
2551+ (this, right_column_x_, get_y_from_preceding(m_ta_mapname) + 2 * padding_,
2552 "",
2553 UI::Align_Left),
2554 m_ta_gametime(this,
2555@@ -103,7 +104,7 @@
2556 get_right_column_w(m_right_column_tab), m_label_height),
2557
2558 m_label_players
2559- (this, m_right_column_x, get_y_from_preceding(m_ta_gametime),
2560+ (this, right_column_x_, get_y_from_preceding(m_ta_gametime),
2561 "",
2562 UI::Align_Left),
2563 m_ta_players(this,
2564@@ -111,39 +112,39 @@
2565 get_right_column_w(m_right_column_tab), m_label_height),
2566
2567 m_label_version
2568- (this, m_right_column_x, get_y_from_preceding(m_ta_players),
2569+ (this, right_column_x_, get_y_from_preceding(m_ta_players),
2570 "",
2571 UI::Align_Left),
2572 m_ta_version(this,
2573 m_right_column_tab, m_label_version.get_y(), "", UI::Align_Left),
2574
2575 m_label_win_condition
2576- (this, m_right_column_x, get_y_from_preceding(m_ta_version) + 3 * m_padding,
2577+ (this, right_column_x_, get_y_from_preceding(m_ta_version) + 3 * padding_,
2578 "",
2579 UI::Align_Left),
2580 m_ta_win_condition(this,
2581- m_right_column_x + m_indent, get_y_from_preceding(m_label_win_condition) + m_padding,
2582- get_right_column_w(m_right_column_x + m_indent), m_label_height),
2583+ right_column_x_ + indent_, get_y_from_preceding(m_label_win_condition) + padding_,
2584+ get_right_column_w(right_column_x_ + indent_), m_label_height),
2585
2586 m_delete
2587 (this, "delete",
2588- m_right_column_x, m_buty - m_buth - 2 * m_padding,
2589- m_butw, m_buth,
2590+ right_column_x_, m_buty - buth_ - 2 * padding_,
2591+ m_butw, buth_,
2592 g_gr->images().get("pics/but0.png"),
2593 _("Delete"), std::string(), false, false),
2594
2595 m_ta_errormessage
2596 (this,
2597- m_right_column_x,
2598- get_y_from_preceding(m_ta_mapname) + 2 * m_padding,
2599- get_right_column_w(m_right_column_x),
2600- m_delete.get_y() - get_y_from_preceding(m_ta_mapname) - 6 * m_padding),
2601+ right_column_x_,
2602+ get_y_from_preceding(m_ta_mapname) + 2 * padding_,
2603+ get_right_column_w(right_column_x_),
2604+ m_delete.get_y() - get_y_from_preceding(m_ta_mapname) - 6 * padding_),
2605
2606- m_minimap_y(get_y_from_preceding(m_ta_win_condition) + 3 * m_padding),
2607- m_minimap_w(get_right_column_w(m_right_column_x)),
2608- m_minimap_h(m_delete.get_y() - get_y_from_preceding(m_ta_win_condition) - 6 * m_padding),
2609+ m_minimap_y(get_y_from_preceding(m_ta_win_condition) + 3 * padding_),
2610+ m_minimap_w(get_right_column_w(right_column_x_)),
2611+ m_minimap_h(m_delete.get_y() - get_y_from_preceding(m_ta_win_condition) - 6 * padding_),
2612 m_minimap_icon(this,
2613- m_right_column_x, get_y_from_preceding(m_ta_win_condition) + 3 * m_padding,
2614+ right_column_x_, get_y_from_preceding(m_ta_win_condition) + 3 * padding_,
2615 m_minimap_w, m_minimap_h, nullptr),
2616
2617 // "Data container" for the savegame information
2618@@ -158,20 +159,20 @@
2619 m_ta_win_condition.set_tooltip(_("The win condition that was set for this game"));
2620
2621 if (m_is_replay) {
2622- m_back.set_tooltip(_("Return to the main menu"));
2623- m_ok.set_tooltip(_("Load this replay"));
2624+ back_.set_tooltip(_("Return to the main menu"));
2625+ ok_.set_tooltip(_("Load this replay"));
2626 m_ta_mapname.set_tooltip(_("The map that this replay is based on"));
2627 m_delete.set_tooltip(_("Delete this replay"));
2628 } else {
2629- m_back.set_tooltip(_("Return to the single player menu"));
2630- m_ok.set_tooltip(_("Load this game"));
2631+ back_.set_tooltip(_("Return to the single player menu"));
2632+ ok_.set_tooltip(_("Load this game"));
2633 m_ta_mapname.set_tooltip(_("The map that this game is based on"));
2634 m_delete.set_tooltip(_("Delete this game"));
2635 }
2636 m_minimap_icon.set_visible(false);
2637
2638- m_back.sigclicked.connect(boost::bind(&FullscreenMenuLoadGame::clicked_back, boost::ref(*this)));
2639- m_ok.sigclicked.connect(boost::bind(&FullscreenMenuLoadGame::clicked_ok, boost::ref(*this)));
2640+ back_.sigclicked.connect(boost::bind(&FullscreenMenuLoadGame::clicked_back, boost::ref(*this)));
2641+ ok_.sigclicked.connect(boost::bind(&FullscreenMenuLoadGame::clicked_ok, boost::ref(*this)));
2642 m_delete.sigclicked.connect
2643 (boost::bind
2644 (&FullscreenMenuLoadGame::clicked_delete, boost::ref(*this)));
2645@@ -295,7 +296,8 @@
2646
2647 bool FullscreenMenuLoadGame::set_has_selection()
2648 {
2649- bool has_selection = FullscreenMenuLoadMapOrGame::set_has_selection();
2650+ bool has_selection = m_table.has_selection();
2651+ ok_.set_enabled(has_selection);
2652 m_delete.set_enabled(has_selection);
2653
2654 if (!has_selection) {
2655@@ -382,7 +384,7 @@
2656 uint16_t h = scale * m_minimap_image->height();
2657
2658 // Center the minimap in the available space
2659- int32_t xpos = m_right_column_x + (get_w() - m_right_column_margin - w - m_right_column_x) / 2;
2660+ int32_t xpos = right_column_x_ + (get_w() - m_right_column_margin - w - right_column_x_) / 2;
2661 int32_t ypos = m_minimap_y;
2662
2663 // Set small minimaps higher up for a more harmonious look
2664@@ -419,7 +421,7 @@
2665 m_minimap_image.reset();
2666
2667 m_ta_errormessage.set_visible(true);
2668- m_ok.set_enabled(false);
2669+ ok_.set_enabled(false);
2670 }
2671 }
2672 }
2673
2674=== modified file 'src/ui_fsmenu/loadgame.h'
2675--- src/ui_fsmenu/loadgame.h 2015-04-29 07:28:48 +0000
2676+++ src/ui_fsmenu/loadgame.h 2015-10-03 07:55:28 +0000
2677@@ -85,13 +85,15 @@
2678 void clicked_ok() override;
2679 void entry_selected() override;
2680 void fill_table() override;
2681- bool set_has_selection() override;
2682-
2683
2684 private:
2685+ /// Updates buttons and text labels and returns whether a table entry is selected.
2686+ bool set_has_selection();
2687 bool compare_date_descending(uint32_t, uint32_t);
2688 void clicked_delete();
2689
2690+ UI::Table<uintptr_t const> m_table;
2691+
2692 bool m_is_replay;
2693
2694 UI::Textarea m_title;
2695
2696=== modified file 'src/ui_fsmenu/mapselect.cc'
2697--- src/ui_fsmenu/mapselect.cc 2015-08-06 17:14:34 +0000
2698+++ src/ui_fsmenu/mapselect.cc 2015-10-03 07:55:28 +0000
2699@@ -27,233 +27,158 @@
2700 #include "base/log.h"
2701 #include "base/wexception.h"
2702 #include "graphic/graphic.h"
2703-#include "graphic/text_constants.h"
2704 #include "io/filesystem/layered_filesystem.h"
2705 #include "logic/game_controller.h"
2706 #include "logic/game_settings.h"
2707 #include "map_io/widelands_map_loader.h"
2708-#include "ui_basic/box.h"
2709
2710 using Widelands::WidelandsMapLoader;
2711
2712 FullscreenMenuMapSelect::FullscreenMenuMapSelect
2713- (GameSettingsProvider* const settings, GameController* const ctrl, bool is_editor) :
2714+ (GameSettingsProvider* const settings, GameController* const ctrl) :
2715 FullscreenMenuLoadMapOrGame(),
2716-
2717- m_is_editor(is_editor),
2718- m_checkbox_space(25),
2719- m_checkboxes_y(m_tabley - 120),
2720+ checkbox_space_(25),
2721+ checkboxes_y_(tabley_ - 120),
2722
2723 // Main title
2724- m_title
2725- (this, get_w() / 2, m_checkboxes_y / 3,
2726+ title_
2727+ (this, get_w() / 2, checkboxes_y_ / 3,
2728 _("Choose a map"),
2729 UI::Align_HCenter),
2730
2731- // Map description
2732- m_label_mapname(this, m_right_column_x, m_tabley, "", UI::Align_Left),
2733- m_ta_mapname(this,
2734- m_right_column_x + m_indent, get_y_from_preceding(m_label_mapname) + m_padding,
2735- get_right_column_w(m_right_column_x + m_indent), m_label_height),
2736-
2737- m_label_author
2738- (this, m_right_column_x, get_y_from_preceding(m_ta_mapname) + 2 * m_padding,
2739- "",
2740- UI::Align_Left),
2741- m_ta_author(this,
2742- m_right_column_x + m_indent, get_y_from_preceding(m_label_author) + m_padding,
2743- get_right_column_w(m_right_column_x + m_indent), m_label_height),
2744-
2745- m_label_description
2746- (this, m_right_column_x, get_y_from_preceding(m_ta_author) + 2 * m_padding,
2747- _("Description:"),
2748- UI::Align_Left),
2749- m_ta_description
2750- (this,
2751- m_right_column_x + m_indent,
2752- get_y_from_preceding(m_label_description) + m_padding,
2753- get_right_column_w(m_right_column_x + m_indent),
2754- m_buty - get_y_from_preceding(m_label_description) - 4 * m_padding),
2755-
2756- m_is_scenario(false),
2757-
2758- // Runtime variables
2759- m_curdir("maps"), m_basedir("maps"),
2760-
2761- m_settings(settings),
2762- m_ctrl(ctrl)
2763+ table_(this, tablex_, tabley_, tablew_, tableh_, false),
2764+ map_details_(this, right_column_x_, tabley_,
2765+ get_right_column_w(right_column_x_ + indent_),
2766+ tableh_ - buth_ - 4 * padding_),
2767+
2768+ basedir_("maps"),
2769+ settings_(settings),
2770+ ctrl_(ctrl),
2771+ has_translated_mapname_(false),
2772+ is_scenario_(false)
2773 {
2774- m_title.set_textstyle(UI::TextStyle::ui_big());
2775- if (m_is_editor) {
2776- m_back.set_tooltip(_("Return to the editor menu"));
2777+ curdir_ = basedir_,
2778+ title_.set_textstyle(UI::TextStyle::ui_big());
2779+ if (settings_->settings().multiplayer) {
2780+ back_.set_tooltip(_("Return to the multiplayer game setup"));
2781 } else {
2782- if (m_settings->settings().multiplayer) {
2783- m_back.set_tooltip(_("Return to the multiplayer game setup"));
2784- } else {
2785- m_back.set_tooltip(_("Return to the single player menu"));
2786- }
2787+ back_.set_tooltip(_("Return to the single player menu"));
2788 }
2789- m_ta_description.set_tooltip(_("Story and hints"));
2790-
2791- m_back.sigclicked.connect(boost::bind(&FullscreenMenuMapSelect::clicked_back, boost::ref(*this)));
2792- m_ok.sigclicked.connect(boost::bind(&FullscreenMenuMapSelect::clicked_ok, boost::ref(*this)));
2793- m_table.selected.connect(boost::bind(&FullscreenMenuMapSelect::entry_selected, this));
2794- m_table.double_clicked.connect(boost::bind(&FullscreenMenuMapSelect::clicked_ok, boost::ref(*this)));
2795-
2796- /** TRANSLATORS: Column title for number of players in map list */
2797- m_table.add_column(35, _("Pl."), _("Number of players"), UI::Align_HCenter);
2798- m_table.add_column(m_table.get_w() - 35 - 115, _("Map Name"), _("The name of the map or scenario"),
2799- UI::Align_Left);
2800- m_table.add_column(115, _("Size"), _("The size of the map (Width x Height)"), UI::Align_Left);
2801- m_table.set_column_compare
2802- (0,
2803- boost::bind(&FullscreenMenuMapSelect::compare_players, this, _1, _2));
2804- m_table.set_column_compare
2805- (1,
2806- boost::bind(&FullscreenMenuMapSelect::compare_mapnames, this, _1, _2));
2807- m_table.set_column_compare
2808- (2,
2809- boost::bind(&FullscreenMenuMapSelect::compare_size, this, _1, _2));
2810- m_table.set_sort_column(0);
2811- m_is_scenario = false;
2812-
2813- // Suggested teams
2814- // Y coordinate will be set later, when we know how high this box will get.
2815- m_suggested_teams_box = new UI::SuggestedTeamsBox(this, m_right_column_x, 0, UI::Box::Vertical,
2816- m_padding, m_indent, m_label_height,
2817- get_w() - m_right_column_x, 4 * m_label_height);
2818-
2819- UI::Box* vbox = new UI::Box(this, m_tablex, m_checkboxes_y,
2820- UI::Box::Horizontal, m_checkbox_space, get_w());
2821+
2822+ back_.sigclicked.connect(boost::bind(&FullscreenMenuMapSelect::clicked_back, boost::ref(*this)));
2823+ ok_.sigclicked.connect(boost::bind(&FullscreenMenuMapSelect::clicked_ok, boost::ref(*this)));
2824+ table_.selected.connect(boost::bind(&FullscreenMenuMapSelect::entry_selected, this));
2825+ table_.double_clicked.connect(boost::bind(&FullscreenMenuMapSelect::clicked_ok, boost::ref(*this)));
2826+ table_.set_column_compare(0, boost::bind(&FullscreenMenuMapSelect::compare_players, this, _1, _2));
2827+ table_.set_column_compare(1, boost::bind(&FullscreenMenuMapSelect::compare_mapnames, this, _1, _2));
2828+ table_.set_column_compare(2, boost::bind(&FullscreenMenuMapSelect::compare_size, this, _1, _2));
2829+
2830+ UI::Box* vbox = new UI::Box(this, tablex_, checkboxes_y_,
2831+ UI::Box::Horizontal, checkbox_space_, get_w());
2832
2833 // Must be initialized before tag checkboxes
2834- m_cb_dont_localize_mapnames = new UI::Checkbox(vbox, Point(0, 0));
2835- m_cb_dont_localize_mapnames->set_state(false);
2836- m_cb_dont_localize_mapnames->changedto.connect
2837+ cb_dont_localize_mapnames_ = new UI::Checkbox(vbox, Point(0, 0));
2838+ cb_dont_localize_mapnames_->set_state(false);
2839+ cb_dont_localize_mapnames_->changedto.connect
2840 (boost::bind(&FullscreenMenuMapSelect::fill_table, boost::ref(*this)));
2841
2842- m_cb_show_all_maps = _add_tag_checkbox(vbox, "blumba", _("Show all maps"));
2843- m_tags_checkboxes.clear(); // Remove this again, it is a special tag checkbox
2844- m_cb_show_all_maps->set_state(true);
2845+ cb_show_all_maps_ = _add_tag_checkbox(vbox, "blumba", _("Show all maps"));
2846+ tags_checkboxes_.clear(); // Remove this again, it is a special tag checkbox
2847+ cb_show_all_maps_->set_state(true);
2848
2849- vbox->add(m_cb_dont_localize_mapnames, UI::Box::AlignLeft, true);
2850+ vbox->add(cb_dont_localize_mapnames_, UI::Box::AlignLeft, true);
2851 UI::Textarea * ta_dont_localize_mapnames =
2852 /** TRANSLATORS: Checkbox title. If this checkbox is enabled, map names aren't translated. */
2853 new UI::Textarea(vbox, _("Show original map names"), UI::Align_CenterLeft);
2854- vbox->add_space(m_padding);
2855+ vbox->add_space(padding_);
2856 vbox->add(ta_dont_localize_mapnames, UI::Box::AlignLeft);
2857- vbox->add_space(m_checkbox_space);
2858- vbox->set_size(get_w() - 2 * m_tablex, m_checkbox_space);
2859+ vbox->add_space(checkbox_space_);
2860+ vbox->set_size(get_w() - 2 * tablex_, checkbox_space_);
2861
2862 vbox = new UI::Box(this,
2863- m_tablex, vbox->get_y() + vbox->get_h() + m_padding,
2864- UI::Box::Horizontal, m_checkbox_space, get_w());
2865+ tablex_, vbox->get_y() + vbox->get_h() + padding_,
2866+ UI::Box::Horizontal, checkbox_space_, get_w());
2867 _add_tag_checkbox(vbox, "official", _("Official"));
2868 _add_tag_checkbox(vbox, "unbalanced", _("Unbalanced"));
2869 _add_tag_checkbox(vbox, "seafaring", _("Seafaring"));
2870 _add_tag_checkbox(vbox, "scenario", _("Scenario"));
2871- vbox->set_size(get_w() - 2 * m_tablex, m_checkbox_space);
2872+ vbox->set_size(get_w() - 2 * tablex_, checkbox_space_);
2873
2874 vbox = new UI::Box(this,
2875- m_tablex, vbox->get_y() + vbox->get_h() + m_padding,
2876- UI::Box::Horizontal, m_checkbox_space, get_w());
2877+ tablex_, vbox->get_y() + vbox->get_h() + padding_,
2878+ UI::Box::Horizontal, checkbox_space_, get_w());
2879 _add_tag_checkbox(vbox, "ffa", _("Free for all"));
2880 _add_tag_checkbox(vbox, "1v1", _("1v1"));
2881
2882- vbox->set_size(get_w() - 2 * m_tablex, m_checkbox_space);
2883+ vbox->set_size(get_w() - 2 * tablex_, checkbox_space_);
2884
2885 vbox = new UI::Box(this,
2886- m_tablex, vbox->get_y() + vbox->get_h() + m_padding,
2887- UI::Box::Horizontal, m_checkbox_space, get_w());
2888+ tablex_, vbox->get_y() + vbox->get_h() + padding_,
2889+ UI::Box::Horizontal, checkbox_space_, get_w());
2890 _add_tag_checkbox(vbox, "2teams", _("Teams of 2"));
2891 _add_tag_checkbox(vbox, "3teams", _("Teams of 3"));
2892 _add_tag_checkbox(vbox, "4teams", _("Teams of 4"));
2893- vbox->set_size(get_w() - 2 * m_tablex, m_checkbox_space);
2894-
2895- m_scenario_types = m_settings->settings().multiplayer ? Map::MP_SCENARIO : Map::SP_SCENARIO;
2896-
2897- m_table.focus();
2898+ vbox->set_size(get_w() - 2 * tablex_, checkbox_space_);
2899+
2900+ scenario_types_ = settings_->settings().multiplayer ? Map::MP_SCENARIO : Map::SP_SCENARIO;
2901+
2902+ table_.focus();
2903 fill_table();
2904
2905 // We don't need the unlocalizing option if there is nothing to unlocalize.
2906 // We know this after the list is filled.
2907- m_cb_dont_localize_mapnames->set_visible(m_has_translated_mapname);
2908- ta_dont_localize_mapnames->set_visible(m_has_translated_mapname);
2909+ cb_dont_localize_mapnames_->set_visible(has_translated_mapname_);
2910+ ta_dont_localize_mapnames->set_visible(has_translated_mapname_);
2911 }
2912
2913 void FullscreenMenuMapSelect::think()
2914 {
2915- if (m_ctrl) {
2916- m_ctrl->think();
2917+ if (ctrl_) {
2918+ ctrl_->think();
2919 }
2920 }
2921
2922
2923 bool FullscreenMenuMapSelect::compare_players(uint32_t rowa, uint32_t rowb)
2924 {
2925- const MapData & r1 = m_maps_data[m_table[rowa]];
2926- const MapData & r2 = m_maps_data[m_table[rowb]];
2927-
2928- if (r1.nrplayers == r2.nrplayers) {
2929- return compare_mapnames(rowa, rowb);
2930- }
2931- return r1.nrplayers < r2.nrplayers;
2932+ return maps_data_[table_[rowa]].compare_players(maps_data_[table_[rowb]]);
2933 }
2934
2935
2936 bool FullscreenMenuMapSelect::compare_mapnames(uint32_t rowa, uint32_t rowb)
2937 {
2938- const MapData & r1 = m_maps_data[m_table[rowa]];
2939- const MapData & r2 = m_maps_data[m_table[rowb]];
2940-
2941- if (!r1.width && !r2.width) {
2942- return r1.name < r2.name;
2943- } else if (!r1.width && r2.width) {
2944- return true;
2945- } else if (r1.width && !r2.width) {
2946- return false;
2947- } else if (m_cb_dont_localize_mapnames->get_state()) {
2948- return r1.name < r2.name;
2949- }
2950- return r1.localized_name < r2.localized_name;
2951+ return maps_data_[table_[rowa]].compare_names(maps_data_[table_[rowb]]);
2952 }
2953
2954
2955 bool FullscreenMenuMapSelect::compare_size(uint32_t rowa, uint32_t rowb)
2956 {
2957- const MapData & r1 = m_maps_data[m_table[rowa]];
2958- const MapData & r2 = m_maps_data[m_table[rowb]];
2959-
2960- if (r1.width != r2.width) {
2961- return r1.width < r2.width;
2962- } else if (r1.height == r2.height) {
2963- return compare_mapnames(rowa, rowb);
2964- }
2965- return r1.height < r2.height;
2966+ return maps_data_[table_[rowa]].compare_size(maps_data_[table_[rowb]]);
2967 }
2968
2969
2970 bool FullscreenMenuMapSelect::is_scenario()
2971 {
2972- return m_is_scenario;
2973+ return is_scenario_;
2974 }
2975
2976
2977 MapData const * FullscreenMenuMapSelect::get_map() const
2978 {
2979- if (!m_table.has_selection()) {
2980+ if (!table_.has_selection()) {
2981 return nullptr;
2982 }
2983- return &m_maps_data[m_table.get_selected()];
2984+ return &maps_data_[table_.get_selected()];
2985 }
2986
2987
2988 void FullscreenMenuMapSelect::clicked_ok()
2989 {
2990- const MapData & mapdata = m_maps_data[m_table.get_selected()];
2991+ assert(table_.has_selection());
2992+ const MapData& mapdata = maps_data_[table_.get_selected()];
2993
2994 if (!mapdata.width) {
2995- m_curdir = mapdata.filename;
2996+ curdir_ = mapdata.filename;
2997 fill_table();
2998 } else {
2999 if (is_scenario()) {
3000@@ -266,19 +191,11 @@
3001
3002 bool FullscreenMenuMapSelect::set_has_selection()
3003 {
3004- bool has_selection = m_table.has_selection();
3005- FullscreenMenuLoadMapOrGame::set_has_selection();
3006+ bool has_selection = table_.has_selection();
3007+ ok_.set_enabled(has_selection);
3008
3009 if (!has_selection) {
3010- m_label_mapname.set_text(std::string());
3011- m_label_author.set_text(std::string());
3012- m_label_description.set_text(std::string());
3013-
3014- m_ta_mapname.set_text(std::string());
3015- m_ta_author.set_text(std::string());
3016- m_ta_description.set_text(std::string());
3017-
3018- m_suggested_teams_box->hide();
3019+ map_details_.clear();
3020 }
3021 return has_selection;
3022 }
3023@@ -287,78 +204,7 @@
3024 void FullscreenMenuMapSelect::entry_selected()
3025 {
3026 if (set_has_selection()) {
3027- const MapData & map = m_maps_data[m_table.get_selected()];
3028-
3029- if (map.width) {
3030- // Show map information
3031- if (map.scenario) {
3032- m_label_mapname.set_text(_("Scenario:"));
3033- } else {
3034- m_label_mapname.set_text(_("Map:"));
3035- }
3036- std::string map_displayname = map.localized_name;
3037- if (m_cb_dont_localize_mapnames->get_state()) {
3038- map_displayname = map.name;
3039- }
3040- m_ta_mapname.set_text(map_displayname);
3041- if (map.localized_name != map.name) {
3042- if (m_cb_dont_localize_mapnames->get_state()) {
3043- m_ta_mapname.set_tooltip
3044- /** TRANSLATORS: Tooltip in map description when map names are being displayed in English. */
3045- /** TRANSLATORS: %s is the localized name of the map. */
3046- ((boost::format(_("The name of this map in your language: %s"))
3047- % map.localized_name).str());
3048- } else {
3049- m_ta_mapname.set_tooltip
3050- /** TRANSLATORS: Tooltip in map description when translated map names are being displayed. */
3051- /** TRANSLATORS: %s is the English name of the map. */
3052- ((boost::format(_("The original name of this map: %s"))
3053- % map.name).str());
3054- }
3055- } else {
3056- m_ta_mapname.set_tooltip(_("The name of this map"));
3057- }
3058- m_label_author.set_text(ngettext("Author:", "Authors:", map.authors.get_number()));
3059- m_ta_author.set_tooltip(ngettext("The designer of this map", "The designers of this map",
3060- map.authors.get_number()));
3061- m_ta_author.set_text(map.authors.get_names());
3062- m_ta_description.set_text(map.description +
3063- (map.hint.empty() ? "" : (std::string("\n\n") + map.hint)));
3064- m_label_author.set_visible(true);
3065- m_label_description.set_visible(true);
3066- m_ta_description.set_size
3067- (m_ta_description.get_w(),
3068- m_buty - get_y_from_preceding(m_label_description) - 4 * m_padding);
3069- m_ok.set_tooltip(m_is_editor ? _("Edit this map") : _("Play this map"));
3070- } else {
3071- // Show directory information
3072- m_label_mapname.set_text(_("Directory:"));
3073- m_ta_mapname.set_text(map.localized_name);
3074- m_ta_mapname.set_tooltip(_("The name of this directory"));
3075-
3076- m_ta_author.set_text(std::string());
3077- m_ta_description.set_text(std::string());
3078- m_label_author.set_visible(false);
3079- m_label_description.set_visible(false);
3080- m_ok.set_tooltip(_("Open this directory"));
3081- }
3082-
3083- m_is_scenario = map.scenario; // reset
3084- m_ta_description.scroll_to_top();
3085-
3086- // Show / hide suggested teams
3087- m_suggested_teams_box->hide();
3088-
3089- if (!map.suggested_teams.empty()) {
3090- m_suggested_teams_box->show(map.suggested_teams);
3091-
3092- m_suggested_teams_box->set_pos(
3093- Point(m_suggested_teams_box->get_x(),
3094- m_buty - m_padding - m_suggested_teams_box->get_h() - m_padding));
3095-
3096- m_ta_description.set_size(m_ta_description.get_w(),
3097- m_suggested_teams_box->get_y() - m_ta_description.get_y() - 3 * m_padding);
3098- }
3099+ map_details_.update(maps_data_[table_.get_selected()], !cb_dont_localize_mapnames_->get_state());
3100 }
3101 }
3102
3103@@ -375,7 +221,7 @@
3104 * be taken to sort uncompressed maps (which look like and really are
3105 * directories) with the files.
3106 *
3107- * The search starts in \ref m_curdir ("..../maps") and there is no possibility
3108+ * The search starts in \ref curdir_ ("..../maps") and there is no possibility
3109 * to move further up. If the user moves down into subdirectories, we insert an
3110 * entry to move back up.
3111 *
3112@@ -384,162 +230,89 @@
3113 */
3114 void FullscreenMenuMapSelect::fill_table()
3115 {
3116- uint8_t col_players = 0;
3117- uint8_t col_name = 1;
3118- uint8_t col_size = 2;
3119-
3120- m_maps_data.clear();
3121- m_table.clear();
3122- m_has_translated_mapname = false;
3123-
3124-
3125- if (m_settings->settings().maps.empty()) {
3126+ has_translated_mapname_ = false;
3127+
3128+ maps_data_.clear();
3129+
3130+ MapData::DisplayType display_type;
3131+ if (cb_dont_localize_mapnames_->get_state()) {
3132+ display_type = MapData::DisplayType::kMapnames;
3133+ } else {
3134+ display_type = MapData::DisplayType::kMapnamesLocalized;
3135+ }
3136+
3137+ if (settings_->settings().maps.empty()) {
3138 // This is the normal case
3139
3140 // Fill it with all files we find in all directories.
3141- FilenameSet files = g_fs->list_directory(m_curdir);
3142-
3143- int32_t ndirs = 0;
3144+ FilenameSet files = g_fs->list_directory(curdir_);
3145
3146 //If we are not at the top of the map directory hierarchy (we're not talking
3147 //about the absolute filesystem top!) we manually add ".."
3148- if (m_curdir != m_basedir) {
3149- MapData mapdata;
3150- #ifndef _WIN32
3151- mapdata.filename = m_curdir.substr(0, m_curdir.rfind('/'));
3152- #else
3153- mapdata.filename = m_curdir.substr(0, m_curdir.rfind('\\'));
3154- #endif
3155- mapdata.localized_name = (boost::format("\\<%s\\>") % _("parent")).str();
3156- m_maps_data.push_back(mapdata);
3157- UI::Table<uintptr_t const>::EntryRecord & te =
3158- m_table.add(m_maps_data.size() - 1);
3159-
3160- te.set_string(col_players, "");
3161- te.set_picture
3162- (col_name, g_gr->images().get("pics/ls_dir.png"),
3163- mapdata.localized_name);
3164- te.set_string(col_size, "");
3165-
3166- ++ndirs;
3167+ if (curdir_ != basedir_) {
3168+ maps_data_.push_back(MapData::create_parent_dir(curdir_));
3169 }
3170
3171- //Add subdirectories to the list (except for uncompressed maps)
3172+ Widelands::Map map; // MapLoader needs a place to put its preload data
3173+
3174 for (const std::string& mapfilename : files) {
3175- char const * const name = mapfilename.c_str();
3176- if (!strcmp(FileSystem::fs_filename(name), "."))
3177- continue;
3178- // Upsy, appeared again. ignore
3179- if (!strcmp(FileSystem::fs_filename(name), ".."))
3180- continue;
3181- if (!g_fs->is_directory(name))
3182- continue;
3183- if (WidelandsMapLoader::is_widelands_map(name))
3184- continue;
3185-
3186- MapData mapdata;
3187- mapdata.filename = name;
3188- if (strcmp (name, "maps/MP Scenarios") == 0) {
3189- /** TRANSLATORS: Directory name for MP Scenarios in map selection */
3190- mapdata.localized_name = _("Multiplayer Scenarios");
3191- } else {
3192- mapdata.localized_name = FileSystem::fs_filename(name);
3193- }
3194-
3195- m_maps_data.push_back(mapdata);
3196- UI::Table<uintptr_t const>::EntryRecord & te = m_table.add(m_maps_data.size() - 1);
3197-
3198- te.set_string(col_players, "");
3199- te.set_picture(col_name, g_gr->images().get("pics/ls_dir.png"), mapdata.localized_name);
3200- te.set_string(col_size, "");
3201-
3202- ++ndirs;
3203- }
3204-
3205- //Add map files(compressed maps) and directories(uncompressed)
3206- {
3207- Widelands::Map map; // MapLoader needs a place to put its preload data
3208-
3209- for (const std::string& mapfilename : files) {
3210-
3211+
3212+ // Add map file (compressed) or map directory (uncompressed)
3213+ if (Widelands::WidelandsMapLoader::is_widelands_map(mapfilename)) {
3214 std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(mapfilename);
3215- if (!ml) {
3216+ if (ml.get() != nullptr) {
3217+ try {
3218+ map.set_filename(mapfilename);
3219+ ml->preload_map(true);
3220+
3221+ if (!map.get_width() || !map.get_height()) {
3222+ continue;
3223+ }
3224+
3225+ MapData::MapType maptype;
3226+ if (map.scenario_types() & scenario_types_) {
3227+ maptype = MapData::MapType::kScenario;
3228+ } else if (dynamic_cast<WidelandsMapLoader*>(ml.get())) {
3229+ maptype = MapData::MapType::kNormal;
3230+ } else {
3231+ maptype = MapData::MapType::kSettlers2;
3232+ }
3233+
3234+ MapData mapdata(map, mapfilename, maptype, display_type);
3235+
3236+ has_translated_mapname_ =
3237+ has_translated_mapname_ || (mapdata.name != mapdata.localized_name);
3238+
3239+ bool has_all_tags = true;
3240+ for (std::set<uint32_t>::const_iterator it = req_tags_.begin(); it != req_tags_.end(); ++it)
3241+ has_all_tags &= mapdata.tags.count(tags_ordered_[*it]);
3242+ if (!has_all_tags) {
3243+ continue;
3244+ }
3245+ maps_data_.push_back(mapdata);
3246+ } catch (const std::exception & e) {
3247+ log("Mapselect: Skip %s due to preload error: %s\n", mapfilename.c_str(), e.what());
3248+ } catch (...) {
3249+ log("Mapselect: Skip %s due to unknown exception\n", mapfilename.c_str());
3250+ }
3251+ }
3252+ } else if (g_fs->is_directory(mapfilename)) {
3253+ // Add subdirectory to the list
3254+ const char* fs_filename = FileSystem::fs_filename(mapfilename.c_str());
3255+ if (!strcmp(fs_filename, ".") || !strcmp(fs_filename, ".."))
3256 continue;
3257- }
3258-
3259- try {
3260- map.set_filename(mapfilename);
3261- ml->preload_map(true);
3262-
3263- i18n::Textdomain td("maps");
3264-
3265- MapData mapdata;
3266- mapdata.filename = mapfilename;
3267- mapdata.name = map.get_name();
3268- mapdata.localized_name = mapdata.name.empty() ? "" : _(mapdata.name);
3269- mapdata.authors.parse(map.get_author());
3270- mapdata.description = map.get_description().empty() ? "" : _(map.get_description());
3271- mapdata.hint = map.get_hint().empty() ? "" : _(map.get_hint());
3272- mapdata.nrplayers = map.get_nrplayers();
3273- mapdata.width = map.get_width();
3274- mapdata.height = map.get_height();
3275- mapdata.scenario = map.scenario_types() & m_scenario_types
3276- || (m_is_editor && map.scenario_types() > 0);
3277- mapdata.tags = map.get_tags();
3278- if (mapdata.scenario) {
3279- mapdata.tags.insert("scenario");
3280- }
3281- mapdata.suggested_teams = map.get_suggested_teams();
3282-
3283- m_has_translated_mapname =
3284- m_has_translated_mapname || (mapdata.name != mapdata.localized_name);
3285-
3286- if (!mapdata.width || !mapdata.height) {
3287- continue;
3288- }
3289-
3290- bool has_all_tags = true;
3291- for (std::set<uint32_t>::const_iterator it = m_req_tags.begin(); it != m_req_tags.end(); ++it)
3292- has_all_tags &= mapdata.tags.count(m_tags_ordered[*it]);
3293- if (!has_all_tags) {
3294- continue;
3295- }
3296-
3297- m_maps_data.push_back(mapdata);
3298- UI::Table<uintptr_t const>::EntryRecord & te = m_table.add(m_maps_data.size() - 1);
3299-
3300- te.set_string(col_players, (boost::format("(%i)") % mapdata.nrplayers).str());
3301-
3302- std::string map_displayname = mapdata.localized_name;
3303- if (m_cb_dont_localize_mapnames->get_state()) {
3304- map_displayname = mapdata.name;
3305- }
3306- te.set_picture
3307- (col_name, g_gr->images().get
3308- (dynamic_cast<WidelandsMapLoader*>(ml.get()) ?
3309- (mapdata.scenario ? "pics/ls_wlscenario.png" : "pics/ls_wlmap.png") :
3310- "pics/ls_s2map.png"),
3311- map_displayname);
3312-
3313- te.set_string(col_size, (boost::format("%u x %u") % mapdata.width % mapdata.height).str());
3314- } catch (const std::exception & e) {
3315- log("Mapselect: Skip %s due to preload error: %s\n", mapfilename.c_str(), e.what());
3316- } catch (...) {
3317- log("Mapselect: Skip %s due to unknown exception\n", mapfilename.c_str());
3318- }
3319+ maps_data_.push_back(MapData::create_directory(mapfilename));
3320 }
3321 }
3322 } else {
3323 //client changing maps on dedicated server
3324- for (uint16_t i = 0; i < m_settings->settings().maps.size(); ++i) {
3325+ for (uint16_t i = 0; i < settings_->settings().maps.size(); ++i) {
3326 Widelands::Map map; // MapLoader needs a place to put its preload data
3327
3328- const DedicatedMapInfos & dmap = m_settings->settings().maps.at(i);
3329+ const DedicatedMapInfos & dmap = settings_->settings().maps.at(i);
3330 const std::string& mapfilename = dmap.path;
3331 std::unique_ptr<Widelands::MapLoader> ml(map.get_correct_loader(mapfilename));
3332
3333- i18n::Textdomain td("maps");
3334- MapData mapdata;
3335 try {
3336 if (!ml) {
3337 throw wexception("Mapselect: No MapLoader");
3338@@ -548,68 +321,61 @@
3339 map.set_filename(mapfilename);
3340 ml->preload_map(true);
3341
3342- mapdata.filename = mapfilename;
3343- mapdata.name = map.get_name();
3344- mapdata.authors.parse(map.get_author());
3345- mapdata.description = map.get_description();
3346- mapdata.hint = map.get_hint();
3347- mapdata.nrplayers = map.get_nrplayers();
3348- mapdata.width = map.get_width();
3349- mapdata.height = map.get_height();
3350- mapdata.scenario = map.scenario_types() & m_scenario_types;
3351-
3352- if (mapdata.nrplayers != dmap.players || mapdata.scenario != dmap.scenario) {
3353+ if (!map.get_width() || !map.get_height()) {
3354+ throw wexception("Mapselect: Map has no size");
3355+ }
3356+
3357+ MapData::MapType maptype;
3358+
3359+ if (map.scenario_types() & scenario_types_) {
3360+ maptype = MapData::MapType::kScenario;
3361+ } else if (dynamic_cast<WidelandsMapLoader*>(ml.get())) {
3362+ maptype = MapData::MapType::kSettlers2;
3363+ } else {
3364+ maptype = MapData::MapType::kNormal;
3365+ }
3366+
3367+ if (map.get_nrplayers() != dmap.players ||
3368+ (maptype == MapData::MapType::kScenario) != dmap.scenario) {
3369 throw wexception("Mapselect: Number of players or scenario doesn't match");
3370 }
3371
3372- if (!mapdata.width || !mapdata.height) {
3373- throw wexception("Mapselect: Map has no size");
3374- }
3375+ MapData mapdata(map, mapfilename, maptype, display_type);
3376
3377 // Finally write the entry to the list
3378- m_maps_data.push_back(mapdata);
3379- UI::Table<uintptr_t const>::EntryRecord & te = m_table.add(m_maps_data.size() - 1);
3380-
3381- te.set_string(col_players, (boost::format("(%i)") % mapdata.nrplayers).str());
3382- te.set_picture
3383- (col_name,
3384- g_gr->images().get((mapdata.scenario ? "pics/ls_wlscenario.png" : "pics/ls_wlmap.png")),
3385- mapdata.name.c_str());
3386- te.set_string(col_size, (boost::format("%u x %u") % mapdata.width % mapdata.height).str());
3387-
3388+ maps_data_.push_back(mapdata);
3389 } catch (...) {
3390 log("Mapselect: Skipped reading locale data for file %s - not valid.\n", mapfilename.c_str());
3391
3392+ MapData mapdata;
3393+
3394 // Fill in the data we got from the dedicated server
3395 mapdata.filename = mapfilename;
3396 mapdata.name = mapfilename.substr(5, mapfilename.size() - 1);
3397- mapdata.authors.parse(_("Nobody"));
3398+ mapdata.authors = MapAuthorData(_("Nobody"));
3399 mapdata.description = _("This map file is not present in your filesystem."
3400 " The data shown here was sent by the server.");
3401 mapdata.hint = "";
3402 mapdata.nrplayers = dmap.players;
3403 mapdata.width = 1;
3404 mapdata.height = 0;
3405- mapdata.scenario = dmap.scenario;
3406+ mapdata.displaytype = display_type;
3407+
3408+ if (dmap.scenario) {
3409+ mapdata.maptype = MapData::MapType::kScenario;
3410+ mapdata.tags.insert("scenario");
3411+ } else if (dynamic_cast<WidelandsMapLoader*>(ml.get())) {
3412+ mapdata.maptype = MapData::MapType::kSettlers2;
3413+ } else {
3414+ mapdata.maptype = MapData::MapType::kNormal;
3415+ }
3416
3417 // Finally write the entry to the list
3418- m_maps_data.push_back(mapdata);
3419- UI::Table<uintptr_t const>::EntryRecord & te = m_table.add(m_maps_data.size() - 1);
3420-
3421- te.set_string(col_players, (boost::format("(%i)") % mapdata.nrplayers).str());
3422- te.set_picture
3423- (col_name, g_gr->images().get
3424- ((mapdata.scenario ? "pics/ls_wlscenario.png" : "pics/ls_wlmap.png")),
3425- mapdata.name.c_str());
3426- te.set_string(col_size, (boost::format("%u x %u") % mapdata.width % mapdata.height).str());
3427+ maps_data_.push_back(mapdata);
3428 }
3429 }
3430 }
3431- m_table.sort();
3432-
3433- if (m_table.size()) {
3434- m_table.select(0);
3435- }
3436+ table_.fill(maps_data_, display_type);
3437 }
3438
3439 /*
3440@@ -618,8 +384,8 @@
3441 UI::Checkbox * FullscreenMenuMapSelect::_add_tag_checkbox
3442 (UI::Box * box, std::string tag, std::string displ_name)
3443 {
3444- int32_t id = m_tags_ordered.size();
3445- m_tags_ordered.push_back(tag);
3446+ int32_t id = tags_ordered_.size();
3447+ tags_ordered_.push_back(tag);
3448
3449 UI::Checkbox * cb = new UI::Checkbox(box, Point(0, 0));
3450 cb->changedto.connect
3451@@ -627,11 +393,11 @@
3452
3453 box->add(cb, UI::Box::AlignLeft, true);
3454 UI::Textarea * ta = new UI::Textarea(box, displ_name, UI::Align_CenterLeft);
3455- box->add_space(m_padding);
3456+ box->add_space(padding_);
3457 box->add(ta, UI::Box::AlignLeft);
3458- box->add_space(m_checkbox_space);
3459+ box->add_space(checkbox_space_);
3460
3461- m_tags_checkboxes.push_back(cb);
3462+ tags_checkboxes_.push_back(cb);
3463
3464 return cb;
3465 }
3466@@ -642,23 +408,23 @@
3467 void FullscreenMenuMapSelect::_tagbox_changed(int32_t id, bool to) {
3468 if (id == 0) { // Show all maps checbox
3469 if (to) {
3470- for (UI::Checkbox * checkbox : m_tags_checkboxes) {
3471+ for (UI::Checkbox * checkbox : tags_checkboxes_) {
3472 checkbox->set_state(false);
3473 }
3474 }
3475 } else { // Any tag
3476 if (to) {
3477- m_req_tags.insert(id);
3478+ req_tags_.insert(id);
3479 }
3480 else {
3481- m_req_tags.erase(id);
3482+ req_tags_.erase(id);
3483 }
3484 }
3485- if (m_req_tags.empty()) {
3486- m_cb_show_all_maps->set_state(true);
3487+ if (req_tags_.empty()) {
3488+ cb_show_all_maps_->set_state(true);
3489 }
3490 else {
3491- m_cb_show_all_maps->set_state(false);
3492+ cb_show_all_maps_->set_state(false);
3493 }
3494
3495 fill_table();
3496
3497=== modified file 'src/ui_fsmenu/mapselect.h'
3498--- src/ui_fsmenu/mapselect.h 2014-11-13 08:39:14 +0000
3499+++ src/ui_fsmenu/mapselect.h 2015-10-03 07:55:28 +0000
3500@@ -20,56 +20,28 @@
3501 #ifndef WL_UI_FSMENU_MAPSELECT_H
3502 #define WL_UI_FSMENU_MAPSELECT_H
3503
3504-#include <set>
3505 #include <string>
3506+#include <vector>
3507
3508 #include "ui_fsmenu/base.h"
3509-#include "logic/map.h"
3510-#include "ui_basic/button.h"
3511+#include "ui_basic/box.h"
3512 #include "ui_basic/checkbox.h"
3513-#include "ui_basic/multilinetextarea.h"
3514-#include "ui_basic/table.h"
3515 #include "ui_basic/textarea.h"
3516 #include "ui_fsmenu/load_map_or_game.h"
3517-#include "ui_fsmenu/suggested_teams_box.h"
3518-
3519+#include "wui/mapdetails.h"
3520+#include "wui/maptable.h"
3521
3522 using Widelands::Map;
3523 class GameController;
3524 struct GameSettingsProvider;
3525
3526-namespace UI {
3527- struct Box;
3528-}
3529-
3530-/**
3531- * Data about a map that we're interested in.
3532- */
3533-struct MapData {
3534- using Tags = std::set<std::string>;
3535-
3536- std::string filename;
3537- std::string name;
3538- std::string localized_name;
3539- std::string description;
3540- std::string hint;
3541- Tags tags;
3542- std::vector<Map::SuggestedTeamLineup> suggested_teams;
3543-
3544- MapAuthorData authors;
3545- uint32_t width = 0;
3546- uint32_t height = 0;
3547- uint32_t nrplayers = 0;
3548- bool scenario = false; // is this a scenario we should list?
3549-};
3550-
3551
3552 /**
3553 * Select a Map in Fullscreen Mode. It's a modal fullscreen menu
3554 */
3555 class FullscreenMenuMapSelect : public FullscreenMenuLoadMapOrGame {
3556 public:
3557- FullscreenMenuMapSelect(GameSettingsProvider*, GameController*, bool is_editor = false);
3558+ FullscreenMenuMapSelect(GameSettingsProvider*, GameController*);
3559
3560 bool is_scenario();
3561 MapData const* get_map() const;
3562@@ -79,48 +51,44 @@
3563 void clicked_ok() override;
3564 void entry_selected() override;
3565 void fill_table() override;
3566- bool set_has_selection() override;
3567-
3568
3569 private:
3570 bool compare_players(uint32_t, uint32_t);
3571 bool compare_mapnames(uint32_t, uint32_t);
3572 bool compare_size(uint32_t, uint32_t);
3573
3574+ /// Updates buttons and text labels and returns whether a table entry is selected.
3575+ bool set_has_selection();
3576 UI::Checkbox* _add_tag_checkbox(UI::Box*, std::string, std::string);
3577 void _tagbox_changed(int32_t, bool);
3578
3579- bool const m_is_editor;
3580- int32_t const m_checkbox_space;
3581- int32_t const m_checkboxes_y;
3582-
3583- UI::Textarea m_title;
3584- UI::Textarea m_label_mapname;
3585- UI::MultilineTextarea m_ta_mapname;
3586- UI::Textarea m_label_author;
3587- UI::MultilineTextarea m_ta_author;
3588- UI::Textarea m_label_description;
3589- UI::MultilineTextarea m_ta_description;
3590-
3591- UI::Checkbox* m_cb_dont_localize_mapnames;
3592- bool m_has_translated_mapname;
3593-
3594- UI::Checkbox* m_cb_show_all_maps;
3595- std::vector<UI::Checkbox*> m_tags_checkboxes;
3596-
3597- UI::SuggestedTeamsBox* m_suggested_teams_box;
3598-
3599- bool m_is_scenario;
3600- std::string m_curdir, m_basedir;
3601- Map::ScenarioTypes m_scenario_types;
3602-
3603- std::vector<std::string> m_tags_ordered;
3604- std::set<uint32_t> m_req_tags;
3605-
3606- std::vector<MapData> m_maps_data;
3607-
3608- GameSettingsProvider* m_settings;
3609- GameController* m_ctrl;
3610+ int32_t const checkbox_space_;
3611+ int32_t const checkboxes_y_;
3612+
3613+ UI::Textarea title_;
3614+
3615+ MapTable table_;
3616+ MapDetails map_details_;
3617+
3618+ const std::string basedir_;
3619+ std::string curdir_;
3620+
3621+ GameSettingsProvider* settings_;
3622+ GameController* ctrl_;
3623+
3624+ UI::Checkbox* cb_dont_localize_mapnames_;
3625+ bool has_translated_mapname_;
3626+
3627+ UI::Checkbox* cb_show_all_maps_;
3628+ std::vector<UI::Checkbox*> tags_checkboxes_;
3629+
3630+ bool is_scenario_;
3631+ Map::ScenarioTypes scenario_types_;
3632+
3633+ std::vector<std::string> tags_ordered_;
3634+ std::set<uint32_t> req_tags_;
3635+
3636+ std::vector<MapData> maps_data_;
3637 };
3638
3639 #endif // end of include guard: WL_UI_FSMENU_MAPSELECT_H
3640
3641=== modified file 'src/wlapplication.cc'
3642--- src/wlapplication.cc 2015-08-10 08:21:37 +0000
3643+++ src/wlapplication.cc 2015-10-03 07:55:28 +0000
3644@@ -409,7 +409,6 @@
3645
3646 // Load the requested map
3647 Widelands::Map map;
3648- i18n::Textdomain td("maps");
3649 map.set_filename(m_filename);
3650 std::unique_ptr<Widelands::MapLoader> ml = map.get_correct_loader(m_filename);
3651 if (!ml) {
3652@@ -420,18 +419,8 @@
3653 }
3654 ml->preload_map(true);
3655
3656- // fill in the mapdata structure
3657- MapData mapdata;
3658- mapdata.filename = m_filename;
3659- mapdata.name = map.get_name();
3660- mapdata.authors.parse(map.get_author());
3661- mapdata.description = map.get_description();
3662- mapdata.nrplayers = map.get_nrplayers();
3663- mapdata.width = map.get_width();
3664- mapdata.height = map.get_height();
3665-
3666 // set the map
3667- netgame.set_map(mapdata.name, mapdata.filename, mapdata.nrplayers);
3668+ netgame.set_map(map.get_name(), map.get_filename(), map.get_nrplayers());
3669
3670 // run the network game
3671 // -> autostarts when a player sends "/start" as pm to the server.
3672
3673=== modified file 'src/wui/CMakeLists.txt'
3674--- src/wui/CMakeLists.txt 2015-01-31 16:03:59 +0000
3675+++ src/wui/CMakeLists.txt 2015-10-03 07:55:28 +0000
3676@@ -43,6 +43,22 @@
3677 logic_widelands_geometry
3678 )
3679
3680+wl_library(wui_common
3681+ SRCS
3682+ mapdetails.cc
3683+ mapdetails.h
3684+ mapdata.h
3685+ maptable.cc
3686+ maptable.h
3687+ suggested_teams_box.cc
3688+ suggested_teams_box.h
3689+ DEPENDS
3690+ base_i18n
3691+ io_filesystem
3692+ logic
3693+ ui_basic
3694+)
3695+
3696 wl_library(wui
3697 SRCS
3698 actionconfirm.cc
3699
3700=== modified file 'src/wui/login_box.cc'
3701--- src/wui/login_box.cc 2015-08-06 17:14:34 +0000
3702+++ src/wui/login_box.cc 2015-10-03 07:55:28 +0000
3703@@ -63,7 +63,7 @@
3704 (this, "login",
3705 (get_inner_w() / 2 - 200) / 2, get_inner_h() - 20 - margin,
3706 200, 20,
3707- g_gr->images().get("pics/but0.png"),
3708+ g_gr->images().get("pics/but5.png"),
3709 _("Login"));
3710 loginbtn->sigclicked.connect(boost::bind(&LoginBox::clicked_ok, boost::ref(*this)));
3711 UI::Button * cancelbtn = new UI::Button
3712
3713=== added file 'src/wui/mapdata.h'
3714--- src/wui/mapdata.h 1970-01-01 00:00:00 +0000
3715+++ src/wui/mapdata.h 2015-10-03 07:55:28 +0000
3716@@ -0,0 +1,197 @@
3717+/*
3718+ * Copyright (C) 2002, 2006-2009, 2011, 2014-2015 by the Widelands Development Team
3719+ *
3720+ * This program is free software; you can redistribute it and/or
3721+ * modify it under the terms of the GNU General Public License
3722+ * as published by the Free Software Foundation; either version 2
3723+ * of the License, or (at your option) any later version.
3724+ *
3725+ * This program is distributed in the hope that it will be useful,
3726+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3727+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3728+ * GNU General Public License for more details.
3729+ *
3730+ * You should have received a copy of the GNU General Public License
3731+ * along with this program; if not, write to the Free Software
3732+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3733+ *
3734+ */
3735+
3736+#ifndef WL_WUI_MAPDATA_H
3737+#define WL_WUI_MAPDATA_H
3738+
3739+#include <set>
3740+#include <string>
3741+#include <vector>
3742+
3743+#include <boost/algorithm/string.hpp>
3744+#include <boost/format.hpp>
3745+
3746+#include "base/i18n.h"
3747+#include "io/filesystem/filesystem.h"
3748+#include "logic/map.h"
3749+
3750+
3751+/**
3752+ * Author data for a map or scenario.
3753+ */
3754+struct MapAuthorData {
3755+ const std::string& get_names() const {return m_names;}
3756+ size_t get_number() const {return m_number;}
3757+
3758+ // Parses author list string into localized contatenated list
3759+ // string. Use , as list separator and no whitespaces between
3760+ // author names.
3761+ MapAuthorData(const std::string& author_list) {
3762+ std::vector<std::string> authors;
3763+ boost::split(authors, author_list, boost::is_any_of(","));
3764+ m_names = i18n::localize_list(authors, i18n::ConcatenateWith::AMPERSAND);
3765+ m_number = authors.size();
3766+ }
3767+
3768+private:
3769+ std::string m_names;
3770+ size_t m_number;
3771+};
3772+
3773+/**
3774+ * Data about a map that we're interested in.
3775+ */
3776+struct MapData {
3777+ using Tags = std::set<std::string>;
3778+
3779+ enum class MapType {
3780+ kNormal,
3781+ kDirectory,
3782+ kScenario,
3783+ kSettlers2
3784+ };
3785+
3786+ enum class DisplayType {
3787+ kFilenames,
3788+ kMapnames,
3789+ kMapnamesLocalized
3790+ };
3791+
3792+
3793+ /// For incomplete data
3794+ MapData() : authors(""), nrplayers(0), width(0), height(0),
3795+ maptype(MapData::MapType::kNormal), displaytype(MapData::DisplayType::kMapnamesLocalized) {}
3796+
3797+ /// For normal maps and scenarios
3798+ MapData(const Widelands::Map& map, const std::string& init_filename,
3799+ const MapData::MapType& init_maptype,
3800+ const MapData::DisplayType& init_displaytype) :
3801+ MapData() {
3802+ i18n::Textdomain td("maps");
3803+ filename = init_filename;
3804+ name = map.get_name();
3805+ localized_name = name.empty() ? "" : _(name);
3806+ authors = MapAuthorData(map.get_author());
3807+ description = map.get_description().empty() ? "" : _(map.get_description());
3808+ hint = map.get_hint().empty() ? "" : _(map.get_hint());
3809+ nrplayers = map.get_nrplayers();
3810+ width = map.get_width();
3811+ height = map.get_height();
3812+ suggested_teams = map.get_suggested_teams();
3813+ tags = map.get_tags();
3814+ maptype = init_maptype;
3815+ displaytype = init_displaytype;
3816+
3817+ if (maptype == MapData::MapType::kScenario) {
3818+ tags.insert("scenario");
3819+ }
3820+ }
3821+
3822+ /// For directories
3823+ MapData(const std::string& init_filename, const std::string& init_localized_name) :
3824+ MapData() {
3825+ filename = init_filename;
3826+ name = init_localized_name;
3827+ localized_name = init_localized_name;
3828+ maptype = MapData::MapType::kDirectory;
3829+ }
3830+
3831+ /// Get the ".." directory
3832+ static MapData create_parent_dir(const std::string& current_dir) {
3833+#ifndef _WIN32
3834+ const std::string filename = current_dir.substr(0, current_dir.rfind('/'));
3835+#else
3836+ const std::string filename = current_dir.substr(0, current_dir.rfind('\\'));
3837+#endif
3838+ return MapData(filename, (boost::format("\\<%s\\>") % _("parent")).str());
3839+ }
3840+
3841+ /// Create a subdirectory
3842+ static MapData create_directory(const std::string& directory) {
3843+ std::string localized_name;
3844+ if (boost::equals(directory, "maps/MP Scenarios")) {
3845+ /** TRANSLATORS: Directory name for MP Scenarios in map selection */
3846+ localized_name = _("Multiplayer Scenarios");
3847+ } else {
3848+ localized_name = FileSystem::fs_filename(directory.c_str());
3849+ }
3850+ return MapData(directory, localized_name);
3851+ }
3852+
3853+ std::string filename;
3854+ std::string name;
3855+ std::string localized_name;
3856+ MapAuthorData authors;
3857+ std::string description;
3858+ std::string hint;
3859+ uint32_t nrplayers;
3860+ uint32_t width;
3861+ uint32_t height;
3862+ std::vector<Widelands::Map::SuggestedTeamLineup> suggested_teams;
3863+ Tags tags;
3864+ MapData::MapType maptype;
3865+ MapData::DisplayType displaytype;
3866+
3867+ bool compare_names(const MapData& other) {
3868+ std::string this_name;
3869+ std::string other_name;
3870+ switch (displaytype) {
3871+ case MapData::DisplayType::kFilenames:
3872+ this_name = filename;
3873+ other_name = other.filename;
3874+ break;
3875+ case MapData::DisplayType::kMapnames:
3876+ this_name = name;
3877+ other_name = other.name;
3878+ break;
3879+ default:
3880+ this_name = localized_name;
3881+ other_name = other.localized_name;
3882+ }
3883+
3884+ // If there is no width, we have a directory - we want them first.
3885+ if (!width && !other.width) {
3886+ return this_name < other_name;
3887+ } else if (!width && other.width) {
3888+ return true;
3889+ } else if (width && !other.width) {
3890+ return false;
3891+ }
3892+ return this_name < other_name;
3893+ }
3894+
3895+ bool compare_players(const MapData& other) {
3896+ if (nrplayers == other.nrplayers) {
3897+ return compare_names(other);
3898+ }
3899+ return nrplayers < other.nrplayers;
3900+ }
3901+
3902+ bool compare_size(const MapData& other) {
3903+ if (width == other.width && height == other.height) {
3904+ return compare_names(other);
3905+ }
3906+ if (width != other.width) {
3907+ return width < other.width;
3908+ }
3909+ return height < other.height;
3910+ }
3911+};
3912+
3913+#endif // end of include guard: WL_WUI_MAPDATA_H
3914
3915=== added file 'src/wui/mapdetails.cc'
3916--- src/wui/mapdetails.cc 1970-01-01 00:00:00 +0000
3917+++ src/wui/mapdetails.cc 2015-10-03 07:55:28 +0000
3918@@ -0,0 +1,154 @@
3919+/*
3920+ * Copyright (C) 2002, 2006-2015 by the Widelands Development Team
3921+ *
3922+ * This program is free software; you can redistribute it and/or
3923+ * modify it under the terms of the GNU General Public License
3924+ * as published by the Free Software Foundation; either version 2
3925+ * of the License, or (at your option) any later version.
3926+ *
3927+ * This program is distributed in the hope that it will be useful,
3928+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3930+ * GNU General Public License for more details.
3931+ *
3932+ * You should have received a copy of the GNU General Public License
3933+ * along with this program; if not, write to the Free Software
3934+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3935+ */
3936+
3937+#include "wui/mapdetails.h"
3938+
3939+#include <cstdio>
3940+#include <memory>
3941+
3942+#include <boost/format.hpp>
3943+
3944+#include "base/i18n.h"
3945+#include "base/log.h"
3946+#include "base/wexception.h"
3947+#include "graphic/graphic.h"
3948+#include "graphic/text_constants.h"
3949+#include "io/filesystem/layered_filesystem.h"
3950+#include "logic/game_controller.h"
3951+#include "logic/game_settings.h"
3952+#include "map_io/widelands_map_loader.h"
3953+#include "ui_basic/box.h"
3954+
3955+MapDetails::MapDetails
3956+ (Panel* parent, int32_t x, int32_t y, int32_t max_x, int32_t max_y) :
3957+ UI::Panel(parent, x, y, max_x, max_y),
3958+
3959+ padding_(4),
3960+ indent_(10),
3961+ labelh_(20),
3962+ max_x_(max_x),
3963+ max_y_(max_y),
3964+
3965+ main_box_(this, 0, 0, UI::Box::Vertical,
3966+ max_x_, max_y_, 0),
3967+
3968+ name_box_(&main_box_, 0, 0, UI::Box::Horizontal,
3969+ max_x_, 3 * labelh_ + padding_, padding_ / 2),
3970+ name_label_(&main_box_, 0, 0, max_x_ - padding_, labelh_, ""),
3971+ name_(&name_box_, 0, 0, max_x_ - indent_, 2 * labelh_, ""),
3972+
3973+ author_box_(&main_box_, 0, 0, UI::Box::Horizontal,
3974+ max_x_, 3 * labelh_ + padding_, padding_ / 2),
3975+ author_label_(&main_box_, 0, 0, max_x_ - padding_, labelh_, ""),
3976+ author_(&author_box_, 0, 0, max_x_ - indent_, labelh_, ""),
3977+
3978+ descr_box_(&main_box_, 0, 0, UI::Box::Horizontal,
3979+ max_x_, 6 * labelh_ + padding_, padding_ / 2),
3980+ descr_label_(&main_box_, 0, 0, max_x_, labelh_, ""),
3981+ descr_(&descr_box_, 0, 0, max_x_ - indent_, 5 * labelh_, "")
3982+{
3983+ suggested_teams_box_ = new UI::SuggestedTeamsBox(this, 0, 0, UI::Box::Vertical,
3984+ padding_, indent_, labelh_, max_x_, 4 * labelh_);
3985+
3986+ main_box_.add(&name_label_, UI::Box::AlignLeft);
3987+ name_box_.add_space(indent_);
3988+ name_box_.add(&name_, UI::Box::AlignLeft);
3989+ main_box_.add(&name_box_, UI::Box::AlignLeft);
3990+ main_box_.add_space(padding_);
3991+
3992+ main_box_.add(&author_label_, UI::Box::AlignLeft);
3993+ author_box_.add_space(indent_);
3994+ author_box_.add(&author_, UI::Box::AlignLeft);
3995+ main_box_.add(&author_box_, UI::Box::AlignLeft);
3996+ main_box_.add_space(padding_);
3997+
3998+ main_box_.add(&descr_label_, UI::Box::AlignLeft);
3999+ descr_box_.add_space(indent_);
4000+ descr_box_.add(&descr_, UI::Box::AlignLeft);
4001+ main_box_.add(&descr_box_, UI::Box::AlignLeft);
4002+ main_box_.add_space(padding_);
4003+}
4004+
4005+
4006+void MapDetails::clear() {
4007+ name_label_.set_text("");
4008+ author_label_.set_text("");
4009+ descr_label_.set_text("");
4010+ name_.set_text("");
4011+ author_.set_text("");
4012+ descr_.set_text("");
4013+ suggested_teams_box_->hide();
4014+}
4015+
4016+void MapDetails::update(const MapData& mapdata, bool localize_mapname) {
4017+ clear();
4018+ if (mapdata.maptype == MapData::MapType::kDirectory) {
4019+ // Show directory information
4020+ name_label_.set_text(_("Directory:"));
4021+ name_.set_text(mapdata.localized_name);
4022+ name_.set_tooltip(_("The name of this directory"));
4023+ main_box_.set_size(max_x_, max_y_);
4024+ } else {
4025+ // Show map information
4026+ if (mapdata.maptype == MapData::MapType::kScenario) {
4027+ name_label_.set_text(_("Scenario:"));
4028+ } else {
4029+ name_label_.set_text(_("Map:"));
4030+ }
4031+ name_.set_text(localize_mapname ? mapdata.localized_name : mapdata.name);
4032+ if (mapdata.localized_name != mapdata.name) {
4033+ if (localize_mapname) {
4034+ name_.set_tooltip
4035+ /** TRANSLATORS: Tooltip in map description when translated map names are being displayed. */
4036+ /** TRANSLATORS: %s is the English name of the map. */
4037+ ((boost::format(_("The original name of this map: %s"))
4038+ % mapdata.name).str());
4039+ } else {
4040+ name_.set_tooltip
4041+ /** TRANSLATORS: Tooltip in map description when map names are being displayed in English. */
4042+ /** TRANSLATORS: %s is the localized name of the map. */
4043+ ((boost::format(_("The name of this map in your language: %s"))
4044+ % mapdata.localized_name).str());
4045+ }
4046+ } else {
4047+ name_.set_tooltip(_("The name of this map"));
4048+ }
4049+ author_label_.set_text(ngettext("Author:", "Authors:", mapdata.authors.get_number()));
4050+ author_.set_text(mapdata.authors.get_names());
4051+ descr_label_.set_text(_("Description:"));
4052+ descr_.set_text(mapdata.description +
4053+ (mapdata.hint.empty() ? "" : (std::string("\n\n") + mapdata.hint)));
4054+
4055+ // Show / hide suggested teams
4056+ if (mapdata.suggested_teams.empty()) {
4057+ main_box_.set_size(max_x_, max_y_);
4058+ descr_box_.set_size(
4059+ descr_box_.get_w(),
4060+ max_y_ - descr_label_.get_y() - descr_label_.get_h() - 2 * padding_);
4061+ } else {
4062+ suggested_teams_box_->show(mapdata.suggested_teams);
4063+ suggested_teams_box_->set_pos(Point(0, max_y_ - suggested_teams_box_->get_h()));
4064+ main_box_.set_size(max_x_, max_y_ - suggested_teams_box_->get_h());
4065+ descr_box_.set_size(
4066+ descr_box_.get_w(),
4067+ suggested_teams_box_->get_y() - descr_label_.get_y() - descr_label_.get_h() - 4 * padding_);
4068+ }
4069+ descr_.set_size(descr_.get_w(), descr_box_.get_h());
4070+ descr_.scroll_to_top();
4071+ }
4072+}
4073
4074=== added file 'src/wui/mapdetails.h'
4075--- src/wui/mapdetails.h 1970-01-01 00:00:00 +0000
4076+++ src/wui/mapdetails.h 2015-10-03 07:55:28 +0000
4077@@ -0,0 +1,64 @@
4078+/*
4079+ * Copyright (C) 2002, 2006-2015, 2011 by the Widelands Development Team
4080+ *
4081+ * This program is free software; you can redistribute it and/or
4082+ * modify it under the terms of the GNU General Public License
4083+ * as published by the Free Software Foundation; either version 2
4084+ * of the License, or (at your option) any later version.
4085+ *
4086+ * This program is distributed in the hope that it will be useful,
4087+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4088+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4089+ * GNU General Public License for more details.
4090+ *
4091+ * You should have received a copy of the GNU General Public License
4092+ * along with this program; if not, write to the Free Software
4093+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
4094+ *
4095+ */
4096+
4097+#ifndef WL_WUI_MAPDETAILS_H
4098+#define WL_WUI_MAPDETAILS_H
4099+
4100+#include "ui_basic/box.h"
4101+#include "ui_basic/multilinetextarea.h"
4102+#include "ui_basic/panel.h"
4103+#include "ui_basic/textarea.h"
4104+#include "wui/mapdata.h"
4105+#include "wui/suggested_teams_box.h"
4106+
4107+
4108+/**
4109+ * Show a Panel with information about a map.
4110+ */
4111+class MapDetails : public UI::Panel {
4112+public:
4113+ MapDetails(Panel * parent,
4114+ int32_t x, int32_t y,
4115+ int32_t max_x, int32_t max_y);
4116+
4117+ void clear();
4118+ void update(const MapData& mapdata, bool localize_mapname);
4119+
4120+private:
4121+ const int padding_, indent_, labelh_;
4122+ const int32_t max_x_, max_y_;
4123+
4124+ UI::Box main_box_;
4125+
4126+ UI::Box name_box_;
4127+ UI::Textarea name_label_;
4128+ UI::MultilineTextarea name_;
4129+
4130+ UI::Box author_box_;
4131+ UI::Textarea author_label_;
4132+ UI::MultilineTextarea author_;
4133+
4134+ UI::Box descr_box_;
4135+ UI::Textarea descr_label_;
4136+ UI::MultilineTextarea descr_;
4137+
4138+ UI::SuggestedTeamsBox* suggested_teams_box_;
4139+};
4140+
4141+#endif // end of include guard: WL_WUI_MAPDETAILS_H
4142
4143=== added file 'src/wui/maptable.cc'
4144--- src/wui/maptable.cc 1970-01-01 00:00:00 +0000
4145+++ src/wui/maptable.cc 2015-10-03 07:55:28 +0000
4146@@ -0,0 +1,82 @@
4147+/*
4148+ * Copyright (C) 2002, 2006-2013 by the Widelands Development Team
4149+ *
4150+ * This program is free software; you can redistribute it and/or
4151+ * modify it under the terms of the GNU General Public License
4152+ * as published by the Free Software Foundation; either version 2
4153+ * of the License, or (at your option) any later version.
4154+ *
4155+ * This program is distributed in the hope that it will be useful,
4156+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4157+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4158+ * GNU General Public License for more details.
4159+ *
4160+ * You should have received a copy of the GNU General Public License
4161+ * along with this program; if not, write to the Free Software
4162+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
4163+ */
4164+
4165+#include "wui/maptable.h"
4166+
4167+#include <string>
4168+
4169+#include <boost/format.hpp>
4170+
4171+#include "base/i18n.h"
4172+#include "graphic/graphic.h"
4173+#include "io/filesystem/filesystem.h"
4174+
4175+MapTable::MapTable
4176+ (UI::Panel * parent,
4177+ int32_t x, int32_t y, uint32_t w, uint32_t h,
4178+ const bool descending) :
4179+ UI::Table<uintptr_t>(parent, x, y, w, h, descending) {
4180+
4181+ /** TRANSLATORS: Column title for number of players in map list */
4182+ add_column(35, _("Pl."), _("Number of players"), UI::Align_HCenter);
4183+ add_column(get_w() - 35 - 115, "", _("The name of the map or scenario"), UI::Align_Left);
4184+ add_column(115, _("Size"), _("The size of the map (Width x Height)"), UI::Align_Left);
4185+ set_sort_column(0);
4186+}
4187+
4188+void MapTable::fill(const std::vector<MapData>& entries, MapData::DisplayType type) {
4189+ clear();
4190+
4191+ for (size_t i = 0; i < entries.size(); ++i) {
4192+ const MapData& mapdata = entries[i];
4193+ UI::Table<uintptr_t const>::EntryRecord& te = add(i);
4194+
4195+ if (mapdata.maptype == MapData::MapType::kDirectory) {
4196+ te.set_string(0, "");
4197+ te.set_picture(1, g_gr->images().get("pics/ls_dir.png"), mapdata.localized_name);
4198+ te.set_string(2, "");
4199+ } else {
4200+ te.set_string(0, (boost::format("(%i)") % mapdata.nrplayers).str());
4201+
4202+ std::string picture = "pics/ls_wlmap.png";
4203+ if (mapdata.maptype == MapData::MapType::kScenario) {
4204+ picture = "pics/ls_wlscenario.png";
4205+ } else if (mapdata.maptype == MapData::MapType::kSettlers2) {
4206+ picture = "pics/ls_s2map.png";
4207+ }
4208+
4209+ if (type == MapData::DisplayType::kFilenames) {
4210+ set_column_title(1, _("Filename"));
4211+ te.set_picture(
4212+ 1,
4213+ g_gr->images().get(picture),
4214+ FileSystem::filename_without_ext(mapdata.filename.c_str()));
4215+ } else {
4216+ set_column_title(1, _("Map Name"));
4217+ if (type == MapData::DisplayType::kMapnames) {
4218+ te.set_picture(1, g_gr->images().get(picture), mapdata.name);
4219+ } else {
4220+ te.set_picture(1, g_gr->images().get(picture), mapdata.localized_name);
4221+ }
4222+ }
4223+
4224+ te.set_string(2, (boost::format("%u x %u") % mapdata.width % mapdata.height).str());
4225+ }
4226+ }
4227+ sort();
4228+}
4229
4230=== added file 'src/wui/maptable.h'
4231--- src/wui/maptable.h 1970-01-01 00:00:00 +0000
4232+++ src/wui/maptable.h 2015-10-03 07:55:28 +0000
4233@@ -0,0 +1,45 @@
4234+/*
4235+ * Copyright (C) 2002, 2006-2009, 2011, 2014-2015 by the Widelands Development Team
4236+ *
4237+ * This program is free software; you can redistribute it and/or
4238+ * modify it under the terms of the GNU General Public License
4239+ * as published by the Free Software Foundation; either version 2
4240+ * of the License, or (at your option) any later version.
4241+ *
4242+ * This program is distributed in the hope that it will be useful,
4243+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4244+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4245+ * GNU General Public License for more details.
4246+ *
4247+ * You should have received a copy of the GNU General Public License
4248+ * along with this program; if not, write to the Free Software
4249+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
4250+ *
4251+ */
4252+
4253+#ifndef WL_WUI_MAPTABLE_H
4254+#define WL_WUI_MAPTABLE_H
4255+
4256+#include <vector>
4257+
4258+#include "ui_basic/table.h"
4259+#include "wui/mapdata.h"
4260+
4261+
4262+/**
4263+ * A table listing all the available maps for saveloading.
4264+ * This contains a UI model only; the callig classes have to define the data model
4265+ * and bind the compare functions.
4266+ */
4267+class MapTable : public UI::Table<uintptr_t> {
4268+public:
4269+
4270+ MapTable(UI::Panel * parent,
4271+ int32_t x, int32_t y, uint32_t w, uint32_t h,
4272+ const bool descending);
4273+
4274+ /// Fill the table with maps and directories.
4275+ void fill(const std::vector<MapData>& entries, MapData::DisplayType type);
4276+};
4277+
4278+#endif // end of include guard: WL_WUI_MAPTABLE_H
4279
4280=== modified file 'src/wui/story_message_box.cc'
4281--- src/wui/story_message_box.cc 2015-08-06 17:14:34 +0000
4282+++ src/wui/story_message_box.cc 2015-10-03 07:55:28 +0000
4283@@ -64,7 +64,7 @@
4284 UI::Button * okbtn = new UI::Button
4285 (this, "ok",
4286 posx, posy, but_width, 20,
4287- g_gr->images().get("pics/but0.png"),
4288+ g_gr->images().get("pics/but5.png"),
4289 button_text);
4290 okbtn->sigclicked.connect(boost::bind(&StoryMessageBox::clicked_ok, boost::ref(*this)));
4291
4292
4293=== renamed file 'src/ui_fsmenu/suggested_teams_box.cc' => 'src/wui/suggested_teams_box.cc'
4294--- src/ui_fsmenu/suggested_teams_box.cc 2015-03-01 09:21:20 +0000
4295+++ src/wui/suggested_teams_box.cc 2015-10-03 07:55:28 +0000
4296@@ -17,7 +17,7 @@
4297 *
4298 */
4299
4300-#include "ui_fsmenu/suggested_teams_box.h"
4301+#include "wui/suggested_teams_box.h"
4302
4303 #include <set>
4304 #include <string>
4305@@ -95,7 +95,7 @@
4306 for (const Widelands::Map::SuggestedTeamLineup& lineup : m_suggested_teams) {
4307
4308 m_lineup_box =
4309- new UI::Box(this, m_indent, teamlist_offset + lineup_counter * m_label_height,
4310+ new UI::Box(this, m_indent, teamlist_offset + lineup_counter * (m_label_height + m_padding),
4311 UI::Box::Horizontal, get_w() - m_indent);
4312
4313 m_lineup_box->set_size(get_w(), m_label_height + m_padding);
4314@@ -105,7 +105,7 @@
4315
4316 if (!is_first) {
4317 m_lineup_box->add_space(m_padding);
4318- vs_label = new UI::Textarea(m_lineup_box, "x", UI::Align_CenterLeft);
4319+ vs_label = new UI::Textarea(m_lineup_box, "x", UI::Align_BottomCenter);
4320 m_lineup_box->add(vs_label, UI::Box::AlignLeft);
4321 vs_label->set_visible(true);
4322 m_vs_labels.push_back(vs_label);
4323@@ -129,7 +129,7 @@
4324 } // All lineups
4325
4326 // Adjust size to content
4327- set_size(get_w(), teamlist_offset + lineup_counter * m_label_height);
4328+ set_size(get_w(), teamlist_offset + lineup_counter * (m_label_height + m_padding));
4329 }
4330 }
4331
4332
4333=== renamed file 'src/ui_fsmenu/suggested_teams_box.h' => 'src/wui/suggested_teams_box.h'
4334--- src/ui_fsmenu/suggested_teams_box.h 2015-03-01 09:21:20 +0000
4335+++ src/wui/suggested_teams_box.h 2015-10-03 07:55:28 +0000
4336@@ -17,8 +17,8 @@
4337 *
4338 */
4339
4340-#ifndef WL_UI_FSMENU_SUGGESTED_TEAMS_BOX_H
4341-#define WL_UI_FSMENU_SUGGESTED_TEAMS_BOX_H
4342+#ifndef WL_WUI_SUGGESTED_TEAMS_BOX_H
4343+#define WL_WUI_SUGGESTED_TEAMS_BOX_H
4344
4345 #include <set>
4346 #include <string>
4347@@ -57,4 +57,4 @@
4348
4349 }
4350
4351-#endif // end of include guard: WL_UI_FSMENU_SUGGESTED_TEAMS_BOX_H
4352+#endif // end of include guard: WL_WUI_SUGGESTED_TEAMS_BOX_H

Subscribers

People subscribed via source and target branches

to status/vote changes: