Not logged inGosu Forums
Forum back to libgosu.org Help Search Register Login
Up Topic Gosu / Extending Gosu / [C++] GosuWidgets
- By Quit Date 2009-06-11 20:20 Edited 2009-06-19 18:48
GosuWidgets is a simple way of creating an own "UI" for Gosu. It actually supports Images, Buttons, Cursors, Texts (static and 'dynamic') and inputs (for text). Everything is in its namespace 'Widgets'. Every widget can fire callbacks (boost::function, use boost::bind to bind them), some are useful, others aren't. An (stupid but working and documentated...!) example is included.

MEET THE WIDGET:
The widget is the basic class for this whole thing. It can be just a container, means it has no x/y/z/width/height values and (itself) does not trigger any events but it could also be an "invisible" layer of area that triggers onHover/onBlur/on(Left|Right)Click (as used in SimpleButton). It's recommended to have a WidgetPtr defined as rootWidget in your Window-class. Widgets can have children, which can have children, which ..., you see my point. If you hide the parent the children won't be drawn (unless they're in another, visible widget, which isn't recommended). You can mix all different z-Levels into a widget. They do *not* respect that, i.e. having two visible and active widgets at the same position with same size will fire the events twice, for both widgets (for menus etc: Disable the whole UI, which you put into another widget than the menu, and enable the menu then).

MEET THE IMAGE:
Maybe the most used widget. Like a widget but it can (or better said: should) have a shared_ptr to a Gosu::Image, which is drawn. This class accept many attributes Gosu provides, such as different color, different alphamode or "stretching factors".

MEET THE SIMPLEBUTTON:
SimpleButton is (somehow) an example how you can easily build something new out of the basic widgets. It always requires an Widgets::Image-ptr to the default (= not hovering, not disabled) widget. If an hover widget is defined, it will be shown when the cursor moves over it. If a disabled widget is defined, it is shown when the widget is disabled (it doesn't matter if the cursor is above it or whatever). You should always bind to the SimpleButton, not to its Image-Widgets.

MEET THE SIMPLECURSOR:
Well, takes an Image and a z-Position and is doing a great job as cursor.

MEET THE TEXT:
"Dynamic text", based on Gosu::Font. This widget does not trigger onHover when the mouse is over a letter, just when it is over the rect that the text produces. Can have a different color, alphamode, factors or relations.

MEET THE STATICTEXT:
StaticText, quite the same as Text, except it is writing its data to an Gosu::Image, which is somehow "caching". Faster than Text if not changed very often. If your text changes often, go and use Text instead.

MEET THE TEXTINPUT:
TextInput, allows you to simple let the user enter something. You can define textcolor, the color of the caret (the, usually, blinking thing, which isn't blinking here because that would be annoying) and the color of the selection (passing Gosu::Colors::none if you don't want that). This kind of widget has a new callback: onReturn. It's fired as soon as the user presses the return ('Enter') key (Gosu::kbReturn).

The whole thing is thought to be built as a lib and requires, of course, Gosu-Headers (to build the lib it shouldn't be necessary to link against the libs of Gosu though) and boost. I don't know if it's already out there, may you will need an SVN version of Gosu to build it correctly.

The whole lib hasn't been tested and I'm quite sure they are some bugs around because I simply don't use that silly stuff I put in somehow ("setAlphaMode"?!). The code is a bit messy, I haven't cleaned it yet and I guess some things are only settable in the constructor. If you find something like this, tell me. I will fix it.

What I've tested are mostly basic things ("create everything in the Window-constructor and change only things like the text or something like that") under WinXP 32bit SP3 which is working quite well. All headers are documentated, the c++ files aren't. The example contains a C++-file, the images and the Inkscape .svg they were created with.

Don't expect crazy things like the things the guys do in the ruby section about UIs - it's not thought to "imitate" the OS or to have everything. I think there will come more things in the future, like some kind of a list (but mostly only when I require it in a application/game).

Set your include path to there where the .sln is (you should include 'GosuWidgets/GosuWidgets.hpp' for example), if you want to use it as lib the MSVS2008 project will build it into libs/.

Well. Have Fun.

Update 19.06.2009
Now using shared_ptr<Widget> (aka WidgetPtr) for almost everything. Using widget[5] is not possible anymore, use ->getChild to get the pointer to that child. However, the [] for a simple Widget will still return Widget&. Some few fixes with canHover (unsigned-thingy) and SimpleButton.
Attachment: GosuWidgets.zip (0B)
- By Maverick Date 2009-06-11 20:43
Kewl. I'll check it out when I gotz time.
- By banister Date 2009-06-11 22:57
nice work! :) do you have any screenshots of working widgets?
- By Quit Date 2009-06-12 09:57
Since a screen wouldn't show much more than just drawing Gosu::Image / Gosu::Font, no. I think the name could be miss interpreted, this is *not* for some kind of sidebar.
- By jlnr (dev) Date 2009-06-16 14:21
Okay, bundled criticism from my first attempt at integrating them into my game:

• SimpleButton is a bit weird to use. Why are its states Widgets again? I think I'd prefer subclassing it to show some Gosu::Images, but I guess I can just do that, so no problem :)
• StaticText requiring a shared_ptr<Font> is evil when it just needs it to extract the font name and height. Even if you insist on the existence of a font (I happen to have it), Font& would be nicer
• As the root of the class hierarchy, Widget should be boost::noncopyable to avoid slicing and double-freeing.
• I don't always have a Gosu::Window& in my code. The game uses one, the editor doesn't (yet). What are you using it for other than the mouse position?
• Beware, Input::mouseX() can be negative ;)

I'll leave it in my codebase for now and retry it in a few iterations :)
- By Quit Date 2009-06-17 10:04

>• SimpleButton is a bit weird to use. Why are its states Widgets again? I think I'd prefer subclassing it to show some Gosu::Images, but I guess I can just do that, so no problem :)


Because of the Design. Since it's just a "wrapper" for three other Widgets (and in my local, newest version) they really can be any widget, you could also do Text-Things - but I think that there will be something like "SimpleColorTextButton", or something like that.

>• StaticText requiring a shared_ptr<Font> is evil when it just needs it to extract the font name and height. Even if you insist on the existence of a font (I happen to have it), Font& would be nicer


Text requires a shared_ptr to a Font, so does StaticText. I don't know if you could set another font anyway, I'm changing the font in a program of mine for example. Also, I don't know how the memory management with many Widgets with the same font-reference would be (you have to keep the Font in your Window-class?)

>• As the root of the class hierarchy, Widget should be boost::noncopyable to avoid slicing and double-freeing.


It's not the root. You can put a Widget into a Widget into a Widget into a Widget, as often as you like, for 'layers' or better said 'groups'. Also, since everything in the Widget-things is using shared_ptr now, that shouldn't be a problem.

>• I don't always have a Gosu::Window& in my code. The game uses one, the editor doesn't (yet). What are you using it for other than the mouse position?


Custom widgets. Because you can (and are allowed/expected to) create new Widgets, based on the default widgets, you may require something from the Window. I thought about storing the window in a weak_ptr or something like that. However, if you use the widgets I expect you to have an instance of Gosu::Window or a childclass. Since updating/drawing requires this variable anyway... Or did you thought about the StaticText::setText-thing?

>• Beware, Input::mouseX() can be negative ;)


That's a fossil. Widgets were unsigned int with x/y/height/width once. It's fixed in my local version.
- By jlnr (dev) Date 2009-06-17 14:14
OK, I think I should clarify some points from my quick feedback:

> Text requires a shared_ptr to a Font, so does StaticText. I don't know if you could set another font anyway, I'm changing the font in a program of mine for example. Also, I don't know how the memory management with many Widgets with the same font-reference would be (you have to keep the Font in your Window-class?)


So the way I understand it now, StaticText uses the Font just to get the font name and height. Couldn't it do that in the constructor and then forget about the Font& altogether afterwards? (Haven't used Text, sounds like it actually uses the Font dynamically)

> It's not the root. You can put a Widget into a Widget into a Widget into a Widget, as often as you like, for 'layers' or better said 'groups'. Also, since everything in the Widget-things is using shared_ptr now, that shouldn't be a problem.


But it's still the root of the C++ class hierarchy ;) And classes meant to be derived from should always be noncopyable IMHO. Otherwise, the compiler will allow this: Widget a = otherWidget;, something that can happen implicitly if you forget a & somewhere, but which will crash at runtime.

> Custom widgets. Because you can (and are allowed/expected to) create new Widgets, based on the default widgets, you may require something from the Window.


Yeah, but if these widgets need anything from a Window (or MyWindowSubclass, or MyCustomUnrelatedClass), couldn't they take it in their constructors?
- By Quit Date 2009-06-17 18:20

>So the way I understand it now, StaticText uses the Font just to get the font name and height. Couldn't it do that in the constructor and then forget about the Font& altogether afterwards? (Haven't used Text, sounds like it actually uses the Font dynamically)


Could, yes. But I think you may want to get the Font again and this way, you can get it.

>But it's still the root of the C++ class hierarchy ;) And classes meant to be derived from should always be noncopyable IMHO. Otherwise, the compiler will allow this: Widget a = otherWidget;, something that can happen implicitly if you forget a & somewhere, but which will crash at runtime.


OK, will do that next time.

>Yeah, but if these widgets need anything from a Window (or MyWindowSubclass, or MyCustomUnrelatedClass), couldn't they take it in their constructors?


And then save it as? Reference? shared_ptr?
Up Topic Gosu / Extending Gosu / [C++] GosuWidgets

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill