Added more complete support for in-GUI navigation with a joystick

for those dialogs that don't emulate the mouse (currently the Launcher
and Command dialogs).  Moving a joystick axis in such dialogs now repeats
the event until the axis is released (similar to key repeat).  Also,
the number of events is based on how long the axis is held.  So the
longer the axis is pressed, the faster events will be generated.

The LauncherDialog now handles its own joystick axis events, which
are described as follows:
 - Axis up/down (on any stick) move up and down through the game list.
 - Axis left/right moves between the 4 buttons on the bottom (play,
   options, reload, quit).
 - The buttons are now highlighted to indicate that they're focusable.
   So the cursor keys can also be used to move between them.

Still TODO is deal with analog joystick axis events.  The analog nature
of these types of joysticks should really be ignored by the GUI.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@935 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-01-04 01:24:17 +00:00
parent 2f16788aaa
commit adc6354943
14 changed files with 258 additions and 91 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventHandler.cxx,v 1.138 2005-12-29 21:16:26 stephena Exp $
// $Id: EventHandler.cxx,v 1.139 2006-01-04 01:24:17 stephena Exp $
//============================================================================
#include <sstream>
@ -175,6 +175,8 @@ void EventHandler::reset(State state)
setPaddleSpeed(1, myOSystem->settings().getInt("p2speed"));
setPaddleSpeed(2, myOSystem->settings().getInt("p3speed"));
setPaddleSpeed(3, myOSystem->settings().getInt("p4speed"));
myEventStreamer->reset();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventStreamer.cxx,v 1.3 2005-12-29 21:16:28 stephena Exp $
// $Id: EventStreamer.cxx,v 1.4 2006-01-04 01:24:17 stephena Exp $
//============================================================================
#include "bspf.hxx"
@ -44,6 +44,16 @@ EventStreamer::~EventStreamer()
myStreamWriter.close();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventStreamer::reset()
{
cerr << "EventStreamer::reset()\n";
myEventWriteFlag = false;
myEventReadFlag = false;
myFrameCounter = -1;
myEventPos = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventStreamer::startRecording()
{
@ -57,10 +67,8 @@ bool EventStreamer::startRecording()
return false;
myEventHistory.clear();
myEventWriteFlag = true;
myEventReadFlag = false;
return myEventWriteFlag;
reset();
return myEventWriteFlag = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -97,6 +105,7 @@ bool EventStreamer::stopRecording()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventStreamer::loadRecording()
{
cerr << "EventStreamer::loadRecording()\n";
string eventfile = /*myOSystem->baseDir() + BSPF_PATH_SEPARATOR +*/ "test.inp";
if(!myStreamReader.open(eventfile))
return false;
@ -128,10 +137,8 @@ bool EventStreamer::loadRecording()
return false;
}
myEventWriteFlag = false;
reset();
myEventReadFlag = myEventHistory.size() > 0;
myFrameCounter = -1;
myEventPos = 0;
return true;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventStreamer.hxx,v 1.2 2005-12-29 01:25:07 stephena Exp $
// $Id: EventStreamer.hxx,v 1.3 2006-01-04 01:24:17 stephena Exp $
//============================================================================
#ifndef EVENTSTREAMER_HXX
@ -48,7 +48,7 @@ class OSystem;
the correct order at the correct time.
@author Stephen Anthony
@version $Id: EventStreamer.hxx,v 1.2 2005-12-29 01:25:07 stephena Exp $
@version $Id: EventStreamer.hxx,v 1.3 2006-01-04 01:24:17 stephena Exp $
*/
class EventStreamer
{
@ -99,6 +99,11 @@ class EventStreamer
*/
void nextFrame();
/**
Reset to base state (not saving or loading an eventstream)
*/
void reset();
private:
private:

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CommandDialog.cxx,v 1.5 2005-12-19 02:19:49 stephena Exp $
// $Id: CommandDialog.cxx,v 1.6 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -26,35 +26,6 @@
#include "CommandDialog.hxx"
#include "EventHandler.hxx"
enum {
kSelectCmd = 'Csel',
kResetCmd = 'Cres',
kColorCmd = 'Ccol',
kBWCmd = 'Cbwt',
kLeftDiffACmd = 'Clda',
kLeftDiffBCmd = 'Cldb',
kRightDiffACmd = 'Crda',
kRightDiffBCmd = 'Crdb',
kSaveStateCmd = 'Csst',
kStateSlotCmd = 'Ccst',
kLoadStateCmd = 'Clst',
kSnapshotCmd = 'Csnp',
kFormatCmd = 'Cfmt',
kPaletteCmd = 'Cpal',
kReloadRomCmd = 'Crom',
kExitCmd = 'Clex'
};
enum {
kUpArrow = 256+17,
kDownArrow = 256+18,
kLeftArrow = 256+20,
kRightArrow = 256+19,
kNumRows = 4,
kNumCols = 4
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandDialog::CommandDialog(OSystem* osystem, DialogContainer* parent)
: Dialog(osystem, parent, 0, 0, 16, 16),
@ -180,7 +151,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
// Only detect the cursor keys, otherwise pass to base class
switch(ascii)
{
case kUpArrow:
case kCursorUp:
if (row > 0)
--row;
else if(col > 0)
@ -190,7 +161,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
}
break;
case kDownArrow:
case kCursorDown:
if (row < kNumRows - 1)
++row;
else if(col < kNumCols - 1)
@ -200,7 +171,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
}
break;
case kLeftArrow:
case kCursorLeft:
if (col > 0)
--col;
else if(row > 0)
@ -210,7 +181,7 @@ void CommandDialog::handleKeyDown(int ascii, int keycode, int modifiers)
}
break;
case kRightArrow:
case kCursorRight:
if (col < kNumCols - 1)
++col;
else if(row < kNumRows - 1)
@ -245,16 +216,16 @@ void CommandDialog::handleJoyAxis(int stick, int axis, int value)
if(axis % 2 == 0) // x-direction
{
if(value < 0)
key = kLeftArrow;
key = kCursorLeft;
else if(value > 0)
key = kRightArrow;
key = kCursorRight;
}
else // y-direction
{
if(value < 0)
key = kUpArrow;
key = kCursorUp;
else if(value > 0)
key = kDownArrow;
key = kCursorDown;
}
if(key != -1)

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CommandDialog.hxx,v 1.3 2005-12-24 22:09:36 stephena Exp $
// $Id: CommandDialog.hxx,v 1.4 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -44,6 +44,30 @@ class CommandDialog : public Dialog
private:
int mySelectedItem;
enum {
kSelectCmd = 'Csel',
kResetCmd = 'Cres',
kColorCmd = 'Ccol',
kBWCmd = 'Cbwt',
kLeftDiffACmd = 'Clda',
kLeftDiffBCmd = 'Cldb',
kRightDiffACmd = 'Crda',
kRightDiffBCmd = 'Crdb',
kSaveStateCmd = 'Csst',
kStateSlotCmd = 'Ccst',
kLoadStateCmd = 'Clst',
kSnapshotCmd = 'Csnp',
kFormatCmd = 'Cfmt',
kPaletteCmd = 'Cpal',
kReloadRomCmd = 'Crom',
kExitCmd = 'Clex'
};
enum {
kNumRows = 4,
kNumCols = 4
};
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DialogContainer.cxx,v 1.22 2005-12-24 22:50:53 stephena Exp $
// $Id: DialogContainer.cxx,v 1.23 2006-01-04 01:24:17 stephena Exp $
//============================================================================
#include "OSystem.hxx"
@ -72,6 +72,31 @@ void DialogContainer::updateTime(uInt32 time)
myClickRepeatTime = myTime + kClickRepeatSustainDelay;
}
if(myCurrentAxisDown.stick != -1 && myAxisRepeatTime < myTime)
{
// The longer an axis event is enabled, the faster it should change
// We do this by decreasing the amount of time between consecutive axis events
// After a certain threshold, send 10 events at a time (this is necessary
// since at some point, we'd like to process more eventss than the
// current framerate allows)
myCurrentAxisDown.count++;
int interval = myCurrentAxisDown.count / 40 + 1;
myAxisRepeatTime = myTime + kAxisRepeatSustainDelay / interval;
if(interval > 3)
{
for(int i = 0; i < 10; ++i)
activeDialog->handleJoyAxis(myCurrentAxisDown.stick, myCurrentAxisDown.axis,
myCurrentAxisDown.value);
myAxisRepeatTime = myTime + kAxisRepeatSustainDelay / 3;
}
else
{
activeDialog->handleJoyAxis(myCurrentAxisDown.stick, myCurrentAxisDown.axis,
myCurrentAxisDown.value);
myAxisRepeatTime = myTime + kAxisRepeatSustainDelay / interval;
}
}
// Update joy to mouse events
handleJoyMouse(time);
}
@ -270,17 +295,33 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
// Send the event to the dialog box on the top of the stack
Dialog* activeDialog = myDialogStack.top();
if(value > JOY_DEADZONE)
value -= JOY_DEADZONE;
else if(value < -JOY_DEADZONE )
value += JOY_DEADZONE;
else
value = 0;
if(activeDialog->wantsEvents())
{
// Only stop firing events if it's the current key
if(myCurrentAxisDown.stick == stick && value == 0)
{
myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
myCurrentAxisDown.count = 0;
}
else
{
// Now account for repeated axis events (press and hold)
myCurrentAxisDown.stick = stick;
myCurrentAxisDown.axis = axis;
myCurrentAxisDown.value = value;
myAxisRepeatTime = myTime + kAxisRepeatInitialDelay;
}
activeDialog->handleJoyAxis(stick, axis, value);
}
else
{
if(value > JOY_DEADZONE)
value -= JOY_DEADZONE;
else if(value < -JOY_DEADZONE )
value += JOY_DEADZONE;
else
value = 0;
if(axis % 2 == 0) // x-direction
{
if(value != 0)
@ -309,6 +350,8 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
ourJoyMouse.y_down_count = 0;
}
}
myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
myCurrentAxisDown.count = 0;
}
}
@ -413,6 +456,9 @@ void DialogContainer::reset()
myLastClick.time = 0;
myLastClick.count = 0;
myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
myCurrentAxisDown.count = 0;
int oldX = ourJoyMouse.x, oldY = ourJoyMouse.y;
if(ourJoyMouse.x > ourJoyMouse.x_max)
ourJoyMouse.x = ourJoyMouse.x_max;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DialogContainer.hxx,v 1.12 2005-12-24 22:50:53 stephena Exp $
// $Id: DialogContainer.hxx,v 1.13 2006-01-04 01:24:17 stephena Exp $
//============================================================================
#ifndef DIALOG_CONTAINER_HXX
@ -37,7 +37,7 @@ typedef FixedStack<Dialog *> DialogStack;
a stack, and handles their events.
@author Stephen Anthony
@version $Id: DialogContainer.hxx,v 1.12 2005-12-24 22:50:53 stephena Exp $
@version $Id: DialogContainer.hxx,v 1.13 2006-01-04 01:24:17 stephena Exp $
*/
class DialogContainer
{
@ -154,11 +154,13 @@ class DialogContainer
DialogStack myDialogStack;
enum {
kDoubleClickDelay = 500,
kKeyRepeatInitialDelay = 400,
kKeyRepeatSustainDelay = 50,
kDoubleClickDelay = 500,
kKeyRepeatInitialDelay = 400,
kKeyRepeatSustainDelay = 50,
kClickRepeatInitialDelay = kKeyRepeatInitialDelay,
kClickRepeatSustainDelay = kKeyRepeatSustainDelay
kClickRepeatSustainDelay = kKeyRepeatSustainDelay,
kAxisRepeatInitialDelay = kKeyRepeatInitialDelay,
kAxisRepeatSustainDelay = kKeyRepeatSustainDelay
};
// Indicates the most current time (in milliseconds) as set by updateTime()
@ -183,6 +185,15 @@ class DialogContainer
} myCurrentMouseDown;
uInt32 myClickRepeatTime;
// For continuous events (joyaxisDown)
struct {
int stick;
int axis;
int value;
int count;
} myCurrentAxisDown;
uInt32 myAxisRepeatTime;
// Position and time of last mouse click (used to detect double clicks)
struct {
int x, y; // Position of mouse when the click occured

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: GuiObject.hxx,v 1.16 2005-12-09 01:16:13 stephena Exp $
// $Id: GuiObject.hxx,v 1.17 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -32,11 +32,22 @@ class Widget;
typedef Common::Array<Widget*> WidgetArray;
enum {
kCursorUp = 256+17,
kCursorDown = 256+18,
kCursorRight = 256+19,
kCursorLeft = 256+20,
kCursorHome = 256+22,
kCursorEnd = 256+23,
kCursorPgUp = 256+24,
kCursorPgDn = 256+25
};
/**
This is the base class for all GUI objects/widgets.
@author Stephen Anthony
@version $Id: GuiObject.hxx,v 1.16 2005-12-09 01:16:13 stephena Exp $
@version $Id: GuiObject.hxx,v 1.17 2006-01-04 01:24:17 stephena Exp $
*/
class GuiObject : public CommandReceiver
{

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: LauncherDialog.cxx,v 1.34 2005-12-18 18:37:03 stephena Exp $
// $Id: LauncherDialog.cxx,v 1.35 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -53,10 +53,12 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
myQuitButton(NULL),
myList(NULL),
myGameList(NULL),
myProgressBar(NULL)
myProgressBar(NULL),
mySelectedItem(0)
{
const GUI::Font& font = instance()->font();
const int fontHeight = font.getFontHeight();
WidgetArray wid;
// Show game name
new StaticTextWidget(this, 10, 8, 200, fontHeight,
@ -74,31 +76,49 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
#ifndef MAC_OSX
myStartButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Play", kStartCmd, 'S');
myStartButton->setEditable(true);
wid.push_back(myStartButton);
xpos += space + width;
myOptionsButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Options", kOptionsCmd, 'O');
myOptionsButton->setEditable(true);
wid.push_back(myOptionsButton);
xpos += space + width;
myReloadButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Reload", kReloadCmd, 'R');
myReloadButton->setEditable(true);
wid.push_back(myReloadButton);
xpos += space + width;
myQuitButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Quit", kQuitCmd, 'Q');
myQuitButton->setEditable(true);
wid.push_back(myQuitButton);
xpos += space + width;
#else
myQuitButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Quit", kQuitCmd, 'Q');
myQuitButton->setEditable(true);
wid.push_back(myQuitButton);
xpos += space + width;
myOptionsButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Options", kOptionsCmd, 'O');
myOptionsButton->setEditable(true);
wid.push_back(myOptionsButton);
xpos += space + width;
myReloadButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Reload", kReloadCmd, 'R');
myReloadButton->setEditable(true);
wid.push_back(myReloadButton);
xpos += space + width;
myStartButton = new ButtonWidget(this, xpos, _h - 24, width, 16, "Start", kStartCmd, 'Q');
myStartButton->setEditable(true);
wid.push_back(myStartButton);
xpos += space + width;
#endif
// Add list with game titles
// The list isn't added to focus objects, but is instead made 'sticky'
// This means it will act as if it were focused (wrt how it's drawn), but
// won't actually be able to lose focus
myList = new StringListWidget(this, instance()->font(),
10, 24, _w - 20, _h - 24 - 26 - 10 - 10);
myList->setNumberingMode(kListNumberingOff);
myList->setEditable(false);
myList->setFlags(WIDGET_NODRAW_FOCUS);
addFocusWidget(myList);
myList->setFlags(WIDGET_STICKY_FOCUS);
// Add note textwidget to show any notes for the currently selected ROM
new StaticTextWidget(this, 20, _h - 43, 30, fontHeight, "Note:", kTextAlignLeft);
@ -113,6 +133,8 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
// Create a game list, which contains all the information about a ROM that
// the launcher needs
myGameList = new GameList();
addToFocusList(wid);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -336,6 +358,62 @@ string LauncherDialog::MD5FromFile(const string& path)
return md5;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::handleKeyDown(int ascii, int keycode, int modifiers)
{
// Only detect the cursor keys, otherwise pass to base class
switch(ascii)
{
case kCursorLeft:
mySelectedItem--;
if(mySelectedItem < 0) mySelectedItem = 3;
Dialog::setFocus(getFocusList()[mySelectedItem]);
break;
case kCursorRight:
mySelectedItem++;
if(mySelectedItem > 3) mySelectedItem = 0;
Dialog::setFocus(getFocusList()[mySelectedItem]);
break;
case ' ': // Used to activate currently focused button
Dialog::handleKeyDown(ascii, keycode, modifiers);
break;
default:
if(!myList->handleKeyDown(ascii, keycode, modifiers))
Dialog::handleKeyDown(ascii, keycode, modifiers);
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::handleJoyAxis(int stick, int axis, int value)
{
// We make the (hopefully) valid assumption that all joysticks
// treat axis the same way. Eventually, we may need to remap
// these actions of this assumption is invalid.
// TODO - make this work better with analog axes ...
int key = -1;
if(axis % 2 == 0) // x-direction
{
if(value < 0)
key = kCursorLeft;
else if(value > 0)
key = kCursorRight;
}
else // y-direction
{
if(value < 0)
key = kCursorUp;
else if(value > 0)
key = kCursorDown;
}
if(key != -1)
handleKeyDown(key, 0, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
int data, int id)

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: LauncherDialog.hxx,v 1.13 2005-08-22 18:17:10 stephena Exp $
// $Id: LauncherDialog.hxx,v 1.14 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -36,10 +36,6 @@ class OSystem;
#include "bspf.hxx"
enum {
kStartCmd = 'STRT',
kOptionsCmd = 'OPTI',
kReloadCmd = 'RELO',
kQuitCmd = 'QUIT',
kChooseRomDirCmd = 'roms', // rom select
kChooseSnapDirCmd = 'snps', // snap select
kRomDirChosenCmd = 'romc', // rom chosen
@ -53,12 +49,16 @@ class LauncherDialog : public Dialog
int x, int y, int w, int h);
~LauncherDialog();
protected:
virtual void handleKeyDown(int ascii, int keycode, int modifiers);
virtual void handleJoyAxis(int stick, int axis, int value);
virtual void handleCommand(CommandSender* sender, int cmd, int data, int id);
protected:
void updateListing(bool fullReload = false);
void loadConfig();
virtual bool wantsEvents() { return true; }
protected:
ButtonWidget* myStartButton;
ButtonWidget* myOptionsButton;
@ -79,6 +79,16 @@ class LauncherDialog : public Dialog
void loadListFromCache();
void createListCache();
string MD5FromFile(const string& path);
private:
int mySelectedItem;
enum {
kStartCmd = 'STRT',
kOptionsCmd = 'OPTI',
kReloadCmd = 'RELO',
kQuitCmd = 'QUIT'
};
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: ListWidget.cxx,v 1.37 2005-12-21 19:31:18 stephena Exp $
// $Id: ListWidget.cxx,v 1.38 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -287,33 +287,33 @@ bool ListWidget::handleKeyDown(int ascii, int keycode, int modifiers)
}
break;
case 256+17: // up arrow
case kCursorUp:
if (_selectedItem > 0)
_selectedItem--;
break;
case 256+18: // down arrow
case kCursorDown:
if (_selectedItem < (int)_list.size() - 1)
_selectedItem++;
break;
case 256+24: // pageup
case kCursorPgUp:
_selectedItem -= _rows - 1;
if (_selectedItem < 0)
_selectedItem = 0;
break;
case 256+25: // pagedown
case kCursorPgDn:
_selectedItem += _rows - 1;
if (_selectedItem >= (int)_list.size() )
_selectedItem = _list.size() - 1;
break;
case 256+22: // home
case kCursorHome:
_selectedItem = 0;
break;
case 256+23: // end
case kCursorEnd:
_selectedItem = _list.size() - 1;
break;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: ListWidget.hxx,v 1.14 2005-09-30 18:17:29 stephena Exp $
// $Id: ListWidget.hxx,v 1.15 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -70,7 +70,7 @@ class ListWidget : public EditableWidget
virtual void handleCommand(CommandSender* sender, int cmd, int data, int id);
virtual GUI::Rect getRect() const;
virtual bool wantsFocus() { return true; }
virtual bool wantsFocus() { return !isSticky(); }
void startEditMode();
void endEditMode();

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: StringListWidget.cxx,v 1.2 2005-08-23 18:32:51 stephena Exp $
// $Id: StringListWidget.cxx,v 1.3 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -67,7 +67,7 @@ void StringListWidget::drawWidget(bool hilite)
// Draw the selected item inverted, on a highlighted background.
if (_selectedItem == pos)
{
if (_hasFocus && !_editMode)
if ((_hasFocus && !_editMode) || isSticky())
fb.fillRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, kTextColorHi);
else
fb.frameRect(_x + 1, _y + 1 + kLineHeight * i, _w - 1, kLineHeight, kTextColorHi);

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Widget.hxx,v 1.43 2005-12-24 22:09:36 stephena Exp $
// $Id: Widget.hxx,v 1.44 2006-01-04 01:24:17 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -44,8 +44,9 @@ enum {
WIDGET_TRACK_MOUSE = 1 << 6,
WIDGET_RETAIN_FOCUS = 1 << 7,
WIDGET_NODRAW_FOCUS = 1 << 8,
WIDGET_WANTS_TAB = 1 << 9,
WIDGET_WANTS_EVENTS = 1 << 10
WIDGET_STICKY_FOCUS = 1 << 9,
WIDGET_WANTS_TAB = 1 << 10,
WIDGET_WANTS_EVENTS = 1 << 11
};
enum {
@ -73,7 +74,7 @@ enum {
This is the base class for all widgets.
@author Stephen Anthony
@version $Id: Widget.hxx,v 1.43 2005-12-24 22:09:36 stephena Exp $
@version $Id: Widget.hxx,v 1.44 2006-01-04 01:24:17 stephena Exp $
*/
class Widget : public GuiObject
{
@ -115,6 +116,7 @@ class Widget : public GuiObject
bool isEnabled() const { return _flags & WIDGET_ENABLED; }
bool isVisible() const { return !(_flags & WIDGET_INVISIBLE); }
bool isSticky() const { return _flags & WIDGET_STICKY_FOCUS; }
bool wantsEvents() const { return _flags & WIDGET_WANTS_EVENTS; }
void setID(int id) { _id = id; }