diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index ab69eea..7ea9040 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -26,6 +26,7 @@ SET(HDRS ${CMAKE_CURRENT_SOURCE_DIR}/SchematicChoiceDialog.h ${CMAKE_CURRENT_SOURCE_DIR}/RecipeSelectionDialog.h ${CMAKE_CURRENT_SOURCE_DIR}/RecipeLineRow.h + ${CMAKE_CURRENT_SOURCE_DIR}/OptionButton.h ${CMAKE_CURRENT_SOURCE_DIR}/ItemProducers.h ${CMAKE_CURRENT_SOURCE_DIR}/ItemIconCache.h ${CMAKE_CURRENT_SOURCE_DIR}/BuildingIconCache.h @@ -61,6 +62,7 @@ SET(SRCS ${CMAKE_CURRENT_SOURCE_DIR}/SchematicChoiceDialog.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RecipeSelectionDialog.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RecipeLineRow.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/OptionButton.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ItemProducers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ItemIconCache.cpp ${CMAKE_CURRENT_SOURCE_DIR}/BuildingIconCache.cpp diff --git a/src/ui/OptionButton.cpp b/src/ui/OptionButton.cpp new file mode 100644 index 0000000..aba0991 --- /dev/null +++ b/src/ui/OptionButton.cpp @@ -0,0 +1,35 @@ +#include "OptionButton.h" + +#include +#include +#include + +OptionButton::OptionButton(QWidget* parent) + : QPushButton(parent) +{ +} + +QSize OptionButton::sizeHint() const +{ + if (layout() == nullptr) + { + return QPushButton::sizeHint(); + } + return sizeForFace(layout()->sizeHint()); +} + +QSize OptionButton::minimumSizeHint() const +{ + if (layout() == nullptr) + { + return QPushButton::minimumSizeHint(); + } + return sizeForFace(layout()->minimumSize()); +} + +QSize OptionButton::sizeForFace(const QSize& faceSize) const +{ + QStyleOptionButton option; + initStyleOption(&option); + return style()->sizeFromContents(QStyle::CT_PushButton, &option, faceSize, this); +} diff --git a/src/ui/OptionButton.h b/src/ui/OptionButton.h new file mode 100644 index 0000000..2127a67 --- /dev/null +++ b/src/ui/OptionButton.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +// A push button whose face is built of widgets rather than of a caption: an option's +// name over the recipe line stating what it makes (REQ-UI-SELECT-OPTIONS), or a module's +// name over what it costs (REQ-MOD-UI-DIALOG). +// +// It exists only to be measured correctly. QPushButton computes its size hint from its +// text and icon and ignores a layout set on it, so a button carrying a face of widgets +// would be sized as if it were empty and clip everything in it. This asks the layout +// instead, and then lets the style add what the button's own frame needs. +class OptionButton : public QPushButton +{ + Q_OBJECT + +public: + explicit OptionButton(QWidget* parent = nullptr); + + QSize sizeHint() const override; + QSize minimumSizeHint() const override; + +private: + // The style's button size for the given face size, or the plain QPushButton hint + // when there is no face to measure. + QSize sizeForFace(const QSize& faceSize) const; +}; diff --git a/src/ui/RecipeSelectionDialog.cpp b/src/ui/RecipeSelectionDialog.cpp index c7189b4..9c996fa 100644 --- a/src/ui/RecipeSelectionDialog.cpp +++ b/src/ui/RecipeSelectionDialog.cpp @@ -13,6 +13,7 @@ #include "BuildingType.h" #include "DisplayName.h" #include "GameConfig.h" +#include "OptionButton.h" #include "RecipesConfig.h" #include "ShipsConfig.h" #include "Simulation.h" @@ -138,7 +139,9 @@ RecipeSelectionDialog::RecipeSelectionDialog( { const RecipeSelectionOption& option = options[static_cast(i)]; - QPushButton* button = new QPushButton(list); + // An OptionButton so the face of widgets below is what sizes the button + // (REQ-UI-SELECT-OPTIONS). + OptionButton* button = new OptionButton(list); if (option.line.isEmpty()) { // The "(None)" option makes nothing and is a caption alone diff --git a/src/ui/ShipLayoutDialog.cpp b/src/ui/ShipLayoutDialog.cpp index 9dc1ac8..7653ee1 100644 --- a/src/ui/ShipLayoutDialog.cpp +++ b/src/ui/ShipLayoutDialog.cpp @@ -5,6 +5,7 @@ #include #include "DisplayName.h" +#include "OptionButton.h" #include "ProductionRules.h" #include "RecipeLineRow.h" #include "SectionBox.h" @@ -520,7 +521,7 @@ ShipLayoutDialog::ShipLayoutDialog(const GameConfig* config, // The module's name and glyph over what it costs -- its materials and the // production time it adds (REQ-MOD-UI-DIALOG). Both children are transparent to // the mouse so a click anywhere on the face still reaches the button. - QPushButton* btn = new QPushButton(this); + OptionButton* btn = new OptionButton(this); btn->setCheckable(true); QVBoxLayout* face = new QVBoxLayout(btn);