diff --git a/client/AdventureMapClasses.cpp b/client/AdventureMapClasses.cpp index 6f1aa8a10..b3fd46252 100644 --- a/client/AdventureMapClasses.cpp +++ b/client/AdventureMapClasses.cpp @@ -71,7 +71,7 @@ void CList::CListItem::clickLeft(tribool down, bool previousState) void CList::CListItem::hover(bool on) { if (on) - GH.statusbar->print(getHoverText()); + GH.statusbar->setText(getHoverText()); else GH.statusbar->clear(); } @@ -561,7 +561,7 @@ void CMinimap::clickRight(tribool down, bool previousState) void CMinimap::hover(bool on) { if (on) - GH.statusbar->print(CGI->generaltexth->zelp[291].first); + GH.statusbar->setText(CGI->generaltexth->zelp[291].first); else GH.statusbar->clear(); } @@ -872,7 +872,7 @@ void CInfoBar::clickRight(tribool down, bool previousState) void CInfoBar::hover(bool on) { if (on) - GH.statusbar->print(CGI->generaltexth->zelp[292].first); + GH.statusbar->setText(CGI->generaltexth->zelp[292].first); else GH.statusbar->clear(); } diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index 6ed998b4b..f48e630ed 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -1231,13 +1231,13 @@ void CAdvMapInt::tileHovered(const int3 &mapPos) { std::string text = objAtTile->getHoverText(); boost::replace_all(text,"\n"," "); - statusbar.print(text); + statusbar.setText(text); } else { std::string hlp; CGI->mh->getTerrainDescr(mapPos, hlp, false); - statusbar.print(hlp); + statusbar.setText(hlp); } const CGPathNode *pnode = LOCPLINT->cb->getPathInfo(mapPos); diff --git a/client/CCastleInterface.cpp b/client/CCastleInterface.cpp index 7b094a61c..f3c8069be 100644 --- a/client/CCastleInterface.cpp +++ b/client/CCastleInterface.cpp @@ -247,7 +247,7 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent) || (*parent->selectedBuilding)<(*this)) //or we are on top { parent->selectedBuilding = this; - GH.statusbar->print(getSubtitle()); + GH.statusbar->setText(getSubtitle()); } } } @@ -335,7 +335,7 @@ void CHeroGSlot::hover (bool on) } } if(temp.size()) - GH.statusbar->print(temp); + GH.statusbar->setText(temp); } void CHeroGSlot::clickLeft(tribool down, bool previousState) @@ -961,7 +961,7 @@ void CCastleInterface::recreateIcons() size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->modh->settings.MAX_BUILDING_PER_TURN]; icon->setFrame(iconIndex); - income->setTxt(boost::lexical_cast(town->dailyIncome())); + income->setText(boost::lexical_cast(town->dailyIncome())); hall = new CTownInfo( 80, 413, town, true); fort = new CTownInfo(122, 413, town, false); @@ -1031,7 +1031,7 @@ void CCreaInfo::update() value = boost::lexical_cast(town->creatureGrowth(level)); if (value != label->text) - label->setTxt(value); + label->setText(value); } } @@ -1042,9 +1042,9 @@ void CCreaInfo::hover(bool on) if(on) { - GH.statusbar->print(message); + GH.statusbar->setText(message); } - else if (message == GH.statusbar->getCurrent()) + else if (message == GH.statusbar->getText()) GH.statusbar->clear(); } @@ -1122,7 +1122,7 @@ void CTownInfo::hover(bool on) if(on) { if ( building ) - GH.statusbar->print(building->Name()); + GH.statusbar->setText(building->Name()); } else GH.statusbar->clear(); @@ -1244,7 +1244,7 @@ void CHallInterface::CBuildingBox::hover(bool on) else toPrint = CGI->generaltexth->hcommands[state]; boost::algorithm::replace_first(toPrint,"%s",building->Name()); - GH.statusbar->print(toPrint); + GH.statusbar->setText(toPrint); } else GH.statusbar->clear(); @@ -1508,7 +1508,7 @@ void LabeledValue::init(std::string nameText, std::string descr, int min, int ma void LabeledValue::hover(bool on) { if(on) - GH.statusbar->print(hoverText); + GH.statusbar->setText(hoverText); else { GH.statusbar->clear(); @@ -1570,7 +1570,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance * void CFortScreen::RecruitArea::hover(bool on) { if(on) - GH.statusbar->print(hoverText); + GH.statusbar->setText(hoverText); else GH.statusbar->clear(); } @@ -1581,7 +1581,7 @@ void CFortScreen::RecruitArea::creaturesChanged() { std::string availableText = CGI->generaltexth->allTexts[217] + boost::lexical_cast(town->creatures[level].first); - availableCount->setTxt(availableText); + availableCount->setText(availableText); } } @@ -1659,7 +1659,7 @@ void CMageGuildScreen::Scroll::clickRight(tribool down, bool previousState) void CMageGuildScreen::Scroll::hover(bool on) { if(on) - GH.statusbar->print(spell->name); + GH.statusbar->setText(spell->name); else GH.statusbar->clear(); diff --git a/client/CKingdomInterface.cpp b/client/CKingdomInterface.cpp index db81530fa..e14eb2e59 100644 --- a/client/CKingdomInterface.cpp +++ b/client/CKingdomInterface.cpp @@ -812,7 +812,7 @@ void CTownItem::update() { std::string incomeVal = boost::lexical_cast(town->dailyIncome()); if (incomeVal != income->text) - income->setTxt(incomeVal); + income->setText(incomeVal); heroes->update(); diff --git a/client/CMT.cpp b/client/CMT.cpp index a9931e3e0..7e6380c0d 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -443,7 +443,7 @@ void printInfoAboutIntObject(const CIntObject *obj, int level) sbuffer << "inactive"; sbuffer << " at " << obj->pos.x <<"x"<< obj->pos.y; sbuffer << " (" << obj->pos.w <<"x"<< obj->pos.h << ")"; - logGlobal->debugStream() << sbuffer.str(); + logGlobal->infoStream() << sbuffer.str(); for(const CIntObject *child : obj->children) printInfoAboutIntObject(child, level+1); diff --git a/client/CMessage.cpp b/client/CMessage.cpp index ba90fa8a1..66373ff96 100644 --- a/client/CMessage.cpp +++ b/client/CMessage.cpp @@ -232,11 +232,17 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor play && ret->text->slider; i++) { - ret->text->setBounds(sizes[i][0], sizes[i][1]); + ret->text->resize(Point(sizes[i][0], sizes[i][1])); } if(ret->text->slider) + { ret->text->slider->addUsedEvents(CIntObject::WHEEL | CIntObject::KEYBOARD); + } + else + { + ret->text->resize(ret->text->label->textSize + Point(10, 10)); + } std::pair winSize(ret->text->pos.w, ret->text->pos.h); //start with text size diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 819e24563..1570c9504 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -408,7 +408,7 @@ CreditsScreen::CreditsScreen() size_t firstQuote = text.find('\"')+1; text = text.substr(firstQuote, text.find('\"', firstQuote) - firstQuote ); credits = new CTextBox(text, Rect(pos.w - 350, 600, 350, 32000), 0, FONT_CREDITS, CENTER, Colors::WHITE); - credits->pos.h = credits->maxH; + credits->pos.h = credits->label->textSize.y; } void CreditsScreen::showAll(SDL_Surface * to) @@ -1291,7 +1291,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const std::functionsetTxt("NEWGAME"); + txt->setText("NEWGAME"); } else { @@ -1353,7 +1353,7 @@ void SelectionTab::select( int position ) { std::string filename = *CResourceHandler::get()->getResourceName( ResourceID(curItems[py]->fileURI, EResType::CLIENT_SAVEGAME)); - txt->setTxt(CFileInfo(filename).getBaseName()); + txt->setText(CFileInfo(filename).getBaseName()); } onSelect(curItems[py]); @@ -1901,7 +1901,7 @@ CChatBox::CChatBox(const Rect &rect) inputBox->removeUsedEvents(KEYBOARD); chatHistory = new CTextBox("", Rect(0, 0, rect.w, rect.h - height), 1); - chatHistory->color = Colors::GREEN; + chatHistory->label->color = Colors::GREEN; } void CChatBox::keyPressed(const SDL_KeyboardEvent & key) @@ -1909,7 +1909,7 @@ void CChatBox::keyPressed(const SDL_KeyboardEvent & key) if(key.keysym.sym == SDLK_RETURN && key.state == SDL_PRESSED && inputBox->text.size()) { SEL->postChatMessage(inputBox->text); - inputBox->setTxt(""); + inputBox->setText(""); } else inputBox->keyPressed(key); @@ -1917,7 +1917,7 @@ void CChatBox::keyPressed(const SDL_KeyboardEvent & key) void CChatBox::addNewMessage(const std::string &text) { - chatHistory->setTxt(chatHistory->text + text + "\n"); + chatHistory->setText(chatHistory->label->text + text + "\n"); if(chatHistory->slider) chatHistory->slider->moveToMax(); } @@ -1964,8 +1964,6 @@ InfoCard::InfoCard( bool Network ) if(SEL->screenType != CMenuScreen::newGame) difficulty->block(true); - //description needs bg - mapDescription->addChild(new CPicture(*bg, descriptionRect), true); //move subpicture bg to our description control (by default it's our (Infocard) child) if(network) { @@ -2152,9 +2150,9 @@ void InfoCard::changeSelection( const CMapInfo *to ) if(to && mapDescription) { if (SEL->screenType == CMenuScreen::campaignList) - mapDescription->setTxt(to->campaignHeader->description); + mapDescription->setText(to->campaignHeader->description); else - mapDescription->setTxt(to->mapHeader->description); + mapDescription->setText(to->mapHeader->description); if(SEL->screenType != CMenuScreen::newGame && SEL->screenType != CMenuScreen::campaignList) { difficulty->block(true); @@ -2926,7 +2924,7 @@ OptionsTab::SelectedBox::SelectedBox(Point position, PlayerSettings & settings, void OptionsTab::SelectedBox::update() { image->setFrame(getImageIndex()); - subtitle->setTxt(getName()); + subtitle->setText(getName()); } void OptionsTab::SelectedBox::clickRight( tribool down, bool previousState ) @@ -3048,7 +3046,7 @@ CMultiMode::CMultiMode() bar = new CGStatusBar(new CPicture(Rect(7, 465, 440, 18), 0));//226, 472 txt = new CTextInput(Rect(19, 436, 334, 16), *bg); - txt->setTxt(settings["general"]["playerName"].String()); //Player + txt->setText(settings["general"]["playerName"].String()); //Player btns[0] = new CAdventureMapButton(CGI->generaltexth->zelp[266], boost::bind(&CMultiMode::openHotseat, this), 373, 78, "MUBHOT.DEF"); btns[1] = new CAdventureMapButton("Host TCP/IP game", "", boost::bind(&CMultiMode::hostTCP, this), 373, 78 + 57*1, "MUBHOST.DEF"); @@ -3097,7 +3095,7 @@ CHotSeatPlayers::CHotSeatPlayers(const std::string &firstPlayer) cancel = new CAdventureMapButton(CGI->generaltexth->zelp[561], boost::bind(&CGuiHandler::popIntTotally, boost::ref(GH), this), 205, 338, "MUBCANC.DEF", SDLK_ESCAPE); bar = new CGStatusBar(new CPicture(Rect(7, 381, 348, 18), 0));//226, 472 - txt[0]->setTxt(firstPlayer, true); + txt[0]->setText(firstPlayer, true); txt[0]->giveFocus(); } @@ -3331,7 +3329,7 @@ void CBonusSelection::selectMap( int whichOne, bool initialSelect ) sInfo.turnTime = 0; sInfo.difficulty = ourCampaign->camp->scenarios[whichOne].difficulty; - mapDesc->setTxt(ourHeader->description); + mapDesc->setText(ourHeader->description); updateBonusSelection(); } @@ -3602,13 +3600,9 @@ void CBonusSelection::startMap() if (scenario.prolog.hasPrologEpilog) { GH.pushInt(new CPrologEpilogVideo(scenario.prolog, exitCb)); - logGlobal->infoStream() << "Video: " << scenario.prolog.prologVideo; - logGlobal->infoStream() << "Audio: " << scenario.prolog.prologMusic; - logGlobal->infoStream() << "Text: " << scenario.prolog.prologText; } else { - logGlobal->infoStream() << "Without prolog"; exitCb(); } } @@ -3991,9 +3985,9 @@ void CCampaignScreen::CCampaignButton::clickLeft(tribool down, bool previousStat void CCampaignScreen::CCampaignButton::hover(bool on) { if (on) - hoverLabel->setTxt(hoverText); // Shows the name of the campaign when you get into the bounds of the button + hoverLabel->setText(hoverText); // Shows the name of the campaign when you get into the bounds of the button else - hoverLabel->setTxt(" "); + hoverLabel->setText(" "); } void CCampaignScreen::CCampaignButton::show(SDL_Surface * to) @@ -4111,7 +4105,6 @@ CPrologEpilogVideo::CPrologEpilogVideo( CCampaignScenario::SScenarioPrologEpilog txt = CSDL_Ext::newSurface(500, 20 * lines.size() + 10); curTxtH = screen->h; graphics->fonts[FONT_BIG]->renderTextLinesCenter(txt, lines, Colors::METALLIC_GOLD, Point(txt->w/2, txt->h/2 + 5)); - //SDL_SaveBMP(txt, "txtsrfc.bmp"); } void CPrologEpilogVideo::show( SDL_Surface * to ) @@ -4160,8 +4153,8 @@ CSimpleJoinScreen::CSimpleJoinScreen() cancel = new CAdventureMapButton(CGI->generaltexth->zelp[561], boost::bind(&CGuiHandler::popIntTotally, boost::ref(GH), this), 142, 142, "MUBCANC.DEF", SDLK_ESCAPE); bar = new CGStatusBar(new CPicture(Rect(7, 186, 218, 18), 0)); - port->setTxt(boost::lexical_cast(settings["server"]["port"].Float()), true); - address->setTxt(settings["server"]["server"].String(), true); + port->setText(boost::lexical_cast(settings["server"]["port"].Float()), true); + address->setText(settings["server"]["server"].String(), true); address->giveFocus(); } diff --git a/client/CQuestLog.cpp b/client/CQuestLog.cpp index 1bca4d732..cc14cca49 100644 --- a/client/CQuestLog.cpp +++ b/client/CQuestLog.cpp @@ -43,7 +43,7 @@ void CQuestLabel::clickLeft(tribool down, bool previousState) void CQuestLabel::showAll(SDL_Surface * to) { if (active) - CBoundedLabel::showAll (to); + CMultiLineLabel::showAll (to); } CQuestIcon::CQuestIcon (const std::string &defname, int index, int x, int y) : @@ -144,7 +144,7 @@ void CQuestLog::init() text.addReplacement (quests[i].obj->getHoverText()); //get name of the object CQuestLabel * label = new CQuestLabel (28, 199 + i * 24, FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString()); label->callback = boost::bind(&CQuestLog::selectQuest, this, i); - label->setBounds (172, 30); + label->setVisibleSize (Rect(0, 0, 172, 30)); labels.push_back(label); } @@ -192,7 +192,7 @@ void CQuestLog::selectQuest (int which) MetaString text; std::vector components; //TODO: display them currentQuest->quest->getVisitText (text, components , currentQuest->quest->isCustomFirst, true); - description->setTxt (text.toString()); //TODO: use special log entry text + description->setText (text.toString()); //TODO: use special log entry text redraw(); } diff --git a/client/CQuestLog.h b/client/CQuestLog.h index 0400a964d..ef662cf93 100644 --- a/client/CQuestLog.h +++ b/client/CQuestLog.h @@ -33,13 +33,13 @@ extern CAdvMapInt *adventureInt; const int QUEST_COUNT = 9; -class CQuestLabel : public LRClickableAreaWText, public CBoundedLabel +class CQuestLabel : public LRClickableAreaWText, public CMultiLineLabel { public: std::function callback; CQuestLabel (int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "") - : CBoundedLabel (x, y, FONT_SMALL, TOPLEFT, Colors::WHITE, Text){}; + : CMultiLineLabel (x, y, FONT_SMALL, TOPLEFT, Colors::WHITE, Text){}; void clickLeft(tribool down, bool previousState); void showAll(SDL_Surface * to); }; diff --git a/client/CSpellWindow.cpp b/client/CSpellWindow.cpp index 1cf5dee29..4ee290e75 100644 --- a/client/CSpellWindow.cpp +++ b/client/CSpellWindow.cpp @@ -159,29 +159,29 @@ CSpellWindow::CSpellWindow(const SDL_Rect &, const CGHeroInstance * _myHero, CPl statusBar = new CGStatusBar(7 + pos.x, 569 + pos.y, "Spelroll.bmp"); SDL_Rect temp_rect = genRect(45, 35, 479 + pos.x, 405 + pos.y); - exitBtn = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fexitb, this), CGI->generaltexth->zelp[460].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[460].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + exitBtn = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fexitb, this), CGI->generaltexth->zelp[460].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[460].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(45, 35, 221 + pos.x, 405 + pos.y); - battleSpells = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fbattleSpellsb, this), CGI->generaltexth->zelp[453].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[453].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + battleSpells = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fbattleSpellsb, this), CGI->generaltexth->zelp[453].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[453].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(45, 35, 355 + pos.x, 405 + pos.y); - adventureSpells = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fadvSpellsb, this), CGI->generaltexth->zelp[452].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[452].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + adventureSpells = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fadvSpellsb, this), CGI->generaltexth->zelp[452].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[452].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(45, 35, 418 + pos.x, 405 + pos.y); - manaPoints = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fmanaPtsb, this), CGI->generaltexth->zelp[459].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[459].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + manaPoints = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fmanaPtsb, this), CGI->generaltexth->zelp[459].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[459].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(36, 56, 549 + pos.x, 94 + pos.y); - selectSpellsA = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 0), CGI->generaltexth->zelp[454].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[454].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + selectSpellsA = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 0), CGI->generaltexth->zelp[454].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[454].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(36, 56, 549 + pos.x, 151 + pos.y); - selectSpellsE = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 3), CGI->generaltexth->zelp[457].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[457].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + selectSpellsE = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 3), CGI->generaltexth->zelp[457].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[457].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(36, 56, 549 + pos.x, 210 + pos.y); - selectSpellsF = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 1), CGI->generaltexth->zelp[455].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[455].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + selectSpellsF = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 1), CGI->generaltexth->zelp[455].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[455].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(36, 56, 549 + pos.x, 270 + pos.y); - selectSpellsW = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 2), CGI->generaltexth->zelp[456].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[456].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + selectSpellsW = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 2), CGI->generaltexth->zelp[456].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[456].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(36, 56, 549 + pos.x, 330 + pos.y); - selectSpellsAll = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 4), CGI->generaltexth->zelp[458].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[458].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + selectSpellsAll = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::selectSchool, this, 4), CGI->generaltexth->zelp[458].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[458].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(leftCorner->h, leftCorner->w, 97 + pos.x, 77 + pos.y); - lCorner = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fLcornerb, this), CGI->generaltexth->zelp[450].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[450].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + lCorner = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fLcornerb, this), CGI->generaltexth->zelp[450].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[450].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); temp_rect = genRect(rightCorner->h, rightCorner->w, 487 + pos.x, 72 + pos.y); - rCorner = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fRcornerb, this), CGI->generaltexth->zelp[451].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[451].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); + rCorner = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fRcornerb, this), CGI->generaltexth->zelp[451].second, boost::bind(&CGStatusBar::setText, statusBar, (CGI->generaltexth->zelp[451].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt); //areas for spells int xpos = 117 + pos.x, ypos = 90 + pos.y; @@ -813,7 +813,7 @@ void CSpellWindow::SpellArea::hover(bool on) { std::ostringstream ss; ss<spellh->spells[mySpell]->name<<" ("<generaltexth->allTexts[171+CGI->spellh->spells[mySpell]->level]<<")"; - owner->statusBar->print(ss.str()); + owner->statusBar->setText(ss.str()); } else { diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 3cd97554a..e51dfacfc 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -282,7 +282,7 @@ void CGarrisonSlot::hover (bool on) temp = CGI->generaltexth->tcommands[11]; //Empty } } - GH.statusbar->print(temp); + GH.statusbar->setText(temp); } else { @@ -464,7 +464,7 @@ void CGarrisonSlot::update() creatureImage->setFrame(creature->iconIndex); stackCount->enable(); - stackCount->setTxt(boost::lexical_cast(myStack->count)); + stackCount->setText(boost::lexical_cast(myStack->count)); } else { @@ -510,7 +510,7 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, int if (!creature) stackCount->disable(); else - stackCount->setTxt(boost::lexical_cast(myStack->count)); + stackCount->setText(boost::lexical_cast(myStack->count)); } void CGarrisonInt::addSplitBtn(CAdventureMapButton * button) @@ -667,8 +667,7 @@ CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); if(!text->slider) { - text->pos.w = text->maxW; - text->pos.h = text->maxH; + text->resize(text->label->textSize); } if(buttons.size()) @@ -1397,7 +1396,7 @@ void CRecruitmentWindow::CCostBox::set(TResources res) //just update values for(auto & item : resources) { - item.second.first->setTxt(boost::lexical_cast(res[item.first])); + item.second.first->setText(boost::lexical_cast(res[item.first])); } } @@ -1469,7 +1468,7 @@ void CRecruitmentWindow::select(CCreatureCard *card) totalCostValue->set(card->creature->cost * maxAmount); //Recruit %s - title->setTxt(boost::str(boost::format(CGI->generaltexth->tcommands[21]) % card->creature->namePl)); + title->setText(boost::str(boost::format(CGI->generaltexth->tcommands[21]) % card->creature->namePl)); maxButton->block(maxAmount == 0); slider->block(maxAmount == 0); @@ -1626,8 +1625,8 @@ void CRecruitmentWindow::sliderMoved(int to) return; buyButton->block(!to); - availableValue->setTxt(boost::lexical_cast(selected->amount - to)); - toRecruitValue->setTxt(boost::lexical_cast(to)); + availableValue->setText(boost::lexical_cast(selected->amount - to)); + toRecruitValue->setText(boost::lexical_cast(to)); totalCostValue->set(selected->creature->cost * to); } @@ -1660,8 +1659,8 @@ CSplitWindow::CSplitWindow(const CCreature * creature, std::functionfilters.add(boost::bind(&CTextInput::numberFilter, _1, _2, leftMin, leftMax)); rightInput->filters.add(boost::bind(&CTextInput::numberFilter, _1, _2, rightMin, rightMax)); - leftInput->setTxt(boost::lexical_cast(leftAmount), false); - rightInput->setTxt(boost::lexical_cast(rightAmount), false); + leftInput->setText(boost::lexical_cast(leftAmount), false); + rightInput->setText(boost::lexical_cast(rightAmount), false); animLeft = new CCreaturePic(20, 54, creature, true, false); animRight = new CCreaturePic(177, 54,creature, true, false); @@ -1691,8 +1690,8 @@ void CSplitWindow::setAmount(int value, bool left) leftAmount = left ? value : total - value; rightAmount = left ? total - value : value; - leftInput->setTxt(boost::lexical_cast(leftAmount)); - rightInput->setTxt(boost::lexical_cast(rightAmount)); + leftInput->setText(boost::lexical_cast(leftAmount)); + rightInput->setText(boost::lexical_cast(rightAmount)); } void CSplitWindow::apply() @@ -2157,13 +2156,13 @@ void CTradeWindow::CTradeableItem::hover(bool on) { case CREATURE: case CREATURE_PLACEHOLDER: - GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->creatures[id]->namePl)); + GH.statusbar->setText(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->creatures[id]->namePl)); break; case ARTIFACT_PLACEHOLDER: if(id < 0) - GH.statusbar->print(CGI->generaltexth->zelp[582].first); + GH.statusbar->setText(CGI->generaltexth->zelp[582].first); else - GH.statusbar->print(CGI->arth->artifacts[id]->Name()); + GH.statusbar->setText(CGI->arth->artifacts[id]->Name()); break; } } @@ -2964,27 +2963,27 @@ void CMarketplaceWindow::updateTraderText() if(mode == EMarketMode::RESOURCE_PLAYER) { //I can give %s to the %s player. - traderText->setTxt(boost::str(boost::format(CGI->generaltexth->allTexts[165]) % hLeft->getName() % hRight->getName())); + traderText->setText(boost::str(boost::format(CGI->generaltexth->allTexts[165]) % hLeft->getName() % hRight->getName())); } else if(mode == EMarketMode::RESOURCE_ARTIFACT) { //I can offer you the %s for %d %s of %s. - traderText->setTxt(boost::str(boost::format(CGI->generaltexth->allTexts[267]) % hRight->getName() % r1 % CGI->generaltexth->allTexts[160 + (r1==1)] % hLeft->getName())); + traderText->setText(boost::str(boost::format(CGI->generaltexth->allTexts[267]) % hRight->getName() % r1 % CGI->generaltexth->allTexts[160 + (r1==1)] % hLeft->getName())); } else if(mode == EMarketMode::RESOURCE_RESOURCE) { //I can offer you %d %s of %s for %d %s of %s. - traderText->setTxt(boost::str(boost::format(CGI->generaltexth->allTexts[157]) % r2 % CGI->generaltexth->allTexts[160 + (r2==1)] % hRight->getName() % r1 % CGI->generaltexth->allTexts[160 + (r1==1)] % hLeft->getName())); + traderText->setText(boost::str(boost::format(CGI->generaltexth->allTexts[157]) % r2 % CGI->generaltexth->allTexts[160 + (r2==1)] % hRight->getName() % r1 % CGI->generaltexth->allTexts[160 + (r1==1)] % hLeft->getName())); } else if(mode == EMarketMode::CREATURE_RESOURCE) { //I can offer you %d %s of %s for %d %s. - traderText->setTxt(boost::str(boost::format(CGI->generaltexth->allTexts[269]) % r2 % CGI->generaltexth->allTexts[160 + (r2==1)] % hRight->getName() % r1 % hLeft->getName(r1))); + traderText->setText(boost::str(boost::format(CGI->generaltexth->allTexts[269]) % r2 % CGI->generaltexth->allTexts[160 + (r2==1)] % hRight->getName() % r1 % hLeft->getName(r1))); } else if(mode == EMarketMode::ARTIFACT_RESOURCE) { //I can offer you %d %s of %s for your %s. - traderText->setTxt(boost::str(boost::format(CGI->generaltexth->allTexts[268]) % r2 % CGI->generaltexth->allTexts[160 + (r2==1)] % hRight->getName() % hLeft->getName(r1))); + traderText->setText(boost::str(boost::format(CGI->generaltexth->allTexts[268]) % r2 % CGI->generaltexth->allTexts[160 + (r2==1)] % hRight->getName() % hLeft->getName(r1))); } return; } @@ -3004,7 +3003,7 @@ void CMarketplaceWindow::updateTraderText() else gnrtxtnr = 163; //Please inspect our fine wares. If you feel like offering a trade, click on the items you wish to trade with and for. } - traderText->setTxt(CGI->generaltexth->allTexts[gnrtxtnr]); + traderText->setText(CGI->generaltexth->allTexts[gnrtxtnr]); } CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*= nullptr*/, EMarketMode::EMarketMode Mode) @@ -3297,12 +3296,12 @@ void CAltarWindow::calcTotalExp() } } val = hero->calculateXp(val); - expOnAltar->setTxt(boost::lexical_cast(val)); + expOnAltar->setText(boost::lexical_cast(val)); } void CAltarWindow::setExpToLevel() { - expToLevel->setTxt(boost::lexical_cast(CGI->heroh->reqExp(CGI->heroh->level(hero->exp)+1) - hero->exp)); + expToLevel->setText(boost::lexical_cast(CGI->heroh->reqExp(CGI->heroh->level(hero->exp)+1) - hero->exp)); } void CAltarWindow::blockTrade() @@ -3609,7 +3608,7 @@ void CSystemOptionsWindow::setGameRes(int index) resText += boost::lexical_cast(iter->first.first); resText += "x"; resText += boost::lexical_cast(iter->first.second); - gameResLabel->setTxt(resText); + gameResLabel->setText(resText); } void CSystemOptionsWindow::toggleReminder(bool on) @@ -3814,7 +3813,7 @@ void CTavernWindow::HeroPortrait::hover( bool on ) { //Hoverable::hover(on); if(on) - GH.statusbar->print(hoverName); + GH.statusbar->setText(hoverName); else GH.statusbar->clear(); } @@ -3977,12 +3976,11 @@ void CInGameConsole::startEnteringText() enteredText = "_"; if(GH.topInt() == adventureInt) { - GH.statusbar->alignment = TOPLEFT; - GH.statusbar->calcOffset(); - GH.statusbar->print(enteredText); + GH.statusbar->alignment = TOPLEFT; + GH.statusbar->setText(enteredText); - //Prevent changes to the text from mouse interaction with the adventure map - GH.statusbar->lock(true); + //Prevent changes to the text from mouse interaction with the adventure map + GH.statusbar->lock(true); } else if(LOCPLINT->battleInt) { @@ -4003,10 +4001,9 @@ void CInGameConsole::endEnteringText(bool printEnteredText) enteredText = ""; if(GH.topInt() == adventureInt) { - GH.statusbar->alignment = CENTER; - GH.statusbar->calcOffset(); - GH.statusbar->lock(false); - GH.statusbar->clear(); + GH.statusbar->alignment = CENTER; + GH.statusbar->lock(false); + GH.statusbar->clear(); } else if(LOCPLINT->battleInt) { @@ -4018,10 +4015,10 @@ void CInGameConsole::refreshEnteredText() { if(GH.topInt() == adventureInt) { - GH.statusbar->lock(false); - GH.statusbar->clear(); - GH.statusbar->print(enteredText); - GH.statusbar->lock(true); + GH.statusbar->lock(false); + GH.statusbar->clear(); + GH.statusbar->setText(enteredText); + GH.statusbar->lock(true); } else if(LOCPLINT->battleInt) { @@ -4521,7 +4518,7 @@ void CHeroArea::clickRight(tribool down, bool previousState) void CHeroArea::hover(bool on) { if (on && hero) - GH.statusbar->print(hero->hoverName); + GH.statusbar->setText(hero->hoverName); else GH.statusbar->clear(); } @@ -5438,7 +5435,7 @@ void CUniversityWindow::CItem::clickRight(tribool down, bool previousState) void CUniversityWindow::CItem::hover(bool on) { if (on) - GH.statusbar->print(CGI->generaltexth->skillName[ID]); + GH.statusbar->setText(CGI->generaltexth->skillName[ID]); else GH.statusbar->clear(); } diff --git a/client/gui/CIntObjectClasses.cpp b/client/gui/CIntObjectClasses.cpp index 2edf1d0c4..3451a8341 100644 --- a/client/gui/CIntObjectClasses.cpp +++ b/client/gui/CIntObjectClasses.cpp @@ -376,8 +376,8 @@ void CAdventureMapButton::hover (bool on) else if(GH.statusbar) //for other buttons { if (on) - GH.statusbar->print(*name); - else if ( GH.statusbar->getCurrent()==(*name) ) + GH.statusbar->setText(*name); + else if ( GH.statusbar->getText()==(*name) ) GH.statusbar->clear(); } } @@ -725,8 +725,12 @@ CSlider::~CSlider() } -CSlider::CSlider(int x, int y, int totalw, std::function Moved, int Capacity, int Amount, int Value, bool Horizontal, int style) -:capacity(Capacity),amount(Amount),horizontal(Horizontal), moved(Moved) +CSlider::CSlider(int x, int y, int totalw, std::function Moved, int Capacity, int Amount, int Value, bool Horizontal, int style): + capacity(Capacity), + amount(Amount), + scrollStep(1), + horizontal(Horizontal), + moved(Moved) { OBJ_CONSTRUCTION_CAPTURING_ALL; setAmount(amount); @@ -827,7 +831,7 @@ void CSlider::showAll(SDL_Surface * to) void CSlider::wheelScrolled(bool down, bool in) { - moveTo(value + 3 * (down ? +1 : -1)); + moveTo(value + 3 * (down ? +scrollStep : -scrollStep)); } void CSlider::keyPressed(const SDL_KeyboardEvent & key) @@ -839,17 +843,17 @@ void CSlider::keyPressed(const SDL_KeyboardEvent & key) { case SDLK_UP: case SDLK_LEFT: - moveDest = value - 1; + moveDest = value - scrollStep; break; case SDLK_DOWN: case SDLK_RIGHT: - moveDest = value + 1; + moveDest = value + scrollStep; break; case SDLK_PAGEUP: - moveDest = value - capacity + 1; + moveDest = value - capacity + scrollStep; break; case SDLK_PAGEDOWN: - moveDest = value + capacity - 1; + moveDest = value + capacity - scrollStep; break; case SDLK_HOME: moveDest = 0; @@ -1104,8 +1108,8 @@ CSimpleWindow::~CSimpleWindow() void CHoverableArea::hover (bool on) { if (on) - GH.statusbar->print(hoverText); - else if (GH.statusbar->getCurrent()==hoverText) + GH.statusbar->setText(hoverText); + else if (GH.statusbar->getText()==hoverText) GH.statusbar->clear(); } @@ -1156,24 +1160,20 @@ void CLabel::showAll(SDL_Surface * to) { CIntObject::showAll(to); - std::string toPrint = visibleText(); - if(!toPrint.length()) - return; - - //blitLine(to, pos.topLeft()/2 + pos.bottomRight()/2, toPrint); - blitLine(to, pos.topLeft() + textOffset, toPrint); + if(!text.empty()) + blitLine(to, pos, text); } CLabel::CLabel(int x, int y, EFonts Font /*= FONT_SMALL*/, EAlignment Align, const SDL_Color &Color /*= Colors::WHITE*/, const std::string &Text /*= ""*/) :CTextContainer(Align, Font, Color), text(Text) { + type |= REDRAW_PARENT; autoRedraw = true; pos.x += x; pos.y += y; pos.w = pos.h = 0; bg = nullptr; - ignoreLeadingWhitespace = false; if (alignment == TOPLEFT) // causes issues for MIDDLE { @@ -1182,15 +1182,17 @@ CLabel::CLabel(int x, int y, EFonts Font /*= FONT_SMALL*/, EAlignment Align, con } } -std::string CLabel::visibleText() +Point CLabel::getBorderSize() { - std::string ret = text; - if(ignoreLeadingWhitespace) - boost::trim_left(ret); - return ret; + return Point(0, 0); } -void CLabel::setTxt(const std::string &Txt) +std::string CLabel::getText() +{ + return text; +} + +void CLabel::setText(const std::string &Txt) { text = Txt; if(autoRedraw) @@ -1202,33 +1204,60 @@ void CLabel::setTxt(const std::string &Txt) } } -void CBoundedLabel::setBounds(int limitW, int limitH) +CMultiLineLabel::CMultiLineLabel(int x, int y, EFonts Font, EAlignment Align, const SDL_Color &Color, const std::string &Text): + CLabel(x, y, Font, Align, Color, Text), + visibleSize(0, 0, 0, 0) { - pos.h = limitH; - pos.w = limitW; - recalculateLines(text); + splitText(Text); } -void CBoundedLabel::setTxt(const std::string &Txt) +void CMultiLineLabel::setVisibleSize(Rect visibleSize) { - recalculateLines(Txt); - CLabel::setTxt(Txt); + this->visibleSize = visibleSize; + redraw(); } -void CTextContainer::blitLine(SDL_Surface *to, Point where, std::string what) +void CMultiLineLabel::scrollTextBy(int distance) +{ + scrollTextTo(visibleSize.y + distance); +} + +void CMultiLineLabel::scrollTextTo(int distance) +{ + Rect size = visibleSize; + size.y = distance; + setVisibleSize(size); +} + +void CMultiLineLabel::setText(const std::string &Txt) +{ + splitText(Txt); + CLabel::setText(Txt); +} + +void CTextContainer::blitLine(SDL_Surface *to, Rect destRect, std::string what) { const IFont * f = graphics->fonts[font]; + Point where = destRect.topLeft(); + + // input is rect in which given text should be placed + // calculate proper position for top-left corner of the text + if (alignment == TOPLEFT) + { + where.x += getBorderSize().x; + where.y += getBorderSize().y; + } if (alignment == CENTER) { - where.x -= f->getStringWidth(what) / 2; - where.y -= f->getLineHeight() / 2; + where.x += (destRect.w - f->getStringWidth(what)) / 2; + where.y += (destRect.h - f->getLineHeight()) / 2; } if (alignment == BOTTOMRIGHT) { - where.x -= f->getStringWidth(what); - where.y -= f->getLineHeight(); + where.x += getBorderSize().x + destRect.w - f->getStringWidth(what); + where.y += getBorderSize().y + destRect.h - f->getLineHeight(); } size_t begin = 0; @@ -1245,11 +1274,11 @@ void CTextContainer::blitLine(SDL_Surface *to, Point where, std::string what) if (currDelimeter % 2) // Enclosed in {} text - set to yellow f->renderTextLeft(to, toPrint, Colors::YELLOW, where); - else // Non-enclosed text + else // Non-enclosed text, use default color f->renderTextLeft(to, toPrint, color, where); begin = end; - where.x += f->getStringWidth(toPrint); + destRect.x += f->getStringWidth(toPrint); } currDelimeter++; } @@ -1262,36 +1291,33 @@ CTextContainer::CTextContainer(EAlignment alignment, EFonts font, SDL_Color colo color(color) {} -void CBoundedLabel::showAll(SDL_Surface * to) +void CMultiLineLabel::showAll(SDL_Surface * to) { CIntObject::showAll(to); const IFont * f = graphics->fonts[font]; - int lineHeight = f->getLineHeight(); - int lineCapacity = pos.h / lineHeight; - int dy = f->getLineHeight(); //line height - int base_y = pos.y; - if(alignment == CENTER) - base_y += std::max((pos.h - maxH)/2,0); + // calculate which lines should be visible + size_t totalLines = lines.size(); + size_t beginLine = visibleSize.y / f->getLineHeight(); + size_t endLine = (getTextLocation().h + visibleSize.y) / f->getLineHeight() + 1; - for (int i = 0; i < lineCapacity; i++) + // and where they should be displayed + Point lineStart = getTextLocation().topLeft() - visibleSize + Point(0, beginLine * f->getLineHeight()); + Point lineSize = Point(getTextLocation().w, f->getLineHeight()); + + CSDL_Ext::CClipRectGuard guard(to, getTextLocation()); // to properly trim text that is too big to fit + + for (size_t i = beginLine; i < std::min(totalLines, endLine); i++) { - const std::string &line = lines[i]; - if ( !(lines.size() && line.size())) //empty message or empty line - continue; + if (!lines[i].empty()) //non-empty line + blitLine(to, Rect(lineStart, lineSize), lines[i]); - int x = pos.x; - if(alignment == CENTER) - { - x += pos.w - f->getStringWidth(line.c_str()) / 2; - } - - blitLine(to, Point(x, base_y + i * dy), line); + lineStart.y += f->getLineHeight(); } } -void CBoundedLabel::recalculateLines(const std::string &Txt) +void CMultiLineLabel::splitText(const std::string &Txt) { lines.clear(); @@ -1300,10 +1326,32 @@ void CBoundedLabel::recalculateLines(const std::string &Txt) lines = CMessage::breakText(Txt, pos.w, font); - maxH = lineHeight * lines.size(); - maxW = 0; + textSize.y = lineHeight * lines.size(); + textSize.x = 0; for(const std::string &line : lines) - vstd::amax(maxW, f->getStringWidth(line.c_str())); + vstd::amax( textSize.x, f->getStringWidth(line.c_str())); + redraw(); +} + +Rect CMultiLineLabel::getTextLocation() +{ + // this method is needed for vertical alignment alignment of text + // when height of available text is smaller than height of widget + // in this case - we should add proper offset to display text at required position + if (pos.h <= textSize.y) + return pos; + + Point textSize(pos.w, graphics->fonts[font]->getLineHeight() * lines.size()); + Point textOffset(pos.w - textSize.x, pos.h - textSize.y); + + switch(alignment) + { + case TOPLEFT: return Rect(pos.topLeft(), textSize); + case CENTER: return Rect(pos.topLeft() + textOffset / 2, textSize); + case BOTTOMRIGHT: return Rect(pos.topLeft() + textOffset, textSize); + } + assert(0); + return Rect(); } CLabelGroup::CLabelGroup(EFonts Font, EAlignment Align, const SDL_Color &Color): @@ -1316,104 +1364,72 @@ void CLabelGroup::add(int x, int y, const std::string &text) new CLabel(x, y, font, align, color, text); } -CTextBox::CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font /*= FONT_SMALL*/, EAlignment Align /*= TOPLEFT*/, const SDL_Color &Color /*= Colors::WHITE*/) -:CBoundedLabel(rect.x, rect.y, Font, Align, Color, Text), sliderStyle(SliderStyle), slider(nullptr) +CTextBox::CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font /*= FONT_SMALL*/, EAlignment Align /*= TOPLEFT*/, const SDL_Color &Color /*= Colors::WHITE*/): + sliderStyle(SliderStyle), + slider(nullptr) { + OBJ_CONSTRUCTION_CAPTURING_ALL; + label = new CMultiLineLabel(rect.x, rect.y, Font, Align, Color); + type |= REDRAW_PARENT; - autoRedraw = false; - pos.h = rect.h; - pos.w = rect.w; - assert(Align == TOPLEFT || Align == CENTER); //TODO: support for other alignments + label->pos.h = pos.h = rect.h; + label->pos.w = pos.w = rect.w; + assert(pos.w >= 40); //we need some space - setTxt(Text); -} - -void CTextBox::recalculateLines(const std::string &Txt) -{ - //TODO: merge with CBoundedlabel::recalculateLines - - vstd::clear_pointer(slider); - lines.clear(); - const IFont * f = graphics->fonts[font]; - int lineHeight = f->getLineHeight(); - int lineCapacity = pos.h / lineHeight; - - lines = CMessage::breakText(Txt, pos.w, font); - if (lines.size() > lineCapacity) //we need to add a slider - { - lines = CMessage::breakText(Txt, pos.w - 32 - 10, font); - OBJ_CONSTRUCTION_CAPTURING_ALL; - slider = new CSlider(pos.w - 32, 0, pos.h, boost::bind(&CTextBox::sliderMoved, this, _1), lineCapacity, lines.size(), 0, false, sliderStyle); - if(active) - slider->activate(); - } - - maxH = lineHeight * lines.size(); - maxW = 0; - for(const std::string &line : lines) - vstd::amax(maxW, f->getStringWidth(line)); -} - -void CTextBox::showAll(SDL_Surface * to) -{ - CIntObject::showAll(to); - - const IFont * f = graphics->fonts[font]; - int dy = f->getLineHeight(); //line height - int base_y = pos.y; - - if (alignment == CENTER) - base_y += std::max((pos.h - maxH)/2,0); - - int howManyLinesToPrint = slider ? slider->capacity : lines.size(); - int firstLineToPrint = slider ? slider->value : 0; - - for (int i = 0; i < howManyLinesToPrint; i++) - { - const std::string &line = lines[i + firstLineToPrint]; - if(!line.size()) continue; - - int width = pos.w + (slider ? (slider->pos.w) : 0); - int x = pos.x + int(alignment) * width / 2; - - blitLine(to, Point(x, base_y + i * dy), line); - } - + setText(Text); } void CTextBox::sliderMoved(int to) { - if(!slider) - return; - - redraw(); + label->scrollTextTo(to); } -const Point CGStatusBar::edgeOffset = Point(5, 1); - -void CGStatusBar::print(const std::string & Text) +void CTextBox::resize(Point newSize) { - if(!textLock) - setTxt(Text); + pos.w = newSize.x; + pos.h = newSize.y; + label->pos.w = pos.w; + label->pos.h = pos.h; + if (slider) + vstd::clear_pointer(slider); // will be recreated if needed later + + setText(label->getText()); // force refresh +} + +void CTextBox::setText(const std::string &text) +{ + label->setText(text); + if (label->textSize.y <= label->pos.h && slider) + { + // slider is no longer needed + vstd::clear_pointer(slider); + label->pos.w = pos.w; + label->setText(text); + } + else if (label->textSize.y > label->pos.h && !slider) + { + // create slider and update widget + label->pos.w = pos.w - 32; + label->setText(text); + + OBJ_CONSTRUCTION_CAPTURING_ALL; + slider = new CSlider(pos.w - 32, 0, pos.h, boost::bind(&CTextBox::sliderMoved, this, _1), + label->pos.h, label->textSize.y, 0, false, sliderStyle); + slider->scrollStep = graphics->fonts[label->font]->getLineHeight(); + } +} + +void CGStatusBar::setText(const std::string & Text) +{ + if(!textLock) + CLabel::setText(Text); } void CGStatusBar::clear() { - if(!textLock) - setTxt(""); + setText(""); } -std::string CGStatusBar::getCurrent() -{ - return text; -} - -//CGStatusBar::CGStatusBar(int x, int y, EFonts Font /*= FONT_SMALL*/, EAlignment Align, const SDL_Color &Color /*= Colors::WHITE*/, const std::string &Text /*= ""*/) -//: CLabel(x, y, Font, Align, Color, Text) -//{ -// init(); -//} - CGStatusBar::CGStatusBar(CPicture *BG, EFonts Font /*= FONT_SMALL*/, EAlignment Align /*= CENTER*/, const SDL_Color &Color /*= Colors::WHITE*/) : CLabel(BG->pos.x, BG->pos.y, Font, Align, Color, "") { @@ -1421,7 +1437,7 @@ CGStatusBar::CGStatusBar(CPicture *BG, EFonts Font /*= FONT_SMALL*/, EAlignment bg = BG; addChild(bg); pos = bg->pos; - calcOffset(); + getBorderSize(); textLock = false; } @@ -1437,7 +1453,6 @@ CGStatusBar::CGStatusBar(int x, int y, std::string name/*="ADROLLVR.bmp"*/, int vstd::amin(pos.w, maxw); bg->srcRect = new Rect(0, 0, maxw, pos.h); } - calcOffset(); textLock = false; } @@ -1457,20 +1472,19 @@ void CGStatusBar::init() GH.statusbar = this; } -void CGStatusBar::calcOffset() +Point CGStatusBar::getBorderSize() { + //Width of borders where text should not be printed + static const Point borderSize(5,1); + switch(alignment) { - case TOPLEFT: - textOffset = Point(edgeOffset.x, edgeOffset.y); - break; - case CENTER: - textOffset = Point(pos.w/2, pos.h/2); - break; - case BOTTOMRIGHT: - textOffset = Point(pos.w - edgeOffset.x, pos.h - edgeOffset.y); - break; + case TOPLEFT: return Point(borderSize.x, borderSize.y); + case CENTER: return Point(pos.w/2, pos.h/2); + case BOTTOMRIGHT: return Point(pos.w - borderSize.x, pos.h - borderSize.y); } + assert(0); + return Point(); } void CGStatusBar::lock(bool shouldLock) @@ -1486,7 +1500,6 @@ CTextInput::CTextInput(const Rect &Pos, EFonts font, const CFunctionList labels; + EFonts font; + EAlignment align; + SDL_Color color; +public: + CLabelGroup(EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE); + void add(int x=0, int y=0, const std::string &text = ""); +}; + +/// Base class for all text-related widgets. +/// Controls text blitting-related options class CTextContainer : public virtual CIntObject { protected: - void blitLine(SDL_Surface * to, Point where, std::string what); + /// returns size of border, for left- or right-aligned text + virtual Point getBorderSize() = 0; + /// do actual blitting of line. Text "what" will be placed at "where" and aligned according to alignment + void blitLine(SDL_Surface * to, Rect where, std::string what); CTextContainer(EAlignment alignment, EFonts font, SDL_Color color); - //CTextContainer() {}; public: EAlignment alignment; EFonts font; - SDL_Color color; + SDL_Color color; // default font color. Can be overriden by placing "{}" into the string }; /// Label which shows text class CLabel : public CTextContainer { protected: - virtual std::string visibleText(); + Point getBorderSize() override; -public: - std::string text; CPicture *bg; - bool autoRedraw; //whether control will redraw itself on setTxt - Point textOffset; //text will be blitted at pos + textOffset with appropriate alignment - bool ignoreLeadingWhitespace; +public: - virtual void setTxt(const std::string &Txt); + std::string text; + bool autoRedraw; //whether control will redraw itself on setTxt + + std::string getText(); + virtual void setText(const std::string &Txt); + + CLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, + const SDL_Color &Color = Colors::WHITE, const std::string &Text = ""); void showAll(SDL_Surface * to); //shows statusbar (with current text) - CLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = ""); }; -class CBoundedLabel : public CLabel +/// Multi-line label that can display multiple lines of text +/// If text is too big to fit into requested area remaining part will not be visible +class CMultiLineLabel : public CLabel { -public: - - int maxW; //longest line of text in px - int maxH; //total height needed to print all lines - + // text to blit, split into lines that are no longer than widget width std::vector lines; - CBoundedLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "") - : CLabel (x, y, Font, Align, Color, Text){}; - void setTxt(const std::string &Txt); - void setBounds(int limitW, int limitH); - virtual void recalculateLines(const std::string &Txt); + // area of text that actually will be printed, default is widget size + Rect visibleSize; + + void splitText(const std::string &Txt); + Rect getTextLocation(); +public: + // total size of text, x = longest line of text, y = total height of lines + Point textSize; + + CMultiLineLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = ""); + + void setText(const std::string &Txt); void showAll(SDL_Surface * to); + + void setVisibleSize(Rect visibleSize); + // scrolls text visible in widget. Positive value will move text up + void scrollTextTo(int distance); + void scrollTextBy(int distance); }; -//Small helper class to manage group of similar labels -class CLabelGroup : public CIntObject +/// a multi-line label that tries to fit text with given available width and height; +/// if not possible, it creates a slider for scrolling text +class CTextBox : public CIntObject { - std::list labels; - EFonts font; - EAlignment align; - const SDL_Color &color; -public: - CLabelGroup(EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE); - void add(int x=0, int y=0, const std::string &text = ""); -}; - -/// a multi-line label that tries to fit text with given available width and height; if not possible, it creates a slider for scrolling text -class CTextBox : public CBoundedLabel -{ -public: - int sliderStyle; - - std::vector effects; +public: + CMultiLineLabel * label; CSlider *slider; - //CTextBox( std::string Text, const Point &Pos, int w, int h, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE); - CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE); - void showAll(SDL_Surface * to); //shows statusbar (with current text) - void recalculateLines(const std::string &Txt); + CTextBox(std::string Text, const Rect &rect, int SliderStyle, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE); + void resize(Point newSize); + void setText(const std::string &Txt); void sliderMoved(int to); }; /// Status bar which is shown at the bottom of the in-game screens class CGStatusBar : public CLabel { - bool textLock; //Used for blocking changes to the text + bool textLock; //Used for blocking changes to the text void init(); -public: - CGStatusBar *oldStatusBar; - //statusbar interface overloads - void print(const std::string & Text); //prints text and refreshes statusbar + CGStatusBar *oldStatusBar; +protected: + Point getBorderSize() override; + +public: + void clear();//clears statusbar and refreshes - std::string getCurrent(); //returns currently displayed text + void setText(const std::string & Text) override; //prints text and refreshes statusbar + void show(SDL_Surface * to); //shows statusbar (with current text) - //CGStatusBar(int x, int y, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE, const std::string &Text = ""); - CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar - CGStatusBar(int x, int y, std::string name, int maxw=-1); - + CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar + CGStatusBar(int x, int y, std::string name, int maxw=-1); ~CGStatusBar(); - void calcOffset(); - void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called - - const static Point edgeOffset; //Amount to move text from side when alignment is left or right + void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called }; /// UIElement which can get input focus @@ -441,7 +454,7 @@ protected: public: CFunctionList cb; CFunctionList filters; - void setTxt(const std::string &nText, bool callCb = false); + void setText(const std::string &nText, bool callCb = false); CTextInput(const Rect &Pos, EFonts font, const CFunctionList &CB); CTextInput(const Rect &Pos, const Point &bgOffset, const std::string &bgName, const CFunctionList &CB); diff --git a/config/campaignMedia.json b/config/campaignMedia.json index 14e4e2d0a..dac8405b1 100644 --- a/config/campaignMedia.json +++ b/config/campaignMedia.json @@ -128,7 +128,7 @@ "music" : [ ], - "voice" : { + "voice" : [ //Restoration of Erathia "G1A", //Long live the Queen 1 "G1B", //Long live the Queen 2 @@ -233,5 +233,5 @@ "H3x2UAk", //Unholy alliance 11 "H3x2UAl", //Unholy alliance 12 "H3x2UAm" //Unholy alliance 12end - } -} \ No newline at end of file + ] +}