1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

Fixes for positioning on popups with components

This commit is contained in:
Ivan Savenko
2024-02-26 23:26:06 +02:00
parent 93b3cb3af5
commit 99cb1df91d
6 changed files with 60 additions and 46 deletions

View File

@@ -374,7 +374,7 @@ void OptionsTab::CPlayerOptionTooltipBox::genTownWindow()
if(!elem.empty()) if(!elem.empty())
components.push_back(std::make_shared<CComponent>(ComponentType::CREATURE, elem.front(), std::nullopt, CComponent::tiny)); components.push_back(std::make_shared<CComponent>(ComponentType::CREATURE, elem.front(), std::nullopt, CComponent::tiny));
} }
boxAssociatedCreatures = std::make_shared<CComponentBox>(components, Rect(10, 140, pos.w - 20, 140)); boxAssociatedCreatures = std::make_shared<CComponentBox>(components, Rect(10, 140, pos.w - 20, 140), 20, 10, 22, 4);
} }
void OptionsTab::CPlayerOptionTooltipBox::genHeroWindow() void OptionsTab::CPlayerOptionTooltipBox::genHeroWindow()

View File

@@ -427,6 +427,7 @@ void CComponentBox::placeComponents(bool selectable)
for(auto & comp : components) for(auto & comp : components)
{ {
addChild(comp.get()); addChild(comp.get());
comp->recActions = defActions; //FIXME: for some reason, received component might have recActions set to 0
comp->moveTo(Point(pos.x, pos.y)); comp->moveTo(Point(pos.x, pos.y));
} }

View File

@@ -92,7 +92,7 @@ class CComponentBox : public CIntObject
std::shared_ptr<CSelectableComponent> selected; std::shared_ptr<CSelectableComponent> selected;
std::function<void(int newID)> onSelect; std::function<void(int newID)> onSelect;
static constexpr int defaultBetweenImagesMin = 20; static constexpr int defaultBetweenImagesMin = 42;
static constexpr int defaultBetweenSubtitlesMin = 10; static constexpr int defaultBetweenSubtitlesMin = 10;
static constexpr int defaultBetweenRows = 22; static constexpr int defaultBetweenRows = 22;
static constexpr int defaultComponentsInRow = 4; static constexpr int defaultComponentsInRow = 4;

View File

@@ -374,9 +374,6 @@ void CTextBox::trimToFit()
if (slider) if (slider)
return; return;
if(label->alignment == ETextAlignment::CENTER)
moveBy((pos.dimensions() - label->textSize) / 2);
pos.w = label->textSize.x; pos.w = label->textSize.x;
pos.h = label->textSize.y; pos.h = label->textSize.y;
label->pos.w = label->textSize.x; label->pos.w = label->textSize.x;

View File

@@ -27,6 +27,7 @@
#include "../widgets/TextControls.h" #include "../widgets/TextControls.h"
#include "../windows/InfoWindows.h" #include "../windows/InfoWindows.h"
constexpr int RIGHT_CLICK_POPUP_MIN_SIZE = 100;
constexpr int BEFORE_COMPONENTS = 30; constexpr int BEFORE_COMPONENTS = 30;
constexpr int SIDE_MARGIN = 11; constexpr int SIDE_MARGIN = 11;
constexpr int TOP_MARGIN = 20; constexpr int TOP_MARGIN = 20;
@@ -220,6 +221,8 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor play
assert(ret && ret->text); assert(ret && ret->text);
// STEP 1: DETERMINE SIZE OF ALL ELEMENTS
for(const auto & area : textAreaSizes) for(const auto & area : textAreaSizes)
{ {
ret->text->resize(area); ret->text->resize(area);
@@ -227,70 +230,83 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor play
break; // suitable size found, use it break; // suitable size found, use it
} }
// int textWidth = ret->text->pos.w;
int textHeight = ret->text->pos.h;
if(ret->text->slider) if(ret->text->slider)
ret->text->slider->addUsedEvents(CIntObject::WHEEL | CIntObject::KEYBOARD); ret->text->slider->addUsedEvents(CIntObject::WHEEL | CIntObject::KEYBOARD);
Point winSize(ret->text->pos.w, ret->text->pos.h); //start with text size
if(ret->components)
winSize.y += 10 + ret->components->pos.h; //space to first component
int buttonsWidth = 0; int buttonsWidth = 0;
if(ret->buttons.size()) int buttonsHeight = 0;
if(!ret->buttons.empty())
{ {
int bh = 0;
// Compute total width of buttons // Compute total width of buttons
buttonsWidth = INTERVAL_BETWEEN_BUTTONS * (ret->buttons.size() - 1); // space between all buttons buttonsWidth = INTERVAL_BETWEEN_BUTTONS * (ret->buttons.size() - 1); // space between all buttons
for(auto & elem : ret->buttons) //and add buttons width for(auto & elem : ret->buttons) //and add buttons width
{ {
buttonsWidth += elem->pos.w; buttonsWidth += elem->pos.w;
vstd::amax(bh, elem->pos.h); vstd::amax(buttonsHeight, elem->pos.h);
} }
winSize.y += INTERVAL_BETWEEN_TEXT_AND_BUTTONS + bh; //before button + button
} }
// Clip window size // STEP 2: COMPUTE WINDOW SIZE
if(ret->components)
vstd::amax(winSize.x, ret->components->pos.w);
vstd::amax(winSize.x, buttonsWidth);
vstd::amin(winSize.x, GH.screenDimensions().x);
vstd::amin(winSize.y, GH.screenDimensions().y);
ret->pos.h = winSize.y + TOP_MARGIN + BOTTOM_MARGIN;
ret->pos.w = winSize.x + 2 * SIDE_MARGIN;
ret->center();
Point marginTopLeft(SIDE_MARGIN, TOP_MARGIN);
ret->text->moveBy(marginTopLeft);
ret->text->trimToFit();
if(ret->buttons.empty() && !ret->components) if(ret->buttons.empty() && !ret->components)
{ {
//improvement for text only right-click popups -> center text // use more compact form for right-click popup with no buttons / components
Point distance = ret->pos.topLeft() - ret->text->pos.topLeft() + marginTopLeft;
ret->text->moveBy(distance);
ret->pos.h = ret->text->pos.h + TOP_MARGIN + BOTTOM_MARGIN; ret->pos.w = std::max(RIGHT_CLICK_POPUP_MIN_SIZE, ret->text->label->textSize.x + 2 * SIDE_MARGIN);
ret->pos.w = ret->text->pos.w + 2 * SIDE_MARGIN; ret->pos.h = std::max(RIGHT_CLICK_POPUP_MIN_SIZE, ret->text->label->textSize.y + TOP_MARGIN + BOTTOM_MARGIN);
}
else
{
int windowContentWidth = ret->text->pos.w;
int windowContentHeight = ret->text->pos.h;
if(ret->components)
{
vstd::amax(windowContentWidth, ret->components->pos.w);
windowContentHeight += INTERVAL_BETWEEN_TEXT_AND_BUTTONS + ret->components->pos.h;
}
if(!ret->buttons.empty())
{
vstd::amax(windowContentWidth, buttonsWidth);
windowContentHeight += INTERVAL_BETWEEN_TEXT_AND_BUTTONS + buttonsHeight;
}
ret->pos.w = windowContentWidth + 2 * SIDE_MARGIN;
ret->pos.h = windowContentHeight + TOP_MARGIN + BOTTOM_MARGIN;
} }
if(!ret->buttons.empty()) // STEP 3: MOVE ALL ELEMENTS IN PLACE
{
int buttonPosX = ret->pos.w / 2 - buttonsWidth / 2;
int buttonPosY = ret->pos.h - BOTTOM_MARGIN - ret->buttons[0]->pos.h;
for(auto & elem : ret->buttons) if(ret->buttons.empty() && !ret->components)
{
ret->text->trimToFit();
ret->text->center(ret->pos.center());
}
else
{
if(ret->components)
ret->components->moveBy(Point((ret->pos.w - ret->components->pos.w) / 2, TOP_MARGIN + ret->text->pos.h + INTERVAL_BETWEEN_TEXT_AND_BUTTONS));
ret->text->trimToFit();
ret->text->moveBy(Point((ret->pos.w - ret->text->pos.w) / 2, TOP_MARGIN + (textHeight - ret->text->pos.h) / 2 ));
if(!ret->buttons.empty())
{ {
elem->moveBy(Point(buttonPosX, buttonPosY)); int buttonPosX = ret->pos.w / 2 - buttonsWidth / 2;
buttonPosX += elem->pos.w + INTERVAL_BETWEEN_BUTTONS; int buttonPosY = ret->pos.h - BOTTOM_MARGIN - ret->buttons[0]->pos.h;
for(auto & elem : ret->buttons)
{
elem->moveBy(Point(buttonPosX, buttonPosY));
buttonPosX += elem->pos.w + INTERVAL_BETWEEN_BUTTONS;
}
} }
} }
if(ret->components)
ret->components->moveBy(Point(ret->pos.x, ret->pos.y));
ret->backgroundTexture->pos = ret->pos; ret->backgroundTexture->pos = ret->pos;
ret->center();
} }
void CMessage::drawBorder(PlayerColor playerColor, Canvas & to, int w, int h, int x, int y) void CMessage::drawBorder(PlayerColor playerColor, Canvas & to, int w, int h, int x, int y)

View File

@@ -69,7 +69,7 @@ CSelWindow::CSelWindow( const std::string & Text, PlayerColor player, int charpe
} }
if(!comps.empty()) if(!comps.empty())
components = std::make_shared<CComponentBox>(comps, Rect(0, 0, 600, 300)); components = std::make_shared<CComponentBox>(comps, Rect(0,0,0,0));
CMessage::drawIWindow(this, Text, player); CMessage::drawIWindow(this, Text, player);
} }
@@ -124,7 +124,7 @@ CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo
} }
if(!comps.empty()) if(!comps.empty())
components = std::make_shared<CComponentBox>(comps, Rect(0, 0, 600, 300)); components = std::make_shared<CComponentBox>(comps, Rect(0,0,0,0));
CMessage::drawIWindow(this, Text, player); CMessage::drawIWindow(this, Text, player);
} }