File: MultiIconValueIndicator.cpp

package info (click to toggle)
freeorion 0.5.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 194,920 kB
  • sloc: cpp: 186,821; python: 40,979; ansic: 1,164; xml: 721; makefile: 32; sh: 7
file content (149 lines) | stat: -rw-r--r-- 6,241 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "MultiIconValueIndicator.h"

#include <GG/Texture.h>

#include "../util/i18n.h"
#include "../util/Logger.h"
#include "../universe/UniverseObject.h"
#include "../universe/Planet.h"
#include "../universe/Enums.h"
#include "../client/human/GGHumanClientApp.h"
#include "ClientUI.h"
#include "CUIControls.h"

namespace {
    constexpr int EDGE_PAD(3);

    int IconSpacing() { return ClientUI::Pts(); }
    GG::X IconWidth() { return GG::X(IconSpacing()*2); }
    GG::Y IconHeight() { return GG::Y(IconSpacing()*2); }
}

MultiIconValueIndicator::MultiIconValueIndicator(GG::X w) :
    MultiIconValueIndicator(w, {}, {})
{}

MultiIconValueIndicator::MultiIconValueIndicator(
    GG::X w, int object_id,
    std::vector<std::pair<MeterType, MeterType>> meter_types) :
    MultiIconValueIndicator(w, std::vector<int>{object_id}, std::move(meter_types))
{}

MultiIconValueIndicator::MultiIconValueIndicator(
    GG::X w, const std::vector<int>& object_ids,
    std::vector<std::pair<MeterType, MeterType>> meter_types) :
    GG::Wnd(GG::X0, GG::Y0, w, GG::Y1, GG::INTERACTIVE),
    m_meter_types(std::move(meter_types)),
    m_object_ids(object_ids)
{}

void MultiIconValueIndicator::CompleteConstruction() {
    GG::Wnd::CompleteConstruction();

    SetName("MultiIconValueIndicator");

    GG::X x{EDGE_PAD};
    for (const auto& meter_type : m_meter_types) {
        const MeterType PRIMARY_METER_TYPE = meter_type.first;
        // get icon texture.
        auto texture = ClientUI::MeterIcon(PRIMARY_METER_TYPE);

        // special case for population meter for an indicator showing only a
        // single popcenter: icon is species icon, rather than generic pop icon
        if (PRIMARY_METER_TYPE == MeterType::METER_POPULATION && m_object_ids.size() == 1) {
            if (auto pc = Objects().get<Planet>(m_object_ids.front()))
                texture = ClientUI::SpeciesIcon(pc->SpeciesName());
        }

        m_icons.push_back(GG::Wnd::Create<StatisticIcon>(std::move(texture), 0.0, 3, false,
                                                         IconWidth(), IconHeight()));
        const GG::Pt icon_ul(x, GG::Y(EDGE_PAD));
        const GG::Pt icon_lr = icon_ul + GG::Pt(IconWidth(), IconHeight() + ClientUI::Pts()*3/2);
        m_icons.back()->SizeMove(icon_ul, icon_lr);
        const auto meter = meter_type.first;
        const auto meter_string = to_string(meter_type.first);
        m_icons.back()->RightClickedSignal.connect([this, meter, meter_string](GG::Pt pt) {
            auto popup = GG::Wnd::Create<CUIPopupMenu>(pt.x, pt.y);

            auto pc = Objects().get<Planet>(this->m_object_ids.front());
            if (meter == MeterType::METER_POPULATION && pc && this->m_object_ids.size() == 1) {
                auto species_name = pc->SpeciesName();  // intentionally making a copy for use in lambda
                if (!species_name.empty()) {
                    auto zoom_species_action = [species_name]() { ClientUI::GetClientUI()->ZoomToSpecies(species_name); };
                    std::string species_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) %
                                                                              UserString(species_name));
                    popup->AddMenuItem(GG::MenuItem(std::move(species_label), false, false,
                                                    zoom_species_action));
                }
            }


            auto zoom_article_action = [meter_string]() { ClientUI::GetClientUI()->ZoomToMeterTypeArticle(std::string{meter_string});}; // TODO: avoid copy
            std::string popup_label = boost::io::str(FlexibleFormat(UserString("ENC_LOOKUP")) %
                                                                    UserString(meter_string));
            popup->AddMenuItem(GG::MenuItem(std::move(popup_label), false, false,
                                            zoom_article_action));
            popup->Run();
        });
        AttachChild(m_icons.back());
        x += IconWidth() + IconSpacing();
    }
    if (!m_icons.empty())
        Resize(GG::Pt(Width(), EDGE_PAD + IconHeight() + ClientUI::Pts()*3/2));
    Update();
}

bool MultiIconValueIndicator::Empty() const
{ return m_object_ids.empty(); }

void MultiIconValueIndicator::Render() {
    GG::Pt ul = UpperLeft();
    GG::Pt lr = LowerRight();

    // outline of whole control
    GG::FlatRectangle(ul, lr, ClientUI::WndColor(), ClientUI::WndOuterBorderColor(), 1);
}

void MultiIconValueIndicator::MouseWheel(GG::Pt pt, int move, GG::Flags<GG::ModKey> mod_keys)
{ ForwardEventToParent(); }

void MultiIconValueIndicator::Update() {
    if (m_icons.size() != m_meter_types.size()) {
        ErrorLogger() << "MultiIconValueIndicator::Update has inconsitent numbers of icons and meter types";
        return;
    }

    for (std::size_t i = 0; i < m_icons.size(); ++i) {
        assert(m_icons[i]);
        double total = 0.0;
        for (const auto& obj : Objects().find<UniverseObject>(m_object_ids)) {
            if (!obj)
                continue;
            auto type = m_meter_types[i].first;
            const auto* meter{obj->GetMeter(type)};
            if (!meter) {
                ErrorLogger() << "MultiIconValueIndicator::Update couldn't get meter type " << type << " for object " << obj->Name() << " (" << obj->ID() << ")";
                continue;
            }
            double value = obj->GetMeter(type)->Initial();
            // Supply is a special case: the only thing that matters is the highest value.
            if (type == MeterType::METER_SUPPLY)
                total = std::max(total, value);
            else
                total += value;
        }
        m_icons[i]->SetValue(total);
    }
}

void MultiIconValueIndicator::SetToolTip(MeterType meter_type, const std::shared_ptr<GG::BrowseInfoWnd>& browse_wnd) {
    for (unsigned int i = 0; i < m_icons.size(); ++i)
        if (m_meter_types.at(i).first == meter_type)
            m_icons.at(i)->SetBrowseInfoWnd(browse_wnd);
}

void MultiIconValueIndicator::ClearToolTip(MeterType meter_type) {
    for (unsigned int i = 0; i < m_icons.size(); ++i)
        if (m_meter_types.at(i).first == meter_type)
            m_icons.at(i)->ClearBrowseInfoWnd();
}