summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui/widgets/extendedlistbox.cpp174
-rw-r--r--src/gui/widgets/extendedlistbox.h25
-rw-r--r--src/gui/widgets/listbox.cpp10
-rw-r--r--src/gui/widgets/listbox.h4
4 files changed, 174 insertions, 39 deletions
diff --git a/src/gui/widgets/extendedlistbox.cpp b/src/gui/widgets/extendedlistbox.cpp
index 3126b14b0..00bb5e5fd 100644
--- a/src/gui/widgets/extendedlistbox.cpp
+++ b/src/gui/widgets/extendedlistbox.cpp
@@ -44,7 +44,10 @@ ExtendedListBox::ExtendedListBox(const Widget2 *const widget,
mRowHeight(rowHeight),
mImagePadding(mSkin ? mSkin->getOption("imagePadding") : 0),
mSpacing(mSkin ? mSkin->getOption("spacing") : 0),
- mItemPadding(mSkin ? mSkin->getOption("itemPadding") : 1)
+ mItemPadding(mSkin ? mSkin->getOption("itemPadding") : 1),
+ mHeight(0),
+ mListItems(),
+ mSelectedItems()
{
if (!mRowHeight)
{
@@ -73,71 +76,172 @@ void ExtendedListBox::draw(gcn::Graphics *graphics)
updateAlpha();
gcn::Font *const font = getFont();
- const int height = getRowHeight();
+ const int height = mRowHeight;
const int pad2 = 2 + mPadding;
+ const int width = mDimension.width;
int textPos = (height - font->getHeight()) / 2 + mPadding;
if (textPos < 0)
textPos = 0;
- // Draw filled rectangle around the selected list element
- if (mSelected >= 0)
+ const int sz = mListModel->getNumberOfElements();
+ mListItems.clear();
+ mSelectedItems.clear();
+ int y = 0;
+ const int insideWidth = width - pad2;
+ for (int f = 0; f < sz; f ++)
+ {
+ int row = f;
+ bool useImage = true;
+ std::string str = mListModel->getElementAt(f);
+ int strWidth = font->getWidth(str) + 8;
+
+ const Image *const image = model->getImageAt(row);
+ if (image)
+ strWidth += image->getWidth() + mImagePadding;
+
+ std::vector<ExtendedListBoxItem> &list =
+ row == mSelected ? mSelectedItems : mListItems;
+
+ if (insideWidth < strWidth)
+ {
+ const int strSize = str.size();
+ list.push_back(ExtendedListBoxItem(row,
+ str.substr(0, strSize / 2), useImage, y));
+ str = str.substr(strSize / 2);
+ y += height;
+ useImage = false;
+ }
+ list.push_back(ExtendedListBoxItem(row, str, useImage, y));
+
+ y += height;
+ }
+ mHeight = y + height;
+
+ const int itemsSz = mListItems.size();
+ const int selSz = mSelectedItems.size();
+ int minY = -1;
+ int maxY = -1;
+ for (int f = 0; f < selSz; f ++)
+ {
+ const ExtendedListBoxItem &item = mSelectedItems[f];
+ const int y1 = item.y;
+ if (minY == -1)
+ minY = y1;
+ if (maxY < y1)
+ maxY = y1;
+ }
+
+ if (minY != -1)
{
mHighlightColor.a = static_cast<int>(mAlpha * 255.0f);
graphics->setColor(mHighlightColor);
- graphics->fillRectangle(gcn::Rectangle(mPadding,
- height * mSelected + mPadding,
- getWidth() - pad2, height));
+ graphics->fillRectangle(gcn::Rectangle(mPadding, minY + mPadding,
+ width - pad2, maxY - minY + height));
}
- const int sz = mListModel->getNumberOfElements();
- for (int i = 0, y = 0; i < sz; ++i, y += height)
+ for (int f = 0; f < itemsSz; ++f)
{
- if (i != mSelected)
+ const ExtendedListBoxItem &item = mListItems[f];
+ const int row1 = item.row;
+ if (item.image)
{
- const Image *const image = model->getImageAt(i);
+ const Image *const image = model->getImageAt(row1);
if (image)
{
- g->drawImage(image, mImagePadding, y + (height
+ g->drawImage(image, mImagePadding, item.y + (height
- image->getHeight()) / 2 + mPadding);
}
}
}
+
g->setColorAll(mForegroundColor, mForegroundColor2);
- for (int i = 0, y = 0; i < sz; ++i, y += height)
+
+ for (int f = 0; f < itemsSz; ++f)
{
- if (i != mSelected)
+ const ExtendedListBoxItem &item = mListItems[f];
+ const int row1 = item.row;
+ const int y1 = item.y;
+ const Image *const image = model->getImageAt(row1);
+ if (!image || !item.image)
{
- const Image *const image = model->getImageAt(i);
- if (!image)
- {
- font->drawString(graphics, mListModel->getElementAt(i),
- mPadding, y + textPos);
- }
- else
+ font->drawString(graphics, item.text, mPadding, y1 + textPos);
+ }
+ else
+ {
+ font->drawString(graphics, item.text,
+ image->getWidth() + mImagePadding + mSpacing, y1 + textPos);
+ }
+ }
+
+
+
+ for (int f = 0; f < selSz; ++f)
+ {
+ const ExtendedListBoxItem &item = mSelectedItems[f];
+ const int row1 = item.row;
+ if (item.image)
+ {
+ const Image *const image = model->getImageAt(row1);
+ if (image)
{
- font->drawString(graphics, mListModel->getElementAt(i),
- image->getWidth() + mImagePadding + mSpacing, y + textPos);
+ g->drawImage(image, mImagePadding, item.y + (height
+ - image->getHeight()) / 2 + mPadding);
}
}
}
- if (mSelected >= 0)
+
+ g->setColorAll(mForegroundSelectedColor, mForegroundSelectedColor2);
+
+ for (int f = 0; f < selSz; ++f)
{
- const Image *const image = model->getImageAt(mSelected);
- if (!image)
+ const ExtendedListBoxItem &item = mSelectedItems[f];
+ const int row1 = item.row;
+ const int y1 = item.y;
+ const Image *const image = model->getImageAt(row1);
+ if (!image || !item.image)
{
- font->drawString(graphics, mListModel->getElementAt(mSelected),
- mPadding, mSelected * height + textPos);
+ font->drawString(graphics, item.text, mPadding, y1 + textPos);
}
else
{
- const int y = mSelected * height;
- g->drawImage(image, mImagePadding, y + (height
- - image->getHeight()) / 2 + mPadding);
- g->setColorAll(mForegroundSelectedColor,
- mForegroundSelectedColor2);
- font->drawString(graphics, mListModel->getElementAt(mSelected),
- image->getWidth() + mImagePadding + mSpacing, y + textPos);
+ font->drawString(graphics, item.text,
+ image->getWidth() + mImagePadding + mSpacing, y1 + textPos);
}
}
+
BLOCK_END("ExtendedListBox::draw")
}
+
+void ExtendedListBox::adjustSize()
+{
+ if (mHeight)
+ setHeight(mHeight + 2 * mPadding);
+ else
+ ListBox::adjustSize();
+}
+
+int ExtendedListBox::getSelectionByMouse(const int y) const
+{
+ if (mListItems.empty() && mSelectedItems.empty())
+ return ListBox::getSelectionByMouse(y);
+
+ const int height = mRowHeight;
+ const int itemsSz = mListItems.size();
+ for (int f = 0; f < itemsSz; f ++)
+ {
+ const ExtendedListBoxItem &item = mListItems[f];
+ const int y2 = item.y;
+ if (y2 <= y && y2 + height > y)
+ return item.row;
+ }
+
+ const int selSz = mSelectedItems.size();
+ for (int f = 0; f < selSz; f ++)
+ {
+ const ExtendedListBoxItem &item = mSelectedItems[f];
+ const int y2 = item.y;
+ if (y2 <= y && y2 + height > y)
+ return item.row;
+ }
+ return 0;
+}
diff --git a/src/gui/widgets/extendedlistbox.h b/src/gui/widgets/extendedlistbox.h
index 9d3394dd4..79fef2f50 100644
--- a/src/gui/widgets/extendedlistbox.h
+++ b/src/gui/widgets/extendedlistbox.h
@@ -23,6 +23,24 @@
#include "gui/widgets/listbox.h"
+struct ExtendedListBoxItem
+{
+ ExtendedListBoxItem(const int row0,
+ const std::string &text0,
+ const bool image0,
+ const int y0) :
+ row(row0),
+ text(text0),
+ image(image0),
+ y(y0)
+ {
+ }
+ int row;
+ std::string text;
+ bool image;
+ int y;
+};
+
class ExtendedListBox final : public ListBox
{
public:
@@ -49,11 +67,18 @@ class ExtendedListBox final : public ListBox
void setRowHeight(unsigned int n)
{ mRowHeight = n; }
+ void adjustSize() override;
+
+ int getSelectionByMouse(const int y) const override;
+
protected:
unsigned int mRowHeight;
int mImagePadding;
int mSpacing;
int mItemPadding;
+ int mHeight;
+ std::vector<ExtendedListBoxItem> mListItems;
+ std::vector<ExtendedListBoxItem> mSelectedItems;
};
#endif // GUI_WIDGETS_EXTENDEDLISTBOX_H
diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp
index 2f0f8d941..e5229eca6 100644
--- a/src/gui/widgets/listbox.cpp
+++ b/src/gui/widgets/listbox.cpp
@@ -209,8 +209,7 @@ void ListBox::mousePressed1(gcn::MouseEvent &mouseEvent)
{
if (mouseEvent.getButton() == gcn::MouseEvent::LEFT)
{
- setSelected(std::max(0, mouseEvent.getY() - mPadding)
- / getRowHeight());
+ setSelected(std::max(0, getSelectionByMouse(mouseEvent.getY())));
distributeActionEvent();
}
}
@@ -222,7 +221,7 @@ void ListBox::mouseDragged(gcn::MouseEvent &event)
// Make list selection update on drag, but guard against negative y
if (getRowHeight())
- setSelected(std::max(0, event.getY() - mPadding) / getRowHeight());
+ setSelected(std::max(0, getSelectionByMouse(event.getY())));
}
void ListBox::refocus()
@@ -249,3 +248,8 @@ void ListBox::logic()
{
adjustSize();
}
+
+int ListBox::getSelectionByMouse(const int y) const
+{
+ return (y - mPadding) / getRowHeight();
+}
diff --git a/src/gui/widgets/listbox.h b/src/gui/widgets/listbox.h
index a4a931a1f..113174332 100644
--- a/src/gui/widgets/listbox.h
+++ b/src/gui/widgets/listbox.h
@@ -85,10 +85,12 @@ class ListBox : public gcn::ListBox,
void setDistributeMousePressed(bool b)
{ mDistributeMousePressed = b; }
- void adjustSize();
+ virtual void adjustSize();
void logic() override;
+ virtual int getSelectionByMouse(const int y) const;
+
protected:
gcn::Color mHighlightColor;
gcn::Color mForegroundColor2;