Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
6.0 kB · 184 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185#include "list.hpp"
#include <MyGUI_Button.h>#include <MyGUI_Gui.h>#include <MyGUI_ImageBox.h>
#include <components/misc/strings/algorithm.hpp>
namespace Gui{
MWList::MWList() : mScrollView(nullptr) , mClient(nullptr) , mItemHeight(0) { }
void MWList::initialiseOverride() { Base::initialiseOverride();
assignWidget(mClient, "Client"); if (mClient == nullptr) mClient = this;
mScrollView = mClient->createWidgetReal<MyGUI::ScrollView>("MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0), MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView"); }
void MWList::addItem(std::string_view name, int verticalPadding) { mItems.emplace_back(name, verticalPadding); }
void MWList::addSeparator() { addItem({}); }
void MWList::adjustSize() { redraw(); }
void MWList::redraw(bool scrollbarShown) { constexpr int scrollbarShownScrollBarWidth = 20; // fetch this from skin? const int scrollBarWidth = scrollbarShown ? scrollbarShownScrollBarWidth : 0; int viewPosition = -mScrollView->getViewOffset().top;
while (mScrollView->getChildCount()) { MyGUI::Gui::getInstance().destroyWidget(mScrollView->getChildAt(0)); }
mItemHeight = 0; int i = 0; for (const auto& item : mItems) { mItemHeight += item.mVPadding; if (!item.mName.empty()) { if (mListItemSkin.empty()) return; MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(mListItemSkin, MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24), MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + item.mName); button->setCaption(item.mName); button->getSubWidgetText()->setWordWrap(true); button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left); button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheelMoved); button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected); button->setNeedKeyFocus(true);
// Morrowind list item text widgets are typically 18 pixels tall int height = button->getTextSize().height + 2; button->setSize(MyGUI::IntSize(button->getSize().width, height)); button->setUserData(i);
mItemHeight += height; } else { MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>("MW_HLine", MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth() - scrollBarWidth - 4, 18), MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch); separator->setNeedMouseFocus(false);
mItemHeight += 18; } mItemHeight += item.mVPadding; ++i; }
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the // scrollbar is hidden mScrollView->setVisibleVScroll(false); mScrollView->setCanvasSize(mClient->getSize().width, std::max(mItemHeight, mClient->getSize().height)); mScrollView->setVisibleVScroll(true);
if (!scrollbarShown && mItemHeight > mClient->getSize().height) redraw(true);
int viewRange = mScrollView->getCanvasSize().height; if (viewPosition > viewRange) viewPosition = viewRange; mScrollView->setViewOffset(MyGUI::IntPoint(0, -viewPosition)); }
void MWList::setPropertyOverride(std::string_view key, std::string_view value) { if (key == "ListItemSkin") mListItemSkin = value; else Base::setPropertyOverride(key, value); }
size_t MWList::getItemCount() { return mItems.size(); }
const std::string& MWList::getItemNameAt(size_t at) { assert(at < mItems.size() && "List item out of bounds"); return mItems[at].mName; }
void MWList::sort() { // A special case for separators is not needed for now std::sort(mItems.begin(), mItems.end(), [](const auto& left, const auto& right) { return Misc::StringUtils::ciLess(left.mName, right.mName); }); }
void MWList::removeItem(const std::string& name) { auto it = std::find_if(mItems.begin(), mItems.end(), [&name](const auto& item) { return item.mName == name; }); assert(it != mItems.end()); mItems.erase(it); }
void MWList::clear() { mItems.clear(); }
void MWList::onMouseWheelMoved(MyGUI::Widget* /*sender*/, int rel) { // NB view offset is negative if (mScrollView->getViewOffset().top + rel * 0.3f > 0) mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); else mScrollView->setViewOffset( MyGUI::IntPoint(0, static_cast<int>(mScrollView->getViewOffset().top + rel * 0.3))); }
void MWList::onItemSelected(MyGUI::Widget* sender) { std::string name = sender->castType<MyGUI::Button>()->getCaption(); int id = *sender->getUserData<int>(); eventItemSelected(name, id); eventWidgetSelected(sender); }
MyGUI::Button* MWList::getItemWidget(std::string_view name) { std::string search = getName() + "_item_"; search += name; return mScrollView->findWidget(search)->castType<MyGUI::Button>(); }
void MWList::scrollToTop() { mScrollView->setViewOffset(MyGUI::IntPoint(0, 0)); }
void MWList::setViewOffset(int offset) { mScrollView->setViewOffset(MyGUI::IntPoint(0, offset)); }}