Skip to content

Commit

Permalink
Implement autoscroll for research tree
Browse files Browse the repository at this point in the history
Allows the user to conveniently scroll the technology tree to the
currently researched technology or the technology goal. A button next
to the corresponding combo box is available to the user for this
purpose.

The icon used for the buttons is based on `crosshair-light` from
Phosphor Icons with minor modifications to let it play nicely with our
theming and to be recognizable on the small button.
  • Loading branch information
blabber committed Sep 18, 2024
1 parent 7a1644c commit 67a946b
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 5 deletions.
94 changes: 89 additions & 5 deletions client/views/view_research.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
#include <QPainter>
#include <QPushButton>
#include <QScrollArea>
#include <QStringLiteral>
#include <QTimer>
#include <QToolButton>
#include <QToolTip>

// common
#include "fc_types.h"
#include "game.h"
#include "government.h"
#include "icons.h"
#include "research.h"

// client
Expand Down Expand Up @@ -107,6 +111,16 @@ void research_diagram::reset()
resize(width, height);
}

/**
Find the center of a node, identified by tech id, and return true
if the node was found; false otherwise. If a node is found, x and y
are filled with the center of the node.
*/
bool research_diagram::get_tech_position(Tech_type_id id, int *x, int *y)
{
return get_position_on_reqtree(req, id, x, y);
}

/**
Mouse handler for research_diagram
*/
Expand Down Expand Up @@ -274,25 +288,47 @@ science_report::science_report() : QWidget()
researching_combo = new QComboBox();
auto sci_layout = new QGridLayout();
res_diag = new research_diagram();
auto scroll = new QScrollArea();
scroll = new QScrollArea();
refresh_but = new QPushButton();
refresh_but->setText(_("Refresh"));
refresh_but->setToolTip(_("Press to refresh currently researched "
"technology calculation again."));
refresh_but->setDisabled(true);

locate_researching_but = new QToolButton();
locate_researching_but->setIcon(
fcIcons::instance()->getIcon(QStringLiteral("crosshair")));
locate_researching_but->setIconSize(
QSize(locate_researching_but->fontInfo().pixelSize(),
locate_researching_but->fontInfo().pixelSize()));
locate_researching_but->setToolTip(
_("Press to locate currently researched "
"technology in tree."));
locate_researching_but->setDisabled(true);

locate_goal_but = new QToolButton();
locate_goal_but->setIcon(
fcIcons::instance()->getIcon(QStringLiteral("crosshair")));
locate_goal_but->setIconSize(
QSize(locate_researching_but->fontInfo().pixelSize(),
locate_researching_but->fontInfo().pixelSize()));
locate_goal_but->setToolTip(_("Press to locate technology goal in tree."));
locate_goal_but->setDisabled(true);

progress->setTextVisible(true);
progress_label->setSizePolicy(size_fixed_policy);
sci_layout->addWidget(progress_label, 0, 0, 1, 8);
sci_layout->addWidget(progress_label, 0, 0, 1, 9);
sci_layout->addWidget(researching_combo, 1, 0, 1, 3);
sci_layout->addWidget(refresh_but, 1, 3, 1, 1);
researching_combo->setSizePolicy(size_fixed_policy);
sci_layout->addWidget(locate_researching_but, 1, 3, 1, 1);
sci_layout->addWidget(refresh_but, 1, 4, 1, 1);
refresh_but->setSizePolicy(size_fixed_policy);
sci_layout->addWidget(progress, 1, 5, 1, 4);
sci_layout->addWidget(progress, 1, 6, 1, 4);
progress->setSizePolicy(size_fixed_policy);
sci_layout->addWidget(goal_combo, 2, 0, 1, 3);
goal_combo->setSizePolicy(size_fixed_policy);
sci_layout->addWidget(info_label, 2, 5, 1, 4);
sci_layout->addWidget(locate_goal_but, 2, 3, 1, 1);
sci_layout->addWidget(info_label, 2, 6, 1, 4);
info_label->setSizePolicy(size_fixed_policy);

size = res_diag->size();
Expand All @@ -310,6 +346,12 @@ science_report::science_report() : QWidget()
QObject::connect(refresh_but, &QAbstractButton::pressed, this,
&science_report::push_research);

QObject::connect(locate_goal_but, &QAbstractButton::pressed, this,
&science_report::locate_goal);

QObject::connect(locate_researching_but, &QAbstractButton::pressed, this,
&science_report::locate_researching);

QObject::connect(goal_combo,
QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&science_report::goal_tech_changed);
Expand Down Expand Up @@ -518,6 +560,10 @@ void science_report::update_report()
refresh_but->setDisabled(false);
}

// Update locate buttons
locate_researching_but->setDisabled(research->researching == A_UNSET);
locate_goal_but->setDisabled(research->tech_goal == A_UNSET);

update_reqtree();
}

Expand All @@ -526,6 +572,17 @@ void science_report::update_report()
*/
void science_report::update_reqtree() { res_diag->update_reqtree(); }

/**
Scroll the science tree to display the technology identified by tech id.
*/
void science_report::scroll_reqtree_to_tech(Tech_type_id id)
{
int x, y;
if (res_diag->get_tech_position(id, &x, &y)) {
scroll->ensureVisible(x, y, scroll->width() / 2, scroll->height() / 2);
}
}

/**
Slot used when combo box with current tech changes
*/
Expand Down Expand Up @@ -570,6 +627,33 @@ void science_report::push_research()
}
}

/**
Locate technology goal in tree and scroll so that it is visible.
*/
void science_report::locate_goal()
{
auto research = research_get(client_player());
if (!research) {
return;
}

scroll_reqtree_to_tech(research->tech_goal);
}

/**
Locate the currently researched technology in tree and scroll so that it
is visible.
*/
void science_report::locate_researching()
{
auto research = research_get(client_player());
if (!research) {
return;
}

scroll_reqtree_to_tech(research->researching);
}

/**
Update the science report.
*/
Expand Down
8 changes: 8 additions & 0 deletions client/views/view_research.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class QPaintEvent;
class QScrollArea;
class progress_bar;
class QPushButton;
class QToolButton;

/****************************************************************************
Custom widget representing research diagram in science_report
Expand All @@ -37,6 +38,7 @@ class research_diagram : public QWidget {
void update_reqtree();
void reset();
QSize size();
bool get_tech_position(Tech_type_id id, int *x, int *y);
private slots:
void show_tooltip();

Expand Down Expand Up @@ -71,9 +73,12 @@ struct qlist_item {
class science_report : public QWidget {
Q_OBJECT

QScrollArea *scroll;
QComboBox *goal_combo;
QComboBox *researching_combo;
QPushButton *refresh_but;
QToolButton *locate_researching_but;
QToolButton *locate_goal_but;
progress_bar *progress;
QLabel *info_label;
QLabel *progress_label;
Expand All @@ -92,11 +97,14 @@ class science_report : public QWidget {
private:
void update_reqtree();
int index{0};
void scroll_reqtree_to_tech(Tech_type_id id);

private slots:
void current_tech_changed(int index);
void goal_tech_changed(int index);
void push_research();
void locate_researching();
void locate_goal();
};

void popdown_science_report();
Expand Down
22 changes: 22 additions & 0 deletions client/views/view_research_reqtree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1183,3 +1183,25 @@ Tech_type_id get_tech_on_reqtree(struct reqtree *tree, int x, int y)
}
return A_NONE;
}

/**
Find the center of a node, identified by tech id in a given reqtree
and return true if the node was found; false otherwise. If a node
is found, x and y are filled with the center of the node in
reqtrees coordinate system.
*/
bool get_position_on_reqtree(struct reqtree *tree, Tech_type_id tech, int *x,
int *y)
{
for (int i = 0; i < tree->num_nodes; i++) {
struct tree_node *node = tree->nodes[i];

if (tech == node->tech) {
*x = node->node_x + node->node_width / 2;
*y = node->node_y + node->node_height / 2;
return true;
}
}

return false;
}
3 changes: 3 additions & 0 deletions client/views/view_research_reqtree.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,6 @@ QList<req_tooltip_help *> *draw_reqtree(struct reqtree *tree,
int w, int h);

Tech_type_id get_tech_on_reqtree(struct reqtree *tree, int x, int y);

bool get_position_on_reqtree(struct reqtree *tree, Tech_type_id tech, int *x,
int *y);
10 changes: 10 additions & 0 deletions data/themes/icons/crosshair.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions data/themes/icons/crosshair.svg.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SPDX-License-Identifier: MIT
SPDX-FileCopyrightText: Copyright (c) 2023 Phosphor Icons
SPDX-FileCopyrightText: 2024 Tobias Rehbein

0 comments on commit 67a946b

Please sign in to comment.