1 #include "MultiIconValueIndicator.h"
2
3 #include <GG/Texture.h>
4
5 #include "../util/i18n.h"
6 #include "../util/Logger.h"
7 #include "../universe/PopCenter.h"
8 #include "../universe/UniverseObject.h"
9 #include "../universe/Enums.h"
10 #include "../client/human/HumanClientApp.h"
11 #include "ClientUI.h"
12 #include "CUIControls.h"
13
14 namespace {
15 const int EDGE_PAD(3);
16
IconSpacing()17 int IconSpacing()
18 { return ClientUI::Pts(); }
IconWidth()19 GG::X IconWidth()
20 { return GG::X(IconSpacing()*2); }
IconHeight()21 GG::Y IconHeight()
22 { return GG::Y(IconSpacing()*2); }
23 }
24
MultiIconValueIndicator(GG::X w)25 MultiIconValueIndicator::MultiIconValueIndicator(GG::X w) :
26 MultiIconValueIndicator(w, {}, {})
27 {}
28
MultiIconValueIndicator(GG::X w,int object_id,const std::vector<std::pair<MeterType,MeterType>> & meter_types)29 MultiIconValueIndicator::MultiIconValueIndicator(
30 GG::X w, int object_id,
31 const std::vector<std::pair<MeterType, MeterType>>& meter_types) :
32 MultiIconValueIndicator(w, std::vector<int>{object_id}, meter_types)
33 {}
34
MultiIconValueIndicator(GG::X w,const std::vector<int> & object_ids,const std::vector<std::pair<MeterType,MeterType>> & meter_types)35 MultiIconValueIndicator::MultiIconValueIndicator(
36 GG::X w, const std::vector<int>& object_ids,
37 const std::vector<std::pair<MeterType, MeterType>>& meter_types) :
38 GG::Wnd(GG::X0, GG::Y0, w, GG::Y1, GG::INTERACTIVE),
39 m_meter_types(meter_types),
40 m_object_ids(object_ids)
41 {}
42
CompleteConstruction()43 void MultiIconValueIndicator::CompleteConstruction() {
44 GG::Wnd::CompleteConstruction();
45
46 SetName("MultiIconValueIndicator");
47
48 GG::X x(EDGE_PAD);
49 for (const auto& meter_type : m_meter_types) {
50 const MeterType PRIMARY_METER_TYPE = meter_type.first;
51 // get icon texture.
52 auto texture = ClientUI::MeterIcon(PRIMARY_METER_TYPE);
53
54 // special case for population meter for an indicator showing only a
55 // single popcenter: icon is species icon, rather than generic pop icon
56 if (PRIMARY_METER_TYPE == METER_POPULATION && m_object_ids.size() == 1) {
57 if (auto pc = Objects().get<PopCenter>(*m_object_ids.begin()))
58 texture = ClientUI::SpeciesIcon(pc->SpeciesName());
59 }
60
61 m_icons.push_back(GG::Wnd::Create<StatisticIcon>(texture, 0.0, 3, false, IconWidth(), IconHeight()));
62 GG::Pt icon_ul(x, GG::Y(EDGE_PAD));
63 GG::Pt icon_lr = icon_ul + GG::Pt(IconWidth(), IconHeight() + ClientUI::Pts()*3/2);
64 m_icons.back()->SizeMove(icon_ul, icon_lr);
65 auto meter = meter_type.first;
66 auto meter_string = boost::lexical_cast<std::string>(meter_type.first);
67 m_icons.back()->RightClickedSignal.connect([this, meter, meter_string](const GG::Pt& pt) {
68 auto popup = GG::Wnd::Create<CUIPopupMenu>(pt.x, pt.y);
69
70 auto pc = Objects().get<PopCenter>(*(this->m_object_ids.begin()));
71 if (meter == METER_POPULATION && pc && this->m_object_ids.size() == 1) {
72 auto species_name = pc->SpeciesName();
73 if (!species_name.empty()) {
74 auto zoom_species_action = [species_name]() { ClientUI::GetClientUI()->ZoomToSpecies(species_name); };
75 std::string species_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) %
76 UserString(species_name));
77 popup->AddMenuItem(GG::MenuItem(species_label, false, false, zoom_species_action));
78 }
79 }
80
81
82 auto zoom_article_action = [meter_string]() { ClientUI::GetClientUI()->ZoomToMeterTypeArticle(meter_string);};
83 std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) %
84 UserString(meter_string));
85 popup->AddMenuItem(GG::MenuItem(popup_label, false, false, zoom_article_action));
86 popup->Run();
87 });
88 AttachChild(m_icons.back());
89 x += IconWidth() + IconSpacing();
90 }
91 if (!m_icons.empty())
92 Resize(GG::Pt(Width(), EDGE_PAD + IconHeight() + ClientUI::Pts()*3/2));
93 Update();
94 }
95
Empty() const96 bool MultiIconValueIndicator::Empty() const
97 { return m_object_ids.empty(); }
98
Render()99 void MultiIconValueIndicator::Render() {
100 GG::Pt ul = UpperLeft();
101 GG::Pt lr = LowerRight();
102
103 // outline of whole control
104 GG::FlatRectangle(ul, lr, ClientUI::WndColor(), ClientUI::WndOuterBorderColor(), 1);
105 }
106
MouseWheel(const GG::Pt & pt,int move,GG::Flags<GG::ModKey> mod_keys)107 void MultiIconValueIndicator::MouseWheel(const GG::Pt& pt, int move, GG::Flags<GG::ModKey> mod_keys)
108 { ForwardEventToParent(); }
109
Update()110 void MultiIconValueIndicator::Update() {
111 if (m_icons.size() != m_meter_types.size()) {
112 ErrorLogger() << "MultiIconValueIndicator::Update has inconsitent numbers of icons and meter types";
113 return;
114 }
115
116 for (std::size_t i = 0; i < m_icons.size(); ++i) {
117 assert(m_icons[i]);
118 double total = 0.0;
119 for (const auto& obj : Objects().find<UniverseObject>(m_object_ids)) {
120 if (!obj)
121 continue;
122 //DebugLogger() << "MultiIconValueIndicator::Update object:";
123 //DebugLogger() << obj->Dump();
124 auto type = m_meter_types[i].first;
125 double value = obj->GetMeter(type)->Initial();
126 // Supply is a special case: the only thing that matters is the highest value.
127 if (type == METER_SUPPLY)
128 total = std::max(total, value);
129 else
130 total += value;
131 }
132 m_icons[i]->SetValue(total);
133 }
134 }
135
SetToolTip(MeterType meter_type,const std::shared_ptr<GG::BrowseInfoWnd> & browse_wnd)136 void MultiIconValueIndicator::SetToolTip(MeterType meter_type, const std::shared_ptr<GG::BrowseInfoWnd>& browse_wnd) {
137 for (unsigned int i = 0; i < m_icons.size(); ++i)
138 if (m_meter_types.at(i).first == meter_type)
139 m_icons.at(i)->SetBrowseInfoWnd(browse_wnd);
140 }
141
ClearToolTip(MeterType meter_type)142 void MultiIconValueIndicator::ClearToolTip(MeterType meter_type) {
143 for (unsigned int i = 0; i < m_icons.size(); ++i)
144 if (m_meter_types.at(i).first == meter_type)
145 m_icons.at(i)->ClearBrowseInfoWnd();
146 }
147