diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index db6eabbb2c..d2b9ea55f8 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -113,10 +113,7 @@ namespace MWGui struct TypesetBookImpl : TypesetBook { - typedef std::vector Content; - typedef std::list Contents; - typedef Utf8Stream::Point Utf8Point; - typedef std::pair Range; + typedef std::pair Range; struct StyleImpl : BookTypesetter::Style { @@ -127,29 +124,28 @@ namespace MWGui InteractiveId mInteractiveId; bool match(MyGUI::IFont* tstFont, const MyGUI::Colour& tstHotColour, const MyGUI::Colour& tstActiveColour, - const MyGUI::Colour& tstNormalColour, intptr_t tstInteractiveId) + const MyGUI::Colour& tstNormalColour, InteractiveId tstInteractiveId) const { return (mFont == tstFont) - && partal_match(tstHotColour, tstActiveColour, tstNormalColour, tstInteractiveId); + && partialMatch(tstHotColour, tstActiveColour, tstNormalColour, tstInteractiveId); } bool match(std::string_view tstFont, const MyGUI::Colour& tstHotColour, - const MyGUI::Colour& tstActiveColour, const MyGUI::Colour& tstNormalColour, intptr_t tstInteractiveId) + const MyGUI::Colour& tstActiveColour, const MyGUI::Colour& tstNormalColour, + InteractiveId tstInteractiveId) const { return (mFont->getResourceName() == tstFont) - && partal_match(tstHotColour, tstActiveColour, tstNormalColour, tstInteractiveId); + && partialMatch(tstHotColour, tstActiveColour, tstNormalColour, tstInteractiveId); } - bool partal_match(const MyGUI::Colour& tstHotColour, const MyGUI::Colour& tstActiveColour, - const MyGUI::Colour& tstNormalColour, intptr_t tstInteractiveId) + bool partialMatch(const MyGUI::Colour& tstHotColour, const MyGUI::Colour& tstActiveColour, + const MyGUI::Colour& tstNormalColour, InteractiveId tstInteractiveId) const { return (mHotColour == tstHotColour) && (mActiveColour == tstActiveColour) && (mNormalColour == tstNormalColour) && (mInteractiveId == tstInteractiveId); } }; - typedef std::list Styles; - struct Run { StyleImpl* mStyle; @@ -158,19 +154,15 @@ namespace MWGui int mPrintableChars; }; - typedef std::vector Runs; - struct Line { - Runs mRuns; + std::vector mRuns; MyGUI::IntRect mRect; }; - typedef std::vector Lines; - struct Section { - Lines mLines; + std::vector mLines; MyGUI::IntRect mRect; }; @@ -180,12 +172,10 @@ namespace MWGui // A page is basically a "window" into a portion of the source text, similar to a ScrollView. typedef std::pair Page; - typedef std::vector Pages; - - Pages mPages; + std::vector mPages; Sections mSections; - Contents mContents; - Styles mStyles; + std::list mContents; + std::list mStyles; MyGUI::IntRect mRect; void setColour(size_t section, size_t line, size_t run, const MyGUI::Colour& colour) const override @@ -202,14 +192,14 @@ namespace MWGui virtual ~TypesetBookImpl() = default; - Range addContent(const BookTypesetter::Utf8Span& text) + Range addContent(std::string_view text) { - Contents::iterator i = mContents.insert(mContents.end(), Content(text.first, text.second)); + Content& content = mContents.emplace_back(text.begin(), text.end()); - if (i->empty()) - return Range(Utf8Point(nullptr), Utf8Point(nullptr)); + if (content.empty()) + return Range(nullptr, nullptr); - return Range(i->data(), i->data() + i->size()); + return Range(content.data(), content.data() + content.size()); } size_t pageCount() const override { return mPages.size(); } @@ -222,19 +212,19 @@ namespace MWGui template void visitRuns(int top, int bottom, MyGUI::IFont* font, Visitor const& visitor) const { - for (Sections::const_iterator i = mSections.begin(); i != mSections.end(); ++i) + for (const Section& section : mSections) { - if (top >= mRect.bottom || bottom <= i->mRect.top) + if (top >= mRect.bottom || bottom <= section.mRect.top) continue; - - for (Lines::const_iterator j = i->mLines.begin(); j != i->mLines.end(); ++j) + for (const Line& line : section.mLines) { - if (top >= j->mRect.bottom || bottom <= j->mRect.top) + if (top >= line.mRect.bottom || bottom <= line.mRect.top) continue; - - for (Runs::const_iterator k = j->mRuns.begin(); k != j->mRuns.end(); ++k) - if (!font || k->mStyle->mFont == font) - visitor(*i, *j, *k); + for (const Run& run : line.mRuns) + { + if (!font || run.mStyle->mFont == font) + visitor(section, line, run); + } } } } @@ -275,26 +265,26 @@ namespace MWGui StyleImpl* hitTest(int left, int top) const { - for (Sections::const_iterator i = mSections.begin(); i != mSections.end(); ++i) + for (const Section& section : mSections) { - if (top < i->mRect.top || top >= i->mRect.bottom) + if (top < section.mRect.top || top >= section.mRect.bottom) continue; - int left1 = left - i->mRect.left; + int left1 = left - section.mRect.left; - for (Lines::const_iterator j = i->mLines.begin(); j != i->mLines.end(); ++j) + for (const Line& line : section.mLines) { - if (top < j->mRect.top || top >= j->mRect.bottom) + if (top < line.mRect.top || top >= line.mRect.bottom) continue; - int left2 = left1 - j->mRect.left; + int left2 = left1 - line.mRect.left; - for (Runs::const_iterator k = j->mRuns.begin(); k != j->mRuns.end(); ++k) + for (const Run& run : line.mRuns) { - if (left2 < k->mLeft || left2 >= k->mRight) + if (left2 < run.mLeft || left2 >= run.mRight) continue; - return k->mStyle; + return run.mStyle; } } } @@ -304,9 +294,9 @@ namespace MWGui MyGUI::IFont* affectedFont(StyleImpl* style) { - for (Styles::iterator i = mStyles.begin(); i != mStyles.end(); ++i) - if (&*i == style) - return i->mFont; + for (const StyleImpl& s : mStyles) + if (&s == style) + return s.mFont; return nullptr; } @@ -331,14 +321,10 @@ namespace MWGui } }; - typedef TypesetBookImpl Book; - typedef std::shared_ptr BookPtr; - typedef std::vector::const_iterator PartialTextConstIterator; - int mPageWidth; int mPageHeight; - BookPtr mBook; + std::shared_ptr mBook; Section* mSection; Line* mLine; Run* mRun; @@ -347,7 +333,7 @@ namespace MWGui std::vector mPartialWhitespace; std::vector mPartialWord; - Book::Content const* mCurrentContent; + TypesetBookImpl::Content const* mCurrentContent; Alignment mCurrentAlignment; Typesetter(int width, int height) @@ -359,12 +345,12 @@ namespace MWGui , mCurrentContent(nullptr) , mCurrentAlignment(AlignLeft) { - mBook = std::make_shared(); + mBook = std::make_shared(); } virtual ~Typesetter() = default; - Style* createStyle(const std::string& fontName, const Colour& fontColour, bool useBookFont) override + Style* createStyle(const std::string& fontName, const MyGUI::Colour& fontColour, bool useBookFont) override { std::string fullFontName; if (fontName.empty()) @@ -375,9 +361,9 @@ namespace MWGui if (useBookFont) fullFontName = "Journalbook " + fullFontName; - for (Styles::iterator i = mBook->mStyles.begin(); i != mBook->mStyles.end(); ++i) - if (i->match(fullFontName, fontColour, fontColour, fontColour, 0)) - return &*i; + for (StyleImpl& style : mBook->mStyles) + if (style.match(fullFontName, fontColour, fontColour, fontColour, 0)) + return &style; MyGUI::IFont* font = MyGUI::FontManager::getInstance().getByName(fullFontName); if (!font) @@ -393,15 +379,15 @@ namespace MWGui return &style; } - Style* createHotStyle(Style* baseStyle, const Colour& normalColour, const Colour& hoverColour, - const Colour& activeColour, InteractiveId id, bool unique) override + Style* createHotStyle(Style* baseStyle, const MyGUI::Colour& normalColour, const MyGUI::Colour& hoverColour, + const MyGUI::Colour& activeColour, InteractiveId id, bool unique) override { StyleImpl* const baseStyleImpl = static_cast(baseStyle); if (!unique) - for (Styles::iterator i = mBook->mStyles.begin(); i != mBook->mStyles.end(); ++i) - if (i->match(baseStyleImpl->mFont, hoverColour, activeColour, normalColour, id)) - return &*i; + for (StyleImpl& style : mBook->mStyles) + if (style.match(baseStyleImpl->mFont, hoverColour, activeColour, normalColour, id)) + return &style; StyleImpl& style = *mBook->mStyles.insert(mBook->mStyles.end(), StyleImpl()); @@ -414,30 +400,30 @@ namespace MWGui return &style; } - void write(Style* style, Utf8Span text) override + void write(Style* style, std::string_view text) override { Range range = mBook->addContent(text); - writeImpl(static_cast(style), range.first, range.second); + writeImpl(static_cast(style), Utf8Stream(range.first, range.second)); } - intptr_t addContent(Utf8Span text, bool select) override + const Content* addContent(std::string_view text, bool select) override { add_partial_text(); - Contents::iterator i = mBook->mContents.insert(mBook->mContents.end(), Content(text.first, text.second)); + Content& content = mBook->mContents.emplace_back(text.begin(), text.end()); if (select) - mCurrentContent = &(*i); + mCurrentContent = &content; - return reinterpret_cast(&(*i)); + return &content; } - void selectContent(intptr_t contentHandle) override + void selectContent(const Content* contentHandle) override { add_partial_text(); - mCurrentContent = reinterpret_cast(contentHandle); + mCurrentContent = contentHandle; } void write(Style* style, size_t begin, size_t end) override @@ -446,10 +432,10 @@ namespace MWGui assert(end <= mCurrentContent->size()); assert(begin <= mCurrentContent->size()); - const Utf8Point contentBegin = mCurrentContent->data() + begin; - const Utf8Point contentEnd = mCurrentContent->data() + end; + const Utf8Stream::Point contentBegin = mCurrentContent->data() + begin; + const Utf8Stream::Point contentEnd = mCurrentContent->data() + end; - writeImpl(static_cast(style), contentBegin, contentEnd); + writeImpl(static_cast(style), Utf8Stream(contentBegin, contentEnd)); } void lineBreak(float margin) override @@ -486,7 +472,7 @@ namespace MWGui mCurrentAlignment = sectionAlignment; } - TypesetBook::Ptr complete() override + std::shared_ptr complete() override { int curPageStart = 0; int curPageStop = 0; @@ -497,26 +483,26 @@ namespace MWGui for (Sections::iterator i = mBook->mSections.begin(); i != mBook->mSections.end(); ++i, ++sa) { // apply alignment to individual lines... - for (Lines::iterator j = i->mLines.begin(); j != i->mLines.end(); ++j) + for (Line& line : i->mLines) { - int width = j->mRect.width(); + int width = line.mRect.width(); int excess = mPageWidth - width; switch (*sa) { default: case AlignLeft: - j->mRect.left = 0; + line.mRect.left = 0; break; case AlignCenter: - j->mRect.left = excess / 2; + line.mRect.left = excess / 2; break; case AlignRight: - j->mRect.left = excess; + line.mRect.left = excess; break; } - j->mRect.right = j->mRect.left + width; + line.mRect.right = line.mRect.left + width; } if (curPageStop == curPageStart) @@ -541,7 +527,7 @@ namespace MWGui // one. assert(curPageStart != curPageStop); - mBook->mPages.push_back(Page(curPageStart, curPageStop)); + mBook->mPages.emplace_back(curPageStart, curPageStop); curPageStart = i->mRect.top; curPageStop = i->mRect.bottom; @@ -553,7 +539,7 @@ namespace MWGui { // The section won't completely fit on the current page. Finish the current page and start a new // one. - mBook->mPages.push_back(Page(curPageStart, curPageStop)); + mBook->mPages.emplace_back(curPageStart, curPageStop); curPageStart = i->mRect.top; curPageStop = i->mRect.bottom; @@ -564,16 +550,16 @@ namespace MWGui { // Adjust to the top of the first line that does not fit on the current page anymore int splitPos = curPageStop; - for (Lines::iterator j = i->mLines.begin(); j != i->mLines.end(); ++j) + for (const Line& line : i->mLines) { - if (j->mRect.bottom > curPageStart + mPageHeight) + if (line.mRect.bottom > curPageStart + mPageHeight) { - splitPos = j->mRect.top; + splitPos = line.mRect.top; break; } } - mBook->mPages.push_back(Page(curPageStart, splitPos)); + mBook->mPages.emplace_back(curPageStart, splitPos); curPageStart = splitPos; curPageStop = splitPos; @@ -584,15 +570,13 @@ namespace MWGui } if (curPageStart != curPageStop) - mBook->mPages.push_back(Page(curPageStart, curPageStop)); + mBook->mPages.emplace_back(curPageStart, curPageStop); return mBook; } - void writeImpl(StyleImpl* style, Utf8Stream::Point begin, Utf8Stream::Point end) + void writeImpl(StyleImpl* style, Utf8Stream&& stream) { - Utf8Stream stream(begin, end); - while (!stream.eof()) { if (ucsLineBreak(stream.peek())) @@ -651,10 +635,10 @@ namespace MWGui int spaceWidth = 0; int wordWidth = 0; - for (PartialTextConstIterator i = mPartialWhitespace.begin(); i != mPartialWhitespace.end(); ++i) - spaceWidth += i->mWidth; - for (PartialTextConstIterator i = mPartialWord.begin(); i != mPartialWord.end(); ++i) - wordWidth += i->mWidth; + for (const PartialText& partialText : mPartialWhitespace) + spaceWidth += partialText.mWidth; + for (const PartialText& partialText : mPartialWord) + wordWidth += partialText.mWidth; int left = mLine ? mLine->mRect.right : 0; @@ -666,21 +650,23 @@ namespace MWGui } else { - for (PartialTextConstIterator i = mPartialWhitespace.begin(); i != mPartialWhitespace.end(); ++i) + for (const PartialText& partialText : mPartialWhitespace) { int top = mLine ? mLine->mRect.top : mBook->mRect.bottom; - appendRun(i->mStyle, i->mBegin, i->mEnd, 0, left + i->mWidth, top + fontHeight); + appendRun(partialText.mStyle, partialText.mBegin, partialText.mEnd, 0, left + partialText.mWidth, + top + fontHeight); left = mLine->mRect.right; } } - for (PartialTextConstIterator i = mPartialWord.begin(); i != mPartialWord.end(); ++i) + for (const PartialText& partialText : mPartialWord) { int top = mLine ? mLine->mRect.top : mBook->mRect.bottom; - const int numChars = static_cast(i->mEnd - i->mBegin); - appendRun(i->mStyle, i->mBegin, i->mEnd, numChars, left + i->mWidth, top + fontHeight); + const int numChars = static_cast(partialText.mEnd - partialText.mBegin); + appendRun(partialText.mStyle, partialText.mBegin, partialText.mEnd, numChars, left + partialText.mWidth, + top + fontHeight); left = mLine->mRect.right; } @@ -747,7 +733,7 @@ namespace MWGui } }; - BookTypesetter::Ptr BookTypesetter::create(int pageWidth, int pageHeight) + std::shared_ptr BookTypesetter::create(int pageWidth, int pageHeight) { return std::make_shared(pageWidth, pageHeight); } @@ -932,17 +918,12 @@ namespace MWGui { MYGUI_RTTI_DERIVED(PageDisplay) protected: - typedef TypesetBookImpl::Section Section; - typedef TypesetBookImpl::Line Line; - typedef TypesetBookImpl::Run Run; bool mIsPageReset; size_t mPage; struct TextFormat : ISubWidget { - typedef MyGUI::IFont* Id; - - Id mFont; + MyGUI::IFont* mFont; int mCountVertex; MyGUI::ITexture* mTexture; MyGUI::RenderItem* mRenderItem; @@ -1017,16 +998,15 @@ namespace MWGui } public: - typedef TypesetBookImpl::StyleImpl Style; - typedef std::map> ActiveTextFormats; + typedef std::map> ActiveTextFormats; int mViewTop; int mViewBottom; - Style* mFocusItem; + TypesetBookImpl::StyleImpl* mFocusItem; bool mItemActive; MyGUI::MouseButton mLastDown; - std::function mLinkClicked; + std::function mLinkClicked; std::shared_ptr mBook; @@ -1072,7 +1052,7 @@ namespace MWGui void onMouseMove(int left, int top) { - Style* hit = nullptr; + TypesetBookImpl::StyleImpl* hit = nullptr; if (auto pos = getAdjustedPos(left, top, true)) if (pos->top <= mViewBottom) hit = mBook->hitTestWithMargin(pos->left, pos->top); @@ -1123,7 +1103,8 @@ namespace MWGui if (pos && mLastDown == id) { - Style* item = pos->top <= mViewBottom ? mBook->hitTestWithMargin(pos->left, pos->top) : nullptr; + TypesetBookImpl::StyleImpl* item + = pos->top <= mViewBottom ? mBook->hitTestWithMargin(pos->left, pos->top) : nullptr; bool clicked = mFocusItem == item; @@ -1138,7 +1119,7 @@ namespace MWGui } } - void showPage(TypesetBook::Ptr book, size_t newPage) + void showPage(std::shared_ptr book, size_t newPage) { std::shared_ptr newBook = std::dynamic_pointer_cast(book); @@ -1212,7 +1193,8 @@ namespace MWGui { } - void operator()(Section const& section, Line const& line, Run const& run) const + void operator()(const TypesetBookImpl::Section& section, const TypesetBookImpl::Line& line, + const TypesetBookImpl::Run& run) const { MyGUI::IFont* const font = run.mStyle->mFont; @@ -1281,7 +1263,8 @@ namespace MWGui { } - void operator()(Section const& section, Line const& line, Run const& run) const + void operator()(const TypesetBookImpl::Section& section, const TypesetBookImpl::Line& line, + const TypesetBookImpl::Run& run) const { bool isActive = run.mStyle->mInteractiveId && (run.mStyle == mPageDisplay->mFocusItem); @@ -1374,14 +1357,20 @@ namespace MWGui { } - void showPage(TypesetBook::Ptr book, size_t page) override { mPageDisplay->showPage(std::move(book), page); } + void showPage(std::shared_ptr book, size_t page) override + { + mPageDisplay->showPage(std::move(book), page); + } - void adviseLinkClicked(std::function linkClicked) override + void adviseLinkClicked(std::function linkClicked) override { mPageDisplay->mLinkClicked = std::move(linkClicked); } - void unadviseLinkClicked() override { mPageDisplay->mLinkClicked = std::function(); } + void unadviseLinkClicked() override + { + mPageDisplay->mLinkClicked = std::function(); + } void setFocusItem(BookTypesetter::Style* itemStyle) override { diff --git a/apps/openmw/mwgui/bookpage.hpp b/apps/openmw/mwgui/bookpage.hpp index b7b5784b72..ca5beae2dc 100644 --- a/apps/openmw/mwgui/bookpage.hpp +++ b/apps/openmw/mwgui/bookpage.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -17,7 +18,7 @@ namespace MWGui /// the book page widget. struct TypesetBook { - typedef std::shared_ptr Ptr; + using Content = std::vector; typedef intptr_t InteractiveId; /// Returns the number of pages in the document. @@ -40,12 +41,6 @@ namespace MWGui /// A factory class for creating a typeset book instance. struct BookTypesetter { - typedef std::shared_ptr Ptr; - typedef TypesetBook::InteractiveId InteractiveId; - typedef MyGUI::Colour Colour; - typedef uint8_t const* Utf8Point; - typedef std::pair Utf8Span; - virtual ~BookTypesetter() = default; enum Alignment @@ -62,16 +57,18 @@ namespace MWGui struct Style; /// A factory function for creating the default implementation of a book typesetter - static Ptr create(int pageWidth, int pageHeight); + static std::shared_ptr create(int pageWidth, int pageHeight); /// Create a simple text style consisting of a font and a text color. - virtual Style* createStyle(const std::string& fontName, const Colour& colour, bool useBookFont = true) = 0; + virtual Style* createStyle(const std::string& fontName, const MyGUI::Colour& colour, bool useBookFont = true) + = 0; /// Create a hyper-link style with a user-defined identifier based on an /// existing style. The unique flag forces a new instance of this style /// to be created even if an existing instance is present. - virtual Style* createHotStyle(Style* baseStyle, const Colour& normalColour, const Colour& hoverColour, - const Colour& activeColour, InteractiveId id, bool unique = true) + virtual Style* createHotStyle(Style* baseStyle, const MyGUI::Colour& normalColour, + const MyGUI::Colour& hoverColour, const MyGUI::Colour& activeColour, TypesetBook::InteractiveId id, + bool unique = true) = 0; /// Insert a line break into the document. Newline characters in the input @@ -89,22 +86,22 @@ namespace MWGui virtual void setSectionAlignment(Alignment sectionAlignment) = 0; // Layout a block of text with the specified style into the document. - virtual void write(Style* style, Utf8Span text) = 0; + virtual void write(Style* style, std::string_view text) = 0; /// Adds a content block to the document without laying it out. An /// identifier is returned that can be used to refer to it. If select /// is true, the block is activated to be references by future writes. - virtual intptr_t addContent(Utf8Span text, bool select = true) = 0; + virtual const TypesetBook::Content* addContent(std::string_view text, bool select = true) = 0; /// Select a previously created content block for future writes. - virtual void selectContent(intptr_t contentHandle) = 0; + virtual void selectContent(const TypesetBook::Content* contentHandle) = 0; /// Layout a span of the selected content block into the document /// using the specified style. virtual void write(Style* style, size_t begin, size_t end) = 0; /// Finalize the document layout, and return a pointer to it. - virtual TypesetBook::Ptr complete() = 0; + virtual std::shared_ptr complete() = 0; }; /// An interface to the BookPage widget. @@ -112,11 +109,10 @@ namespace MWGui { MYGUI_RTTI_DERIVED(BookPage) public: - typedef TypesetBook::InteractiveId InteractiveId; - typedef std::function ClickCallback; + using ClickCallback = std::function; /// Make the widget display the specified page from the specified book. - virtual void showPage(TypesetBook::Ptr book, size_t page) = 0; + virtual void showPage(std::shared_ptr book, size_t page) = 0; /// Set the callback for a clicking a hyper-link in the document. virtual void adviseLinkClicked(ClickCallback callback) = 0; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index a142bf034d..d9a675acc5 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -32,8 +32,6 @@ #include "bookpage.hpp" #include "textcolours.hpp" -#include "journalbooks.hpp" // to_utf8_span - namespace MWGui { void ResponseCallback::addResponse(std::string_view title, std::string_view text) @@ -208,7 +206,7 @@ namespace MWGui mText = text; } - void Response::write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, + void Response::write(std::shared_ptr typesetter, const TopicSearch& keywordSearch, std::map>& topicLinks) const { typesetter->sectionBreak(mNeedMargin ? 9 : 0); @@ -218,12 +216,11 @@ namespace MWGui { const MyGUI::Colour& headerColour = windowManager->getTextColours().header; BookTypesetter::Style* title = typesetter->createStyle({}, headerColour, false); - typesetter->write(title, to_utf8_span(mTitle)); + typesetter->write(title, mTitle); typesetter->sectionBreak(); } - typedef std::pair Range; - std::map hyperLinks; + std::map, const Link*> hyperLinks; // We need this copy for when @# hyperlinks are replaced std::string text = mText; @@ -250,14 +247,13 @@ namespace MWGui text.replace(posBegin, posEnd + 1 - posBegin, displayName); if (topicLinks.find(topicName) != topicLinks.end()) - hyperLinks[std::make_pair(posBegin, posBegin + displayName.size())] - = intptr_t(topicLinks[topicName].get()); + hyperLinks[std::make_pair(posBegin, posBegin + displayName.size())] = topicLinks[topicName].get(); } else break; } - typesetter->addContent(to_utf8_span(text)); + typesetter->addContent(text); if (hyperLinks.size() && MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation()) @@ -266,48 +262,48 @@ namespace MWGui BookTypesetter::Style* style = typesetter->createStyle({}, textColours.normal, false); size_t formatted = 0; // points to the first character that is not laid out yet - for (auto& hyperLink : hyperLinks) + for (const auto& [range, link] : hyperLinks) { - intptr_t topicId = hyperLink.second; - BookTypesetter::Style* hotStyle = typesetter->createHotStyle( - style, textColours.link, textColours.linkOver, textColours.linkPressed, topicId); - if (formatted < hyperLink.first.first) - typesetter->write(style, formatted, hyperLink.first.first); - typesetter->write(hotStyle, hyperLink.first.first, hyperLink.first.second); - formatted = hyperLink.first.second; + BookTypesetter::Style* hotStyle = typesetter->createHotStyle(style, textColours.link, + textColours.linkOver, textColours.linkPressed, TypesetBook::InteractiveId(link)); + if (formatted < range.first) + typesetter->write(style, formatted, range.first); + typesetter->write(hotStyle, range.first, range.second); + formatted = range.second; } if (formatted < text.size()) typesetter->write(style, formatted, text.size()); } else { - std::vector matches; - keywordSearch->highlightKeywords(text.begin(), text.end(), matches); + std::vector matches; + keywordSearch.highlightKeywords(text.begin(), text.end(), matches); std::string::const_iterator i = text.begin(); - for (KeywordSearchT::Match& match : matches) + for (TopicSearch::Match& match : matches) { if (i != match.mBeg) - addTopicLink(typesetter, 0, i - text.begin(), match.mBeg - text.begin()); + addTopicLink(typesetter, nullptr, i - text.begin(), match.mBeg - text.begin()); addTopicLink(typesetter, match.mValue, match.mBeg - text.begin(), match.mEnd - text.begin()); i = match.mEnd; } if (i != text.end()) - addTopicLink(std::move(typesetter), 0, i - text.begin(), text.size()); + addTopicLink(std::move(typesetter), nullptr, i - text.begin(), text.size()); } } - void Response::addTopicLink(BookTypesetter::Ptr typesetter, intptr_t topicId, size_t begin, size_t end) const + void Response::addTopicLink( + std::shared_ptr typesetter, const MWGui::Topic* topic, size_t begin, size_t end) const { const TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours(); BookTypesetter::Style* style = typesetter->createStyle({}, textColours.normal, false); - if (topicId) - style = typesetter->createHotStyle( - style, textColours.link, textColours.linkOver, textColours.linkPressed, topicId); + if (topic) + style = typesetter->createHotStyle(style, textColours.link, textColours.linkOver, textColours.linkPressed, + TypesetBook::InteractiveId(topic)); typesetter->write(style, begin, end); } @@ -316,13 +312,13 @@ namespace MWGui mText = text; } - void Message::write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, - std::map>& topicLinks) const + void Message::write(std::shared_ptr typesetter, const TopicSearch&, + std::map>&) const { const MyGUI::Colour& textColour = MWBase::Environment::get().getWindowManager()->getTextColours().notify; BookTypesetter::Style* title = typesetter->createStyle({}, textColour, false); typesetter->sectionBreak(9); - typesetter->write(title, to_utf8_span(mText)); + typesetter->write(title, mText); } // -------------------------------------------------------------------------------------------------- @@ -661,7 +657,7 @@ namespace MWGui mTopicsList->addItem(keyword, sVerticalPadding); auto t = std::make_unique(keyword); - mKeywordSearch.seed(topicId, intptr_t(t.get())); + mKeywordSearch.seed(topicId, t.get()); t->eventTopicActivated += MyGUI::newDelegate(this, &DialogueWindow::onTopicActivated); mTopicLinks[topicId] = std::move(t); @@ -689,10 +685,11 @@ namespace MWGui mScrollBar->setVisible(true); } - BookTypesetter::Ptr typesetter = BookTypesetter::create(mHistory->getWidth(), std::numeric_limits::max()); + std::shared_ptr typesetter + = BookTypesetter::create(mHistory->getWidth(), std::numeric_limits::max()); for (const auto& text : mHistoryContents) - text->write(typesetter, &mKeywordSearch, mTopicLinks); + text->write(typesetter, mKeywordSearch, mTopicLinks); BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::White, false); @@ -712,7 +709,7 @@ namespace MWGui typesetter->lineBreak(); BookTypesetter::Style* questionStyle = typesetter->createHotStyle( body, textColours.answer, textColours.answerOver, textColours.answerPressed, interactiveId); - typesetter->write(questionStyle, to_utf8_span(choice.first)); + typesetter->write(questionStyle, choice.first); mChoiceStyles.push_back(questionStyle); } @@ -731,10 +728,10 @@ namespace MWGui BookTypesetter::Style* questionStyle = typesetter->createHotStyle( body, textColours.answer, textColours.answerOver, textColours.answerPressed, interactiveId); typesetter->lineBreak(); - typesetter->write(questionStyle, to_utf8_span(goodbye)); + typesetter->write(questionStyle, goodbye); } - TypesetBook::Ptr book = typesetter->complete(); + std::shared_ptr book = typesetter->complete(); mHistory->showPage(book, 0); size_t viewHeight = mHistory->getParent()->getHeight(); if (!scrollbar && book->getSize().second > viewHeight) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index b95a20ddab..4f79f49637 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -79,14 +79,13 @@ namespace MWGui struct Link { - virtual ~Link() {} + virtual ~Link() = default; virtual void activated() = 0; }; struct Topic : Link { - typedef MyGUI::delegates::MultiDelegate EventHandle_TopicId; - EventHandle_TopicId eventTopicActivated; + MyGUI::delegates::MultiDelegate eventTopicActivated; Topic(const std::string& id) : mTopicId(id) { @@ -97,8 +96,7 @@ namespace MWGui struct Choice : Link { - typedef MyGUI::delegates::MultiDelegate EventHandle_ChoiceId; - EventHandle_ChoiceId eventChoiceActivated; + MyGUI::delegates::MultiDelegate eventChoiceActivated; Choice(int id) : mChoiceId(id) { @@ -109,27 +107,28 @@ namespace MWGui struct Goodbye : Link { - typedef MyGUI::delegates::MultiDelegate<> Event_Activated; - Event_Activated eventActivated; + MyGUI::delegates::MultiDelegate<> eventActivated; void activated() override; }; - typedef MWDialogue::KeywordSearch KeywordSearchT; + using TopicSearch = MWDialogue::KeywordSearch; struct DialogueText { virtual ~DialogueText() = default; - virtual void write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, - std::map>& topicLinks) const = 0; + virtual void write(std::shared_ptr typesetter, const TopicSearch& keywordSearch, + std::map>& topicLinks) const + = 0; std::string mText; }; struct Response : DialogueText { Response(std::string_view text, std::string_view title = {}, bool needMargin = true); - void write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, + void write(std::shared_ptr typesetter, const TopicSearch& keywordSearch, std::map>& topicLinks) const override; - void addTopicLink(BookTypesetter::Ptr typesetter, intptr_t topicId, size_t begin, size_t end) const; + void addTopicLink( + std::shared_ptr typesetter, const Topic* topic, size_t begin, size_t end) const; std::string mTitle; bool mNeedMargin; }; @@ -137,7 +136,7 @@ namespace MWGui struct Message : DialogueText { Message(std::string_view text); - void write(BookTypesetter::Ptr typesetter, KeywordSearchT* keywordSearch, + void write(std::shared_ptr typesetter, const TopicSearch& keywordSearch, std::map>& topicLinks) const override; }; @@ -150,9 +149,6 @@ namespace MWGui bool exit() override; - // Events - typedef MyGUI::delegates::MultiDelegate<> EventHandle_Void; - void notifyLinkClicked(TypesetBook::InteractiveId link); void setPtr(const MWWorld::Ptr& actor) override; @@ -213,7 +209,7 @@ namespace MWGui std::vector> mDeleteLater; - KeywordSearchT mKeywordSearch; + TopicSearch mKeywordSearch; BookPage* mHistory; Gui::MWList* mTopicsList; diff --git a/apps/openmw/mwgui/journalbooks.cpp b/apps/openmw/mwgui/journalbooks.cpp index 3e9916c345..c0b0708382 100644 --- a/apps/openmw/mwgui/journalbooks.cpp +++ b/apps/openmw/mwgui/journalbooks.cpp @@ -12,10 +12,10 @@ namespace { struct AddContent { - MWGui::BookTypesetter::Ptr mTypesetter; + std::shared_ptr mTypesetter; MWGui::BookTypesetter::Style* mBodyStyle; - explicit AddContent(MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle) + explicit AddContent(std::shared_ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle) : mTypesetter(std::move(typesetter)) , mBodyStyle(bodyStyle) { @@ -24,19 +24,19 @@ namespace struct AddSpan : AddContent { - explicit AddSpan(MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle) + explicit AddSpan(std::shared_ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle) : AddContent(std::move(typesetter), bodyStyle) { } - void operator()(intptr_t topicId, size_t begin, size_t end) + void operator()(const MWDialogue::Topic* topic, size_t begin, size_t end) { MWGui::BookTypesetter::Style* style = mBodyStyle; const MWGui::TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours(); - if (topicId) + if (topic) style = mTypesetter->createHotStyle(mBodyStyle, textColours.journalLink, textColours.journalLinkOver, - textColours.journalLinkPressed, topicId); + textColours.journalLinkPressed, MWGui::TypesetBook::InteractiveId(topic)); mTypesetter->write(style, begin, end); } @@ -44,10 +44,10 @@ namespace struct AddEntry { - MWGui::BookTypesetter::Ptr mTypesetter; + std::shared_ptr mTypesetter; MWGui::BookTypesetter::Style* mBodyStyle; - AddEntry(MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle) + AddEntry(std::shared_ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle) : mTypesetter(std::move(typesetter)) , mBodyStyle(bodyStyle) { @@ -66,8 +66,8 @@ namespace bool mAddHeader; MWGui::BookTypesetter::Style* mHeaderStyle; - explicit AddJournalEntry(MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle, - MWGui::BookTypesetter::Style* headerStyle, bool addHeader) + explicit AddJournalEntry(std::shared_ptr typesetter, + MWGui::BookTypesetter::Style* bodyStyle, MWGui::BookTypesetter::Style* headerStyle, bool addHeader) : AddEntry(std::move(typesetter), bodyStyle) , mAddHeader(addHeader) , mHeaderStyle(headerStyle) @@ -90,11 +90,12 @@ namespace struct AddTopicEntry : AddEntry { - intptr_t mContentId; + const MWGui::TypesetBook::Content* mContentId; MWGui::BookTypesetter::Style* mHeaderStyle; - explicit AddTopicEntry(MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* bodyStyle, - MWGui::BookTypesetter::Style* headerStyle, intptr_t contentId) + explicit AddTopicEntry(std::shared_ptr typesetter, + MWGui::BookTypesetter::Style* bodyStyle, MWGui::BookTypesetter::Style* headerStyle, + const MWGui::TypesetBook::Content* contentId) : AddEntry(std::move(typesetter), bodyStyle) , mContentId(contentId) , mHeaderStyle(headerStyle) @@ -117,12 +118,12 @@ namespace struct AddTopicName : AddContent { - AddTopicName(MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* style) + AddTopicName(std::shared_ptr typesetter, MWGui::BookTypesetter::Style* style) : AddContent(std::move(typesetter), style) { } - void operator()(MWGui::JournalViewModel::Utf8Span topicName) + void operator()(std::string_view topicName) { mTypesetter->write(mBodyStyle, topicName); mTypesetter->sectionBreak(); @@ -131,12 +132,12 @@ namespace struct AddQuestName : AddContent { - AddQuestName(MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* style) + AddQuestName(std::shared_ptr typesetter, MWGui::BookTypesetter::Style* style) : AddContent(std::move(typesetter), style) { } - void operator()(MWGui::JournalViewModel::Utf8Span topicName) + void operator()(std::string_view topicName) { mTypesetter->write(mBodyStyle, topicName); mTypesetter->sectionBreak(); @@ -147,15 +148,6 @@ namespace namespace MWGui { - MWGui::BookTypesetter::Utf8Span to_utf8_span(std::string_view text) - { - typedef MWGui::BookTypesetter::Utf8Point point; - - point begin = reinterpret_cast(text.data()); - - return MWGui::BookTypesetter::Utf8Span(begin, begin + text.length()); - } - int getCyrillicIndexPageCount() { // For small font size split alphabet to two columns (2x15 characers), for big font size split it to three @@ -163,33 +155,30 @@ namespace MWGui return Settings::gui().mFontSize < 18 ? 2 : 3; } - typedef TypesetBook::Ptr book; - - JournalBooks::JournalBooks(JournalViewModel::Ptr model, ToUTF8::FromType encoding) + JournalBooks::JournalBooks(std::shared_ptr model, ToUTF8::FromType encoding) : mModel(std::move(model)) , mEncoding(encoding) , mIndexPagesCount(0) { } - book JournalBooks::createEmptyJournalBook() + std::shared_ptr JournalBooks::createEmptyJournalBook() { - BookTypesetter::Ptr typesetter = createTypesetter(); + std::shared_ptr typesetter = createTypesetter(); BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour); BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black); - typesetter->write(header, to_utf8_span("You have no journal entries!")); + typesetter->write(header, "You have no journal entries!"); typesetter->lineBreak(); - typesetter->write( - body, to_utf8_span("You should have gone though the starting quest and got an initial quest.")); + typesetter->write(body, "You should have gone though the starting quest and got an initial quest."); return typesetter->complete(); } - book JournalBooks::createJournalBook() + std::shared_ptr JournalBooks::createJournalBook() { - BookTypesetter::Ptr typesetter = createTypesetter(); + std::shared_ptr typesetter = createTypesetter(); BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour); BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black); @@ -199,49 +188,50 @@ namespace MWGui return typesetter->complete(); } - book JournalBooks::createTopicBook(uintptr_t topicId) + std::shared_ptr JournalBooks::createTopicBook(const MWDialogue::Topic& topic) { - BookTypesetter::Ptr typesetter = createTypesetter(); + std::shared_ptr typesetter = createTypesetter(); BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour); BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black); - mModel->visitTopicName(topicId, AddTopicName(typesetter, header)); + mModel->visitTopicName(topic, AddTopicName(typesetter, header)); - intptr_t contentId = typesetter->addContent(to_utf8_span(", \"")); + const TypesetBook::Content* contentId = typesetter->addContent(", \""); - mModel->visitTopicEntries(topicId, AddTopicEntry(typesetter, body, header, contentId)); + mModel->visitTopicEntries(topic, AddTopicEntry(typesetter, body, header, contentId)); return typesetter->complete(); } - book JournalBooks::createQuestBook(std::string_view questName) + std::shared_ptr JournalBooks::createQuestBook(std::string_view questName) { - BookTypesetter::Ptr typesetter = createTypesetter(); + std::shared_ptr typesetter = createTypesetter(); BookTypesetter::Style* header = typesetter->createStyle({}, journalHeaderColour); BookTypesetter::Style* body = typesetter->createStyle({}, MyGUI::Colour::Black); AddQuestName addName(typesetter, header); - addName(to_utf8_span(questName)); + addName(questName); mModel->visitJournalEntries(questName, AddJournalEntry(typesetter, body, header, false)); return typesetter->complete(); } - book JournalBooks::createTopicIndexBook() + std::shared_ptr JournalBooks::createTopicIndexBook() { bool isRussian = (mEncoding == ToUTF8::WINDOWS_1251); - BookTypesetter::Ptr typesetter = isRussian ? createCyrillicJournalIndex() : createLatinJournalIndex(); + std::shared_ptr typesetter + = isRussian ? createCyrillicJournalIndex() : createLatinJournalIndex(); return typesetter->complete(); } - BookTypesetter::Ptr JournalBooks::createLatinJournalIndex() + std::shared_ptr JournalBooks::createLatinJournalIndex() { - BookTypesetter::Ptr typesetter = BookTypesetter::create(92, 260); + std::shared_ptr typesetter = BookTypesetter::create(92, 260); typesetter->setSectionAlignment(BookTypesetter::AlignCenter); @@ -260,12 +250,12 @@ namespace MWGui const MWGui::TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours(); BookTypesetter::Style* style = typesetter->createHotStyle(body, textColours.journalTopic, - textColours.journalTopicOver, textColours.journalTopicPressed, (Utf8Stream::UnicodeChar)ch); + textColours.journalTopicOver, textColours.journalTopicPressed, Utf8Stream::UnicodeChar(ch)); if (i == 13) typesetter->sectionBreak(); - typesetter->write(style, to_utf8_span(buffer)); + typesetter->write(style, buffer); typesetter->lineBreak(); ch++; @@ -274,9 +264,9 @@ namespace MWGui return typesetter; } - BookTypesetter::Ptr JournalBooks::createCyrillicJournalIndex() + std::shared_ptr JournalBooks::createCyrillicJournalIndex() { - BookTypesetter::Ptr typesetter = BookTypesetter::create(92, 260); + std::shared_ptr typesetter = BookTypesetter::create(92, 260); typesetter->setSectionAlignment(BookTypesetter::AlignCenter); @@ -314,14 +304,14 @@ namespace MWGui if (i % sectionBreak == 0) typesetter->sectionBreak(); - typesetter->write(style, to_utf8_span(buffer)); + typesetter->write(style, buffer); typesetter->lineBreak(); } return typesetter; } - BookTypesetter::Ptr JournalBooks::createTypesetter() + std::shared_ptr JournalBooks::createTypesetter() { // TODO: determine page size from layout... return BookTypesetter::create(240, 320); diff --git a/apps/openmw/mwgui/journalbooks.hpp b/apps/openmw/mwgui/journalbooks.hpp index 3d55135d9c..73348d7beb 100644 --- a/apps/openmw/mwgui/journalbooks.hpp +++ b/apps/openmw/mwgui/journalbooks.hpp @@ -8,31 +8,29 @@ namespace MWGui { - MWGui::BookTypesetter::Utf8Span to_utf8_span(std::string_view text); int getCyrillicIndexPageCount(); const MyGUI::Colour journalHeaderColour = MyGUI::Colour(0.60f, 0.00f, 0.00f); struct JournalBooks { - typedef TypesetBook::Ptr Book; - JournalViewModel::Ptr mModel; + std::shared_ptr mModel; - JournalBooks(JournalViewModel::Ptr model, ToUTF8::FromType encoding); + JournalBooks(std::shared_ptr model, ToUTF8::FromType encoding); - Book createEmptyJournalBook(); - Book createJournalBook(); - Book createTopicBook(uintptr_t topicId); - Book createQuestBook(std::string_view questName); - Book createTopicIndexBook(); + std::shared_ptr createEmptyJournalBook(); + std::shared_ptr createJournalBook(); + std::shared_ptr createTopicBook(const MWDialogue::Topic& topic); + std::shared_ptr createQuestBook(std::string_view questName); + std::shared_ptr createTopicIndexBook(); ToUTF8::FromType mEncoding; int mIndexPagesCount; private: - BookTypesetter::Ptr createTypesetter(); - BookTypesetter::Ptr createLatinJournalIndex(); - BookTypesetter::Ptr createCyrillicJournalIndex(); + std::shared_ptr createTypesetter(); + std::shared_ptr createLatinJournalIndex(); + std::shared_ptr createCyrillicJournalIndex(); }; } diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index b5a0215db2..b3108be4cc 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -22,26 +22,15 @@ namespace MWGui struct JournalViewModelImpl : JournalViewModel { - typedef MWDialogue::KeywordSearch KeywordSearchT; + using TopicSearch = MWDialogue::KeywordSearch; mutable bool mKeywordSearchLoaded; - mutable KeywordSearchT mKeywordSearch; + mutable TopicSearch mKeywordSearch; JournalViewModelImpl() { mKeywordSearchLoaded = false; } virtual ~JournalViewModelImpl() = default; - /// \todo replace this nasty BS - static Utf8Span toUtf8Span(std::string_view str) - { - if (str.empty()) - return Utf8Span(Utf8Point(nullptr), Utf8Point(nullptr)); - - Utf8Point point = reinterpret_cast(str.data()); - - return Utf8Span(point, point + str.size()); - } - void load() override {} void unload() override @@ -57,7 +46,7 @@ namespace MWGui MWBase::Journal* journal = MWBase::Environment::get().getJournal(); for (const auto& [_, topic] : journal->getTopics()) - mKeywordSearch.seed(topic.getName(), intptr_t(&topic)); + mKeywordSearch.seed(topic.getName(), &topic); mKeywordSearchLoaded = true; } @@ -88,10 +77,8 @@ namespace MWGui mutable bool loaded; mutable std::string utf8text; - typedef std::pair Range; - // hyperlinks in @link# notation - mutable std::map mHyperLinks; + mutable std::map, const MWDialogue::Topic*> mHyperLinks; virtual std::string getText() const = 0; @@ -126,7 +113,7 @@ namespace MWGui utf8text.replace(posBegin, posEnd + 1 - posBegin, displayName); - intptr_t value = 0; + const MWDialogue::Topic* value = nullptr; if (mModel->mKeywordSearch.containsKeyword(topicName, value)) mHyperLinks[std::make_pair(posBegin, posBegin + displayName.size())] = value; } @@ -138,14 +125,14 @@ namespace MWGui } } - Utf8Span body() const override + std::string_view body() const override { ensureLoaded(); - return toUtf8Span(utf8text); + return utf8text; } - void visitSpans(std::function visitor) const override + void visitSpans(std::function visitor) const override { ensureLoaded(); mModel->ensureKeyWordSearchLoaded(); @@ -154,25 +141,23 @@ namespace MWGui && MWBase::Environment::get().getWindowManager()->getTranslationDataStorage().hasTranslation()) { size_t formatted = 0; // points to the first character that is not laid out yet - for (std::map::const_iterator it = mHyperLinks.begin(); it != mHyperLinks.end(); - ++it) + for (const auto& [range, topicId] : mHyperLinks) { - intptr_t topicId = it->second; - if (formatted < it->first.first) - visitor(0, formatted, it->first.first); - visitor(topicId, it->first.first, it->first.second); - formatted = it->first.second; + if (formatted < range.first) + visitor(0, formatted, range.first); + visitor(topicId, range.first, range.second); + formatted = range.second; } if (formatted < utf8text.size()) visitor(0, formatted, utf8text.size()); } else { - std::vector matches; + std::vector matches; mModel->mKeywordSearch.highlightKeywords(utf8text.begin(), utf8text.end(), matches); std::string::const_iterator i = utf8text.begin(); - for (const KeywordSearchT::Match& match : matches) + for (const TopicSearch::Match& match : matches) { if (i != match.mBeg) visitor(0, i - utf8text.begin(), match.mBeg - utf8text.begin()); @@ -231,7 +216,7 @@ namespace MWGui std::string getText() const override { return mEntry->getText(); } - Utf8Span timestamp() const override + std::string_view timestamp() const override { if (timestamp_buffer.empty()) { @@ -246,7 +231,7 @@ namespace MWGui timestamp_buffer = os.str(); } - return toUtf8Span(timestamp_buffer); + return timestamp_buffer; } }; @@ -288,10 +273,10 @@ namespace MWGui } } - void visitTopicName(TopicId topicId, std::function visitor) const override + void visitTopicName( + const MWDialogue::Topic& topic, std::function visitor) const override { - MWDialogue::Topic const& topic = *reinterpret_cast(topicId); - visitor(toUtf8Span(topic.getName())); + visitor(topic.getName()); } void visitTopicNamesStartingWith( @@ -324,19 +309,18 @@ namespace MWGui std::string getText() const override { return mEntry->getText(); } - Utf8Span source() const override { return toUtf8Span(mEntry->mActorName); } + std::string_view source() const override { return mEntry->mActorName; } }; - void visitTopicEntries(TopicId topicId, std::function visitor) const override + void visitTopicEntries( + const MWDialogue::Topic& topic, std::function visitor) const override { - MWDialogue::Topic const& topic = *reinterpret_cast(topicId); - for (const MWDialogue::Entry& entry : topic) visitor(TopicEntryImpl(this, topic, entry)); } }; - JournalViewModel::Ptr JournalViewModel::create() + std::shared_ptr JournalViewModel::create() { return std::make_shared(); } diff --git a/apps/openmw/mwgui/journalviewmodel.hpp b/apps/openmw/mwgui/journalviewmodel.hpp index 9b06ae465b..7a1733894d 100644 --- a/apps/openmw/mwgui/journalviewmodel.hpp +++ b/apps/openmw/mwgui/journalviewmodel.hpp @@ -8,6 +8,11 @@ #include +namespace MWDialogue +{ + class Topic; +} + namespace MWGui { /// View-Model for the journal GUI @@ -18,13 +23,6 @@ namespace MWGui /// game data store. struct JournalViewModel { - typedef std::shared_ptr Ptr; - - typedef intptr_t QuestId; - typedef intptr_t TopicId; - typedef uint8_t const* Utf8Point; - typedef std::pair Utf8Span; - /// The base interface for both journal entries and topics. struct Entry { @@ -33,12 +31,12 @@ namespace MWGui /// This function returns a borrowed reference to the body of the /// journal entry. The returned reference becomes invalid when the /// entry is destroyed. - virtual Utf8Span body() const = 0; + virtual std::string_view body() const = 0; /// Visits each subset of text in the body, delivering the beginning /// and end of the span relative to the body, and a valid topic ID if /// the span represents a keyword, or zero if not. - virtual void visitSpans(std::function visitor) const = 0; + virtual void visitSpans(std::function visitor) const = 0; virtual ~Entry() = default; }; @@ -48,7 +46,7 @@ namespace MWGui { /// Returns a pre-formatted span of UTF8 encoded text representing /// the name of the NPC this portion of dialog was heard from. - virtual Utf8Span source() const = 0; + virtual std::string_view source() const = 0; virtual ~TopicEntry() = default; }; @@ -58,7 +56,7 @@ namespace MWGui { /// Returns a pre-formatted span of UTF8 encoded text representing /// the in-game date this entry was added to the journal. - virtual Utf8Span timestamp() const = 0; + virtual std::string_view timestamp() const = 0; virtual ~JournalEntry() = default; }; @@ -78,20 +76,25 @@ namespace MWGui /// walks over the journal entries related to all quests with the given name /// If \a questName is empty, simply visits all journal entries virtual void visitJournalEntries( - std::string_view questName, std::function visitor) const = 0; + std::string_view questName, std::function visitor) const + = 0; /// provides the name of the topic specified by its id - virtual void visitTopicName(TopicId topicId, std::function visitor) const = 0; + virtual void visitTopicName(const MWDialogue::Topic& topic, std::function visitor) const + = 0; /// walks over the topics whose names start with the character virtual void visitTopicNamesStartingWith( - Utf8Stream::UnicodeChar character, std::function visitor) const = 0; + Utf8Stream::UnicodeChar character, std::function visitor) const + = 0; /// walks over the topic entries for the topic specified by its identifier - virtual void visitTopicEntries(TopicId topicId, std::function visitor) const = 0; + virtual void visitTopicEntries( + const MWDialogue::Topic& topic, std::function visitor) const + = 0; // create an instance of the default journal view model implementation - static Ptr create(); + static std::shared_ptr create(); virtual ~JournalViewModel() = default; }; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index fe2e2156b6..f7f76cfb6c 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -50,13 +50,11 @@ namespace struct DisplayState { size_t mPage; - Book mBook; + std::shared_ptr mBook; }; - typedef std::stack DisplayStateStack; - - DisplayStateStack mStates; - Book mTopicIndexBook; + std::stack mStates; + std::shared_ptr mTopicIndexBook; bool mQuestMode; bool mOptionsMode; bool mTopicsMode; @@ -91,7 +89,7 @@ namespace MWGui::BookPage* getPage(std::string_view name) { return getWidget(name); } - JournalWindowImpl(MWGui::JournalViewModel::Ptr model, bool questList, ToUTF8::FromType encoding) + JournalWindowImpl(std::shared_ptr model, bool questList, ToUTF8::FromType encoding) : JournalBooks(std::move(model), encoding) , JournalWindow() { @@ -123,7 +121,10 @@ namespace topicsList->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyTopicSelected); { - MWGui::BookPage::ClickCallback callback = [this](intptr_t linkId) { notifyTopicClicked(linkId); }; + MWGui::BookPage::ClickCallback callback = [this](MWGui::TypesetBook::InteractiveId linkId) { + const MWDialogue::Topic& topic = *reinterpret_cast(linkId); + notifyTopicClicked(topic); + }; getPage(LeftBookPage)->adviseLinkClicked(callback); getPage(RightBookPage)->adviseLinkClicked(std::move(callback)); @@ -135,8 +136,9 @@ namespace } { - MWGui::BookPage::ClickCallback callback - = [this](MWGui::TypesetBook::InteractiveId index) { notifyIndexLinkClicked(index); }; + MWGui::BookPage::ClickCallback callback = [this](MWGui::TypesetBook::InteractiveId index) { + notifyIndexLinkClicked(static_cast(index)); + }; getPage(LeftTopicIndex)->adviseLinkClicked(callback); getPage(CenterTopicIndex)->adviseLinkClicked(callback); @@ -240,7 +242,7 @@ namespace setBookMode(); - Book journalBook; + std::shared_ptr journalBook; if (mModel->isEmpty()) journalBook = createEmptyJournalBook(); else @@ -268,8 +270,8 @@ namespace { mModel->unload(); - getPage(LeftBookPage)->showPage(Book(), 0); - getPage(RightBookPage)->showPage(Book(), 0); + getPage(LeftBookPage)->showPage({}, 0); + getPage(RightBookPage)->showPage({}, 0); while (!mStates.empty()) mStates.pop(); @@ -315,7 +317,7 @@ namespace // TODO: figure out how to make "options" page overlay book page // correctly, so that text may show underneath - getPage(RightBookPage)->showPage(Book(), 0); + getPage(RightBookPage)->showPage({}, 0); // If in quest mode, ensure the quest list is updated if (mQuestMode) @@ -326,7 +328,7 @@ namespace MWBase::Environment::get().getWindowManager()->updateControllerButtonsOverlay(); } - void pushBook(Book& book) + void pushBook(std::shared_ptr& book) { DisplayState bs; bs.mPage = 0; @@ -336,7 +338,7 @@ namespace updateCloseJournalButton(); } - void replaceBook(Book& book) + void replaceBook(std::shared_ptr& book) { assert(!mStates.empty()); mStates.top().mBook = book; @@ -360,7 +362,7 @@ namespace void updateShowingPages() { - Book book; + std::shared_ptr book; size_t page; size_t relPages; @@ -393,8 +395,16 @@ namespace setVisible(PageOneNum, relPages > 0); setVisible(PageTwoNum, relPages > 1); - getPage(LeftBookPage)->showPage((relPages > 0) ? book : Book(), page + 0); - getPage(RightBookPage)->showPage((relPages > 0) ? std::move(book) : Book(), page + 1); + if (relPages > 0) + { + getPage(LeftBookPage)->showPage(book, page + 0); + getPage(RightBookPage)->showPage(std::move(book), page + 1); + } + else + { + getPage(LeftBookPage)->showPage({}, page + 0); + getPage(RightBookPage)->showPage({}, page + 1); + } setText(PageOneNum, page + 1); setText(PageTwoNum, page + 2); @@ -410,9 +420,9 @@ namespace notifyNextPage(sender); } - void notifyTopicClicked(intptr_t linkId) + void notifyTopicClicked(const MWDialogue::Topic& topic) { - Book topicBook = createTopicBook(linkId); + std::shared_ptr topicBook = createTopicBook(topic); if (mStates.size() > 1) replaceBook(topicBook); @@ -434,17 +444,14 @@ namespace { 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 const auto it = journal->getTopics().find(topic); if (it != journal->getTopics().end()) - topicId = intptr_t(&it->second); - - notifyTopicClicked(topicId); + notifyTopicClicked(it->second); } void notifyQuestClicked(const std::string& name, int id) { - Book book = createQuestBook(name); + std::shared_ptr book = createQuestBook(name); if (mStates.size() > 1) replaceBook(book); @@ -508,7 +515,7 @@ namespace } } - void notifyIndexLinkClicked(MWGui::TypesetBook::InteractiveId index) + void notifyIndexLinkClicked(Utf8Stream::UnicodeChar index) { setVisible(LeftTopicIndex, false); setVisible(CenterTopicIndex, false); @@ -664,7 +671,7 @@ namespace if (!mStates.empty()) { size_t& page = mStates.top().mPage; - Book book = mStates.top().mBook; + std::shared_ptr book = mStates.top().mBook; if (page + 2 < book->pageCount()) { @@ -785,7 +792,8 @@ namespace if (mSelectedIndex >= 27) russianOffset++; // 27, not 28, because of skipping char 26 bool isRussian = (mEncoding == ToUTF8::WINDOWS_1251); - notifyIndexLinkClicked(isRussian ? mSelectedIndex + russianOffset : mSelectedIndex + 'A'); + size_t ch = isRussian ? mSelectedIndex + russianOffset : mSelectedIndex + 'A'; + notifyIndexLinkClicked(static_cast(ch)); } } else if (arg.button == SDL_CONTROLLER_BUTTON_B) // B: Back @@ -945,7 +953,7 @@ namespace // glue the implementation to the interface std::unique_ptr MWGui::JournalWindow::create( - JournalViewModel::Ptr model, bool questList, ToUTF8::FromType encoding) + std::shared_ptr model, bool questList, ToUTF8::FromType encoding) { return std::make_unique(model, questList, encoding); }