Implemented EditTextWidget; fixed Add Game/Remove Game in launcher; make use of EditTextWidget in EditGameDialog; various other tweaks

svn-id: r5665
This commit is contained in:
Max Horn 2002-11-21 15:20:52 +00:00
parent 5852b6a09b
commit 9ff12dbc01
9 changed files with 223 additions and 65 deletions

View file

@ -22,3 +22,136 @@
#include "EditTextWidget.h" #include "EditTextWidget.h"
#include "dialog.h" #include "dialog.h"
#include "newgui.h" #include "newgui.h"
EditTextWidget::EditTextWidget(Dialog *boss, int x, int y, int w, int h, const String &text)
: StaticTextWidget(boss, x, y-1, w, h+2, text, kTextAlignLeft), _backupString(text)
{
_flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE;
_type = kEditTextWidget;
_currentKeyDown = 0;
_caretVisible = false;
_caretTime = 0;
}
void EditTextWidget::handleTickle()
{
uint32 time = _boss->getGui()->get_time();
if (_caretTime < time) {
_caretTime = time + kCaretBlinkTime;
if (_caretVisible) {
drawCaret(true);
} else {
drawCaret(false);
}
}
}
void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount)
{
// TODO - once we support "real editing" (i.e. caret can be at any spot),
// a mouse click should place the caret.
}
bool EditTextWidget::handleKeyDown(char key, int modifiers)
{
bool handled = true;
bool dirty = false;
// First remove caret
if (_caretVisible)
drawCaret(true);
switch (key) {
case '\n': // enter/return
case '\r':
_boss->releaseFocus();
dirty = true;
break;
case 27: // escape
_label = _backupString;
_boss->releaseFocus();
dirty = true;
break;
case 8: // backspace
_label.deleteLastChar();
dirty = true;
break;
case 20: // left arrow
break;
case 19: // right arrow
break;
case 22: // home
break;
case 23: // end
break;
default:
if (isalnum(key) || key == ' ') {
_label += key;
dirty = true;
} else {
handled = false;
}
}
if (dirty)
draw();
#ifndef _WIN32_WCE
// not done on WinCE because keyboard is emulated and
// keyup is not generated
_currentKeyDown = key;
#endif
return handled;
}
bool EditTextWidget::handleKeyUp(char key, int modifiers)
{
if (key == _currentKeyDown)
_currentKeyDown = 0;
return true;
}
void EditTextWidget::drawWidget(bool hilite)
{
NewGui *gui = _boss->getGui();
// Draw a thin frame around us.
gui->hline(_x, _y, _x+_w-1, gui->_color);
gui->hline(_x, _y+_h-1, _x+_w-1, gui->_shadowcolor);
gui->vline(_x, _y, _y+_h-1, gui->_color);
// Draw the text
_align = (gui->getStringWidth(_label) > _w-6) ? kTextAlignRight : kTextAlignLeft;
gui->drawString(_label, _x+2, _y+3, _w-6, gui->_textcolor, _align);
}
void EditTextWidget::drawCaret(bool erase)
{
// Only draw if item is visible
if (!isVisible() || !_boss->isVisible())
return;
NewGui *gui = _boss->getGui();
int16 color = erase ? gui->_bgcolor : gui->_textcolorhi;
int x = _x + _boss->getX() + 3;
int y = _y + _boss->getY() + 1;
// TODO - once we support "real editing" (i.e. caret can be at any spot),
// x should be calculated based on the current caret position.
int width = gui->getStringWidth(_label);
if (width > _w-6)
width = _w-6;
x += width;
gui->vline(x, y, y+kLineHeight, color);
gui->addDirtyRect(x, y, 2, kLineHeight);
_caretVisible = !erase;
}

View file

@ -35,22 +35,20 @@ protected:
bool _caretVisible; bool _caretVisible;
uint32 _caretTime; uint32 _caretTime;
public: public:
EditTextWidget(Dialog *boss, int x, int y, int w, int h); EditTextWidget(Dialog *boss, int x, int y, int w, int h, const String &text);
virtual ~EditTextWidget();
virtual void handleTickle(); virtual void handleTickle();
virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleMouseDown(int x, int y, int button, int clickCount);
virtual void handleMouseUp(int x, int y, int button, int clickCount);
virtual bool handleKeyDown(char key, int modifiers); virtual bool handleKeyDown(char key, int modifiers);
virtual bool handleKeyUp(char key, int modifiers); virtual bool handleKeyUp(char key, int modifiers);
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); //virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
virtual bool wantsFocus() { return true; }; virtual bool wantsFocus() { return true; };
protected: protected:
void drawWidget(bool hilite); void drawWidget(bool hilite);
void drawCaret(bool erase); void drawCaret(bool erase);
void lostFocusWidget(); void lostFocusWidget() { _backupString = _label; drawCaret(true); }
}; };
#endif #endif

View file

@ -92,7 +92,7 @@ void ListWidget::handleTickle()
{ {
uint32 time = _boss->getGui()->get_time(); uint32 time = _boss->getGui()->get_time();
if (_editMode && _caretTime < time) { if (_editMode && _caretTime < time) {
_caretTime = time + 300; _caretTime = time + kCaretBlinkTime;
if (_caretVisible) { if (_caretVisible) {
drawCaret(true); drawCaret(true);
} else { } else {
@ -101,40 +101,6 @@ void ListWidget::handleTickle()
} }
} }
void ListWidget::drawCaret(bool erase)
{
// Only draw if item is visible
if (_selectedItem < _currentPos || _selectedItem >= _currentPos + _entriesPerPage)
return;
if (!isVisible() || !_boss->isVisible())
return;
NewGui *gui = _boss->getGui();
// The item is selected, thus _bgcolor is used to draw the caret and _textcolorhi to erase it
int16 color = erase ? gui->_textcolorhi : gui->_bgcolor;
int x = _x + _boss->getX() + 3;
int y = _y + _boss->getY() + 1;
ScummVM::String buffer;
y += (_selectedItem - _currentPos) * kLineHeight;
if (_numberingMode == kListNumberingZero || _numberingMode == kListNumberingOne) {
char temp[10];
sprintf(temp, "%2d. ", (_selectedItem + _numberingMode));
buffer = temp;
buffer += _list[_selectedItem];
} else
buffer = _list[_selectedItem];
x += gui->getStringWidth(buffer);
gui->vline(x, y, y+kLineHeight, color);
gui->addDirtyRect(x, y, 2, kLineHeight);
_caretVisible = !erase;
}
void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) void ListWidget::handleMouseDown(int x, int y, int button, int clickCount)
{ {
if (isEnabled()) { if (isEnabled()) {
@ -332,6 +298,40 @@ void ListWidget::drawWidget(bool hilite)
} }
} }
void ListWidget::drawCaret(bool erase)
{
// Only draw if item is visible
if (_selectedItem < _currentPos || _selectedItem >= _currentPos + _entriesPerPage)
return;
if (!isVisible() || !_boss->isVisible())
return;
NewGui *gui = _boss->getGui();
// The item is selected, thus _bgcolor is used to draw the caret and _textcolorhi to erase it
int16 color = erase ? gui->_textcolorhi : gui->_bgcolor;
int x = _x + _boss->getX() + 3;
int y = _y + _boss->getY() + 1;
ScummVM::String buffer;
y += (_selectedItem - _currentPos) * kLineHeight;
if (_numberingMode == kListNumberingZero || _numberingMode == kListNumberingOne) {
char temp[10];
sprintf(temp, "%2d. ", (_selectedItem + _numberingMode));
buffer = temp;
buffer += _list[_selectedItem];
} else
buffer = _list[_selectedItem];
x += gui->getStringWidth(buffer);
gui->vline(x, y, y+kLineHeight, color);
gui->addDirtyRect(x, y, 2, kLineHeight);
_caretVisible = !erase;
}
void ListWidget::scrollToCurrent() { void ListWidget::scrollToCurrent() {
// Only do something if the current item is not in our view port // Only do something if the current item is not in our view port

View file

@ -90,12 +90,18 @@ void Dialog::close()
_mouseWidget->handleMouseLeft(0); _mouseWidget->handleMouseLeft(0);
_mouseWidget = 0; _mouseWidget = 0;
} }
releaseFocus();
}
void Dialog::releaseFocus()
{
if (_focusedWidget) { if (_focusedWidget) {
_focusedWidget->lostFocus(); _focusedWidget->lostFocus();
_focusedWidget = 0; _focusedWidget = 0;
} }
} }
void Dialog::draw() void Dialog::draw()
{ {
_gui->_needRedraw = true; _gui->_needRedraw = true;
@ -134,8 +140,7 @@ void Dialog::handleMouseDown(int x, int y, int button, int clickCount)
if (w && w != _focusedWidget) { if (w && w != _focusedWidget) {
// The focus will change. Tell the old focused widget (if any) // The focus will change. Tell the old focused widget (if any)
// that it lost the focus. // that it lost the focus.
if (_focusedWidget) releaseFocus();
_focusedWidget->lostFocus();
// Tell the new focused widget (if any) that it just gained the focus. // Tell the new focused widget (if any) that it just gained the focus.
if (w) if (w)
@ -157,8 +162,7 @@ void Dialog::handleMouseUp(int x, int y, int button, int clickCount)
// Lose focus on mouseup unless the widget requested to retain the focus // Lose focus on mouseup unless the widget requested to retain the focus
if (! (_focusedWidget->getFlags() & WIDGET_RETAIN_FOCUS )) { if (! (_focusedWidget->getFlags() & WIDGET_RETAIN_FOCUS )) {
_focusedWidget->lostFocus(); releaseFocus();
_focusedWidget = 0;
} }
} else { } else {
@ -208,6 +212,8 @@ void Dialog::handleKeyDown(char key, int modifiers)
// ESC closes all dialogs by default // ESC closes all dialogs by default
if (key == 27) if (key == 27)
close(); close();
// TODO: tab/shift-tab should focus the next/previous focusable widget
} }
void Dialog::handleKeyUp(char key, int modifiers) void Dialog::handleKeyUp(char key, int modifiers)

View file

@ -62,6 +62,8 @@ public:
int16 getX() const { return _x; } int16 getX() const { return _x; }
int16 getY() const { return _y; } int16 getY() const { return _y; }
void releaseFocus();
protected: protected:
virtual void open(); virtual void open();
virtual void close(); virtual void close();

View file

@ -50,6 +50,7 @@ typedef ScummVM::List<const VersionSettings *> GameList;
* - the description (used for user feedback only) * - the description (used for user feedback only)
* - amiga/subtitles flag? Although those make only sense for Scumm games * - amiga/subtitles flag? Although those make only sense for Scumm games
* - the music driver for that game (<Default> or custom) * - the music driver for that game (<Default> or custom)
* Of course this means we need an API to query the available music drivers.
* - maybe scaler. But there are two problems: * - maybe scaler. But there are two problems:
* 1) different backends can have different scalers with different names, * 1) different backends can have different scalers with different names,
* so we first have to add a way to query those... no Ender, I don't * so we first have to add a way to query those... no Ender, I don't
@ -97,19 +98,18 @@ EditGameDialog::EditGameDialog(NewGui *gui, Config &config, const String &domain
} }
// Label & edit widget for the description // Label & edit widget for the description
new StaticTextWidget(this, 10, 8, 40, kLineHeight, "Name: ", kTextAlignRight); new StaticTextWidget(this, 10, 10, 40, kLineHeight, "Name: ", kTextAlignRight);
new StaticTextWidget(this, 50, 8, _w-50-10, kLineHeight, description, kTextAlignLeft); // TODO - should be an EditTextWidget new EditTextWidget(this, 50, 10, _w-50-10, kLineHeight, description);
// Path to game data (view only) // Path to game data (view only)
String path(_config.get("path", domain)); String path(_config.get("path", domain));
new StaticTextWidget(this, 10, 20, 40, kLineHeight, "Path: ", kTextAlignRight); new StaticTextWidget(this, 10, 24, 40, kLineHeight, "Path: ", kTextAlignRight);
new StaticTextWidget(this, 50, 20, _w-50-10, kLineHeight, path, kTextAlignLeft); new StaticTextWidget(this, 50, 24, _w-50-10, kLineHeight, path, kTextAlignLeft);
// Add OK & Cancel buttons // Add OK & Cancel buttons
addButton(_w-2*(kButtonWidth+10), _h-24, "Cancel", kCloseCmd, 0); addButton(_w-2*(kButtonWidth+10), _h-24, "Cancel", kCloseCmd, 0);
addButton(_w-(kButtonWidth+10), _h-24, "OK", kCloseCmd, 0); addButton(_w-(kButtonWidth+10), _h-24, "OK", kOKCmd, 0);
} }
void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
@ -172,6 +172,7 @@ LauncherDialog::LauncherDialog(NewGui *gui, GameDetector &detector)
// Create file browser dialog // Create file browser dialog
_browser = new BrowserDialog(_gui); _browser = new BrowserDialog(_gui);
} }
LauncherDialog::~LauncherDialog() LauncherDialog::~LauncherDialog()
@ -179,18 +180,29 @@ LauncherDialog::~LauncherDialog()
delete _browser; delete _browser;
} }
void LauncherDialog::open()
{
Dialog::open();
g_config->set_writing(true);
}
void LauncherDialog::close()
{
g_config->flush();
g_config->set_writing(false);
Dialog::close();
}
void LauncherDialog::updateListing() void LauncherDialog::updateListing()
{ {
int i; int i;
const VersionSettings *v = version_settings; const VersionSettings *v = version_settings;
ScummVM::StringList l; ScummVM::StringList l;
// TODO - maybe only display those games for which settings are known
// (i.e. a path to the game data was set and is accesible) ?
// Retrieve a list of all games defined in the config file // Retrieve a list of all games defined in the config file
_domains.clear();
StringList domains = g_config->get_domains(); StringList domains = g_config->get_domains();
for (i = 0; i < domains.size();i++) { for (i = 0; i < domains.size(); i++) {
String name(g_config->get("gameid", domains[i])); String name(g_config->get("gameid", domains[i]));
String description(g_config->get("description", domains[i])); String description(g_config->get("description", domains[i]));
@ -217,8 +229,7 @@ void LauncherDialog::updateListing()
} }
} }
if (l.size() > 0) _list->setList(l);
_list->setList(l);
} }
/* /*
@ -340,9 +351,7 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// User pressed OK, so make changes permanent // User pressed OK, so make changes permanent
// Write config to disk // Write config to disk
g_config->set_writing(true);
g_config->flush(); g_config->flush();
g_config->set_writing(false);
// Update the ListWidget and force a redraw // Update the ListWidget and force a redraw
updateListing(); updateListing();
@ -358,6 +367,11 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// Remove the currently selected game from the list // Remove the currently selected game from the list
assert(item >= 0); assert(item >= 0);
g_config->delete_domain(_domains[item]); g_config->delete_domain(_domains[item]);
// Write config to disk
g_config->flush();
// Update the ListWidget and force a redraw
updateListing(); updateListing();
draw(); draw();
break; break;
@ -374,9 +388,7 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// User pressed OK, so make changes permanent // User pressed OK, so make changes permanent
// Write config to disk // Write config to disk
g_config->set_writing(true);
g_config->flush(); g_config->flush();
g_config->set_writing(false);
// Update the ListWidget and force a redraw // Update the ListWidget and force a redraw
updateListing(); updateListing();

View file

@ -36,7 +36,9 @@ public:
LauncherDialog(NewGui *gui, GameDetector &detector); LauncherDialog(NewGui *gui, GameDetector &detector);
~LauncherDialog(); ~LauncherDialog();
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); virtual void open();
virtual void close();
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
protected: protected:
ListWidget *_list; ListWidget *_list;

View file

@ -101,7 +101,7 @@ void StaticTextWidget::setValue(int value)
void StaticTextWidget::drawWidget(bool hilite) void StaticTextWidget::drawWidget(bool hilite)
{ {
NewGui *gui = _boss->getGui(); NewGui *gui = _boss->getGui();
gui->drawString(_label.c_str(), _x, _y, _w, gui->_textcolor, _align); gui->drawString(_label, _x, _y, _w, gui->_textcolor, _align);
} }
@ -125,7 +125,7 @@ void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount)
void ButtonWidget::drawWidget(bool hilite) void ButtonWidget::drawWidget(bool hilite)
{ {
NewGui *gui = _boss->getGui(); NewGui *gui = _boss->getGui();
gui->drawString(_label.c_str(), _x, _y, _w, gui->drawString(_label, _x, _y, _w,
!isEnabled() ? gui->_color : !isEnabled() ? gui->_color :
hilite ? gui->_textcolorhi : gui->_textcolor, _align); hilite ? gui->_textcolorhi : gui->_textcolor, _align);
} }
@ -195,7 +195,7 @@ void CheckboxWidget::drawWidget(bool hilite)
gui->fillRect(_x + 2, _y + 2, 10, 10, gui->_bgcolor); gui->fillRect(_x + 2, _y + 2, 10, 10, gui->_bgcolor);
// Finally draw the label // Finally draw the label
gui->drawString(_label.c_str(), _x + 20, _y + 3, _w, gui->_textcolor); gui->drawString(_label, _x + 20, _y + 3, _w, gui->_textcolor);
} }
#pragma mark - #pragma mark -

View file

@ -41,6 +41,7 @@ enum {
enum { enum {
kStaticTextWidget = 'TEXT', kStaticTextWidget = 'TEXT',
kEditTextWidget = 'EDIT',
kButtonWidget = 'BTTN', kButtonWidget = 'BTTN',
kCheckboxWidget = 'CHKB', kCheckboxWidget = 'CHKB',
kSliderWidget = 'SLDE', kSliderWidget = 'SLDE',
@ -48,6 +49,10 @@ enum {
kScrollBarWidget = 'SCRB' kScrollBarWidget = 'SCRB'
}; };
enum {
kCaretBlinkTime = 300
};
enum { enum {
kButtonWidth = 56, kButtonWidth = 56,
kButtonHeight = 16, kButtonHeight = 16,