
Please keep the MVC, model view controller, pattern in mind from the beginning so that we the users can map our existing data to the gui controls rather than having to add them. This pattern is also used in Java's Swing (not AWT) and somewhat in .NET's windows form. Though I will say that .NET is more like a wrapper around the Win32/64 api and doesn't use MVC extensively. Though in their defense the common IList, ICollection and IEnumerable interfaces works more consistently over all their controls than Java's multitude of control specific model interfaces. So a balance needs to be reached using C++ idioms. As an example, when working on a list control it could be associated with a range of random access iterators. The control than would not add all the items to the control but would rather use delay loading to ask the collection what the data when it needs it. Since STL collections doesn't provide change notifications nor classes by default than such a sublibrary would also need to be considered. -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Felipe Magno de Almeida Sent: Saturday, October 20, 2007 9:43 PM To: boost@lists.boost.org Subject: [boost] [rfc] Gui library Hi, I'm already working on a GUI library for some time (three weeks). And come up with some designs and code. I'm sure to have it for review when ready and I would like to ask for comments here to get it going in the right direction. The code is in www.sourceforge.net/projects/cppgui The code is not completely compiling right now, but I'm writing it with support for win32/64, gtk and qt. The main design decision I have is that the GUI interface and the implementation specific code is completely decoupled. That way I can have a application that executes win32, gtk *and* qt at the same time. It is indeed what the first example does. In that, I call the implementations as drivers. And I can have the driver specified in the create window function. Just as this: wnd<> w = create<frame_window>( _driver = drivers::win32 ); For this to work, I had to create two hierarchies: window window_impl_base | | / \ / \ / \ / \ / \ / \ / \ / \ frame button frame_impl_base button_impl_base The first hierarchy is the one exposed to the user and the second must be derived from the drivers. The first can be subclassed by the user with this syntax: class my_frame : gui::subclass<my_frame, gui::frame> { my_frame() { wnd_lock<my_frame> w = wnd_pointer_cast_lock<my_frame>(wnd_from_this()); wnd_lock<gui::controls:button> btn = create<gui::controls::button> ( _parent = w, _size = std::make_pair(20, 20) ); btn_ = btn; } static void info(gui::create_info& i) { i.pos = std::make_pair(100, 100); } wnd<> btn_; }; And then the info function is called before my_frame instantiation automagically. This way my_frame can override the window creation properties before it is actually created by the driver. There's a injection of the window implementation in the window base class of the hierarchy too, so that calling GUI functions from inside the constructor would be safe too. Now, what I think is the most complicated part: wnd<> and wnd_lock<> classes. I decided to use functors as a way to execute handlers for GUI events. Therefore, window smart pointers could end up inside functors objects through boost::bind and others. The problem is: The window should be destroyable while waiting for user response. But if smart pointers inside functors were registered within the window, there would be a cyclic relationship that would prohibit it. And then I created these two classes. wnd<> being like weak_ptr in shared_ptr and wnd_lock<> would be the shared_ptr itself. I honestly do not like this solution and even less the wnd_lock<> name. It even seem to imply thread mutual exclusion, which it does *not*. Also, I found when using asio and win32gui that it is nice to have a class just for the handlers, which holds all its state. So I created a way to register event classes to windows, and to which you can return a functor that returns this event class object to be used in the handler binder. So you can do this: struct event_class { void btn_clicked(wnd_lock<> btn) { // do something } int x; // data required for handlers }; my_frame::my_frame() { wnd_lock<controls::button> btn = create<controls::button> ( _parent = wnd_from_this(), _text = "My button!" ); add_event_class<event_class>(); // this registers to call event_class::btn_clicked with // the event_class object under the window's lifetime management. btn->on_click(boost::bind(&event_class::btn_clicked , boost::bind(get_event_f<event_class>(), _1 )); } That way event classes can be completely defined inside a .cpp file, and any alteration to it wouldn't need the world to recompile, nor would be coupling between event handlers and the visual creation code. In theory, at least. But I find the syntax horrible for event registration and the event handler class ends up being referenced *a lot* inside the window's constructor. So, any comments would be *really* appreciated. And keep in mind that the library is in pre-alpha state (and that's why I'm posting this rfc here, so that I can find a better design to code). Which means that most parts aren't implemented yet. (Most controls, dialogs, resource files, etc). Thanks and best regards, -- Felipe Magno de Almeida _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost