The Battle for Wesnoth  1.19.4+dev
achievements_dialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
19 #include "game_config_manager.hpp"
20 #include "gettext.hpp"
21 #include "gui/widgets/drawing.hpp"
22 #include "gui/widgets/grid.hpp"
23 #include "gui/widgets/label.hpp"
25 #include "gui/widgets/window.hpp"
26 #include "log.hpp"
28 #include "serialization/markup.hpp"
29 
30 static lg::log_domain log_config("config");
31 #define ERR_CONFIG LOG_STREAM(err, log_config)
32 
33 constexpr int sub_achievements_limit = 28;
34 
35 namespace gui2::dialogs
36 {
37 
39 
41  : modal_dialog(window_id())
42  , achieve_()
43  , last_selected_(prefs::get().selected_achievement_group())
44  , achievements_box_(nullptr)
45  , content_names_(nullptr)
46 {
47 }
48 
50 {
51  std::vector<config> content_list;
52  content_names_ = &find_widget<menu_button>("selected_achievements_list");
54 
55  achievements_box_ = find_widget<listbox>("achievements_list", false, true);
56 
57  std::vector<achievement_group> groups = game_config_manager::get()->get_achievements();
58  int selected = 0;
59 
60  for(const auto& list : groups) {
61  // only display the achievements for the first dropdown option on first showing the dialog
62  if(list.content_for_ == last_selected_ || last_selected_ == "") {
63  selected = content_list.size();
64  }
65 
66  // populate all possibilities into the dropdown
67  content_list.emplace_back("label", list.display_name_);
68  }
69 
70  if(content_list.size() > 0) {
71  content_names_->set_values(content_list);
74  }
75 }
76 
78 {
79  prefs::get().set_selected_achievement_group(last_selected_);
80 }
81 
83 {
87  int achieved_count = 0;
88 
89  for(const auto& ach : list.achievements_) {
90  if(ach.achieved_) {
91  achieved_count++;
92  } else if(ach.hidden_ && !ach.achieved_) {
93  continue;
94  }
95 
96  widget_data row;
97  widget_item item;
98 
99  item["label"] = !ach.achieved_ ? ach.icon_ : ach.icon_completed_;
100  row.emplace("icon", item);
101 
102  if(!ach.achieved_) {
103  t_string name = ach.name_;
104  if(ach.max_progress_ != 0 && ach.current_progress_ != -1) {
105  name += (formatter() << " (" << ach.current_progress_ << "/" << ach.max_progress_).str();
106  }
107  item["label"] = name;
108  } else {
109  item["label"] = ach.name_completed_;
110  item["definition"] = "gold_large";
111  }
112  row.emplace("name", item);
113 
114  if(!ach.achieved_) {
115  item["label"] = ach.description_;
116  } else {
117  item["label"] = markup::span_color("green", ach.description_completed_);
118  }
119  row.emplace("description", item);
120 
121  grid& newrow = achievements_box_->add_row(row);
122  progress_bar* achievement_progress = static_cast<progress_bar*>(newrow.find("achievement_progress", false));
123  if(ach.max_progress_ != 0 && ach.current_progress_ != -1) {
124  achievement_progress->set_percentage((ach.current_progress_/double(ach.max_progress_))*100);
125  } else {
126  achievement_progress->set_visible(gui2::widget::visibility::invisible);
127  }
128 
129  label* name = static_cast<label*>(newrow.find("name", false));
130  canvas& canvas = name->get_canvas(0);
131  canvas.set_variable("achieved", wfl::variant(ach.achieved_));
132 
133  set_sub_achievements(newrow, ach);
134  }
135 
136  label* achieved_label = find_widget<label>("achievement_count", false, true);
137  achieved_label->set_label(_("Completed")+" "+std::to_string(achieved_count)+"/"+std::to_string(list.achievements_.size()));
138 }
139 
141 {
142  int i = 0;
143 
144  // set any sub achievements
145  for(const sub_achievement& sub_ach : ach.sub_achievements_)
146  {
148  {
149  ERR_CONFIG << "Too many sub achievements";
150  break;
151  }
152  else
153  {
154  drawing* img = static_cast<drawing*>(newrow.find("sub_icon"+std::to_string(i), false));
155  img->set_label(sub_ach.achieved_ ? sub_ach.icon_completed_ : sub_ach.icon_);
156  img->set_tooltip(sub_ach.description_);
157  }
158  i++;
159  }
160 
161  // if an achievement hasn't defined the maximum possible sub-achievements, hide the [image]s for the rest
162  for(; i < sub_achievements_limit; i++)
163  {
164  static_cast<drawing*>(newrow.find("sub_icon"+std::to_string(i), false))->set_visible(visibility::invisible);
165  }
166 }
167 
168 } // namespace gui2::dialogs
constexpr int sub_achievements_limit
#define ERR_CONFIG
static lg::log_domain log_config("config")
std::ostringstream wrapper.
Definition: formatter.hpp:40
static game_config_manager * get()
std::vector< achievement_group > & get_achievements()
A simple canvas which can be drawn upon.
Definition: canvas.hpp:45
void set_variable(const std::string &key, wfl::variant &&value)
Definition: canvas.hpp:154
virtual void post_show() override
Actions to be taken after the window has been shown.
virtual void pre_show() override
Actions to be taken before showing the window.
void set_sub_achievements(grid &newrow, const achievement &ach)
Abstract base class for all modal dialogs.
Base container class.
Definition: grid.hpp:32
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Definition: grid.cpp:645
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Definition: listbox.cpp:58
void clear()
Removes all the rows in the listbox, clearing it.
Definition: listbox.cpp:117
void set_selected(unsigned selected, bool fire_event=true)
void set_values(const std::vector<::config > &values, unsigned selected=0)
virtual unsigned get_value() const override
Inherited from selectable_item.
Definition: menu_button.hpp:55
void set_percentage(unsigned percentage)
virtual void set_label(const t_string &text)
canvas & get_canvas(const unsigned index)
void set_visible(const visibility visible)
Definition: widget.cpp:479
@ invisible
The user set the widget invisible, that means:
static prefs & get()
std::size_t i
Definition: function.cpp:1023
static std::string _(const char *str)
Definition: gettext.hpp:93
This file contains the window object, this object is a top level container which has the event manage...
Standard logging facilities (interface).
CURSOR_TYPE get()
Definition: cursor.cpp:216
std::string selected
REGISTER_DIALOG(editor_edit_unit)
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:203
std::map< std::string, widget_item > widget_data
Definition: widget.hpp:36
std::map< std::string, t_string > widget_item
Definition: widget.hpp:33
std::string img(const std::string &src, const std::string &align, const bool floating)
Definition: markup.cpp:29
std::string span_color(const color_t &color, Args &&... data)
Returns a Pango formatting string using the provided color_t object.
Definition: markup.hpp:68
A set of achievements tied to a particular content.
std::string content_for_
The internal ID used for this content.
std::vector< achievement > achievements_
The achievements associated to this content.
Represents a single achievement and its data.
std::vector< sub_achievement > sub_achievements_
The list of distinct sub-achievements for this achievement.
Represents a distinct sub-achievement within another achievement.
t_string description_
The description of the sub-achievement to be shown in its tooltip.
std::string icon_completed_
The icon of the sub-achievement to show on the UI when completed.
std::string icon_
The icon of the sub-achievement to show on the UI when not completed.
bool achieved_
Whether the sub-achievement has been completed.