1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-30 12:32:36 +00:00
OpenMW/apps/openmw/mwgui/journalwindow.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

656 lines
23 KiB
C++
Raw Normal View History

#include "journalwindow.hpp"
#include <set>
#include <stack>
#include <string>
#include <utility>
2015-01-10 02:50:43 +01:00
#include <MyGUI_Button.h>
#include <MyGUI_InputManager.h>
2015-01-10 02:50:43 +01:00
#include <MyGUI_TextBox.h>
#include <components/misc/strings/algorithm.hpp>
#include <components/widgets/imagebutton.hpp>
#include <components/widgets/list.hpp>
2015-01-10 02:50:43 +01:00
#include "../mwbase/environment.hpp"
#include "../mwbase/journal.hpp"
#include "../mwbase/windowmanager.hpp"
#include "bookpage.hpp"
#include "journalbooks.hpp"
#include "journalviewmodel.hpp"
#include "windowbase.hpp"
2012-01-17 13:53:27 +01:00
namespace
{
2023-05-08 17:18:18 +02:00
static constexpr std::string_view OptionsOverlay = "OptionsOverlay";
static constexpr std::string_view OptionsBTN = "OptionsBTN";
static constexpr std::string_view PrevPageBTN = "PrevPageBTN";
static constexpr std::string_view NextPageBTN = "NextPageBTN";
static constexpr std::string_view CloseBTN = "CloseBTN";
static constexpr std::string_view JournalBTN = "JournalBTN";
static constexpr std::string_view TopicsBTN = "TopicsBTN";
static constexpr std::string_view QuestsBTN = "QuestsBTN";
static constexpr std::string_view CancelBTN = "CancelBTN";
static constexpr std::string_view ShowAllBTN = "ShowAllBTN";
static constexpr std::string_view ShowActiveBTN = "ShowActiveBTN";
static constexpr std::string_view PageOneNum = "PageOneNum";
static constexpr std::string_view PageTwoNum = "PageTwoNum";
static constexpr std::string_view TopicsList = "TopicsList";
static constexpr std::string_view QuestsList = "QuestsList";
static constexpr std::string_view LeftBookPage = "LeftBookPage";
static constexpr std::string_view RightBookPage = "RightBookPage";
static constexpr std::string_view LeftTopicIndex = "LeftTopicIndex";
static constexpr std::string_view CenterTopicIndex = "CenterTopicIndex";
static constexpr std::string_view RightTopicIndex = "RightTopicIndex";
struct JournalWindowImpl : MWGui::JournalBooks, MWGui::JournalWindow
{
struct DisplayState
{
unsigned int mPage;
Book mBook;
};
typedef std::stack<DisplayState> DisplayStateStack;
DisplayStateStack mStates;
Book mTopicIndexBook;
bool mQuestMode;
bool mOptionsMode;
bool mTopicsMode;
bool mAllQuests;
template <typename T>
2023-05-08 17:18:18 +02:00
T* getWidget(std::string_view name)
{
T* widget;
WindowBase::getWidget(widget, name);
return widget;
}
template <typename value_type>
2023-05-08 17:18:18 +02:00
void setText(std::string_view name, value_type const& value)
{
getWidget<MyGUI::TextBox>(name)->setCaption(MyGUI::utility::toString(value));
}
2023-05-08 17:18:18 +02:00
void setVisible(std::string_view name, bool visible) { getWidget<MyGUI::Widget>(name)->setVisible(visible); }
2023-05-08 17:18:18 +02:00
void adviseButtonClick(std::string_view name, void (JournalWindowImpl::*handler)(MyGUI::Widget*))
{
getWidget<MyGUI::Widget>(name)->eventMouseButtonClick += newDelegate(this, handler);
}
void adviseKeyPress(
2023-05-08 17:18:18 +02:00
std::string_view name, void (JournalWindowImpl::*handler)(MyGUI::Widget*, MyGUI::KeyCode, MyGUI::Char))
{
getWidget<MyGUI::Widget>(name)->eventKeyButtonPressed += newDelegate(this, handler);
}
2023-05-08 17:18:18 +02:00
MWGui::BookPage* getPage(std::string_view name) { return getWidget<MWGui::BookPage>(name); }
2023-07-29 11:44:39 +04:00
JournalWindowImpl(MWGui::JournalViewModel::Ptr model, bool questList, ToUTF8::FromType encoding)
: JournalBooks(std::move(model), encoding)
, JournalWindow()
{
center();
adviseButtonClick(OptionsBTN, &JournalWindowImpl::notifyOptions);
adviseButtonClick(PrevPageBTN, &JournalWindowImpl::notifyPrevPage);
adviseButtonClick(NextPageBTN, &JournalWindowImpl::notifyNextPage);
adviseButtonClick(CloseBTN, &JournalWindowImpl::notifyClose);
adviseButtonClick(JournalBTN, &JournalWindowImpl::notifyJournal);
adviseButtonClick(TopicsBTN, &JournalWindowImpl::notifyTopics);
adviseButtonClick(QuestsBTN, &JournalWindowImpl::notifyQuests);
adviseButtonClick(CancelBTN, &JournalWindowImpl::notifyCancel);
adviseButtonClick(ShowAllBTN, &JournalWindowImpl::notifyShowAll);
adviseButtonClick(ShowActiveBTN, &JournalWindowImpl::notifyShowActive);
adviseKeyPress(OptionsBTN, &JournalWindowImpl::notifyKeyPress);
adviseKeyPress(PrevPageBTN, &JournalWindowImpl::notifyKeyPress);
adviseKeyPress(NextPageBTN, &JournalWindowImpl::notifyKeyPress);
adviseKeyPress(CloseBTN, &JournalWindowImpl::notifyKeyPress);
adviseKeyPress(JournalBTN, &JournalWindowImpl::notifyKeyPress);
Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked);
2022-10-14 00:41:59 +02:00
Gui::MWList* topicsList = getWidget<Gui::MWList>(TopicsList);
topicsList->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyTopicSelected);
{
2023-05-14 22:51:43 +02:00
MWGui::BookPage::ClickCallback callback = [this](intptr_t linkId) { notifyTopicClicked(linkId); };
2022-09-22 21:26:05 +03:00
getPage(LeftBookPage)->adviseLinkClicked(callback);
getPage(RightBookPage)->adviseLinkClicked(callback);
getPage(LeftBookPage)->eventMouseWheel
+= MyGUI::newDelegate(this, &JournalWindowImpl::notifyMouseWheel);
getPage(RightBookPage)->eventMouseWheel
+= MyGUI::newDelegate(this, &JournalWindowImpl::notifyMouseWheel);
}
{
2023-05-14 22:51:43 +02:00
MWGui::BookPage::ClickCallback callback
2023-05-15 21:06:05 +02:00
= [this](MWGui::TypesetBook::InteractiveId index) { notifyIndexLinkClicked(index); };
getPage(LeftTopicIndex)->adviseLinkClicked(callback);
2018-06-18 13:43:39 +04:00
getPage(CenterTopicIndex)->adviseLinkClicked(callback);
getPage(RightTopicIndex)->adviseLinkClicked(callback);
}
2013-05-08 13:55:15 +02:00
adjustButton(PrevPageBTN);
float nextButtonScale = adjustButton(NextPageBTN);
2013-05-08 13:55:15 +02:00
adjustButton(CloseBTN);
adjustButton(CancelBTN);
adjustButton(JournalBTN);
Gui::ImageButton* optionsButton = getWidget<Gui::ImageButton>(OptionsBTN);
Gui::ImageButton* showActiveButton = getWidget<Gui::ImageButton>(ShowActiveBTN);
Gui::ImageButton* showAllButton = getWidget<Gui::ImageButton>(ShowAllBTN);
Gui::ImageButton* questsButton = getWidget<Gui::ImageButton>(QuestsBTN);
Gui::ImageButton* nextButton = getWidget<Gui::ImageButton>(NextPageBTN);
if (nextButton->getSize().width == 64)
{
// english button has a 7 pixel wide strip of garbage on its right edge
nextButton->setSize(64 - 7, nextButton->getSize().height);
nextButton->setImageCoord(
MyGUI::IntCoord(0, 0, (64 - 7) * nextButtonScale, nextButton->getSize().height * nextButtonScale));
}
if (!questList)
{
// If tribunal is not installed (-> no options button), we still want the Topics button available,
// so place it where the options button would have been
Gui::ImageButton* topicsButton = getWidget<Gui::ImageButton>(TopicsBTN);
topicsButton->detachFromWidget();
topicsButton->attachToWidget(optionsButton->getParent());
topicsButton->setPosition(optionsButton->getPosition());
topicsButton->eventMouseButtonClick.clear();
topicsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &JournalWindowImpl::notifyOptions);
optionsButton->setVisible(false);
showActiveButton->setVisible(false);
showAllButton->setVisible(false);
questsButton->setVisible(false);
adjustButton(TopicsBTN);
}
else
{
optionsButton->setImage("textures/tx_menubook_options.dds");
showActiveButton->setImage("textures/tx_menubook_quests_active.dds");
showAllButton->setImage("textures/tx_menubook_quests_all.dds");
questsButton->setImage("textures/tx_menubook_quests.dds");
adjustButton(ShowAllBTN);
adjustButton(ShowActiveBTN);
adjustButton(OptionsBTN);
adjustButton(QuestsBTN);
adjustButton(TopicsBTN);
int topicsWidth = getWidget<MyGUI::Widget>(TopicsBTN)->getSize().width;
int cancelLeft = getWidget<MyGUI::Widget>(CancelBTN)->getPosition().left;
int cancelRight = getWidget<MyGUI::Widget>(CancelBTN)->getPosition().left
+ getWidget<MyGUI::Widget>(CancelBTN)->getSize().width;
getWidget<MyGUI::Widget>(QuestsBTN)->setPosition(
cancelRight, getWidget<MyGUI::Widget>(QuestsBTN)->getPosition().top);
// Usually Topics, Quests, and Cancel buttons have the 64px width, so we can place the Topics left-up
// from the Cancel button, and the Quests right-up from the Cancel button. But in some installations,
// e.g. German one, the Topics button has the 128px width, so we should place it exactly left from the
// Quests button.
if (topicsWidth == 64)
{
getWidget<MyGUI::Widget>(TopicsBTN)->setPosition(
cancelLeft - topicsWidth, getWidget<MyGUI::Widget>(TopicsBTN)->getPosition().top);
}
else
{
int questLeft = getWidget<MyGUI::Widget>(QuestsBTN)->getPosition().left;
getWidget<MyGUI::Widget>(TopicsBTN)->setPosition(
questLeft - topicsWidth, getWidget<MyGUI::Widget>(TopicsBTN)->getPosition().top);
}
}
mQuestMode = false;
mAllQuests = false;
mOptionsMode = false;
mTopicsMode = false;
}
void onOpen() override
{
mModel->load();
setBookMode();
Book journalBook;
if (mModel->isEmpty())
journalBook = createEmptyJournalBook();
else
journalBook = createJournalBook();
pushBook(journalBook, 0);
// fast forward to the last page
if (!mStates.empty())
{
unsigned int& page = mStates.top().mPage;
page = mStates.top().mBook->pageCount() - 1;
if (page % 2)
--page;
}
updateShowingPages();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(getWidget<MyGUI::Widget>(CloseBTN));
}
void onClose() override
{
mModel->unload();
getPage(LeftBookPage)->showPage(Book(), 0);
getPage(RightBookPage)->showPage(Book(), 0);
2013-02-09 10:44:20 -08:00
while (!mStates.empty())
mStates.pop();
mTopicIndexBook.reset();
}
void setVisible(bool newValue) override { WindowBase::setVisible(newValue); }
void setBookMode()
{
mOptionsMode = false;
mTopicsMode = false;
setVisible(OptionsBTN, true);
setVisible(OptionsOverlay, false);
updateShowingPages();
updateCloseJournalButton();
}
void setOptionsMode()
{
mOptionsMode = true;
mTopicsMode = false;
setVisible(OptionsBTN, false);
setVisible(OptionsOverlay, true);
setVisible(PrevPageBTN, false);
setVisible(NextPageBTN, false);
setVisible(CloseBTN, false);
setVisible(JournalBTN, false);
setVisible(TopicsList, false);
setVisible(QuestsList, mQuestMode);
setVisible(LeftTopicIndex, !mQuestMode);
2018-06-18 13:43:39 +04:00
setVisible(CenterTopicIndex, !mQuestMode);
setVisible(RightTopicIndex, !mQuestMode);
setVisible(ShowAllBTN, mQuestMode && !mAllQuests);
setVisible(ShowActiveBTN, mQuestMode && mAllQuests);
// TODO: figure out how to make "options" page overlay book page
// correctly, so that text may show underneath
getPage(RightBookPage)->showPage(Book(), 0);
// If in quest mode, ensure the quest list is updated
if (mQuestMode)
notifyQuests(getWidget<MyGUI::Widget>(QuestsList));
2017-07-29 19:41:46 +04:00
else
notifyTopics(getWidget<MyGUI::Widget>(TopicsList));
}
2023-07-29 11:44:39 +04:00
void pushBook(Book& book, unsigned int page)
{
DisplayState bs;
bs.mPage = page;
bs.mBook = book;
mStates.push(bs);
updateShowingPages();
updateCloseJournalButton();
}
2023-07-29 11:44:39 +04:00
void replaceBook(Book& book, unsigned int page)
{
assert(!mStates.empty());
mStates.top().mBook = book;
mStates.top().mPage = page;
updateShowingPages();
}
void popBook()
{
mStates.pop();
updateShowingPages();
updateCloseJournalButton();
}
void updateCloseJournalButton()
{
setVisible(CloseBTN, mStates.size() < 2);
setVisible(JournalBTN, mStates.size() >= 2);
}
void updateShowingPages()
{
Book book;
unsigned int page;
unsigned int relPages;
if (!mStates.empty())
{
book = mStates.top().mBook;
page = mStates.top().mPage;
relPages = book->pageCount() - page;
}
else
{
page = 0;
relPages = 0;
}
MyGUI::Widget* nextPageBtn = getWidget<MyGUI::Widget>(NextPageBTN);
MyGUI::Widget* prevPageBtn = getWidget<MyGUI::Widget>(PrevPageBTN);
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
bool nextPageVisible = relPages > 2;
nextPageBtn->setVisible(nextPageVisible);
bool prevPageVisible = page > 0;
prevPageBtn->setVisible(prevPageVisible);
if (focus == nextPageBtn && !nextPageVisible && prevPageVisible)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(prevPageBtn);
else if (focus == prevPageBtn && !prevPageVisible && nextPageVisible)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nextPageBtn);
setVisible(PageOneNum, relPages > 0);
setVisible(PageTwoNum, relPages > 1);
getPage(LeftBookPage)->showPage((relPages > 0) ? book : Book(), page + 0);
getPage(RightBookPage)->showPage((relPages > 0) ? book : Book(), page + 1);
setText(PageOneNum, page + 1);
setText(PageTwoNum, page + 2);
}
void notifyKeyPress(MyGUI::Widget* sender, MyGUI::KeyCode key, MyGUI::Char character)
{
if (key == MyGUI::KeyCode::ArrowUp)
notifyPrevPage(sender);
else if (key == MyGUI::KeyCode::ArrowDown)
notifyNextPage(sender);
}
void notifyTopicClicked(intptr_t linkId)
{
Book topicBook = createTopicBook(linkId);
if (mStates.size() > 1)
replaceBook(topicBook, 0);
else
pushBook(topicBook, 0);
setVisible(OptionsOverlay, false);
setVisible(OptionsBTN, true);
setVisible(JournalBTN, true);
mOptionsMode = false;
mTopicsMode = false;
2017-07-29 19:41:46 +04:00
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
}
2022-10-14 00:41:59 +02:00
void notifyTopicSelected(const std::string& topicIdString, int id)
{
2022-10-14 00:41:59 +02:00
ESM::RefId topic = ESM::RefId::stringRefId(topicIdString);
const MWBase::Journal* journal = MWBase::Environment::get().getJournal();
intptr_t topicId = 0; /// \todo get rid of intptr ids
for (MWBase::Journal::TTopicIter i = journal->topicBegin(); i != journal->topicEnd(); ++i)
{
if (i->first == topic)
topicId = intptr_t(&i->second);
}
notifyTopicClicked(topicId);
}
void notifyQuestClicked(const std::string& name, int id)
{
Book book = createQuestBook(name);
if (mStates.size() > 1)
replaceBook(book, 0);
else
pushBook(book, 0);
setVisible(OptionsOverlay, false);
setVisible(OptionsBTN, true);
setVisible(JournalBTN, true);
mOptionsMode = false;
2017-07-29 19:41:46 +04:00
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
}
2011-12-29 17:58:58 +01:00
2013-05-06 16:04:28 +02:00
void notifyOptions(MyGUI::Widget* _sender)
{
setOptionsMode();
if (!mTopicIndexBook)
mTopicIndexBook = createTopicIndexBook();
if (mIndexPagesCount == 3)
2018-06-18 13:43:39 +04:00
{
getPage(LeftTopicIndex)->showPage(mTopicIndexBook, 0);
getPage(CenterTopicIndex)->showPage(mTopicIndexBook, 1);
getPage(RightTopicIndex)->showPage(mTopicIndexBook, 2);
}
else
{
getPage(LeftTopicIndex)->showPage(mTopicIndexBook, 0);
getPage(RightTopicIndex)->showPage(mTopicIndexBook, 1);
}
}
2013-05-06 16:04:28 +02:00
void notifyJournal(MyGUI::Widget* _sender)
{
assert(mStates.size() > 1);
popBook();
2017-07-29 19:41:46 +04:00
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
}
2012-01-16 17:46:25 +01:00
2017-08-04 20:21:13 +04:00
void notifyIndexLinkClicked(MWGui::TypesetBook::InteractiveId index)
{
setVisible(LeftTopicIndex, false);
2018-06-18 13:43:39 +04:00
setVisible(CenterTopicIndex, false);
setVisible(RightTopicIndex, false);
setVisible(TopicsList, true);
mTopicsMode = true;
Gui::MWList* list = getWidget<Gui::MWList>(TopicsList);
list->clear();
AddNamesToList add(list);
2017-08-04 20:21:13 +04:00
mModel->visitTopicNamesStartingWith(index, add);
list->adjustSize();
2017-07-29 19:41:46 +04:00
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
}
2013-05-06 16:04:28 +02:00
void notifyTopics(MyGUI::Widget* _sender)
{
mQuestMode = false;
mTopicsMode = false;
setVisible(LeftTopicIndex, true);
2018-06-18 13:43:39 +04:00
setVisible(CenterTopicIndex, true);
setVisible(RightTopicIndex, true);
setVisible(TopicsList, false);
setVisible(QuestsList, false);
setVisible(ShowAllBTN, false);
setVisible(ShowActiveBTN, false);
2017-07-29 19:41:46 +04:00
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
}
struct AddNamesToList
{
AddNamesToList(Gui::MWList* list)
: mList(list)
{
}
2022-09-22 21:26:05 +03:00
Gui::MWList* mList;
2022-08-24 20:38:52 +02:00
void operator()(std::string_view name, bool finished = false) { mList->addItem(name); }
};
struct SetNamesInactive
{
SetNamesInactive(Gui::MWList* list)
: mList(list)
{
}
Gui::MWList* mList;
2022-08-24 20:38:52 +02:00
void operator()(std::string_view name, bool finished)
{
if (finished)
{
mList->getItemWidget(name)->setStateSelected(true);
}
}
};
2013-05-06 16:04:28 +02:00
void notifyQuests(MyGUI::Widget* _sender)
{
mQuestMode = true;
setVisible(LeftTopicIndex, false);
setVisible(CenterTopicIndex, false);
setVisible(RightTopicIndex, false);
setVisible(TopicsList, false);
setVisible(QuestsList, true);
setVisible(ShowAllBTN, !mAllQuests);
setVisible(ShowActiveBTN, mAllQuests);
Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
list->clear();
AddNamesToList add(list);
mModel->visitQuestNames(!mAllQuests, add);
list->sort();
list->adjustSize();
if (mAllQuests)
{
SetNamesInactive setInactive(list);
2021-01-09 13:52:01 +04:00
mModel->visitQuestNames(false, setInactive);
}
2017-07-29 19:41:46 +04:00
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
}
2013-05-06 16:04:28 +02:00
void notifyShowAll(MyGUI::Widget* _sender)
{
mAllQuests = true;
notifyQuests(_sender);
}
2013-05-06 16:04:28 +02:00
void notifyShowActive(MyGUI::Widget* _sender)
{
mAllQuests = false;
notifyQuests(_sender);
}
2013-05-06 16:04:28 +02:00
void notifyCancel(MyGUI::Widget* _sender)
{
if (mTopicsMode)
{
notifyTopics(_sender);
}
else
{
setBookMode();
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
}
}
2013-05-06 16:04:28 +02:00
void notifyClose(MyGUI::Widget* _sender)
{
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
Initial commit: In ESM structures, replace the string members that are RefIds to other records, to a new strong type The strong type is actually just a string underneath, but this will help in the future to have a distinction so it's easier to search and replace when we use an integer ID Slowly going through all the changes to make, still hundreds of errors a lot of functions/structures use std::string or stringview to designate an ID. So it takes time Continues slowly replacing ids. There are technically more and more compilation errors I have good hope that there is a point where the amount of errors will dramatically go down as all the main functions use the ESM::RefId type Continue moving forward, changes to the stores slowly moving along Starting to see the fruit of those changes. still many many error, but more and more Irun into a situation where a function is sandwiched between two functions that use the RefId type. More replacements. Things are starting to get easier I can see more and more often the issue is that the function is awaiting a RefId, but is given a string there is less need to go down functions and to fix a long list of them. Still moving forward, and for the first time error count is going down! Good pace, not sure about topics though, mId and mName are actually the same thing and are used interchangeably Cells are back to using string for the name, haven't fixed everything yet. Many other changes Under the bar of 400 compilation errors. more good progress <100 compile errors! More progress Game settings store can use string for find, it was a bit absurd how every use of it required to create refId from string some more progress on other fronts Mostly game settings clean one error opened a lot of other errors. Down to 18, but more will prbably appear only link errors left?? Fixed link errors OpenMW compiles, and launches, with some issues, but still!
2022-09-25 13:17:09 +02:00
winMgr->playSound(ESM::RefId::stringRefId("book close"));
winMgr->popGuiMode();
}
void notifyMouseWheel(MyGUI::Widget* sender, int rel)
{
if (rel < 0)
notifyNextPage(sender);
else
notifyPrevPage(sender);
}
2013-05-06 16:04:28 +02:00
void notifyNextPage(MyGUI::Widget* _sender)
{
if (mOptionsMode)
return;
if (!mStates.empty())
{
unsigned int& page = mStates.top().mPage;
Book book = mStates.top().mBook;
if (page + 2 < book->pageCount())
{
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
2017-07-29 19:41:46 +04:00
page += 2;
updateShowingPages();
}
}
}
2013-05-06 16:04:28 +02:00
void notifyPrevPage(MyGUI::Widget* _sender)
{
if (mOptionsMode)
return;
if (!mStates.empty())
{
unsigned int& page = mStates.top().mPage;
if (page >= 2)
{
MWBase::Environment::get().getWindowManager()->playSound(ESM::RefId::stringRefId("book page"));
2017-07-29 19:41:46 +04:00
page -= 2;
updateShowingPages();
}
}
}
};
2012-01-17 13:53:27 +01:00
}
// glue the implementation to the interface
2022-08-31 21:07:59 +02:00
std::unique_ptr<MWGui::JournalWindow> MWGui::JournalWindow::create(
JournalViewModel::Ptr Model, bool questList, ToUTF8::FromType encoding)
{
2022-08-31 21:07:59 +02:00
return std::make_unique<JournalWindowImpl>(Model, questList, encoding);
}
MWGui::JournalWindow::JournalWindow()
: BookWindowBase("openmw_journal.layout")
{
}