[Scummvm-devel] New GUI code
Max Horn
fingolfin at marblehorse.org
Thu Jul 4 08:10:06 CEST 2002
As most (all? :-) of you will agree, the current GUI code in ScummVM
is quite crappy.... we just had quite some discussion about this in
#scummvm and decided to scrap it and rewrite it from scratch
(possibly keeping a future GUI that allows in-game selection of the
game to play and other nice stuff). Both me and Endy wanted to start
working on it, so I figure it's better if we first agree on what it
should be like .
So here are my thoughts to it. First some important requirements I'd
like to be met:
* Properly seperate the logic of each dialog into seperate
classes/functions (the current GUI mixes them all into the same code)
* OOP based: one class "Dialog", from which we derive
"SaveLoadDialog", "OptionDialog" which carries the control logic for
each dialog
* Seperate the view logic (how to draw a button if it is clicked?)
from the control logic (what happens if the button is clicked?). This
can be achieved by having a lightweight Widget class (and subclasses)
that perform the drawing and some other common things (like a
CheckBoxWidget would simply toggle itself when clicked).
* proper nesting of dialogs must be possible. That probably involves
a "dialog stack" of some kind but overall shouldn't be too hard
* small memory footprint should be kept in mind
* everything still should be simple to use and extend. Like, don't
force us to subclass Widget whenever we want to add a new button;
instead, the ButtonWidget class should be designed flexible enough to
easily allow for most uses w/o any additional subclass.
OK, and here is how I envision how this could be done:
Each Dialog contains "Widget" objects (that's not really much
different from what we have). There are different Widget subclasses,
for various purposes (ButtonWidget, CheckBoxWidget, StaticTextWidget,
SliderWidget, etc.). They all share some API, but also can have class
specific API.
All widgets share some properties:
* can have an ID assigned to it, that can be used by the parent
dialog to identify the widget (e.g. distinguish OK from Cancel
button).
* knows how to draw itself
* has a method to respond to clicks on it (which can just do nothing
by default)
* a "boss"/"owner"/"parent", probably just always the dialog it is
contained in.
* a set of flags, to be defined, but among them: dis/enabled. others
could be: wantPeriodicTickle, wantKeyboardEvents, etc.
Widgets can have some own intelligence: e.g. a CheckBoxWidget, when
clicked, may toggle itself. A ButtonWidget can have a command ID (an
Uint32), and when it's clicked, it will send this ID to its boss.
Making this Uint32 allows us to use human readable constants, like
'SAVE' or 'LOAD' for the command IDs
OTOH a widget can be "dumb", e.g. a StaticTextWidget does nothing
when it is clicked
Widget also can request to be be periodically notified, e.g. so they
can animate.
Event handling is starts in the Gui class. It will first determine
the top most dialog. Then depending on the event it calls the
handleClick/handleKey method of that top dialog.
These methods in turn provide default implementation: handleClick()
by default just determines the widget that was clicked and calsl the
handleClick method of that. That will be sufficient for 99% of all
uses but can be customized if necessary this way. handleKey() will by
default only handle "hot keys", or if there is an active edit field,
pass the key to that edit field instead.
This could amount to classes similar to these:
class Widget;
class Dialog {
Widget *_firstWidget;
public:
void handleIdle(); // Called periodically
void handleClick(int x, int y, char button) // left/middle/right
{
Widget *w = findWidget(x,y);
if (w)
w->handleClick(button);
}
void handleKey(char key, int modifiers); // modifiers = alt/shift/ctrl etc.
void handleCommand(uint32 cmd);
protected:
Widget* findWidget(int x, int y); // Find the widget at pos x,y if any
}
typedef enum {
WIDGET_ENABLED,
WIDGET_WANT_TICKLE,
} WidgetFlags;
class Widget {
Dialog *_boss;
Widget *_next;
int16 _x,_y;
uint16 _w,_h;
uint16 _id;
uint8 _hotkey;
WidgetFlags _flags;
public:
Widget(Dialog *boss, int x, int y, int w, int h);
void handleClick(char button);
void draw();
};
class ButtonWidget : public Widget {
uint32 _cmd;
public:
void setCmd(uint32 cmd);
void handleClick(char button) { if (_flags & WIDGET_ENABLED)
boss->handleCommand(_cmd); }
}
Cheers,
Max
--
-----------------------------------------------
Max Horn
Software Developer
email: <mailto:max at quendi.de>
phone: (+49) 6151-494890
More information about the Scummvm-devel
mailing list