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