diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index c87c6b1e6..ef3f1317b 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1292,8 +1292,8 @@ void CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path ) if (adventureInt && adventureInt->isHeroSleeping(h)) { - adventureInt->sleepWake.clickLeft(true, false); - adventureInt->sleepWake.clickLeft(false, true); + adventureInt->sleepWake->clickLeft(true, false); + adventureInt->sleepWake->clickLeft(false, true); //could've just called //adventureInt->fsleepWake(); //but no authentic button click/sound ;-) @@ -1328,7 +1328,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer waitForAllDialogs(); auto cgw = new CGarrisonWindow(up,down,removableUnits); - cgw->quit->callback += onEnd; + cgw->quit->addCallback(onEnd); GH.pushInt(cgw); } @@ -2246,7 +2246,7 @@ void CPlayerInterface::acceptTurn() if(CInfoWindow *iw = dynamic_cast(GH.topInt())) iw->close(); - adventureInt->endTurn.callback(); + adventureInt->fendTurn(); } // warn player if he has no town diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 11a69b547..f2fbb6a3e 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -30,8 +30,8 @@ */ class CDefEssential; -class CAdventureMapButton; -class CHighlightableButtonsGroup; +class CButton; +class CToggleGroup; class CDefHandler; struct TryMoveHero; class CDefEssential; diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 6b637ab2f..ff8b192f2 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -372,7 +372,7 @@ static std::function genCommand(CMenuScreen* menu, std::vector(); } -CAdventureMapButton* CMenuEntry::createButton(CMenuScreen* parent, const JsonNode& button) +CButton* CMenuEntry::createButton(CMenuScreen* parent, const JsonNode& button) { std::function command = genCommand(parent, parent->menuNameToEntry, button["command"].String()); @@ -388,7 +388,7 @@ CAdventureMapButton* CMenuEntry::createButton(CMenuScreen* parent, const JsonNod if (posy < 0) posy = pos.h + posy; - return new CAdventureMapButton(help, command, posx, posy, button["name"].String(), button["hotkey"].Float()); + return new CButton(Point(posx, posy), button["name"].String(), help, command, button["hotkey"].Float()); } CMenuEntry::CMenuEntry(CMenuScreen* parent, const JsonNode &config) @@ -644,40 +644,39 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMulti { case CMenuScreen::newGame: { - card->difficulty->onChange = boost::bind(&CSelectionScreen::difficultyChange, this, _1); - card->difficulty->select(1, 0); - CAdventureMapButton * select = new CAdventureMapButton(CGI->generaltexth->zelp[45], 0, 411, 80, "GSPBUTT.DEF", SDLK_s); - select->callback = [&]() + SDL_Color orange = {232, 184, 32, 0}; + SDL_Color overlayColor = multiPlayer == CMenuScreen::MULTI_NETWORK_GUEST ? orange : Colors::WHITE; + + card->difficulty->addCallback(boost::bind(&CSelectionScreen::difficultyChange, this, _1)); + card->difficulty->setSelected(1); + CButton * select = new CButton(Point(411, 80), "GSPBUTT.DEF", CGI->generaltexth->zelp[45], 0, SDLK_s); + select->addCallback([&]() { toggleTab(sel); changeSelection(sel->getSelectedMapInfo()); - }; - select->addTextOverlay(CGI->generaltexth->allTexts[500], FONT_SMALL); + }); + select->addTextOverlay(CGI->generaltexth->allTexts[500], FONT_SMALL, overlayColor); - CAdventureMapButton *opts = new CAdventureMapButton(CGI->generaltexth->zelp[46], boost::bind(&CSelectionScreen::toggleTab, this, opt), 411, 510, "GSPBUTT.DEF", SDLK_a); - opts->addTextOverlay(CGI->generaltexth->allTexts[501], FONT_SMALL); + CButton *opts = new CButton(Point(411, 510), "GSPBUTT.DEF", CGI->generaltexth->zelp[46], boost::bind(&CSelectionScreen::toggleTab, this, opt), SDLK_a); + opts->addTextOverlay(CGI->generaltexth->allTexts[501], FONT_SMALL, overlayColor); - CAdventureMapButton * randomBtn = new CAdventureMapButton(CGI->generaltexth->zelp[47], 0, 411, 105, "GSPBUTT.DEF", SDLK_r); - randomBtn->addTextOverlay(CGI->generaltexth->allTexts[740], FONT_SMALL); - randomBtn->callback = [&]() + CButton * randomBtn = new CButton(Point(411, 105), "GSPBUTT.DEF", CGI->generaltexth->zelp[47], 0, SDLK_r); + randomBtn->addTextOverlay(CGI->generaltexth->allTexts[740], FONT_SMALL, overlayColor); + randomBtn->addCallback([&]() { toggleTab(randMapTab); changeSelection(randMapTab->getMapInfo()); - }; + }); - start = new CAdventureMapButton(CGI->generaltexth->zelp[103], boost::bind(&CSelectionScreen::startScenario, this), 411, 535, "SCNRBEG.DEF", SDLK_b); + start = new CButton(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], boost::bind(&CSelectionScreen::startScenario, this), SDLK_b); if(network) { - CAdventureMapButton *hideChat = new CAdventureMapButton(CGI->generaltexth->zelp[48], boost::bind(&InfoCard::toggleChat, card), 619, 83, "GSPBUT2.DEF", SDLK_h); + CButton *hideChat = new CButton(Point(619, 83), "GSPBUT2.DEF", CGI->generaltexth->zelp[48], boost::bind(&InfoCard::toggleChat, card), SDLK_h); hideChat->addTextOverlay(CGI->generaltexth->allTexts[531], FONT_SMALL); if(multiPlayer == CMenuScreen::MULTI_NETWORK_GUEST) { - SDL_Color orange = {232, 184, 32, 0}; - dynamic_cast(select->overlay)->color = orange; - dynamic_cast(opts->overlay)->color = orange; - dynamic_cast(randomBtn->overlay)->color = orange; select->block(true); opts->block(true); randomBtn->block(true); @@ -688,21 +687,21 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMulti break; case CMenuScreen::loadGame: sel->recActions = 255; - start = new CAdventureMapButton(CGI->generaltexth->zelp[103], boost::bind(&CSelectionScreen::startScenario, this), 411, 535, "SCNRLOD.DEF", SDLK_l); + start = new CButton(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], boost::bind(&CSelectionScreen::startScenario, this), SDLK_l); break; case CMenuScreen::saveGame: sel->recActions = 255; - start = new CAdventureMapButton("", CGI->generaltexth->zelp[103].second, boost::bind(&CSelectionScreen::startScenario, this), 411, 535, "SCNRSAV.DEF"); + start = new CButton(Point(411, 535), "SCNRSAV.DEF", CGI->generaltexth->zelp[103], boost::bind(&CSelectionScreen::startScenario, this), SDLK_s); break; case CMenuScreen::campaignList: sel->recActions = 255; - start = new CAdventureMapButton(std::pair(), boost::bind(&CSelectionScreen::startCampaign, this), 411, 535, "SCNRLOD.DEF", SDLK_b); + start = new CButton(Point(411, 535), "SCNRLOD.DEF", CButton::tooltip(), boost::bind(&CSelectionScreen::startCampaign, this), SDLK_b); break; } start->assignedKeys.insert(SDLK_RETURN); - back = new CAdventureMapButton("", CGI->generaltexth->zelp[105].second, boost::bind(&CGuiHandler::popIntTotally, &GH, this), 581, 535, "SCNRBACK.DEF", SDLK_ESCAPE); + back = new CButton(Point(581, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], boost::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE); if(network) { @@ -999,7 +998,7 @@ void CSelectionScreen::setSInfo(const StartInfo &si) if(current) opt->recreate(); //will force to recreate using current sInfo - card->difficulty->select(si.difficulty, 0); + card->difficulty->setSelected(si.difficulty); GH.totalRedraw(); } @@ -1262,7 +1261,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const std::functiongeneraltexth->zelp[54+i].second, boost::bind(&SelectionTab::filter, this, sizes[i], true), 158 + 47*i, 46, names[i]); + new CButton(Point(158 + 47*i, 46), names[i], CGI->generaltexth->zelp[54+i], boost::bind(&SelectionTab::filter, this, sizes[i], true)); } //sort buttons buttons @@ -1276,20 +1275,19 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const std::functiongeneraltexth->zelp[107+i].second, boost::bind(&SelectionTab::sortBy, this, criteria), xpos[i], 86, names[i]); + new CButton(Point(xpos[i], 86), names[i], CGI->generaltexth->zelp[107+i], boost::bind(&SelectionTab::sortBy, this, criteria)); } } } else { //sort by buttons - new CAdventureMapButton("", "", boost::bind(&SelectionTab::sortBy, this, _numOfMaps), 23, 86, "CamCusM.DEF"); //by num of maps - new CAdventureMapButton("", "", boost::bind(&SelectionTab::sortBy, this, _name), 55, 86, "CamCusL.DEF"); //by name + new CButton(Point(23, 86), "CamCusM.DEF", CButton::tooltip(), boost::bind(&SelectionTab::sortBy, this, _numOfMaps)); //by num of maps + new CButton(Point(55, 86), "CamCusL.DEF", CButton::tooltip(), boost::bind(&SelectionTab::sortBy, this, _name)); //by name } slider = new CSlider(372, 86, tabType != CMenuScreen::saveGame ? 480 : 430, boost::bind(&SelectionTab::sliderMove, this, _1), positions, curItems.size(), 0, false, 1); slider->addUsedEvents(WHEEL); - slider->slider->keepFrame = true; format = CDefHandler::giveDef("SCSELC.DEF"); sortingBy = _format; @@ -1575,7 +1573,7 @@ void SelectionTab::onDoubleClick() if(getLine() != -1) //double clicked scenarios list { //act as if start button was pressed - (static_cast(parent))->start->callback(); + (static_cast(parent))->start->clickLeft(false, true); } } @@ -1620,27 +1618,25 @@ CRandomMapTab::CRandomMapTab() bg = new CPicture("RANMAPBK", 0, 6); // Map Size - mapSizeBtnGroup = new CHighlightableButtonsGroup(0); + mapSizeBtnGroup = new CToggleGroup(0); mapSizeBtnGroup->pos.y += 81; mapSizeBtnGroup->pos.x += 158; const std::vector mapSizeBtns = boost::assign::list_of("RANSIZS")("RANSIZM")("RANSIZL")("RANSIZX"); addButtonsToGroup(mapSizeBtnGroup, mapSizeBtns, 0, 3, 47, 198); - mapSizeBtnGroup->select(1, false); - mapSizeBtnGroup->onChange = [&](int btnId) + mapSizeBtnGroup->setSelected(1); + mapSizeBtnGroup->addCallback([&](int btnId) { const std::vector mapSizeVal = boost::assign::list_of(CMapHeader::MAP_SIZE_SMALL)(CMapHeader::MAP_SIZE_MIDDLE) (CMapHeader::MAP_SIZE_LARGE)(CMapHeader::MAP_SIZE_XLARGE); mapGenOptions.setWidth(mapSizeVal[btnId]); mapGenOptions.setHeight(mapSizeVal[btnId]); updateMapInfo(); - }; + }); // Two levels - twoLevelsBtn = new CHighlightableButton(0, 0, std::map(), - CGI->generaltexth->zelp[202].second, false, "RANUNDR", nullptr, 346, 81); + twoLevelsBtn = new CToggleButton(Point(346, 81), "RANUNDR", CGI->generaltexth->zelp[202]); //twoLevelsBtn->select(true); for now, deactivated - twoLevelsBtn->callback = [&]() { mapGenOptions.setHasTwoLevels(true); updateMapInfo(); }; - twoLevelsBtn->callback2 = [&]() { mapGenOptions.setHasTwoLevels(false); updateMapInfo(); }; + twoLevelsBtn->addCallback([&](bool on) { mapGenOptions.setHasTwoLevels(on); updateMapInfo(); }); // Create number defs list std::vector numberDefs; @@ -1652,128 +1648,129 @@ CRandomMapTab::CRandomMapTab() const int NUMBERS_WIDTH = 32; const int BTNS_GROUP_LEFT_MARGIN = 67; // Amount of players - playersCntGroup = new CHighlightableButtonsGroup(0); + playersCntGroup = new CToggleGroup(0); playersCntGroup->pos.y += 153; playersCntGroup->pos.x += BTNS_GROUP_LEFT_MARGIN; addButtonsWithRandToGroup(playersCntGroup, numberDefs, 1, 8, NUMBERS_WIDTH, 204, 212); - playersCntGroup->onChange = [&](int btnId) + playersCntGroup->addCallback([&](int btnId) { mapGenOptions.setPlayerCount(btnId); deactivateButtonsFrom(teamsCntGroup, btnId); deactivateButtonsFrom(compOnlyPlayersCntGroup, 8 - btnId + 1); validatePlayersCnt(btnId); updateMapInfo(); - }; + }); // Amount of teams - teamsCntGroup = new CHighlightableButtonsGroup(0); + teamsCntGroup = new CToggleGroup(0); teamsCntGroup->pos.y += 219; teamsCntGroup->pos.x += BTNS_GROUP_LEFT_MARGIN; addButtonsWithRandToGroup(teamsCntGroup, numberDefs, 0, 7, NUMBERS_WIDTH, 214, 222); - teamsCntGroup->onChange = [&](int btnId) + teamsCntGroup->addCallback([&](int btnId) { mapGenOptions.setTeamCount(btnId); updateMapInfo(); - }; + }); // Computer only players - compOnlyPlayersCntGroup = new CHighlightableButtonsGroup(0); + compOnlyPlayersCntGroup = new CToggleGroup(0); compOnlyPlayersCntGroup->pos.y += 285; compOnlyPlayersCntGroup->pos.x += BTNS_GROUP_LEFT_MARGIN; addButtonsWithRandToGroup(compOnlyPlayersCntGroup, numberDefs, 0, 7, NUMBERS_WIDTH, 224, 232); - compOnlyPlayersCntGroup->select(0, true); - compOnlyPlayersCntGroup->onChange = [&](int btnId) + compOnlyPlayersCntGroup->setSelected(0); + compOnlyPlayersCntGroup->addCallback([&](int btnId) { mapGenOptions.setCompOnlyPlayerCount(btnId); deactivateButtonsFrom(compOnlyTeamsCntGroup, btnId); validateCompOnlyPlayersCnt(btnId); updateMapInfo(); - }; + }); // Computer only teams - compOnlyTeamsCntGroup = new CHighlightableButtonsGroup(0); + compOnlyTeamsCntGroup = new CToggleGroup(0); compOnlyTeamsCntGroup->pos.y += 351; compOnlyTeamsCntGroup->pos.x += BTNS_GROUP_LEFT_MARGIN; addButtonsWithRandToGroup(compOnlyTeamsCntGroup, numberDefs, 0, 6, NUMBERS_WIDTH, 234, 241); deactivateButtonsFrom(compOnlyTeamsCntGroup, 0); - compOnlyTeamsCntGroup->onChange = [&](int btnId) + compOnlyTeamsCntGroup->addCallback([&](int btnId) { mapGenOptions.setCompOnlyTeamCount(btnId); updateMapInfo(); - }; + }); const int WIDE_BTN_WIDTH = 85; // Water content - waterContentGroup = new CHighlightableButtonsGroup(0); + waterContentGroup = new CToggleGroup(0); waterContentGroup->pos.y += 419; waterContentGroup->pos.x += BTNS_GROUP_LEFT_MARGIN; const std::vector waterContentBtns = boost::assign::list_of("RANNONE")("RANNORM")("RANISLD"); addButtonsWithRandToGroup(waterContentGroup, waterContentBtns, 0, 2, WIDE_BTN_WIDTH, 243, 246); - waterContentGroup->onChange = [&](int btnId) + waterContentGroup->addCallback([&](int btnId) { mapGenOptions.setWaterContent(static_cast(btnId)); - }; + }); // Monster strength - monsterStrengthGroup = new CHighlightableButtonsGroup(0); + monsterStrengthGroup = new CToggleGroup(0); monsterStrengthGroup->pos.y += 485; monsterStrengthGroup->pos.x += BTNS_GROUP_LEFT_MARGIN; const std::vector monsterStrengthBtns = boost::assign::list_of("RANWEAK")("RANNORM")("RANSTRG"); addButtonsWithRandToGroup(monsterStrengthGroup, monsterStrengthBtns, 0, 2, WIDE_BTN_WIDTH, 248, 251); - monsterStrengthGroup->onChange = [&](int btnId) + monsterStrengthGroup->addCallback([&](int btnId) { if (btnId < 0) mapGenOptions.setMonsterStrength(EMonsterStrength::RANDOM); else mapGenOptions.setMonsterStrength(static_cast(btnId + EMonsterStrength::GLOBAL_WEAK)); //value 2 to 4 - }; + }); // Show random maps btn - showRandMaps = new CAdventureMapButton("", CGI->generaltexth->zelp[252].second, 0, 54, 535, "RANSHOW"); + showRandMaps = new CButton(Point(54, 535), "RANSHOW", CGI->generaltexth->zelp[252]); // Initialize map info object updateMapInfo(); } -void CRandomMapTab::addButtonsWithRandToGroup(CHighlightableButtonsGroup * group, const std::vector & defs, int nStart, int nEnd, int btnWidth, int helpStartIndex, int helpRandIndex) const +void CRandomMapTab::addButtonsWithRandToGroup(CToggleGroup * group, const std::vector & defs, int nStart, int nEnd, int btnWidth, int helpStartIndex, int helpRandIndex) const { addButtonsToGroup(group, defs, nStart, nEnd, btnWidth, helpStartIndex); // Buttons are relative to button group, TODO better solution? SObjectConstruction obj__i(group); const std::string RANDOM_DEF = "RANRAND"; - group->addButton(new CHighlightableButton("", CGI->generaltexth->zelp[helpRandIndex].second, 0, 256, 0, RANDOM_DEF, CMapGenOptions::RANDOM_SIZE)); - group->select(CMapGenOptions::RANDOM_SIZE, true); + group->addToggle(CMapGenOptions::RANDOM_SIZE, new CToggleButton(Point(256, 0), RANDOM_DEF, CGI->generaltexth->zelp[helpRandIndex])); + group->setSelected(CMapGenOptions::RANDOM_SIZE); } -void CRandomMapTab::addButtonsToGroup(CHighlightableButtonsGroup * group, const std::vector & defs, int nStart, int nEnd, int btnWidth, int helpStartIndex) const +void CRandomMapTab::addButtonsToGroup(CToggleGroup * group, const std::vector & defs, int nStart, int nEnd, int btnWidth, int helpStartIndex) const { // Buttons are relative to button group, TODO better solution? SObjectConstruction obj__i(group); int cnt = nEnd - nStart + 1; for(int i = 0; i < cnt; ++i) { - group->addButton(new CHighlightableButton("", CGI->generaltexth->zelp[helpStartIndex + i].second, 0, i * btnWidth, 0, defs[i + nStart], i + nStart)); + auto button = new CToggleButton(Point(i * btnWidth, 0), defs[i + nStart], CGI->generaltexth->zelp[helpStartIndex + i]); + // For blocked state we should use pressed image actually + button->setImageOrder(0, 1, 1, 3); + + group->addToggle(i + nStart, button); } } -void CRandomMapTab::deactivateButtonsFrom(CHighlightableButtonsGroup * group, int startId) +void CRandomMapTab::deactivateButtonsFrom(CToggleGroup * group, int startId) { - for(CHighlightableButton * btn : group->buttons) + for(auto toggle : group->buttons) { - if(startId == CMapGenOptions::RANDOM_SIZE || btn->ID < startId) + if (auto button = dynamic_cast(toggle.second)) { - if(btn->isBlocked()) + if(startId == CMapGenOptions::RANDOM_SIZE || toggle.first < startId) { - btn->setOffset(0); - btn->setState(CButtonBase::NORMAL); + button->block(false); + } + else + { + button->block(true); } - } - else - { - // Blocked state looks like frame 'selected'=1 - btn->setOffset(-1); - btn->setState(CButtonBase::BLOCKED); } } } @@ -1788,12 +1785,12 @@ void CRandomMapTab::validatePlayersCnt(int playersCnt) if(mapGenOptions.getTeamCount() >= playersCnt) { mapGenOptions.setTeamCount(playersCnt - 1); - teamsCntGroup->select(mapGenOptions.getTeamCount(), true); + teamsCntGroup->setSelected(mapGenOptions.getTeamCount()); } if(mapGenOptions.getCompOnlyPlayerCount() > 8 - playersCnt) { mapGenOptions.setCompOnlyPlayerCount(8 - playersCnt); - compOnlyPlayersCntGroup->select(mapGenOptions.getCompOnlyPlayerCount(), true); + compOnlyPlayersCntGroup->setSelected(mapGenOptions.getCompOnlyPlayerCount()); } validateCompOnlyPlayersCnt(mapGenOptions.getCompOnlyPlayerCount()); @@ -1809,7 +1806,7 @@ void CRandomMapTab::validateCompOnlyPlayersCnt(int compOnlyPlayersCnt) if(mapGenOptions.getCompOnlyTeamCount() >= compOnlyPlayersCnt) { mapGenOptions.setCompOnlyTeamCount(compOnlyPlayersCnt - 1); - compOnlyTeamsCntGroup->select(mapGenOptions.getCompOnlyTeamCount(), true); + compOnlyTeamsCntGroup->setSelected(mapGenOptions.getCompOnlyTeamCount()); } } @@ -1964,20 +1961,20 @@ InfoCard::InfoCard( bool Network ) pos.h = bg->pos.h; sizes = CDefHandler::giveDef("SCNRMPSZ.DEF"); sFlags = CDefHandler::giveDef("ITGFLAGS.DEF"); - difficulty = new CHighlightableButtonsGroup(0); + difficulty = new CToggleGroup(0); { static const char *difButns[] = {"GSPBUT3.DEF", "GSPBUT4.DEF", "GSPBUT5.DEF", "GSPBUT6.DEF", "GSPBUT7.DEF"}; for(int i = 0; i < 5; i++) { - difficulty->addButton(new CHighlightableButton("", CGI->generaltexth->zelp[24+i].second, 0, 110 + i*32, 450, difButns[i], i)); + auto button = new CToggleButton(Point(110 + i*32, 450), difButns[i], CGI->generaltexth->zelp[24+i]); + + difficulty->addToggle(i, button); + if(SEL->screenType != CMenuScreen::newGame) + button->block(true); } } - if(SEL->screenType != CMenuScreen::newGame) - difficulty->block(true); - - if(network) { playerListBg = new CPicture("CHATPLUG.bmp", 16, 276); @@ -2165,8 +2162,8 @@ void InfoCard::changeSelection( const CMapInfo *to ) mapDescription->setText(to->mapHeader->description); if(SEL->screenType != CMenuScreen::newGame && SEL->screenType != CMenuScreen::campaignList) { - difficulty->block(true); - difficulty->select(SEL->sInfo.difficulty, 0); + //difficulty->block(true); + difficulty->setSelected(SEL->sInfo.difficulty); } } redraw(); @@ -2550,12 +2547,12 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry( OptionsTab *owner, PlayerSet bg = new CPicture(BitmapHandler::loadBitmap(bgs[s.color.getNum()]), 0, 0, true); if(SEL->screenType == CMenuScreen::newGame) { - btns[0] = new CAdventureMapButton(CGI->generaltexth->zelp[132], boost::bind(&OptionsTab::nextCastle, owner, s.color, -1), 107, 5, "ADOPLFA.DEF"); - btns[1] = new CAdventureMapButton(CGI->generaltexth->zelp[133], boost::bind(&OptionsTab::nextCastle, owner, s.color, +1), 168, 5, "ADOPRTA.DEF"); - btns[2] = new CAdventureMapButton(CGI->generaltexth->zelp[148], boost::bind(&OptionsTab::nextHero, owner, s.color, -1), 183, 5, "ADOPLFA.DEF"); - btns[3] = new CAdventureMapButton(CGI->generaltexth->zelp[149], boost::bind(&OptionsTab::nextHero, owner, s.color, +1), 244, 5, "ADOPRTA.DEF"); - btns[4] = new CAdventureMapButton(CGI->generaltexth->zelp[164], boost::bind(&OptionsTab::nextBonus, owner, s.color, -1), 259, 5, "ADOPLFA.DEF"); - btns[5] = new CAdventureMapButton(CGI->generaltexth->zelp[165], boost::bind(&OptionsTab::nextBonus, owner, s.color, +1), 320, 5, "ADOPRTA.DEF"); + btns[0] = new CButton(Point(107, 5), "ADOPLFA.DEF", CGI->generaltexth->zelp[132], boost::bind(&OptionsTab::nextCastle, owner, s.color, -1)); + btns[1] = new CButton(Point(168, 5), "ADOPRTA.DEF", CGI->generaltexth->zelp[133], boost::bind(&OptionsTab::nextCastle, owner, s.color, +1)); + btns[2] = new CButton(Point(183, 5), "ADOPLFA.DEF", CGI->generaltexth->zelp[148], boost::bind(&OptionsTab::nextHero, owner, s.color, -1)); + btns[3] = new CButton(Point(244, 5), "ADOPRTA.DEF", CGI->generaltexth->zelp[149], boost::bind(&OptionsTab::nextHero, owner, s.color, +1)); + btns[4] = new CButton(Point(259, 5), "ADOPLFA.DEF", CGI->generaltexth->zelp[164], boost::bind(&OptionsTab::nextBonus, owner, s.color, -1)); + btns[5] = new CButton(Point(320, 5), "ADOPRTA.DEF", CGI->generaltexth->zelp[165], boost::bind(&OptionsTab::nextBonus, owner, s.color, +1)); } else for(auto & elem : btns) @@ -2577,7 +2574,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry( OptionsTab *owner, PlayerSet && SEL->current->mapHeader->players[s.color.getNum()].canHumanPlay && SEL->multiPlayer != CMenuScreen::MULTI_NETWORK_GUEST) { - flag = new CAdventureMapButton(CGI->generaltexth->zelp[180], boost::bind(&OptionsTab::flagPressed, owner, s.color), -43, 2, flags[s.color.getNum()]); + flag = new CButton(Point(-43, 2), flags[s.color.getNum()], CGI->generaltexth->zelp[180], boost::bind(&OptionsTab::flagPressed, owner, s.color)); flag->hoverable = true; } else @@ -2983,8 +2980,8 @@ CScenarioInfo::CScenarioInfo(const CMapHeader *mapHeader, const StartInfo *start opt->recreate(); card->changeSelection(current); - card->difficulty->select(startInfo->difficulty, 0); - back = new CAdventureMapButton("", CGI->generaltexth->zelp[105].second, boost::bind(&CGuiHandler::popIntTotally, &GH, this), 584, 535, "SCNRBACK.DEF", SDLK_ESCAPE); + card->difficulty->setSelected(startInfo->difficulty); + back = new CButton(Point(584, 535), "SCNRBACK.DEF", CGI->generaltexth->zelp[105], boost::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE); } CScenarioInfo::~CScenarioInfo() @@ -3063,10 +3060,10 @@ CMultiMode::CMultiMode() txt = new CTextInput(Rect(19, 436, 334, 16), *bg); 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"); - btns[2] = new CAdventureMapButton("Join TCP/IP game", "", boost::bind(&CMultiMode::joinTCP, this), 373, 78 + 57*2, "MUBJOIN.DEF"); - btns[6] = new CAdventureMapButton(CGI->generaltexth->zelp[288], boost::bind(&CGuiHandler::popIntTotally, boost::ref(GH), this), 373, 424, "MUBCANC.DEF", SDLK_ESCAPE); + btns[0] = new CButton(Point(373, 78), "MUBHOT.DEF", CGI->generaltexth->zelp[266], boost::bind(&CMultiMode::openHotseat, this)); + btns[1] = new CButton(Point(373, 78 + 57*1), "MUBHOST.DEF", CButton::tooltip("Host TCP/IP game", ""), boost::bind(&CMultiMode::hostTCP, this)); + btns[2] = new CButton(Point(373, 78 + 57*2), "MUBJOIN.DEF", CButton::tooltip("Join TCP/IP game", ""), boost::bind(&CMultiMode::joinTCP, this)); + btns[6] = new CButton(Point(373, 424), "MUBCANC.DEF", CGI->generaltexth->zelp[288], [&] { GH.popIntTotally(this);}, SDLK_ESCAPE); } void CMultiMode::openHotseat() @@ -3106,8 +3103,8 @@ CHotSeatPlayers::CHotSeatPlayers(const std::string &firstPlayer) txt[i]->cb += boost::bind(&CHotSeatPlayers::onChange, this, _1); } - ok = new CAdventureMapButton(CGI->generaltexth->zelp[560], boost::bind(&CHotSeatPlayers::enterSelectionScreen, this), 95, 338, "MUBCHCK.DEF", SDLK_RETURN); - cancel = new CAdventureMapButton(CGI->generaltexth->zelp[561], boost::bind(&CGuiHandler::popIntTotally, boost::ref(GH), this), 205, 338, "MUBCANC.DEF", SDLK_ESCAPE); + ok = new CButton(Point(95, 338), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], boost::bind(&CHotSeatPlayers::enterSelectionScreen, this), SDLK_RETURN); + cancel = new CButton(Point(205, 338), "MUBCANC.DEF", CGI->generaltexth->zelp[561], boost::bind(&CGuiHandler::popIntTotally, boost::ref(GH), this), SDLK_ESCAPE); bar = new CGStatusBar(new CPicture(Rect(7, 381, 348, 18), 0));//226, 472 txt[0]->setText(firstPlayer, true); @@ -3170,9 +3167,9 @@ void CBonusSelection::init() blitAt(panel, 456, 6, background); - startB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::startMap, this), 475, 536, "CBBEGIB.DEF", SDLK_RETURN); - restartB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::restartMap, this), 475, 536, "CBRESTB.DEF", SDLK_RETURN); - backB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::goBack, this), 624, 536, "CBCANCB.DEF", SDLK_ESCAPE); + startB = new CButton(Point(475, 536), "CBBEGIB.DEF", CButton::tooltip(), boost::bind(&CBonusSelection::startMap, this), SDLK_RETURN); + restartB = new CButton(Point(475, 536), "CBRESTB.DEF", CButton::tooltip(), boost::bind(&CBonusSelection::restartMap, this), SDLK_RETURN); + backB = new CButton(Point(624, 536), "CBCANCB.DEF", CButton::tooltip(), boost::bind(&CBonusSelection::goBack, this), SDLK_ESCAPE); //campaign name if (ourCampaign->camp->header.name.length()) @@ -3194,7 +3191,7 @@ void CBonusSelection::init() //bonus choosing graphics->fonts[FONT_MEDIUM]->renderTextLeft(background, CGI->generaltexth->allTexts[71], Colors::WHITE, Point(511, 432)); - bonuses = new CHighlightableButtonsGroup(bind(&CBonusSelection::selectBonus, this, _1)); + bonuses = new CToggleGroup(bind(&CBonusSelection::selectBonus, this, _1)); //set left part of window bool isCurrentMapConquerable = ourCampaign->currentMap && ourCampaign->camp->conquerable(*ourCampaign->currentMap); @@ -3245,8 +3242,8 @@ void CBonusSelection::init() //difficulty selection buttons if (ourCampaign->camp->header.difficultyChoosenByPlayer) { - diffLb = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::decreaseDifficulty, this), 694, 508, "SCNRBLF.DEF"); - diffRb = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::increaseDifficulty, this), 738, 508, "SCNRBRT.DEF"); + diffLb = new CButton(Point(694, 508), "SCNRBLF.DEF", CButton::tooltip(), boost::bind(&CBonusSelection::decreaseDifficulty, this)); + diffRb = new CButton(Point(738, 508), "SCNRBRT.DEF", CButton::tooltip(), boost::bind(&CBonusSelection::increaseDifficulty, this)); } //load miniflags @@ -3446,13 +3443,8 @@ void CBonusSelection::updateBonusSelection() updateStartButtonState(-1); - for (auto & elem : bonuses->buttons) - { - if (elem->active) - elem->deactivate(); - delete elem; - } - bonuses->buttons.clear(); + delete bonuses; + bonuses = new CToggleGroup(bind(&CBonusSelection::selectBonus, this, _1)); static const char *bonusPics[] = {"SPELLBON.DEF", "TWCRPORT.DEF", "", "ARTIFBON.DEF", "SPELLBON.DEF", "PSKILBON.DEF", "SSKILBON.DEF", "BORES.DEF", "PORTRAITSLARGE", "PORTRAITSLARGE"}; @@ -3606,7 +3598,7 @@ void CBonusSelection::updateBonusSelection() break; } - CHighlightableButton *bonusButton = new CHighlightableButton(desc, desc, 0, 475 + i*68, 455, "", i); + CToggleButton *bonusButton = new CToggleButton(Point(475 + i*68, 455), "", CButton::tooltip(desc, desc)); if (picNumber != -1) picName += ":" + boost::lexical_cast(picNumber); @@ -3616,13 +3608,13 @@ void CBonusSelection::updateBonusSelection() bonusButton->setImage(anim); const SDL_Color brightYellow = { 242, 226, 110, 0 }; bonusButton->borderColor = brightYellow; - bonuses->addButton(bonusButton); + bonuses->addToggle(i, bonusButton); } // set bonus if already chosen if(vstd::contains(ourCampaign->chosenCampaignBonuses, selectedMap)) { - bonuses->select(ourCampaign->chosenCampaignBonuses[selectedMap], false); + bonuses->setSelected(ourCampaign->chosenCampaignBonuses[selectedMap]); } } @@ -3731,11 +3723,11 @@ void CBonusSelection::updateStartButtonState(int selected /*= -1*/) { if(selected == -1) { - startB->setState(ourCampaign->camp->scenarios[selectedMap].travelOptions.bonusesToChoose.size() ? CButtonBase::BLOCKED : CButtonBase::NORMAL); + startB->block(ourCampaign->camp->scenarios[selectedMap].travelOptions.bonusesToChoose.size()); } - else if(startB->getState() == CButtonBase::BLOCKED) + else if(startB->isBlocked()) { - startB->setState(CButtonBase::NORMAL); + startB->block(false); } } @@ -4095,14 +4087,14 @@ void CCampaignScreen::CCampaignButton::show(SDL_Surface * to) } } -CAdventureMapButton* CCampaignScreen::createExitButton(const JsonNode& button) +CButton* CCampaignScreen::createExitButton(const JsonNode& button) { std::pair help; if (!button["help"].isNull() && button["help"].Float() > 0) help = CGI->generaltexth->zelp[button["help"].Float()]; std::function close = boost::bind(&CGuiHandler::popIntTotally, &GH, this); - return new CAdventureMapButton(help, close, button["x"].Float(), button["y"].Float(), button["name"].String(), button["hotkey"].Float()); + return new CButton(Point(button["x"].Float(), button["y"].Float()), button["name"].String(), help, close, button["hotkey"].Float()); } @@ -4243,8 +4235,8 @@ CSimpleJoinScreen::CSimpleJoinScreen() port->cb += boost::bind(&CSimpleJoinScreen::onChange, this, _1); port->filters.add(boost::bind(&CTextInput::numberFilter, _1, _2, 0, 65535)); - ok = new CAdventureMapButton(CGI->generaltexth->zelp[560], boost::bind(&CSimpleJoinScreen::enterSelectionScreen, this), 26, 142, "MUBCHCK.DEF", SDLK_RETURN); - cancel = new CAdventureMapButton(CGI->generaltexth->zelp[561], boost::bind(&CGuiHandler::popIntTotally, boost::ref(GH), this), 142, 142, "MUBCANC.DEF", SDLK_ESCAPE); + ok = new CButton(Point( 26, 142), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], boost::bind(&CSimpleJoinScreen::enterSelectionScreen, this), SDLK_RETURN); + cancel = new CButton(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], boost::bind(&CGuiHandler::popIntTotally, boost::ref(GH), this), SDLK_ESCAPE); bar = new CGStatusBar(new CPicture(Rect(7, 186, 218, 18), 0)); port->setText(boost::lexical_cast(settings["server"]["port"].Float()), true); diff --git a/client/CPreGame.h b/client/CPreGame.h index b2cde99c1..a38d29d4a 100644 --- a/client/CPreGame.h +++ b/client/CPreGame.h @@ -33,10 +33,10 @@ class CRandomMapTab; struct CPackForSelectionScreen; struct PlayerInfo; class CMultiLineLabel; -class CHighlightableButton; -class CHighlightableButtonsGroup; +class CToggleButton; +class CToggleGroup; class CTabbedInt; -class CAdventureMapButton; +class CButton; class CSlider; namespace boost{ class thread; class recursive_mutex;} @@ -86,9 +86,9 @@ public: class CMenuEntry : public CIntObject { std::vector images; - std::vector buttons; + std::vector buttons; - CAdventureMapButton* createButton(CMenuScreen* parent, const JsonNode& button); + CButton* createButton(CMenuScreen* parent, const JsonNode& button); public: CMenuEntry(CMenuScreen* parent, const JsonNode &config); }; @@ -132,7 +132,7 @@ public: CChatBox *chat; CPicture *playerListBg; - CHighlightableButtonsGroup *difficulty; + CToggleGroup *difficulty; CDefHandler *sizes, *sFlags; void changeSelection(const CMapInfo *to); @@ -245,8 +245,8 @@ public: PlayerInfo π PlayerSettings &s; CPicture *bg; - CAdventureMapButton *btns[6]; //left and right for town, hero, bonus - CAdventureMapButton *flag; + CButton *btns[6]; //left and right for town, hero, bonus + CButton *flag; SelectedBox *town; SelectedBox *hero; SelectedBox *bonus; @@ -302,17 +302,17 @@ public: const CMapGenOptions & getMapGenOptions() const; private: - void addButtonsToGroup(CHighlightableButtonsGroup * group, const std::vector & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex) const; - void addButtonsWithRandToGroup(CHighlightableButtonsGroup * group, const std::vector & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex, int helpRandIndex) const; - void deactivateButtonsFrom(CHighlightableButtonsGroup * group, int startId); + void addButtonsToGroup(CToggleGroup * group, const std::vector & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex) const; + void addButtonsWithRandToGroup(CToggleGroup * group, const std::vector & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex, int helpRandIndex) const; + void deactivateButtonsFrom(CToggleGroup * group, int startId); void validatePlayersCnt(int playersCnt); void validateCompOnlyPlayersCnt(int compOnlyPlayersCnt); CPicture * bg; - CHighlightableButton * twoLevelsBtn; - CHighlightableButtonsGroup * mapSizeBtnGroup, * playersCntGroup, * teamsCntGroup, * compOnlyPlayersCntGroup, + CToggleButton * twoLevelsBtn; + CToggleGroup * mapSizeBtnGroup, * playersCntGroup, * teamsCntGroup, * compOnlyPlayersCntGroup, * compOnlyTeamsCntGroup, * waterContentGroup, * monsterStrengthGroup; - CAdventureMapButton * showRandMaps; + CButton * showRandMaps; CMapGenOptions mapGenOptions; unique_ptr mapInfo; CFunctionList mapInfoChanged; @@ -353,7 +353,7 @@ public: InfoCard *card; OptionsTab *opt; CRandomMapTab * randMapTab; - CAdventureMapButton *start, *back; + CButton *start, *back; SelectionTab *sel; CIntObject *curTab; @@ -401,7 +401,7 @@ public: class CScenarioInfo : public CIntObject, public ISelectionScreenInfo { public: - CAdventureMapButton *back; + CButton *back; InfoCard *card; OptionsTab *opt; @@ -415,7 +415,7 @@ class CMultiMode : public CIntObject public: CPicture *bg; CTextInput *txt; - CAdventureMapButton *btns[7]; //0 - hotseat, 6 - cancel + CButton *btns[7]; //0 - hotseat, 6 - cancel CGStatusBar *bar; CMultiMode(); @@ -430,7 +430,7 @@ class CHotSeatPlayers : public CIntObject CPicture *bg; CTextBox *title; CTextInput* txt[8]; - CAdventureMapButton *ok, *cancel; + CButton *ok, *cancel; CGStatusBar *bar; void onChange(std::string newText); @@ -518,14 +518,14 @@ private: // GUI components SDL_Surface * background; - CAdventureMapButton * startB, * restartB, * backB; + CButton * startB, * restartB, * backB; CTextBox * campaignDescription, * mapDescription; std::vector campDescriptions; std::vector regions; CRegion * highlightedRegion; - CHighlightableButtonsGroup * bonuses; + CToggleGroup * bonuses; SDL_Surface * diffPics[5]; //pictures of difficulties, user-selectable (or not if campaign locks this) - CAdventureMapButton * diffLb, * diffRb; //buttons for changing difficulty + CButton * diffLb, * diffRb; //buttons for changing difficulty CDefHandler * sizes; //icons of map sizes CDefHandler * sFlags; @@ -566,11 +566,11 @@ private: void show(SDL_Surface * to); }; - CAdventureMapButton *back; + CButton *back; std::vector campButtons; std::vector images; - CAdventureMapButton* createExitButton(const JsonNode& button); + CButton* createExitButton(const JsonNode& button); public: enum CampaignSet {ROE, AB, SOD, WOG}; @@ -636,7 +636,7 @@ class CSimpleJoinScreen : public CIntObject { CPicture * bg; CTextBox * title; - CAdventureMapButton * ok, * cancel; + CButton * ok, * cancel; CGStatusBar * bar; CTextInput * address; CTextInput * port; diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index f7dfcdb5a..2d3ed01cd 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -222,17 +222,17 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe // blitAt(menu, pos.x, 556 + pos.y); //preparing buttons and console - bOptions = new CAdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3, 561, "icm003.def", SDLK_o); - bSurrender = new CAdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54, 561, "icm001.def", SDLK_s); - bFlee = new CAdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105, 561, "icm002.def", SDLK_r); - bAutofight = new CAdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157, 561, "icm004.def", SDLK_a); - bSpell = new CAdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645, 561, "icm005.def", SDLK_c); - bWait = new CAdventureMapButton (CGI->generaltexth->zelp[386].first, CGI->generaltexth->zelp[386].second, boost::bind(&CBattleInterface::bWaitf,this), 696, 561, "icm006.def", SDLK_w); - bDefence = new CAdventureMapButton (CGI->generaltexth->zelp[387].first, CGI->generaltexth->zelp[387].second, boost::bind(&CBattleInterface::bDefencef,this), 747, 561, "icm007.def", SDLK_d); + bOptions = new CButton (Point( 3, 561), "icm003.def", CGI->generaltexth->zelp[381], boost::bind(&CBattleInterface::bOptionsf,this), SDLK_o); + bSurrender = new CButton (Point( 54, 561), "icm001.def", CGI->generaltexth->zelp[379], boost::bind(&CBattleInterface::bSurrenderf,this), SDLK_s); + bFlee = new CButton (Point(105, 561), "icm002.def", CGI->generaltexth->zelp[380], boost::bind(&CBattleInterface::bFleef,this), SDLK_r); + bAutofight = new CButton (Point(157, 561), "icm004.def", CGI->generaltexth->zelp[382], boost::bind(&CBattleInterface::bAutofightf,this), SDLK_a); + bSpell = new CButton (Point(645, 561), "icm005.def", CGI->generaltexth->zelp[385], boost::bind(&CBattleInterface::bSpellf,this), SDLK_c); + bWait = new CButton (Point(696, 561), "icm006.def", CGI->generaltexth->zelp[386], boost::bind(&CBattleInterface::bWaitf,this), SDLK_w); + bDefence = new CButton (Point(747, 561), "icm007.def", CGI->generaltexth->zelp[387], boost::bind(&CBattleInterface::bDefencef,this), SDLK_d); bDefence->assignedKeys.insert(SDLK_SPACE); - bConsoleUp = new CAdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bConsoleUpf,this), 624, 561, "ComSlide.def", SDLK_UP); - bConsoleDown = new CAdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bConsoleDownf,this), 624, 580, "ComSlide.def", SDLK_DOWN); - bConsoleDown->setOffset(2); + bConsoleUp = new CButton (Point(624, 561), "ComSlide.def", std::make_pair("", ""), boost::bind(&CBattleInterface::bConsoleUpf,this), SDLK_UP); + bConsoleDown = new CButton (Point(624, 580), "ComSlide.def", std::make_pair("", ""), boost::bind(&CBattleInterface::bConsoleDownf,this), SDLK_DOWN); + bConsoleDown->setImageOrder(2, 3, 4, 5); console = new CBattleConsole(); console->pos.x += 211; console->pos.y += 560; @@ -240,8 +240,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe console->pos.h = 38; if(tacticsMode) { - btactNext = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bTacticNextStack,this, (CStack*)nullptr), 213, 560, "icm011.def", SDLK_SPACE); - btactEnd = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CBattleInterface::bEndTacticPhase,this), 419, 560, "icm012.def", SDLK_RETURN); + btactNext = new CButton(Point(213, 560), "icm011.def", std::make_pair("", ""), [&]{ bTacticNextStack(nullptr);}, SDLK_SPACE); + btactEnd = new CButton(Point(419, 560), "icm012.def", std::make_pair("", ""), [&]{ bEndTacticPhase();}, SDLK_RETURN); menu = BitmapHandler::loadBitmap("COPLACBR.BMP"); } else diff --git a/client/battle/CBattleInterface.h b/client/battle/CBattleInterface.h index 2b064ca8c..cbb11ad94 100644 --- a/client/battle/CBattleInterface.h +++ b/client/battle/CBattleInterface.h @@ -23,9 +23,9 @@ class CGHeroInstance; class CDefHandler; class CStack; class CCallback; -class CAdventureMapButton; -class CHighlightableButton; -class CHighlightableButtonsGroup; +class CButton; +class CToggleButton; +class CToggleGroup; struct BattleResult; struct BattleSpellCast; struct CObstacleInstance; @@ -120,7 +120,7 @@ class CBattleInterface : public CIntObject }; private: SDL_Surface * background, * menu, * amountNormal, * amountNegative, * amountPositive, * amountEffNeutral, * cellBorders, * backgroundWithHexes; - CAdventureMapButton * bOptions, * bSurrender, * bFlee, * bAutofight, * bSpell, + CButton * bOptions, * bSurrender, * bFlee, * bAutofight, * bSpell, * bWait, * bDefence, * bConsoleUp, * bConsoleDown, *btactNext, *btactEnd; CBattleConsole * console; CBattleHero * attackingHero, * defendingHero; //fighting heroes @@ -338,7 +338,7 @@ public: InfoAboutHero enemyHero() const; friend class CPlayerInterface; - friend class CAdventureMapButton; + friend class CButton; friend class CInGameConsole; friend class CBattleResultWindow; diff --git a/client/battle/CBattleInterfaceClasses.cpp b/client/battle/CBattleInterfaceClasses.cpp index ec897ff42..15dda2f10 100644 --- a/client/battle/CBattleInterfaceClasses.cpp +++ b/client/battle/CBattleInterfaceClasses.cpp @@ -263,26 +263,23 @@ CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInt background = new CPicture("comopbck.bmp"); background->colorize(owner->getCurrentPlayerInterface()->playerID); - viewGrid = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintCellBorders, owner, true), boost::bind(&CBattleInterface::setPrintCellBorders, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[427].first)(3,CGI->generaltexth->zelp[427].first), CGI->generaltexth->zelp[427].second, false, "sysopchk.def", nullptr, 25, 56, false); - viewGrid->select(settings["battle"]["cellBorders"].Bool()); - movementShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintStackRange, owner, true), boost::bind(&CBattleInterface::setPrintStackRange, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[428].first)(3,CGI->generaltexth->zelp[428].first), CGI->generaltexth->zelp[428].second, false, "sysopchk.def", nullptr, 25, 89, false); - movementShadow->select(settings["battle"]["stackRange"].Bool()); - mouseShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintMouseShadow, owner, true), boost::bind(&CBattleInterface::setPrintMouseShadow, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[429].first)(3,CGI->generaltexth->zelp[429].first), CGI->generaltexth->zelp[429].second, false, "sysopchk.def", nullptr, 25, 122, false); - mouseShadow->select(settings["battle"]["mouseShadow"].Bool()); + viewGrid = new CToggleButton(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [&](bool on){owner->setPrintCellBorders(on);} ); + viewGrid->setSelected(settings["battle"]["cellBorders"].Bool()); + movementShadow = new CToggleButton(Point(25, 89), "sysopchk.def", CGI->generaltexth->zelp[428], [&](bool on){owner->setPrintStackRange(on);}); + movementShadow->setSelected(settings["battle"]["stackRange"].Bool()); + mouseShadow = new CToggleButton(Point(25, 122), "sysopchk.def", CGI->generaltexth->zelp[429], [&](bool on){owner->setPrintMouseShadow(on);}); + mouseShadow->setSelected(settings["battle"]["mouseShadow"].Bool()); - animSpeeds = new CHighlightableButtonsGroup(0); - animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[422].first),CGI->generaltexth->zelp[422].second, "sysopb9.def", 28, 225, 40); - animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[423].first),CGI->generaltexth->zelp[423].second, "sysob10.def", 92, 225, 63); - animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[424].first),CGI->generaltexth->zelp[424].second, "sysob11.def",156, 225, 100); - animSpeeds->select(owner->getAnimSpeed(), 1); - animSpeeds->onChange = boost::bind(&CBattleInterface::setAnimSpeed, owner, _1); + animSpeeds = new CToggleGroup([&](int value){ owner->setAnimSpeed(value);}); + animSpeeds->addToggle(40, new CToggleButton(Point( 28, 225), "sysopb9.def", CGI->generaltexth->zelp[422])); + animSpeeds->addToggle(63, new CToggleButton(Point( 92, 225), "sysob10.def", CGI->generaltexth->zelp[423])); + animSpeeds->addToggle(100, new CToggleButton(Point(156, 225), "sysob11.def", CGI->generaltexth->zelp[424])); + animSpeeds->setSelected(owner->getAnimSpeed()); - setToDefault = new CAdventureMapButton (CGI->generaltexth->zelp[393], boost::bind(&CBattleOptionsWindow::bDefaultf,this), 246, 359, "codefaul.def"); - setToDefault->swappedImages = true; - setToDefault->update(); - exit = new CAdventureMapButton (CGI->generaltexth->zelp[392], boost::bind(&CBattleOptionsWindow::bExitf,this), 357, 359, "soretrn.def",SDLK_RETURN); - exit->swappedImages = true; - exit->update(); + setToDefault = new CButton (Point(246, 359), "codefaul.def", CGI->generaltexth->zelp[393], [&]{ bDefaultf(); }); + setToDefault->setImageOrder(1, 0, 2, 3); + exit = new CButton (Point(357, 359), "soretrn.def", CGI->generaltexth->zelp[392], [&]{ bExitf();}, SDLK_RETURN); + exit->setImageOrder(1, 0, 2, 3); //creating labels labels.push_back(new CLabel(242, 32, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[392]));//window title @@ -312,6 +309,7 @@ CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInt void CBattleOptionsWindow::bDefaultf() { + //TODO: implement } void CBattleOptionsWindow::bExitf() @@ -327,9 +325,8 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect CPicture * bg = new CPicture("CPRESULT"); bg->colorize(owner.playerID); - exit = new CAdventureMapButton ("", "", boost::bind(&CBattleResultWindow::bExitf,this), 384, 505, "iok6432.def", SDLK_RETURN); + exit = new CButton (Point(384, 505), "iok6432.def", std::make_pair("", ""), [&]{ bExitf();}, SDLK_RETURN); exit->borderColor = Colors::METALLIC_GOLD; - exit->borderEnabled = true; if(br.winner==0) //attacker won { diff --git a/client/battle/CBattleInterfaceClasses.h b/client/battle/CBattleInterfaceClasses.h index 055e1a672..3f20c7206 100644 --- a/client/battle/CBattleInterfaceClasses.h +++ b/client/battle/CBattleInterfaceClasses.h @@ -8,9 +8,9 @@ class CDefHandler; class CGHeroInstance; class CBattleInterface; class CPicture; -class CAdventureMapButton; -class CHighlightableButton; -class CHighlightableButtonsGroup; +class CButton; +class CToggleButton; +class CToggleGroup; class CLabel; struct BattleResult; class CStack; @@ -72,9 +72,9 @@ class CBattleOptionsWindow : public CIntObject { private: CPicture * background; - CAdventureMapButton * setToDefault, * exit; - CHighlightableButton * viewGrid, * movementShadow, * mouseShadow; - CHighlightableButtonsGroup * animSpeeds; + CButton * setToDefault, * exit; + CToggleButton * viewGrid, * movementShadow, * mouseShadow; + CToggleGroup * animSpeeds; std::vector labels; public: @@ -88,7 +88,7 @@ public: class CBattleResultWindow : public CIntObject { private: - CAdventureMapButton *exit; + CButton *exit; CPlayerInterface &owner; public: CBattleResultWindow(const BattleResult & br, const SDL_Rect & pos, CPlayerInterface &_owner); //c-tor @@ -152,4 +152,4 @@ public: void update(); void showAll(SDL_Surface *to); void blitBg(SDL_Surface * to); -}; \ No newline at end of file +}; diff --git a/client/gui/CIntObject.cpp b/client/gui/CIntObject.cpp index aeabf3046..06c9159ad 100644 --- a/client/gui/CIntObject.cpp +++ b/client/gui/CIntObject.cpp @@ -323,6 +323,19 @@ bool CIntObject::captureThisEvent(const SDL_KeyboardEvent & key) return captureAllKeys; } +CKeyShortcut::CKeyShortcut() +{} + +CKeyShortcut::CKeyShortcut(int key) +{ + if (key != SDLK_UNKNOWN) + assignedKeys.insert(key); +} + +CKeyShortcut::CKeyShortcut(std::set Keys) + :assignedKeys(Keys) +{} + void CKeyShortcut::keyPressed(const SDL_KeyboardEvent & key) { if(vstd::contains(assignedKeys,key.keysym.sym) diff --git a/client/gui/CIntObject.h b/client/gui/CIntObject.h index 16279bb72..b0c1013f4 100644 --- a/client/gui/CIntObject.h +++ b/client/gui/CIntObject.h @@ -218,8 +218,8 @@ class CKeyShortcut : public virtual CIntObject { public: std::set assignedKeys; - CKeyShortcut(){}; //c-tor - CKeyShortcut(int key){assignedKeys.insert(key);}; //c-tor - CKeyShortcut(std::set Keys):assignedKeys(Keys){}; //c-tor + CKeyShortcut(); + CKeyShortcut(int key); + CKeyShortcut(std::set Keys); virtual void keyPressed(const SDL_KeyboardEvent & key); //call-in }; diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 022129b26..f8b68d817 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -106,15 +106,15 @@ CList::CList(int Size, Point position, std::string btnUp, std::string btnDown, s selected(nullptr) { OBJ_CONSTRUCTION_CAPTURING_ALL; - scrollUp = new CAdventureMapButton(CGI->generaltexth->zelp[helpUp], 0, 0, 0, btnUp); + scrollUp = new CButton(Point(0, 0), btnUp, CGI->generaltexth->zelp[helpUp]); list = new CListBox(create, destroy, Point(1,scrollUp->pos.h), Point(0, 32), size, listAmount); //assign callback only after list was created - scrollUp->callback = boost::bind(&CListBox::moveToPrev, list); - scrollDown = new CAdventureMapButton(CGI->generaltexth->zelp[helpDown], boost::bind(&CListBox::moveToNext, list), 0, scrollUp->pos.h + 32*size, btnDown); + scrollUp->addCallback(boost::bind(&CListBox::moveToPrev, list)); + scrollDown = new CButton(Point(0, scrollUp->pos.h + 32*size), btnDown, CGI->generaltexth->zelp[helpDown], boost::bind(&CListBox::moveToNext, list)); - scrollDown->callback += boost::bind(&CList::update, this); - scrollUp->callback += boost::bind(&CList::update, this); + scrollDown->addCallback(boost::bind(&CList::update, this)); + scrollUp->addCallback(boost::bind(&CList::update, this)); update(); } diff --git a/client/widgets/AdventureMapClasses.h b/client/widgets/AdventureMapClasses.h index 8cfe252f1..84652db71 100644 --- a/client/widgets/AdventureMapClasses.h +++ b/client/widgets/AdventureMapClasses.h @@ -9,7 +9,7 @@ class CGGarrison; class CGObjectInstance; class CGHeroInstance; class CGTownInstance; -class CAdventureMapButton; +class CButton; struct Component; struct InfoAboutArmy; struct InfoAboutHero; @@ -83,8 +83,8 @@ protected: public: - CAdventureMapButton * scrollUp; - CAdventureMapButton * scrollDown; + CButton * scrollUp; + CButton * scrollDown; /// functions that will be called when selection changes CFunctionList onSelect; diff --git a/client/widgets/Buttons.cpp b/client/widgets/Buttons.cpp index 21bf74d6c..73ec72a68 100644 --- a/client/widgets/Buttons.cpp +++ b/client/widgets/Buttons.cpp @@ -24,21 +24,40 @@ * */ -CButtonBase::CButtonBase() +ClickableArea::ClickableArea(CIntObject * object, CFunctionList callback): + callback(callback), + area(nullptr) { - swappedImages = keepFrame = false; - bitmapOffset = 0; - state=NORMAL; - image = nullptr; - overlay = nullptr; + if (object) + pos = object->pos; + setArea(object); } -CButtonBase::~CButtonBase() +void ClickableArea::addCallback(std::function callback) { - + this->callback += callback; } -void CButtonBase::update() +void ClickableArea::setArea(CIntObject * object) +{ + delete area; + addChild(area); + pos.w = object->pos.w; + pos.h = object->pos.h; +} + +void ClickableArea::onClick() +{ + callback(); +} + +void ClickableArea::clickLeft(tribool down, bool previousState) +{ + if (down) + onClick(); +} + +void CButton::update() { if (overlay) { @@ -48,34 +67,31 @@ void CButtonBase::update() overlay->moveTo(overlay->pos.centerIn(pos).topLeft()); } - int newPos = (int)state + bitmapOffset; + int newPos = stateToIndex[int(state)]; if (newPos < 0) newPos = 0; if (state == HIGHLIGHTED && image->size() < 4) newPos = image->size()-1; - - if (swappedImages) - { - if (newPos == 0) newPos = 1; - else if (newPos == 1) newPos = 0; - } - - if (!keepFrame) - image->setFrame(newPos); + image->setFrame(newPos); if (active) redraw(); } -void CButtonBase::addTextOverlay( const std::string &Text, EFonts font, SDL_Color color) +void CButton::addCallback(std::function callback) +{ + this->callback += callback; +} + +void CButton::addTextOverlay( const std::string &Text, EFonts font, SDL_Color color) { OBJ_CONSTRUCTION_CAPTURING_ALL; addOverlay(new CLabel(pos.w/2, pos.h/2, font, CENTER, color, Text)); update(); } -void CButtonBase::addOverlay(CIntObject *newOverlay) +void CButton::addOverlay(CIntObject *newOverlay) { delete overlay; overlay = newOverlay; @@ -84,15 +100,26 @@ void CButtonBase::addOverlay(CIntObject *newOverlay) update(); } -void CButtonBase::setOffset(int newOffset) +void CButton::addImage(std::string filename) { - if (bitmapOffset == newOffset) - return; - bitmapOffset = newOffset; + imageNames.push_back(filename); +} + +void CButton::addHoverText(ButtonState state, std::string text) +{ + hoverTexts[state] = text; +} + +void CButton::setImageOrder(int state1, int state2, int state3, int state4) +{ + stateToIndex[0] = state1; + stateToIndex[1] = state2; + stateToIndex[2] = state3; + stateToIndex[3] = state4; update(); } -void CButtonBase::setState(ButtonState newState) +void CButton::setState(ButtonState newState) { if (state == newState) return; @@ -100,58 +127,30 @@ void CButtonBase::setState(ButtonState newState) update(); } -CButtonBase::ButtonState CButtonBase::getState() +CButton::ButtonState CButton::getState() { return state; } -bool CButtonBase::isBlocked() +bool CButton::isBlocked() { return state == BLOCKED; } -bool CButtonBase::isHighlighted() +bool CButton::isHighlighted() { return state == HIGHLIGHTED; } -void CButtonBase::block(bool on) +void CButton::block(bool on) { setState(on?BLOCKED:NORMAL); } -CAdventureMapButton::CAdventureMapButton () -{ - hoverable = actOnDown = borderEnabled = soundDisabled = false; - CSDL_Ext::colorSetAlpha(borderColor,1);// represents a transparent color, used for HighlightableButton - addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD); -} - -CAdventureMapButton::CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList &Callback, int x, int y, const std::string &defName,int key, std::vector * add, bool playerColoredButton ) -{ - std::map pom; - pom[0] = Name; - init(Callback, pom, HelpBox, playerColoredButton, defName, add, x, y, key); -} - -CAdventureMapButton::CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList &Callback, config::ButtonInfo *info, int key/*=0*/ ) -{ - std::map pom; - pom[0] = Name; - init(Callback, pom, HelpBox, info->playerColoured, info->defName, &info->additionalDefs, info->x, info->y, key); -} - -CAdventureMapButton::CAdventureMapButton( const std::pair &help, const CFunctionList &Callback, int x, int y, const std::string &defName, int key/*=0*/, std::vector * add /*= nullptr*/, bool playerColoredButton /*= false */ ) -{ - std::map pom; - pom[0] = help.first; - init(Callback, pom, help.second, playerColoredButton, defName, add, x, y, key); -} - -void CAdventureMapButton::onButtonClicked() +void CButton::onButtonClicked() { // debug logging to figure out pressed button (and as result - player actions) in case of crash - logAnim->traceStream() << "Button clicked at " << pos.x << "x" << pos.y; + logAnim->traceStream() << "Button clicked at " << pos.x << "x" << pos.y << ", " << callback.funcs.size() << " functions"; CIntObject * parent = this->parent; std::string prefix = "Parent is"; while (parent) @@ -163,7 +162,7 @@ void CAdventureMapButton::onButtonClicked() callback(); } -void CAdventureMapButton::clickLeft(tribool down, bool previousState) +void CButton::clickLeft(tribool down, bool previousState) { if(isBlocked()) return; @@ -189,13 +188,13 @@ void CAdventureMapButton::clickLeft(tribool down, bool previousState) } } -void CAdventureMapButton::clickRight(tribool down, bool previousState) +void CButton::clickRight(tribool down, bool previousState) { if(down && helpBox.size()) //there is no point to show window with nothing inside... CRClickPopup::createAndPush(helpBox); } -void CAdventureMapButton::hover (bool on) +void CButton::hover (bool on) { if(hoverable) { @@ -208,19 +207,20 @@ void CAdventureMapButton::hover (bool on) if(pressedL && on) setState(PRESSED); - std::string *name = (vstd::contains(hoverTexts,getState())) - ? (&hoverTexts[getState()]) - : (vstd::contains(hoverTexts,0) ? (&hoverTexts[0]) : nullptr); - if(name && name->size() && !isBlocked()) //if there is no name, there is nohing to display also + std::string name = hoverTexts[getState()].empty() + ? hoverTexts[getState()] + : hoverTexts[0]; + + if(!name.empty() && !isBlocked()) //if there is no name, there is nohing to display also { if (LOCPLINT && LOCPLINT->battleInt) //for battle buttons { if(on && LOCPLINT->battleInt->console->alterTxt == "") { - LOCPLINT->battleInt->console->alterTxt = *name; + LOCPLINT->battleInt->console->alterTxt = name; LOCPLINT->battleInt->console->whoSetAlter = 1; } - else if (LOCPLINT->battleInt->console->alterTxt == *name) + else if (LOCPLINT->battleInt->console->alterTxt == name) { LOCPLINT->battleInt->console->alterTxt = ""; LOCPLINT->battleInt->console->whoSetAlter = 0; @@ -229,38 +229,44 @@ void CAdventureMapButton::hover (bool on) else if(GH.statusbar) //for other buttons { if (on) - GH.statusbar->setText(*name); - else if ( GH.statusbar->getText()==(*name) ) + GH.statusbar->setText(name); + else if ( GH.statusbar->getText()==(name) ) GH.statusbar->clear(); } } } -void CAdventureMapButton::init(const CFunctionList &Callback, const std::map &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector * add, int x, int y, int key) +CButton::CButton(Point position, const std::string &defName, const std::pair &help, CFunctionList Callback, int key, bool playerColoredButton): + CKeyShortcut(key), + callback(Callback) { - currentImage = -1; addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD); - callback = Callback; - hoverable = actOnDown = borderEnabled = soundDisabled = false; - CSDL_Ext::colorSetAlpha(borderColor,1);// represents a transparent color, used for HighlightableButton - hoverTexts = Name; - helpBox=HelpBox; - if (key != SDLK_UNKNOWN) - assignedKeys.insert(key); + stateToIndex[0] = 0; + stateToIndex[1] = 1; + stateToIndex[2] = 2; + stateToIndex[3] = 3; - pos.x += x; - pos.y += y; + state=NORMAL; + image = nullptr; + overlay = nullptr; + + currentImage = -1; + hoverable = actOnDown = soundDisabled = false; + hoverTexts[0] = help.first; + helpBox=help.second; + + pos.x += position.x; + pos.y += position.y; if (!defName.empty()) + { imageNames.push_back(defName); - if (add) - for (auto & elem : *add) - imageNames.push_back(elem); - setIndex(0, playerColoredButton); + setIndex(0, playerColoredButton); + } } -void CAdventureMapButton::setIndex(size_t index, bool playerColoredButton) +void CButton::setIndex(size_t index, bool playerColoredButton) { if (index == currentImage || index>=imageNames.size()) return; @@ -268,67 +274,117 @@ void CAdventureMapButton::setIndex(size_t index, bool playerColoredButton) setImage(new CAnimation(imageNames[index]), playerColoredButton); } -void CAdventureMapButton::setImage(CAnimation* anim, bool playerColoredButton, int animFlags) +void CButton::setImage(CAnimation* anim, bool playerColoredButton, int animFlags) { OBJ_CONSTRUCTION_CAPTURING_ALL; - delete image; image = new CAnimImage(anim, getState(), 0, 0, 0, animFlags); if (playerColoredButton) image->playerColored(LOCPLINT->playerID); - - pos.w = image->pos.w; - pos.h = image->pos.h; + pos = image->pos; } -void CAdventureMapButton::setPlayerColor(PlayerColor player) +void CButton::setPlayerColor(PlayerColor player) { if (image) image->playerColored(player); } -void CAdventureMapButton::showAll(SDL_Surface * to) +void CButton::showAll(SDL_Surface * to) { CIntObject::showAll(to); #ifdef VCMI_SDL1 - if (borderEnabled && borderColor.unused == 0) - CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor.r, borderColor.g, borderColor.b)); + if (borderColor && borderColor->unused == 0) + CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor->r, borderColor->g, borderColor->b)); #else - if (borderEnabled && borderColor.a == 0) - CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor.r, borderColor.g, borderColor.b)); + if (borderColor && borderColor->a == 0) + CSDL_Ext::drawBorder(to, pos.x-1, pos.y-1, pos.w+2, pos.h+2, int3(borderColor->r, borderColor->g, borderColor->b)); #endif // 0 } -void CHighlightableButton::select(bool on) +std::pair CButton::tooltip() +{ + return std::pair(); +} + +std::pair CButton::tooltip(const JsonNode & localizedTexts) +{ + return std::make_pair(localizedTexts["label"].String(), localizedTexts["help"].String()); +} + +std::pair CButton::tooltip(const std::string & hover, const std::string & help) +{ + return std::make_pair(hover, help); +} + +CToggleBase::CToggleBase(CFunctionList callback): + callback(callback) +{ +} + +CToggleBase::~CToggleBase() +{ +} + +void CToggleBase::doSelect(bool on) +{ + // for overrides +} + +void CToggleBase::setSelected(bool on) { selected = on; + doSelect(on); +} + +void CToggleBase::activate() +{ + if (canActivate()) + setSelected(!selected); +} + +bool CToggleBase::canActivate() +{ + if (selected && !allowDeselection) + return false; + return true; +} + +void CToggleBase::addCallback(std::function function) +{ + callback.add(function); +} + +CToggleButton::CToggleButton(Point position, const std::string &defName, const std::pair &help, + CFunctionList callback, int key, bool playerColoredButton): + CButton(position, defName, help, 0, key, playerColoredButton), + CToggleBase(callback) +{ +} + +void CToggleButton::doSelect(bool on) +{ if (on) { - borderEnabled = true; setState(HIGHLIGHTED); - callback(); } else { - borderEnabled = false; setState(NORMAL); - callback2(); - } - - if(hoverTexts.size()>1) - { - hover(false); - hover(true); } } -void CHighlightableButton::clickLeft(tribool down, bool previousState) +void CToggleButton::clickLeft(tribool down, bool previousState) { + // force refresh + hover(false); + hover(true); + if(isBlocked()) return; - if (down && !(onlyOn && isHighlighted())) + if (down && canActivate()) { CCS->soundh->playSound(soundBase::button); setState(PRESSED); @@ -337,132 +393,85 @@ void CHighlightableButton::clickLeft(tribool down, bool previousState) if(previousState)//mouse up { if(down == false && getState() == PRESSED) - select(!selected); + setSelected(!selected); else - setState(selected?HIGHLIGHTED:NORMAL); + setSelected(selected); } } -CHighlightableButton::CHighlightableButton( const CFunctionList &onSelect, const CFunctionList &onDeselect, const std::map &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector * add, int x, int y, int key) -: onlyOn(false), selected(false), callback2(onDeselect) +void CToggleGroup::addCallback(std::function callback) { - init(onSelect,Name,HelpBox,playerColoredButton,defName,add,x,y,key); + onChange += callback; } -CHighlightableButton::CHighlightableButton( const std::pair &help, const CFunctionList &onSelect, int x, int y, const std::string &defName, int myid, int key/*=0*/, std::vector * add /*= nullptr*/, bool playerColoredButton /*= false */ ) -: onlyOn(false), selected(false) // TODO: callback2(???) +void CToggleGroup::addToggle(int identifier, CToggleBase* bt) { - ID = myid; - std::map pom; - pom[0] = help.first; - init(onSelect, pom, help.second, playerColoredButton, defName, add, x, y, key); -} - -CHighlightableButton::CHighlightableButton( const std::string &Name, const std::string &HelpBox, const CFunctionList &onSelect, int x, int y, const std::string &defName, int myid, int key/*=0*/, std::vector * add /*= nullptr*/, bool playerColoredButton /*= false */ ) -: onlyOn(false), selected(false) // TODO: callback2(???) -{ - ID = myid; - std::map pom; - pom[0] = Name; - init(onSelect, pom,HelpBox, playerColoredButton, defName, add, x, y, key); -} - -void CHighlightableButtonsGroup::addButton(CHighlightableButton* bt) -{ - if (bt->parent) - bt->parent->removeChild(bt); - addChild(bt); - bt->recActions = defActions;//FIXME: not needed? - - bt->callback += boost::bind(&CHighlightableButtonsGroup::selectionChanged,this,bt->ID); - bt->onlyOn = true; - buttons.push_back(bt); -} - -void CHighlightableButtonsGroup::addButton(const std::map &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid, const CFunctionList &OnSelect, int key) -{ - OBJ_CONSTRUCTION_CAPTURING_ALL; - CHighlightableButton *bt = new CHighlightableButton(OnSelect, 0, tooltip, HelpBox, false, defName, nullptr, x, y, key); - if(musicLike) + if (auto intObj = dynamic_cast(bt)) // hack-ish workagound to avoid diamond problem with inheritance { - bt->setOffset(buttons.size()-3); + if (intObj->parent) + intObj->parent->removeChild(intObj); + addChild(intObj); } - bt->ID = uid; - bt->callback += boost::bind(&CHighlightableButtonsGroup::selectionChanged,this,bt->ID); - bt->onlyOn = true; - buttons.push_back(bt); + + bt->addCallback(boost::bind(&CToggleGroup::selectionChanged, this, identifier)); + bt->allowDeselection = false; + + assert(!buttons.count(identifier)); + buttons[identifier] = bt; } -CHighlightableButtonsGroup::CHighlightableButtonsGroup(const CFunctionList &OnChange, bool musicLikeButtons) +CToggleGroup::CToggleGroup(const CFunctionList &OnChange, bool musicLikeButtons) : onChange(OnChange), musicLike(musicLikeButtons) {} -CHighlightableButtonsGroup::~CHighlightableButtonsGroup() -{ - -} - -void CHighlightableButtonsGroup::select(int id, bool mode) +void CToggleGroup::setSelected(int id) { assert(!buttons.empty()); - CHighlightableButton *bt = buttons.front(); - if(mode) + auto bt = buttons[id]; + if (bt) { - for(auto btn : buttons) - if (btn->ID == id) - bt = btn; + bt->setSelected(true); + selectionChanged(id); } - else - { - bt = buttons[id]; - } - bt->select(true); - selectionChanged(bt->ID); } -void CHighlightableButtonsGroup::selectionChanged(int to) +void CToggleGroup::selectionChanged(int to) { - for(auto & elem : buttons) - if(elem->ID!=to && elem->isHighlighted()) - elem->select(false); + if (buttons.count(selectedID)) + buttons[selectedID]->setSelected(false); + + if (buttons.count(to)) + buttons[to]->setSelected(true); + + selectedID = to; onChange(to); if (parent) parent->redraw(); } -void CHighlightableButtonsGroup::show(SDL_Surface * to) +void CToggleGroup::show(SDL_Surface * to) { if (musicLike) { - for(auto & elem : buttons) - if(elem->isHighlighted()) - elem->show(to); + if (auto intObj = dynamic_cast(buttons[selectedID])) // hack-ish workagound to avoid diamond problem with inheritance + intObj->show(to); } else CIntObject::show(to); } -void CHighlightableButtonsGroup::showAll(SDL_Surface * to) +void CToggleGroup::showAll(SDL_Surface * to) { if (musicLike) { - for(auto & elem : buttons) - if(elem->isHighlighted()) - elem->showAll(to); + if (auto intObj = dynamic_cast(buttons[selectedID])) // hack-ish workagound to avoid diamond problem with inheritance + intObj->showAll(to); } else CIntObject::showAll(to); } -void CHighlightableButtonsGroup::block( ui8 on ) -{ - for(auto & elem : buttons) - { - elem->block(on); - } -} - void CSlider::sliderClicked() { if(!(active & MOVE)) @@ -596,73 +605,53 @@ CSlider::CSlider(int x, int y, int totalw, std::function Moved, int C addUsedEvents(LCLICK | KEYBOARD | WHEEL); strongInterest = true; - - left = new CAdventureMapButton(); - right = new CAdventureMapButton(); - slider = new CAdventureMapButton(); - pos.x += x; pos.y += y; - if(horizontal) - { - left->pos.y = slider->pos.y = right->pos.y = pos.y; - left->pos.x = pos.x; - right->pos.x = pos.x + totalw - 16; - } - else - { - left->pos.x = slider->pos.x = right->pos.x = pos.x; - left->pos.y = pos.y; - right->pos.y = pos.y + totalw - 16; - } - - left->callback = boost::bind(&CSlider::moveLeft,this); - right->callback = boost::bind(&CSlider::moveRight,this); - slider->callback = boost::bind(&CSlider::sliderClicked,this); - left->pos.w = left->pos.h = right->pos.w = right->pos.h = slider->pos.w = slider->pos.h = 16; - if(horizontal) - { - pos.h = 16; - pos.w = totalw; - } - else - { - pos.w = 16; - pos.h = totalw; - } - if(style == 0) { std::string name = horizontal?"IGPCRDIV.DEF":"OVBUTN2.DEF"; //NOTE: this images do not have "blocked" frames. They should be implemented somehow (e.g. palette transform or something...) - //use source def to create custom animations. Format "name.def:123" will load this frame from def file - auto animLeft = new CAnimation(); - animLeft->setCustom(name + ":0", 0); - animLeft->setCustom(name + ":1", 1); - left->setImage(animLeft); + left = new CButton(Point(), name, CButton::tooltip()); + right = new CButton(Point(), name, CButton::tooltip()); + slider = new CButton(Point(), name, CButton::tooltip()); - auto animRight = new CAnimation(); - animRight->setCustom(name + ":2", 0); - animRight->setCustom(name + ":3", 1); - right->setImage(animRight); - - auto animSlider = new CAnimation(); - animSlider->setCustom(name + ":4", 0); - slider->setImage(animSlider); + left->setImageOrder(0, 1, 1, 1); + right->setImageOrder(2, 3, 3, 3); + slider->setImageOrder(4, 4, 4, 4); } else { - left->setImage(new CAnimation(horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF")); - right->setImage(new CAnimation(horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF")); - slider->setImage(new CAnimation("SCNRBSL.DEF")); + left = new CButton(Point(), horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", CButton::tooltip()); + right = new CButton(Point(), horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", CButton::tooltip()); + slider = new CButton(Point(), "SCNRBSL.DEF", CButton::tooltip()); } slider->actOnDown = true; slider->soundDisabled = true; left->soundDisabled = true; right->soundDisabled = true; + if (horizontal) + right->moveBy(Point(totalw - right->pos.w, 0)); + else + right->moveBy(Point(0, totalw - right->pos.h)); + + left->addCallback(boost::bind(&CSlider::moveLeft,this)); + right->addCallback(boost::bind(&CSlider::moveRight,this)); + slider->addCallback(boost::bind(&CSlider::sliderClicked,this)); + + if(horizontal) + { + pos.h = slider->pos.h; + pos.w = totalw; + } + else + { + pos.w = slider->pos.w; + pos.h = totalw; + } + value = -1; moveTo(Value); } diff --git a/client/widgets/Buttons.h b/client/widgets/Buttons.h index 232d313f9..2ab2fc484 100644 --- a/client/widgets/Buttons.h +++ b/client/widgets/Buttons.h @@ -27,9 +27,30 @@ namespace config * */ -/// Base class for buttons. -class CButtonBase : public CKeyShortcut +class ClickableArea : public CIntObject //TODO: derive from LRCLickableArea? Or somehow use its right-click/hover data? { + CFunctionList callback; + + CIntObject * area; + +protected: + void onClick(); + +public: + ClickableArea(CIntObject * object, CFunctionList callback); + + void addCallback(std::function callback); + void setArea(CIntObject * object); + + void clickLeft(tribool down, bool previousState) override; +}; + +/// Typical Heroes 3 button which can be inactive or active and can +/// hold further information if you right-click it +class CButton : public CKeyShortcut +{ + CFunctionList callback; + public: enum ButtonState { @@ -39,110 +60,134 @@ public: HIGHLIGHTED=3 }; private: - int bitmapOffset; // base offset of visible bitmap from animation + std::vector imageNames;//store list of images that can be used by this button + size_t currentImage; ButtonState state;//current state of button from enum -public: - bool swappedImages,//fix for some buttons: normal and pressed image are swapped - keepFrame; // don't change visual representation - - void addOverlay(CIntObject * newOverlay); - void addTextOverlay(const std::string &Text, EFonts font, SDL_Color color = Colors::WHITE); - - void update();//to refresh button after image or text change - - void setOffset(int newOffset); - void setState(ButtonState newState); - ButtonState getState(); - - //just to make code clearer - void block(bool on); - bool isBlocked(); - bool isHighlighted(); + std::array stateToIndex; // mapping of button state to index of frame in animation + std::array hoverTexts; //text for statusbar + std::string helpBox; //for right-click help CAnimImage * image; //image for this button CIntObject * overlay;//object-overlay - - CButtonBase(); //c-tor - virtual ~CButtonBase(); //d-tor -}; - -/// Typical Heroes 3 button which can be inactive or active and can -/// hold further information if you right-click it -class CAdventureMapButton : public CButtonBase -{ - std::vector imageNames;//store list of images that can be used by this button - size_t currentImage; - +protected: void onButtonClicked(); // calls callback + void update();//to refresh button after image or text change + + void setState(ButtonState newState); + ButtonState getState(); + public: - std::map hoverTexts; //text for statusbar - std::string helpBox; //for right-click help - CFunctionList callback; bool actOnDown,//runs when mouse is pressed down over it, not when up hoverable,//if true, button will be highlighted when hovered - borderEnabled, soundDisabled; - SDL_Color borderColor; - void clickRight(tribool down, bool previousState); - virtual void clickLeft(tribool down, bool previousState); - void hover (bool on); + boost::optional borderColor; - CAdventureMapButton(); //c-tor - CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList &Callback, int x, int y, const std::string &defName, int key=0, std::vector * add = nullptr, bool playerColoredButton = false );//c-tor - CAdventureMapButton( const std::pair &help, const CFunctionList &Callback, int x, int y, const std::string &defName, int key=0, std::vector * add = nullptr, bool playerColoredButton = false );//c-tor - CAdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList &Callback, config::ButtonInfo *info, int key=0);//c-tor + void addCallback(std::function callback); + void addOverlay(CIntObject * newOverlay); + void addTextOverlay(const std::string &Text, EFonts font, SDL_Color color = Colors::WHITE); - void init(const CFunctionList &Callback, const std::map &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector * add, int x, int y, int key ); + void addImage(std::string filename); + void addHoverText(ButtonState state, std::string text); + void setImageOrder(int state1, int state2, int state3, int state4); + void block(bool on); + + /// State modifiers + bool isBlocked(); + bool isHighlighted(); + + /// Constructor + CButton(Point position, const std::string &defName, const std::pair &help, + CFunctionList Callback = 0, int key=0, bool playerColoredButton = false ); + + /// Appearance modifiers void setIndex(size_t index, bool playerColoredButton=false); void setImage(CAnimation* anim, bool playerColoredButton=false, int animFlags=0); void setPlayerColor(PlayerColor player); - void showAll(SDL_Surface * to); + + /// CIntObject overrides + void clickRight(tribool down, bool previousState) override; + void clickLeft(tribool down, bool previousState) override; + void hover (bool on) override; + void showAll(SDL_Surface * to) override; + + static std::pair tooltip(); + static std::pair tooltip(const JsonNode & localizedTexts); + static std::pair tooltip(const std::string & hover, const std::string & help = ""); }; -/// A button which can be selected/deselected -class CHighlightableButton - : public CAdventureMapButton +class CToggleBase { + CFunctionList callback; +protected: + + bool selected; + + virtual void doSelect(bool on); + + // returns true if toggle can change its state + bool canActivate(); + public: - CHighlightableButton(const CFunctionList &onSelect, const CFunctionList &onDeselect, const std::map &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector * add, int x, int y, int key=0); - CHighlightableButton(const std::pair &help, const CFunctionList &onSelect, int x, int y, const std::string &defName, int myid, int key=0, std::vector * add = nullptr, bool playerColoredButton = false );//c-tor - CHighlightableButton(const std::string &Name, const std::string &HelpBox, const CFunctionList &onSelect, int x, int y, const std::string &defName, int myid, int key=0, std::vector * add = nullptr, bool playerColoredButton = false );//c-tor - bool onlyOn;//button can not be de-selected - bool selected;//state of highlightable button - int ID; //for identification - CFunctionList callback2; //when de-selecting - void select(bool on); - void clickLeft(tribool down, bool previousState); + bool allowDeselection; + + CToggleBase(CFunctionList callback); + virtual ~CToggleBase(); + + void activate(); + void setSelected(bool on); + + void addCallback(std::function callback); }; -/// A group of buttons where one button can be selected -class CHighlightableButtonsGroup : public CIntObject +class ClickableToggle : public ClickableArea, public CToggleBase { public: + ClickableToggle(CIntObject * object, CFunctionList selectFun, CFunctionList deselectFun); + void clickLeft(tribool down, bool previousState) override; +}; + +/// A button which can be selected/deselected, checkbox +class CToggleButton : public CButton, public CToggleBase +{ + void doSelect(bool on) override; +public: + CToggleButton(Point position, const std::string &defName, const std::pair &help, + CFunctionList Callback = 0, int key=0, bool playerColoredButton = false ); + void clickLeft(tribool down, bool previousState) override; + + // bring overrides into scope + using CButton::addCallback; + using CToggleBase::addCallback; +}; + +class CToggleGroup : public CIntObject +{ CFunctionList onChange; //called when changing selected button with new button's id - std::vector buttons; - bool musicLike; //determines the behaviour of this group - //void addButton(const std::map &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid); - void addButton(CHighlightableButton* bt);//add existing button, it'll be deleted by CHighlightableButtonsGroup destructor - void addButton(const std::map &tooltip, const std::string &HelpBox, const std::string &defName, int x, int y, int uid, const CFunctionList &OnSelect=0, int key=0); //creates new button - CHighlightableButtonsGroup(const CFunctionList & OnChange, bool musicLikeButtons = false); - ~CHighlightableButtonsGroup(); - void select(int id, bool mode); //mode==0: id is serial; mode==1: id is unique button id + int selectedID; + bool musicLike; //determines the behaviour of this group void selectionChanged(int to); +public: + std::map buttons; + + CToggleGroup(const CFunctionList & OnChange, bool musicLikeButtons = false); + + void addCallback(std::function callback); + void addToggle(int index, CToggleBase * button); + void setSelected(int id); + void show(SDL_Surface * to); void showAll(SDL_Surface * to); - void block(ui8 on); }; /// A typical slider which can be orientated horizontally/vertically. class CSlider : public CIntObject { public: - CAdventureMapButton *left, *right, *slider; //if vertical then left=up + CButton *left, *right, *slider; //if vertical then left=up int capacity;//how many elements can be active at same time (e.g. hero list = 5) int amount; //total amount of elements (e.g. hero list = 0-8) int positions; //number of highest position (0 if there is only one) diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index aee62459a..cca81355c 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -657,7 +657,7 @@ void CArtifactsOfHero::eraseSlotData (CArtPlace* artPlace, ArtifactPosition slot } CArtifactsOfHero::CArtifactsOfHero(std::vector ArtWorn, std::vector Backpack, - CAdventureMapButton *leftScroll, CAdventureMapButton *rightScroll, bool createCommonPart): + CButton *leftScroll, CButton *rightScroll, bool createCommonPart): curHero(nullptr), artWorn(ArtWorn), backpack(Backpack), @@ -685,8 +685,8 @@ CArtifactsOfHero::CArtifactsOfHero(std::vector ArtWorn, std::vector eraseSlotData(backpack[s], ArtifactPosition(GameConstants::BACKPACK_START + s)); } - leftArtRoll->callback += boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1); - rightArtRoll->callback += boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1); + leftArtRoll->addCallback(boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1)); + rightArtRoll->addCallback(boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1)); } CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart /*= false*/) @@ -732,8 +732,8 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart backpack.push_back(add); } - leftArtRoll = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,-1), 379, 364, "hsbtns3.def", SDLK_LEFT); - rightArtRoll = new CAdventureMapButton(std::string(), std::string(), boost::bind(&CArtifactsOfHero::scrollBackpack,this,+1), 632, 364, "hsbtns5.def", SDLK_RIGHT); + leftArtRoll = new CButton(Point(379, 364), "hsbtns3.def", CButton::tooltip(), [&]{ scrollBackpack(-1);}, SDLK_LEFT); + rightArtRoll = new CButton(Point(632, 364), "hsbtns5.def", CButton::tooltip(), [&]{ scrollBackpack(+1);}, SDLK_RIGHT); } CArtifactsOfHero::~CArtifactsOfHero() diff --git a/client/widgets/CArtifactHolder.h b/client/widgets/CArtifactHolder.h index 5def9a37f..89ea5e7a6 100644 --- a/client/widgets/CArtifactHolder.h +++ b/client/widgets/CArtifactHolder.h @@ -15,7 +15,7 @@ class CArtifactsOfHero; class CAnimImage; -class CAdventureMapButton; +class CButton; struct ArtifactLocation; @@ -108,7 +108,7 @@ public: bool updateState; // Whether the commonInfo should be updated on setHero or not. - CAdventureMapButton * leftArtRoll, * rightArtRoll; + CButton * leftArtRoll, * rightArtRoll; bool allowedAssembling; std::multiset artifactsOnAltar; //artifacts id that are technically present in backpack but in GUI are moved to the altar - they'll be omitted in backpack slots std::function highlightModeCallback; //if set, clicking on art place doesn't pick artifact but highlights the slot and calls this function @@ -138,7 +138,7 @@ public: CArtifactsOfHero(const Point& position, bool createCommonPart = false); //Alternative constructor, used if custom artifacts positioning required (Kingdom interface) CArtifactsOfHero(std::vector ArtWorn, std::vector Backpack, - CAdventureMapButton *leftScroll, CAdventureMapButton *rightScroll, bool createCommonPart = false); + CButton *leftScroll, CButton *rightScroll, bool createCommonPart = false); ~CArtifactsOfHero(); //d-tor void updateParentWindow(); friend class CArtPlace; diff --git a/client/widgets/CGarrisonInt.cpp b/client/widgets/CGarrisonInt.cpp index 73209ca99..e4ddb97a8 100644 --- a/client/widgets/CGarrisonInt.cpp +++ b/client/widgets/CGarrisonInt.cpp @@ -339,7 +339,7 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, int stackCount->setText(boost::lexical_cast(myStack->count)); } -void CGarrisonInt::addSplitBtn(CAdventureMapButton * button) +void CGarrisonInt::addSplitBtn(CButton * button) { addChild(button); button->recActions = defActions; @@ -482,11 +482,11 @@ CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance garr = new CGarrisonInt(92, 127, 4, Point(0,96), background->bg, Point(93,127), up, down, removableUnits); { - CAdventureMapButton *split = new CAdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),88,314,"IDV6432.DEF"); + CButton *split = new CButton(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&]{ garr->splitClick(); } ); removeChild(split); garr->addSplitBtn(split); } - quit = new CAdventureMapButton(CGI->generaltexth->tcommands[8],"",boost::bind(&CGarrisonWindow::close,this),399,314,"IOK6432.DEF",SDLK_RETURN); + quit = new CButton(Point(399, 314), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[8], ""), [&]{ close(); }, SDLK_RETURN); std::string titleText; if (garr->armedObjs[1]->tempOwner == garr->armedObjs[0]->tempOwner) diff --git a/client/widgets/CGarrisonInt.h b/client/widgets/CGarrisonInt.h index 8ede66ed4..df32cf424 100644 --- a/client/widgets/CGarrisonInt.h +++ b/client/widgets/CGarrisonInt.h @@ -13,7 +13,7 @@ */ class CGarrisonInt; -class CAdventureMapButton; +class CButton; class CArmedInstance; class CAnimImage; class CCreatureSet; @@ -62,7 +62,7 @@ public: int interx; //space between slots Point garOffset; //offset between garrisons (not used if only one hero) - std::vector splitButtons; //may be empty if no buttons + std::vector splitButtons; //may be empty if no buttons SlotID p2; //TODO: comment me int shiftPos;//1st slot of the second row, set shiftPoint for effect @@ -80,7 +80,7 @@ public: //const CArmedInstance *oup, *odown; //upper and lower garrisons (heroes or towns) void setArmy(const CArmedInstance *army, bool bottomGarrison); - void addSplitBtn(CAdventureMapButton * button); + void addSplitBtn(CButton * button); void createSet(std::vector &ret, const CCreatureSet * set, int posX, int distance, int posY, int Upg ); void createSlots(); @@ -116,7 +116,7 @@ public: class CGarrisonWindow : public CWindowObject, public CWindowWithGarrison { public: - CAdventureMapButton * quit; + CButton * quit; CGarrisonWindow(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits); //c-tor }; diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index af997b11c..412e1de7c 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -370,35 +370,6 @@ void CResDataBar::showAll(SDL_Surface * to) CAdvMapInt::CAdvMapInt(): minimap(Rect(ADVOPT.minimapX, ADVOPT.minimapY, ADVOPT.minimapW, ADVOPT.minimapH)), statusbar(ADVOPT.statusbarX,ADVOPT.statusbarY,ADVOPT.statusbarG), -kingOverview(CGI->generaltexth->zelp[293].first,CGI->generaltexth->zelp[293].second, - boost::bind(&CAdvMapInt::fshowOverview,this),&ADVOPT.kingOverview, SDLK_k), - -underground(CGI->generaltexth->zelp[294].first,CGI->generaltexth->zelp[294].second, - boost::bind(&CAdvMapInt::fswitchLevel,this),&ADVOPT.underground, SDLK_u), - -questlog(CGI->generaltexth->zelp[295].first,CGI->generaltexth->zelp[295].second, - boost::bind(&CAdvMapInt::fshowQuestlog,this),&ADVOPT.questlog, SDLK_q), - -sleepWake(CGI->generaltexth->zelp[296].first,CGI->generaltexth->zelp[296].second, - boost::bind(&CAdvMapInt::fsleepWake,this), &ADVOPT.sleepWake, SDLK_w), - -moveHero(CGI->generaltexth->zelp[297].first,CGI->generaltexth->zelp[297].second, - boost::bind(&CAdvMapInt::fmoveHero,this), &ADVOPT.moveHero, SDLK_m), - -spellbook(CGI->generaltexth->zelp[298].first,CGI->generaltexth->zelp[298].second, - boost::bind(&CAdvMapInt::fshowSpellbok,this), &ADVOPT.spellbook, SDLK_c), - -advOptions(CGI->generaltexth->zelp[299].first,CGI->generaltexth->zelp[299].second, - boost::bind(&CAdvMapInt::fadventureOPtions,this), &ADVOPT.advOptions, SDLK_a), - -sysOptions(CGI->generaltexth->zelp[300].first,CGI->generaltexth->zelp[300].second, - boost::bind(&CAdvMapInt::fsystemOptions,this), &ADVOPT.sysOptions, SDLK_o), - -nextHero(CGI->generaltexth->zelp[301].first,CGI->generaltexth->zelp[301].second, - boost::bind(&CAdvMapInt::fnextHero,this), &ADVOPT.nextHero, SDLK_h), - -endTurn(CGI->generaltexth->zelp[302].first,CGI->generaltexth->zelp[302].second, - boost::bind(&CAdvMapInt::fendTurn,this), &ADVOPT.endTurn, SDLK_e), heroList(ADVOPT.hlistSize, Point(ADVOPT.hlistX, ADVOPT.hlistY), ADVOPT.hlistAU, ADVOPT.hlistAD), townList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD), @@ -427,9 +398,28 @@ infoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192) ) gems.push_back(CDefHandler::giveDef(ADVOPT.gemG[g])); } + auto makeButton = [&] (int textID, std::function callback, config::ButtonInfo info, int key) -> CButton * + { + auto button = new CButton(Point(info.x, info.y), info.defName, CGI->generaltexth->zelp[textID], callback, key, info.playerColoured); + + for (auto image : info.additionalDefs) + button->addImage(image); + return button; + }; + + kingOverview = makeButton(293, boost::bind(&CAdvMapInt::fshowOverview,this), ADVOPT.kingOverview, SDLK_k); + underground = makeButton(294, boost::bind(&CAdvMapInt::fswitchLevel,this), ADVOPT.underground, SDLK_u); + questlog = makeButton(295, boost::bind(&CAdvMapInt::fshowQuestlog,this), ADVOPT.questlog, SDLK_q); + sleepWake = makeButton(296, boost::bind(&CAdvMapInt::fsleepWake,this), ADVOPT.sleepWake, SDLK_w); + moveHero = makeButton(297, boost::bind(&CAdvMapInt::fmoveHero,this), ADVOPT.moveHero, SDLK_m); + spellbook = makeButton(298, boost::bind(&CAdvMapInt::fshowSpellbok,this), ADVOPT.spellbook, SDLK_c); + advOptions = makeButton(299, boost::bind(&CAdvMapInt::fadventureOPtions,this), ADVOPT.advOptions, SDLK_a); + sysOptions = makeButton(300, boost::bind(&CAdvMapInt::fsystemOptions,this), ADVOPT.sysOptions, SDLK_o); + nextHero = makeButton(301, boost::bind(&CAdvMapInt::fnextHero,this), ADVOPT.nextHero, SDLK_h); + endTurn = makeButton(302, boost::bind(&CAdvMapInt::fendTurn,this), ADVOPT.endTurn, SDLK_e); setPlayer(LOCPLINT->playerID); - underground.block(!CGI->mh->map->twoLevel); + underground->block(!CGI->mh->map->twoLevel); addUsedEvents(MOVE); } @@ -452,14 +442,14 @@ void CAdvMapInt::fswitchLevel() if (position.z) { position.z--; - underground.setIndex(0,true); - underground.showAll(screenBuf); + underground->setIndex(0,true); + underground->showAll(screenBuf); } else { - underground.setIndex(1,true); + underground->setIndex(1,true); position.z++; - underground.showAll(screenBuf); + underground->showAll(screenBuf); } updateScreen = true; minimap.setLevel(position.z); @@ -544,14 +534,13 @@ void CAdvMapInt::fendTurn() void CAdvMapInt::updateSleepWake(const CGHeroInstance *h) { - sleepWake.block(!h); + sleepWake->block(!h); if (!h) return; bool state = isHeroSleeping(h); - sleepWake.setIndex(state ? 1 : 0, true); - sleepWake.assignedKeys.clear(); - sleepWake.assignedKeys.insert(state ? SDLK_w : SDLK_z); - sleepWake.update(); + sleepWake->setIndex(state ? 1 : 0, true); + sleepWake->assignedKeys.clear(); + sleepWake->assignedKeys.insert(state ? SDLK_w : SDLK_z); } void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath) @@ -561,10 +550,10 @@ void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath) hasPath = LOCPLINT->paths[h].nodes.size() ? true : false; if (!h) { - moveHero.block(true); + moveHero->block(true); return; } - moveHero.block(!hasPath || (h->movement == 0)); + moveHero->block(!hasPath || (h->movement == 0)); } int CAdvMapInt::getNextHeroIndex(int startIndex) @@ -594,12 +583,12 @@ void CAdvMapInt::updateNextHero(const CGHeroInstance *h) int next = getNextHeroIndex(start); if (next < 0) { - nextHero.block(true); + nextHero->block(true); return; } const CGHeroInstance *nextH = LOCPLINT->wanderingHeroes[next]; bool noActiveHeroes = (next == start) && ((nextH->movement == 0) || isHeroSleeping(nextH)); - nextHero.block(noActiveHeroes); + nextHero->block(noActiveHeroes); } void CAdvMapInt::activate() @@ -612,16 +601,16 @@ void CAdvMapInt::activate() GH.statusbar = &statusbar; if(!duringAITurn) { - kingOverview.activate(); - underground.activate(); - questlog.activate(); - sleepWake.activate(); - moveHero.activate(); - spellbook.activate(); - sysOptions.activate(); - advOptions.activate(); - nextHero.activate(); - endTurn.activate(); + kingOverview->activate(); + underground->activate(); + questlog->activate(); + sleepWake->activate(); + moveHero->activate(); + spellbook->activate(); + sysOptions->activate(); + advOptions->activate(); + nextHero->activate(); + endTurn->activate(); minimap.activate(); heroList.activate(); @@ -642,16 +631,16 @@ void CAdvMapInt::deactivate() scrollingDir = 0; CCS->curh->changeGraphic(ECursor::ADVENTURE,0); - kingOverview.deactivate(); - underground.deactivate(); - questlog.deactivate(); - sleepWake.deactivate(); - moveHero.deactivate(); - spellbook.deactivate(); - advOptions.deactivate(); - sysOptions.deactivate(); - nextHero.deactivate(); - endTurn.deactivate(); + kingOverview->deactivate(); + underground->deactivate(); + questlog->deactivate(); + sleepWake->deactivate(); + moveHero->deactivate(); + spellbook->deactivate(); + advOptions->deactivate(); + sysOptions->deactivate(); + nextHero->deactivate(); + endTurn->deactivate(); minimap.deactivate(); heroList.deactivate(); townList.deactivate(); @@ -668,16 +657,16 @@ void CAdvMapInt::showAll(SDL_Surface * to) if(state != INGAME) return; - kingOverview.showAll(to); - underground.showAll(to); - questlog.showAll(to); - sleepWake.showAll(to); - moveHero.showAll(to); - spellbook.showAll(to); - advOptions.showAll(to); - sysOptions.showAll(to); - nextHero.showAll(to); - endTurn.showAll(to); + kingOverview->showAll(to); + underground->showAll(to); + questlog->showAll(to); + sleepWake->showAll(to); + moveHero->showAll(to); + spellbook->showAll(to); + advOptions->showAll(to); + sysOptions->showAll(to); + nextHero->showAll(to); + endTurn->showAll(to); minimap.showAll(to); heroList.showAll(to); @@ -788,8 +777,8 @@ void CAdvMapInt::centerOn(int3 on) position = on; updateScreen=true; - underground.setIndex(on.z,true); //change underground switch button image - underground.redraw(); + underground->setIndex(on.z,true); //change underground switch button image + underground->redraw(); if (switchedLevels) minimap.setLevel(position.z); } @@ -1103,16 +1092,16 @@ void CAdvMapInt::setPlayer(PlayerColor Player) player = Player; graphics->blueToPlayersAdv(bg,player); - kingOverview.setPlayerColor(player); - underground.setPlayerColor(player); - questlog.setPlayerColor(player); - sleepWake.setPlayerColor(player); - moveHero.setPlayerColor(player); - spellbook.setPlayerColor(player); - sysOptions.setPlayerColor(player); - advOptions.setPlayerColor(player); - nextHero.setPlayerColor(player); - endTurn.setPlayerColor(player); + kingOverview->setPlayerColor(player); + underground->setPlayerColor(player); + questlog->setPlayerColor(player); + sleepWake->setPlayerColor(player); + moveHero->setPlayerColor(player); + spellbook->setPlayerColor(player); + sysOptions->setPlayerColor(player); + advOptions->setPlayerColor(player); + nextHero->setPlayerColor(player); + endTurn->setPlayerColor(player); graphics->blueToPlayersAdv(resdatabar.bg,player); //heroList.updateHList(); @@ -1536,19 +1525,20 @@ CAdventureOptions::CAdventureOptions(): { OBJ_CONSTRUCTION_CAPTURING_ALL; - exit = new CAdventureMapButton("","",boost::bind(&CAdventureOptions::close, this), 204, 313, "IOK6432.DEF",SDLK_RETURN); + exit = new CButton(Point(204, 313), "IOK6432.DEF", CButton::tooltip(), boost::bind(&CAdventureOptions::close, this), SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); - scenInfo = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 198, "ADVINFO.DEF",SDLK_i); - scenInfo->callback += CAdventureOptions::showScenarioInfo; - //viewWorld = new CAdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN); + scenInfo = new CButton(Point(24, 198), "ADVINFO.DEF", CButton::tooltip(), [&]{ close(); }, SDLK_i); + scenInfo->addCallback(CAdventureOptions::showScenarioInfo); - puzzle = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 81, "ADVPUZ.DEF"); - puzzle->callback += boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT); + //viewWorld = new CButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 204, 313, "IOK6432.DEF",SDLK_RETURN); - dig = new CAdventureMapButton("","", boost::bind(&CAdventureOptions::close, this), 24, 139, "ADVDIG.DEF"); + puzzle = new CButton(Point(24, 81), "ADVPUZ.DEF", CButton::tooltip(), [&]{ close(); }, SDLK_p); + puzzle->addCallback(boost::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT)); + + dig = new CButton(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&]{ close(); }, SDLK_d); if(const CGHeroInstance *h = adventureInt->curHero()) - dig->callback += boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h); + dig->addCallback(boost::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h)); else dig->block(true); } diff --git a/client/windows/CAdvmapInterface.h b/client/windows/CAdvmapInterface.h index 9701562ee..6a77061b9 100644 --- a/client/windows/CAdvmapInterface.h +++ b/client/windows/CAdvmapInterface.h @@ -32,7 +32,7 @@ class IShipyard; class CAdventureOptions : public CWindowObject { public: - CAdventureMapButton *exit, *viewWorld, *puzzle, *dig, *scenInfo, *replay; + CButton *exit, *viewWorld, *puzzle, *dig, *scenInfo, *replay; CAdventureOptions(); static void showScenarioInfo(); @@ -110,16 +110,16 @@ public: CMinimap minimap; CGStatusBar statusbar; - CAdventureMapButton kingOverview,//- kingdom overview - underground,//- underground switch - questlog,//- questlog - sleepWake, //- sleep/wake hero - moveHero, //- move hero - spellbook,//- spellbook - advOptions, //- adventure options - sysOptions,//- system options - nextHero, //- next hero - endTurn;//- end turn + CButton * kingOverview; + CButton * underground; + CButton * questlog; + CButton * sleepWake; + CButton * moveHero; + CButton * spellbook; + CButton * advOptions; + CButton * sysOptions; + CButton * nextHero; + CButton * endTurn; CTerrainRect terrain; //visible terrain CResDataBar resdatabar; diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 9b2346187..430f5d8d4 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -843,7 +843,7 @@ void CCastleBuildings::enterTownHall() else { LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[673]); - (dynamic_cast(GH.topInt()))->buttons[0]->callback += boost::bind(&CCastleBuildings::openTownHall, this); + dynamic_cast(GH.topInt())->buttons[0]->addCallback(boost::bind(&CCastleBuildings::openTownHall, this)); } } else @@ -888,12 +888,12 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst income = new CLabel(195, 443, FONT_SMALL, CENTER); icon = new CAnimImage("ITPT", 0, 0, 15, 387); - exit = new CAdventureMapButton(CGI->generaltexth->tcommands[8], "", boost::bind(&CCastleInterface::close,this), 744, 544, "TSBTNS", SDLK_RETURN); + exit = new CButton(Point(744, 544), "TSBTNS", CButton::tooltip(CGI->generaltexth->tcommands[8]), [&]{close();}, SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); - exit->setOffset(4); + exit->setImageOrder(4, 5, 6, 7); - split = new CAdventureMapButton(CGI->generaltexth->tcommands[3], "", boost::bind(&CGarrisonInt::splitClick,garr), 744, 382, "TSBTNS.DEF"); - split->callback += boost::bind(&HeroSlots::splitClicked, heroes); + split = new CButton(Point(744, 382), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), [&]{garr->splitClick();}); + split->addCallback(boost::bind(&HeroSlots::splitClicked, heroes)); garr->addSplitBtn(split); Rect barRect(9, 182, 732, 18); @@ -1311,8 +1311,7 @@ CHallInterface::CHallInterface(const CGTownInstance *Town): statusBar = new CGStatusBar(new CPicture(*background, barRect, 5, 556, false)); title = new CLabel(399, 12, FONT_MEDIUM, CENTER, Colors::WHITE, town->town->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->Name()); - exit = new CAdventureMapButton(CGI->generaltexth->hcommands[8], "", - boost::bind(&CHallInterface::close,this), 748, 556, "TPMAGE1.DEF", SDLK_RETURN); + exit = new CButton(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->hcommands[8]), [&]{close();}, SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); auto & boxList = town->town->clientInfo.hallSlots; @@ -1414,15 +1413,14 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin if(!rightClick) { //normal window - buy = new CAdventureMapButton(boost::str(boost::format(CGI->generaltexth->allTexts[595]) % building->Name()), - "", boost::bind(&CBuildWindow::buyFunc,this), 45, 446,"IBUY30", SDLK_RETURN); - buy->borderColor = Colors::METALLIC_GOLD; - buy->borderEnabled = true; + std::string tooltipYes = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % building->Name()); + std::string tooltipNo = boost::str(boost::format(CGI->generaltexth->allTexts[596]) % building->Name()); - cancel = new CAdventureMapButton(boost::str(boost::format(CGI->generaltexth->allTexts[596]) % building->Name()), - "", boost::bind(&CBuildWindow::close,this), 290, 445, "ICANCEL", SDLK_ESCAPE); + buy = new CButton(Point(45, 446), "IBUY30", CButton::tooltip(tooltipYes), [&]{ buyFunc(); }, SDLK_RETURN); + buy->borderColor = Colors::METALLIC_GOLD; + + cancel = new CButton(Point(290, 445), "ICANCEL", CButton::tooltip(tooltipNo), [&] { close();}, SDLK_ESCAPE); cancel->borderColor = Colors::METALLIC_GOLD; - cancel->borderEnabled = true; buy->block(state!=7 || LOCPLINT->playerID != town->tempOwner); } } @@ -1452,7 +1450,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town): title = new CLabel(400, 12, FONT_BIG, CENTER, Colors::WHITE, fortBuilding->Name()); std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->Name()); - exit = new CAdventureMapButton(text, "", boost::bind(&CFortScreen::close,this) ,748, 556, "TPMAGE1", SDLK_RETURN); + exit = new CButton(Point(748, 556), "TPMAGE1", CButton::tooltip(text), [&]{ close(); }, SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); std::vector positions; @@ -1651,7 +1649,6 @@ void CFortScreen::RecruitArea::clickRight(tribool down, bool previousState) CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem) :CWindowObject(BORDERED,imagem) { - OBJ_CONSTRUCTION_CAPTURING_ALL; window = new CPicture(owner->town->town->clientInfo.guildWindow , 332, 76); @@ -1662,7 +1659,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem) Rect barRect(7, 556, 737, 18); statusBar = new CGStatusBar(new CPicture(*background, barRect, 7, 556, false)); - exit = new CAdventureMapButton(CGI->generaltexth->allTexts[593],"",boost::bind(&CMageGuildScreen::close,this), 748, 556,"TPMAGE1.DEF",SDLK_RETURN); + exit = new CButton(Point(748, 556), "TPMAGE1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[593]), [&]{ close(); }, SDLK_RETURN); exit->assignedKeys.insert(SDLK_ESCAPE); std::vector > positions; @@ -1739,13 +1736,13 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art boost::lexical_cast(CGI->arth->artifacts[aid]->price)); std::string text = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % creature->nameSing); - buy = new CAdventureMapButton(text,"",boost::bind(&CBlacksmithDialog::close, this), 42, 312,"IBUY30.DEF",SDLK_RETURN); + buy = new CButton(Point(42, 312), "IBUY30.DEF", CButton::tooltip(text), [&]{ close(); }, SDLK_RETURN); text = boost::str(boost::format(CGI->generaltexth->allTexts[596]) % creature->nameSing); - cancel = new CAdventureMapButton(text,"",boost::bind(&CBlacksmithDialog::close, this), 224, 312,"ICANCEL.DEF",SDLK_ESCAPE); + cancel = new CButton(Point(224, 312), "ICANCEL.DEF", CButton::tooltip(text), [&]{ close(); }, SDLK_ESCAPE); if(possible) - buy->callback += [=]{ LOCPLINT->cb->buyArtifact(LOCPLINT->cb->getHero(hid),aid); }; + buy->addCallback([=]{ LOCPLINT->cb->buyArtifact(LOCPLINT->cb->getHero(hid),aid); }); else buy->block(true); diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index e986da001..b8e9775c5 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -3,7 +3,7 @@ #include "../widgets/CGarrisonInt.h" #include "../widgets/Images.h" -class CAdventureMapButton; +class CButton; class CBuilding; class CCastleBuildings; class CCreaturePic; @@ -203,8 +203,8 @@ class CCastleInterface : public CWindowObject, public CWindowWithGarrison CTownInfo *hall, *fort; - CAdventureMapButton *exit; - CAdventureMapButton *split; + CButton *exit; + CButton *split; std::vector creainfo;//small icons of creatures (bottom-left corner); @@ -260,7 +260,7 @@ class CHallInterface : public CWindowObject CLabel *title; CGStatusBar *statusBar; CMinorResDataBar * resdatabar; - CAdventureMapButton *exit; + CButton *exit; public: CHallInterface(const CGTownInstance * Town); //c-tor @@ -272,8 +272,8 @@ class CBuildWindow: public CWindowObject const CGTownInstance *town; const CBuilding *building; - CAdventureMapButton *buy; - CAdventureMapButton *cancel; + CButton *buy; + CButton *cancel; std::string getTextForState(int state); void buyFunc(); @@ -328,7 +328,7 @@ class CFortScreen : public CWindowObject std::vector recAreas; CMinorResDataBar * resdatabar; CGStatusBar *statusBar; - CAdventureMapButton *exit; + CButton *exit; std::string getBgName(const CGTownInstance *town); @@ -353,7 +353,7 @@ class CMageGuildScreen : public CWindowObject void hover(bool on); }; CPicture *window; - CAdventureMapButton *exit; + CButton *exit; std::vector spells; CMinorResDataBar * resdatabar; CGStatusBar *statusBar; @@ -365,7 +365,7 @@ public: /// The blacksmith window where you can buy available in town war machine class CBlacksmithDialog : public CWindowObject { - CAdventureMapButton *buy, *cancel; + CButton *buy, *cancel; CPicture *animBG; CCreatureAnim * anim; CLabel * title; diff --git a/client/windows/CCreatureWindow.cpp b/client/windows/CCreatureWindow.cpp index 104750d75..846744b7a 100644 --- a/client/windows/CCreatureWindow.cpp +++ b/client/windows/CCreatureWindow.cpp @@ -196,9 +196,9 @@ void CStackWindow::setStackArtifact(const CArtifactInstance * art, Point artPos) if (info->owner) { - stackArtifactButton = new CAdventureMapButton(text["label"].String(), text["help"].String(),[=]{ - removeStackArtifact(ArtifactPosition::CREATURE_SLOT); - }, artPos.x - 2 , artPos.y + 46, "stackWindow/cancelButton"); + stackArtifactButton = new CButton(Point(artPos.x - 2 , artPos.y + 46), "stackWindow/cancelButton", + CButton::tooltip(text), + [=]{ removeStackArtifact(ArtifactPosition::CREATURE_SLOT); }); } } @@ -463,8 +463,8 @@ void CStackWindow::CWindowSection::createCommanderAbilities() }, Point(38, 3+pos.h), Point(63, 0), 6, abilitiesCount); - auto leftBtn = new CAdventureMapButton("", "", [=]{ list->moveToPrev(); }, 10, pos.h + 6, "hsbtns3.def", SDLK_LEFT); - auto rightBtn = new CAdventureMapButton("", "", [=]{ list->moveToNext(); }, 411, pos.h + 6, "hsbtns5.def", SDLK_RIGHT); + auto leftBtn = new CButton(Point(10, pos.h + 6), "hsbtns3.def", CButton::tooltip(), [=]{ list->moveToPrev(); }, SDLK_LEFT); + auto rightBtn = new CButton(Point(411, pos.h + 6), "hsbtns5.def", CButton::tooltip(), [=]{ list->moveToNext(); }, SDLK_RIGHT); if (abilitiesCount <= 6) { @@ -531,7 +531,7 @@ void CStackWindow::CWindowSection::createButtonPanel() { LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[12], onDismiss, 0, false, std::vector()); }; - new CAdventureMapButton(CGI->generaltexth->zelp[445], onClick, 5, 5,"IVIEWCR2.DEF",SDLK_d); + new CButton(Point(5, 5),"IVIEWCR2.DEF", CGI->generaltexth->zelp[445], onClick, SDLK_d); } if (parent->info->upgradeInfo) { @@ -560,7 +560,7 @@ void CStackWindow::CWindowSection::createButtonPanel() } LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[207], onUpgrade, nullptr, true, resComps); }; - auto upgradeBtn = new CAdventureMapButton(CGI->generaltexth->zelp[446], onClick, 221 + i * 40, 5, "stackWindow/upgradeButton", SDLK_1); + auto upgradeBtn = new CButton(Point(221 + i * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick, SDLK_1); upgradeBtn->addOverlay(new CAnimImage("CPRSMALL", VLC->creh->creatures[upgradeInfo.info.newID[i]]->iconIndex)); @@ -583,13 +583,13 @@ void CStackWindow::CWindowSection::createButtonPanel() }; const JsonNode & text = VLC->generaltexth->localizedTexts["creatureWindow"][btnIDs[i]]; - parent->switchButtons[i] = new CAdventureMapButton(text["label"].String(), text["help"].String(), onSwitch, 302 + i*40, 5, "stackWindow/upgradeButton"); + parent->switchButtons[i] = new CButton(Point(302 + i*40, 5), "stackWindow/upgradeButton", CButton::tooltip(text), onSwitch); parent->switchButtons[i]->addOverlay(new CAnimImage("stackWindow/switchModeIcons", i)); } parent->switchButtons[parent->activeTab]->disable(); } - auto exitBtn = new CAdventureMapButton(CGI->generaltexth->zelp[445], [=]{ parent->close(); }, 382, 5, "hsbtns.def", SDLK_RETURN); + auto exitBtn = new CButton(Point(382, 5), "hsbtns.def", CGI->generaltexth->zelp[445], [=]{ parent->close(); }, SDLK_RETURN); exitBtn->assignedKeys.insert(SDLK_ESCAPE); } diff --git a/client/windows/CCreatureWindow.h b/client/windows/CCreatureWindow.h index 57b224745..eac271535 100644 --- a/client/windows/CCreatureWindow.h +++ b/client/windows/CCreatureWindow.h @@ -20,7 +20,7 @@ class CStackInstance; class CStack; struct UpgradeInfo; class CTabbedInt; -class CAdventureMapButton; +class CButton; class CClickableObject : public LRClickableAreaWText { @@ -73,14 +73,14 @@ class CStackWindow : public CWindowObject CAnimImage * stackArtifactIcon; LRClickableAreaWTextComp * stackArtifactHelp; - CAdventureMapButton * stackArtifactButton; + CButton * stackArtifactButton; std::unique_ptr info; std::vector activeBonuses; size_t activeTab; CTabbedInt * commanderTab; - std::map switchButtons; + std::map switchButtons; void setSelection(si32 newSkill, CClickableObject * newIcon); CClickableObject * selectedIcon; diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 043d29a6b..4145f7a79 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -93,8 +93,11 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero): CWindowObject(PLAYER_COLORED, "HeroScr4"), heroWArt(this, hero) { + auto & heroscrn = CGI->generaltexth->heroscrn; + OBJ_CONSTRUCTION_CAPTURING_ALL; garr = nullptr; + tacticsButton = nullptr; curHero = hero; listSelection = nullptr; @@ -103,23 +106,21 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero): //artifs = new CArtifactsOfHero(pos.topLeft(), true); ourBar = new CGStatusBar(7, 559, "ADROLLVR.bmp", 660); // new CStatusBar(pos.x+72, pos.y+567, "ADROLLVR.bmp", 660); - quitButton = new CAdventureMapButton(CGI->generaltexth->heroscrn[17], std::string(),boost::bind(&CHeroWindow::close,this), 609, 516, "hsbtns.def", SDLK_RETURN); + quitButton = new CButton(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [&]{ close(); }, SDLK_RETURN); quitButton->assignedKeys.insert(SDLK_ESCAPE); - dismissButton = new CAdventureMapButton(std::string(), CGI->generaltexth->heroscrn[28], boost::bind(&CHeroWindow::dismissCurrent,this), 454, 429, "hsbtns2.def", SDLK_d); - questlogButton = new CAdventureMapButton(CGI->generaltexth->heroscrn[0], std::string(), boost::bind(&CHeroWindow::questlog,this), 314, 429, "hsbtns4.def", SDLK_q); + dismissButton = new CButton(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [&]{ dismissCurrent(); }, SDLK_d); + questlogButton = new CButton(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [&]{ questlog(); }, SDLK_q); - formations = new CHighlightableButtonsGroup(0); - formations->addButton(map_list_of(0,CGI->generaltexth->heroscrn[23]),CGI->generaltexth->heroscrn[29], "hsbtns6.def", 481, 483, 0, 0, SDLK_t); - formations->addButton(map_list_of(0,CGI->generaltexth->heroscrn[24]),CGI->generaltexth->heroscrn[30], "hsbtns7.def", 481, 519, 1, 0, SDLK_l); - - tacticsButton = new CHighlightableButton(0, 0, map_list_of(0,CGI->generaltexth->heroscrn[26])(3,CGI->generaltexth->heroscrn[25]), CGI->generaltexth->heroscrn[31], false, "hsbtns8.def", nullptr, 539, 483, SDLK_b); + formations = new CToggleGroup(0); + formations->addToggle(0, new CToggleButton(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t)); + formations->addToggle(1, new CToggleButton(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, SDLK_l)); if (hero->commander) { - commanderButton = new CAdventureMapButton ("Commander", "Commander info", boost::bind(&CHeroWindow::commanderWindow, this), 317, 18, "chftke.def", SDLK_c, nullptr, false); + auto texts = CGI->generaltexth->localizedTexts["heroWindow"]["openCommander"]; + commanderButton = new CButton (Point(317, 18), "chftke.def", CButton::tooltip(texts), [&]{ commanderWindow(); }, SDLK_c); } - //right list of heroes for(int i=0; i < std::min(LOCPLINT->cb->howManyHeroes(false), 8); i++) heroList.push_back(new CHeroSwitcher(Point(612, 87 + i * 54), LOCPLINT->cb->getHeroBySerial(i, false))); @@ -180,7 +181,9 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero): } void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= false*/) -{ +{ + auto & heroscrn = CGI->generaltexth->heroscrn; + if(!hero) //something strange... no hero? it shouldn't happen { logGlobal->errorStream() << "Set nullptr hero? no way..."; @@ -192,10 +195,11 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals specArea->text = curHero->type->specDescr; specImage->setFrame(curHero->type->imageIndex); - tacticsButton->callback.clear(); - tacticsButton->callback2.clear(); + delete tacticsButton; + tacticsButton = new CToggleButton(Point(539, 483), "hsbtns8.def", std::make_pair(heroscrn[26], heroscrn[31]), 0, SDLK_b); + tacticsButton->addHoverText(CButton::HIGHLIGHTED, CGI->generaltexth->heroscrn[25]); - dismissButton->hoverTexts[0] = boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name); + dismissButton->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name)); portraitArea->hoverText = boost::str(boost::format(CGI->generaltexth->allTexts[15]) % curHero->name % curHero->type->heroClass->name); portraitArea->text = curHero->getBiography(); portraitImage->setFrame(curHero->portrait); @@ -204,10 +208,11 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals OBJ_CONSTRUCTION_CAPTURING_ALL; if(!garr) { + std::string helpBox = heroscrn[32]; + boost::algorithm::replace_first(helpBox, "%s", CGI->generaltexth->allTexts[43]); + garr = new CGarrisonInt(15, 485, 8, Point(), background->bg, Point(15,485), curHero); - auto split = new CAdventureMapButton(CGI->generaltexth->allTexts[256], CGI->generaltexth->heroscrn[32], - boost::bind(&CGarrisonInt::splitClick,garr), 539, 519, "hsbtns9.def", false, nullptr, false); //deleted by garrison destructor - boost::algorithm::replace_first(split->hoverTexts[0],"%s",CGI->generaltexth->allTexts[43]); + auto split = new CButton(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&]{ garr->splitClick(); }); garr->addSplitBtn(split); } @@ -239,7 +244,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals secSkillAreas[g]->type = skill; secSkillAreas[g]->bonusValue = level; secSkillAreas[g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1]; - secSkillAreas[g]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->generaltexth->skillName[skill]); + secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->generaltexth->skillName[skill]); secSkillImages[g]->setFrame(skill*3 + level + 2); } @@ -274,14 +279,13 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals else { tacticsButton->block(false); - tacticsButton->callback = vstd::assigno(curHero->tacticFormationEnabled,true); - tacticsButton->callback2 = vstd::assigno(curHero->tacticFormationEnabled,false); + tacticsButton->addCallback( [&](bool on) {curHero->tacticFormationEnabled = on;}); + } //setting formations - formations->onChange = 0; - formations->select(curHero->formation,true); - formations->onChange = boost::bind(&CCallback::setFormation, LOCPLINT->cb.get(), curHero, _1); + formations->setSelected(curHero->formation); + formations->addCallback([&] (int value) { LOCPLINT->cb->setFormation(curHero, value); }); morale->set(&heroWArt); luck->set(&heroWArt); diff --git a/client/windows/CHeroWindow.h b/client/windows/CHeroWindow.h index e7131b17a..79af11e3b 100644 --- a/client/windows/CHeroWindow.h +++ b/client/windows/CHeroWindow.h @@ -14,7 +14,7 @@ * */ -class CAdventureMapButton; +class CButton; struct SDL_Surface; class CGHeroInstance; class CDefHandler; @@ -25,8 +25,8 @@ class LRClickableAreaWText; class LRClickableAreaWTextComp; class CArtifactsOfHero; class MoraleLuckBox; -class CHighlightableButton; -class CHighlightableButtonsGroup; +class CToggleButton; +class CToggleGroup; class CGStatusBar; /// Button which switches hero selection @@ -56,7 +56,7 @@ class CHeroWindow: public CWindowObject, public CWindowWithGarrison, public CWin CGStatusBar * ourBar; //heroWindow's statusBar //buttons - //CAdventureMapButton * gar4button; //splitting + //CButton * gar4button; //splitting std::vector heroList; //list of heroes CPicture * listSelection; //selection border @@ -74,10 +74,10 @@ class CHeroWindow: public CWindowObject, public CWindowWithGarrison, public CWin std::vector secSkillImages; CHeroWithMaybePickedArtifact heroWArt; - CAdventureMapButton * quitButton, * dismissButton, * questlogButton, * commanderButton; //general + CButton * quitButton, * dismissButton, * questlogButton, * commanderButton; //general - CHighlightableButton *tacticsButton; //garrison / formation handling; - CHighlightableButtonsGroup *formations; + CToggleButton *tacticsButton; //garrison / formation handling; + CToggleGroup *formations; public: const CGHeroInstance * curHero; diff --git a/client/windows/CKingdomInterface.cpp b/client/windows/CKingdomInterface.cpp index f70036974..7697bf957 100644 --- a/client/windows/CKingdomInterface.cpp +++ b/client/windows/CKingdomInterface.cpp @@ -608,33 +608,29 @@ void CKingdomInterface::generateButtons() ui32 footerPos = conf.go()->ac.overviewSize * 116; //Main control buttons - btnHeroes = new CAdventureMapButton (CGI->generaltexth->overview[11], CGI->generaltexth->overview[6], - boost::bind(&CKingdomInterface::activateTab, this, 0),748,28+footerPos,"OVBUTN1.DEF", SDLK_h); + btnHeroes = new CButton (Point(748, 28+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->overview[11], CGI->generaltexth->overview[6]), + boost::bind(&CKingdomInterface::activateTab, this, 0), SDLK_h); btnHeroes->block(true); - btnTowns = new CAdventureMapButton (CGI->generaltexth->overview[12], CGI->generaltexth->overview[7], - boost::bind(&CKingdomInterface::activateTab, this, 1),748,64+footerPos,"OVBUTN6.DEF", SDLK_t); + btnTowns = new CButton (Point(748, 64+footerPos), "OVBUTN6.DEF", CButton::tooltip(CGI->generaltexth->overview[12], CGI->generaltexth->overview[7]), + boost::bind(&CKingdomInterface::activateTab, this, 1), SDLK_t); - btnExit = new CAdventureMapButton (CGI->generaltexth->allTexts[600],"", - boost::bind(&CKingdomInterface::close, this),748,99+footerPos,"OVBUTN1.DEF", SDLK_RETURN); + btnExit = new CButton (Point(748,99+footerPos), "OVBUTN1.DEF", CButton::tooltip(CGI->generaltexth->allTexts[600]), + boost::bind(&CKingdomInterface::close, this), SDLK_RETURN); btnExit->assignedKeys.insert(SDLK_ESCAPE); - btnExit->setOffset(3); + btnExit->setImageOrder(3, 4, 5, 6); //Object list control buttons - dwellTop = new CAdventureMapButton ("", "", boost::bind(&CListBox::moveToPos, dwellingsList, 0), - 733, 4, "OVBUTN4.DEF"); + dwellTop = new CButton (Point(733, 4), "OVBUTN4.DEF", CButton::tooltip(), [&]{ dwellingsList->moveToPos(0);}); - dwellBottom = new CAdventureMapButton ("", "", boost::bind(&CListBox::moveToPos, dwellingsList, -1), - 733, footerPos+2, "OVBUTN4.DEF"); - dwellBottom->setOffset(2); + dwellBottom = new CButton (Point(733, footerPos+2), "OVBUTN4.DEF", CButton::tooltip(), [&]{ dwellingsList->moveToPos(-1); }); + dwellBottom->setImageOrder(2, 3, 4, 5); - dwellUp = new CAdventureMapButton ("", "", boost::bind(&CListBox::moveToPrev, dwellingsList), - 733, 24, "OVBUTN4.DEF"); - dwellUp->setOffset(4); + dwellUp = new CButton (Point(733, 24), "OVBUTN4.DEF", CButton::tooltip(), [&]{ dwellingsList->moveToPrev(); }); + dwellUp->setImageOrder(4, 5, 6, 7); - dwellDown = new CAdventureMapButton ("", "", boost::bind(&CListBox::moveToNext, dwellingsList), - 733, footerPos-18, "OVBUTN4.DEF"); - dwellDown->setOffset(6); + dwellDown = new CButton (Point(733, footerPos-18), "OVBUTN4.DEF", CButton::tooltip(), [&]{ dwellingsList->moveToNext(); }); + dwellDown->setImageOrder(6, 7, 8, 9); } void CKingdomInterface::activateTab(size_t which) @@ -851,16 +847,16 @@ class BackpackTab : public CIntObject public: CAnimImage * background; std::vector arts; - CAdventureMapButton *btnLeft; - CAdventureMapButton *btnRight; + CButton *btnLeft; + CButton *btnRight; BackpackTab() { OBJ_CONSTRUCTION_CAPTURING_ALL; background = new CAnimImage("OVSLOT", 5); pos = background->pos; - btnLeft = new CAdventureMapButton(std::string(), std::string(), CFunctionList(), 269, 66, "HSBTNS3"); - btnRight = new CAdventureMapButton(std::string(), std::string(), CFunctionList(), 675, 66, "HSBTNS5"); + btnLeft = new CButton(Point(269, 66), "HSBTNS3", CButton::tooltip(), 0); + btnRight = new CButton(Point(675, 66), "HSBTNS5", CButton::tooltip(), 0); for (size_t i=0; i<8; i++) arts.push_back(new CArtPlace(Point(295+i*48, 65))); } @@ -894,21 +890,21 @@ CHeroItem::CHeroItem(const CGHeroInstance* Hero, CArtifactsOfHero::SCommonPart * artsTabs = new CTabbedInt(boost::bind(&CHeroItem::onTabSelected, this, _1), boost::bind(&CHeroItem::onTabDeselected, this, _1)); - artButtons = new CHighlightableButtonsGroup(0); + artButtons = new CToggleGroup(0); for (size_t it = 0; it<3; it++) { int stringID[3] = {259, 261, 262}; - std::map tooltip; - tooltip[0] = CGI->generaltexth->overview[13+it]; + std::string hover = CGI->generaltexth->overview[13+it]; std::string overlay = CGI->generaltexth->overview[8+it]; - artButtons->addButton(tooltip, overlay, "OVBUTN3",364+it*112, 46, it); - artButtons->buttons[it]->addTextOverlay(CGI->generaltexth->allTexts[stringID[it]], FONT_SMALL, Colors::YELLOW); + auto button = new CToggleButton(Point(364+it*112, 46), "OVBUTN3", CButton::tooltip(hover, overlay), 0); + button->addTextOverlay(CGI->generaltexth->allTexts[stringID[it]], FONT_SMALL, Colors::YELLOW); + artButtons->addToggle(it, button); } - artButtons->onChange += boost::bind(&CTabbedInt::setActive, artsTabs, _1); - artButtons->onChange += boost::bind(&CHeroItem::onArtChange, this, _1); - artButtons->select(0,0); + artButtons->addCallback(boost::bind(&CTabbedInt::setActive, artsTabs, _1)); + artButtons->addCallback(boost::bind(&CHeroItem::onArtChange, this, _1)); + artButtons->setSelected(0); garr = new CGarrisonInt(6, 78, 4, Point(), nullptr, Point(), hero, nullptr, true, true); diff --git a/client/windows/CKingdomInterface.h b/client/windows/CKingdomInterface.h index cfcc24710..f4f6f5e53 100644 --- a/client/windows/CKingdomInterface.h +++ b/client/windows/CKingdomInterface.h @@ -3,9 +3,9 @@ #include "../widgets/CArtifactHolder.h" #include "../widgets/CGarrisonInt.h" -class CAdventureMapButton; +class CButton; class CAnimImage; -class CHighlightableButtonsGroup; +class CToggleGroup; class CResDataBar; class CSlider; class CTownInfo; @@ -220,13 +220,13 @@ private: CTabbedInt * tabArea; //Main buttons - CAdventureMapButton *btnTowns; - CAdventureMapButton *btnHeroes; - CAdventureMapButton *btnExit; + CButton *btnTowns; + CButton *btnHeroes; + CButton *btnExit; //Buttons for scrolling dwellings list - CAdventureMapButton *dwellUp, *dwellDown; - CAdventureMapButton *dwellTop, *dwellBottom; + CButton *dwellUp, *dwellDown; + CButton *dwellTop, *dwellBottom; InfoBox * minesBox[7]; @@ -295,7 +295,7 @@ class CHeroItem : public CIntObject, public CWindowWithGarrison CLabel *artsText; CTabbedInt *artsTabs; - CHighlightableButtonsGroup *artButtons; + CToggleGroup *artButtons; std::vector heroInfo; MoraleLuckBox * morale, * luck; diff --git a/client/windows/CQuestLog.cpp b/client/windows/CQuestLog.cpp index a8e0845e2..ad8625544 100644 --- a/client/windows/CQuestLog.cpp +++ b/client/windows/CQuestLog.cpp @@ -129,7 +129,7 @@ void CQuestLog::init() { minimap = new CQuestMinimap (Rect (47, 33, 144, 144)); description = new CTextBox ("", Rect(245, 33, 350, 355), 1, FONT_MEDIUM, TOPLEFT, Colors::WHITE); - ok = new CAdventureMapButton("",CGI->generaltexth->zelp[445].second, boost::bind(&CQuestLog::close,this), 547, 401, "IOKAY.DEF", SDLK_RETURN); + ok = new CButton(Point(547, 401), "IOKAY.DEF", CGI->generaltexth->zelp[445], boost::bind(&CQuestLog::close,this), SDLK_RETURN); if (quests.size() > QUEST_COUNT) slider = new CSlider(203, 199, 230, boost::bind (&CQuestLog::sliderMoved, this, _1), QUEST_COUNT, quests.size(), false, 0); diff --git a/client/windows/CQuestLog.h b/client/windows/CQuestLog.h index 5c5557239..c14b0c32e 100644 --- a/client/windows/CQuestLog.h +++ b/client/windows/CQuestLog.h @@ -18,11 +18,11 @@ class CCreature; class CStackInstance; -class CAdventureMapButton; +class CButton; class CGHeroInstance; class CComponent; class LRClickableAreaWText; -class CAdventureMapButton; +class CButton; class CPicture; class CCreaturePic; class LRClickableAreaWTextComp; @@ -85,7 +85,7 @@ class CQuestLog : public CWindowObject CTextBox * description; CQuestMinimap * minimap; CSlider * slider; //scrolls quests - CAdventureMapButton *ok; + CButton *ok; void init (); public: diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index 688b1c761..4aed415a8 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -695,16 +695,16 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan initItems(false); initItems(true); - ok = new CAdventureMapButton(CGI->generaltexth->zelp[600],boost::bind(&CGuiHandler::popIntTotally,&GH,this),516,520,"IOK6432.DEF",SDLK_RETURN); + ok = new CButton(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[600], [&]{ close(); }, SDLK_RETURN); ok->assignedKeys.insert(SDLK_ESCAPE); - deal = new CAdventureMapButton(CGI->generaltexth->zelp[595],boost::bind(&CMarketplaceWindow::makeDeal,this),307,520,"TPMRKB.DEF"); + deal = new CButton(Point(307, 520), "TPMRKB.DEF", CGI->generaltexth->zelp[595], [&] { makeDeal(); } ); deal->block(true); if(sliderNeeded) { slider = new CSlider(231,490,137,nullptr,0,0); slider->moved = boost::bind(&CMarketplaceWindow::sliderMoved,this,_1); - max = new CAdventureMapButton(CGI->generaltexth->zelp[596],boost::bind(&CMarketplaceWindow::setMax,this),229,520,"IRCBTNS.DEF"); + max = new CButton(Point(229, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[596], [&] { setMax(); }); max->block(true); } else @@ -757,15 +757,15 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan int specialOffset = mode == EMarketMode::ARTIFACT_RESOURCE ? 35 : 0; //in selling artifacts mode we need to move res-res and art-res buttons down if(printButtonFor(EMarketMode::RESOURCE_PLAYER)) - new CAdventureMapButton(CGI->generaltexth->zelp[612],boost::bind(&CMarketplaceWindow::setMode,this, EMarketMode::RESOURCE_PLAYER), 18, 520,"TPMRKBU1.DEF"); + new CButton(Point(18, 520),"TPMRKBU1.DEF", CGI->generaltexth->zelp[612], [&] { setMode(EMarketMode::RESOURCE_PLAYER);}); if(printButtonFor(EMarketMode::RESOURCE_RESOURCE)) - new CAdventureMapButton(CGI->generaltexth->zelp[605],boost::bind(&CMarketplaceWindow::setMode,this, EMarketMode::RESOURCE_RESOURCE), 516, 450 + specialOffset,"TPMRKBU5.DEF"); + new CButton(Point(516, 450 + specialOffset),"TPMRKBU5.DEF", CGI->generaltexth->zelp[605], [&] { setMode(EMarketMode::RESOURCE_RESOURCE);}); if(printButtonFor(EMarketMode::CREATURE_RESOURCE)) - new CAdventureMapButton(CGI->generaltexth->zelp[599],boost::bind(&CMarketplaceWindow::setMode,this, EMarketMode::CREATURE_RESOURCE), 516, 485,"TPMRKBU4.DEF"); //was y=450, changed to not overlap res-res in some conditions + new CButton(Point(516, 485),"TPMRKBU4.DEF", CGI->generaltexth->zelp[599], [&] { setMode(EMarketMode::CREATURE_RESOURCE);}); if(printButtonFor(EMarketMode::RESOURCE_ARTIFACT)) - new CAdventureMapButton(CGI->generaltexth->zelp[598],boost::bind(&CMarketplaceWindow::setMode,this, EMarketMode::RESOURCE_ARTIFACT), 18, 450 + specialOffset,"TPMRKBU2.DEF"); + new CButton(Point(18, 450 + specialOffset),"TPMRKBU2.DEF", CGI->generaltexth->zelp[598], [&] { setMode(EMarketMode::RESOURCE_ARTIFACT);}); if(printButtonFor(EMarketMode::ARTIFACT_RESOURCE)) - new CAdventureMapButton(CGI->generaltexth->zelp[613],boost::bind(&CMarketplaceWindow::setMode,this, EMarketMode::ARTIFACT_RESOURCE), 18, 485,"TPMRKBU3.DEF"); //was y=450, changed to not overlap res-art in some conditions + new CButton(Point(18, 485),"TPMRKBU3.DEF", CGI->generaltexth->zelp[613], [&] { setMode(EMarketMode::ARTIFACT_RESOURCE);}); updateTraderText(); } @@ -1111,10 +1111,10 @@ CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*= slider = new CSlider(231,481,137,nullptr,0,0); slider->moved = boost::bind(&CAltarWindow::sliderMoved,this,_1); - max = new CAdventureMapButton(CGI->generaltexth->zelp[578],boost::bind(&CSlider::moveToMax, slider),147,520,"IRCBTNS.DEF"); + max = new CButton(Point(147, 520), "IRCBTNS.DEF", CGI->generaltexth->zelp[578], boost::bind(&CSlider::moveToMax, slider)); sacrificedUnits.resize(GameConstants::ARMY_SIZE, 0); - sacrificeAll = new CAdventureMapButton(CGI->generaltexth->zelp[579],boost::bind(&CAltarWindow::SacrificeAll,this),393,520,"ALTARMY.DEF"); + sacrificeAll = new CButton(Point(393, 520), "ALTARMY.DEF", CGI->generaltexth->zelp[579], boost::bind(&CAltarWindow::SacrificeAll,this)); sacrificeBackpack = nullptr; initItems(true); @@ -1128,9 +1128,9 @@ CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*= //%s's Creatures new CLabel(302, 423, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478]); - sacrificeAll = new CAdventureMapButton(CGI->generaltexth->zelp[571], boost::bind(&CAltarWindow::SacrificeAll,this),393,520,"ALTFILL.DEF"); + sacrificeAll = new CButton(Point(393, 520), "ALTFILL.DEF", CGI->generaltexth->zelp[571], boost::bind(&CAltarWindow::SacrificeAll,this)); sacrificeAll->block(hero->artifactsInBackpack.empty() && hero->artifactsWorn.empty()); - sacrificeBackpack = new CAdventureMapButton(CGI->generaltexth->zelp[570],boost::bind(&CAltarWindow::SacrificeBackpack,this),147,520,"ALTEMBK.DEF"); + sacrificeBackpack = new CButton(Point(147, 520), "ALTEMBK.DEF", CGI->generaltexth->zelp[570], boost::bind(&CAltarWindow::SacrificeBackpack,this)); sacrificeBackpack->block(hero->artifactsInBackpack.empty()); slider = nullptr; @@ -1149,15 +1149,15 @@ CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*= new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - ok = new CAdventureMapButton(CGI->generaltexth->zelp[568],boost::bind(&CGuiHandler::popIntTotally,&GH,this),516,520,"IOK6432.DEF",SDLK_RETURN); + ok = new CButton(Point(516, 520), "IOK6432.DEF", CGI->generaltexth->zelp[568], [&]{ close();}, SDLK_RETURN); ok->assignedKeys.insert(SDLK_ESCAPE); - deal = new CAdventureMapButton(CGI->generaltexth->zelp[585],boost::bind(&CAltarWindow::makeDeal,this),269,520,"ALTSACR.DEF"); + deal = new CButton(Point(269, 520), "ALTSACR.DEF", CGI->generaltexth->zelp[585], boost::bind(&CAltarWindow::makeDeal,this)); if(Hero->getAlignment() != ::EAlignment::EVIL && Mode == EMarketMode::CREATURE_EXP) - new CAdventureMapButton(CGI->generaltexth->zelp[580], boost::bind(&CTradeWindow::setMode,this, EMarketMode::ARTIFACT_EXP), 516, 421, "ALTART.DEF"); + new CButton(Point(516, 421), "ALTART.DEF", CGI->generaltexth->zelp[580], boost::bind(&CTradeWindow::setMode,this, EMarketMode::ARTIFACT_EXP)); if(Hero->getAlignment() != ::EAlignment::GOOD && Mode == EMarketMode::ARTIFACT_EXP) - new CAdventureMapButton(CGI->generaltexth->zelp[572], boost::bind(&CTradeWindow::setMode,this, EMarketMode::CREATURE_EXP), 516, 421, "ALTSACC.DEF"); + new CButton(Point(516, 421), "ALTSACC.DEF", CGI->generaltexth->zelp[572], boost::bind(&CTradeWindow::setMode,this, EMarketMode::CREATURE_EXP)); expPerUnit.resize(GameConstants::ARMY_SIZE, 0); getExpValues(); diff --git a/client/windows/CTradeWindow.h b/client/windows/CTradeWindow.h index 36a4f91fa..fde6da502 100644 --- a/client/windows/CTradeWindow.h +++ b/client/windows/CTradeWindow.h @@ -68,7 +68,7 @@ public: EType itemsType[2]; EMarketMode::EMarketMode mode;//0 - res<->res; 1 - res<->plauer; 2 - buy artifact; 3 - sell artifact - CAdventureMapButton *ok, *max, *deal; + CButton *ok, *max, *deal; CSlider *slider; //for choosing amount to be exchanged bool readyToTrade; @@ -137,7 +137,7 @@ public: std::vector sacrificedUnits, //[slot_nr] -> how many creatures from that slot will be sacrificed expPerUnit; - CAdventureMapButton *sacrificeAll, *sacrificeBackpack; + CButton *sacrificeAll, *sacrificeBackpack; CLabel *expToLevel, *expOnAltar; diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 84744c793..ff79bbf90 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -264,9 +264,9 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co slider = new CSlider(176,279,135,nullptr,0,0,0,true); slider->moved = boost::bind(&CRecruitmentWindow::sliderMoved,this, _1); - maxButton = new CAdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CSlider::moveToMax,slider),134,313,"IRCBTNS.DEF",SDLK_m); - buyButton = new CAdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecruitmentWindow::buy,this),212,313,"IBY6432.DEF",SDLK_RETURN); - cancelButton = new CAdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecruitmentWindow::close,this),290,313,"ICN6432.DEF",SDLK_ESCAPE); + maxButton = new CButton(Point(134, 313), "IRCBTNS.DEF", CGI->generaltexth->zelp[553], boost::bind(&CSlider::moveToMax,slider), SDLK_m); + buyButton = new CButton(Point(212, 313), "IBY6432.DEF", CGI->generaltexth->zelp[554], boost::bind(&CRecruitmentWindow::buy,this), SDLK_RETURN); + cancelButton = new CButton(Point(290, 313), "ICN6432.DEF", CGI->generaltexth->zelp[555], boost::bind(&CRecruitmentWindow::close,this), SDLK_ESCAPE); title = new CLabel(243, 32, FONT_BIG, CENTER, Colors::YELLOW); availableValue = new CLabel(205, 253, FONT_SMALL, CENTER, Colors::WHITE); @@ -375,8 +375,8 @@ CSplitWindow::CSplitWindow(const CCreature * creature, std::functionshowingDialog->setn(true); new CAnimImage("PortraitsLarge", hero->portrait, 0, 170, 66); - new CAdventureMapButton("", "", boost::bind(&CLevelWindow::close, this), 297, 413, "IOKAY", SDLK_RETURN); + new CButton(Point(297, 413), "IOKAY", CButton::tooltip(), boost::bind(&CLevelWindow::close, this), SDLK_RETURN); //%s has gained a level. new CLabel(192, 33, FONT_MEDIUM, CENTER, Colors::WHITE, @@ -536,96 +536,80 @@ CSystemOptionsWindow::CSystemOptionsWindow(): rightGroup->add(282, 217, texts["fullscreenButton"]["label"].String()); //setting up buttons - load = new CAdventureMapButton (CGI->generaltexth->zelp[321].first, CGI->generaltexth->zelp[321].second, - boost::bind(&CSystemOptionsWindow::bloadf, this), 246, 298, "SOLOAD.DEF", SDLK_l); - load->swappedImages = true; - load->update(); + load = new CButton (Point(246, 298), "SOLOAD.DEF", CGI->generaltexth->zelp[321], [&] { bloadf(); }, SDLK_l); + load->setImageOrder(1, 0, 2, 3); - save = new CAdventureMapButton (CGI->generaltexth->zelp[322].first, CGI->generaltexth->zelp[322].second, - boost::bind(&CSystemOptionsWindow::bsavef, this), 357, 298, "SOSAVE.DEF", SDLK_s); - save->swappedImages = true; - save->update(); + save = new CButton (Point(357, 298), "SOSAVE.DEF", CGI->generaltexth->zelp[322], [&] { bsavef(); }, SDLK_s); + save->setImageOrder(1, 0, 2, 3); - restart = new CAdventureMapButton (CGI->generaltexth->zelp[323].first, CGI->generaltexth->zelp[323].second, - boost::bind(&CSystemOptionsWindow::brestartf, this), 246, 357, "SORSTRT", SDLK_r); - restart->swappedImages = true; - restart->update(); + restart = new CButton (Point(246, 357), "SORSTRT", CGI->generaltexth->zelp[323], [&] { brestartf(); }, SDLK_r); + restart->setImageOrder(1, 0, 2, 3); - mainMenu = new CAdventureMapButton (CGI->generaltexth->zelp[320].first, CGI->generaltexth->zelp[320].second, - boost::bind(&CSystemOptionsWindow::bmainmenuf, this), 357, 357, "SOMAIN.DEF", SDLK_m); - mainMenu->swappedImages = true; - mainMenu->update(); + mainMenu = new CButton (Point(357, 357), "SOMAIN.DEF", CGI->generaltexth->zelp[320], [&] { bmainmenuf(); }, SDLK_m); + mainMenu->setImageOrder(1, 0, 2, 3); - quitGame = new CAdventureMapButton (CGI->generaltexth->zelp[324].first, CGI->generaltexth->zelp[324].second, - boost::bind(&CSystemOptionsWindow::bquitf, this), 246, 415, "soquit.def", SDLK_q); - quitGame->swappedImages = true; - quitGame->update(); - backToMap = new CAdventureMapButton (CGI->generaltexth->zelp[325].first, CGI->generaltexth->zelp[325].second, - boost::bind(&CSystemOptionsWindow::breturnf, this), 357, 415, "soretrn.def", SDLK_RETURN); - backToMap->swappedImages = true; - backToMap->update(); + quitGame = new CButton (Point(246, 415), "soquit.def", CGI->generaltexth->zelp[324], [&] { bquitf(); }, SDLK_q); + quitGame->setImageOrder(1, 0, 2, 3); + + backToMap = new CButton ( Point(357, 415), "soretrn.def", CGI->generaltexth->zelp[325], [&] { breturnf(); }, SDLK_RETURN); + backToMap->setImageOrder(1, 0, 2, 3); backToMap->assignedKeys.insert(SDLK_ESCAPE); - heroMoveSpeed = new CHighlightableButtonsGroup(0); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[349].second),CGI->generaltexth->zelp[349].second, "sysopb1.def", 28, 77, 1); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[350].second),CGI->generaltexth->zelp[350].second, "sysopb2.def", 76, 77, 2); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[351].second),CGI->generaltexth->zelp[351].second, "sysopb3.def", 124, 77, 4); - heroMoveSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[352].second),CGI->generaltexth->zelp[352].second, "sysopb4.def", 172, 77, 8); - heroMoveSpeed->select(settings["adventure"]["heroSpeed"].Float(), 1); - heroMoveSpeed->onChange = boost::bind(&CSystemOptionsWindow::setHeroMoveSpeed, this, _1); + heroMoveSpeed = new CToggleGroup(0); + heroMoveSpeed->addToggle(1, new CToggleButton(Point( 28, 77), "sysopb1.def", CGI->generaltexth->zelp[349])); + heroMoveSpeed->addToggle(2, new CToggleButton(Point( 76, 77), "sysopb2.def", CGI->generaltexth->zelp[350])); + heroMoveSpeed->addToggle(4, new CToggleButton(Point(124, 77), "sysopb3.def", CGI->generaltexth->zelp[351])); + heroMoveSpeed->addToggle(8, new CToggleButton(Point(172, 77), "sysopb4.def", CGI->generaltexth->zelp[352])); + heroMoveSpeed->setSelected(settings["adventure"]["heroSpeed"].Float()); + heroMoveSpeed->addCallback(boost::bind(&CSystemOptionsWindow::setHeroMoveSpeed, this, _1)); - mapScrollSpeed = new CHighlightableButtonsGroup(0); - mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[357].second),CGI->generaltexth->zelp[357].second, "sysopb9.def", 28, 210, 1); - mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[358].second),CGI->generaltexth->zelp[358].second, "sysob10.def", 92, 210, 2); - mapScrollSpeed->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[359].second),CGI->generaltexth->zelp[359].second, "sysob11.def", 156, 210, 4); - mapScrollSpeed->select(settings["adventure"]["scrollSpeed"].Float(), 1); - mapScrollSpeed->onChange = boost::bind(&CSystemOptionsWindow::setMapScrollingSpeed, this, _1); + mapScrollSpeed = new CToggleGroup(0); + mapScrollSpeed->addToggle(1, new CToggleButton(Point( 28, 210), "sysopb9.def", CGI->generaltexth->zelp[357])); + mapScrollSpeed->addToggle(2, new CToggleButton(Point( 92, 210), "sysob10.def", CGI->generaltexth->zelp[358])); + mapScrollSpeed->addToggle(4, new CToggleButton(Point(156, 210), "sysob11.def", CGI->generaltexth->zelp[359])); + mapScrollSpeed->setSelected(settings["adventure"]["scrollSpeed"].Float()); + mapScrollSpeed->addCallback(boost::bind(&CSystemOptionsWindow::setMapScrollingSpeed, this, _1)); - musicVolume = new CHighlightableButtonsGroup(0, true); + musicVolume = new CToggleGroup(0, true); for(int i=0; i<10; ++i) - musicVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[326+i].second),CGI->generaltexth->zelp[326+i].second, "syslb.def", 29 + 19*i, 359, i*11); + musicVolume->addToggle(i*11, new CToggleButton(Point(29 + 19*i, 359), "syslb.def", CGI->generaltexth->zelp[326+i])); - musicVolume->select(CCS->musich->getVolume(), 1); - musicVolume->onChange = boost::bind(&CSystemOptionsWindow::setMusicVolume, this, _1); + musicVolume->setSelected(CCS->musich->getVolume()); + musicVolume->addCallback(boost::bind(&CSystemOptionsWindow::setMusicVolume, this, _1)); - effectsVolume = new CHighlightableButtonsGroup(0, true); + effectsVolume = new CToggleGroup(0, true); for(int i=0; i<10; ++i) - effectsVolume->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[336+i].second),CGI->generaltexth->zelp[336+i].second, "syslb.def", 29 + 19*i, 425, i*11); + effectsVolume->addToggle(i*11, new CToggleButton(Point(29 + 19*i, 425), "syslb.def", CGI->generaltexth->zelp[336+i])); - effectsVolume->select(CCS->soundh->getVolume(), 1); - effectsVolume->onChange = boost::bind(&CSystemOptionsWindow::setSoundVolume, this, _1); + effectsVolume->setSelected(CCS->soundh->getVolume()); + effectsVolume->addCallback(boost::bind(&CSystemOptionsWindow::setSoundVolume, this, _1)); - showReminder = new CHighlightableButton( - boost::bind(&CSystemOptionsWindow::toggleReminder, this, true), boost::bind(&CSystemOptionsWindow::toggleReminder, this, false), - std::map(), CGI->generaltexth->zelp[361].second, false, "sysopchk.def", nullptr, 246, 87, false); + showReminder = new CToggleButton(Point(246, 87), "sysopchk.def", CGI->generaltexth->zelp[361], + [&] (bool value) { toggleReminder(value);}); - quickCombat = new CHighlightableButton( - boost::bind(&CSystemOptionsWindow::toggleQuickCombat, this, true), boost::bind(&CSystemOptionsWindow::toggleQuickCombat, this, false), - std::map(), CGI->generaltexth->zelp[362].second, false, "sysopchk.def", nullptr, 246, 87+32, false); + quickCombat = new CToggleButton(Point(246, 87+32), "sysopchk.def", CGI->generaltexth->zelp[362], + [&] (bool value) { toggleQuickCombat(value);}); - spellbookAnim = new CHighlightableButton( - boost::bind(&CSystemOptionsWindow::toggleSpellbookAnim, this, true), boost::bind(&CSystemOptionsWindow::toggleSpellbookAnim, this, false), - std::map(), CGI->generaltexth->zelp[364].second, false, "sysopchk.def", nullptr, 246, 87+64, false); + spellbookAnim = new CToggleButton(Point(246, 87+64), "sysopchk.def", CGI->generaltexth->zelp[364], + [&] (bool value) { toggleSpellbookAnim(value);}); - newCreatureWin = new CHighlightableButton( - boost::bind(&CSystemOptionsWindow::toggleCreatureWin, this, true), boost::bind(&CSystemOptionsWindow::toggleCreatureWin, this, false), - std::map(), texts["creatureWindowButton"]["help"].String(), false, "sysopchk.def", nullptr, 246, 183, false); + newCreatureWin = new CToggleButton(Point(246, 183), "sysopchk.def", CButton::tooltip(texts["creatureWindowButton"]), + [&] (bool value) { toggleCreatureWin(value);}); - fullscreen = new CHighlightableButton( - boost::bind(&CSystemOptionsWindow::toggleFullscreen, this, true), boost::bind(&CSystemOptionsWindow::toggleFullscreen, this, false), - std::map(), texts["fullscreenButton"]["help"].String(), false, "sysopchk.def", nullptr, 246, 215, false); + fullscreen = new CToggleButton(Point(246, 215), "sysopchk.def", CButton::tooltip(texts["fullscreenButton"]), + [&] (bool value) { toggleFullscreen(value);}); - showReminder->select(settings["adventure"]["heroReminder"].Bool()); - quickCombat->select(settings["adventure"]["quickCombat"].Bool()); - spellbookAnim->select(settings["video"]["spellbookAnimation"].Bool()); - newCreatureWin->select(settings["general"]["classicCreatureWindow"].Bool()); - fullscreen->select(settings["video"]["fullscreen"].Bool()); + showReminder->setSelected(settings["adventure"]["heroReminder"].Bool()); + quickCombat->setSelected(settings["adventure"]["quickCombat"].Bool()); + spellbookAnim->setSelected(settings["video"]["spellbookAnimation"].Bool()); + newCreatureWin->setSelected(settings["general"]["classicCreatureWindow"].Bool()); + fullscreen->setSelected(settings["video"]["fullscreen"].Bool()); - onFullscreenChanged([&](const JsonNode &newState){ fullscreen->select(newState.Bool());}); + onFullscreenChanged([&](const JsonNode &newState){ fullscreen->setSelected(newState.Bool());}); - gameResButton = new CAdventureMapButton("", texts["resolutionButton"]["help"].String(), + gameResButton = new CButton(Point(28, 275),"SYSOB12", CButton::tooltip(texts["resolutionButton"]), boost::bind(&CSystemOptionsWindow::selectGameRes, this), - 28, 275,"SYSOB12", SDLK_g); + SDLK_g); std::string resText; resText += boost::lexical_cast(settings["video"]["screenRes"]["width"].Float()); @@ -762,30 +746,30 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj): new CTextBox(LOCPLINT->cb->getTavernGossip(tavernObj), Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE); new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); - cancel = new CAdventureMapButton(CGI->generaltexth->tavernInfo[7],"", boost::bind(&CTavernWindow::close, this), 310, 428, "ICANCEL.DEF", SDLK_ESCAPE); - recruit = new CAdventureMapButton("", "", boost::bind(&CTavernWindow::recruitb, this), 272, 355, "TPTAV01.DEF", SDLK_RETURN); - thiefGuild = new CAdventureMapButton(CGI->generaltexth->tavernInfo[5],"", boost::bind(&CTavernWindow::thievesguildb, this), 22, 428, "TPTAV02.DEF", SDLK_t); + cancel = new CButton(Point(310, 428), "ICANCEL.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[7]), boost::bind(&CTavernWindow::close, this), SDLK_ESCAPE); + recruit = new CButton(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), boost::bind(&CTavernWindow::recruitb, this), SDLK_RETURN); + thiefGuild = new CButton(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), boost::bind(&CTavernWindow::thievesguildb, this), SDLK_t); if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < 2500) //not enough gold { - recruit->hoverTexts[0] = CGI->generaltexth->tavernInfo[0]; //Cannot afford a Hero + recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero recruit->block(true); } else if(LOCPLINT->castleInt && LOCPLINT->cb->howManyHeroes(true) >= VLC->modh->settings.MAX_HEROES_AVAILABLE_PER_PLAYER) { - recruit->hoverTexts[0] = CGI->generaltexth->tavernInfo[1]; //Cannot recruit. You already have %d Heroes. - boost::algorithm::replace_first(recruit->hoverTexts[0],"%d",boost::lexical_cast(LOCPLINT->cb->howManyHeroes(true))); + //Cannot recruit. You already have %d Heroes. + recruit->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[1]) % LOCPLINT->cb->howManyHeroes(true))); recruit->block(true); } else if((!LOCPLINT->castleInt) && LOCPLINT->cb->howManyHeroes(false) >= VLC->modh->settings.MAX_HEROES_ON_MAP_PER_PLAYER) { - recruit->hoverTexts[0] = CGI->generaltexth->tavernInfo[1]; //Cannot recruit. You already have %d Heroes. - boost::algorithm::replace_first(recruit->hoverTexts[0], "%d", boost::lexical_cast(LOCPLINT->cb->howManyHeroes(false))); + //Cannot recruit. You already have %d Heroes. + recruit->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[1]) % LOCPLINT->cb->howManyHeroes(false))); recruit->block(true); } else if(LOCPLINT->castleInt && LOCPLINT->castleInt->town->visitingHero) { - recruit->hoverTexts[0] = CGI->generaltexth->tavernInfo[2]; //Cannot recruit. You already have a Hero in this town. + recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[2]); //Cannot recruit. You already have a Hero in this town. recruit->block(true); } else @@ -831,9 +815,8 @@ void CTavernWindow::show(SDL_Surface * to) // Selected hero just changed. Update RECRUIT button hover text if recruitment is allowed. oldSelected = selected; - recruit->hoverTexts[0] = CGI->generaltexth->tavernInfo[3]; //Recruit %s the %s - boost::algorithm::replace_first(recruit->hoverTexts[0],"%s",sel->h->name); - boost::algorithm::replace_first(recruit->hoverTexts[0],"%s",sel->h->type->heroClass->name); + //Recruit %s the %s + recruit->addHoverText(CButton::NORMAL, boost::str(boost::format(CGI->generaltexth->tavernInfo[3]) % sel->h->name % sel->h->type->heroClass->name)); } printAtMiddleWBLoc(sel->description, 146, 395, FONT_SMALL, 200, Colors::WHITE, to); @@ -1038,20 +1021,20 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, } //buttons - quit = new CAdventureMapButton(CGI->generaltexth->zelp[600], boost::bind(&CExchangeWindow::close, this), 732, 567, "IOKAY.DEF", SDLK_RETURN); + quit = new CButton(Point(732, 567), "IOKAY.DEF", CGI->generaltexth->zelp[600], boost::bind(&CExchangeWindow::close, this), SDLK_RETURN); if(queryID.getNum() > 0) - quit->callback += [=]{ LOCPLINT->cb->selectionMade(0, queryID); }; + quit->addCallback([=]{ LOCPLINT->cb->selectionMade(0, queryID); }); - questlogButton[0] = new CAdventureMapButton(CGI->generaltexth->heroscrn[0], "", boost::bind(&CExchangeWindow::questlog,this, 0), 10, 44, "hsbtns4.def"); - questlogButton[1] = new CAdventureMapButton(CGI->generaltexth->heroscrn[0], "", boost::bind(&CExchangeWindow::questlog,this, 1), 740, 44, "hsbtns4.def"); + questlogButton[0] = new CButton(Point( 10, 44), "hsbtns4.def", CButton::tooltip(CGI->generaltexth->heroscrn[0]), boost::bind(&CExchangeWindow::questlog,this, 0)); + questlogButton[1] = new CButton(Point(740, 44), "hsbtns4.def", CButton::tooltip(CGI->generaltexth->heroscrn[0]), boost::bind(&CExchangeWindow::questlog,this, 1)); Rect barRect(5, 578, 725, 18); ourBar = new CGStatusBar(new CPicture(*background, barRect, 5, 578, false)); //garrison interface garr = new CGarrisonInt(69, 131, 4, Point(418,0), *background, Point(69,131), heroInst[0],heroInst[1], true, true); - garr->addSplitBtn(new CAdventureMapButton(CGI->generaltexth->tcommands[3], "", boost::bind(&CGarrisonInt::splitClick, garr), 10, 132, "TSBTNS.DEF")); - garr->addSplitBtn(new CAdventureMapButton(CGI->generaltexth->tcommands[3], "", boost::bind(&CGarrisonInt::splitClick, garr), 740, 132, "TSBTNS.DEF")); + garr->addSplitBtn(new CButton( Point( 10, 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), boost::bind(&CGarrisonInt::splitClick, garr))); + garr->addSplitBtn(new CButton( Point(740, 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), boost::bind(&CGarrisonInt::splitClick, garr))); } CExchangeWindow::~CExchangeWindow() //d-tor @@ -1084,9 +1067,9 @@ CShipyardWindow::CShipyardWindow(const std::vector &cost, int state, int b goldPic = new CAnimImage("RESOURCE", Res::GOLD, 0, 100, 244); woodPic = new CAnimImage("RESOURCE", Res::WOOD, 0, 196, 244); - quit = new CAdventureMapButton(CGI->generaltexth->allTexts[599], "", boost::bind(&CShipyardWindow::close, this), 224, 312, "ICANCEL", SDLK_RETURN); - build = new CAdventureMapButton(CGI->generaltexth->allTexts[598], "", boost::bind(&CShipyardWindow::close, this), 42, 312, "IBUY30", SDLK_RETURN); - build->callback += onBuy; + quit = new CButton( Point(224, 312), "ICANCEL", CButton::tooltip(CGI->generaltexth->allTexts[599]), boost::bind(&CShipyardWindow::close, this), SDLK_RETURN); + build = new CButton( Point( 42, 312), "IBUY30", CButton::tooltip(CGI->generaltexth->allTexts[598]), boost::bind(&CShipyardWindow::close, this),SDLK_RETURN); + build->addCallback(onBuy); for(Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1)) { @@ -1111,10 +1094,9 @@ CPuzzleWindow::CPuzzleWindow(const int3 &GrailPos, double discoveredRatio): OBJ_CONSTRUCTION_CAPTURING_ALL; CCS->soundh->playSound(soundBase::OBELISK); - quitb = new CAdventureMapButton(CGI->generaltexth->allTexts[599], "", boost::bind(&CPuzzleWindow::close, this), 670, 538, "IOK6432.DEF", SDLK_RETURN); + quitb = new CButton(Point(670, 538), "IOK6432.DEF", CButton::tooltip(CGI->generaltexth->allTexts[599]), boost::bind(&CPuzzleWindow::close, this), SDLK_RETURN); quitb->assignedKeys.insert(SDLK_ESCAPE); quitb->borderColor = Colors::METALLIC_GOLD; - quitb->borderEnabled = true; new CPicture("PUZZLOGO", 607, 3); new CLabel(700, 95, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[463]); @@ -1253,10 +1235,10 @@ CTransformerWindow::CTransformerWindow(const CGHeroInstance * _hero, const CGTow if ( army->getCreature(SlotID(i)) ) items.push_back(new CItem(this, army->getStackCount(SlotID(i)), i)); - all = new CAdventureMapButton(CGI->generaltexth->zelp[590],boost::bind(&CTransformerWindow::addAll,this), 146,416,"ALTARMY.DEF",SDLK_a); - convert= new CAdventureMapButton(CGI->generaltexth->zelp[591],boost::bind(&CTransformerWindow::makeDeal,this), 269,416,"ALTSACR.DEF",SDLK_RETURN); - cancel = new CAdventureMapButton(CGI->generaltexth->zelp[592],boost::bind(&CTransformerWindow::close, this),392,416,"ICANCEL.DEF",SDLK_ESCAPE); - bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); + all = new CButton(Point(146, 416), "ALTARMY.DEF", CGI->generaltexth->zelp[590], [&] { addAll(); }, SDLK_a); + convert = new CButton(Point(269, 416), "ALTSACR.DEF", CGI->generaltexth->zelp[591], [&] { makeDeal(); }, SDLK_RETURN); + cancel = new CButton(Point(392, 416), "ICANCEL.DEF", CGI->generaltexth->zelp[592], [&] { close(); },SDLK_ESCAPE); + bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); new CLabel(153, 29,FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[485]);//holding area new CLabel(153+295, 29, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[486]);//transformer @@ -1373,8 +1355,7 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket for (int i=0; igeneraltexth->zelp[632], - boost::bind(&CUniversityWindow::close, this),200,313,"IOKAY.DEF",SDLK_RETURN); + cancel = new CButton(Point(200, 313), "IOKAY.DEF", CGI->generaltexth->zelp[632], [&]{ close(); }, SDLK_RETURN); bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); } @@ -1407,12 +1388,10 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bo boost::replace_first(text, "%s", CGI->generaltexth->skillName[SKILL]); boost::replace_first(text, "%d", "2000"); - confirm= new CAdventureMapButton(hoverText, text, boost::bind(&CUnivConfirmWindow::makeDeal, this, SKILL), - 148,299,"IBY6432.DEF",SDLK_RETURN); + confirm= new CButton(Point(148, 299), "IBY6432.DEF", CButton::tooltip(hoverText, text), [&]{makeDeal(SKILL);}, SDLK_RETURN); confirm->block(!available); - cancel = new CAdventureMapButton(CGI->generaltexth->zelp[631],boost::bind(&CUnivConfirmWindow::close, this), - 252,299,"ICANCEL.DEF",SDLK_ESCAPE); + cancel = new CButton(Point(252,299), "ICANCEL.DEF", CGI->generaltexth->zelp[631], [&]{ close(); }, SDLK_ESCAPE); bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); } @@ -1439,21 +1418,21 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance *visitor, const CGObjectIn currState.resize(slotsCount+1); costs.resize(slotsCount); totalSumm.resize(GameConstants::RESOURCE_QUANTITY); - std::vector files; - files += "APHLF1R.DEF", "APHLF1Y.DEF", "APHLF1G.DEF"; + for (int i=0; iblock(currState[i] == -1); + for (auto image : { "APHLF1R.DEF", "APHLF1Y.DEF", "APHLF1G.DEF" }) + upgrade[i]->addImage(image); } - files.clear(); - files += "APHLF4R.DEF", "APHLF4Y.DEF", "APHLF4G.DEF"; currState[slotsCount] = getState(SlotID(slotsCount)); - upgradeAll = new CAdventureMapButton(CGI->generaltexth->allTexts[432],"",boost::bind(&CHillFortWindow::makeDeal, this, SlotID(slotsCount)), - 30, 231, "", SDLK_0, &files); - quit = new CAdventureMapButton("","",boost::bind(&CHillFortWindow::close, this), 294, 275, "IOKAY.DEF", SDLK_RETURN); + upgradeAll = new CButton(Point(30, 231), "", CButton::tooltip(CGI->generaltexth->allTexts[432]), [&]{ makeDeal(SlotID(slotsCount));}, SDLK_0); + for (auto image : { "APHLF4R.DEF", "APHLF4Y.DEF", "APHLF4G.DEF" }) + upgradeAll->addImage(image); + + quit = new CButton(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), boost::bind(&CHillFortWindow::close, this), SDLK_RETURN); bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); garr = new CGarrisonInt(108, 60, 18, Point(),background->bg,Point(108,60),hero,nullptr); @@ -1483,7 +1462,7 @@ void CHillFortWindow::updateGarrisons() currState[i] = newState; upgrade[i]->setIndex(newState); upgrade[i]->block(currState[i] == -1); - upgrade[i]->hoverTexts[0] = getTextForSlot(SlotID(i)); + upgrade[i]->addHoverText(CButton::NORMAL, getTextForSlot(SlotID(i))); } int newState = getState(SlotID(slotsCount)); @@ -1614,7 +1593,7 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner): SThievesGuildInfo tgi; //info to be displayed LOCPLINT->cb->getThievesGuildInfo(tgi, owner); - exitb = new CAdventureMapButton (CGI->generaltexth->allTexts[600], "", boost::bind(&CThievesGuildWindow::close,this), 748, 556, "TPMAGE1", SDLK_RETURN); + exitb = new CButton (Point(748, 556), "TPMAGE1", CButton::tooltip(CGI->generaltexth->allTexts[600]), [&]{ close();}, SDLK_RETURN); exitb->assignedKeys.insert(SDLK_ESCAPE); statusBar = new CGStatusBar(3, 555, "TStatBar.bmp", 742); @@ -1800,9 +1779,9 @@ void CObjectListWindow::init(CIntObject * titlePic, std::string _title, std::str title = new CLabel(152, 27, FONT_BIG, CENTER, Colors::YELLOW, _title); descr = new CLabel(145, 133, FONT_SMALL, CENTER, Colors::WHITE, _descr); - ok = new CAdventureMapButton("","",boost::bind(&CObjectListWindow::elementSelected, this),15,402,"IOKAY.DEF", SDLK_RETURN); + ok = new CButton(Point(15, 402), "IOKAY.DEF", CButton::tooltip(), boost::bind(&CObjectListWindow::elementSelected, this), SDLK_RETURN); ok->block(true); - exit = new CAdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally,&GH, this),228,402,"ICANCEL.DEF",SDLK_ESCAPE); + exit = new CButton( Point(228, 402), "ICANCEL.DEF", CButton::tooltip(), boost::bind(&CGuiHandler::popIntTotally,&GH, this), SDLK_ESCAPE); if (titlePic) { diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index 7215eedce..94eae5d10 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -29,8 +29,8 @@ class CComponentBox; class CTextInput; class CListBox; class CLabelGroup; -class CHighlightableButton; -class CHighlightableButtonsGroup; +class CToggleButton; +class CToggleGroup; class CGStatusBar; /// Recruitment window where you can recruit creatures @@ -75,7 +75,7 @@ class CRecruitmentWindow : public CWindowObject std::vector cards; CSlider *slider; //for selecting amount - CAdventureMapButton *maxButton, *buyButton, *cancelButton; + CButton *maxButton, *buyButton, *cancelButton; //labels for visible values CLabel * title; CLabel * availableValue; @@ -106,7 +106,7 @@ class CSplitWindow : public CWindowObject CSlider *slider; CCreaturePic *animLeft, *animRight; //creature's animation - CAdventureMapButton *ok, *cancel; + CButton *ok, *cancel; CTextInput *leftInput, *rightInput; void setAmountText(std::string text, bool left); @@ -161,7 +161,7 @@ class CObjectListWindow : public CWindowObject CListBox * list; CIntObject * titleImage;//title image (castle gate\town portal picture) - CAdventureMapButton *ok, *exit; + CButton *ok, *exit; std::vector< std::pair > items;//all items present in list @@ -188,19 +188,19 @@ private: CLabel *title; CLabelGroup *leftGroup; CLabelGroup *rightGroup; - CAdventureMapButton *load, *save, *restart, *mainMenu, *quitGame, *backToMap; //load and restart are not used yet - CHighlightableButtonsGroup * heroMoveSpeed; - CHighlightableButtonsGroup * mapScrollSpeed; - CHighlightableButtonsGroup * musicVolume, * effectsVolume; + CButton *load, *save, *restart, *mainMenu, *quitGame, *backToMap; //load and restart are not used yet + CToggleGroup * heroMoveSpeed; + CToggleGroup * mapScrollSpeed; + CToggleGroup * musicVolume, * effectsVolume; //CHighlightableButton * showPath; - CHighlightableButton * showReminder; - CHighlightableButton * quickCombat; - CHighlightableButton * spellbookAnim; - CHighlightableButton * newCreatureWin; - CHighlightableButton * fullscreen; + CToggleButton * showReminder; + CToggleButton * quickCombat; + CToggleButton * spellbookAnim; + CToggleButton * newCreatureWin; + CToggleButton * fullscreen; - CAdventureMapButton *gameResButton; + CButton *gameResButton; CLabel *gameResLabel; SettingsListener onFullscreenChanged; @@ -258,7 +258,7 @@ public: int selected;//0 (left) or 1 (right) int oldSelected;//0 (left) or 1 (right) - CAdventureMapButton *thiefGuild, *cancel, *recruit; + CButton *thiefGuild, *cancel, *recruit; const CGObjectInstance *tavernObj; CTavernWindow(const CGObjectInstance *TavernObj); //c-tor @@ -273,7 +273,7 @@ class CExchangeWindow : public CWindowObject, public CWindowWithGarrison, public { CGStatusBar * ourBar; //internal statusbar - CAdventureMapButton * quit, * questlogButton[2]; + CButton * quit, * questlogButton[2]; std::vector secSkillAreas[2], primSkillAreas; @@ -311,7 +311,7 @@ public: CLabel *woodCost, *goldCost; CAnimImage *bgShip; - CAdventureMapButton *build, *quit; + CButton *build, *quit; CGStatusBar * statusBar; @@ -324,7 +324,7 @@ class CPuzzleWindow : public CWindowObject private: int3 grailPos; - CAdventureMapButton * quitb; + CButton * quitb; std::vector piecesToRemove; ui8 currentAlpha; @@ -360,7 +360,7 @@ public: const CGTownInstance *town;//market, town garrison is used if hero == nullptr std::vector items; - CAdventureMapButton *all, *convert, *cancel; + CButton *all, *convert, *cancel; CGStatusBar *bar; void makeDeal(); void addAll(); @@ -391,7 +391,7 @@ public: CPicture * green, * yellow, * red;//colored bars near skills std::vector items; - CAdventureMapButton *cancel; + CButton *cancel; CGStatusBar *bar; CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market); //c-tor @@ -403,7 +403,7 @@ class CUnivConfirmWindow : public CWindowObject public: CUniversityWindow * parent; CGStatusBar *bar; - CAdventureMapButton *confirm, *cancel; + CButton *confirm, *cancel; CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available); //c-tor void makeDeal(int skill); @@ -418,7 +418,7 @@ public: CGStatusBar * bar; CDefEssential *resources; CHeroArea *heroPic;//clickable hero image - CAdventureMapButton *quit,//closes window + CButton *quit,//closes window *upgradeAll,//upgrade all creatures *upgrade[7];//upgrade single creature @@ -443,7 +443,7 @@ class CThievesGuildWindow : public CWindowObject const CGObjectInstance * owner; CGStatusBar * statusBar; - CAdventureMapButton * exitb; + CButton * exitb; CMinorResDataBar * resdatabar; public: diff --git a/client/windows/InfoWindows.cpp b/client/windows/InfoWindows.cpp index 876b0ae3c..8c7ff3a5e 100644 --- a/client/windows/InfoWindows.cpp +++ b/client/windows/InfoWindows.cpp @@ -72,10 +72,10 @@ CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperl ID = askID; for(int i=0;i= 0) - buttons.back()->callback += boost::bind(&CSelWindow::madeChoice,this); - buttons[i]->callback += boost::bind(&CInfoWindow::close,this); //each button will close the window apart from call-defined actions + buttons.back()->addCallback(boost::bind(&CSelWindow::madeChoice,this)); + buttons[i]->addCallback(boost::bind(&CInfoWindow::close,this)); //each button will close the window apart from call-defined actions } text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); @@ -84,7 +84,7 @@ CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperl buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape if(buttons.size() > 1 && askID.getNum() >= 0) //cancel button functionality - buttons.back()->callback += boost::bind(&CCallback::selectionMade,LOCPLINT->cb.get(),0,askID); + buttons.back()->addCallback(boost::bind(&CCallback::selectionMade,LOCPLINT->cb.get(),0,askID)); for(int i=0;iborderColor = Colors::METALLIC_GOLD; - button->borderEnabled = true; - button->callback.add(Button.second); //each button will close the window apart from call-defined actions + button->addCallback(Button.second); //each button will close the window apart from call-defined actions buttons.push_back(button); } @@ -199,9 +198,9 @@ void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector >("ICANCEL.DEF",0)); CInfoWindow * temp = new CInfoWindow(text, player, components ? *components : std::vector(), pom, DelComps); for(auto & elem : onYes.funcs) - temp->buttons[0]->callback += elem; + temp->buttons[0]->addCallback(elem); for(auto & elem : onNo.funcs) - temp->buttons[1]->callback += elem; + temp->buttons[1]->addCallback(elem); GH.pushInt(temp); } @@ -211,7 +210,7 @@ void CInfoWindow::showOkDialog(const std::string & text, const std::vector > > pom; pom.push_back(std::pair >("IOKAY.DEF",0)); CInfoWindow * temp = new CInfoWindow(text, player, *components, pom, delComps); - temp->buttons[0]->callback += onOk; + temp->buttons[0]->addCallback(onOk); GH.pushInt(temp); } diff --git a/client/windows/InfoWindows.h b/client/windows/InfoWindows.h index cec5441c6..afb5e3f95 100644 --- a/client/windows/InfoWindows.h +++ b/client/windows/InfoWindows.h @@ -14,7 +14,7 @@ class CComponent; class CSelectableComponent; class CGGarrison; class CTextBox; -class CAdventureMapButton; +class CButton; class CSlider; /* @@ -46,7 +46,7 @@ public: typedef std::vector TCompsInfo; QueryID ID; //for identification CTextBox *text; - std::vector buttons; + std::vector buttons; std::vector components; CSlider *slider; diff --git a/config/translate.json b/config/translate.json index 7a93eabf5..634355303 100644 --- a/config/translate.json +++ b/config/translate.json @@ -55,6 +55,13 @@ "allOf" : "All of the following:", "noneOf" : "None of the following:" }, + "heroWindow" : { + "openCommander" : + { + "label" : "Open commander window", + "help" : "Displays information about commander of this hero" + } + }, "creatureWindow" : { "showBonuses" :