diff --git a/client/lobby/OptionsTab.cpp b/client/lobby/OptionsTab.cpp index 99f6851f7..2f1dc5cbb 100644 --- a/client/lobby/OptionsTab.cpp +++ b/client/lobby/OptionsTab.cpp @@ -374,7 +374,7 @@ void OptionsTab::CPlayerOptionTooltipBox::genTownWindow() if(!elem.empty()) components.push_back(std::make_shared(ComponentType::CREATURE, elem.front(), std::nullopt, CComponent::tiny)); } - boxAssociatedCreatures = std::make_shared(components, Rect(10, 140, pos.w - 20, 140)); + boxAssociatedCreatures = std::make_shared(components, Rect(10, 140, pos.w - 20, 140), 20, 10, 22, 4); } void OptionsTab::CPlayerOptionTooltipBox::genHeroWindow() diff --git a/client/widgets/CComponent.cpp b/client/widgets/CComponent.cpp index cff5ec9db..d8e7a7d97 100644 --- a/client/widgets/CComponent.cpp +++ b/client/widgets/CComponent.cpp @@ -427,6 +427,7 @@ void CComponentBox::placeComponents(bool selectable) for(auto & comp : components) { 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)); } diff --git a/client/widgets/CComponent.h b/client/widgets/CComponent.h index f41ea3264..f4d360460 100644 --- a/client/widgets/CComponent.h +++ b/client/widgets/CComponent.h @@ -92,7 +92,7 @@ class CComponentBox : public CIntObject std::shared_ptr selected; std::function onSelect; - static constexpr int defaultBetweenImagesMin = 20; + static constexpr int defaultBetweenImagesMin = 42; static constexpr int defaultBetweenSubtitlesMin = 10; static constexpr int defaultBetweenRows = 22; static constexpr int defaultComponentsInRow = 4; diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index 355e7a744..32b477818 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -374,9 +374,6 @@ void CTextBox::trimToFit() if (slider) return; - if(label->alignment == ETextAlignment::CENTER) - moveBy((pos.dimensions() - label->textSize) / 2); - pos.w = label->textSize.x; pos.h = label->textSize.y; label->pos.w = label->textSize.x; diff --git a/client/windows/CMessage.cpp b/client/windows/CMessage.cpp index 5fc1ac083..a7ade93b5 100644 --- a/client/windows/CMessage.cpp +++ b/client/windows/CMessage.cpp @@ -27,6 +27,7 @@ #include "../widgets/TextControls.h" #include "../windows/InfoWindows.h" +constexpr int RIGHT_CLICK_POPUP_MIN_SIZE = 100; constexpr int BEFORE_COMPONENTS = 30; constexpr int SIDE_MARGIN = 11; constexpr int TOP_MARGIN = 20; @@ -220,6 +221,8 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor play assert(ret && ret->text); + // STEP 1: DETERMINE SIZE OF ALL ELEMENTS + for(const auto & area : textAreaSizes) { ret->text->resize(area); @@ -227,70 +230,83 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor play break; // suitable size found, use it } +// int textWidth = ret->text->pos.w; + int textHeight = ret->text->pos.h; + if(ret->text->slider) 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; - if(ret->buttons.size()) + int buttonsHeight = 0; + if(!ret->buttons.empty()) { - int bh = 0; // Compute total width of buttons buttonsWidth = INTERVAL_BETWEEN_BUTTONS * (ret->buttons.size() - 1); // space between all buttons for(auto & elem : ret->buttons) //and add buttons width { 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 - 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(); + // STEP 2: COMPUTE WINDOW SIZE if(ret->buttons.empty() && !ret->components) { - //improvement for text only right-click popups -> center text - Point distance = ret->pos.topLeft() - ret->text->pos.topLeft() + marginTopLeft; - ret->text->moveBy(distance); + // use more compact form for right-click popup with no buttons / components - ret->pos.h = ret->text->pos.h + TOP_MARGIN + BOTTOM_MARGIN; - ret->pos.w = ret->text->pos.w + 2 * SIDE_MARGIN; + ret->pos.w = std::max(RIGHT_CLICK_POPUP_MIN_SIZE, ret->text->label->textSize.x + 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()) - { - int buttonPosX = ret->pos.w / 2 - buttonsWidth / 2; - int buttonPosY = ret->pos.h - BOTTOM_MARGIN - ret->buttons[0]->pos.h; + // STEP 3: MOVE ALL ELEMENTS IN PLACE - 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)); - buttonPosX += elem->pos.w + INTERVAL_BETWEEN_BUTTONS; + 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) + { + 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->center(); } void CMessage::drawBorder(PlayerColor playerColor, Canvas & to, int w, int h, int x, int y) diff --git a/client/windows/InfoWindows.cpp b/client/windows/InfoWindows.cpp index 19c938bc0..97a3ffa50 100644 --- a/client/windows/InfoWindows.cpp +++ b/client/windows/InfoWindows.cpp @@ -69,7 +69,7 @@ CSelWindow::CSelWindow( const std::string & Text, PlayerColor player, int charpe } if(!comps.empty()) - components = std::make_shared(comps, Rect(0, 0, 600, 300)); + components = std::make_shared(comps, Rect(0,0,0,0)); CMessage::drawIWindow(this, Text, player); } @@ -124,7 +124,7 @@ CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo } if(!comps.empty()) - components = std::make_shared(comps, Rect(0, 0, 600, 300)); + components = std::make_shared(comps, Rect(0,0,0,0)); CMessage::drawIWindow(this, Text, player); }