|
|
This thread is locked; no one can reply to it.
|
1
2
|
| Project Idea for a "good GUI lib for Windows" |
|
axilmar
Member #1,204
April 2001
|
Is anyone interested in participating in an open source project for a GUI library? I am motivated by the lack of a simple GUI library, as it is mentioned in this thread. I've seen this request for a simple gui library before. The desired features are: 1) native look and feel; it will use native Win32 widgets underneath and Qt or GTK on Linux. 2) cross-platform at source-code level. 3) simple; the APIs would be uniform and as less complicated as possible. 4) uses established C++ principles, i.e. the STL, boost::shared_ptr, boost::bind, boost::functional, virtual methods etc.; no message maps or macros 5) it will only be a GUI library; there would be no networking, threads, database, etc stuff. 6) uses unicode through out First version will have a few widgets: label, image, button, check box, radio button, scroll bar, text box, combo box, list box, window, menu, menu item, file dialogs. Future versions may have more complicated functionality, i.e. Multiple Document Interface, spin box, tree view, table view, drawing canvas, date and time picker, tabs, font and palette dialogs, printer and font support, open gl, drag and drop etc. These things are difficult and time-consuming to code, but once a basic setup is there, I think it is enjoyable to code components. So, is anyone interested? |
|
Stagera
Member #4,606
May 2004
|
wxWidgets? |
|
nonnus29
Member #2,606
August 2002
|
SmartGuy said: wxWidgets? Reading comprehension needs some work I think... |
|
bamccaig
Member #7,536
July 2006
|
Sounds like fun... -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
|
Arthur Kalliokoski
Second in Command
February 2005
|
I've been thinking about dredging up my old brute-force assembler code for 486 which works just fine... I need it for my game. Never did have a drop-down list though, I'd want that for the available screen modes and saved games. They all watch too much MSNBC... they get ideas. |
|
Neil Walker
Member #210
April 2000
|
other than c++, it ticks all the boxes. You didn't mention it had to be a thick client Neil. wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie |
|
Andrei Ellman
Member #3,434
April 2003
|
I've made a C GUI library that I use for my projects. It started off as a buttoned-menu manager but I decided to turn it into a full blown GUI. It's based on Allegro and uses no other APIs. But it currently lacks several important widgets (most notably text-entry widgets) and could do with being tidied up. AE. -- |
|
Kitty Cat
Member #2,815
October 2002
|
Quote: 5) it will only be a GUI library; there would be no networking, threads, database, etc stuff. Wouldn't something like threads be a great benefit to a GUI lib? Especially where multiple windows are concerned? You'd end up having to wrap the native thread lib (Windows threads or pthreads) into a coherent interface anyway, so what's the difference if it's exposed or not? The app may even have to use it to gaurantee safety, so it would likely have to be exposed.. Plus there's issues between different STL implementations.. some are quite broken, or the spec is just so ill-defined in some places you can't rely on its behavior, meaning you'd have to rewrite at least some of the functionality. Want unicode support? Got a few functions to write, then.. Then you should look into what people would be using a GUI lib for, and provide features so everyone doesn't have to reinvent the wheel all the time.. and since such features are optional, why not include them? -- |
|
axilmar
Member #1,204
April 2001
|
Quote: Wouldn't something like threads be a great benefit to a GUI lib? I think the decision to use threads or not is better left to the programmer. The point of my proposal is to only deal with GUI, nothing else. Quote: You'd end up having to wrap the native thread lib (Windows threads or pthreads) into a coherent interface anyway, so what's the difference if it's exposed or not? It's not required for a GUI library to use threads. The basic execution flow of a GUI is: a) read events, b) dispatch events. If the user wants to use threads, that's fine. Quote: Plus there's issues between different STL implementations.. some are quite broken Your comment would be valid 10 years ago, but nowadays it's not. All major compilers have a very nice STL implementation. Quote: Want unicode support? Got a few functions to write, then.. wstring is quite good. Win32 also has plenty of functions for unicode support. Quote: Then you should look into what people would be using a GUI lib for, and provide features so everyone doesn't have to reinvent the wheel all the time.. Because not everyone needs X feature or Y feature. Someone may want to use pthreads, someone else win32 threads, etc. Why force anything on the programmers? |
|
SiegeLord
Member #7,827
October 2006
|
This sounds like an awesome idea. I've always lamented that wxWidgets does not have a Qt backend. Having a unified library to make GUI for both GNOME and KDE would be awesome. I am not a fan of using boost... I'd prefer the 3rd point to be "simple and small" which would rule out using boost... "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
I've been gearing up to start on my own GUI and since you had mentioned earlier that you were working on one I thought about asking you about collaboration, however I can see that our overall desires for design would not work together at this time. Having a native look is not that important to me at this time, my GUI's idea of cross-platform is using Allegro while allowing customization by the user to the extent I am able to program in. I would like to achieve your 3rd goal of simplicity as well but I'll have to see how that goes. Regarding 4), boost seems like bloat to me, especially if it is just to manage memory. This can easily be taken care of with proper ownership. I agree with 5) but 6) seems like a feature I wouldn't have time for in the first version. In any case, good luck and good coding. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
axilmar
Member #1,204
April 2001
|
Quote: I am not a fan of using boost... I'd prefer the 3rd point to be "simple and small" which would rule out using boost... Why recreate shared ptrs and signals/slots when boost has them ready for us? I had a problem with boost too 'cause I am no fan of 'build it yourself', but since I discovered boostPro, I changed my mind. The aforementioned free download offers precompiled binaries for Visual Studio. But it's not that hard to download and compile boost yourself. I did it on several occasions. You just download bjam, invoke bjam in the appropriate directory, wait a little and ...hey presto, you've got the binaries. Recreating shared ptrs, weak ptrs, boost::bind and boost::signal is a major package of work itself. Quote: I've been gearing up to start on my own GUI and since you had mentioned earlier that you were working on one I thought about asking you about collaboration, however I can see that our overall desires for design would not work together at this time. Sorry, I was talking about an application-oriented library. Creating a good gui library for Allegro was a dream of mine a few years back though. Do you have a proposal? I might be interested. |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Quote: Creating a good gui library for Allegro was a dream of mine a few years back though. Do you have a proposal? I might be interested.
Well, I'd like to keep it pure Allegro if possible to be useable as an add on package. Really though, I'm still in the brainstorming phase. I started putting together some of the basic layout ideas but give me a few days to have a more concrete proposal of any kind. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
axilmar
Member #1,204
April 2001
|
Edgar, Are you talking about a game-oriented GUI, an application-oriented GUI, or both? |
|
Matthew Leverton
Supreme Loser
January 1999
|
Are you polling for interest because you want help designing it? Coding it? To know if it's worth your time? You will be best off to just code the base and a few widgets yourself. Then build some sample applications and release it all. That's the only way you'll both get it working and get some help. As soon as you introduce other people into the "brainstorming," you'll never come to a satisfactory design as everybody will want their own way because they are all programmers that could do it themselves if they had the ambition. But if you get something working, people will care less about the implementation details and more about getting more widgets done. Hopefully that is your plan, because on the Internet it is unfortunately the only way things work. |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Quote: Are you talking about a game-oriented GUI, an application-oriented GUI, or both? Well, both really. I'm not quite sure what your ideas of the differences between them are though. If you could tell me that I should be able to give you a better answer. I don't seem to have a differentiated notion of one from the other. One of the main things I'd like to accomplish is a smooth interface between the gui and the function it runs in so that information is easily passed back from the gui to let the function alter settings, update objects, and so on. I'd basically like the gui to be able to interact with other objects without making those objects part of the gui or its components. One thing that's proving difficult for me to imagine is the design scheme of modern program guis. Is there some kind of super global object that knows everything and how to manipulate it or what? Maybe I need to check out some open source projects for some design ideas. Quote: You will be best off to just code the base and a few widgets yourself. Then build some sample applications and release it all. That's the only way you'll both get it working and get some help. That's probably how I'll do it. I wouldn't mind some advice on flexible object interface techniques but that may be better left to ask for in a different thread. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
axilmar
Member #1,204
April 2001
|
Matthew Leverton said: Are you polling for interest because you want help designing it? Coding it? To know if it's worth your time?
a) I want help designing it. Edgar Reynaldo said: I'm not quite sure what your ideas of the differences between them are though. The update method for a game GUI is different from the update method for an application GUI. For applications, the traditional method of putting paint events in a queue is adequate for most GUI cases. For games, it's not acceptable: the update method has to be mixed with the game graphics update method. Edgar Reynaldo said: One of the main things I'd like to accomplish is a smooth interface between the gui and the function it runs in so that information is easily passed back from the gui to let the function alter settings, update objects, and so on. Hey, me too. I am fed up having to code a lot of lines of code just to do the most trivial tasks, i.e. change a variable etc. What I've done in my latest project (using Qt 3.0.5) is to write connection objects between data models and widgets. Qt 3 does not support the Model-View-Controller paradigm, so I had to do this. It works exceptionally well. Say, for example, that I want to edit an int variable. All I have to do is: int var; new LineEditConnection<int>(var, new QLineEdit(form)); The connection object connects the QLineEdit's signals with its own slots, knows how to convert a String to an int, and sets automatically the variable 'var' to the appropriate value. I think this model of connecting things together with external classes is better than the Model-View-Controller paradigm, because it's much more flexible. With the MVC model, you are limited to what the author of the library thought is required. With this solution, you can connect anything to anything, provided that the necessary events/signals/callbacks/etc are provided. Edgar Reynaldo said: Is there some kind of super global object that knows everything and how to manipulate it or what? Certainly not. All GUIs provide events; you have to create a good way of catching those events and connecting them to the appropriate handlers. The handlers themselves should contain all the necessary information to change the data as needed. |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Quote: For applications, the traditional method of putting paint events in a queue is adequate for most GUI cases. For games, it's not acceptable: the update method has to be mixed with the game graphics update method. I think that I would like a more direct method, that all necessary logical updates are performed and then the view is updated all at once and not asynchronously with a paint event queue. I may have misunderstood you though. Quote: What I've done in my latest project (using Qt 3.0.5) is to write connection objects between data models and widgets. Qt 3 does not support the Model-View-Controller paradigm, so I had to do this. It works exceptionally well.
It looks quite handy. I'd like to have widgets like this built in to my gui. // class IntEditor : public TextEntryWidget {/* Magic */};// All widgets derived from GuiBase GuiManager* Gui = new GuiManager; int number = 0; GuiBase* int_editor = new IntEditor(&number); Gui->AddComponent(int_editor); // What I haven't fully imagined is a good way to handle the dependencies on that integer. Does it set a mode or merely a value and what needs to be updated because of it? Should this be accomplished through building callbacks into the widgets, if so is there anyway to avoid forcing the user to use specific call back types. Should the gui return a list of events that the user has to process into what needs to be updated, if so, what's a nice way to do that and stay organized? Quote: Certainly not. All GUIs provide events; you have to create a good way of catching those events and connecting them to the appropriate handlers. The handlers themselves should contain all the necessary information to change the data as needed. It would be nice if I could build in a way for my gui objects to be able to call the handlers themselves, although I don't know a nice way to handle diverse function types and the appropriate way to pass in the correct arguments as well. I'll have to look over some of Boost's signal/slot source code and see if I can find some inspiration. One thing I have to learn about is function objects. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
axilmar
Member #1,204
April 2001
|
Quote: I think that I would like a more direct method, that all necessary logical updates are performed and then the view is updated all at once and not asynchronously with a paint event queue. That's the best way to handle updates in a GUI. It also covers the case of a game GUI. Quote: What I haven't fully imagined is a good way to handle the dependencies on that integer. Ah, you are correct. My code example above shows how the widget changes the integer, but not how the integer changes the widget. I intentionally omitted the part where the integer is not really an integer, but a Property<int> instance. The property has callbacks for when modified, and the connection object modifies the widget if the property's value is changed. Quote: Does it set a mode or merely a value and what needs to be updated because of it? Should this be accomplished through building callbacks into the widgets, if so is there anyway to avoid forcing the user to use specific call back types. Should the gui return a list of events that the user has to process into what needs to be updated, if so, what's a nice way to do that and stay organized? You only need a few primitives (model objects with 'change' callbacks, connection objects that connect the model objects with the widgets). You don't need callback types or anything else you mention. Quote: It would be nice if I could build in a way for my gui objects to be able to call the handlers themselves, although I don't know a nice way to handle diverse function types and the appropriate way to pass in the correct arguments as well. You can do that sort of thing with boost::bind: you can bind any values to a function. It's very sophisticated, and a great deal of work to do on your own. |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Quote: Ah, you are correct. My code example above shows how the widget changes the integer, but not how the integer changes the widget. I was thinking more along the lines of that the integer is a setting somewhere else independent of the gui and what would be an efficient and practical way to notify the user that the setting had changed. Should it be a message returned by the gui that gets processed by the user or should the widget know what method(s) to call to take care of updating whatever is dependent on the value of that setting? I realize you were talking about the integer in an abstracted way, I just wanted to keep the question down to effective gui and widget behaviour and the methods of achieving it. Quote: You only need a few primitives (model objects with 'change' callbacks, connection objects that connect the model objects with the widgets). You don't need callback types or anything else you mention. If there are model objects with change callbacks and connection objects connecting the model objects with the widgets, why not just build the callbacks into the widgets and make the user register one? What I mean is that the user could register a function pointer with the widget to call when the data changes. Were you talking about using the boost library to accomplish this? I haven't decided whether I want to include it but I'd prefer for the gui to only be dependent on allegro. Something I'd like to avoid is gui code that forces the user to use lots of global variables. This pollutes the namespace and leads to scattered code which I'd like to stay away from. This is why I want to build more functionality into the widgets themselves which will hopefully help keep the scope localized to the function the gui runs in. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
axilmar
Member #1,204
April 2001
|
Quote: I was thinking more along the lines of that the integer is a setting somewhere else independent of the gui and what would be an efficient and practical way to notify the user that the setting had changed. Should it be a message returned by the gui that gets processed by the user or should the widget know what method(s) to call to take care of updating whatever is dependent on the value of that setting? I realize you were talking about the integer in an abstracted way, I just wanted to keep the question down to effective gui and widget behaviour and the methods of achieving it. Talking with actual code is always easier:
In the above code:
So now you have a perfect connection between the UI and the data, specified externally. Quote: If there are model objects with change callbacks and connection objects connecting the model objects with the widgets, why not just build the callbacks into the widgets and make the user register one? What I mean is that the user could register a function pointer with the widget to call when the data changes. Because keeping the widgets independent from the model:
Quote: Were you talking about using the boost library to accomplish this? I haven't decided whether I want to include it but I'd prefer for the gui to only be dependent on allegro. Why re-invent the wheel? boost is there, it works out of the box. Furthermore, I'd like to use:
Quote: Something I'd like to avoid is gui code that forces the user to use lots of global variables. This pollutes the namespace and leads to scattered code which I'd like to stay away from. This is why I want to build more functionality into the widgets themselves which will hopefully help keep the scope localized to the function the gui runs in. From my experience, a GUI application is composed of 3 things:
Good separation of concerns is the #1 quality of any good program. |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Quote:
In the above code: This is helpful certainly, but it is not the entire picture - neither TextBox::set nor Model<int>::set will generally know much about the display logic of the system involved. TextBox::set may know to pass back NEED_REDRAW to a gui manager that could have called it, but it's unlikely that Model<int>::set will know whether the user needs to update any graphics display related to the setting. Does boost::bind allow the return value of a function to be passed somewhere as well? It seems to me a message has to be passed back along the proper channels to notify the user by means of the gui interface : // // Messages for the gui to pass back to the user to allow for dependency updates and for the gui to process const int WIDGET_SETTING_CHANGED = 1;// for the gui to tell the user that one of the widgets changed a data setting const int CHANGED_WIDGET_SETTING = 2;// for telling the gui that one of it's widgets settings has been changed outside of the gui const int Other_Notifications... class GuiUserMsg { public : WidgetId widgetid; int usermsg; }; std::vector<GuiUserMsg*> GuiManager::GuiUpdate(); void GuiManager::UserMessages(std::vector<GuiUserMsg*>*); //
Quote:
Because keeping the widgets independent from the model: I agree that they should both be autonomous, but that doesn't mean that the widgets can't have generic call backs available if the user desires it. I think that I'd rather handle this with a message system though, having the widget notify the gui of a setting change through a return, which the gui relays on to the user who is allowed to make the necessary dependency updates. I think this allows for the most flexibility by the user. Quote: Why re-invent the wheel? boost is there, it works out of the box. I'll download it tomorrow - it will take me 3 hours to do it though as the source is 22MB in the smallest compression package, a .7z file. However, it seems like adding boost to the gui I'm working on may reduce the achievement of one of my main goals - simplicity for the end user with few if any dependencies. The part about boost generally being wholly contained in headers is interesting. I agree that Boost could be quite useful for the gui version you're looking to create though as it seems more like it is destined to be a professional developer package. In any case, I've monopolized enough of your time and it looks you want to go a different direction for an Allegro Gui than I do. Thank you for your advice and answering my numerous questions. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
axilmar
Member #1,204
April 2001
|
Quote: It seems to me a message has to be passed back along the proper channels to notify the user by means of the gui interface I don't understand why you have the notification mechanism. Can you explain why you think it is more useful than signals and slots? The data model should never tell anyone to redraw anything. That's the job of the connected views. Quote: I agree that they should both be autonomous, but that doesn't mean that the widgets can't have generic call backs available if the user desires it. I think that I'd rather handle this with a message system though, having the widget notify the gui of a setting change through a return, which the gui relays on to the user who is allowed to make the necessary dependency updates. I think this allows for the most flexibility by the user. So, are you saying that, instead of connecting the widget to the model, the widget should be connected to something else, and this something else should actually modify the model? Well, that's possible, as well, with signals and slots. In my example, the connection between the text box widget and the model is done externally: the text box does not know anything about the model, and vice versa. So, instead of connecting the model directly to the widget, you can connect something else to the widget. I see no need for a messaging queue in either case. Quote: However, it seems like adding boost to the gui I'm working on may reduce the achievement of one of my main goals - simplicity for the end user with few if any dependencies. Actually, adding boost to your project will simplify it: shared ptrs, bind, etc simply the development greatly. Quote:
In any case, I've monopolized enough of your time and it looks you want to go a different direction for an Allegro Gui than I do. Thank you for your advice and answering my numerous questions. Thank you very much for the discussion. |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
Quote: I don't understand why you have the notification mechanism. Can you explain why you think it is more useful than signals and slots? I see it like this - the function running gui->GuiUpdate() (asking for user input) is basically asking to know what the user has changed setting and selection wise so it makes sense to me to have GuiUpdate() return notifications as to what the user input resulted in. Basically, I think it just needs to return which widget it was that changed a setting. From the widget id, the local function knows what setting was changed and what it should do about it. With only signals and slots between the widget and the data it modifies, the controller (local function) is cut out of the loop and it seems it would have to check whether the data changed before it could make an appropriate decision as to what else needs to be done based on the relevance and context of the data modified by the widget. I think another limitation of signals and slots is that the scope they are run from might not necessarily have all the context needed to make the appropriate calls, although I haven't programmed with them before and I don't really know this. Quote: So, are you saying that, instead of connecting the widget to the model, the widget should be connected to something else, and this something else should actually modify the model? Yes, my idea is that the widget relays information to it's controller, the Gui class, which relays information back to it's controller the local function which then makes the relevant decisions what to do with the information. In a static gui in which all of the data modified remains unused until the gui is closed, I can see that GuiUpdate() might not need to return any information and the user is still free to ignore the function return if they wish to do so. Notifications should allow for both a statically run gui where the settings are checked after the gui closes and one where it is run interactively, effectively becoming an extension of the function. At least I hope so. Just got Boost downloaded, I'll check it out tomorrow. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
axilmar
Member #1,204
April 2001
|
Quote: I see it like this - the function running gui->GuiUpdate() (asking for user input) is basically asking to know what the user has changed setting and selection wise so it makes sense to me to have GuiUpdate() return notifications as to what the user input resulted in. Basically, I think it just needs to return which widget it was that changed a setting. From the widget id, the local function knows what setting was changed and what it should do about it. With only signals and slots between the widget and the data it modifies, the controller (local function) is cut out of the loop and it seems it would have to check whether the data changed before it could make an appropriate decision as to what else needs to be done based on the relevance and context of the data modified by the widget. In case you have signals and slots, you don't need the local function. It's work can be done inside the slots. Quote: I think another limitation of signals and slots is that the scope they are run from might not necessarily have all the context needed to make the appropriate calls, although I haven't programmed with them before and I don't really know this. That's why you use boost::bind for: to bind the required scope to the slots. Quote: Yes, my idea is that the widget relays information to it's controller, the Gui class, which relays information back to it's controller the local function which then makes the relevant decisions what to do with the information. One problem with your mechanism is that you need a lot of event classes to represent all possible data changes, whereas with signals and slots you don't need those event classes, as the data are directly passed to the slots. Quote: In a static gui in which all of the data modified remains unused until the gui is closed, I can see that GuiUpdate() might not need to return any information and the user is still free to ignore the function return if they wish to do so. Notifications should allow for both a statically run gui where the settings are checked after the gui closes and one where it is run interactively, effectively becoming an extension of the function. At least I hope so. Nothing prevents you from not connecting a GUI to a model in the case of signals and slots. Suppose you have a modal dialog: you don't connect any widget to a model. The widgets change their contents, and when the user presses OK, then the data are transferred to the models. There is one benefit from using a queue of events: the changes are there for anyone to see and process in their own pace. There is also a drawback: the queue of events might contain multiple successive changes of the same widget, whereas only the last change is relevant. The event queue can be simulated almost automatically by the signals and slots mechanism, if you connect widget signals to slots that put data in a queue. |
|
|
1
2
|