[Scummvm-git-logs] scummvm master -> 34ecd753ad7939fdcab8e9227e245396e2c845ec
sev-
noreply at scummvm.org
Wed Mar 27 14:34:38 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
34ecd753ad GRAPHICS: MACGUI: Implement submenu scrolling
Commit: 34ecd753ad7939fdcab8e9227e245396e2c845ec
https://github.com/scummvm/scummvm/commit/34ecd753ad7939fdcab8e9227e245396e2c845ec
Author: Krish (ganatrakrish2882005 at gmail.com)
Date: 2024-03-27T15:34:34+01:00
Commit Message:
GRAPHICS: MACGUI: Implement submenu scrolling
Changed paths:
graphics/macgui/macmenu.cpp
graphics/macgui/macmenu.h
graphics/macgui/macpopupmenu.cpp
diff --git a/graphics/macgui/macmenu.cpp b/graphics/macgui/macmenu.cpp
index d51b723b60e..471b96022d3 100644
--- a/graphics/macgui/macmenu.cpp
+++ b/graphics/macgui/macmenu.cpp
@@ -25,6 +25,7 @@
#include "common/macresman.h"
#include "common/formats/winexe_pe.h"
#include "common/unicode-bidi.h"
+#include "common/timer.h"
#include "graphics/primitives.h"
#include "graphics/font.h"
@@ -34,6 +35,8 @@
#include "graphics/macgui/macwindow.h"
#include "graphics/macgui/macmenu.h"
+#define SCROLL_DELAY 100000
+
namespace Graphics {
enum {
@@ -121,6 +124,11 @@ MacMenu::MacMenu(int id, const Common::Rect &bounds, MacWindowManager *wm)
_unicodeccallback = NULL;
_cdata = NULL;
+ _scrollTimerActive = false;
+ _scrollDirection = 0;
+
+ _isModal = false;
+
_tempSurface.create(_screen.w, _font->getFontHeight(), PixelFormat::createFormatCLUT8());
}
@@ -937,8 +945,8 @@ void MacMenu::calcSubMenuBounds(MacMenuSubMenu *submenu, int x, int y) {
int x1 = x;
int y1 = y;
int x2 = x1 + maxWidth + _menuLeftDropdownPadding + _menuRightDropdownPadding - 4;
-
int y2 = y1 + submenu->items.size() * _menuDropdownItemHeight + 2;
+ y2 = MIN(y2, y1 + ((_screen.h - y1) / _menuDropdownItemHeight) * _menuDropdownItemHeight + 2);
submenu->bbox.left = x1;
submenu->bbox.top = y1;
@@ -1089,7 +1097,27 @@ void MacMenu::renderSubmenu(MacMenuSubMenu *menu, bool recursive) {
int x = _align == kTextAlignRight ? -_menuRightDropdownPadding: _menuLeftDropdownPadding;
x += r->left;
- for (uint i = 0; i < menu->items.size(); i++) {
+ int maxVis = menu->bbox.height() / _menuDropdownItemHeight;
+ int numVis = menu->items.size() - menu->visStart - menu->visEnd + ABS(menu->scroll);
+ numVis = MIN(numVis, maxVis);
+
+ int ovTop = menu->visStart + menu->scroll; // Number of items overflowing from top
+ int ovBot = menu->items.size() - ovTop - numVis; // Number of items overflowing from bottom
+
+ for (uint i = menu->visStart + menu->scroll; i < menu->items.size(); i++) {
+ if ((ovTop && i == menu->visStart + menu->scroll) ||
+ (ovBot && i == numVis - 1 + menu->scroll + menu->visStart)) {
+ int direction = (i == menu->visStart + menu->scroll) ? 1 : -1;
+
+ int arrowX = _align == kTextAlignRight ? menu->bbox.right - _menuRightDropdownPadding : menu->bbox.left + _menuLeftDropdownPadding;
+ int arrowY = direction == 1 ? menu->bbox.top + _menuDropdownItemHeight / 2 : menu->bbox.bottom - _menuDropdownItemHeight / 2;
+
+ drawScrollArrow(arrowX, arrowY, direction);
+
+ y += _menuDropdownItemHeight;
+ continue;
+ }
+
Common::String text(menu->items[i]->text);
Common::String acceleratorText(getAcceleratorString(menu->items[i], ""));
@@ -1257,8 +1285,32 @@ bool MacMenu::checkIntersects(Common::Rect &rect) {
return false;
}
+static void scrollCallback(void *data) {
+ MacMenu *menu = (MacMenu *)data;
+ MacMenuSubMenu *subMenu = menu->_menustack.back();
+
+ int maxVis = subMenu->bbox.height() / menu->getDropdownItemHeight();
+ int numVis = subMenu->items.size() - subMenu->visStart - subMenu->visEnd + ABS(subMenu->scroll);
+ numVis = MIN(numVis, maxVis);
+
+ int ovTop = subMenu->visStart + subMenu->scroll; // Number of items overflowing from top
+ int ovBot = subMenu->items.size() - ovTop - numVis; // Number of items overflowing from bottom
+
+ if (menu->getScrollDirection() == -1) {
+ if (ovTop) {
+ subMenu->scroll--;
+ menu->renderSubmenu(subMenu);
+ }
+ } else {
+ if (ovBot) {
+ subMenu->scroll++;
+ menu->renderSubmenu(subMenu);
+ }
+ }
+}
+
bool MacMenu::mouseClick(int x, int y) {
- if (_bbox.contains(x, y)) {
+ if (!_isModal &&_bbox.contains(x, y)) {
for (uint i = 0; i < _items.size(); i++) {
if (_items[i]->bbox.contains(x, y)) {
if ((uint)_activeItem == i)
@@ -1298,20 +1350,62 @@ bool MacMenu::mouseClick(int x, int y) {
if (_menustack.size() > 0 && _menustack.back()->bbox.contains(x, y)) {
MacMenuSubMenu *menu = _menustack.back();
int numSubItem = menu->ytoItem(y, _menuDropdownItemHeight);
+ int selectedOption = numSubItem;
+ numSubItem += menu->visStart + menu->scroll;
+ numSubItem = MIN((uint)numSubItem, menu->items.size() - 1);
if (numSubItem != _activeSubItem) {
if (_wm->_mode & kWMModalMenuMode) {
if (_activeSubItem == -1 || menu->items[_activeSubItem]->submenu != nullptr)
g_system->copyRectToScreen(_wm->_screenCopy->getPixels(), _wm->_screenCopy->pitch, 0, 0, _wm->_screenCopy->w, _wm->_screenCopy->h);
}
- _activeSubItem = numSubItem;
- menu->highlight = _activeSubItem;
+
+ int maxVis = menu->bbox.height() / _menuDropdownItemHeight;
+ int numItemsVisible = menu->items.size() - menu->visStart - menu->visEnd + ABS(menu->scroll);
+ numItemsVisible = MIN(numItemsVisible, maxVis);
+
+ int ovTop = menu->visStart + menu->scroll;
+ int ovBot = menu->items.size() - ovTop - numItemsVisible;
+
+ // If the user clicks on the "Scroll Up Arrow" or the "Scroll Down Arrow" then ignore the selection
+ if (!(ovTop && selectedOption == 0) && !(ovBot && numItemsVisible == maxVis && menu->ytoItem(y, _menuDropdownItemHeight) == numItemsVisible - 1)) {
+ _activeSubItem = numSubItem;
+ menu->highlight = _activeSubItem;
+ }
+
+ if (selectedOption == 0) {
+ if (ovTop) {
+ if (!_scrollTimerActive) {
+ _scrollDirection = -1;
+ _scrollTimerActive = true;
+ g_system->getTimerManager()->installTimerProc(&scrollCallback, SCROLL_DELAY, this, "Scroll Up Handler");
+ }
+ }
+ } else if (selectedOption == numItemsVisible - 1) {
+ if (ovBot && numItemsVisible == maxVis) {
+ if (!_scrollTimerActive) {
+ _scrollDirection = 1;
+ _scrollTimerActive = true;
+ g_system->getTimerManager()->installTimerProc(&scrollCallback, SCROLL_DELAY, this, "Scroll Down Handler");
+ }
+ }
+ } else {
+ if (_scrollTimerActive) {
+ _scrollTimerActive = false;
+ g_system->getTimerManager()->removeTimerProc(&scrollCallback);
+ }
+ }
_contentIsDirty = true;
_wm->setFullRefresh(true);
}
return true;
+ } else {
+ if (_scrollTimerActive) {
+ _scrollTimerActive = false;
+ g_system->getTimerManager()->removeTimerProc(&scrollCallback);
+ }
}
if (_activeSubItem != -1 && _menustack.back()->items[_activeSubItem]->submenu != nullptr) {
@@ -1381,6 +1475,13 @@ bool MacMenu::contains(int x, int y) {
return false;
}
+void MacMenu::drawScrollArrow(int arrowX, int arrowY, int direction) {
+ int arrowHeight = getMenuFont()->getFontHeight() / 2;
+
+ for (int j = 0; j <= arrowHeight / 2; j++)
+ _screen.hLine(arrowX - j, arrowY + j * direction, arrowX + j, _wm->_colorBlack);
+}
+
bool MacMenu::mouseMove(int x, int y) {
if (_active) {
if (mouseClick(x, y))
@@ -1413,6 +1514,12 @@ bool MacMenu::checkCallback(bool unicode) {
void MacMenu::closeMenu() {
setActive(false);
+
+ if (_scrollTimerActive) {
+ _scrollTimerActive = false;
+ g_system->getTimerManager()->removeTimerProc(&scrollCallback);
+ }
+
if (_wm->_mode & kWMModeAutohideMenu)
_isVisible = false;
diff --git a/graphics/macgui/macmenu.h b/graphics/macgui/macmenu.h
index be27d80b604..5f3cd0aa099 100644
--- a/graphics/macgui/macmenu.h
+++ b/graphics/macgui/macmenu.h
@@ -43,8 +43,11 @@ struct MacMenuSubMenu {
ItemArray items;
Common::Rect bbox;
int highlight;
+ int visStart; // Visible start
+ int visEnd; // Visible end
+ int scroll;
- MacMenuSubMenu() : highlight(-1) {}
+ MacMenuSubMenu() : highlight(-1), visStart(0), visEnd(0), scroll(0) {}
~MacMenuSubMenu();
@@ -168,6 +171,14 @@ public:
int getLastSelectedMenuItem() { return _lastActiveItem; };
int getLastSelectedSubmenuItem() { return _lastActiveSubItem; };
+ void renderSubmenu(MacMenuSubMenu *menu, bool recursive = true);
+
+ int getScrollDirection() { return _scrollDirection; }
+
+ int getDropdownItemHeight() { return _menuDropdownItemHeight; }
+
+ Common::Array<MacMenuSubMenu *> _menustack;
+
protected:
Common::Rect _bbox;
ManagedSurface _screen;
@@ -175,12 +186,12 @@ protected:
bool _isVisible;
bool _dimensionsDirty;
int _menuDropdownItemHeight;
- Common::Array<MacMenuSubMenu *> _menustack;
int _activeItem;
int _activeSubItem;
- void renderSubmenu(MacMenuSubMenu *menu, bool recursive = true);
+ bool _isModal;
+
void calcSubMenuBounds(MacMenuSubMenu *menu, int x, int y);
private:
@@ -207,6 +218,8 @@ private:
void drawSubMenuArrow(ManagedSurface *dst, int x, int y, int color);
bool contains(int x, int y);
+ void drawScrollArrow(int arrowX, int arrowY, int direction);
+
MacMenuItem *findMenuItem(const Common::String &menuId, const Common::String &itemId);
MacMenuItem *findMenuItem(int menuId, int itemId);
@@ -217,6 +230,9 @@ private:
int _lastActiveItem;
int _lastActiveSubItem;
+ bool _scrollTimerActive;
+ int _scrollDirection;
+
void (*_ccallback)(int action, Common::String &text, void *data);
void (*_unicodeccallback)(int action, Common::U32String &text, void *data);
void *_cdata;
diff --git a/graphics/macgui/macpopupmenu.cpp b/graphics/macgui/macpopupmenu.cpp
index bd042323963..ba3461c301f 100644
--- a/graphics/macgui/macpopupmenu.cpp
+++ b/graphics/macgui/macpopupmenu.cpp
@@ -90,6 +90,8 @@ void MacPopUp::closeMenu() {
_prevCheckedItem = activeSubItem;
}
+ _isModal = false;
+
// Close now
MacMenu::closeMenu();
}
@@ -105,10 +107,37 @@ uint32 MacPopUp::drawAndSelectMenu(int x, int y, int item) {
_contentIsDirty = true; // Set true to force refresh menu open changes
+ _isModal = true;
+
// Push our submenu to stack
_menustack.clear();
_menustack.push_back(_items[0]->submenu);
+ _items[0]->submenu->visStart = 0;
+ _items[0]->submenu->visEnd = 0;
+ _items[0]->submenu->scroll = 0;
+ _offsetY = 0;
+
+ if (_isSmart) {
+ int activeSubItem = getLastSelectedSubmenuItem();
+
+ if (activeSubItem != -1)
+ _offsetY = -activeSubItem * _menuDropdownItemHeight;
+ else if (_prevCheckedItem != -1)
+ _offsetY = -_prevCheckedItem * _menuDropdownItemHeight;
+
+ while (_offsetY + _mouseY < 0) {
+ _offsetY += _menuDropdownItemHeight;
+
+ _items[0]->submenu->visStart++;
+ }
+
+ int itemsLeft = _items[0]->submenu->items.size() - _items[0]->submenu->visStart;
+ int spaceLeft = _screen.h - MIN(_mouseY + _offsetY, _mouseY);
+ _items[0]->submenu->visEnd = MAX(0, itemsLeft - spaceLeft / _menuDropdownItemHeight);
+ }
+
+
// Highlight previous item if smart menu
if (_isSmart && getLastSelectedSubmenuItem() != -1) {
_activeItem = 0;
More information about the Scummvm-git-logs
mailing list