Skip to content

Commit

Permalink
Merge pull request #229 from cbeck88/wmi_items_preference
Browse files Browse the repository at this point in the history
add adv. preference for number of menu items displayed at once,

and remaining fixups there
  • Loading branch information
cbeck88 committed Jul 7, 2014
2 parents 0a8d153 + 188b3be commit 1cb74d6
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 40 deletions.
12 changes: 12 additions & 0 deletions data/advanced_preferences.cfg
Expand Up @@ -158,6 +158,18 @@
step=1
[/advanced_preference]

[advanced_preference]
field=max_wml_menu_items
# TODO: It would be better to eliminate this preference and have it instead determined by the gui layout algorithm.
name=_ "Max WML menu items"
description= _ "Maximum number of WML menu items displayed at once"
type=int
default=7
min=3
max=32
step=1
[/advanced_preference]

[advanced_preference]
field=use_twelve_hour_clock_format
name= _ "Use 12-hour clock format"
Expand Down
120 changes: 120 additions & 0 deletions data/test/scenarios/test_max_menu_items.cfg
@@ -0,0 +1,120 @@
{GENERIC_UNIT_TEST "test_max_menu_items" (
[event]
name=side 1 turn
first_time_only=no
{VARIABLE current_side 1}
[/event]
[event]
name=side 2 turn
first_time_only=no
{VARIABLE current_side 2}
[/event]
[event]
name=start
[set_menu_item]
id=bar1
description=foo1
[/set_menu_item]
[set_menu_item]
id=bar2
description=foo2
[show_if]
{VARIABLE_CONDITIONAL current_side equals 1}
[/show_if]
[/set_menu_item]
[set_menu_item]
id=bar3
description=foo3
[command]
[chat]
message="ASDFSAASDF"
[/chat]
[/command]
[/set_menu_item]
[set_menu_item]
id=bar4
description=foo4
[/set_menu_item]
[set_menu_item]
id=bar5
description=foo5
[show_if]
{VARIABLE_CONDITIONAL current_side equals 1}
[/show_if]
[/set_menu_item]
[set_menu_item]
id=bar6
description=foo6
[/set_menu_item]
[set_menu_item]
id=bar7
description=foo7
[/set_menu_item]
[set_menu_item]
id=bar8
description=foo8
[/set_menu_item]
[clear_menu_item]
id=bar5
[/clear_menu_item]
[set_menu_item]
id=bar9
description=foo9
[show_if]
{VARIABLE_CONDITIONAL current_side equals 1}
[/show_if]
[/set_menu_item]
[set_menu_item]
id=bar10
description=foo10
[show_if]
{VARIABLE_CONDITIONAL current_side equals 1}
[/show_if]
[/set_menu_item]
[set_menu_item]
id=bar12
description=foo12
[/set_menu_item]
[set_menu_item]
id=bar13
description=foo13
[command]
[chat]
message="ASDFSAASDF"
[/chat]
[/command]
[/set_menu_item]
[set_menu_item]
id=bar14
description=foo14
[/set_menu_item]
[set_menu_item]
id=bar15
description=foo15
[/set_menu_item]
[set_menu_item]
id=bar16
description=foo16
[/set_menu_item]
[set_menu_item]
id=bar17
description=foo17
[/set_menu_item]
[set_menu_item]
id=bar18
description=foo18
[/set_menu_item]
[set_menu_item]
id=bar19
description=foo19
[/set_menu_item]
[set_menu_item]
id=bar20
description=foo20
[/set_menu_item]
[set_menu_item]
id=bar21
description=foo21
[/set_menu_item]
[/event]
)}
12 changes: 6 additions & 6 deletions src/game_events/wmi_container.cpp
Expand Up @@ -105,13 +105,13 @@ bool wmi_container::fire_item(const std::string & id, const map_location & hex)
* @param[out] items Pointers to applicable menu items will be pushed onto @a items.
* @param[out] descriptions Menu item text will be pushed onto @descriptions (in the same order as @a items).
*/
void wmi_container::get_items(const map_location& hex,
std::vector<boost::shared_ptr<const wml_menu_item> > & items,
std::vector<std::string> & descriptions, const_iterator start, const_iterator finish) const
std::vector<std::pair<boost::shared_ptr<const wml_menu_item>, std::string> > wmi_container::get_items(const map_location& hex,
const_iterator start, const_iterator finish) const
{
std::vector<std::pair<boost::shared_ptr<const wml_menu_item>, std::string> > ret;
if ( empty() )
// Nothing to do (skip setting game variables).
return;
return ret;

// Prepare for can show().
resources::gamedata->get_variable("x1") = hex.x + 1;
Expand All @@ -125,10 +125,10 @@ void wmi_container::get_items(const map_location& hex,
if ( item->use_wml_menu() && item->can_show(hex) )
{
// Include this item.
items.push_back(item);
descriptions.push_back(item->menu_text());
ret.push_back(std::make_pair(item, item->menu_text()));
}
}
return ret;
}

/**
Expand Down
10 changes: 3 additions & 7 deletions src/game_events/wmi_container.hpp
Expand Up @@ -75,15 +75,11 @@ class wmi_container{
/// Fires the menu item with the given @a id.
bool fire_item(const std::string & id, const map_location & hex) const;
/// Returns the menu items that can be shown for the given location.
void get_items(const map_location& hex,
std::vector<boost::shared_ptr<const wml_menu_item> > & items,
std::vector<std::string> & descriptions,
std::vector<std::pair<boost::shared_ptr<const wml_menu_item>, std::string> > get_items(const map_location& hex,
const_iterator start, const_iterator finish) const;
/// Range over all items by default
void get_items(const map_location& hex,
std::vector<boost::shared_ptr<const wml_menu_item> > & items,
std::vector<std::string> & descriptions) const {
get_items(hex, items, descriptions, begin(), end());
std::vector<std::pair<boost::shared_ptr<const wml_menu_item>, std::string> > get_items(const map_location& hex) const {
return get_items(hex, begin(), end());
}
/// Initializes the implicit event handlers for inlined [command]s.
void init_handlers() const;
Expand Down
10 changes: 10 additions & 0 deletions src/game_preferences.cpp
Expand Up @@ -987,6 +987,16 @@ int chat_message_aging()
return lexical_cast_default<int>(preferences::get("chat_message_aging"), 20);
}

void set_max_wml_menu_items(int max)
{
preferences::set("max_wml_menu_items", max);
}

int max_wml_menu_items()
{
return lexical_cast_default<int>(preferences::get("max_wml_menu_items"), 7);
}

bool show_all_units_in_help() {
return preferences::get("show_all_units_in_help", false);
}
Expand Down
3 changes: 3 additions & 0 deletions src/game_preferences.hpp
Expand Up @@ -233,6 +233,9 @@ class acquaintance;
int chat_message_aging();
void set_chat_message_aging(const int aging);

int max_wml_menu_items();
void set_max_wml_menu_items(int max);

bool show_all_units_in_help();
void set_show_all_units_in_help(bool value);

Expand Down
84 changes: 59 additions & 25 deletions src/wmi_pager.cpp
Expand Up @@ -19,10 +19,13 @@
#include "config.hpp"
#include "game_events/menu_item.hpp"
#include "game_events/wmi_container.hpp"
#include "game_preferences.hpp"
#include "gettext.hpp"

#include <algorithm> //std::transform
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <cassert>
#include <iterator> //std::advance
#include <string>
#include <vector>
Expand All @@ -45,7 +48,7 @@ static void add_next_page_item( std::vector<boost::shared_ptr<const game_events:
static void add_prev_page_item( std::vector<boost::shared_ptr<const game_events::wml_menu_item> > & items,
std::vector<std::string> & descriptions)
{
std::string desc = _("Earlier Items");
std::string desc = _("Previous Items");
config temp;
temp["description"] = desc;
items.push_back(boost::make_shared<const game_events::wml_menu_item>(prev_id, temp));
Expand All @@ -64,20 +67,42 @@ bool wmi_pager::capture ( const game_events::wml_menu_item & item )
return false;
}

typedef game_events::wmi_container::const_iterator wmi_it;
typedef boost::shared_ptr<const game_events::wml_menu_item> wmi_ptr;
typedef std::pair<wmi_ptr, std::string> wmi_pair;
typedef std::vector<wmi_pair>::iterator wmi_it;

static wmi_ptr select_first(const wmi_pair & p)
{
return p.first;
}

static std::string select_second(const wmi_pair & p)
{
return p.second;
}

void wmi_pager::get_items(const map_location& hex,
std::vector<boost::shared_ptr<const game_events::wml_menu_item> > & items,
std::vector<wmi_ptr > & items,
std::vector<std::string> & descriptions)
{
if (!foo_) {
return;
}

assert(page_size_ > 2u); //if we dont have at least 3 items, we can't display anything...
const int page_size_int = preferences::max_wml_menu_items();

assert(page_size_int >= 0 && "max wml menu items cannot be negative, this indicates preferences corruption");

const size_t page_size = page_size_int;

assert(page_size > 2u && "if we dont have at least 3 items, we can't display anything on a middle page...");

std::vector<wmi_pair > bar = foo_->get_items(hex);

if (bar.size() <= page_size) { //In this case the first page is sufficient and we don't have to do anything.
std::transform(bar.begin(), bar.end(), back_inserter(items), select_first);
std::transform(bar.begin(), bar.end(), back_inserter(descriptions), select_second);

if (foo_->size() <= page_size_) { //In this case the first page is sufficient and we don't have to do anything.
foo_->get_items(hex, items, descriptions);
page_num_ = 0; //reset page num in case there are more items later.
return;
}
Expand All @@ -87,44 +112,53 @@ void wmi_pager::get_items(const map_location& hex,
page_num_ = 0;
}

if (page_num_ == 0) { //we are on the first page, so show page_size_-1 items and a next button
wmi_it end_first_page = foo_->begin();
std::advance(end_first_page, page_size_ - 1);
if (page_num_ == 0) { //we are on the first page, so show page_size-1 items and a next button
wmi_it end_first_page = bar.begin();
std::advance(end_first_page, page_size - 1);

foo_->get_items(hex, items, descriptions, foo_->begin(), end_first_page);
std::transform(bar.begin(), end_first_page, back_inserter(items), select_first);
std::transform(bar.begin(), end_first_page, back_inserter(descriptions), select_second);

add_next_page_item(items, descriptions);
return;
}

add_prev_page_item(items, descriptions); //this will be necessary since we aren't on the first page

// first page has page_size_ - 1.
// last page has page_size_ - 1.
// all other pages have page_size_ - 2;
// first page has page_size - 1.
// last page has page_size - 1.
// all other pages have page_size - 2;

size_t first_displayed_index = (page_size_ - 2) * page_num_ + 1; //this is the 0-based index of the first item displayed on this page.
size_t first_displayed_index = (page_size - 2) * page_num_ + 1; //this is the 0-based index of the first item displayed on this page.
//alternatively, the number of items displayed on earlier pages

while (first_displayed_index >= foo_->size())
while (first_displayed_index >= bar.size())
{
page_num_--; //The list must have gotten shorter and our page counter is now off the end, so decrement
first_displayed_index = (page_size_ - 2) * page_num_ + 1; //recalculate
first_displayed_index = (page_size - 2) * page_num_ + 1; //recalculate
}
// ^ This loop terminates with first_displayed_index > 0, because foo_->size() > page_size_ or else we exited earlier, and we only decrease by (page_size_-2) each time.
// ^ This loop terminates with first_displayed_index > 0, because bar.size() > page_size or else we exited earlier, and we only decrease by (page_size-2) each time.

wmi_it start_range = foo_->begin();
std::advance(start_range, first_displayed_index); // <-- get an iterator to the start of our range. begin() + n doesn't work because map is not random access
//^ = foo_->begin() + first_displayed_index

if (first_displayed_index + page_size_-1 >= foo_->size()) //if this can be the last page, then we won't put next page at the bottom.
if (first_displayed_index + page_size-1 >= bar.size()) //if this can be the last page, then we won't put next page at the bottom.
{
foo_->get_items(hex, items, descriptions, start_range, foo_->end()); // display all of the remaining items
//The last page we treat differently -- we always want to display (page_size) entries, to prevent resizing the context menu, so count back from end.
wmi_it end_range = bar.end(); // It doesn't really matter if we display some entries that appeared on the previous page by doing this.
wmi_it start_range = end_range;
std::advance(start_range, -(page_size-1));

std::transform(start_range, end_range, back_inserter(items), select_first);
std::transform(start_range, end_range, back_inserter(descriptions), select_second);
return;
} else { //we are in a middle page
wmi_it start_range = bar.begin();
std::advance(start_range, first_displayed_index); // <-- get an iterator to the start of our range. begin() + n doesn't work because map is not random access

wmi_it end_range = start_range;
std::advance(end_range, page_size_-2);
std::advance(end_range, page_size-2);

std::transform(start_range, end_range, back_inserter(items), select_first);
std::transform(start_range, end_range, back_inserter(descriptions), select_second);

foo_->get_items(hex, items, descriptions, start_range, end_range);
add_next_page_item(items, descriptions);
return;
}
Expand Down
6 changes: 4 additions & 2 deletions src/wmi_pager.hpp
Expand Up @@ -17,6 +17,9 @@
* container. It is an adapter, managing the production of items lists
* from the container, and screening the "fire" signals coming back
* in to intercept the paging signals.
*
* TODO: Implement this as a helper class for menu perhaps, so that it
* can interact with the gui layout algorithm.
*/

struct map_location;
Expand All @@ -32,11 +35,10 @@ namespace game_events { class wmi_container; }
class wmi_pager {
private:
int page_num_; //!< Current page number
size_t page_size_; //!< Current size of a page
const game_events::wmi_container * foo_; //!< Internal pointer to the collection of wml menu items

public:
wmi_pager() : page_num_(0), page_size_(7), foo_(NULL) {}
wmi_pager() : page_num_(0), foo_(NULL) {}

void update_ref(game_events::wmi_container * ptr) { foo_ = ptr; } //!< Updates the internal wmi_container pointer

Expand Down

0 comments on commit 1cb74d6

Please sign in to comment.