17 #include <QTextCharFormat>
53 const QPixmap *
icon =
nullptr;
62 void add_icon(
const QPixmap *icon,
const QMargins &margins = QMargins());
63 void add_text(
const QString &text,
const QTextCharFormat &format,
64 bool shadow =
true,
const QMargins &margins = QMargins());
72 void paint(QPainter &p,
const QPointF &top_left)
const;
100 m_blocks.back().base_size = icon->size();
108 const QTextCharFormat &format,
bool shadow,
109 const QMargins &margins)
118 QFontMetricsF
metrics(format.font());
126 m_blocks.back().base_size += QSizeF(1, 1);
128 m_blocks.back().margins.setBottom(margins.bottom() + 1);
140 blk.margins.left() + blk.base_size.width() + blk.margins.right();
170 return blk.mode == block::SPACER_MODE;
172 double spacer = empty_width / std::max(num_spacers, 1L);
193 double ascent = 0, descent = 0,
height = 0;
207 double baseline = (
height + ascent - descent) / 2;
229 auto rect = blk.draw_rect.translated(top_left);
232 if (blk.format.background() != Qt::transparent) {
234 auto fill_rect = rect.marginsAdded(blk.margins);
235 fill_rect.setY(top_left.y());
236 fill_rect.setHeight(
height());
237 p.fillRect(fill_rect, blk.format.background());
239 p.setFont(blk.format.font());
243 p.drawText(rect.translated(1, 1), blk.text);
245 p.setPen(QPen(blk.format.foreground(), 1));
246 p.drawText(rect, blk.text);
249 p.drawPixmap(rect, *blk.icon, blk.icon->rect());
264 return {
N_(
"Simple"),
N_(
"Traditional"),
N_(
"Polished")};
274 if (vector.isEmpty()) {
276 vector <<
_(qUtf8Printable(
name));
309 if (
name == QStringLiteral(
"Simple")) {
310 s_current = std::make_unique<simple_citybar_painter>();
312 }
else if (
name == QStringLiteral(
"Traditional")) {
313 s_current = std::make_unique<traditional_citybar_painter>();
315 }
else if (
name == QStringLiteral(
"Polished")) {
316 s_current = std::make_unique<polished_citybar_painter>();
319 qCCritical(bugs_category,
320 "Could not instantiate known city bar style %s",
321 qUtf8Printable(
name));
323 qCCritical(bugs_category,
"Unknown city bar style %s",
324 qUtf8Printable(
name));
328 s_current = std::make_unique<polished_citybar_painter>();
335 const QPointF &position,
336 const city *pcity)
const
346 const bool can_see_inside =
349 char name[512], growth[32];
350 color_std growth_color, production_color;
352 sizeof(growth), &growth_color,
356 QTextCharFormat format;
370 static const QString en_space = QStringLiteral(
" ");
389 char trade_routes[32];
390 color_std trade_routes_color;
392 pcity, trade_routes,
sizeof(trade_routes), &trade_routes_color);
397 first.
add_text(en_space + trade_routes, format);
417 double width = std::max(first_width, second_width);
422 first.
paint(painter, position - QPointF(first_width / 2, 0));
423 second.
paint(painter,
424 position + QPointF(-second_width / 2, first.
height()));
426 return QRect(position.x() - width / 2, position.y(), width,
435 const QPointF &position,
436 const city *pcity)
const
445 const bool can_see_inside =
447 const bool should_draw_productions =
449 const bool should_draw_growth =
451 const bool should_draw_trade_routes =
453 const bool should_draw_lower_bar = should_draw_productions
454 || should_draw_growth
455 || should_draw_trade_routes;
468 char name[512], growth[32];
469 color_std growth_color, production_color;
471 sizeof(growth), &growth_color,
473 const QMargins text_margins(3, 0, 3, 0);
477 QTextCharFormat format;
489 unsigned long count = unit_list_size(pcity->
tile->
units);
492 static_cast<unsigned long>(citybar->
occupancy.size() - 1));
495 if (pcity->
client.occupied) {
503 format.setForeground(
get_color(t, COLOR_MAPVIEW_CITYTEXT));
510 format.setBackground(owner_color);
514 QColor textcolors[2] = {
get_color(t, COLOR_MAPVIEW_CITYTEXT),
515 get_color(t, COLOR_MAPVIEW_CITYTEXT_DARK)};
520 false, text_margins);
522 format.setBackground(Qt::transparent);
526 if (should_draw_lower_bar) {
530 if (should_draw_productions) {
538 format.setForeground(
get_color(t, production_color));
539 second.
add_text(prod, format,
false, text_margins);
545 if (should_draw_growth) {
550 format.setForeground(
get_color(t, growth_color));
551 second.
add_text(growth, format,
false, text_margins);
554 if (should_draw_trade_routes) {
559 char trade_routes[32];
560 color_std trade_routes_color;
562 pcity, trade_routes,
sizeof(trade_routes), &trade_routes_color);
564 format.setForeground(
get_color(t, trade_routes_color));
565 second.
add_text(trade_routes, format,
false, text_margins);
576 double x = std::floor(position.x() - width / 2 - 1);
577 double y = std::floor(position.y());
579 int num_lines = (should_draw_lower_bar ? 2 : 1);
581 QRectF(x, y, width + 2, first.
height() + num_lines + second.
height());
584 painter.drawTiledPixmap(bounds, *citybar->
background);
585 painter.setPen(owner_color);
586 painter.drawRect(bounds);
588 painter.drawLine(bounds.topLeft() + QPointF(0, first.
height() + 1),
589 bounds.topRight() + QPointF(0, first.
height() + 1));
593 first.
paint(painter, QPointF(x + 1, y + 1));
594 second.
paint(painter, QPointF(x + 1, y + 1 + num_lines + first.
height()));
596 return QRect(x, y, x + width + 2, bounds.height());
604 const QPointF &position,
605 const city *pcity)
const
612 const bool can_see_inside =
614 const bool should_draw_productions =
616 const bool should_draw_growth =
618 const bool should_draw_trade_routes =
627 char name[512], growth[32];
628 color_std growth_color, production_color;
630 sizeof(growth), &growth_color,
635 QColor textcolors[2] = {
get_color(t, COLOR_MAPVIEW_CITYTEXT),
636 get_color(t, COLOR_MAPVIEW_CITYTEXT_DARK)};
645 double target_height = citybar->
occupancy[0]->height();
646 target_height = std::max(target_height,
648 target_height = std::max(target_height,
654 QMargins text_margins(3, 0, 3, 0);
655 QTextCharFormat format;
659 format.setForeground(text_color);
660 line.
add_text(QString::number(pcity->
size), format,
false, text_margins);
663 std::unique_ptr<QPixmap> growth_progress;
664 if (should_draw_growth) {
666 growth_progress = std::make_unique<QPixmap>(
667 QSize(6, target_height) * painter.device()->devicePixelRatio());
668 growth_progress->setDevicePixelRatio(
669 painter.device()->devicePixelRatio());
670 growth_progress->fill(Qt::black);
672 QPainter p(growth_progress.get());
677 double next_turn = qBound(
681 next_turn *= target_height;
685 p.fillRect(QRectF(0, target_height, 6, -next_turn),
686 QColor(200, 200, 60));
690 p.fillRect(QRectF(0, target_height, 6, -
current), QColor(70, 120, 50));
694 p.fillRect(QRectF(0, target_height -
current, 6,
current - next_turn),
699 line.
add_icon(growth_progress.get());
703 format.setFontPointSize(format.fontPointSize() / 1.5);
704 format.setForeground(
get_color(t, growth_color));
705 line.
add_text(growth, format,
false, text_margins);
709 std::unique_ptr<QPixmap> scaled_flag;
711 scaled_flag = std::make_unique<QPixmap>(
713 target_height, Qt::SmoothTransformation));
719 unsigned long count = unit_list_size(pcity->
tile->
units);
722 static_cast<unsigned long>(citybar->
occupancy.size() - 1));
725 if (pcity->
client.occupied) {
735 format.setForeground(text_color);
740 std::unique_ptr<QPixmap> production_pix;
741 std::unique_ptr<QPixmap> production_progress;
742 if (should_draw_productions) {
745 format.setFontPointSize(format.fontPointSize() / 1.5);
746 format.setForeground(
get_color(t, production_color));
748 QMargins prod_margins = text_margins;
749 prod_margins.setLeft(0);
754 line.
add_text(QString::number(turns), format,
false, text_margins);
756 line.
add_text(QStringLiteral(
"∞"), format,
false, text_margins);
760 production_progress = std::make_unique<QPixmap>(
761 QSize(6, target_height) * painter.device()->devicePixelRatio());
762 production_progress->setDevicePixelRatio(
763 painter.device()->devicePixelRatio());
765 QPainter p(production_progress.get());
769 production_progress->fill(Qt::red);
771 production_progress->fill(Qt::black);
779 next_turn *= target_height;
783 p.fillRect(QRectF(0, target_height, 6, -next_turn),
784 QColor(200, 200, 60));
788 p.fillRect(QRectF(0, target_height, 6, -
current), Qt::blue);
792 p.fillRect(QRectF(0, target_height -
current, 6,
current - next_turn),
797 line.
add_icon(production_progress.get());
800 const QPixmap *xsprite =
nullptr;
802 if (can_see_inside && (VUT_UTYPE == target.kind)) {
805 }
else if (can_see_inside && (target.kind == VUT_IMPROVEMENT)) {
809 production_pix = std::make_unique<QPixmap>(
810 xsprite->scaledToHeight(target_height, Qt::SmoothTransformation));
811 line.
add_icon(production_pix.get());
818 double width = std::ceil(line.
size().width());
819 double height = line.
height() + 2;
820 double x = std::floor(position.x() - width / 2 - 1);
821 double y = std::floor(position.y());
825 painter.setPen(QPen(Qt::black, 1));
826 painter.setBrush(QColor(0, 0, 0, 100));
828 owner_color.setAlpha(90);
829 painter.setPen(QPen(owner_color, 1));
830 painter.setBrush(QBrush(owner_color));
832 painter.drawRoundedRect(QRectF(x, y, width + 2, height - 1), 7, 7);
835 line.
paint(painter, QPointF(x + 1, y + 1));
838 if (should_draw_trade_routes) {
845 char trade_routes[32];
846 color_std trade_routes_color;
848 &trade_routes_color);
851 format.setForeground(
get_color(t, trade_routes_color));
852 trade_line.
add_text(trade_routes, format,
false, text_margins);
857 double trade_width = std::ceil(trade_line.
size().width());
858 double trade_x = std::floor(position.x() - trade_width / 2 - 1);
859 double trade_y = y + height;
863 painter.setPen(QPen(Qt::black, 1));
864 painter.setBrush(QColor(0, 0, 0, 100));
866 owner_color.setAlpha(90);
867 painter.setPen(QPen(owner_color, 1));
868 painter.setBrush(QBrush(owner_color));
870 painter.drawRoundedRect(QRectF(trade_x, y + line.
height() + 2,
871 trade_width + 2, trade_line.
height() + 1),
875 trade_line.
paint(painter, QPointF(trade_x + 1, trade_y + 1));
877 x = std::min(x, trade_x);
878 width = std::max(width, trade_width);
879 height += trade_line.
height() + 2;
882 return QRect(x, y, std::ceil(width + 2), std::ceil(height));
QFont get_font(client_font font)
Returns given font.
int city_granary_size(int city_size)
Generalized formula used to calculate granary size.
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Calculates the turns which are needed to build the requested production in the city.
citizens city_size_get(const struct city *pcity)
Get the city size.
Abstraction for city bars of various styles.
static void option_changed(option *opt)
Called by the option code when the option has changed.
static const QVector< QString > * available_vector(const option *)
Returns the list of all available city bar styles.
static void set_current(const QString &name)
Sets the current city bar style.
static QStringList available()
Returns the list of all available city bar styles.
static std::unique_ptr< citybar_painter > s_current
Pointer to the city bar painter currently in use.
static citybar_painter * current()
Returns the current painter (never null).
Helper class to create a line of text.
void paint(QPainter &p, const QPointF &top_left) const
Paints the line at the given position.
double ideal_width() const
Returns the ideal line width (the sum of the width of all blocks)
void add_text(const QString &text, const QTextCharFormat &format, bool shadow=true, const QMargins &margins=QMargins())
Adds text to the line with the given format.
void set_text_shadow_brush(const QBrush &brush)
void add_icon(const QPixmap *icon, const QMargins &margins=QMargins())
Adds an icon to the line.
void do_layout(double width=0)
Lays out the line to fill the given width.
std::vector< block > m_blocks
void add_spacer()
Adds a spacer to the line.
QRect paint(QPainter &painter, const QPointF &position, const city *pcity) const override
Draws the "polished" city bar.
QRect paint(QPainter &painter, const QPointF &position, const city *pcity) const override
Draws a simple city bar.
QRect paint(QPainter &painter, const QPointF &position, const city *pcity) const override
Draws the traditional city bar with a dark background, two lines of text and colored borders.
bool client_is_global_observer()
Returns whether client is global observer.
struct player * client_player()
Either controlling or observing.
QColor color_best_contrast(const QColor &subject, const QColor *candidates, int ncandidates)
Find the colour from 'candidates' with the best perceptual contrast from 'subject'.
QColor get_color(const struct tileset *t, enum color_std stdcolor)
Return a pointer to the given "standard" color.
QColor get_player_color(const struct tileset *t, const struct player *pplayer)
Return the color of the player.
Constants used when drawing the button.
const char * option_str_get(const struct option *poption)
Returns the current value of this string option.
client_options * gui_options
bool can_player_see_units_in_city(const struct player *pplayer, const struct city *pcity)
Return TRUE iff the player can see units in the city.
int universal_build_shield_cost(const struct city *pcity, const struct universal *target)
Return the number of shields it takes to build this universal.
struct city::@15::@18 client
struct universal production
std::vector< QPixmap * > occupancy
bool draw_city_productions
bool draw_city_trade_routes
char default_city_bar_style_name[512]
enum line_of_text::block::@118 mode
The base class for options.
const QPixmap * get_city_flag_sprite(const struct tileset *t, const struct city *pcity)
Return the flag graphic to be used by the city.
const struct citybar_sprites * get_citybar_sprites(const struct tileset *t)
Return all the sprites used for city bar drawing.
const QPixmap * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum direction8 facing, const QColor &replace)
Return the sprite for the unit type (the base "unit" sprite).
struct tileset * get_tileset()
Returns the tileset.
const QPixmap * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Return the sprite for the building/improvement.
void get_city_mapview_production(const city *pcity, char *buffer, size_t buffer_len)
Find the mapview city production text for the given city, and place it into the buffer.
void get_city_mapview_name_and_growth(const city *pcity, char *name_buffer, size_t name_buffer_len, char *growth_buffer, size_t growth_buffer_len, enum color_std *growth_color, enum color_std *production_color)
Fill the two buffers which information about the city which is shown below it.
void get_city_mapview_trade_routes(const city *pcity, char *trade_routes_buffer, size_t trade_routes_buffer_len, enum color_std *pcolor)
Find the mapview city trade routes text for the given city, and place it into the buffer.
void update_map_canvas_visible()
Schedules an update of (only) the visible part of the map at the next unqueue_mapview_update().