mirror of https://github.com/stella-emu/stella.git
First pass at fixing ContextMenu when list of items is larger
than the enclosing screen. Selecting images with the mouse is working, but the up and down 'buttons' are currently just drawn text/placeholders. Still TODO is get the keyboard actions (cursor up/down, etc) working. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1949 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
f096fa1eb7
commit
965787050a
|
@ -108,7 +108,7 @@ void AboutDialog::updateStrings(int page, int lines, string& title)
|
||||||
case 1:
|
case 1:
|
||||||
title = string("Stella ") + STELLA_VERSION;
|
title = string("Stella ") + STELLA_VERSION;
|
||||||
ADD_ATEXT("\\CA multi-platform Atari 2600 VCS emulator");
|
ADD_ATEXT("\\CA multi-platform Atari 2600 VCS emulator");
|
||||||
ADD_ATEXT(string("\\C\\c2") + instance().features());
|
ADD_ATEXT(string("\\C\\c2Features: ") + instance().features());
|
||||||
ADD_ATEXT(string("\\C\\c2") + instance().buildInfo());
|
ADD_ATEXT(string("\\C\\c2") + instance().buildInfo());
|
||||||
ADD_ALINE;
|
ADD_ALINE;
|
||||||
ADD_ATEXT("\\CCopyright (C) 1995-2010 The Stella Team");
|
ADD_ATEXT("\\CCopyright (C) 1995-2010 The Stella Team");
|
||||||
|
|
|
@ -33,7 +33,9 @@ ContextMenu::ContextMenu(GuiObject* boss, const GUI::Font& font,
|
||||||
_currentItem(-1),
|
_currentItem(-1),
|
||||||
_selectedItem(-1),
|
_selectedItem(-1),
|
||||||
_rowHeight(font.getLineHeight()),
|
_rowHeight(font.getLineHeight()),
|
||||||
_twoColumns(false),
|
_firstEntry(0),
|
||||||
|
_numEntries(0),
|
||||||
|
_showScroll(false),
|
||||||
_font(&font),
|
_font(&font),
|
||||||
_cmd(cmd),
|
_cmd(cmd),
|
||||||
_xorig(0),
|
_xorig(0),
|
||||||
|
@ -54,21 +56,6 @@ void ContextMenu::addItems(const StringMap& items)
|
||||||
_entries.clear();
|
_entries.clear();
|
||||||
_entries = items;
|
_entries = items;
|
||||||
|
|
||||||
// Create two columns of entries if there are more than 10 items
|
|
||||||
if(_entries.size() > 10)
|
|
||||||
{
|
|
||||||
_twoColumns = true;
|
|
||||||
_entriesPerColumn = _entries.size() / 2;
|
|
||||||
|
|
||||||
if(_entries.size() & 1)
|
|
||||||
_entriesPerColumn++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_twoColumns = false;
|
|
||||||
_entriesPerColumn = _entries.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize to largest string
|
// Resize to largest string
|
||||||
int maxwidth = 0;
|
int maxwidth = 0;
|
||||||
for(unsigned int i = 0; i < _entries.size(); ++i)
|
for(unsigned int i = 0; i < _entries.size(); ++i)
|
||||||
|
@ -79,8 +66,8 @@ void ContextMenu::addItems(const StringMap& items)
|
||||||
}
|
}
|
||||||
|
|
||||||
_x = _y = 0;
|
_x = _y = 0;
|
||||||
_w = maxwidth * (_twoColumns ? 2 : 1) + 10;
|
_w = maxwidth + 10;
|
||||||
_h = _entriesPerColumn * _rowHeight + 4;
|
_h = 1; // recalculate this in ::recalc()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -88,6 +75,8 @@ void ContextMenu::show(uInt32 x, uInt32 y, int item)
|
||||||
{
|
{
|
||||||
_xorig = x;
|
_xorig = x;
|
||||||
_yorig = y;
|
_yorig = y;
|
||||||
|
|
||||||
|
recalc(instance().frameBuffer().imageRect());
|
||||||
parent().addDialog(this);
|
parent().addDialog(this);
|
||||||
setSelected(item);
|
setSelected(item);
|
||||||
}
|
}
|
||||||
|
@ -98,6 +87,7 @@ void ContextMenu::center()
|
||||||
// Make sure the menu is exactly where it should be, in case the image
|
// Make sure the menu is exactly where it should be, in case the image
|
||||||
// offset has changed
|
// offset has changed
|
||||||
const GUI::Rect& image = instance().frameBuffer().imageRect();
|
const GUI::Rect& image = instance().frameBuffer().imageRect();
|
||||||
|
recalc(image);
|
||||||
uInt32 x = image.x() + _xorig;
|
uInt32 x = image.x() + _xorig;
|
||||||
uInt32 y = image.y() + _yorig;
|
uInt32 y = image.y() + _yorig;
|
||||||
uInt32 tx = image.x() + image.width();
|
uInt32 tx = image.x() + image.width();
|
||||||
|
@ -108,6 +98,27 @@ void ContextMenu::center()
|
||||||
surface().setPos(x, y);
|
surface().setPos(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void ContextMenu::recalc(const GUI::Rect& image)
|
||||||
|
{
|
||||||
|
// Now is the time to adjust the height
|
||||||
|
// If it's higher than the screen, we need to scroll through
|
||||||
|
int maxentries = (image.height() - 4) / _rowHeight;
|
||||||
|
if((int)_entries.size() > maxentries)
|
||||||
|
{
|
||||||
|
// We show two less than the max, so we have room for two scroll buttons
|
||||||
|
_numEntries = maxentries - 2;
|
||||||
|
_h = maxentries * _rowHeight + 4;
|
||||||
|
_showScroll = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_numEntries = _entries.size();
|
||||||
|
_h = _entries.size() * _rowHeight + 4;
|
||||||
|
_showScroll = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ContextMenu::setSelected(int item)
|
void ContextMenu::setSelected(int item)
|
||||||
{
|
{
|
||||||
|
@ -184,15 +195,6 @@ void ContextMenu::handleMouseDown(int x, int y, int button, int clickCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void ContextMenu::handleMouseWheel(int x, int y, int direction)
|
|
||||||
{
|
|
||||||
if(direction < 0)
|
|
||||||
moveUp();
|
|
||||||
else if(direction > 0)
|
|
||||||
moveDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ContextMenu::handleMouseMoved(int x, int y, int button)
|
void ContextMenu::handleMouseMoved(int x, int y, int button)
|
||||||
{
|
{
|
||||||
|
@ -265,21 +267,8 @@ void ContextMenu::handleEvent(Event::Type e)
|
||||||
int ContextMenu::findItem(int x, int y) const
|
int ContextMenu::findItem(int x, int y) const
|
||||||
{
|
{
|
||||||
if(x >= 0 && x < _w && y >= 0 && y < _h)
|
if(x >= 0 && x < _w && y >= 0 && y < _h)
|
||||||
{
|
|
||||||
if(_twoColumns)
|
|
||||||
{
|
|
||||||
unsigned int entry = (y - 4) / _rowHeight;
|
|
||||||
if(x > _w / 2)
|
|
||||||
{
|
|
||||||
entry += _entriesPerColumn;
|
|
||||||
|
|
||||||
if(entry >= _entries.size())
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
return (y - 4) / _rowHeight;
|
return (y - 4) / _rowHeight;
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,6 +286,19 @@ void ContextMenu::drawCurrentSelection(int item)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ContextMenu::sendSelection()
|
void ContextMenu::sendSelection()
|
||||||
{
|
{
|
||||||
|
// Select the correct item when scrolling; we have to take into account
|
||||||
|
// that the viewable items are no longer 1-to-1 with the entries
|
||||||
|
int item = _currentItem;
|
||||||
|
if(_showScroll)
|
||||||
|
{
|
||||||
|
if(item == 0) // scroll up
|
||||||
|
return scrollUp();
|
||||||
|
else if(item == _numEntries+1) // scroll down
|
||||||
|
return scrollDown();
|
||||||
|
else
|
||||||
|
item = item + _firstEntry - 1;
|
||||||
|
}
|
||||||
|
|
||||||
// We remove the dialog when the user has selected an item
|
// We remove the dialog when the user has selected an item
|
||||||
// Make sure the dialog is removed before sending any commands,
|
// Make sure the dialog is removed before sending any commands,
|
||||||
// since one consequence of sending a command may be to add another
|
// since one consequence of sending a command may be to add another
|
||||||
|
@ -304,7 +306,7 @@ void ContextMenu::sendSelection()
|
||||||
close();
|
close();
|
||||||
|
|
||||||
// Send any command associated with the selection
|
// Send any command associated with the selection
|
||||||
_selectedItem = _currentItem;
|
_selectedItem = item;
|
||||||
sendCommand(_cmd ? _cmd : kCMenuItemSelectedCmd, _selectedItem, -1);
|
sendCommand(_cmd ? _cmd : kCMenuItemSelectedCmd, _selectedItem, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +314,14 @@ void ContextMenu::sendSelection()
|
||||||
void ContextMenu::moveUp()
|
void ContextMenu::moveUp()
|
||||||
{
|
{
|
||||||
int item = _currentItem;
|
int item = _currentItem;
|
||||||
|
if(_showScroll)
|
||||||
|
{
|
||||||
|
if(item > 0) // scroll up
|
||||||
|
{
|
||||||
|
if(_firstEntry > item)
|
||||||
|
_firstEntry--;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(item > 0)
|
if(item > 0)
|
||||||
drawCurrentSelection(--item);
|
drawCurrentSelection(--item);
|
||||||
}
|
}
|
||||||
|
@ -320,10 +330,39 @@ void ContextMenu::moveUp()
|
||||||
void ContextMenu::moveDown()
|
void ContextMenu::moveDown()
|
||||||
{
|
{
|
||||||
int item = _currentItem;
|
int item = _currentItem;
|
||||||
|
if(_showScroll)
|
||||||
|
{
|
||||||
|
if(item == _numEntries+1) // scroll down
|
||||||
|
{
|
||||||
|
if(_firstEntry + _numEntries < (int)_entries.size())
|
||||||
|
_firstEntry++;
|
||||||
|
}
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
if(item < (int)_entries.size() - 1)
|
if(item < (int)_entries.size() - 1)
|
||||||
drawCurrentSelection(++item);
|
drawCurrentSelection(++item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void ContextMenu::scrollUp()
|
||||||
|
{
|
||||||
|
if(_firstEntry > _currentItem)
|
||||||
|
{
|
||||||
|
_firstEntry--;
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void ContextMenu::scrollDown()
|
||||||
|
{
|
||||||
|
if(_firstEntry + _numEntries < (int)_entries.size())
|
||||||
|
{
|
||||||
|
_firstEntry++;
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ContextMenu::drawDialog()
|
void ContextMenu::drawDialog()
|
||||||
{
|
{
|
||||||
|
@ -338,42 +377,34 @@ void ContextMenu::drawDialog()
|
||||||
s.fillRect(_x+1, _y+1, _w-2, _h-2, kWidColor);
|
s.fillRect(_x+1, _y+1, _w-2, _h-2, kWidColor);
|
||||||
s.box(_x, _y, _w, _h, kColor, kShadowColor);
|
s.box(_x, _y, _w, _h, kColor, kShadowColor);
|
||||||
|
|
||||||
// If necessary, draw dividing line
|
// Draw the entries, taking scroll buttons into account
|
||||||
if(_twoColumns)
|
int x = _x + 2, y = _y + 2, w = _w - 4;
|
||||||
s.vLine(_x + _w / 2, _y, _y + _h - 2, kColor);
|
cerr << "_firstEntry = " << _firstEntry << ", _numEntries = " << _numEntries << endl;
|
||||||
|
|
||||||
// Draw the entries
|
// Show top scroll area
|
||||||
int x, y, w;
|
int offset = _firstEntry;
|
||||||
int count = _entries.size();
|
if(_showScroll)
|
||||||
for(int i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
bool hilite = i == _currentItem;
|
s.drawString(_font, " ^^^^^", x + 1, y + 2, w, kTextColor);
|
||||||
if(_twoColumns)
|
y += _rowHeight;
|
||||||
{
|
offset--;
|
||||||
int n = _entries.size() / 2;
|
|
||||||
if(_entries.size() & 1) n++;
|
|
||||||
if(i >= n)
|
|
||||||
{
|
|
||||||
x = _x + 1 + _w / 2;
|
|
||||||
y = _y + 2 + _rowHeight * (i - n);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = _x + 2;
|
|
||||||
y = _y + 2 + _rowHeight * i;
|
|
||||||
}
|
|
||||||
w = _w / 2 - 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = _x + 2;
|
|
||||||
y = _y + 2 + i * _rowHeight;
|
|
||||||
w = _w - 4;
|
|
||||||
}
|
|
||||||
if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi);
|
|
||||||
s.drawString(_font, _entries[i].first, x + 1, y + 2, w - 2,
|
|
||||||
hilite ? kWidColor : kTextColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(int i = _firstEntry; i < _firstEntry + _numEntries; ++i)
|
||||||
|
{
|
||||||
|
bool hilite = (i-offset) == _currentItem;
|
||||||
|
if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi);
|
||||||
|
s.drawString(_font, _entries[i].first, x + 1, y + 2, w,
|
||||||
|
hilite ? kWidColor : kTextColor);
|
||||||
|
y += _rowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show bottom scroll area
|
||||||
|
if(_showScroll)
|
||||||
|
{
|
||||||
|
s.drawString(_font, " vvvvv", x + 1, y + 2, w, kTextColor);
|
||||||
|
}
|
||||||
|
|
||||||
s.addDirtyRect(_x, _y, _w, _h);
|
s.addDirtyRect(_x, _y, _w, _h);
|
||||||
_dirty = false;
|
_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ class ContextMenu : public Dialog, public CommandSender
|
||||||
public:
|
public:
|
||||||
ContextMenu(GuiObject* boss, const GUI::Font& font,
|
ContextMenu(GuiObject* boss, const GUI::Font& font,
|
||||||
const StringMap& items, int cmd = 0);
|
const StringMap& items, int cmd = 0);
|
||||||
virtual ~ContextMenu();
|
virtual ~ContextMenu();
|
||||||
|
|
||||||
/** Add the given items to the widget. */
|
/** Add the given items to the widget. */
|
||||||
void addItems(const StringMap& items);
|
void addItems(const StringMap& items);
|
||||||
|
@ -74,7 +74,6 @@ class ContextMenu : public Dialog, public CommandSender
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void handleMouseDown(int x, int y, int button, int clickCount);
|
void handleMouseDown(int x, int y, int button, int clickCount);
|
||||||
void handleMouseWheel(int x, int y, int direction);
|
|
||||||
void handleMouseMoved(int x, int y, int button);
|
void handleMouseMoved(int x, int y, int button);
|
||||||
void handleKeyDown(int ascii, int keycode, int modifiers); // Scroll through entries with arrow keys etc
|
void handleKeyDown(int ascii, int keycode, int modifiers); // Scroll through entries with arrow keys etc
|
||||||
void handleJoyDown(int stick, int button);
|
void handleJoyDown(int stick, int button);
|
||||||
|
@ -85,6 +84,7 @@ class ContextMenu : public Dialog, public CommandSender
|
||||||
void drawDialog();
|
void drawDialog();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void recalc(const GUI::Rect& image);
|
||||||
void drawMenuEntry(int entry, bool hilite);
|
void drawMenuEntry(int entry, bool hilite);
|
||||||
|
|
||||||
int findItem(int x, int y) const;
|
int findItem(int x, int y) const;
|
||||||
|
@ -92,6 +92,8 @@ class ContextMenu : public Dialog, public CommandSender
|
||||||
|
|
||||||
void moveUp();
|
void moveUp();
|
||||||
void moveDown();
|
void moveDown();
|
||||||
|
void scrollUp();
|
||||||
|
void scrollDown();
|
||||||
|
|
||||||
void sendSelection();
|
void sendSelection();
|
||||||
|
|
||||||
|
@ -101,9 +103,8 @@ class ContextMenu : public Dialog, public CommandSender
|
||||||
int _currentItem;
|
int _currentItem;
|
||||||
int _selectedItem;
|
int _selectedItem;
|
||||||
int _rowHeight;
|
int _rowHeight;
|
||||||
|
int _firstEntry, _numEntries;
|
||||||
bool _twoColumns;
|
bool _showScroll;
|
||||||
int _entriesPerColumn;
|
|
||||||
|
|
||||||
const GUI::Font* _font;
|
const GUI::Font* _font;
|
||||||
int _cmd;
|
int _cmd;
|
||||||
|
|
|
@ -107,6 +107,9 @@ void DialogContainer::draw(bool full)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DialogContainer::addDialog(Dialog* d)
|
void DialogContainer::addDialog(Dialog* d)
|
||||||
{
|
{
|
||||||
|
const GUI::Rect& image = myOSystem->frameBuffer().imageRect();
|
||||||
|
assert(d->getWidth() <= image.width() && d->getHeight() <= image.height());
|
||||||
|
|
||||||
myDialogStack.push(d);
|
myDialogStack.push(d);
|
||||||
d->open();
|
d->open();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue