cghislai has proposed merging lp:~widelands-dev/widelands/ui_improvments into lp:widelands.
Requested reviews: Widelands Developers (widelands-dev) Related bugs: Bug #657285 in widelands: "Multiple tooltips may be shown when opening building information" https://bugs.launchpad.net/widelands/+bug/657285 Bug #738643 in widelands: "Pause game while in 'save'-dialog" https://bugs.launchpad.net/widelands/+bug/738643 Bug #738895 in widelands: "Show a message when the game is autosaving" https://bugs.launchpad.net/widelands/+bug/738895 Bug #744749 in widelands: "Training sites should either show statistics as a military or as a productionsite" https://bugs.launchpad.net/widelands/+bug/744749 Bug #763567 in widelands: "Sort Messages in Message Inbox to be most recent on top" https://bugs.launchpad.net/widelands/+bug/763567 Bug #898129 in widelands: "Workarea color policy" https://bugs.launchpad.net/widelands/+bug/898129 Bug #986526 in widelands: "Clarify "X player teams" map filter" https://bugs.launchpad.net/widelands/+bug/986526 Bug #1132469 in widelands: "List of workers in building window not updating properly" https://bugs.launchpad.net/widelands/+bug/1132469 Bug #1132476 in widelands: "change yellow color in white(?) - building menu % is unreadable" https://bugs.launchpad.net/widelands/+bug/1132476 For more details, see: https://code.launchpad.net/~widelands-dev/widelands/ui_improvments/+merge/175090 Some fixes and features related to ui. See linked bugs and commit messages for details. I tried to make commits as atomic as possible, so they could be merged separately if needed. -- https://code.launchpad.net/~widelands-dev/widelands/ui_improvments/+merge/175090 Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ui_improvments into lp:widelands.
=== added file 'pics/workarea12.png' Binary files pics/workarea12.png 1970-01-01 00:00:00 +0000 and pics/workarea12.png 2013-07-16 17:39:34 +0000 differ === added file 'pics/workarea123.png' Binary files pics/workarea123.png 1970-01-01 00:00:00 +0000 and pics/workarea123.png 2013-07-16 17:39:34 +0000 differ === removed file 'pics/workarea1cumulative.png' Binary files pics/workarea1cumulative.png 2005-12-29 01:10:07 +0000 and pics/workarea1cumulative.png 1970-01-01 00:00:00 +0000 differ === added file 'pics/workarea23.png' Binary files pics/workarea23.png 1970-01-01 00:00:00 +0000 and pics/workarea23.png 2013-07-16 17:39:34 +0000 differ === removed file 'pics/workarea2cumulative.png' Binary files pics/workarea2cumulative.png 2005-12-29 01:10:07 +0000 and pics/workarea2cumulative.png 1970-01-01 00:00:00 +0000 differ === removed file 'pics/workarea3cumulative.png' Binary files pics/workarea3cumulative.png 2009-11-09 19:01:11 +0000 and pics/workarea3cumulative.png 1970-01-01 00:00:00 +0000 differ === modified file 'src/chat.h' --- src/chat.h 2013-02-10 19:36:24 +0000 +++ src/chat.h 2013-07-16 17:39:34 +0000 @@ -106,6 +106,12 @@ virtual void send(const std::string &) = 0; /** + * Sends the given message to the local player only + * This may be used to display useful log messages. + */ + virtual void send_local(const std::string &) = 0; + + /** * \return a (chronological) list of received chat messages. * This list need not be stable or monotonic. In other words, * subsequent calls to this functions may return a smaller or === modified file 'src/constants.h' --- src/constants.h 2013-07-13 14:32:49 +0000 +++ src/constants.h 2013-07-16 17:39:34 +0000 @@ -131,7 +131,7 @@ * C++ is really bad at integer types. For example this constant is not * recognized as a valid value of type Workarea_Info::size_type without a cast. */ -#define NUMBER_OF_WORKAREA_PICS static_cast<Workarea_Info::size_type>(3) +#define NUMBER_OF_WORKAREA_PICS static_cast<Workarea_Info::size_type>(6) /// The size of the transient (i.e. temporary) surfaces in the cache in bytes. /// These are all surfaces that are not loaded from disk. === modified file 'src/debugconsole.cc' --- src/debugconsole.cc 2013-02-10 19:36:24 +0000 +++ src/debugconsole.cc 2013-07-16 17:39:34 +0000 @@ -85,6 +85,10 @@ it->second(arg); } + void send_local(const std::string& msg) { + send(msg); + } + const std::vector<ChatMessage> & getMessages() const { return messages; === modified file 'src/gamecontroller.cc' --- src/gamecontroller.cc 2012-02-15 21:25:34 +0000 +++ src/gamecontroller.cc 2013-07-16 17:39:34 +0000 @@ -25,8 +25,10 @@ #include "logic/playercommand.h" #include "profile/profile.h" #include "wlapplication.h" +#include "chat.h" +#include "wui/interactive_player.h" -struct SinglePlayerGameController : public GameController { +struct SinglePlayerGameController : public GameController, public ChatProvider { SinglePlayerGameController (Widelands::Game &, bool useai, Widelands::Player_Number local); ~SinglePlayerGameController(); @@ -42,6 +44,10 @@ bool isPaused(); void setPaused(bool paused); + // Chat provider implementation + void send(const std::string & msg); + void send_local(const std::string & msg); + const std::vector<ChatMessage> & getMessages() const; private: Widelands::Game & m_game; bool m_useai; @@ -52,13 +58,14 @@ uint32_t m_player_cmdserial; Widelands::Player_Number m_local; std::vector<Computer_Player *> m_computerplayers; + std::vector<ChatMessage> m_chatmessages; }; SinglePlayerGameController::SinglePlayerGameController (Widelands::Game & game, bool const useai, Widelands::Player_Number const local) - : + : ChatProvider(), m_game (game), m_useai (useai), m_lastframe (WLApplication::get()->get_time()), @@ -156,10 +163,31 @@ m_paused = paused; } +void SinglePlayerGameController::send_local(const std::string& msg) +{ + ChatMessage c; + c.msg = msg; + c.time = time(0); + m_chatmessages.push_back(c); + ChatProvider::send(c); +} + +void SinglePlayerGameController::send(const std::string& msg) +{ + log("SinglePlayerGameController:: Cannot send chat messages in single player game!"); +} + +const std::vector< ChatMessage >& SinglePlayerGameController::getMessages() const +{ + return m_chatmessages; +} + GameController * GameController::createSinglePlayer (Widelands::Game & game, bool const cpls, Widelands::Player_Number const local) { - return new SinglePlayerGameController(game, cpls, local); + SinglePlayerGameController* spgc = new SinglePlayerGameController(game, cpls, local); + game.get_ipl()->set_chat_provider(*spgc); + return spgc; } === modified file 'src/logic/building.cc' --- src/logic/building.cc 2013-07-14 10:38:26 +0000 +++ src/logic/building.cc 2013-07-16 17:39:34 +0000 @@ -19,6 +19,7 @@ #include <cstdio> #include <sstream> +#include <boost/foreach.hpp> #include "upcast.h" #include "wexception.h" @@ -436,6 +437,9 @@ } PlayerImmovable::cleanup(egbase); + + BOOST_FOREACH(boost::signals::connection& c, options_window_connections) + c.disconnect(); } @@ -855,6 +859,7 @@ set_seeing(true); } PlayerImmovable::add_worker(worker); + workers_changed(); } @@ -862,6 +867,7 @@ PlayerImmovable::remove_worker(worker); if (not get_workers().size()) set_seeing(false); + workers_changed(); } /** === modified file 'src/logic/building.h' --- src/logic/building.h 2013-07-14 10:38:26 +0000 +++ src/logic/building.h 2013-07-16 17:39:34 +0000 @@ -34,6 +34,7 @@ #include <string> #include <cstring> #include <vector> +#include <boost/signal.hpp> namespace UI {class Window;} struct BuildingHints; @@ -223,6 +224,7 @@ void add_worker(Worker &); void remove_worker(Worker &); + mutable boost::signal<void ()> workers_changed; void send_message (Game & game, @@ -268,6 +270,9 @@ /// Whether we see our vision_range area based on workers in the building bool m_seeing; + + // Signals connected for the option window + std::vector<boost::signals::connection> options_window_connections; }; } === modified file 'src/logic/production_program.cc' --- src/logic/production_program.cc 2013-04-27 16:55:46 +0000 +++ src/logic/production_program.cc 2013-07-16 17:39:34 +0000 @@ -1288,7 +1288,7 @@ snprintf (ps.m_result_buffer, sizeof(ps.m_result_buffer), _("No soldier for this training level found!")); - return ps.program_end(game, Failed); + return ps.program_end(game, Skipped); } if (attribute == atrHP) { if ((*it)->get_hp_level() == level) @@ -1378,7 +1378,7 @@ snprintf (ps.m_result_buffer, sizeof(ps.m_result_buffer), _("No soldier for this training level found!")); - return ps.program_end(game, Failed); + return ps.program_end(game, Skipped); } if (attribute == atrHP) { if ((*it)->get_hp_level () == level) === modified file 'src/logic/productionsite.cc' --- src/logic/productionsite.cc 2013-05-25 09:30:35 +0000 +++ src/logic/productionsite.cc 2013-07-16 17:39:34 +0000 @@ -457,7 +457,6 @@ if (upcast(Game, game, &egbase)) try_start_working(*game); - return 0; } @@ -874,6 +873,7 @@ for (uint32_t i = descr().nr_working_positions(); i;) m_working_positions[--i].worker->gain_experience(game); m_result_buffer[0] = '\0'; + Building::workers_changed(); } calc_statistics(); break; === modified file 'src/logic/trainingsite.cc' --- src/logic/trainingsite.cc 2013-06-16 16:29:48 +0000 +++ src/logic/trainingsite.cc 2013-07-16 17:39:34 +0000 @@ -192,12 +192,7 @@ */ std::string TrainingSite::get_statistics_string() { - if (State * const state = get_state()) - return state->program->descname(); - else if (m_result == Completed) - return _("Resting"); - else - return _("Not Working"); + return ProductionSite::get_statistics_string(); } /** === modified file 'src/network/internet_gaming.cc' --- src/network/internet_gaming.cc 2013-04-20 20:20:34 +0000 +++ src/network/internet_gaming.cc 2013-07-16 17:39:34 +0000 @@ -768,7 +768,14 @@ s.send(m_sock); } - +void InternetGaming::send_local(const std::string& msg) +{ + ChatMessage c; + c.msg = msg; + c.time = time(0); + messages.push_back(c); + ChatProvider::send(c); +} /** * \returns the boolean value of a string received from the metaserver. === modified file 'src/network/internet_gaming.h' --- src/network/internet_gaming.h 2013-02-10 19:36:24 +0000 +++ src/network/internet_gaming.h 2013-07-16 17:39:34 +0000 @@ -114,6 +114,9 @@ // ChatProvider: sends a message via the metaserver. void send(const std::string &); + // ChatProvider: sends local messages + void send_local(const std::string &); + /// ChatProvider: adds the message to the message list and calls parent. void receive(const ChatMessage & msg) {messages.push_back(msg); ChatProvider::send(msg);} === modified file 'src/network/netclient.cc' --- src/network/netclient.cc 2013-04-22 20:15:00 +0000 +++ src/network/netclient.cc 2013-07-16 17:39:34 +0000 @@ -628,6 +628,15 @@ s.send(d->sock); } +void NetClient::send_local(const std::string& msg) +{ + ChatMessage c; + c.msg = msg; + c.time = time(0); + d->chatmessages.push_back(c); + ChatProvider::send(c); +} + const std::vector<ChatMessage> & NetClient::getMessages() const { return d->chatmessages; === modified file 'src/network/netclient.h' --- src/network/netclient.h 2013-02-10 19:36:24 +0000 +++ src/network/netclient.h 2013-07-16 17:39:34 +0000 @@ -92,6 +92,7 @@ // ChatProvider interface void send(const std::string & msg); + void send_local(const std::string & msg); const std::vector<ChatMessage> & getMessages() const; private: === modified file 'src/network/nethost.cc' --- src/network/nethost.cc 2013-07-15 05:18:12 +0000 +++ src/network/nethost.cc 2013-07-16 17:39:34 +0000 @@ -498,6 +498,13 @@ h->send(c); } + void send_local(const std::string & msg) { + ChatMessage c; + c.time = time(0); + c.msg = msg; + ChatProvider::send(c); + } + const std::vector<ChatMessage> & getMessages() const { return messages; } === modified file 'src/save_handler.cc' --- src/save_handler.cc 2013-07-14 11:48:13 +0000 +++ src/save_handler.cc 2013-07-16 17:39:34 +0000 @@ -25,6 +25,8 @@ #include "io/filesystem/filesystem.h" #include "game_io/game_saver.h" #include "profile/profile.h" +#include "wui/interactive_player.h" +#include "chat.h" #include "log.h" @@ -51,7 +53,10 @@ if (elapsed < autosaveInterval) return; - log("Autosave: interval elapsed (%d s), saving\n", elapsed); + // TODO: defer saving to next tick so that this message is shown + // before the actual save, or put the saving logic in another thread + game.get_ipl()->get_chat_provider()->send_local + (_("Saving game...")); // save the game std::string complete_filename = @@ -70,6 +75,8 @@ static std::string error; if (!save_game(game, complete_filename, &error)) { log("Autosave: ERROR! - %s\n", error.c_str()); + game.get_ipl()->get_chat_provider()->send_local + (_("Saving failed!")); // if backup file was created, move it back if (backup_filename.length() > 0) { @@ -88,6 +95,8 @@ } log("Autosave: save took %d ms\n", m_last_saved_time - realtime); + game.get_ipl()->get_chat_provider()->send_local + (_("Game saved")); } /** @@ -98,7 +107,6 @@ return; m_last_saved_time = currenttime; - log("Autosave: initialized\n"); m_initialized = true; } === modified file 'src/timestring.cc' --- src/timestring.cc 2013-03-21 10:45:51 +0000 +++ src/timestring.cc 2013-07-16 17:39:34 +0000 @@ -75,3 +75,18 @@ } return timestring_buffer; } + +char gamestringbuffer[] = "000:00:00"; +char * gametimestring(uint32_t gametime) +{ + uint32_t time = gametime / 1000; + gamestringbuffer[8] = '0' + time % 10; + gamestringbuffer[7] = '0' + (time /= 10) % 6; + gamestringbuffer[5] = '0' + (time /= 6) % 10; + gamestringbuffer[4] = '0' + (time /= 10) % 6; + gamestringbuffer[2] = '0' + (time /= 6) % 10; + gamestringbuffer[1] = '0' + (time /= 10) % 10; + gamestringbuffer[0] = '0' + (time /= 10); + return gamestringbuffer; +} + === modified file 'src/timestring.h' --- src/timestring.h 2012-02-15 21:25:34 +0000 +++ src/timestring.h 2013-07-16 17:39:34 +0000 @@ -21,3 +21,8 @@ /// seconds since the Epoch). The return value points to a statically allocated /// string which might be overwritten by subsequent calls. char * timestring(); + +/// Get a string representation of the game time +/// as hhh:mm:ss. If Time represents more than +/// 999 hours, it wraps around +char * gametimestring(uint32_t gametime); === modified file 'src/ui_basic/progressbar.cc' --- src/ui_basic/progressbar.cc 2012-02-15 21:25:34 +0000 +++ src/ui_basic/progressbar.cc 2013-07-16 17:39:34 +0000 @@ -21,10 +21,12 @@ #include "constants.h" #include "graphic/font.h" -#include "graphic/font_handler.h" +#include "graphic/font_handler1.h" +#include "text_layout.h" #include "graphic/rendertarget.h" #include <cstdio> +#include <boost/format.hpp> namespace UI { @@ -103,16 +105,11 @@ } // Print the state in percent - char buffer[30]; - - snprintf - (buffer, sizeof(buffer), "%u%%", static_cast<uint32_t>(fraction * 100)); - - UI::g_fh->draw_text - (dst, UI::TextStyle::ui_small(), - Point(get_w() / 2, get_h() / 2), - buffer, - Align_Center); + // TODO use UI_FNT_COLOR_BRIGHT when merged + uint32_t percent = static_cast<uint32_t>(fraction * 100); + const std::string progress_text = + (boost::format("<font color=%1$s>%2$i%%</font>") % "ffffff" % percent).str(); + const Point pos(get_w() / 2, get_h() / 2); + dst.blit(pos, UI::g_fh1->render(as_uifont(progress_text)), CM_Normal, Align_Center); } - } === modified file 'src/ui_basic/table.cc' --- src/ui_basic/table.cc 2013-07-13 14:25:41 +0000 +++ src/ui_basic/table.cc 2013-07-16 17:39:34 +0000 @@ -23,11 +23,13 @@ #include "graphic/font_handler.h" #include "graphic/graphic.h" #include "graphic/rendertarget.h" +#include "graphic/font_handler1.h" #include "button.h" #include "mouse_constants.h" #include "scrollbar.h" #include "wlapplication.h" +#include "text_layout.h" #include "container_iterate.h" #include <boost/bind.hpp> @@ -273,21 +275,13 @@ const std::string & entry_string = er.get_string (i); uint32_t picw = 0; uint32_t pich = 0; - uint32_t stringw = 0; - uint32_t stringh = g_fh->get_fontheight(m_fontname, m_fontsize); + if (entry_picture) { picw = entry_picture->width(); pich = entry_picture->height(); } - Point point = - Point(curx, y) - + - Point - (alignment & Align_Right ? curw - (picw + stringw) - 1 : - alignment & Align_HCenter ? (curw - (picw + stringw)) / 2 : - 1, - 0); - if (entry_picture) + Point point(curx, y); + if (entry_picture) { dst.blit (point + Point @@ -296,18 +290,13 @@ static_cast<int32_t>(pich)) / 2), entry_picture); + point.x += picw; + } - UI::g_fh->draw_text - (dst, - TextStyle::makebold(Font::get(m_fontname, m_fontsize), er.use_clr ? er.clr : UI_FONT_CLR_FG), - point + - Point - (picw, - (static_cast<int32_t>(lineheight) - - static_cast<int32_t>(stringh)) - / 2), - entry_string, - alignment); + const Image* entry_text_im = UI::g_fh1->render(as_uifont(entry_string, m_fontsize)); + // Crop to column width + UI::correct_for_align(alignment, entry_text_im->width(), entry_text_im->height(), &point); + dst.blitrect(point, entry_text_im, Rect(0, 0, curw - picw, lineheight)); curx += curw; } === modified file 'src/ui_fsmenu/loadgame.cc' --- src/ui_fsmenu/loadgame.cc 2013-07-15 05:18:12 +0000 +++ src/ui_fsmenu/loadgame.cc 2013-07-16 17:39:34 +0000 @@ -29,6 +29,7 @@ #include "log.h" #include "logic/game.h" #include "ui_basic/messagebox.h" +#include "timestring.h" #include <cstdio> @@ -203,15 +204,9 @@ m_tamapname.set_text(_(gpdp.get_mapname())); } - char buf[200]; + char buf[20]; uint32_t gametime = gpdp.get_gametime(); - - int32_t hours = gametime / 3600000; - gametime -= hours * 3600000; - int32_t minutes = gametime / 60000; - - sprintf(buf, "%02i:%02i", hours, minutes); - m_tagametime.set_text(buf); + m_tagametime.set_text(gametimestring(gametime)); sprintf(buf, "%i", gpdp.get_player_nr()); m_ta_players.set_text(buf); === modified file 'src/ui_fsmenu/loadreplay.cc' --- src/ui_fsmenu/loadreplay.cc 2013-07-14 16:11:41 +0000 +++ src/ui_fsmenu/loadreplay.cc 2013-07-16 17:39:34 +0000 @@ -28,6 +28,7 @@ #include "logic/game.h" #include "logic/replay.h" #include "ui_basic/messagebox.h" +#include "timestring.h" Fullscreen_Menu_LoadReplay::Fullscreen_Menu_LoadReplay() : Fullscreen_Menu_Base("choosemapmenu.jpg"), @@ -186,15 +187,9 @@ m_delete.set_enabled(true); m_tamapname.set_text(gpdp.get_mapname()); - char buf[200]; + char buf[20]; uint32_t gametime = gpdp.get_gametime(); - - int32_t hours = gametime / 3600000; - gametime -= hours * 3600000; - int32_t minutes = gametime / 60000; - - sprintf(buf, "%02i:%02i", hours, minutes); - m_tagametime.set_text(buf); + m_tagametime.set_text(gametimestring(gametime)); sprintf(buf, "%i", gpdp.get_player_nr()); m_ta_players.set_text(buf); === modified file 'src/ui_fsmenu/mapselect.cc' --- src/ui_fsmenu/mapselect.cc 2013-06-15 14:35:17 +0000 +++ src/ui_fsmenu/mapselect.cc 2013-07-16 17:39:34 +0000 @@ -172,11 +172,11 @@ vbox->set_size(get_w(), 25); vbox = new UI::Box(this, m_table.get_x(), m_table.get_y() - 60, UI::Box::Horizontal, m_table.get_w()); _add_tag_checkbox(vbox, "1v1", _("1v1")); - _add_tag_checkbox(vbox, "2teams", _("2 Player Teams")); - _add_tag_checkbox(vbox, "3teams", _("3 Player Teams")); + _add_tag_checkbox(vbox, "2teams", _("Teams of 2")); + _add_tag_checkbox(vbox, "3teams", _("Teams of 3")); vbox->set_size(get_w(), 25); vbox = new UI::Box(this, m_table.get_x(), m_table.get_y() - 30, UI::Box::Horizontal, m_table.get_w()); - _add_tag_checkbox(vbox, "4teams", _("4 Player Teams")); + _add_tag_checkbox(vbox, "4teams", _("Teams of 4")); _add_tag_checkbox(vbox, "ffa", _("Free for all")); _add_tag_checkbox(vbox, "unbalanced", _("Unbalanced")); vbox->set_size(get_w(), 25); === modified file 'src/wlapplication.cc' --- src/wlapplication.cc 2013-07-15 05:18:12 +0000 +++ src/wlapplication.cc 2013-07-16 17:39:34 +0000 @@ -2036,9 +2036,14 @@ } } else { // normal singleplayer uint8_t const pn = sp.settings().playernum + 1; - boost::scoped_ptr<GameController> ctrl - (GameController::createSinglePlayer(game, true, pn)); try { + // Game controller needs the ibase pointer to init + // the chat + game.set_ibase + (new Interactive_Player + (game, g_options.pull_section("global"), pn, false, false)); + boost::scoped_ptr<GameController> ctrl + (GameController::createSinglePlayer(game, true, pn)); UI::ProgressWindow loaderUI; std::vector<std::string> tipstext; tipstext.push_back("general_game"); @@ -2052,9 +2057,6 @@ loaderUI.step(_("Preparing game")); game.set_game_controller(ctrl.get()); - game.set_ibase - (new Interactive_Player - (game, g_options.pull_section("global"), pn, false, false)); game.init_newgame(&loaderUI, sp.settings()); game.run(&loaderUI, Widelands::Game::NewNonScenario); } catch (const std::exception & e) { === modified file 'src/wui/building_ui.cc' --- src/wui/building_ui.cc 2013-07-09 05:53:39 +0000 +++ src/wui/building_ui.cc 2013-07-16 17:39:34 +0000 @@ -17,6 +17,8 @@ * */ +#include <boost/foreach.hpp> +#include <boost/lexical_cast.hpp> #include "buildingwindow.h" #include "logic/building.h" #include "ui_basic/window.h" @@ -30,14 +32,17 @@ */ void Building::show_options(Interactive_GameBase & igbase, bool avoid_fastclick) { + // Reset tooltip before opening the window + igbase.set_tooltip(""); if (m_optionswindow) { if (m_optionswindow->is_minimal()) m_optionswindow->restore(); m_optionswindow->move_to_top(); } else { create_options_window(igbase, m_optionswindow); - if (upcast(Building_Window, bw, m_optionswindow)) + if (upcast(Building_Window, bw, m_optionswindow)) { bw->set_avoid_fastclick(avoid_fastclick); + } // Run a first think here so that certain things like caps buttons // get properly initialized m_optionswindow->think(); @@ -49,6 +54,8 @@ */ void Building::hide_options() { + BOOST_FOREACH(boost::signals::connection& c, options_window_connections) + c.disconnect(); delete m_optionswindow; m_optionswindow = NULL; } === modified file 'src/wui/buildingwindow.cc' --- src/wui/buildingwindow.cc 2013-07-13 15:58:52 +0000 +++ src/wui/buildingwindow.cc 2013-07-16 17:39:34 +0000 @@ -79,13 +79,6 @@ set_center_panel(vbox); set_think(true); - char filename[] = "pics/workarea0cumulative.png"; - compile_assert(NUMBER_OF_WORKAREA_PICS <= 9); - for (Workarea_Info::size_type i = 0; i < NUMBER_OF_WORKAREA_PICS; ++i) { - ++filename[13]; - workarea_cumulative_pic[i] = g_gr->images().get(filename); - } - show_workarea(); set_fastclick_panel(this); @@ -327,7 +320,7 @@ (capsbuttons, "workarea", 0, 0, 34, 34, g_gr->images().get("pics/but4.png"), - g_gr->images().get("pics/workarea3cumulative.png"), + g_gr->images().get("pics/workarea123.png"), _("Hide workarea")); m_toggle_workarea->sigclicked.connect (boost::bind(&Building_Window::toggle_workarea, boost::ref(*this))); @@ -512,41 +505,11 @@ */ void Building_Window::show_workarea() { - if (m_workarea_job_id) + if (m_workarea_job_id) { return; // already shown, nothing to be done - + } const Workarea_Info & workarea_info = m_building.descr().m_workarea_info; - if (workarea_info.size() == 0) - return; // building has no workarea - - Widelands::Map & map = - ref_cast<const Interactive_GameBase, UI::Panel>(*get_parent()).egbase() - .map(); - Overlay_Manager & overlay_manager = map.overlay_manager(); - m_workarea_job_id = overlay_manager.get_a_job_id(); - - Widelands::HollowArea<> hollow_area - (Widelands::Area<>(m_building.get_position(), 0), 0); - Workarea_Info::const_iterator it = workarea_info.begin(); - for - (Workarea_Info::size_type i = - std::min(workarea_info.size(), NUMBER_OF_WORKAREA_PICS); - i; - ++it) - { - --i; - hollow_area.radius = it->first; - Widelands::MapHollowRegion<> mr(map, hollow_area); - do - overlay_manager.register_overlay - (mr.location(), - workarea_cumulative_pic[i], - 0, - Point::invalid(), - m_workarea_job_id); - while (mr.advance(map)); - hollow_area.hole_radius = hollow_area.radius; - } + m_workarea_job_id = igbase().show_work_area(workarea_info, m_building.get_position()); configure_workarea_button(); } @@ -557,11 +520,7 @@ void Building_Window::hide_workarea() { if (m_workarea_job_id) { - Widelands::Map & map = - ref_cast<const Interactive_GameBase, UI::Panel>(*get_parent()).egbase() - .map(); - Overlay_Manager & overlay_manager = map.overlay_manager(); - overlay_manager.remove_overlay(m_workarea_job_id); + igbase().hide_work_area(m_workarea_job_id); m_workarea_job_id = Overlay_Manager::Job_Id::Null(); configure_workarea_button(); === modified file 'src/wui/buildingwindow.h' --- src/wui/buildingwindow.h 2013-07-08 03:35:09 +0000 +++ src/wui/buildingwindow.h 2013-07-16 17:39:34 +0000 @@ -94,7 +94,6 @@ bool m_caps_setup; Overlay_Manager::Job_Id m_workarea_job_id; - const Image* workarea_cumulative_pic[NUMBER_OF_WORKAREA_PICS]; bool m_avoid_fastclick; }; === modified file 'src/wui/fieldaction.cc' --- src/wui/fieldaction.cc 2013-02-09 23:36:30 +0000 +++ src/wui/fieldaction.cc 2013-07-16 17:39:34 +0000 @@ -231,7 +231,6 @@ bool m_fastclick; // if true, put the mouse over first button in first tab uint32_t m_best_tab; Overlay_Manager::Job_Id m_workarea_preview_job_id; - const Image* workarea_cumulative_pic[NUMBER_OF_WORKAREA_PICS]; /// Variables to use with attack dialog. AttackBox * m_attack_box; @@ -297,13 +296,6 @@ set_center_panel(&m_tabpanel); - - char filename[] = "pics/workarea0cumulative.png"; - compile_assert(NUMBER_OF_WORKAREA_PICS <= 9); - for (Workarea_Info::size_type i = 0; i < NUMBER_OF_WORKAREA_PICS; ++i) { - ++filename[13]; - workarea_cumulative_pic[i] = g_gr->images().get(filename); - } } @@ -856,44 +848,10 @@ (const Widelands::Building_Index::value_t idx) { if (ibase().m_show_workarea_preview and not m_workarea_preview_job_id) { - m_workarea_preview_job_id = m_overlay_manager.get_a_job_id(); - Widelands::HollowArea<> hollow_area(Widelands::Area<>(m_node, 0), 0); const Workarea_Info & workarea_info = m_plr->tribe().get_building_descr(Widelands::Building_Index(idx)) ->m_workarea_info; - Workarea_Info::const_iterator it = workarea_info.begin(); - for - (Workarea_Info::size_type i = - std::min(workarea_info.size(), NUMBER_OF_WORKAREA_PICS); - i; - ++it) - { - --i; - hollow_area.radius = it->first; - assert(hollow_area.radius); - assert(hollow_area.hole_radius < hollow_area.radius); - Widelands::MapHollowRegion<> mr(*m_map, hollow_area); - do - m_overlay_manager.register_overlay - (mr.location(), - workarea_cumulative_pic[i], - 0, - Point::invalid(), - m_workarea_preview_job_id); - while (mr.advance(*m_map)); - hollow_area.hole_radius = hollow_area.radius; - } - -#if 0 - // This is debug output. - // Improvement suggestion: add to sign explanation window instead. - container_iterate_const(Workarea_Info, workarea_info, i) { - log("Radius: %i\n", i.current->first); - container_iterate_const(std::set<std::string>, i.current->second, j) - log(" %s\n", j.current->c_str()); - } -#endif - + m_workarea_preview_job_id = ibase().show_work_area(workarea_info, m_node); } } === modified file 'src/wui/game_main_menu_save_game.cc' --- src/wui/game_main_menu_save_game.cc 2013-07-15 11:01:59 +0000 +++ src/wui/game_main_menu_save_game.cc 2013-07-16 17:39:34 +0000 @@ -28,10 +28,13 @@ #include "game_io/game_saver.h" #include "i18n.h" #include "interactive_gamebase.h" +#include "gamecontroller.h" #include "io/filesystem/filesystem.h" #include "io/filesystem/layered_filesystem.h" #include "logic/game.h" #include "profile/profile.h" +#include "interactive_player.h" +#include "timestring.h" using boost::format; @@ -125,6 +128,10 @@ } m_editbox->focus(); + if (!parent.game().get_ipl()->is_multiplayer()) { + // Pause the game + parent.game().gameController()->setPaused(true); + } } @@ -144,20 +151,11 @@ m_button_ok->set_enabled(true); m_name.set_text(gpdp.get_mapname()); + + uint32_t gametime = gpdp.get_gametime(); + m_gametime.set_text(gametimestring(gametime)); + char buf[200]; - uint32_t gametime = gpdp.get_gametime(); -#define SPLIT_GAMETIME(unit, factor) \ - uint32_t const unit = gametime / factor; gametime %= factor; - SPLIT_GAMETIME(days, 86400000); - SPLIT_GAMETIME(hours, 3600000); - SPLIT_GAMETIME(minutes, 60000); - SPLIT_GAMETIME(seconds, 1000); - sprintf - (buf, - _("%02ud%02uh%02u'%02u\"%03u"), - days, hours, minutes, seconds, gametime); - m_gametime.set_text(buf); - sprintf (buf, "%i %s", gpdp.get_player_nr(), ngettext(_("player"), _("players"), gpdp.get_player_nr())); @@ -293,6 +291,15 @@ } } +void Game_Main_Menu_Save_Game::die() +{ + UI::UniqueWindow::die(); + if (!igbase().game().get_ipl()->is_multiplayer()) { + igbase().game().gameController()->setPaused(false); + } +} + + struct DeletionMessageBox : public UI::WLMessageBox { DeletionMessageBox === modified file 'src/wui/game_main_menu_save_game.h' --- src/wui/game_main_menu_save_game.h 2013-07-13 15:17:51 +0000 +++ src/wui/game_main_menu_save_game.h 2013-07-16 17:39:34 +0000 @@ -43,7 +43,7 @@ void select_by_name(std::string name); private: Interactive_GameBase & igbase(); - void die() {UI::UniqueWindow::die();} + void die(); void selected (uint32_t); void double_clicked(uint32_t); void edit_box_changed(); === modified file 'src/wui/game_message_menu.cc' --- src/wui/game_message_menu.cc 2013-07-12 15:11:32 +0000 +++ src/wui/game_message_menu.cc 2013-07-16 17:39:34 +0000 @@ -28,6 +28,7 @@ #include "logic/playercommand.h" #include "container_iterate.h" +#include "timestring.h" using Widelands::Message; using Widelands::Message_Id; @@ -109,6 +110,8 @@ list->set_column_compare (ColStatus, boost::bind(&GameMessageMenu::status_compare, this, _1, _2)); + list->set_sort_column(ColTimeSent); + list->set_sort_descending(true); set_can_focus(true); focus(); @@ -200,19 +203,8 @@ g_gr->images().get(status_picture_filename[message.status()])); er.set_string(ColTitle, message.title()); - uint32_t time = message.sent(); - char timestring[] = "000:00:00.000"; - timestring[12] += time % 10; - timestring[11] += (time /= 10) % 10; - timestring[10] += (time /= 10) % 10; - timestring [8] += (time /= 10) % 10; - timestring [7] += (time /= 10) % 6; - timestring [5] += (time /= 6) % 10; - timestring [4] += (time /= 10) % 6; - timestring [2] += (time /= 6) % 10; - timestring [1] += (time /= 10) % 10; - timestring [0] += time /= 10; - er.set_string(ColTimeSent, time < 10 ? timestring : "-------------"); + const uint32_t time = message.sent(); + er.set_string(ColTimeSent, gametimestring(time)); } /* === modified file 'src/wui/interactive_base.cc' --- src/wui/interactive_base.cc 2013-06-15 13:38:19 +0000 +++ src/wui/interactive_base.cc 2013-07-16 17:39:34 +0000 @@ -36,6 +36,7 @@ #include "logic/maptriangleregion.h" #include "logic/player.h" #include "logic/productionsite.h" +#include "logic/maphollowregion.h" #include "mapviewpixelconstants.h" #include "mapviewpixelfunctions.h" #include "minimap.h" @@ -119,6 +120,15 @@ // funny results. m_sel.pic = g_gr->images().get("pics/fsel.png"); + // Load workarea images. + // Start at idx 0 for 2 enhancements, idx 3 for 1, idx 5 if none + workarea_pics[0] = g_gr->images().get("pics/workarea123.png"); + workarea_pics[1] = g_gr->images().get("pics/workarea23.png"); + workarea_pics[2] = g_gr->images().get("pics/workarea3.png"); + workarea_pics[3] = g_gr->images().get("pics/workarea12.png"); + workarea_pics[4] = g_gr->images().get("pics/workarea2.png"); + workarea_pics[5] = g_gr->images().get("pics/workarea1.png"); + m_label_speed.set_visible(false); m_label_speed_shadow.set_visible(false); @@ -229,6 +239,60 @@ egbase().map().overlay_manager().show_buildhelp(t); } +// Show the given workareas at the given coords and returns the overlay job id associated +Overlay_Manager::Job_Id Interactive_Base::show_work_area + (const Workarea_Info & workarea_info, Widelands::Coords coords) +{ + uint8_t workareas_nrs = workarea_info.size(); + Workarea_Info::size_type wa_index; + switch (workareas_nrs) { + case 0: return Overlay_Manager::Job_Id::Null(); break; // no workarea + case 1: wa_index = 5; break; + case 2: wa_index = 3; break; + case 3: wa_index = 0; break; + default: assert(false); break; + } + Widelands::Map & map = m_egbase.map(); + Overlay_Manager & overlay_manager = map.overlay_manager(); + Overlay_Manager::Job_Id job_id = overlay_manager.get_a_job_id(); + + Widelands::HollowArea<> hollow_area(Widelands::Area<>(coords, 0), 0); + + // Iterate through the work areas, from building to its enhancement + Workarea_Info::const_iterator it = workarea_info.begin(); + for (; it != workarea_info.end(); ++it) { + assert(wa_index < NUMBER_OF_WORKAREA_PICS); + hollow_area.radius = it->first; + Widelands::MapHollowRegion<> mr(map, hollow_area); + do + overlay_manager.register_overlay + (mr.location(), + workarea_pics[wa_index], + 0, + Point::invalid(), + job_id); + while (mr.advance(map)); + wa_index++; + hollow_area.hole_radius = hollow_area.radius; + } + return job_id; +#if 0 + // This is debug output. + // Improvement suggestion: add to sign explanation window instead. + container_iterate_const(Workarea_Info, workarea_info, i) { + log("Radius: %i\n", i.current->first); + container_iterate_const(std::set<std::string>, i.current->second, j) + log(" %s\n", j.current->c_str()); + } +#endif +} + +void Interactive_Base::hide_work_area(Overlay_Manager::Job_Id job_id) { + Widelands::Map & map = m_egbase.map(); + Overlay_Manager & overlay_manager = map.overlay_manager(); + overlay_manager.remove_overlay(job_id); +} + /** * Called by \ref Game::postload at the end of the game loading === modified file 'src/wui/interactive_base.h' --- src/wui/interactive_base.h 2013-02-10 19:36:24 +0000 +++ src/wui/interactive_base.h 2013-07-16 17:39:34 +0000 @@ -60,6 +60,8 @@ virtual void reference_player_tribe(Widelands::Player_Number, const void * const) {} bool m_show_workarea_preview; + Overlay_Manager::Job_Id show_work_area(const Workarea_Info & workarea_info, Widelands::Coords coords); + void hide_work_area(Overlay_Manager::Job_Id job_id); // point of view for drawing virtual Widelands::Player * get_player() const throw () = 0; @@ -151,6 +153,7 @@ Overlay_Manager::Job_Id m_road_buildhelp_overlay_jobid; Widelands::CoordPath * m_buildroad; // path for the new road Widelands::Player_Number m_road_build_player; + const Image* workarea_pics[NUMBER_OF_WORKAREA_PICS]; protected: void toggle_minimap(); === modified file 'src/wui/interactive_player.cc' --- src/wui/interactive_player.cc 2013-02-21 19:02:21 +0000 +++ src/wui/interactive_player.cc 2013-07-16 17:39:34 +0000 @@ -85,7 +85,8 @@ : Interactive_GameBase (_game, global_s), m_auto_roadbuild_mode(global_s.get_bool("auto_roadbuild_mode", true)), -m_flag_to_connect(Widelands::Coords::Null()), + m_flag_to_connect(Widelands::Coords::Null()), + m_multiplayer(multiplayer), // Chat is different, as m_chatProvider needs to be checked when toggling // Buildhelp is different as it does not toggle a UniqueWindow @@ -152,16 +153,16 @@ m_toolbar.add(&m_toggle_statistics_menu, UI::Box::AlignLeft); m_toolbar.add(&m_toggle_minimap, UI::Box::AlignLeft); m_toolbar.add(&m_toggle_buildhelp, UI::Box::AlignLeft); + // Limit chat width to half the screen, to limit the damage lamers can do + // by flooding chat messages + m_chatOverlay = + new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25); if (multiplayer) { m_toolbar.add(&m_toggle_chat, UI::Box::AlignLeft); - // Limit chat width to half the screen, to limit the damage lamers can do - // by flooding chat messages - m_chatOverlay = - new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25); m_toggle_chat.set_visible(false); m_toggle_chat.set_enabled(false); - } else - m_toggle_chat.set_visible(false); + } + m_toolbar.add(&m_toggle_help, UI::Box::AlignLeft); if (not scenario) m_toggle_objectives.set_visible(false); @@ -283,8 +284,10 @@ m_flag_to_connect = Widelands::Coords::Null(); } } - m_toggle_chat.set_visible(m_chatenabled); - m_toggle_chat.set_enabled(m_chatenabled); + if (m_multiplayer) { + m_toggle_chat.set_visible(m_chatenabled); + m_toggle_chat.set_enabled(m_chatenabled); + } { char buffer[128]; char const * msg_icon = "pics/menu_toggle_oldmessage_menu.png"; @@ -452,7 +455,7 @@ case SDLK_KP_ENTER: case SDLK_RETURN: - if (!m_chatProvider | !m_chatenabled) + if (!m_chatProvider | !m_chatenabled || !m_multiplayer) break; if (!m_chat.window) === modified file 'src/wui/interactive_player.h' --- src/wui/interactive_player.h 2013-02-10 19:36:24 +0000 +++ src/wui/interactive_player.h 2013-07-16 17:39:34 +0000 @@ -88,12 +88,15 @@ void popup_message(Widelands::Message_Id, const Widelands::Message &); + bool is_multiplayer() {return m_multiplayer;} + private: void cmdSwitchPlayer(const std::vector<std::string> & args); Widelands::Player_Number m_player_number; bool m_auto_roadbuild_mode; Widelands::Coords m_flag_to_connect; + bool m_multiplayer; UI::Button m_toggle_chat; UI::Button m_toggle_options_menu; === modified file 'src/wui/productionsitewindow.cc' --- src/wui/productionsitewindow.cc 2013-02-10 19:36:24 +0000 +++ src/wui/productionsitewindow.cc 2013-07-16 17:39:34 +0000 @@ -105,13 +105,41 @@ worker_box, productionsite().descr().nr_working_positions() > 1 ? _("Workers") : _("Worker")); + update_worker_table(); } } void ProductionSite_Window::think() { Building_Window::think(); - + // If we have pending requests, update table as the worker might be coming + for + (unsigned int i = 0; + i < productionsite().descr().nr_working_positions(); ++i) + { + if (productionsite().working_positions()[i].worker_request) { + update_worker_table(); + break; + } + } +} + +/* +=============== +Create the production site information window. +=============== +*/ +void ProductionSite::create_options_window + (Interactive_GameBase & parent, UI::Window * & registry) +{ + ProductionSite_Window* win = new ProductionSite_Window(parent, *this, registry); + options_window_connections.push_back + (workers_changed.connect(boost::bind + (&ProductionSite_Window::update_worker_table, boost::ref(*win)))); +} + +void ProductionSite_Window::update_worker_table() +{ if (m_worker_table) { assert (productionsite().descr().nr_working_positions() == @@ -155,7 +183,7 @@ er.set_string(1, "---"); er.set_string(2, "---"); } - } else { + } else if (request) { const Widelands::Worker_Descr * desc = productionsite().tribe().get_worker_descr(request->get_index()); er.set_picture @@ -164,20 +192,13 @@ er.set_string(1, ""); er.set_string(2, ""); + } else { + // Occurs during cleanup + return; } } } -} - -/* -=============== -Create the production site information window. -=============== -*/ -void ProductionSite::create_options_window - (Interactive_GameBase & parent, UI::Window * & registry) -{ - new ProductionSite_Window(parent, *this, registry); + m_worker_table->update(); } void ProductionSite_Window::evict_worker() { === modified file 'src/wui/productionsitewindow.h' --- src/wui/productionsitewindow.h 2013-02-02 14:42:48 +0000 +++ src/wui/productionsitewindow.h 2013-07-16 17:39:34 +0000 @@ -33,7 +33,7 @@ Widelands::ProductionSite & productionsite() { return ref_cast<Widelands::ProductionSite, Widelands::Building>(building()); } - + void update_worker_table(); protected: virtual void think(); void evict_worker();
_______________________________________________ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp