diff --git a/apps/openmw/mwgui/journalbooks.cpp b/apps/openmw/mwgui/journalbooks.cpp index 683fe9208..70f156922 100644 --- a/apps/openmw/mwgui/journalbooks.cpp +++ b/apps/openmw/mwgui/journalbooks.cpp @@ -148,22 +148,6 @@ namespace mTypesetter->lineBreak (); } }; - - struct AddQuestLink : AddContent - { - AddQuestLink (MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* style) : - AddContent (typesetter, style) - { - } - - void operator () (MWGui::JournalViewModel::QuestId id, MWGui::JournalViewModel::Utf8Span name) - { - MWGui::BookTypesetter::Style* style = mTypesetter->createHotStyle (mBodyStyle, MyGUI::Colour::Black, linkHot, linkActive, id); - - mTypesetter->write (style, name); - mTypesetter->lineBreak (); - } - }; } namespace MWGui @@ -206,7 +190,7 @@ book JournalBooks::createJournalBook () BookTypesetter::Style* header = typesetter->createStyle ("", MyGUI::Colour (0.60f, 0.00f, 0.00f)); BookTypesetter::Style* body = typesetter->createStyle ("", MyGUI::Colour::Black); - mModel->visitJournalEntries (0, AddJournalEntry (typesetter, body, header, true)); + mModel->visitJournalEntries ("", AddJournalEntry (typesetter, body, header, true)); return typesetter->complete (); } @@ -227,16 +211,17 @@ book JournalBooks::createTopicBook (uintptr_t topicId) return typesetter->complete (); } -book JournalBooks::createQuestBook (uintptr_t questId) +book JournalBooks::createQuestBook (const std::string& questName) { BookTypesetter::Ptr typesetter = createTypesetter (); BookTypesetter::Style* header = typesetter->createStyle ("", MyGUI::Colour (0.60f, 0.00f, 0.00f)); BookTypesetter::Style* body = typesetter->createStyle ("", MyGUI::Colour::Black); - mModel->visitQuestName (questId, AddQuestName (typesetter, header)); + AddQuestName addName (typesetter, header); + addName(to_utf8_span(questName.c_str())); - mModel->visitJournalEntries (questId, AddJournalEntry (typesetter, body, header, false)); + mModel->visitJournalEntries (questName, AddJournalEntry (typesetter, body, header, false)); return typesetter->complete (); } @@ -279,16 +264,6 @@ book JournalBooks::createTopicIndexBook (char character) return typesetter->complete (); } -book JournalBooks::createQuestIndexBook (bool activeOnly) -{ - BookTypesetter::Ptr typesetter = BookTypesetter::create (0x7FFFFFFF, 0x7FFFFFFF); - BookTypesetter::Style* base = typesetter->createStyle ("", MyGUI::Colour::Black); - - mModel->visitQuestNames (activeOnly, AddQuestLink (typesetter, base)); - - return typesetter->complete (); -} - BookTypesetter::Ptr JournalBooks::createTypesetter () { //TODO: determine page size from layout... diff --git a/apps/openmw/mwgui/journalbooks.hpp b/apps/openmw/mwgui/journalbooks.hpp index 819bda0fd..6ae2ba82a 100644 --- a/apps/openmw/mwgui/journalbooks.hpp +++ b/apps/openmw/mwgui/journalbooks.hpp @@ -18,10 +18,9 @@ namespace MWGui Book createEmptyJournalBook (); Book createJournalBook (); Book createTopicBook (uintptr_t topicId); - Book createQuestBook (uintptr_t questId); + Book createQuestBook (const std::string& questName); Book createTopicIndexBook (); Book createTopicIndexBook (char character); - Book createQuestIndexBook (bool showAll); private: BookTypesetter::Ptr createTypesetter (); diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 5994c6e21..1feb92b02 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -195,10 +195,12 @@ struct JournalViewModelImpl : JournalViewModel }; - void visitQuestNames (bool active_only, boost::function visitor) const + void visitQuestNames (bool active_only, boost::function visitor) const { MWBase::Journal * journal = MWBase::Environment::get ().getJournal (); + std::set visitedQuests; + for (MWBase::Journal::TQuestIter i = journal->questBegin (); i != journal->questEnd (); ++i) { if (active_only && i->second.isFinished ()) @@ -209,7 +211,15 @@ struct JournalViewModelImpl : JournalViewModel // Note that even with Tribunal, some quests still don't have quest names. I'm assuming those are not supposed // to appear in the quest book. if (!quest.getName().empty()) - visitor (reinterpret_cast (&i->second), toUtf8Span (quest.getName())); + { + // Don't list the same quest name twice + if (visitedQuests.find(quest.getName()) != visitedQuests.end()) + continue; + + visitor (quest.getName()); + + visitedQuests.insert(quest.getName()); + } } } @@ -258,20 +268,29 @@ struct JournalViewModelImpl : JournalViewModel } }; - void visitJournalEntries (QuestId questId, boost::function visitor) const + void visitJournalEntries (const std::string& questName, boost::function visitor) const { MWBase::Journal * journal = MWBase::Environment::get().getJournal(); - if (questId != 0) + if (!questName.empty()) { - MWDialogue::Quest const * quest = reinterpret_cast (questId); + std::vector quests; + for (MWBase::Journal::TQuestIter questIt = journal->questBegin(); questIt != journal->questEnd(); ++questIt) + { + if (Misc::StringUtils::ciEqual(questIt->second.getName(), questName)) + quests.push_back(&questIt->second); + } for(MWBase::Journal::TEntryIter i = journal->begin(); i != journal->end (); ++i) { - for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j) + for (std::vector::iterator questIt = quests.begin(); questIt != quests.end(); ++questIt) { - if (i->mInfoId == j->mInfoId) - visitor (JournalEntryImpl (this, i)); + MWDialogue::Quest const* quest = *questIt; + for (MWDialogue::Topic::TEntryIter j = quest->begin (); j != quest->end (); ++j) + { + if (i->mInfoId == j->mInfoId) + visitor (JournalEntryImpl (this, i)); + } } } } diff --git a/apps/openmw/mwgui/journalviewmodel.hpp b/apps/openmw/mwgui/journalviewmodel.hpp index 9efdeae54..feb9457c6 100644 --- a/apps/openmw/mwgui/journalviewmodel.hpp +++ b/apps/openmw/mwgui/journalviewmodel.hpp @@ -70,11 +70,12 @@ namespace MWGui /// provides access to the name of the quest with the specified identifier virtual void visitQuestName (TopicId topicId, boost::function visitor) const = 0; - /// walks the active and optionally completed, quests providing the quest id and name - virtual void visitQuestNames (bool active_only, boost::function visitor) const = 0; + /// walks the active and optionally completed, quests providing the name + virtual void visitQuestNames (bool active_only, boost::function visitor) const = 0; - /// walks over the journal entries related to the specified quest identified by its id - virtual void visitJournalEntries (QuestId questId, boost::function visitor) const = 0; + /// 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 (const std::string& questName, boost::function visitor) const = 0; /// provides the name of the topic specified by its id virtual void visitTopicName (TopicId topicId, boost::function visitor) const = 0; diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index f3c9e9c73..0940b7fef 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -19,6 +19,7 @@ #include "imagebutton.hpp" #include "journalviewmodel.hpp" #include "journalbooks.hpp" +#include "list.hpp" namespace { @@ -38,7 +39,6 @@ namespace static char const TopicsList [] = "TopicsList"; static char const TopicsPage [] = "TopicsPage"; static char const QuestsList [] = "QuestsList"; - static char const QuestsPage [] = "QuestsPage"; static char const LeftBookPage [] = "LeftBookPage"; static char const RightBookPage [] = "RightBookPage"; static char const LeftTopicIndex [] = "LeftTopicIndex"; @@ -110,6 +110,9 @@ namespace adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll ); adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive); + MWGui::Widgets::MWList* list = getWidget(QuestsList); + list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked); + { MWGui::BookPage::ClickCallback callback; @@ -129,14 +132,6 @@ namespace getPage (RightTopicIndex)->adviseLinkClicked (callback); } - { - MWGui::BookPage::ClickCallback callback; - - callback = boost::bind (&JournalWindowImpl::notifyQuestClicked, this, _1); - - getPage (QuestsPage)->adviseLinkClicked (callback); - } - adjustButton(OptionsBTN, true); adjustButton(PrevPageBTN); adjustButton(NextPageBTN); @@ -271,6 +266,10 @@ namespace //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(QuestsList)); } void pushBook (Book book, unsigned int page) @@ -349,9 +348,9 @@ namespace setVisible (JournalBTN, true); } - void notifyQuestClicked (intptr_t questId) + void notifyQuestClicked (const std::string& name, int id) { - Book book = createQuestBook (questId); + Book book = createQuestBook (name); if (mStates.size () > 1) replaceBook (book, 0); @@ -409,9 +408,21 @@ namespace setVisible (ShowActiveBTN, false); } + struct AddQuestNamesToList + { + AddQuestNamesToList(MWGui::Widgets::MWList* list) : mList(list) {} + + MWGui::Widgets::MWList* mList; + void operator () (const std::string& name) + { + mList->addItem(name); + } + }; + void notifyQuests(MyGUI::Widget* _sender) { mQuestMode = true; + setVisible (LeftTopicIndex, false); setVisible (RightTopicIndex, false); setVisible (TopicsList, false); @@ -419,23 +430,26 @@ namespace setVisible (ShowAllBTN, !mAllQuests); setVisible (ShowActiveBTN, mAllQuests); - showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests)); + MWGui::Widgets::MWList* list = getWidget(QuestsList); + list->clear(); + + AddQuestNamesToList add(list); + + mModel->visitQuestNames(!mAllQuests, add); + + list->adjustSize(); } void notifyShowAll(MyGUI::Widget* _sender) { mAllQuests = true; - setVisible (ShowAllBTN, !mAllQuests); - setVisible (ShowActiveBTN, mAllQuests); - showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests)); + notifyQuests(_sender); } void notifyShowActive(MyGUI::Widget* _sender) { mAllQuests = false; - setVisible (ShowAllBTN, !mAllQuests); - setVisible (ShowActiveBTN, mAllQuests); - showList (QuestsList, QuestsPage, createQuestIndexBook (!mAllQuests)); + notifyQuests(_sender); } void notifyCancel(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwgui/list.cpp b/apps/openmw/mwgui/list.cpp index 19f20eeee..ca2989646 100644 --- a/apps/openmw/mwgui/list.cpp +++ b/apps/openmw/mwgui/list.cpp @@ -65,8 +65,10 @@ namespace MWGui { if (*it != "") { + if (mListItemSkin.empty()) + throw std::runtime_error("MWList needs a ListItemSkin property"); MyGUI::Button* button = mScrollView->createWidget( - "MW_ListLine", MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), + mListItemSkin, MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it)); button->setCaption((*it)); button->getSubWidgetText()->setWordWrap(true); @@ -102,6 +104,14 @@ namespace MWGui mScrollView->setViewOffset(MyGUI::IntPoint(0, -viewPosition)); } + void MWList::setPropertyOverride(const std::string &_key, const std::string &_value) + { + if (_key == "ListItemSkin") + mListItemSkin = _value; + else + Base::setPropertyOverride(_key, _value); + } + bool MWList::hasItem(const std::string& name) { return (std::find(mItems.begin(), mItems.end(), name) != mItems.end()); diff --git a/apps/openmw/mwgui/list.hpp b/apps/openmw/mwgui/list.hpp index dcfe7931a..acf078a2c 100644 --- a/apps/openmw/mwgui/list.hpp +++ b/apps/openmw/mwgui/list.hpp @@ -22,7 +22,7 @@ namespace MWGui /** * Event: Item selected with the mouse. - * signature: void method(std::string itemName) + * signature: void method(std::string itemName, int index) */ EventHandle_StringInt eventItemSelected; @@ -49,6 +49,8 @@ namespace MWGui MyGUI::Widget* getItemWidget(const std::string& name); ///< get widget for an item name, useful to set up tooltip + virtual void setPropertyOverride(const std::string& _key, const std::string& _value); + protected: void initialiseOverride(); @@ -60,6 +62,7 @@ namespace MWGui private: MyGUI::ScrollView* mScrollView; MyGUI::Widget* mClient; + std::string mListItemSkin; std::vector mItems; diff --git a/files/mygui/openmw_journal.layout b/files/mygui/openmw_journal.layout index 34421d431..c460aa41a 100644 --- a/files/mygui/openmw_journal.layout +++ b/files/mygui/openmw_journal.layout @@ -82,9 +82,7 @@ - - - + diff --git a/files/mygui/openmw_journal_skin.xml b/files/mygui/openmw_journal_skin.xml index ca6d309d7..71a2a7865 100644 --- a/files/mygui/openmw_journal_skin.xml +++ b/files/mygui/openmw_journal_skin.xml @@ -12,4 +12,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index 4dbc3da45..b2f9c1bef 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -157,6 +157,7 @@ +