xuni: a Graphical User Interface Widget Toolkit

I've finally uploaded a reasonably recent version of xuni, my latest project. It's a GUI (Graphical User Interface) "library" (Widget Toolkit) for the SDL, written in C. (I hope to make it a library eventually, but right now it's just a program . . . .)

This is a very preliminary upload. It's the subversion version 73. There is no Windows executable, though there are 32-bit and 64-bit Linux executables. It's not even the absolute latest version, just the latest commit. Anyway, it should run under any platform, assuming you felt like downloading SDL, SDL_image, SDL_ttf, and SDL_gfx in order to compile it. I'll probably have a Win32 executable uploaded pretty soon. Meantime, Windows users can admire my screenshot. It doesn't do the parallax justice.

Textboxes and listboxes don't work very well, but buttons and (I think) checkboxes do. (Actually, checkboxes work in the latest version, but not this one. Too bad. You'll have to wait for the upgrade. ) You can press ALT-ENTER to toggle fullscreen, ALT-F9 to minimize the window, and different keys instead of clicking on buttons. For example, 'q' quits, at the main menu. I'm in the middle of dealing with themes, so there's lots of code that looks like it's doing things in a stupid way at the moment.

Other than that, xuni is pretty neat. It supports arbitrary screen modes, rescaling widgets and images and text to fit the new size. Its GUI data is in XML files (read via expat), so you can change the positions of the buttons etc without recompiling the program. (Have fun . . . positions are specified as percentages of the screen, i.e. 50 is halfway across the screen.) It has a really primitive "garbage collector", which is really just a reference counter. But at least it does catch some memory leaks, which you'll see if you run the program from the command line. xuni has a very simple expression parser, so you can even use 100/3 instead of 33.3333... in the XML resource files.

It's about 7,000 lines long, which is pretty large for one of my projects. Most of the code is well separated into different source files -- except for graphics.c! -- and nearly all of it is quite well modularized. (I didn't write resize.c, which is SDL_Resize; and it's actually not even used in this version.)

Anyway, have a look at xuni if you feel like it and tell me what you think. Feedback would be much appreciated . . . .

For example: is struct widget_t in graphics.h too unwieldy? Would a void* pointer be better? etc. . . .

I know I put my codeform thread in General Discussions, but I figured that this is a better place for this type of thread. Hopefully it will get some traffic in this forgotten corner of CBoard . . . .

dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

Oops . . . I forgot to get rid of that "-xx" after all. Oh well. I just fixed the page again.

Last edited by dwks; 01-24-2008 at 04:58 PM.

dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

Alright, I've uploaded xuni again. It's SVN version 79 this time, up from 73. It's very different. There's a very, very basic resource editor (./xuni) that doesn't even let you save, plus the old test program renamed to ./test -- although the old test program has been changed significantly. You can type a different theme name and that is actually loaded (try "shadow" and "alienglow round" and "bluesq"). You can type a new font name, and it is actually loaded (try "gui/PenguinAttack.ttf"). NASA images make the artwork look so much better. There are some bugs with it (click on the options->graphics menu, on nothing in particular), but it's pretty good.

I apologise that only a Linux 64-bit executable is uploaded at the moment. I'm going to get other versions as soon as possible.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

With either of the above archives, you'll still need to download the main archive at: http://dwks.theprogrammingsite.com/m...xuni-79.tar.gz
Just copy the contents of the lin32 or win32 archive into the root of the other archive, and run test-i386 or xuni.exe (which is really ./test, not ./xuni) instead of ./test (which is the 64-bit Linux version).

* Note: this archive only contains ./test, not ./xuni -- but ./xuni is only the very rudimentary alpha version of the resource editor, and not very interesting at the moment. This archive also contains all -- that I know of -- of the DLLs required to run xuni. So now, Windows users, try it out, because you shouldn't have to download anything else . . . besides the other archive, of course.

Also note that while I tested the 32-bit executable quite thoroughly, the Windows one was only tested (and even compiled!) under wine. You'll have to let me know whether it works or not under a native Windows environment.

dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

EDIT: the project seems pretty cool, I may want to join the project, but my C skills are lame so we will see.

EDIT2: Ran it from the CLI since I noticed that it does some output, finding all sorts of stuff now, attempting to consistently reproduce the error messages. Most have to do with attempting to deallocate null pointers, or freeing duplicate strings (is what the error messages say at least)

EDIT3: First bug report sucked because I didn't test it very well, it seems if you click anywhere but the buttons on the graphics options page you get full screen/windowed toggle.

I'm sorry I haven't been updating this page more frequently; I thought no one was interested. I have in fact fixed all the memory leaks that are reported by the internal garbage collector at the moment. And I'm aware of the click-on-options-graphics-panel-to-toggle-fullscreen bug. In case you're interested, it's caused by this:

In a likely misguided attempt to prematurely optimise how widgets are addressed, widgets are first loaded by name such as "options graphics/fullscreen", for example. Then, an enum value such as WID_GRAPHICS_FULLSCREEN (in options.c) is assigned to the widget matching this name. Finally, a pointer to the actual widget is found, and all of this information is stored in a widget_nameid_t. Then the widgets can be referenced by the enum values instead of by strings, which is presumably more efficient.

Anyway. The trouble is that each panel has its own array of widget_nameid_t's. This is to let different menus etc use their own enum values starting from zero -- otherwise, each enum value would have to be unique, and that would be annoying. But when a widget is clicked in, the enum value is returned; and yet, options.c has no way of telling whether the panel was clicked or the fullscreen checkbox was clicked, because both happen to share the same wids. (Widget IDentifiers.)

I should be able to fix this pretty soon -- the most plausible way to do it is to check all wids in options_perform_click() from the root element to the clicked element. That is, for the fullscreen checkbox, check for PANEL_OPTIONS_GRAPHICS and then WID_GRAPHICS_FULLSCREEN.

BTW, the latest version also has very nice textbox support and theme roundness . . . sorry I can't upload it at the moment, but I shall try to do so as soon as possible. Probably tomorrow by the very latest. The trouble is that I'm working on it for several hours every day, so even yesterday's version is going to be quite different from today's . . . .

Just out of curiosity, are you using Windows to test xuni? I did in fact test the Windows executable myself later on, so it's not important, but I'm just curious . . . .

[edit] 6,000th post! [/edit]

Last edited by dwks; 02-12-2008 at 07:22 PM.

dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

I'm interested, always have been since you showed it to me a few months ago.

However, my only 'annoyance' is that it's tied with SDL, ever considered removing the dependency for SDL, and support a few others? I think you were talking about doing that before... BTW have you losly based the API on Gtk? If not you could probably borrow a few ideas, I love Gtk and it's very easy to use. Also, being constructive have you thought about 'cleaning' it up a bit? -- You know a few comments here and there, such as

Normally I'd say 'brute force for the win', however you could simply chuck a timestamp on the end of the filename. Someone could seriously have 4000 screenshots, considered defining MAX_SCREENSHOTS instead at least .

[off-topic]
How are you finding 64bit Debian? I've thought about changing from OpenSuSE to Debian but need a bit of persuasion
[/off-topic]

News: I've uploaded xuni SVN version 80, with a win32 executable. (Sorry, no lin32 one yet. Let me know if you need it and don't feel like building it yourself.) I also separated the Doxygen documentation into a separate archive, because it was so large. Unless you want to understand the code, you probably don't need this. It's not very complete, anyway -- though font.c and memory.c are getting there.

As before, windows users, download the normal archive and the win32 archive, and extract them in the same place. The win32 executable was compiled with -g, so you can use a debugger on it now. I would appreciate it if someone could test this -- it doesn't work very well under my wine, even though the Linux-64 version does.

Yeah, tested on Windows XP 32bit. If this project were C++ based, I would be all over it but my C skills are so weak that I would be a complete noob playing with all of that.

Eh, it's not that different from C. Most of the code is just calling other functions of mine, anyway. About the only differences from non-object-oriented-C++ are declaring variables at the beginning of blocks and multiline comments. Syntax things like that.

Originally Posted by zacs7

I'm interested, always have been since you showed it to me a few months ago.

Ah yes, you got to see the prerelease version.

However, my only 'annoyance' is that it's tied with SDL, ever considered removing the dependency for SDL, and support a few others? I think you were talking about doing that before... BTW have you losly based the API on Gtk? If not you could probably borrow a few ideas, I love Gtk and it's very easy to use.

Actually, no. I haven't really based it on anything. I've never actually really used the GTK, nor the Win32 API, nor any GUI library, really, at least a non object-oriented one. If you have any specific comments on GTK+-ness, let me know . . . .

I have tried to keep xuni separated from the SDL more than my other projects. It's reasonably well separated. The main things I can think of at the moment are: TTF_Font is used in places -- it needs to be wrapped in a structure; SDL_Surface is used in a few places, though not very many; and some code, such as minimization, might not be supported in other libraries. If not, it could just be commented out. If I knew how to use another library I might port it. If someone else knows another library and feels like porting it, let me know what needs to be done to port it and I'll try to do it . . . .

Actually, I have a few questions about GTK and other libraries. How are widgets referenced? (You know, if you want to add a line to a specific listbox, how do you say "that listbox"?) And how are callback handlers implemented? (One for every widget, probably.) Finally, what's in the widget structure; how are different widgets represented; and how are widgets stored internally? (I'm not expecting anyone to know this, just thinking out loud . . . .)

Also, being constructive have you thought about 'cleaning' it up a bit? -- You know a few comments here and there, such as

Code:

void rescale_checkbox(struct widget_t *widget) {
}

... why that's blank!? :\

Aye, it's sadly lacking in documentation. Some of my more recent code -- like memory.c -- has reasonably complete documentation, but the old code . . . nope.

As for why it is blank: it's a callback function. It doesn't have to do anything, but it's more convenient for rescale_widget() to have an empty function to call.

Did you notice the -Wno-unused-parameters? That's because of all my callback functions . . .

Side note: -Wno-endif-labels is required, after -pedantic, for the SDL 1.2.12 that currently comes with Debian Lenny. Someone put something like "#endif // whatever"; in ANSI C mode, it doesn't recognize that comment, and then sees extra characters after the endif. I haven't reported this yet, feel free to do so if you're so inclined. A simple /**/ comment instead would fix everything. It's very annoying -- with the number of times that file is included, you can easily get several thousand lines of warnings about it. Hence this particular warning flag.

Normally I'd say 'brute force for the win', however you could simply chuck a timestamp on the end of the filename. Someone could seriously have 4000 screenshots, considered defining MAX_SCREENSHOTS instead at least .

Yes, I copied that function from a much older program of mine because I was too lazy to re-write it.

[off-topic]
How are you finding 64bit Debian? I've thought about changing from OpenSuSE to Debian but need a bit of persuasion
[/off-topic]

It's very nice. I have no specific good or bad things to say about the 64-bit version of Debian; I never use 64-bit specific programs, and don't program on a low enough level for it to matter that much. I do have 32- and 64-bit versions of Debian installed, but on vastly different computers, so I couldn't say if the 64-bit version is more efficient or anything, though I imagine it is.

There's only one thing about it: it can be difficult to compile or run 32-bit programs on a 64-bit system. But if you have a constant, fast internet connection, as I do not, then it's no hassle to download the right 32-bit libraries. The Debian package manager will do it automatically.

But Debian in general . . . highly recommended. It's really nice. The package management means you hardly ever break anything when you upgrade, and uninstalling things is very easy. The number of packages is astounding, and the default installation is very complete. The number of times I've gone to install something off the internet, only to find that there is a package for it, or even that I already had it installed without realizing it . . . .

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

On another note, this 80 version also fixed that click-on-panel,-get-fullscreen-toggle bug. It's just a temporary one, probably, but it works. [/edit]

Last edited by dwks; 02-13-2008 at 06:19 PM.

dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

Actually, I have a few questions about GTK and other libraries.
How are widgets referenced? (You know, if you want to add a line to a specific listbox, how do you say "that listbox"?)
And how are callback handlers implemented? (One for every widget, probably.)
Finally, what's in the widget structure; how are different widgets represented; and how are widgets stored internally?
(I'm not expecting anyone to know this, just thinking out loud . . . .)

In GTK, you basically keep pointers to GtkWidgets (ie, 'that listbox') and do what you will.
Take an editbox for example,

... what would appear to be a memory leak is in-fact not. In-between each line you could add some callbacks to each editbox, some text, add them to a dialog (or a container).

Seriously have a look at http://library.gnome.org/devel/gtk/stable/ (Being a Debian man, I hope you're also a Gnome man ). I'd suggest doing a few Gtk programs, get the hang of it then you'll probably get a lot of good ideas for xuni.

I've uploaded xuni SVN version 81. There were quite a few changes in this release, notably modularization of widget freeing code, conversion of font into a widget*, re-write of the Windows Makewins, and a re-write of save_screenshot(). All memory leaks that I know of are fixed. Note that the theme roundness checkbox is in a monospace font.

This version also contains Windows executables for the editor as well as ./test; and linux 32-bit exeutables as well. In separate archives, of course. You'll need to get the shared libraries yourself in order to run the linux executables.

Actually, I have a few questions about GTK and other libraries.
How are widgets referenced? (You know, if you want to add a line to a specific listbox, how do you say "that listbox"?)
And how are callback handlers implemented? (One for every widget, probably.)
Finally, what's in the widget structure; how are different widgets represented; and how are widgets stored internally?
(I'm not expecting anyone to know this, just thinking out loud . . . .)

In GTK, you basically keep pointers to GtkWidgets (ie, 'that listbox') and do what you will.
Take an editbox for example,

Since everything is a GtkWidget, it's possible to use them everywhere. For example, you can put editbox widgets in menus... Easily too, no different than placing a label.

I have it set up in a similar way with xuni, except that the structure (struct widget_t) doesn't need to be casted or anything. Instead, it has a union of pointers to the different widget-specific data structures. I've been hoping that this will let me add images etc to listboxes, but it doesn't work quite yet . . . .

For example, if you did want to change the text of an editbox (aka entry), you'd simply:

Vote of confidence appreciated. It looks very simple compared to xuni . . . probably because the positions for each of xuni's widgets has to be specified. I've started implementing WIDGET_PACK_TOP, but that's only for listboxes so far.

That's another thing I want to do with xuni: name all of the public functions xuni_*, to avoid naming collision if possible.

More importantly Gtk cleans up for you (you don't explicitly have to delete a widget) -- you can do:

... what would appear to be a memory leak is in-fact not. In-between each line you could add some callbacks to each editbox, some text, add them to a dialog (or a container).

Yes, xuni does clean up for you too, though you can't just add callbacks for every widget. That was something I wanted to avoid, for some reason (probably didn't want millions of really short functions), so you can just add a panel callback which handles every widget for that panel. I think I will change this, however. It's making things unnecessarily complicated.

Seriously have a look at http://library.gnome.org/devel/gtk/stable/ (Being a Debian man, I hope you're also a Gnome man ). I'd suggest doing a few Gtk programs, get the hang of it then you'll probably get a lot of good ideas for xuni.

Perhaps I shall, we'll have to see . . . BTW, I already have the GTK+ development libraries installed and a tutorial downloaded, because I had much the same thought a while ago.

And yes, I do use Gnome almost all of the time. I prefer some KDE programs, however. So I have a weird mix of programs running: gnome-terminal, kdevelop, meld, kdesvn, nautilus, kompare, epiphany, . . . .

I take it you use Gnome? What IDE do you use? KDevelop is very nice . . . I tried downloading Anjuta (and Geany) a few days ago because I saw them in someone's signature, but neither is as nice as KDevelop. Geany is a nice lightweight editor, though; nicer than Kwrite or Kate.

dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell