GUI: Moved Grid widgets to separate files.

This commit is contained in:
av-dx 2021-06-12 15:59:42 +05:30 committed by Eugene Sandulenko
parent f3f657bd8d
commit 6a57173c5a
6 changed files with 529 additions and 467 deletions

View File

@ -50,6 +50,7 @@
#include "gui/widgets/list.h"
#include "gui/widgets/tab.h"
#include "gui/widgets/popup.h"
#include "gui/widgets/grid.h"
#include "gui/ThemeEval.h"
#include "engines/advancedDetector.h"

View File

@ -35,6 +35,7 @@ MODULE_OBJS := \
widgets/edittext.o \
widgets/list.o \
widgets/popup.o \
widgets/grid.o \
widgets/scrollbar.o \
widgets/scrollcontainer.o \
widgets/tab.o

View File

@ -36,9 +36,6 @@
#include "gui/widgets/popup.h"
#include "gui/widgets/scrollcontainer.h"
#include "image/bmp.h"
#include "image/png.h"
namespace GUI {
Widget::Widget(GuiObject *boss, int x, int y, int w, int h, const Common::U32String &tooltip)
@ -1010,357 +1007,6 @@ void ContainerWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _backgroundType);
}
#pragma mark -
GridItemWidget::GridItemWidget(GridWidget *boss, int x, int y, int w, int h) :
ContainerWidget(boss, x, y, w, h) {
_plat = new GraphicsWidget(this, kThumbnailWidth - 32, kThumbnailHeight - 32, 32, 32);
_lang = new StaticTextWidget(this, kThumbnailWidth - 32, 0, 32, 32, Common::U32String("XX"), Graphics::TextAlign::kTextAlignRight);
_title = new StaticTextWidget(this, 0, kThumbnailHeight, w , kLineHeight*2, Common::U32String("Title"), Graphics::TextAlign::kTextAlignLeft);
_thumb = new GraphicsWidget(this, 0, 0 , kThumbnailWidth, kThumbnailHeight);
_activeEntry = nullptr;
_grid = boss;
}
GridItemWidget::GridItemWidget(GridWidget *boss, GraphicsWidget *th, GraphicsWidget *p, StaticTextWidget *l, StaticTextWidget *t) :
ContainerWidget(boss, 0, 0, 0, 0), _thumb(th), _plat(p), _lang(l), _title(t) {
_activeEntry = nullptr;
_grid = boss;
}
void GridItemWidget::attachEntry(Common::String key, Common::String description, Common::ConfigManager::Domain *domain) {
Common::String gameid = domain->getVal("gameid");
Common::String engineid = domain->getVal("engineid");
Common::String language = "XX";
Common::String platform = "UNK";
domain->tryGetVal("language",language);
domain->tryGetVal("platform", platform);
_attachedEntries.push_back(GridItemInfo(gameid, engineid, description, language, platform));
}
void GridItemWidget::attachEntry(GridItemInfo &entry) {
_attachedEntries.push_back(entry);
}
void GridItemWidget::attachEntries(Common::Array<GridItemInfo> entries) {
_attachedEntries.push_back(entries);
}
void GridItemWidget::setActiveEntry(GridItemInfo &entry) {
_activeEntry = &entry;
}
void GridItemWidget::updateThumb() {
const Graphics::ManagedSurface *gfx = _grid->filenameToSurface(_activeEntry->thumbPath);
_thumb->setGfx(gfx);
}
void GridItemWidget::update() {
if ((!_activeEntry) && (!_attachedEntries.empty())) {
_activeEntry = _attachedEntries.begin();
}
updateThumb();
_lang->setLabel(_activeEntry->language);
_title->setLabel(_activeEntry->title);
const Graphics::ManagedSurface *gfx;
if (_activeEntry->platform == "pc")
gfx = _grid->platformToSurface(kPlatformDOS);
else if (_activeEntry->platform == "amiga")
gfx = _grid->platformToSurface(kPlatformAmiga);
else if (_activeEntry->platform == "apple2")
gfx = _grid->platformToSurface(kPlatformApple2);
else
gfx = _grid->platformToSurface(kPlatformUnknown);
_plat->setGfx(gfx);
markAsDirty();
}
void GridItemWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x,_y,_x+kThumbnailWidth,_y+kThumbnailHeight), ThemeEngine::WidgetBackground::kThumbnailBackground);
}
#pragma mark -
Graphics::ManagedSurface *loadSurfaceFromFile(Common::String &name) {
Graphics::ManagedSurface *surf = nullptr;
const Graphics::Surface *srcSurface = nullptr;
if (name.hasSuffix(".png")) {
#ifdef USE_PNG
Image::PNGDecoder decoder;
Common::FSNode fileNode(name);
Common::SeekableReadStream * stream = fileNode.createReadStream();
if (stream) {
if (!decoder.loadStream(*stream))
warning("Error decoding PNG");
srcSurface = decoder.getSurface();
delete stream;
if (!srcSurface) {
warning("Failed to load surface : %s", name.c_str());
}
if (srcSurface && srcSurface->format.bytesPerPixel != 1) {
surf = new Graphics::ManagedSurface(srcSurface->convertTo(g_system->getOverlayFormat()));
}
} else {
warning("No such file : %s", name.c_str());
}
#else
error("No PNG support compiled");
#endif
}
else {
}
return surf;
}
#pragma mark -
GridWidget::GridWidget(GuiObject *boss, int x, int y, int w, int h) :
ContainerWidget(boss, x, y, w, h) {
loadPlatformIcons();
}
GridWidget::GridWidget(GuiObject *boss, const Common::String &name) :
ContainerWidget(boss, name) {
loadPlatformIcons();
_gridItemHeight = kThumbnailHeight + (2*kLineHeight);
_gridItemWidth = kThumbnailWidth;
_scrollBar = new ScrollBarWidget(this, 0, 0, 20, 100);
_scrollBar->setTarget(this);
_scrollPos = 0;
}
void GridWidget::setEntryList(Common::Array<GridItemInfo> *list) {
for (auto entryIter = list->begin(); entryIter != list->end(); ++entryIter) {
_allEntries.push_back(*entryIter);
}
}
void GridWidget::destroyItems() {
for (Common::Array<GridItemWidget *>::iterator i = _gridItems.begin(), end = _gridItems.end(); i != end; ++i) {
removeWidget((*i));
delete (*i);
}
_gridItems.clear();
}
void GridWidget::loadPlatformIcons() {
for (auto iter = _platformIcons.begin(); iter != _platformIcons.end(); ++iter) {
delete *iter;
}
_platformIcons.clear();
Common::String pathPrefix("./icons/");
Common::Array<Common::String> iconFilenames;
iconFilenames.push_back(Common::String("dos.png"));
iconFilenames.push_back(Common::String("amiga.png"));
iconFilenames.push_back(Common::String("apple2.png"));
for (auto i = iconFilenames.begin(); i != iconFilenames.end(); ++i) {
Common::String fullPath = pathPrefix + (*i);
Graphics::ManagedSurface *gfx = loadSurfaceFromFile(fullPath);
if (gfx) {
const Graphics::ManagedSurface *scGfx = scaleGfx(gfx, 32, 32);
_platformIcons.push_back(scGfx);
gfx->free();
delete gfx;
}
}
}
bool GridWidget::calcVisibleEntries() {
bool needsReload = false;
int nFirstVisibleItem = 0;
int nItemsOnScreen = 0;
nFirstVisibleItem = _itemsPerRow * (-_scrollPos / (_gridItemHeight + kGridItemVPadding));
nItemsOnScreen = (3 + (_scrollWindowHeight / (_gridItemHeight + kGridItemVPadding))) * (_itemsPerRow);
if ((nFirstVisibleItem != _firstVisibleItem) || (nItemsOnScreen != _itemsOnScreen)) {
needsReload = true;
_firstVisibleItem = nFirstVisibleItem;
_itemsOnScreen = nItemsOnScreen;
int toRender = MIN(_firstVisibleItem + _itemsOnScreen, (int)_allEntries.size()-1);
_visibleEntries.clear();
for (int ind = _firstVisibleItem; ind < toRender; ++ind) {
GridItemInfo *iter = _allEntries.begin() + ind;
_visibleEntries.push_back(*iter);
}
}
return needsReload;
}
void GridWidget::reloadThumbnails() {
Graphics::ManagedSurface *surf = nullptr;
Common::String gameid;
Common::String engineid;
Common::String path;
for (Common::Array<GridItemInfo>::iterator iter = _visibleEntries.begin(); iter != _visibleEntries.end(); ++iter) {
path = Common::String("./icons/")+iter->thumbPath;
if (_loadedSurfaces.contains(path)) {
// warning("Thumbnail already loaded, skipping...");
}
else {
surf = loadSurfaceFromFile(path);
if (surf) {
const Graphics::ManagedSurface *scSurf(scaleGfx(surf, kThumbnailWidth, 512));
_loadedSurfaces[path] = scSurf;
}
}
}
}
const Graphics::ManagedSurface *GridWidget::filenameToSurface(Common::String &name) {
Common::String path = Common::String("./icons/")+name;
for (auto l = _visibleEntries.begin(); l!=_visibleEntries.end(); ++l) {
if (l->thumbPath == name) {
return _loadedSurfaces[path];
}
}
return nullptr;
}
const Graphics::ManagedSurface *GridWidget::platformToSurface(Platform platformCode) {
if ((platformCode == kPlatformUnknown) || (platformCode < 0 || platformCode >= _platformIcons.size())) {
warning("Unknown Platform");
return nullptr;
}
return _platformIcons[platformCode];
}
void GridWidget::handleMouseWheel(int x, int y, int direction) {
int scrollSpeed = -direction*40;
_scrollPos += scrollSpeed;
if (_scrollPos > 0) {
_scrollPos = 0;
scrollSpeed = 0;
}
if (_scrollPos < -(_innerHeight - _scrollWindowHeight)) {
_scrollPos = -(_innerHeight - _scrollWindowHeight);
scrollSpeed = 0;
}
bool needsReload = calcVisibleEntries();
if (needsReload) {
reloadThumbnails();
}
// warning("%d %d", _visibleEntries.size(), _gridItems.size());
Common::Array<GridItemInfo>::iterator eIter = _visibleEntries.begin();
Common::Array<GridItemWidget *>::iterator iter = _gridItems.begin() + (_firstVisibleItem % _gridItems.size());
for (int k = 0; k < _gridItems.size(); ++k) {
GridItemWidget *it = *iter;
it->setPos(it->getRelX(), scrollSpeed + it->getRelY());
if (it->getRelY() <= -_gridItemHeight) {
it->setVisible(false);
if (it->getRelY() <= -((_gridItemHeight) * 2)) {
it->setPos(it->getRelX(), it->getRelY() + ((_itemsOnScreen / _itemsPerRow) * (kThumbnailHeight + 80)));
}
}
else if (it->getRelY() >= _h) {
it->setVisible(false);
if (it->getRelY() >= -_gridItemHeight + ((_itemsOnScreen / _itemsPerRow) * (kThumbnailHeight + 80))) {
it->setPos(it->getRelX(), it->getRelY() - ((_itemsOnScreen / _itemsPerRow) * (kThumbnailHeight + 80)));
}
}
else {
it->setVisible(true);
}
if (eIter != _visibleEntries.end()) {
it->setActiveEntry(*eIter);
eIter++;
}
else {
it->setActiveEntry(*_visibleEntries.begin());
it->setVisible(false);
}
iter++;
if (iter == _gridItems.end())
iter = _gridItems.begin();
}
if (needsReload) {
updateGrid();
}
markAsDirty();
}
void GridWidget::reflowLayout() {
Widget::reflowLayout();
destroyItems();
_scrollWindowHeight = _h;
_scrollWindowWidth = _w;
_itemsPerRow = MAX((((int)_scrollWindowWidth - 100) / kThumbnailWidth) - 1, 1);
int rows = _allEntries.size() / _itemsPerRow; // change this to be calced using eindow sizes
_innerHeight = 100 + ((rows + 1) * (kThumbnailHeight + 80));
_innerWidth = 100 + (_itemsPerRow * (kThumbnailWidth + 50));
if (_scrollPos < -(_innerHeight - _scrollWindowHeight))
_scrollPos = -(_innerHeight - _scrollWindowHeight);
int row = 0;
int col = 0;
if (calcVisibleEntries()) {
reloadThumbnails();
}
for (Common::Array<GridItemInfo>::iterator i = _visibleEntries.begin(); i != _visibleEntries.end(); ++i) {
GridItemWidget *newEntry = nullptr;
if (!newEntry) {
newEntry = new GridItemWidget(this,
50 + col * (kThumbnailWidth + 50),
_scrollPos + 50 + row * (kThumbnailHeight + 80),
kThumbnailWidth,
kThumbnailHeight+kLineHeight*2);
_gridItems.push_back(newEntry);
if ((newEntry->getRelY() <= -_gridItemHeight) || (newEntry->getRelY() >= _h)) {
newEntry->setVisible(false);
}
else {
newEntry->setVisible(true);
}
if (++col >= _itemsPerRow) {
++row;
col = 0;
}
}
newEntry->attachEntry(*i);
newEntry->update();
}
markAsDirty();
}
void GridWidget::updateGrid() {
for (auto i = _gridItems.begin(); i != _gridItems.end(); ++i) {
(*i)->update();
}
}
#pragma mark -
OptionsContainerWidget::OptionsContainerWidget(GuiObject *boss, const Common::String &name, const Common::String &dialogLayout,

View File

@ -461,119 +461,6 @@ protected:
ThemeEngine::WidgetBackground _backgroundType;
};
enum Platform {
kPlatformDOS,
kPlatformAmiga,
kPlatformApple2,
kPlatformUnknown = -1
};
struct GridItemInfo
{
Common::String engineid;
Common::String gameid;
Common::String language;
Common::String title;
Common::String platform;
Common::String thumbPath;
GridItemInfo(Common::String &eid, Common::String &gid, Common::String &t, Common::String &l, Common::String &p) :
gameid(gid), engineid(eid), title(t), language(l), platform(p) {
thumbPath = Common::String::format("%s-%s.png", engineid.c_str(), gameid.c_str());
}
};
class GridItemWidget;
/* GridWidget */
class GridWidget : public ContainerWidget {
private:
Common::Array<const Graphics::ManagedSurface *> _platformIcons;
// _gridItems should be reserved to hold few more than visible items
// Fixing it to 30 for now, 6 items * (4 rows + 1 extra row);
Common::Array<GridItemWidget *> _gridItems;
Common::Array<GridItemInfo> _allEntries;
Common::Array<GridItemInfo> _visibleEntries;
Common::HashMap<Common::String, const Graphics::ManagedSurface *> _loadedSurfaces;
Common::Array<Common::Array<GridItemWidget *>> _grid;
ScrollBarWidget *_scrollBar;
uint16 _scrollWindowHeight, _scrollWindowWidth, _scrollSpeed;
uint16 _innerHeight, _innerWidth;
uint16 _thumbnailHeight, _thumbnailWidth;
uint16 _gridItemHeight, _gridItemWidth;
int _scrollPos;
int _itemsPerRow;
int _firstVisibleItem;
int _itemsOnScreen;
bool _titlesVisible;
public:
GridWidget(GuiObject *boss, int x, int y, int w, int h);
GridWidget(GuiObject *boss, const Common::String &name);
const Graphics::ManagedSurface * filenameToSurface(Common::String &name);
const Graphics::ManagedSurface * platformToSurface(Platform platformCode);
bool calcVisibleEntries(void);
void setEntryList(Common::Array<GridItemInfo> *list);
void destroyItems();
void loadPlatformIcons();
void updateGrid(void);
void gridFromGameList();
int getLoadedNumber(void) {return _loadedSurfaces.size();}
void reloadThumbnails();
void handleMouseWheel(int x, int y, int direction) override;
void reflowLayout() override;
int selectedEntry;
};
enum {
kGridItemHPadding = 50,
kGridItemVPadding = 50,
kThumbnailWidth = 192,
kThumbnailHeight = 192
};
/* EntryContainerWidget */
class GridItemWidget : public ContainerWidget {
public:
GraphicsWidget *_thumb;
GraphicsWidget *_plat;
StaticTextWidget *_lang;
StaticTextWidget *_title;
GridWidget *_grid;
Common::Array<GridItemInfo> _attachedEntries;
GridItemInfo *_activeEntry;
bool isHighlighted;
void setActiveEntry(GridItemInfo &entry);
public:
GridItemWidget(GridWidget *boss, int x, int y, int w, int h);
GridItemWidget(GridWidget *boss, GraphicsWidget *th, GraphicsWidget *p, StaticTextWidget *l, StaticTextWidget *t);
void attachEntry(Common::String key, Common::String description, Common::ConfigManager::Domain *domain);
void attachEntry(GridItemInfo &entry);
void attachEntries(Common::Array<GridItemInfo> entry);
void setActiveEntry(int i) {setActiveEntry(_attachedEntries[i]);};
void update();
void updateThumb();
void drawWidget() override;
};
/* OptionsContainerWidget */
class OptionsContainerWidget : public Widget {
public:

377
gui/widgets/grid.cpp Normal file
View File

@ -0,0 +1,377 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "common/system.h"
#include "gui/gui-manager.h"
#include "gui/widgets/grid.h"
#include "gui/ThemeEval.h"
namespace GUI {
GridItemWidget::GridItemWidget(GridWidget *boss, int x, int y, int w, int h) :
ContainerWidget(boss, x, y, w, h) {
_plat = new GraphicsWidget(this, kThumbnailWidth - 32, kThumbnailHeight - 32, 32, 32);
_lang = new StaticTextWidget(this, kThumbnailWidth - 32, 0, 32, 32, Common::U32String("XX"), Graphics::TextAlign::kTextAlignRight);
_title = new StaticTextWidget(this, 0, kThumbnailHeight, w , kLineHeight*2, Common::U32String("Title"), Graphics::TextAlign::kTextAlignLeft);
_thumb = new GraphicsWidget(this, 0, 0 , kThumbnailWidth, kThumbnailHeight);
_activeEntry = nullptr;
_grid = boss;
}
GridItemWidget::GridItemWidget(GridWidget *boss, GraphicsWidget *th, GraphicsWidget *p, StaticTextWidget *l, StaticTextWidget *t) :
ContainerWidget(boss, 0, 0, 0, 0), _thumb(th), _plat(p), _lang(l), _title(t) {
_activeEntry = nullptr;
_grid = boss;
}
void GridItemWidget::attachEntry(Common::String key, Common::String description, Common::ConfigManager::Domain *domain) {
Common::String gameid = domain->getVal("gameid");
Common::String engineid = domain->getVal("engineid");
Common::String language = "XX";
Common::String platform = "UNK";
domain->tryGetVal("language",language);
domain->tryGetVal("platform", platform);
_attachedEntries.push_back(GridItemInfo(gameid, engineid, description, language, platform));
}
void GridItemWidget::attachEntry(GridItemInfo &entry) {
_attachedEntries.push_back(entry);
}
void GridItemWidget::attachEntries(Common::Array<GridItemInfo> entries) {
_attachedEntries.push_back(entries);
}
void GridItemWidget::setActiveEntry(GridItemInfo &entry) {
_activeEntry = &entry;
}
void GridItemWidget::updateThumb() {
const Graphics::ManagedSurface *gfx = _grid->filenameToSurface(_activeEntry->thumbPath);
_thumb->setGfx(gfx);
}
void GridItemWidget::update() {
if ((!_activeEntry) && (!_attachedEntries.empty())) {
_activeEntry = _attachedEntries.begin();
}
updateThumb();
_lang->setLabel(_activeEntry->language);
_title->setLabel(_activeEntry->title);
const Graphics::ManagedSurface *gfx;
if (_activeEntry->platform == "pc")
gfx = _grid->platformToSurface(kPlatformDOS);
else if (_activeEntry->platform == "amiga")
gfx = _grid->platformToSurface(kPlatformAmiga);
else if (_activeEntry->platform == "apple2")
gfx = _grid->platformToSurface(kPlatformApple2);
else
gfx = _grid->platformToSurface(kPlatformUnknown);
_plat->setGfx(gfx);
markAsDirty();
}
void GridItemWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x,_y,_x+kThumbnailWidth,_y+kThumbnailHeight), ThemeEngine::WidgetBackground::kThumbnailBackground);
}
#pragma mark -
Graphics::ManagedSurface *loadSurfaceFromFile(Common::String &name) {
Graphics::ManagedSurface *surf = nullptr;
const Graphics::Surface *srcSurface = nullptr;
if (name.hasSuffix(".png")) {
#ifdef USE_PNG
Image::PNGDecoder decoder;
Common::FSNode fileNode(name);
Common::SeekableReadStream * stream = fileNode.createReadStream();
if (stream) {
if (!decoder.loadStream(*stream))
warning("Error decoding PNG");
srcSurface = decoder.getSurface();
delete stream;
if (!srcSurface) {
warning("Failed to load surface : %s", name.c_str());
}
if (srcSurface && srcSurface->format.bytesPerPixel != 1) {
surf = new Graphics::ManagedSurface(srcSurface->convertTo(g_system->getOverlayFormat()));
}
} else {
warning("No such file : %s", name.c_str());
}
#else
error("No PNG support compiled");
#endif
}
else {
}
return surf;
}
#pragma mark -
GridWidget::GridWidget(GuiObject *boss, int x, int y, int w, int h) :
ContainerWidget(boss, x, y, w, h) {
loadPlatformIcons();
}
GridWidget::GridWidget(GuiObject *boss, const Common::String &name) :
ContainerWidget(boss, name) {
loadPlatformIcons();
_gridItemHeight = kThumbnailHeight + (2*kLineHeight);
_gridItemWidth = kThumbnailWidth;
_scrollPos = 0;
}
void GridWidget::setEntryList(Common::Array<GridItemInfo> *list) {
for (auto entryIter = list->begin(); entryIter != list->end(); ++entryIter) {
_allEntries.push_back(*entryIter);
}
}
void GridWidget::destroyItems() {
for (Common::Array<GridItemWidget *>::iterator i = _gridItems.begin(), end = _gridItems.end(); i != end; ++i) {
removeWidget((*i));
delete (*i);
}
_gridItems.clear();
}
void GridWidget::loadPlatformIcons() {
for (auto iter = _platformIcons.begin(); iter != _platformIcons.end(); ++iter) {
delete *iter;
}
_platformIcons.clear();
Common::String pathPrefix("./icons/");
Common::Array<Common::String> iconFilenames;
iconFilenames.push_back(Common::String("dos.png"));
iconFilenames.push_back(Common::String("amiga.png"));
iconFilenames.push_back(Common::String("apple2.png"));
for (auto i = iconFilenames.begin(); i != iconFilenames.end(); ++i) {
Common::String fullPath = pathPrefix + (*i);
Graphics::ManagedSurface *gfx = loadSurfaceFromFile(fullPath);
if (gfx) {
const Graphics::ManagedSurface *scGfx = scaleGfx(gfx, 32, 32);
_platformIcons.push_back(scGfx);
gfx->free();
delete gfx;
}
}
}
bool GridWidget::calcVisibleEntries() {
bool needsReload = false;
int nFirstVisibleItem = 0;
int nItemsOnScreen = 0;
nFirstVisibleItem = _itemsPerRow * (-_scrollPos / (_gridItemHeight + kGridItemVPadding));
nItemsOnScreen = (3 + (_scrollWindowHeight / (_gridItemHeight + kGridItemVPadding))) * (_itemsPerRow);
if ((nFirstVisibleItem != _firstVisibleItem) || (nItemsOnScreen != _itemsOnScreen)) {
needsReload = true;
_firstVisibleItem = nFirstVisibleItem;
_itemsOnScreen = nItemsOnScreen;
int toRender = MIN(_firstVisibleItem + _itemsOnScreen, (int)_allEntries.size()-1);
_visibleEntries.clear();
for (int ind = _firstVisibleItem; ind < toRender; ++ind) {
GridItemInfo *iter = _allEntries.begin() + ind;
_visibleEntries.push_back(*iter);
}
}
return needsReload;
}
void GridWidget::reloadThumbnails() {
Graphics::ManagedSurface *surf = nullptr;
Common::String gameid;
Common::String engineid;
Common::String path;
for (Common::Array<GridItemInfo>::iterator iter = _visibleEntries.begin(); iter != _visibleEntries.end(); ++iter) {
path = Common::String("./icons/")+iter->thumbPath;
if (_loadedSurfaces.contains(path)) {
// warning("Thumbnail already loaded, skipping...");
}
else {
surf = loadSurfaceFromFile(path);
if (surf) {
const Graphics::ManagedSurface *scSurf(scaleGfx(surf, kThumbnailWidth, 512));
_loadedSurfaces[path] = scSurf;
}
}
}
}
const Graphics::ManagedSurface *GridWidget::filenameToSurface(Common::String &name) {
Common::String path = Common::String("./icons/")+name;
for (auto l = _visibleEntries.begin(); l!=_visibleEntries.end(); ++l) {
if (l->thumbPath == name) {
return _loadedSurfaces[path];
}
}
return nullptr;
}
const Graphics::ManagedSurface *GridWidget::platformToSurface(Platform platformCode) {
if ((platformCode == kPlatformUnknown) || (platformCode < 0 || platformCode >= _platformIcons.size())) {
warning("Unknown Platform");
return nullptr;
}
return _platformIcons[platformCode];
}
void GridWidget::handleMouseWheel(int x, int y, int direction) {
int scrollSpeed = -direction*40;
_scrollPos += scrollSpeed;
if (_scrollPos > 0) {
_scrollPos = 0;
scrollSpeed = 0;
}
if (_scrollPos < -(_innerHeight - _scrollWindowHeight)) {
_scrollPos = -(_innerHeight - _scrollWindowHeight);
scrollSpeed = 0;
}
bool needsReload = calcVisibleEntries();
if (needsReload) {
reloadThumbnails();
}
// warning("%d %d", _visibleEntries.size(), _gridItems.size());
Common::Array<GridItemInfo>::iterator eIter = _visibleEntries.begin();
Common::Array<GridItemWidget *>::iterator iter = _gridItems.begin() + (_firstVisibleItem % _gridItems.size());
for (int k = 0; k < _gridItems.size(); ++k) {
GridItemWidget *it = *iter;
it->setPos(it->getRelX(), scrollSpeed + it->getRelY());
if (it->getRelY() <= -_gridItemHeight) {
it->setVisible(false);
if (it->getRelY() <= -((_gridItemHeight) * 2)) {
it->setPos(it->getRelX(), it->getRelY() + ((_itemsOnScreen / _itemsPerRow) * (kThumbnailHeight + 80)));
}
}
else if (it->getRelY() >= _h) {
it->setVisible(false);
if (it->getRelY() >= -_gridItemHeight + ((_itemsOnScreen / _itemsPerRow) * (kThumbnailHeight + 80))) {
it->setPos(it->getRelX(), it->getRelY() - ((_itemsOnScreen / _itemsPerRow) * (kThumbnailHeight + 80)));
}
}
else {
it->setVisible(true);
}
if (eIter != _visibleEntries.end()) {
it->setActiveEntry(*eIter);
eIter++;
}
else {
it->setActiveEntry(*_visibleEntries.begin());
it->setVisible(false);
}
iter++;
if (iter == _gridItems.end())
iter = _gridItems.begin();
}
if (needsReload) {
updateGrid();
}
markAsDirty();
}
void GridWidget::reflowLayout() {
Widget::reflowLayout();
destroyItems();
_scrollWindowHeight = _h;
_scrollWindowWidth = _w;
_itemsPerRow = MAX((((int)_scrollWindowWidth - 100) / kThumbnailWidth) - 1, 1);
int rows = _allEntries.size() / _itemsPerRow; // change this to be calced using eindow sizes
_innerHeight = 100 + ((rows + 1) * (kThumbnailHeight + 80));
_innerWidth = 100 + (_itemsPerRow * (kThumbnailWidth + 50));
if (_scrollPos < -(_innerHeight - _scrollWindowHeight))
_scrollPos = -(_innerHeight - _scrollWindowHeight);
int row = 0;
int col = 0;
if (calcVisibleEntries()) {
reloadThumbnails();
}
for (Common::Array<GridItemInfo>::iterator i = _visibleEntries.begin(); i != _visibleEntries.end(); ++i) {
GridItemWidget *newEntry = nullptr;
if (!newEntry) {
newEntry = new GridItemWidget(this,
50 + col * (kThumbnailWidth + 50),
_scrollPos + 50 + row * (kThumbnailHeight + 80),
kThumbnailWidth,
kThumbnailHeight+kLineHeight*2);
_gridItems.push_back(newEntry);
if ((newEntry->getRelY() <= -_gridItemHeight) || (newEntry->getRelY() >= _h)) {
newEntry->setVisible(false);
}
else {
newEntry->setVisible(true);
}
if (++col >= _itemsPerRow) {
++row;
col = 0;
}
}
newEntry->attachEntry(*i);
newEntry->update();
}
markAsDirty();
}
void GridWidget::updateGrid() {
for (auto i = _gridItems.begin(); i != _gridItems.end(); ++i) {
(*i)->update();
}
}
} // End of namespace GUI

150
gui/widgets/grid.h Normal file
View File

@ -0,0 +1,150 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef GUI_WIDGETS_GRID_H
#define GUI_WIDGETS_GRID_H
#include "gui/dialog.h"
#include "gui/widget.h"
#include "common/str.h"
#include "common/array.h"
#include "image/bmp.h"
#include "image/png.h"
namespace GUI {
const Graphics::ManagedSurface *scaleGfx(Graphics::ManagedSurface *gfx, int w, int h);
enum Platform {
kPlatformDOS,
kPlatformAmiga,
kPlatformApple2,
kPlatformUnknown = -1
};
struct GridItemInfo
{
Common::String engineid;
Common::String gameid;
Common::String language;
Common::String title;
Common::String platform;
Common::String thumbPath;
GridItemInfo(Common::String &eid, Common::String &gid, Common::String &t, Common::String &l, Common::String &p) :
gameid(gid), engineid(eid), title(t), language(l), platform(p) {
thumbPath = Common::String::format("%s-%s.png", engineid.c_str(), gameid.c_str());
}
};
class GridItemWidget;
/* GridWidget */
class GridWidget : public ContainerWidget {
private:
Common::Array<const Graphics::ManagedSurface *> _platformIcons;
// _gridItems should be reserved to hold few more than visible items
Common::Array<GridItemWidget *> _gridItems;
Common::Array<GridItemInfo> _allEntries;
Common::Array<GridItemInfo> _visibleEntries;
Common::HashMap<Common::String, const Graphics::ManagedSurface *> _loadedSurfaces;
Common::Array<Common::Array<GridItemWidget *>> _grid;
ScrollBarWidget *_scrollBar;
uint16 _scrollWindowHeight, _scrollWindowWidth, _scrollSpeed;
uint16 _innerHeight, _innerWidth;
uint16 _thumbnailHeight, _thumbnailWidth;
uint16 _gridItemHeight, _gridItemWidth;
int _scrollPos;
int _itemsPerRow;
int _firstVisibleItem;
int _itemsOnScreen;
bool _titlesVisible;
public:
GridWidget(GuiObject *boss, int x, int y, int w, int h);
GridWidget(GuiObject *boss, const Common::String &name);
const Graphics::ManagedSurface * filenameToSurface(Common::String &name);
const Graphics::ManagedSurface * platformToSurface(Platform platformCode);
bool calcVisibleEntries(void);
void setEntryList(Common::Array<GridItemInfo> *list);
void destroyItems();
void loadPlatformIcons();
void updateGrid(void);
void gridFromGameList();
int getLoadedNumber(void) {return _loadedSurfaces.size();}
void reloadThumbnails();
void handleMouseWheel(int x, int y, int direction) override;
void reflowLayout() override;
int selectedEntry;
};
enum {
kGridItemHPadding = 50,
kGridItemVPadding = 50,
kThumbnailWidth = 192,
kThumbnailHeight = 192
};
/* EntryContainerWidget */
class GridItemWidget : public ContainerWidget {
public:
GraphicsWidget *_thumb;
GraphicsWidget *_plat;
StaticTextWidget *_lang;
StaticTextWidget *_title;
GridWidget *_grid;
Common::Array<GridItemInfo> _attachedEntries;
GridItemInfo *_activeEntry;
bool isHighlighted;
void setActiveEntry(GridItemInfo &entry);
public:
GridItemWidget(GridWidget *boss, int x, int y, int w, int h);
GridItemWidget(GridWidget *boss, GraphicsWidget *th, GraphicsWidget *p, StaticTextWidget *l, StaticTextWidget *t);
void attachEntry(Common::String key, Common::String description, Common::ConfigManager::Domain *domain);
void attachEntry(GridItemInfo &entry);
void attachEntries(Common::Array<GridItemInfo> entry);
void setActiveEntry(int i) {setActiveEntry(_attachedEntries[i]);};
void update();
void updateThumb();
void drawWidget() override;
};
} // End of namespace GUI
#endif