More GUI infrastructure changes. I'm hoping to have the CheatWidget

complete by tomorrow evening.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@493 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-06-14 01:11:48 +00:00
parent 15ae1043e9
commit 780422bd42
20 changed files with 769 additions and 65 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: makefile,v 1.93 2005-06-12 20:12:10 stephena Exp $
## $Id: makefile,v 1.94 2005-06-14 01:11:47 stephena Exp $
##============================================================================
##============================================================================
@ -157,6 +157,7 @@ M6502_OBJS = D6502.o Device.o M6502.o M6502Low.o M6502Hi.o NullDev.o System.o
GUI_OBJS = Font.o Menu.o Launcher.o \
Widget.o PopUpWidget.o ScrollBarWidget.o ListWidget.o TabWidget.o \
EditableWidget.o EditTextWidget.o \
Dialog.o DialogContainer.o OptionsDialog.o VideoDialog.o AudioDialog.o \
EventMappingDialog.o GameInfoDialog.o HelpDialog.o AboutDialog.o \
LauncherDialog.o LauncherOptionsDialog.o BrowserDialog.o GameList.o \
@ -407,6 +408,12 @@ ListWidget.o: $(GUI)/ListWidget.cxx $(GUI)/ListWidget.hxx
TabWidget.o: $(GUI)/TabWidget.cxx $(GUI)/TabWidget.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(GUI)/TabWidget.cxx
EditableWidget.o: $(GUI)/EditableWidget.cxx $(GUI)/EditableWidget.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(GUI)/EditableWidget.cxx
EditTextWidget.o: $(GUI)/EditTextWidget.cxx $(GUI)/EditTextWidget.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(GUI)/EditTextWidget.cxx
Dialog.o: $(GUI)/Dialog.cxx $(GUI)/Dialog.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(GUI)/Dialog.cxx

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: FrameBufferGL.cxx,v 1.28 2005-06-08 18:45:07 stephena Exp $
// $Id: FrameBufferGL.cxx,v 1.29 2005-06-14 01:11:47 stephena Exp $
//============================================================================
#include <SDL.h>
@ -352,26 +352,25 @@ void FrameBufferGL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::drawChar(const GUI::Font& FONT, uInt8 chr,
void FrameBufferGL::drawChar(const GUI::Font* FONT, uInt8 chr,
uInt32 xorig, uInt32 yorig, OverlayColor color)
{
// FIXME - I do this to prevent 'const' warnings; it should be done better
GUI::Font& font = (GUI::Font&)FONT;
GUI::Font* font = (GUI::Font*) FONT;
// If this character is not included in the font, use the default char.
if(chr < font.desc().firstchar ||
chr >= font.desc().firstchar + font.desc().size)
if(chr < font->desc().firstchar ||
chr >= font->desc().firstchar + font->desc().size)
{
if (chr == ' ')
return;
chr = font.desc().defaultchar;
chr = font->desc().defaultchar;
}
const Int32 w = font.getCharWidth(chr);
const Int32 h = font.getFontHeight();
chr -= font.desc().firstchar;
const uInt16* tmp = font.desc().bits + (font.desc().offset ?
font.desc().offset[chr] : (chr * h));
const Int32 w = font->getCharWidth(chr);
const Int32 h = font->getFontHeight();
chr -= font->desc().firstchar;
const uInt16* tmp = font->desc().bits + (font->desc().offset ?
font->desc().offset[chr] : (chr * h));
SDL_Rect rect;
for(int y = 0; y < h; y++)

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: FrameBufferGL.hxx,v 1.15 2005-06-08 18:45:08 stephena Exp $
// $Id: FrameBufferGL.hxx,v 1.16 2005-06-14 01:11:48 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_GL_HXX
@ -35,7 +35,7 @@ class GUI::Font;
This class implements an SDL OpenGL framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferGL.hxx,v 1.15 2005-06-08 18:45:08 stephena Exp $
@version $Id: FrameBufferGL.hxx,v 1.16 2005-06-14 01:11:48 stephena Exp $
*/
class FrameBufferGL : public FrameBuffer
{
@ -164,7 +164,7 @@ class FrameBufferGL : public FrameBuffer
@param y The y coordinate
@param color The color of the character
*/
virtual void drawChar(const GUI::Font& font, uInt8 c, uInt32 x, uInt32 y,
virtual void drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y,
OverlayColor color);
/**

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: FrameBufferSoft.cxx,v 1.24 2005-06-08 18:45:08 stephena Exp $
// $Id: FrameBufferSoft.cxx,v 1.25 2005-06-14 01:11:48 stephena Exp $
//============================================================================
#include <SDL.h>
@ -375,26 +375,25 @@ void FrameBufferSoft::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::drawChar(const GUI::Font& FONT, uInt8 chr,
void FrameBufferSoft::drawChar(const GUI::Font* FONT, uInt8 chr,
uInt32 xorig, uInt32 yorig, OverlayColor color)
{
// FIXME - I do this to prevent 'const' warnings; it should be done better
GUI::Font& font = (GUI::Font&)FONT;
GUI::Font* font = (GUI::Font*)FONT;
// If this character is not included in the font, use the default char.
if(chr < font.desc().firstchar ||
chr >= font.desc().firstchar + font.desc().size)
if(chr < font->desc().firstchar ||
chr >= font->desc().firstchar + font->desc().size)
{
if (chr == ' ')
return;
chr = font.desc().defaultchar;
chr = font->desc().defaultchar;
}
const Int32 w = font.getCharWidth(chr);
const Int32 h = font.getFontHeight();
chr -= font.desc().firstchar;
const uInt16* tmp = font.desc().bits + (font.desc().offset ?
font.desc().offset[chr] : (chr * h));
const Int32 w = font->getCharWidth(chr);
const Int32 h = font->getFontHeight();
chr -= font->desc().firstchar;
const uInt16* tmp = font->desc().bits + (font->desc().offset ?
font->desc().offset[chr] : (chr * h));
SDL_Rect rect;
for(int y = 0; y < h; y++)

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: FrameBufferSoft.hxx,v 1.15 2005-06-08 18:45:08 stephena Exp $
// $Id: FrameBufferSoft.hxx,v 1.16 2005-06-14 01:11:48 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_SOFT_HXX
@ -35,7 +35,7 @@ class RectList;
This class implements an SDL software framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.15 2005-06-08 18:45:08 stephena Exp $
@version $Id: FrameBufferSoft.hxx,v 1.16 2005-06-14 01:11:48 stephena Exp $
*/
class FrameBufferSoft : public FrameBuffer
{
@ -164,7 +164,7 @@ class FrameBufferSoft : public FrameBuffer
@param y The y coordinate
@param color The color of the character
*/
virtual void drawChar(const GUI::Font& font, uInt8 c, uInt32 x, uInt32 y,
virtual void drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y,
OverlayColor color);
/**

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: FrameBuffer.cxx,v 1.43 2005-06-08 18:45:08 stephena Exp $
// $Id: FrameBuffer.cxx,v 1.44 2005-06-14 01:11:48 stephena Exp $
//============================================================================
#include <sstream>
@ -185,7 +185,7 @@ void FrameBuffer::update()
// Draw the bounded box and text
blendRect(x+1, y+2, w-2, h-4, kBGColor);
box(x, y+1, w, h-2, kColor, kColor);
drawString(myOSystem->font(), myMessageText, x+1, y+4, w, kTextColor, kTextAlignCenter);
drawString(&myOSystem->font(), myMessageText, x+1, y+4, w, kTextColor, kTextAlignCenter);
myMessageTime--;
// Erase this message on next update
@ -536,14 +536,14 @@ void FrameBuffer::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::drawString(const GUI::Font& font, const string& s,
void FrameBuffer::drawString(const GUI::Font* font, const string& s,
int x, int y, int w,
OverlayColor color, TextAlignment align,
int deltax, bool useEllipsis)
{
const int leftX = x, rightX = x + w;
unsigned int i;
int width = font.getStringWidth(s);
int width = font->getStringWidth(s);
string str;
if(useEllipsis && width > w)
@ -554,7 +554,7 @@ void FrameBuffer::drawString(const GUI::Font& font, const string& s,
// What is best really depends on the context; but unless we want to
// make this configurable, replacing the middle probably is a good
// compromise.
const int ellipsisWidth = font.getStringWidth("...");
const int ellipsisWidth = font->getStringWidth("...");
// SLOW algorithm to remove enough of the middle. But it is good enough for now.
const int halfWidth = (w - ellipsisWidth) / 2;
@ -562,7 +562,7 @@ void FrameBuffer::drawString(const GUI::Font& font, const string& s,
for(i = 0; i < s.size(); ++i)
{
int charWidth = font.getCharWidth(s[i]);
int charWidth = font->getCharWidth(s[i]);
if(w2 + charWidth > halfWidth)
break;
@ -582,13 +582,13 @@ void FrameBuffer::drawString(const GUI::Font& font, const string& s,
// (width + ellipsisWidth - w)
int skip = width + ellipsisWidth - w;
for(; i < s.size() && skip > 0; ++i)
skip -= font.getCharWidth(s[i]);
skip -= font->getCharWidth(s[i]);
// Append the remaining chars, if any
for(; i < s.size(); ++i)
str += s[i];
width = font.getStringWidth(str);
width = font->getStringWidth(str);
}
else
str = s;
@ -601,7 +601,7 @@ void FrameBuffer::drawString(const GUI::Font& font, const string& s,
x += deltax;
for(i = 0; i < str.size(); ++i)
{
w = font.getCharWidth(str[i]);
w = font->getCharWidth(str[i]);
if(x+w > rightX)
break;
if(x >= leftX)

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: FrameBuffer.hxx,v 1.38 2005-06-08 18:45:08 stephena Exp $
// $Id: FrameBuffer.hxx,v 1.39 2005-06-14 01:11:48 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_HXX
@ -46,7 +46,7 @@ enum TextAlignment {
All GUI elements (ala ScummVM) are drawn here as well.
@author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.38 2005-06-08 18:45:08 stephena Exp $
@version $Id: FrameBuffer.hxx,v 1.39 2005-06-14 01:11:48 stephena Exp $
*/
class FrameBuffer
{
@ -245,7 +245,7 @@ class FrameBuffer
@param deltax
@param useEllipsis Whether to use '...' when the string is too long
*/
void drawString(const GUI::Font& font, const string& str, int x, int y, int w,
void drawString(const GUI::Font* font, const string& str, int x, int y, int w,
OverlayColor color, TextAlignment align = kTextAlignLeft,
int deltax = 0, bool useEllipsis = true);
@ -363,7 +363,7 @@ class FrameBuffer
@param y The y coordinate
@param color The color of the character
*/
virtual void drawChar(const GUI::Font& font, uInt8 c, uInt32 x, uInt32 y,
virtual void drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y,
OverlayColor color) = 0;
/**

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: CheatWidget.cxx,v 1.1 2005-06-12 20:12:10 stephena Exp $
// $Id: CheatWidget.cxx,v 1.2 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -26,14 +26,48 @@
#include "Widget.hxx"
#include "ListWidget.hxx"
#include "EditTextWidget.hxx"
#include "CheatWidget.hxx"
enum {
kSearchCmd,
kCmpCmd,
kRestartCmd
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CheatWidget::CheatWidget(GuiObject* boss, int x, int y, int w, int h)
: Widget(boss, x, y, w, h),
CommandSender(boss)
{
int xpos = 10;
const int bwidth = 50, space = 20;
// Add the edit textbox, set to accept decimal values
myEditBox = new EditTextWidget(boss, 10, 10, 80, 16, "");
myEditBox->setFont(_boss->instance()->consoleFont());
myEditBox->setEditString("HELLO!");
// myEditBox->setTarget(this);
// myResult = new StaticTextWidget();
// Add the three search-related buttons
mySearchButton = new ButtonWidget(boss, xpos, _h - space, bwidth, 16,
"Search", kSearchCmd, 0);
mySearchButton->setTarget(this);
xpos += 8 + bwidth;
myCompareButton = new ButtonWidget(boss, xpos, _h - space, bwidth, 16,
"Compare", kCmpCmd, 0);
myCompareButton->setTarget(this);
xpos += 8 + bwidth;
myRestartButton = new ButtonWidget(boss, xpos, _h - space, bwidth, 16,
"Restart", kRestartCmd, 0);
myRestartButton->setTarget(this);
xpos += 8 + bwidth;
ListWidget* myList = new ListWidget(boss, 10, 24, 100, h - 50);
myList->setTarget(this);
myList->setEditable(false);

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: CheatWidget.hxx,v 1.1 2005-06-12 20:12:10 stephena Exp $
// $Id: CheatWidget.hxx,v 1.2 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -23,6 +23,9 @@
#define CHEAT_WIDGET_HXX
class GuiObject;
class ButtonWidget;
class StaticTextWidget;
class EditTextWidget;
#include "Widget.hxx"
#include "Command.hxx"
@ -38,7 +41,14 @@ class CheatWidget : public Widget, public CommandSender
void handleCommand(CommandSender* sender, int cmd, int data);
private:
Widget* myActiveWidget;
Widget* myActiveWidget;
EditTextWidget* myEditBox;
StaticTextWidget* myResult;
ButtonWidget* mySearchButton;
ButtonWidget* myCompareButton;
ButtonWidget* myRestartButton;
};
#endif

View File

@ -0,0 +1,121 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EditTextWidget.cxx,v 1.1 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include "OSystem.hxx"
#include "FrameBuffer.hxx"
#include "Dialog.hxx"
#include "EditTextWidget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EditTextWidget::EditTextWidget(GuiObject* boss, int x, int y, int w, int h,
const string& text)
: EditableWidget(boss, x, y - 1, w, h + 2)
{
_flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS |
WIDGET_TAB_NAVIGATE;
_type = kEditTextWidget;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::setEditString(const string& str)
{
EditableWidget::setEditString(str);
_backupString = str;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount)
{
// First remove caret
if (_caretVisible)
drawCaret(true);
x += _editScrollOffset;
int width = 0;
unsigned int i;
for (i = 0; i < _editString.size(); ++i)
{
width += _font->getCharWidth(_editString[i]);
if (width >= x)
break;
}
if (setCaretPos(i))
draw();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::drawWidget(bool hilite)
{
FrameBuffer& fb = _boss->instance()->frameBuffer();
// Draw a thin frame around us.
fb.hLine(_x, _y, _x + _w - 1, kColor);
fb.hLine(_x, _y + _h - 1, _x +_w - 1, kShadowColor);
fb.vLine(_x, _y, _y + _h - 1, kColor);
fb.vLine(_x + _w - 1, _y, _y + _h - 1, kShadowColor);
// Draw the text
adjustOffset();
fb.drawString(_font, _editString, _x + 2, _y + 2, getEditRect().width(),
kTextColor, kTextAlignLeft, -_editScrollOffset, false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GUI::Rect EditTextWidget::getEditRect() const
{
GUI::Rect r(2, 1, _w - 2, _h);
return r;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::receivedFocusWidget()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::lostFocusWidget()
{
// If we loose focus, 'commit' the user changes
_backupString = _editString;
drawCaret(true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::startEditMode()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::endEditMode()
{
releaseFocus();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditTextWidget::abortEditMode()
{
setEditString(_backupString);
releaseFocus();
}

View File

@ -0,0 +1,56 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EditTextWidget.hxx,v 1.1 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef EDIT_TEXT_WIDGET_HXX
#define EDIT_TEXT_WIDGET_HXX
#include "Rect.hxx"
#include "EditableWidget.hxx"
/* EditTextWidget */
class EditTextWidget : public EditableWidget
{
public:
EditTextWidget(GuiObject* boss, int x, int y, int w, int h, const string& text);
void setEditString(const string& str);
virtual void handleMouseDown(int x, int y, int button, int clickCount);
virtual bool wantsFocus() { return true; }
protected:
void drawWidget(bool hilite);
void receivedFocusWidget();
void lostFocusWidget();
void startEditMode();
void endEditMode();
void abortEditMode();
GUI::Rect getEditRect() const;
protected:
string _backupString;
};
#endif

View File

@ -0,0 +1,232 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EditableWidget.cxx,v 1.1 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#include "EditableWidget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EditableWidget::EditableWidget(GuiObject* boss, int x, int y, int w, int h)
: Widget(boss, x, y, w, h)
{
_caretVisible = false;
_caretTime = 0;
_caretPos = 0; // FIXME
_caretInverse = false;
_editScrollOffset = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EditableWidget::~EditableWidget()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditableWidget::setEditString(const string& str)
{
// TODO: We probably should filter the input string here,
// e.g. using tryInsertChar.
_editString = str;
_caretPos = _editString.size();
_editScrollOffset = (_font->getStringWidth(_editString) - (getEditRect().width()));
if (_editScrollOffset < 0)
_editScrollOffset = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EditableWidget::tryInsertChar(char c, int pos)
{
if (isprint(c))
{
_editString.insert(pos, c, 1);
return true;
}
return false;
}
/*
void EditableWidget::handleTickle() {
uint32 time = getMillis();
if (_caretTime < time) {
_caretTime = time + kCaretBlinkTime;
drawCaret(_caretVisible);
}
}
*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EditableWidget::handleKeyDown(int ascii, int keycode, int modifiers)
{
bool handled = true;
bool dirty = false;
// First remove caret
if (_caretVisible)
drawCaret(true);
switch (keycode)
{
case '\n': // enter/return
case '\r':
// confirm edit and exit editmode
endEditMode();
dirty = true;
break;
case 27: // escape
abortEditMode();
dirty = true;
break;
case 8: // backspace
if (_caretPos > 0)
{
_caretPos--;
_editString.erase(_caretPos);
dirty = true;
}
break;
case 127: // delete
_editString.erase(_caretPos);
dirty = true;
break;
case 256 + 20: // left arrow
if (_caretPos > 0)
dirty = setCaretPos(_caretPos - 1);
break;
case 256 + 19: // right arrow
if (_caretPos < (int)_editString.size())
dirty = setCaretPos(_caretPos + 1);
break;
case 256 + 22: // home
dirty = setCaretPos(0);
break;
case 256 + 23: // end
dirty = setCaretPos(_editString.size());
break;
default:
if (tryInsertChar((char)ascii, _caretPos))
{
_caretPos++;
dirty = true;
}
else
handled = false;
}
if (dirty)
draw();
return handled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int EditableWidget::getCaretOffset() const
{
int caretpos = 0;
for (int i = 0; i < _caretPos; i++)
caretpos += _font->getCharWidth(_editString[i]);
caretpos -= _editScrollOffset;
return caretpos;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EditableWidget::drawCaret(bool erase)
{
// Only draw if item is visible
if (!isVisible() || !_boss->isVisible())
return;
GUI::Rect editRect = getEditRect();
OverlayColor color = (erase ^ _caretInverse) ? kBGColor : kTextColorHi;
int x = editRect.left;
int y = editRect.top + 1;
x += getCaretOffset();
if (y < 0 || y + editRect.height() - 2 >= _h)
return;
x += getAbsX();
y += getAbsY();
FrameBuffer& fb = _boss->instance()->frameBuffer();
fb.vLine(x, y, y + editRect.height() - 2, color);
fb.refresh();//FIXMEfb.addDirtyRect(x, y, 2, editRect.height() - 2);
_caretVisible = !erase;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EditableWidget::setCaretPos(int newPos)
{
assert(newPos >= 0 && newPos <= (int)_editString.size());
_caretPos = newPos;
return adjustOffset();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EditableWidget::adjustOffset()
{
// check if the caret is still within the textbox; if it isn't,
// adjust _editScrollOffset
int caretpos = getCaretOffset();
const int editWidth = getEditRect().width();
if (caretpos < 0)
{
// scroll left
_editScrollOffset += caretpos;
return true;
}
else if (caretpos >= editWidth)
{
// scroll right
_editScrollOffset -= (editWidth - caretpos);
return true;
}
else if (_editScrollOffset > 0)
{
const int strWidth = _font->getStringWidth(_editString);
if (strWidth - _editScrollOffset < editWidth)
{
// scroll right
_editScrollOffset = (strWidth - editWidth);
if (_editScrollOffset < 0)
_editScrollOffset = 0;
}
}
return false;
}

View File

@ -0,0 +1,68 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EditableWidget.hxx,v 1.1 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef EDITABLE_WIDGET_HXX
#define EDITABLE_WIDGET_HXX
#include "Widget.hxx"
#include "Rect.hxx"
/**
* Base class for widgets which need to edit text, like ListWidget and
* EditTextWidget.
*/
class EditableWidget : public Widget
{
public:
EditableWidget(GuiObject *boss, int x, int y, int w, int h);
virtual ~EditableWidget();
virtual void setEditString(const string& str);
virtual const string& getEditString() const { return _editString; }
virtual bool handleKeyDown(int ascii, int keycode, int modifiers);
protected:
virtual void startEditMode() = 0;
virtual void endEditMode() = 0;
virtual void abortEditMode() = 0;
virtual GUI::Rect getEditRect() const = 0;
virtual int getCaretOffset() const;
void drawCaret(bool erase);
bool setCaretPos(int newPos);
bool adjustOffset();
virtual bool tryInsertChar(char c, int pos);
protected:
string _editString;
bool _caretVisible;
int _caretTime;
int _caretPos;
bool _caretInverse;
int _editScrollOffset;
};
#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.14 2005-06-10 17:46:06 stephena Exp $
// $Id: ListWidget.cxx,v 1.15 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -417,10 +417,10 @@ int ListWidget::getCaretPos() const
{
char temp[10];
sprintf(temp, "%2d. ", (_selectedItem + _numberingMode));
caretpos += _font.getStringWidth(temp);
caretpos += _font->getStringWidth(temp);
}
caretpos += _font.getStringWidth(_list[_selectedItem]);
caretpos += _font->getStringWidth(_list[_selectedItem]);
return caretpos;
}

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: PopUpWidget.cxx,v 1.10 2005-06-08 18:45:09 stephena Exp $
// $Id: PopUpWidget.cxx,v 1.11 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -280,7 +280,7 @@ PopUpWidget::PopUpWidget(GuiObject* boss, int x, int y, int w, int h,
_selectedItem = -1;
if(!_label.empty() && _labelWidth == 0)
_labelWidth = _font.getStringWidth(_label);
_labelWidth = _font->getStringWidth(_label);
myPopUpDialog = new PopUpDialog(this, x + getAbsX(), y + getAbsY());
}
@ -372,7 +372,7 @@ void PopUpWidget::drawWidget(bool hilite)
// Draw the selected entry, if any
if(_selectedItem >= 0)
{
TextAlignment align = (_font.getStringWidth(_entries[_selectedItem].name) > w-6) ?
TextAlignment align = (_font->getStringWidth(_entries[_selectedItem].name) > w-6) ?
kTextAlignRight : kTextAlignLeft;
fb.drawString(_font, _entries[_selectedItem].name, x+2, _y+3, w-6,
!isEnabled() ? kColor : kTextColor, align);

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: PromptWidget.cxx,v 1.2 2005-06-13 02:47:44 urchlay Exp $
// $Id: PromptWidget.cxx,v 1.3 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -111,7 +111,7 @@ void PromptWidget::drawWidget(bool hilite)
#else
char c = buffer((start + line) * _lineWidth + column);
#endif
fb.drawChar(instance()->consoleFont(), c, x, y, kTextColor);
fb.drawChar(&instance()->consoleFont(), c, x, y, kTextColor);
x += _kConsoleCharWidth;
}
y += _kConsoleLineHeight;
@ -637,7 +637,7 @@ void PromptWidget::drawCaret()
char c = buffer(_currentPos);
fb.fillRect(x, y, _kConsoleCharWidth, _kConsoleLineHeight, kTextColor);
fb.drawChar(_boss->instance()->consoleFont(), c, x, y + 2, kBGColor);
fb.drawChar(&_boss->instance()->consoleFont(), c, x, y + 2, kBGColor);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

178
stella/src/gui/Rect.hxx Normal file
View File

@ -0,0 +1,178 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2005 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Rect.hxx,v 1.1 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
//============================================================================
#ifndef RECT_HXX
#define RECT_HXX
#include "GuiUtils.hxx"
namespace GUI {
/*! @brief simple class for handling both 2D position and size
This small class is an helper for position and size values.
*/
struct Point
{
int x; //!< The horizontal part of the point
int y; //!< The vertical part of the point
Point() : x(0), y(0) {};
Point(const Point & p) : x(p.x), y(p.y) {};
explicit Point(int x1, int y1) : x(x1), y(y1) {};
Point & operator=(const Point & p) { x = p.x; y = p.y; return *this; };
bool operator==(const Point & p) const { return x == p.x && y == p.y; };
bool operator!=(const Point & p) const { return x != p.x || y != p.y; };
};
/*! @brief simple class for handling a rectangular zone.
This small class is an helper for rectangles.
Note: This implementation is built around the assumption that (top,left) is
part of the rectangle, but (bottom,right) is not! This is reflected in
various methods, including contains(), intersects() and others.
Another very wide spread approach to rectangle classes treats (bottom,right)
also as a part of the rectangle.
Coneptually, both are sound, but the approach we use saves many intermediate
computations (like computing the height in our case is done by doing this:
height = bottom - top;
while in the alternate system, it would be
height = bottom - top + 1;
When writing code using our Rect class, always keep this principle in mind!
*/
struct Rect
{
int top, left; //!< The point at the top left of the rectangle (part of the rect).
int bottom, right; //!< The point at the bottom right of the rectangle (not part of the rect).
Rect() : top(0), left(0), bottom(0), right(0) {}
Rect(int w, int h) : top(0), left(0), bottom(h), right(w) {}
Rect(int x1, int y1, int x2, int y2) : top(y1), left(x1), bottom(y2), right(x2)
{
assert(isValidRect());
}
int width() const { return right - left; }
int height() const { return bottom - top; }
void setWidth(int aWidth) {
right = left + aWidth;
}
void setHeight(int aHeight) {
bottom = top + aHeight;
}
/*! @brief check if given position is inside this rectangle
@param x the horizontal position to check
@param y the vertical position to check
@return true if the given position is inside this rectangle, false otherwise
*/
bool contains(int x, int y) const {
return (left <= x) && (x < right) && (top <= y) && (y < bottom);
}
/*! @brief check if given point is inside this rectangle
@param p the point to check
@return true if the given point is inside this rectangle, false otherwise
*/
bool contains(const Point & p) const {
return contains(p.x, p.y);
}
/*! @brief check if given rectangle intersects with this rectangle
@param r the rectangle to check
@return true if the given rectangle is inside the rectangle, false otherwise
*/
bool intersects(const Rect & r) const {
return (left < r.right) && (r.left < right) && (top < r.bottom) && (r.top < bottom);
}
/*! @brief extend this rectangle so that it contains r
@param r the rectangle to extend by
*/
void extend(const Rect & r) {
left = MIN(left, r.left);
right = MAX(right, r.right);
top = MIN(top, r.top);
bottom = MAX(bottom, r.bottom);
}
/*! @brief extend this rectangle in all four directions by the given number of pixels
@param offset the size to grow by
*/
void grow(int offset) {
top -= offset;
left -= offset;
bottom += offset;
right += offset;
}
void clip(const Rect & r) {
assert(isValidRect());
assert(r.isValidRect());
if (top < r.top) top = r.top;
else if (top > r.bottom) top = r.bottom;
if (left < r.left) left = r.left;
else if (left > r.right) left = r.right;
if (bottom > r.bottom) bottom = r.bottom;
else if (bottom < r.top) bottom = r.top;
if (right > r.right) right = r.right;
else if (right < r.left) right = r.left;
}
void clip(int maxw, int maxh) {
clip(Rect(0, 0, maxw, maxh));
}
bool isValidRect() const {
return (left <= right && top <= bottom);
}
void moveTo(int x, int y) {
bottom += y - top;
right += x - left;
top = y;
left = x;
}
void moveTo(const Point & p) {
moveTo(p.x, p.y);
}
};
} // End of namespace Common
#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: TabWidget.cxx,v 1.5 2005-06-12 20:12:10 stephena Exp $
// $Id: TabWidget.cxx,v 1.6 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -81,7 +81,7 @@ int TabWidget::addTab(const string& title)
int numTabs = _tabs.size();
// Determine the new tab width
int newWidth = _font.getStringWidth(title) + 2 * kTabPadding;
int newWidth = _font->getStringWidth(title) + 2 * kTabPadding;
if (_tabWidth < newWidth)
_tabWidth = newWidth;

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.cxx,v 1.13 2005-06-10 17:46:07 stephena Exp $
// $Id: Widget.cxx,v 1.14 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -40,7 +40,7 @@ Widget::Widget(GuiObject* boss, int x, int y, int w, int h)
_flags(0),
_hasFocus(false),
_color(kTextColor),
_font((GUI::Font&)boss->instance()->font())
_font((GUI::Font*)&(boss->instance()->font()))
{
// Insert into the widget list of the boss
_next = _boss->_firstWidget;

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.15 2005-06-10 17:46:07 stephena Exp $
// $Id: Widget.hxx,v 1.16 2005-06-14 01:11:48 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -66,7 +66,7 @@ enum {
This is the base class for all widgets.
@author Stephen Anthony
@version $Id: Widget.hxx,v 1.15 2005-06-10 17:46:07 stephena Exp $
@version $Id: Widget.hxx,v 1.16 2005-06-14 01:11:48 stephena Exp $
*/
class Widget : public GuiObject
{
@ -109,8 +109,8 @@ class Widget : public GuiObject
bool isVisible() const { return !(_flags & WIDGET_INVISIBLE); }
void setColor(OverlayColor color) { _color = color; }
void setFont(const GUI::Font& font) { _font = font; }
const GUI::Font& font() { return _font; }
void setFont(const GUI::Font& font) { _font = (GUI::Font*) &font; }
const GUI::Font* font() { return _font; }
protected:
virtual void drawWidget(bool hilite) {}
@ -134,7 +134,7 @@ class Widget : public GuiObject
int _flags;
bool _hasFocus;
OverlayColor _color;
GUI::Font& _font;
GUI::Font* _font;
public:
static Widget* findWidgetInChain(Widget* start, int x, int y);