Skip to content

Commit 73cc288

Browse files
authored
Merge pull request #1451 from OutpostUniverse/AddListboxToResearchReport
Add listbox to research report
2 parents c08eecc + 3d49d12 commit 73cc288

File tree

3 files changed

+166
-62
lines changed

3 files changed

+166
-62
lines changed

OPHD/UI/Reports/ResearchReport.cpp

+124-53
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <NAS2D/Utility.h>
44
#include <NAS2D/EventHandler.h>
55
#include <NAS2D/Renderer/Renderer.h>
6-
#include <NAS2D/Math/Rectangle.h>
76

87
#include "../../Constants/UiConstants.h"
98
#include "../../Cache.h"
@@ -38,19 +37,22 @@ namespace
3837
constexpr NAS2D::Vector<int> CategorySelectorPadding{2, 2};
3938
constexpr NAS2D::Vector<int> SectionPadding {10, 10};
4039

41-
struct CategoryPanel
42-
{
43-
NAS2D::Rectangle<int> rect{};
44-
NAS2D::Rectangle<int> imageSlice{};
45-
std::string name{};
46-
bool selected{false};
47-
};
4840

49-
CategoryPanel* SelectedCategory{ nullptr };
50-
51-
Rectangle<int> IconArea{};
41+
std::vector<ListBoxItemText> availableTopics(const std::string& categoryName, const TechnologyCatalog& catalog, const ResearchTracker& tracker)
42+
{
43+
std::vector<ListBoxItemText> itemsToAdd;
44+
const auto& completedTopics = tracker.completedResearch();
45+
for (const auto& topic : catalog.technologiesInCategory(categoryName))
46+
{
47+
const auto it = std::find(completedTopics.begin(), completedTopics.end(), topic.id);
48+
if (it == completedTopics.end())
49+
{
50+
itemsToAdd.emplace_back(ListBoxItemText{topic.name, topic.id});
51+
}
52+
}
5253

53-
std::vector<CategoryPanel> CategoryPanels;
54+
return itemsToAdd;
55+
}
5456
}
5557

5658

@@ -78,6 +80,9 @@ ResearchReport::ResearchReport() :
7880
button->toggle(false);
7981
}
8082

83+
add(lstResearchTopics, {});
84+
lstResearchTopics.selectionChanged().connect({this, &ResearchReport::handleTopicChanged});
85+
8186
const Point<int> buttonStartPosition{rect().position.x + MarginSize * 3 + CategoryIconSize, rect().position.y + MarginSize * 2 + fontBigBold.height()};
8287
const int buttonSpacing = btnAllTopics.size().x + MarginSize;
8388

@@ -95,37 +100,84 @@ ResearchReport::~ResearchReport()
95100

96101
void ResearchReport::fillLists()
97102
{
103+
lstResearchTopics.clear();
104+
resetCategorySelection();
105+
onAllTopicsClicked();
98106
}
99107

100108

101109
void ResearchReport::clearSelected()
102110
{
111+
lstResearchTopics.clearSelected();
112+
resetCategorySelection();
113+
onAllTopicsClicked();
103114
}
104115

105116

106117
void ResearchReport::refresh()
107118
{
108-
if (CategoryPanels.size() < 1) { return; }
119+
if (mCategoryPanels.size() < 1) { return; }
120+
121+
adjustCategoryIconSpacing();
122+
123+
resetCategorySelection();
124+
onAllTopicsClicked();
125+
126+
setSectionRects();
127+
128+
lstResearchTopics.area(mResearchTopicArea);
129+
}
130+
131+
132+
void ResearchReport::setSectionRects()
133+
{
134+
mCategoryIconArea =
135+
{
136+
mCategoryPanels.begin()->rect.startPoint(),
137+
{
138+
CategoryIconSize,
139+
mCategoryPanels.rbegin()->rect.endPoint().y - mCategoryPanels.begin()->rect.startPoint().y
140+
}
141+
};
142+
143+
mResearchTopicArea =
144+
{
145+
{
146+
rect().position.x + MarginSize * 3 + CategoryIconSize,
147+
rect().position.y + fontBigBold.height() + btnAllTopics.size().y + MarginSize * 3
148+
},
149+
150+
{
151+
((rect().size.x / 3) * 2) - (MarginSize * 4) - CategoryIconSize,
152+
rect().size.y - MarginSize * 4 - fontBigBold.height() - btnAllTopics.size().y
153+
}
154+
};
155+
}
156+
109157

110-
const int minimumHeight = CategoryIconSize * (static_cast<int>(CategoryPanels.size()));
111-
const int padding = ((rect().size.y - 20) - minimumHeight) / static_cast<int>(CategoryPanels.size() - 1);
158+
void ResearchReport::adjustCategoryIconSpacing()
159+
{
160+
const int minimumHeight = CategoryIconSize * (static_cast<int>(mCategoryPanels.size()));
161+
const int padding = ((rect().size.y - 20) - minimumHeight) / static_cast<int>(mCategoryPanels.size() - 1);
112162

113-
for (size_t i = 0; i < CategoryPanels.size(); ++i)
163+
for (size_t i = 0; i < mCategoryPanels.size(); ++i)
114164
{
115165
const NAS2D::Point<int> point{rect().position.x + 10, rect().position.y + 10 + static_cast<int>(i) * CategoryIconSize + static_cast<int>(i) * padding};
116-
CategoryPanels[i].rect = {point, {CategoryIconSize, CategoryIconSize}};
166+
mCategoryPanels[i].rect = {point, {CategoryIconSize, CategoryIconSize}};
117167
}
168+
}
118169

119-
CategoryPanels.front().selected = true;
120-
SelectedCategory = &CategoryPanels.front();
121170

122-
onAllTopicsClicked();
171+
void ResearchReport::resetCategorySelection()
172+
{
173+
for (auto& panel : mCategoryPanels)
174+
{
175+
panel.selected = false;
176+
}
123177

124-
IconArea = {
125-
{rect().position.x + MarginSize * 3 + CategoryIconSize,
126-
rect().position.y + fontBigBold.height() + btnAllTopics.size().y + MarginSize * 3},
127-
{((rect().size.x / 3) * 2) - (MarginSize * 4) - CategoryIconSize,
128-
rect().size.y - MarginSize * 4 - fontBigBold.height() - btnAllTopics.size().y}};
178+
mCategoryPanels.front().selected = true;
179+
mSelectedCategory = &mCategoryPanels.front();
180+
handleCategoryChanged();
129181
}
130182

131183

@@ -143,14 +195,14 @@ void ResearchReport::injectTechReferences(TechnologyCatalog& catalog, ResearchTr
143195

144196
for (const auto& category : mTechCatalog->categories())
145197
{
146-
CategoryPanels.emplace_back(CategoryPanel{
198+
mCategoryPanels.emplace_back(CategoryPanel{
147199
{{0, 0}, {CategoryIconSize, CategoryIconSize}},
148200
{{(category.icon_index % columns) * CategoryIconSize, (category.icon_index / columns) * CategoryIconSize}, {CategoryIconSize, CategoryIconSize}},
149201
category.name,
150202
false});
151203
}
152204

153-
std::sort(CategoryPanels.begin(), CategoryPanels.end(), [](const auto& a, const auto& b) { return a.name < b.name; });
205+
std::sort(mCategoryPanels.begin(), mCategoryPanels.end(), [](const auto& a, const auto& b) { return a.name < b.name; });
154206
refresh();
155207
}
156208

@@ -177,26 +229,34 @@ void ResearchReport::onMouseDown(NAS2D::EventHandler::MouseButton button, NAS2D:
177229
return;
178230
}
179231

180-
CategoryPanel* lastPanel = SelectedCategory;
232+
if (mCategoryIconArea.contains(position))
233+
{
234+
handleMouseDownInCategories(position);
235+
}
236+
}
237+
238+
239+
void ResearchReport::handleMouseDownInCategories(NAS2D::Point<int>& position)
240+
{
241+
CategoryPanel* lastPanel = mSelectedCategory;
181242
bool panelClickedOn = false;
182-
for (auto& panel : CategoryPanels)
243+
for (auto& panel : mCategoryPanels)
183244
{
184-
if(panel.rect.contains(position))
245+
panel.selected = false;
246+
247+
if (panel.rect.contains(position))
185248
{
186249
panel.selected = true;
187-
SelectedCategory = &panel;
250+
mSelectedCategory = &panel;
188251
panelClickedOn = true;
189-
}
190-
else
191-
{
192-
panel.selected = false;
252+
handleCategoryChanged();
193253
}
194254
}
195255

196-
if(!panelClickedOn && lastPanel != nullptr)
256+
if (!panelClickedOn && lastPanel != nullptr)
197257
{
198-
SelectedCategory = lastPanel;
199-
SelectedCategory->selected = true;
258+
mSelectedCategory = lastPanel;
259+
mSelectedCategory->selected = true;
200260
}
201261
}
202262

@@ -250,7 +310,7 @@ void ResearchReport::drawCategories() const
250310
{
251311
auto& renderer = Utility<Renderer>::get();
252312

253-
for (const auto& panel : CategoryPanels)
313+
for (const auto& panel : mCategoryPanels)
254314
{
255315
const auto panelRect = Rectangle<int>::Create(
256316
panel.rect.position - CategorySelectorPadding,
@@ -275,7 +335,7 @@ void ResearchReport::drawTopicHeader() const
275335
auto& renderer = Utility<Renderer>::get();
276336
renderer.drawText(
277337
fontBigBold,
278-
SelectedCategory->name,
338+
mSelectedCategory->name,
279339
rect().position + Vector<int>{SectionPadding.x * 3 + CategoryIconSize, SectionPadding.y},
280340
ColorText);
281341
}
@@ -284,25 +344,18 @@ void ResearchReport::drawTopicHeader() const
284344
void ResearchReport::drawVerticalSectionSpacer(const int startX) const
285345
{
286346
auto& renderer = Utility<Renderer>::get();
287-
renderer.drawLine(
288-
Point<int>{startX, rect().position.y + SectionPadding.y},
289-
Point<int>{startX, rect().position.y + rect().size.y - SectionPadding.y},
290-
ColorText);
291-
}
292-
293347

294-
void ResearchReport::drawTopicIconPanel() const
295-
{
296-
auto& renderer = Utility<Renderer>::get();
297-
renderer.drawBox(IconArea, ColorText);
348+
const Point<int> start{startX, rect().position.y + SectionPadding.y};
349+
const Point<int> end{startX, rect().position.y + rect().size.y - SectionPadding.y};
350+
renderer.drawLine(start, end, ColorText);
298351
}
299352

300353

301354
void ResearchReport::drawResearchPointsPanel() const
302355
{
303356
auto& renderer = Utility<Renderer>::get();
304357

305-
const auto startPoint = rect().position + Vector<int>{SectionPadding.x * 5 + CategoryIconSize + IconArea.size.x, SectionPadding.y};
358+
const auto startPoint = rect().position + Vector<int>{SectionPadding.x * 5 + CategoryIconSize + mResearchTopicArea.size.x, SectionPadding.y};
306359

307360
renderer.drawText(fontBigBold, "Research Generated Per Turn", startPoint, ColorText);
308361

@@ -323,14 +376,32 @@ void ResearchReport::drawResearchPointsPanel() const
323376
}
324377

325378

379+
void ResearchReport::handleCategoryChanged()
380+
{
381+
lstResearchTopics.clear();
382+
383+
std::vector<ListBoxItemText> itemsToAdd = availableTopics(mSelectedCategory->name, *mTechCatalog, *mResearchTracker);
384+
385+
std::sort(itemsToAdd.begin(), itemsToAdd.end());
386+
for (auto& item : itemsToAdd)
387+
{
388+
lstResearchTopics.add(item);
389+
}
390+
}
391+
392+
393+
void ResearchReport::handleTopicChanged()
394+
{
395+
}
396+
397+
326398
void ResearchReport::draw() const
327399
{
328400
drawCategories();
329401

330-
drawVerticalSectionSpacer(CategoryPanels.front().rect.endPoint().x + SectionPadding.x);
402+
drawVerticalSectionSpacer(mCategoryPanels.front().rect.endPoint().x + SectionPadding.x);
331403

332404
drawTopicHeader();
333-
drawTopicIconPanel();
334405

335406
drawVerticalSectionSpacer((rect().size.x / 3) * 2);
336407

OPHD/UI/Reports/ResearchReport.h

+37-9
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
#include <libOPHD/Technology/ResearchTracker.h>
99

1010
#include <libControls/Button.h>
11+
#include <libControls/ListBox.h>
1112

1213
#include <NAS2D/Math/Point.h>
14+
#include <NAS2D/Math/Rectangle.h>
1315

1416
#include <vector>
1517

@@ -27,29 +29,38 @@ class Structure;
2729
class ResearchReport : public ReportInterface
2830
{
2931
public:
30-
ResearchReport();
32+
ResearchReport();
3133
~ResearchReport() override;
3234

3335
void fillLists() override;
3436
void clearSelected() override;
3537

3638
void refresh() override;
39+
void setSectionRects();
3740
void selectStructure(Structure*) override;
38-
39-
void injectTechReferences(TechnologyCatalog&, ResearchTracker&);
41+
42+
void injectTechReferences(TechnologyCatalog&, ResearchTracker&);
4043

4144
void update() override;
4245

4346
private:
4447
void onResize() override;
4548
void onMouseDown(NAS2D::EventHandler::MouseButton button, NAS2D::Point<int> position) override;
4649

50+
void handleMouseDownInCategories(NAS2D::Point<int>& position);
51+
52+
void adjustCategoryIconSpacing();
53+
54+
void resetCategorySelection();
55+
4756
void draw() const override;
4857
void drawCategories() const;
4958
void drawTopicHeader() const;
5059
void drawVerticalSectionSpacer(const int column) const;
51-
void drawTopicIconPanel() const;
52-
void drawResearchPointsPanel() const;
60+
void drawResearchPointsPanel() const;
61+
62+
void handleCategoryChanged();
63+
void handleTopicChanged();
5364

5465
void untoggleAllButtons();
5566

@@ -59,7 +70,16 @@ class ResearchReport : public ReportInterface
5970
void onStandardLabClicked();
6071
void onHotLabClicked();
6172

73+
private:
74+
struct CategoryPanel
75+
{
76+
NAS2D::Rectangle<int> rect{};
77+
NAS2D::Rectangle<int> imageSlice{};
78+
std::string name{};
79+
bool selected{false};
80+
};
6281

82+
private:
6383
const NAS2D::Font& fontMedium;
6484
const NAS2D::Font& fontMediumBold;
6585
const NAS2D::Font& fontBigBold;
@@ -73,8 +93,16 @@ class ResearchReport : public ReportInterface
7393
Button btnAvailableTopics;
7494
Button btnCompletedTopics;
7595
Button btnStandardLab;
76-
Button btnHotLab;
77-
78-
TechnologyCatalog* mTechCatalog{ nullptr };
79-
ResearchTracker* mResearchTracker{ nullptr };
96+
Button btnHotLab;
97+
98+
ListBox<ListBoxItemText> lstResearchTopics;
99+
100+
TechnologyCatalog* mTechCatalog{nullptr};
101+
ResearchTracker* mResearchTracker{nullptr};
102+
103+
CategoryPanel* mSelectedCategory{nullptr};
104+
std::vector<CategoryPanel> mCategoryPanels;
105+
106+
NAS2D::Rectangle<int> mCategoryIconArea{};
107+
NAS2D::Rectangle<int> mResearchTopicArea{};
80108
};

0 commit comments

Comments
 (0)