Friday, August 08, 2008

Fun with benchmarks

I was looking into optimizing the new UTF-8 string class in wxWidgets 3 and I had to decide about the most efficient way to cache information about mapping UTF-8 positions into byte offsets. So I wrote a simple benchmark to measure the overhead of using the thread-specific variables compared to using normal globals.

To be precise I wrote a simple loop updating the variable (which is, of course, not at all realistic but that's micro benchmarks for you) using the following methods:
  1. Direct global variable access

  2. Using compiler thread-specific variables support (__thread for g++ and __declspec(thread) for MSVC)

  3. Using OS-specific TLS support (Win32 TLS or POSIX threads TSD)

  4. Using boost::thread_specific_ptr


The results were somewhat surprising, although also encouraging: under both Win32 (x86) and Linux (amd64) platforms the first two ways were the fastest. The OS functions were 3 times slower under Windows and 5 times slower under Linux. Boost implementation was disappointing, at least from performance point of view as it was 2 times slower than OS functions, making it 6 or 10 slower than the fastest version. This is bad news as I hoped to avoid writing a wxWidgets-specific TLS class and just use Boost version but this doesn't seem a good idea for performance-sensitive code.

But the biggest surprise, at least for me, came from the comparison of the first two approaches: using compiler support for thread-specific variables turns out to be faster than using plain old globals. This was so unexpected that I even checked the disassembly to see if I wasn't missing anything and it turns out that gcc generated exactly the same code for both versions except that in the thread-specific version it used FS-relative addressing to access the value. For MSVC the code wasn't quite the same but it also used FS for thread-specific variable. So it looks that under both x86 and amd64 using FS register is actually faster than using normal absolute addressing.

In any case, it's good to know that having thread-specific variables brings no performance loss when they are supported by the compiler. Of course, my benchmarks are very specific and, last but not least, they don't have any thread running. However I think the results should be broadly true for more realistic code which I'm going to benchmark once the real caching implementation is written.

Tuesday, May 27, 2008

What you can learn by reading Slashdot

Slashdot had an interesting post today linking to a project which studied the degree of separation between different Wikipedia articles. Possibly moved by the subconscious feeling of shame due to the fact I was reading Slashdot instead of working on wx I decided to check what does it have to say about the closeness of wxWidgets to paradise. And the result was:

Shortest path from wxwidgets to paradise
WxWidgets
November 27
Eastern Orthodox Church
Paradise
3 clicks needed

I say we're pretty close to the goal! Even better, while we're only 3 clicks removed from Qt too, Qt itself is 1 click further from paradise than wx is. They have some work to do (but then maybe this is what they're doing, instead of reading Slashdot...)

Tuesday, April 29, 2008

Google Summer of Code 2008 and wx

Since a couple of years, there is something we really look forward to each spring. I'm not speaking about blossoming flowers and all this nonsense, of course, but about the Google summer of code. This is a wonderful program which gives many open source projects, including wx, an opportunity to work on some projects which wouldn't be started otherwise because they require initial investment beyond what we can normally afford and attract new contributors to the project.

So it's great to be part of GSoC again, even though -- let me perform some ritualistic whining -- we got only 2 slots this year while we had 3 of them during the previous ones. I'm not sure why did this happen (probably because ever more projects take part in the program and even Google's budget is not unlimited) but it might be related to the relatively few students proposals we received this year (about a dozen and 5 of them about the same project). Of course, there were still some worthy proposals which got cut (at least the third and the fourth one) but I still think that one of the goals for the next year should be to prepare more interesting projects and try to attract more interest -- and if you have any great ideas, please let us know or just add them to this wiki page.

Of course, while wxWidgets itself has 2 slots, there are other wx-related projects undertaken by the other organizations. wxPython has 3 more slots, Audacity uses one of its 5 for writing new draggable sizer classes which could hopefully be reused by other projects and even Perl has wxCPANPLUS project using wx. So the life is still good.

But it will be even better once our 2 projects are completed. Personally I'm mostly excited about the "duller" one of them -- the bug fixing one by Marcin Wojdyr. We currently have an indecent number of open bugs (~1600 at the last count) in our bug tracker and this is way too much, in fact there are so many of them that even finding an existing bug is difficult. This is partly due to the extremely poor SourceForge bug tracker UI so one of the first steps in this project will be migrating all our bugs and patches to Trac. And then, of course, fixing some of them. This is probably not as exciting as writing some great new control but almost certainly is more useful to wxWidgets and will do more for our users so, once again, we're really glad to have the opportunity to do it during this GSoC!

Monday, December 10, 2007

Programming for the Eee PC with wxWidgets

There has been a lot of fuss about the Asus Eee PC in the last few months and Asus have clearly pressed the right consumer buttons with their cheap Linux subnotebook. No doubt there will be many more machines in this format in the future, representing a market of many millions, so it’s an attractive target for developers. Fortunately for wxWidgets programmers, it’s pretty straightforward to adapt wxGTK applications to the requirements of the Eee PC. This consists mainly of two tasks: fitting windows and dialogs onto the 800x480 screen, and distributing the application in a Xandros-friendly package (a .deb).

Here’s an example of one of my wxWidgets applications (Writer's CafĂ©) running on the Eee PC:

Should I port my application?

First, a few observations about the Eee PC from the perspective of a developer wondering whether his or her application would be a good match for it. What kind of users are we talking about? Well, it’s such a general-purpose machine it’s hard to narrow it down, but it obviously has appeal to children and women who generally have smallish hands and could more easily adapt to the diminutive keyboard. But at least for casual use, most people could get used to the form factor, and some tasks don’t need much keyboard use, such as browsing, listening to music or reading e-books.

There are plenty of reports of people using the Eee PC for substantial work – it’s good for journalists, photographers, students, and business travellers (although the limited battery life could be a problem on long trips). It could be useful for accountants visiting client premises, for example, or engineers often on the road. The Eee PC enthusiasts’ forums are full of examples of both business and home use. Unlike smaller devices such as the Nokia N series of internet tablets, or Windows Mobile devices, the usable keyboard means that this machine has the potential for running a fuller range of applications, albeit for shorter periods of time than on a larger computer (due to comfort and battery limitations). The high level of compatibility of files and applications between conventional PCs and the Eee PC increases the appeal of performing regular PC work on a highly mobile machine.

Apart from the small keyboard, the main limiting factor is probably not so much the slower processor as the low-resolution screen. However, people are getting used to it and one user has reported that they find a regular screen too big now, and they have to emulate the Eee PC resolution on their desktop!

So, the answer to the question, “Is it worth porting my app to the Eee PC?” is probably going to be “Yes” in most cases. If you’re already writing wxGTK applications, it’s almost a no-brainer. Apart from anything else, there’s a “cool factor” in showing your applications running on the gadget.

Starting wxGTK development

If you are targetting the Eee PC running Linux, then you will use the wxGTK port (wxWidgets on top of GTK+ 2). As a bonus, your work in tailoring applications to the Eee PC display size will also pay off when recompiling your applications for Windows, to target Eee PC running the Microsoft operating system.

There are many combinations of working methods and tools for writing wxGTK applications. I do most of my development on a Windows PC, and compile the apps on Debian Edge running on the same machine (using VMware) for deployment on Linux. The resulting wxGTK application runs on most modern Linux distributions, which all tend to come with the necessary GTK+ 2 libraries regardless of desktop environment in use. The Eee PC’s Xandros is no exception. The .deb archive I distribute for use on standard GNOME and KDE Linux desktops is the same used for the Eee PC, and the applications dynamically adapt to the display in use. Obviously if you’re going to deliver on an Eee PC it helps to have one for testing purposes – although you can do a certain amount of testing by reducing the resolution, you still need to check the installation and performance on real hardware. Having said that, debugging wxGTK-specific issues can mostly be done within the comfort of a spacious Linux desktop using a distro such as Debian, Ubuntu or Xandros.

As for all wxGTK development, you need the GCC compiler (available preinstalled on most Linux distributions), and the GTK+ 2 development libraries (search for the gtk2.0-dev package). For decent printing support, don't forget to install the libgnomeprintui2.2-dev package also before configuring and compiling wxWidgets. Get the latest version of wxWidgets in the 2.8 series, for example wxGTK-2.8.7.tar.gz at the time of writing. You can use plain old Emacs and gdb to write and debug apps, but you may wish to consider IDEs such as Anjuta and Code::Blocks, and for generating code, dialog editors/RAD tools such as DialogBlocks and wxDesigner. Basically, anything that applies to wxGTK development also applies to Eee PC/Xandros development.

If you decide to use DialogBlocks, both to generate first-cut application skeletons and to help generate detailed dialogs, DialogBlocks will help you compile wxWidgets as well as your own app. Create a project (or try one of the samples), select the configuration you want to use, set the wxWidgets path, and DialogBlocks will first compile wxWidgets before compiling the project.

Adapting to the low resolution screen

The following is applicable to any device with a low resolution, so it’ll help you prepare for future Linux-based mobile devices too. It’s also applicable to other operating systems that wxWidgets supports, such as Windows and Mac OS X.

Your first step might be to add a full-screen mode. This is straightforward in wxWidgets, using the wxTopLevelWindow::ShowFullScreen function. The usual shortcut key for this is F11. From wxWidgets 2.8.7, menu accelerators on wxGTK are still active even if the menubar has been removed, so the user can press F11 to restore the window to normal viewing. ShowFullScreen can retain your toolbar, or hide it, depending on your application’s requiremements. If your main window still uses a lot of space for non-essential control windows (for example tabs and extra toolbars), then you might consider reparenting the editing window to a new frame and showing that full-screen, subsequently reparenting the window back when the user returns the window to normal.

Note that currently on wxGTK, the toolbar is restored when returning to normal view, even if the toolbar was previously hidden. You may need to add some extra logic to hide the toolbar explicitly.

Also note another quirk if you’re planning to show a frame full-screen when the program starts – the window may show in its initial size momentarily, then resize to fit the screen. You can mitigate this effect by making the initial window size very small, say wxSize(1, 1).

You may find you made assumptions about screen size when designing elements of your main screen. Palettes, tabs and toolbars can look rather huge and leave little space for editing, especially when even a maximised main window has to compete with a largish title bar at its top, and a taskbar at the bottom of the Eee PC desktop. Here are some ideas for further adaptations:

  • Add an option for small toolbar icons if your toolbar currently has large ones. Also make it possible to switch toolbar labels off, and remove inessential tools for low-resolution displays.
  • Add an option to hide the toolbar and status bar.
  • Use wxAuiNotebook for a tabbed interface, and set the notebook font to a couple of sizes smaller than normal. Native GTK+ tabs can be rather large.
  • Use wxWindow::SetWindowVariant to set a smaller font size for panels.
  • Use a wxChoicebook instead of wxNotebook for a tabbed palette, to reduce the vertical size requirement.
  • Maximise the main window by default on a small screen.
  • Make sure there are accelerators for important operations, so that the program is still usable when full-screen and without a toolbar or menubar.
  • Consider a vertical toolbar or other control window to the left or right of your main editing area, since vertical space is in shortest supply.
  • Use a wxScrolledWindow for larger panels containing controls. You can just replace the wxPanel base class with wxScrolledWindow, and call SetScrollRate to enable the scrollbars.

I have a function I use to test for a small screen – HasSmallScreen – which I use to make UI choices as the windows are created. You can have a balance of customisable and non-customisable choices: you might want everything to be under user control, or you might not want to burden the user with so many choices. But the defaults should reflect the best choices for the display resolution.

Making your dialogs fit

Probably the area you’ll find in need of most work is your application’s dialogs. You may find that some or all of them they disappear off the edge of the screen, especially vertically. There are several techniques you can apply here. Firstly, you can set the initial size of individual controls (such as listboxes) to be smaller when a small display is detected. You can also use wxWindow::SetWindowVariant, and simply omit certain controls and explanations from the dialog. You can do this by creating all elements as usual, but hiding some of them before showing the dialog, for example:

GetSizer()->Show(m_description, false);

In DialogBlocks, you can make sure the control and its sizer parent both have member names, and then before the end of CreateControls() write something like:

m_innerSizer->Show(m_furtherInfo, false);

You may find that after these adjustments, and others including dividing up the dialog into pages, your dialogs will fit. If not, you can take more drastic action using scrolled windows.

To make an ordinary custom dialog scrollable, add a wxScrolledWindow under the top sizer, add a sizer to the scrolled window, and place the main controls under that sizer. Keep the OK and Cancel button row under the dialog’s main sizer so only the main content of the dialog scrolls, leaving the OK and Cancel buttons accessible at all times. Initially, don’t make the scrolled window scrollable. If you are using DialogBlocks, set PPU X and PPU Y to zero and ensure “Fit to content” is checked and also that the wxNO_BORDER and wxTAB_TRAVERSAL styles are checked. When you have done this, the dialog should behave exactly as before, when wxSizer::SetSizeHints is called and the dialog shown.

Now you need to check whether the dialog size is the same or more than the available desktop client size. wxSizer::Fit (called by wxSizer::SetSizeHints) attempts to restrict the dialog to the available space, so you need to assume that if one or both dimensions are the same as the desktop dimensions, the dialog was too big and has been resized. If the whole dialog couldn’t fit, you need to enable the scrolled window’s scrollbars and resize the dialog, taking into account the dialog titlebar which wxWidgets 2.8 doesn’t currently do itself.

A simple example built with DialogBlocks is available as a zip file and as a tar.gz file from http://www.anthemion.co.uk/wx/largedialog.tar.gz or http://www.anthemion.co.uk/wx/largedialog.zip. You can use the demo version of DialogBlocks to build and run the sample, or you can adapt the makefile as you see fit, or you can simply copy and paste the relevant code for your own applications. The images below show the dialog first on a regular-sized Debian desktop (no scrollbar), and secondly on a 640x480 display (a vertical scrollbar appears).


The function that does the work is wxFitWithScrolling, in mydialog.cpp, which you can use with any dialog that has a scrolling part. Use it instead of wxSizer::Fit or wxSizer::SetSizeHints.

What if you have a lot of dialogs, and don't want to spend time customizing them? No problem - just replace wxDialog with wxScrollingDialog, a class that rejigs an existing hierarchy to keep the standard buttons shown. You can download the class here.

Distributing your application

While it’s best to create a .deb archive, you could also distribute a tarball. For a shortcut to making Debian archives, see checkinstall. For creating a .deb from scratch, see for example here and here.

The .deb or your installation script should also install desktop files and MIME type files. These are standards documented by Freedesktop.org in particular the .desktop file standard. When you install your .desktop files and icons into the appropriate place, and specify the application category, the KDE or GNOME desktop environment will know where to put your application’s shortcut(s) on its menus. However, most people may be using the standard IceWM window manager – the old version in use on Xandros doesn’t follow Freedesktop.org standards and you will need to add the ability to enable the Start menu and add your application’s menu items. I do this with a script that’s included in my application files, so the user can run the script to complete the installation. It’s separate, in case the user isn’t running IceWM. The script creates local IceWM preferences and enables the Start menu; then it appends an entry to the menu file if it’s not already there. The user should reboot X with Ctrl+Alt+Backspace for the changes to take effect.

An example script is available here.

That’s all for now. Good luck with your Eee PC projects! I think the Eee PC and wxWidgets make a great combination, and it will be interesting to see how the market for desktop Linux will develop over the coming months.

Sunday, November 25, 2007

Hildonizing wxGTK

Last week-end I have somehow managed to find myself with a couple of hours of free time and, instead of spending them on fixing random wxWidgets bugs as usual, I wanted to actually do something new and different for once and so chose to check how wx applications look on a Nokia 770 tablet. Several people have talked about porting wxWidgets to this device in the past and at least one has apparently done some work but it was almost two years ago and nothing has happened since, so I felt it was time to do something about it myself; especially as I own a N770 tablet since quite some time but, instead of writing programs for it as originally planned, I've so far spent time just using it (I do feel ashamed).

For those who don't know about Nokia internet tablets line, which started with N770 but has been extended with N800 and N810 since then, they're small handheld non phone devices which run Linux and use a modified Gnome desktop version called Maemo. Maemo basically just adds another level of libraries, called Hildon on top of GTK+ itself. So, while GTK+ applications can mostly run on N770 without changing, they don't have the correct look and feel before they are hildonized, that is modified to use Hildon-specific functions instead of the generic GTK+ ones -- hence the somewhat barbaric adjective used in the title of this article.

This is the theory, anyhow. And I've decided to check how it was in practice. The first results were encouraging: after a few simple fixes, wxGTK did build for Maemo and I could run applications on my device. However they really didn't look like they belonged here as can be seen by comparing the dialogs sample:




with a native application, such as this one:




You can immediately see several differences:

  • The border of the window are not the same, the wx example doesn't fit into the desktop
  • The menus are completely different: the native applications don't show a menu bar but use the drop down menus attached to the window itself
  • The wx example shows a useless status bar with an even more useless resize grip (the window can't be resized anyhow)
So I set about fixing this and after a couple of hours of hacking here is what I got:




This is already much better: the points mentioned above were corrected and I also added a new class (which is available, and hopefully will be useful, under the other platforms too) called wxNotificationMessage and which is used by the small message in the upper right part of the window (such messages are often used in Maemo UI as notifications and also message box replacements)

Of course, there are a lot of other things to do. For one, wxToolBar needs to be changed in the same way wxMenuBar was. Next, as Maemo replaces almost all of the standard GTK+ dialogs with its own ones, we need to do it too. I did it for the colour selection dialog which looks like this now if wxWidgets was built with --with-hildon option:


And the same should be done for the file selection dialogs and several other ones.


There are also less trivial things to do, like to understand how can the size of the library (and of the applications using it) be reduced to be more in line with the embedded systems capabilities. But globally I think wxWidgets is perfectly viable for developing Maemo applications and is even more convenient for doing this than raw GTK+ (which is the native toolkit of the platform) because it transparently abstracts the differences between the desktop GTK+ and Maemo systems: the dialogs sample itself hasn't been modified at all (just extended to show the notification message) to use the correct menus and so on, everything is done inside the library so exactly the same code can be used for the desktop application without any loss in functionality. Of course, in practice you will need to adapt applications to the mobile devices by probably removing some functionality which doesn't make sense there and simplifying the user interface. But wxWidgets already does some of this for you and hopefully will do even more in the future.

Of course, I don't actually expect to have that much free time every week-end so the progress of wxMaemo depends on the help from others. So if you're interested in checking out wxMaemo for yourself, don't hesitate to grab the latest wx code from our svn and build it with the above-mentioned --with-hildon option under Scratchbox. If you are new to Maemo, notice that its web site has nice tutorial about setting up the development environment for this platform. And, of course, if you can contribute to this effort, don't hesitate to send us patches and join us in discussions on wx-dev.

Have fun!

Sunday, November 04, 2007

Looking forward to wxWidgets 3

The first alpha version of wxWidgets 2.0 was released 10 and a half years ago and we are still (only) at version 2.8.6 right now so the wxWidgets version numbers don't change very quickly as we, with the disdain proper to free software developers, don't really like inflating them for marketing purposes. However soon -- hopefully in the beginning of the next year -- we will release wxWidgets 3.0 which will be the first change of major version since a long time and only the second time it happens in wxWidgets history. So it may be interesting to look at what exactly has changed to warrant this and I'll try to briefly describe it in this post.

First, a word of reassurance: there are no sweeping backwards-incompatible changes in wxWidgets 3.0 compared to 2.8. We did have to break compatibility in a few places but fixing the existing code to compile with 3.0 will be trivial, if needed at all, unlike 1.0 -> 2.0 transition which required rewriting it.

Second, the main change in 3.0 is the rethought support of Unicode. While wxWidgets supports Unicode since quite a long time, so far it did according to Win32 model: there were two different builds of the library, one ANSI and the other Unicode and you could either use the former to use the familiar char * strings but stay limited to a single encoding or choose the latter one and be able to use Unicode in the GUI but at the price of working with wchar_t * string only which implied using ugly-looking wxT() macro in a lot of places for example. wxWidgets 3.0 will have only one build (which on its own is a great simplification for developers, packagers and even users who won't hesitate between which one to choose) combining the best features of the two: it will always use Unicode internally but support char * string and simply convert them using the current encoding transparently. In other words, you will be able to write code in exactly the same way as with the old ANSI build if this is all you need but profit from the full Unicode support at the same time. This is especially nice for the existing wxWidgets applications which weren't always written with Unicode in mind and so often didn't even compile with the Unicode build of wx -- now they will and it will be possible to extend them to deal with Unicode at leisure instead of spending a big initial effort on wxT()-izing them first.

wxWidgets 3.0 is still work in progress, in particular documentation hasn't been updated to reflect the changes yet. However the API and the code are believed to be stable enough to be used and we'd welcome any feedback on the new API. In particular, please try recompiling the existing code with the version currently in the svn trunk and let us know about any problems you may encounter (other than those which are mentioned in docs/changes.txt: please read it first!).

There are, of course, many other new features in wxWidgets 3.0 (without speaking about the bug fixes...):
  • The new wxDataViewCtrl class provides all the features lacking in wxListCtrl and a much better and simpler API to use them.
  • There is a new wxDFB (DirectFB-based) port especially suitable for the embedded devices.
  • wxGTK (and wxDFB) are also more efficient internally because they use UTF-8 for the string representation, instead of wchar_t and so avoid the conversions between the underlying toolkit strings and wxString.
  • New and improved wxFileCtrl (thanks to Google summer of code).
  • Many enhancements to wxRichTextCtrl.
  • Important improvements to several controls under wxGTK, including wxToolBar, wxStaticText, wxHyperlinkCtrl and others.
  • Support for auto-completion in wxTextCtrl and wxComboBox.
But, again, the most important change by far is the merge of ANSI and Unicode builds and the resulting changes to wxString. As this is the biggest change to wxWidgets API since several years we'd really welcome your comments on it, this will help us release 3.0 sooner and better!

Sunday, April 15, 2007

wxWidgets in Leopard

The new schedule of Apple's OS X 10.5 a.k.a. Leopard (to ship in October) allows us to get a newer version of 2.8 into the builds. So we aim for a 2.8.4 Release Candidate around the end of April, synching wxPython and wxPerl with it.

Monday, February 05, 2007

wxWidgets under Vista

I've decided to (finally) test how do wxWidgets applications fare under Windows Vista. Installing Vista (in a VMware Workstation 6 Beta virtual machine under a Debian amd64 host) turned out to be more problematic than I thought as the MSDN disk 2429.5 contains exactly 4 ISO images of Vista CDs while the installer asked me to insert disk 5 and as I didn't have I couldn't continue with the installation. So I had to install the Enterprise Edition from the disk 2430.2 which not only comes with 4 CD images on the DVD but also actually installs from them.

Other than that, installation was pretty uneventful and un-wow: the installer warns that the computer must reboot several times during the installation -- and so it does. Why no other system among those I installed (various Linux distributions, FreeBSD, Mac OS X, ...) needs to reboot even once? Anyhow, UI-wise the only useful information from the installer is that Vista seems to use ./../... animation as an indeterminate progress control (OS X, or Firefox which probably copied it from it, use a small spinning wheel for the same thing) so if we ever implement a separate control for this, we know how it should look under Windows now.

After finishing the installation and getting rid of half a dozen of the icons in the taskbar notification area (this is progress, I think XP had only a couple of them) I could finally run the widgets sample. The only problem I could see with it was with wxNotebook tabs on the left or right: this doesn't work at all under Vista and I think we should just abandon trying to make it work as it already was pretty buggy under XP.

But there are a few enhancements we could implement, of course:

  • wxSearchCtrl doesn't look native but Vista does has a native version (just as OS X) and uses it everywhere so it's really jarring to have a different one in wx programs. Apparently the standard "Search Control" class is just a combination of "Edit" and "ToolbarWindow32" (with "Static" thrown in to show the inactive control contents) so we could emulate it easily even on pre-Vista systems. Or we could just use the native control, of course.

  • Buttons with images seem finally to be supported (they can be seen in e.g. "Tools" page of a disk properties dialog), so we should update wxButton to support this too.

  • As mentioned before, some file dialogs (e.g. Ctrl-O one in the dialogs sample) use old style while other ones (Ctrl-Q one) use a new style one which is inconsistent at best. Other dialogs seem to be just fine though, and the new Vista-style icons are used everywhere as expected, e.g. in the log dialog. Funny enough, the standard Vista error message dialog now looks a lot like wxWidgets standard log dialog with its "Details >>" button.



All in all I think wxWidgets applications look pretty decently under Vista, especially considering that we didn't spend any effort at all so far on porting the code to Vista. Of course, it's a tribute to Microsoft engineers backwards compatibility maintaining skills more than anything we did but it's still nice, especially compared with the transition to XP when previously working code started to crash and a lot of things didn't look right at all.

Friday, January 26, 2007

In Praise of Connect()

In this post I'd like to address a common misconception about wxWidgets which is that it is somehow dirty and beneath consideration of "real" C++ programmers because it relies too much on preprocessor macros. While it is true that the traditional way to handle events in wxWidgets is using the macro-based event tables, there is nothing really dirty nor evil about these macros: they are there simply to save typing. In particular, they don't suffer from the usual macro pitfalls as they don't have any side effects and are type-safe (static_cast is used internally to ensure this).

However the main point is that the event tables macros are just one of two ways of connecting the event handlers to events in wxWidgets and it's perfectly possible to not use them at all. Moreover, there are good reasons to use the alternative way beyond the subjective dislike of macros. This other way is the Connect() method which, unsurprisingly, allows to connect a method of a class derived from wxEvtHandler (which includes, but is not limited to, any wxWindow-derived class) to an event.

The syntax is slightly more verbose which is, of course, one of the reasons for using the event table macros in the first place, they simply save some typing. So instead of

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
  EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
END_EVENT_TABLE()

you need to write (in the body of some method of MyFrame and not at global scope as with the event tables)

MyFrame::MyFrame(...)
{
  Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
  wxCommandEventHandler(MyFrame::OnQuit));
}

Notice the use of wxCommandEventHandler which ensures that the method is of correct type by using static_cast in the same way as event table macros do it.

So we see that all uses of event table macros can be trivially replaced with Connect() calls. However Connect() is more powerful than macros and can do a few things that macros are incapable of:

  1. Event handlers can be connected at any moment, e.g. it's possible to do some initialization first and only connect the handlers if and when it succeeds. This can avoid the need to test that the object was properly initialized in the event handlers themselves: with Connect() they simply won't be called at all if it wasn't.

  2. As a slight extension of the above, the handlers can also be
    Disconnect()ed at any time. And maybe later reconnected again. Of course, it's also possible to emulate this behaviour with the classic static (i.e. connected via event tables) handlers by using an internal flag indicating whether the handler is currently enabled and returning from it if it isn't, but using dynamically connected handlers requires less code and is also usually more clear.

  3. Also notice that you must derive a class inherited from, say, wxTextCtrl even if you don't want to modify the control behaviour at all but just want to handle some of its events. This is especially inconvenient when the control is loaded from the XRC. Connecting the event handler dynamically bypasses the need for this unwanted subclassing.

  4. Last but very, very far from least is the possibility to connect an event of some object to a method of another object. This is impossible to do with event tables because there is no possibility to specify the object to dispatch the event to so it necessarily needs to be sent to the same object which generated the event. Not so with Connect() which has an optional eventSink parameter which can be used to specify the object which will handle the event. Of course, in this case the method being connected must belong to the class which is the type of the eventSink object! To give a quick example, people often want to catch mouse movement events happening when the mouse is in one of the frame children in the frame itself. Doing it in a naive way doesn't work:

    • A EVT_LEAVE_WINDOW(MyFrame::OnMouseLeave) line in the frame event table has no effect as mouse move (including entering and leaving) events are not propagated upwards to the parent window (by default, anyhow).
    • Putting the same line in a child event table will crash during run-time because the MyFrame method will be called on a wrong object.

    However writing

    MyFrame::MyFrame(...)
    {
      m_child->Connect(wxID_ANY,
        wxEVT_LEAVE_WINDOW,
        wxMouseEventHandler(MyFrame::OnMouseLeave),
        NULL, this);
    }

    will work exactly as expected. Note that you can get the object which generated the event -- and which is not the same as the frame -- via event.GetEventObject().


So the morale of the story is: don't hesitate to use Connect(), it's much more powerful than static event tables which should be reserved just for the most simple situations when you don't need any additional flexibility and wish to save some extra typing, or maybe not even then for consistency sake.

Friday, December 22, 2006

Goals of wxWidgets

A comment attached to the last post asked the question about what wxWidgets goals are. I was initially quite surprized because the answer was so obvious to me, but thinking a bit more about this I realized that we don't clearly answer this question anywhere in the public documentation and so for someone not following wx-dev mailing list the direction of wxWidgets development may indeed seem mysterious. To help with understanding it, I'd like to briefly explain where wxWidgets is coming from, what are the guiding principles for its development today and what I hope it is going to be tomorrow. Please note that, as anyone who does follow wx-dev would know, we don't always agree about everything and so what follows is just my personal point of view and while it hopefully does overlap with that of the others -- at least for the past and present parts -- I don't pretend to speak for everybody.

This disclaimer aside, let's start by looking at the current state of wxWidgets and how did we get there. On the negative, and often mentioned, side, it's an accretion of almost 15 years of development, by different people, some of which have stopped contributing to the project since a long time. So it is not surprising that there are some inconsistencies in the API (although we work hard on ironing them out) and some components (notably those whose maintainers have left) are not as good as one'd expect them to be. It is also true that compatibility with MFC seemed much more important in the nineties than now and this explains why wxWidgets has some superficial similarities to it, although it has never been nor designed to be, an MFC clone. So it's true that this long history resulted in some problems and we had to change quite a few things to fix them -- even the original name of the library turned out to be a bad idea.

However, on the bright side, not everything we did during these 15 years was a complete waste of time and, in addition to the accumulated historical luggage, everything that we did right is in the wxWidgets codebase too. And this is quite enough to allow people to create real life, professional complicated graphical cross-platform applications -- which is, to answer the initial question, what wxWidgets is about. To be more precise, the main goal is to allow the developers to do everything they need to do without resorting to writing platform-specific code: the "Write once, compile anywhere" principle. Of course, this goal is a moving target which can never be quite achieved because developers discover more and more things that they need to do with time as the new graphical environments introduce new standards (use of gradients and animations in the GUI was not exactly common when wxWidgets was started) but, still, I believe we're pretty close to it -- and getting closer with every new release.

So wxWidgets primary goal is to allow creating sophisticated portable applications without writing platform-specific code. This is not the only goal, of course, but it's the most important one and so trumps all the others. For example, wxWidgets could be more size efficient but this would be mostly important for toy applications and not for the programs which are themselves of reasonably important size. And so, while we'd be as glad to make wxWidgets smaller as anybody else, this currently has a relatively low priority because it's not very important from the main goal perspective. On a perhaps more constructive note, this also explains why do we consider the differences in behaviour of wxWidgets on different platforms important bugs: it's useless to have the code which compiles on all platforms if it doesn't behave the same everywhere during run-time.

But, to repeat, as important as this goal is, I think we're quite close to it and have been there since a long time. However other things could really be improved. Chief among them is the ease of use of wxWidgets: things have changed a lot since its creation and, in particular, modern C++ doesn't have much to do with C++ of the nineties. So it would be great to make wxWidgets evolve with the language and other standard C++ libraries. This would mean providing a more modern API, removing the need for memory management completely (this is very rarely a problem in wxWidgets even now, as most of the objects are owned by the library anyhow, but it would be nice to make this more explicit) and improve error handling by using exceptions. We should also rely more on the standard C++ library and Boost instead of implementing all various useful but not directly GUI-related classes on our own as we had to do in the past (as not implementing them would have conflicted with our primary goal whereas now, when such classes are available from elsewhere, it doesn't any more). This, and much more, is in our plans for wxWidgets 3.

There are certainly a lot of other tactical goals. The fact that I didn't mention at all fixing the bugs or improving the documentation doesn't mean that these goals are not important but just that they are obvious and I don't want to make this article even longer than it already is by stating the obvious. The point of this post was to just say that strategically, our main goal always was and remains making wxWidgets suitable for real-life portable applications development and, in addition, creating a new, modern, API for wxWidgets 3 in (hopefully near) future.

Sunday, December 03, 2006

How to Contribute to wxWidgets Guide

We often have the impression that wxWidgets could be so much better if only we had more time to fix the known problems with it, to implement all these exciting new features it still lacks or even just to fix the numerous old bugs. But unfortunately the time is always lacking (isn't it funny that you can regularly find jokes about 48 hour days in wx-related email since the beginning of the nineties?) and so many things remain undone. So the next idea, after failing to change the duration of the day, is to encourage more people to work on wxWidgets -- and it seems especially actual now that programming is becoming all about parallelization to take advantage of new multi-processor machines. And attracting new contributors does work rather nicely (better than trying to construct time dilatation machine, anyhow), for instance several new developers joined us relatively recently and brought us great things like AUI, custom comboboxes and almost all other new controls in the upcoming 2.8.0 release.


But we'd still like to attract even more! And maybe it's our own fault, after all, if people don't flock to wxWidgets development. We don't do much advertisement (real programmers hate marketing) and we don't even explain clearly how to become a wxWidgets contributor anywhere. Personally, as I want to keep my real programmer badge, I can't really address the former issue but at least I tried to help with the latter and so wrote this guide to explain how you can help with wxWidgets development. It is probably not as useful as it could be as it's hard for me to understand what questions and problems can a newcomer to wxWidgets (and/or open source development in general) have. But hopefully this guide is better than nothing at all and I'm looking forward to improving it in the future with feedback from the people it is really addressed to.

So thanks in advance for any comments about this guide! As for me, I'm finally going to log off and have a few hours of sleep after my 40 hours wxWidgets working day, safe in the knowledge that hundreds of new developers are going to join the project tomorrow ;-)

Friday, October 27, 2006

wxWidgets at Firebird Conference 2006

The fourth worldwide Firebird Conference will convene at Andels Hotel in Prague, Czech Republic, on Sunday November 12. Notice one of the talks: "Developing Cross-Platform Applications with Firebird and wxWidgets" by Milan Babuskov. Be there!

Wednesday, October 18, 2006

wxwidgets.org website issues

As mentioned in a comment on a previous post, the http://www.wxwidgets.org website is currently blank and has been so for a few hours now. Robin Dunn mentioned on the users mailing list that the likely cause is that vhost.sourceforge.net is currently down; alternate addresses such as

http://wxwindows.sourceforge.net/

Still appear to work.

Recently in the past there were also issues with speed of the site as well, possibly concerning sourceforge hosting; specifically image loading. Sometimes images would only load half the time. Images were shifted to and from an alternate server (run by Kevin Olliver) in an attempt to provide a temporary fix for the issue.

Saturday, October 14, 2006

Right-To-Left layout (RTL) support in wxWidgets

Here is some information about the support for locales with right-to-left (RTL) layout out in wxWidgets. As you probably know, RTL-support is required mostly of Hebrew, Arabic and Farsi. It has been decided that wxWidgets should follow mostly the Windows API and Windows approach for displaying RTL text and layout in applications. This approach is described in a document at MSDN here. In short, all coordinates for drawing and for window positioning are mirrored horizontally which means that (apart from bitmap mirroring) little has to be done at the user level. Also, the various native Win32 controls are modified to support RTL design.

This is different from what is done under GTK+, where no coordinates are mirrored. Instead, every app needs to mirror everything itself, even if the job of mirroring controls is mostly done within GTK+'s layout container automatically. As far as drawing within wxWidgets is concerned, coordinates are mirrored at the wxDC level in the GTK+ port. Some more information about GTK's RTL support can be found here.

I have added two screenshots from the popular FileZilla application running in the "ar_EG" (Egyptian variant of Arab) locale (screenshots in parts thanks to Tim Kosse). Since the tree control in the Linux screenshot is using generic wxWidgets code, this also demonstrates how drawing and scrolling is mirrored for user windows.

Below is a screenshot using wxWidgets and GTK 2.4.9.














Here is roughly the same screenshot using Windows 2000.

Thursday, October 12, 2006

wxWidgets 2.7.1 released

12th October 2006: wxWidgets 2.7.1 (a development release) is now available for download via http://www.wxwidgets.org/downloads.

The main changes since 2.7.0 are detailed below. We would be grateful for testing as we work towards 2.8.0 release within the next few weeks. However please be aware that 2.7.1 is not production quality.

wxMac defaults to using the more advanced Core Graphics implementation - this is a work in progress, and we would like to hear of any problems. You can edit include/wx/mac/carbon/chkconf.h to switch Core Graphics off.

Thanks,

The wxWidgets Team


Changes in 2.7.1
=================================================

All:

- Added wxDir::FindFirst() (Francesco Montorsi).
- Added wxPlatformInfo class (Francesco Montorsi).
- Added wxLocale::IsAvailable() (Creighton).
- Added Malay translations (Mahrazi Mohd Kamal)
- Added reference counting for wxVariant
- For consistency, all classes having Ok() method now also have IsOk() one, use
of the latter form is preferred although the former hasn't been deprecated yet

All (GUI):

- Support for right-to-left text layout (started by Diaa Sami during Google Summer of
Code, with a lot of help from Tim Kosse and others).
- wxAnimationCtrl added (Francesco Montorsi)
- Added wxAboutBox() function for displaying the standard about dialog
- Added wxID_PAGE_SETUP standard id.
- Added wxSize::IncBy() and DecBy() methods.
- Added wxTextCtrl::IsEmpty()
- Added file type parameter to wxTextCtrl::LoadFile, wxTextCtrl::SaveFile for
consistency with wxRichTextCtrl.
- wxRichTextCtrl: fixed range out-by-one bug to be consistent with wxTextCtrl API,
fixed some attribute bugs and added wxRichTextStyleComboCtrl.
- Added wxWindow::IsDoubleBuffered()

wxMSW:

- Implemented wxComboBox::SetEditable().
- wxSemaphore::Post() returns wxSEMA_OVERFLOW as documented (Christian Walther)
- Fixed a bug whereby static controls didn't use the correct text colour if the
parent's background colour had been set (most noticeable when switching to a
high-contrast theme).
- Respect wxBU_EXACTFIT style in wxToggleButton (Alexander Borovsky)

wxMac:

- Add parameter to the --enable-universal_binary configure option for the path
to the SDK.

wxGTK:

- Automatically use stock items for menu items with standard ids.
- Setting cursor now works for all controls.
- Implemented right-to-left support
- Implemented left indentation and tab stops support in wxTextCtrl (Tim Kosse).

wxUniv:

- Added wxTLW::UseNativeDecorations() and UseNativeDecorationsByDefault()

Wednesday, October 11, 2006

Towards quality in wxWinCE 2.8

The most mature ports of our toolkit (wxGTK, wxMSW and wxMac) are nearly equally advanced in terms of features. The development on them is "easy" - they all have the same screen sizes, keyboards, pointing devices, and sounds so once a wrapper around their native API is in place, the ports can share a common wxWidgets infrastructure for events, placement of controls etc.

A few releases earlier we started work on a new family of ports that are increasingly demanded by the market: handhelds, phones and PDAS. See more about it at http://wxwidgets.org/docs/embedded.htm

wxWinCE is the name given to wxMSW when compiled on Windows CE devices. We have a dedicated section in our manual about this port, see: http://www.lpthe.jussieu.fr/~zeitlin/wxWindows/docs/wxwin_wxmswport.html#wxmswport

Are you a wxWinCE user? What do you miss most? When and how do you use #ifdef __WXWINCE__ in your code? Do you have some own improvements to this port? Please share any opinions and findings about the current state of the wxWinCE port on wx-dev and (for bugs and patches) the SourceForge trackers, and let's make it better together for future releases.

Tuesday, October 10, 2006

Google Summer of Code 2006: wxWidgets projects summary

Google Summer of Code 2006 is over, and it's time to take stock of what's been achieved. We had nearly 20 proposals, and in the end three projects went ahead. All of the three have contributed useful code, and needless to say we're in awe of Google's programme that gave so much and asked for so little in return. Open source in general, and wxWidgets in particular, just took another big leap this forward this summer. Thank you Google! And of course a big thank you to the three students, and to others who submitted applications - perhaps they will be working on GSoC 2007. Meanwhile, there's still the page of project suggestions for people looking for contribution ideas.

Here then are summaries of the projects.

wxWidgets Package Manager


This project promises to make it easy for people to use the many available third-party wxWidgets components, which often have unique installation methods that take time to understand. What started off as one application has become a suite of three: wxPackageManager, wxPackager and wxp.

wxPackageManager is a GUI application that lets you browse local and remote package repositories, view a summary and details of the packages, and then download, compile, install, and uninstall them.

wxPackager is another GUI application that helps you create and edit a package description file, and upload the compressed package archive to a remote repository.

wxp is a command-line utility that allows you to perform all tasks exposed by the wxPackageManager and wxPackager GUI and also create and maintain repositories of packages.

Francesco Montorsi has already worked on valuable wxWidgets enhancements, but has excelled himself in this project, bringing a high standard of coding and attention to detail. It needed a fairly broad range of skills including knowledge of GUI design and implementation, network programming, multithreading, and XML. The project will make a significant difference to the ease of use of wxWidgets components when the package format is taken up by component authors. It’s doubtful if the package manager would have been built without the support of Google.

Links:

The CVS repository where the sources are hosted:
http://cvs.wxwidgets.org/viewcvs.cgi/sandbox/packagemanager

The server which hosts the latest release of the three programs:
ftp://ftp.wxwidgets.org/pub/utils/wxp/

Screenshots of wxPackageManager and wxPackager on Windows:
ftp://ftp.wxwidgets.org/pub/utils/wxp/wxpackagemanager.jpg
ftp://ftp.wxwidgets.org/pub/utils/wxp/wxpackager.jpg

The Package Manager on Windows XP:


Network class improvements

Angel Vidal’s project involved a range of fixes and enhancements to the wxWidgets network classes. These include unifying socket code for each plaform and rationalising common code; applying patches and updating the SourceForge trackers; adding proxy support for Connect() calls; improving UDP socket support; and testing on Linux 32/64, MSW and Mac OS X.

These improvements haven’t yet been incorporated into the main development branch, but we hope that after a little more work the result will be far better and more easily maintainable network code than in wxWidgets at present.

Angel's code is available in the SOC2006_SOCKET CVS branch.

Right To Left language support

As befits a framework developed by a group of people from many different countries, wxWidgets has long had facilities to help with internationalization and localization issues, but until now it had no support for RTL (right to left) scripts such as Arabic or Hebrew as we didn't have either the resources or knowledge of these languages necessary to implement it. Diaa Mahmoud Sami Abdel-Ghani started on the project to change this and to add full RTL support, including mirroring of the GUI elements, to the library. The project started well enough with the discussions of the API changes needed for this and, relatively soon thereafter, Diaa wrote the code to allow wxWidgets applications to show up correctly in Arabic locale under Microsoft Windows. Unfortunately, after the mid-term point almost no more work had been done until the very last few days of the program, and so the initial goals hadn't been fully achieved which led the mentor to give a negative final evaluation. Nevertheless, the project was far from being a complete failure as all code written by Diaa was integrated into the main wxWidgets sources and several people, notably Tim Kosse and Robert Roebling, were motivated enough by this to fix the remaining bugs and add RTL support for the GTK+ port.

So, while this project wasn't an unmitigated success from the student's point of view, it definitely helped wxWidgets as it has gained RTL support - probably imperfect but incomparably better than no RTL support at all. It wouldn't have happened without GSoC.

The RTL support is in CVS HEAD (2.7).

Beware: 2.7.1 Coming Tomorrow

wxWidgets 2.7.1 will be released on Wednesday October 11 2006 (I thought the year was worth mentioning, especially for people used to our usual release schedules). So today you have the last chance to test your code using the latest cvs sources or the last daily snapshot and let us know about any new problems in 2.7.1 so that we could fix them before the release (and, of course, break something else to compensate for it).

Please pay attention to the documented incompatible changes in the beginning of docs/changes.txt, especially if you hadn't used 2.7.0 before.

Thank you for testing!

Sunday, October 08, 2006

wxFileDialog and Windows Vista

There are some changes regarding the native file dialog
in Windows Vista. Perhaps best explained by a shell
developer here: If one changes properties of the native
file dialog, one gets the "old" file dialog from Windows XP.

Here's an example of the difference: ("Old" is the first menu
option from the filedialog portion of the dialog sample, "New"
is the second.)

"Old":















"New":
















The problem is that the dialogs sample uses
> dialog.CentreOnParent();
which causes Vista to revert to the "old" file dialog.

So, if you are using common dialogs just keep an
eye out if you customize it all; as even centering it
with its parent could change the appearance of it.
In fact, calling any wxWindow method can be
problematic as it can make the look of a common
dialog non-native, or it may not work at all (in
some cases on some platforms setting the
background color doesn't work, for example).

I posted on the mailing list awhile back,
http://lists.wxwidgets.org/cgi-bin/ezmlm-cgi?5:mss:78283:200610:fgbndhmhiamfkklpjajh
but sometimes it is a lot better with pictures :D.

Also, it still happens with RC2, which is supposively
the last release before RTM (Release To Market),
so it is likely that this will stay.

For those to wish to interact with the new Windows
Vista file dialog API, they can use the IFileDialogXXX
COM interfaces. This also includes derivatives
such as IFileOpenDialog. Hopefully wxWidgets
won't end up having to support a seperate file
dialog interface; but then I guess one could
just pImpl it as well.

March of progress in action: wxAboutBox()

Finally, 13 years after its beginning, wxWidgets has gained this mostly indispensable feature of any modern GUI toolkit: the possibility to show the standard "About" dialog with one line of code. As of today, wxAboutBox() function can be used to create a dialog box like this
GTK+ About Dialog
or like that
Mac OS X About Dialog
or, if all else fails, like this
Generic About Dialog under Windows


The generic dialog is not finished however as the best way to implement is seems to be using yet another new control: the hypothetical wxCollapsiblePane. The hope is to have it soon, finish wxGenericAboutDialog next, and release 2.7.1 immediately thereafter.