|
A question for Steve Terry, Miran, Spellcaster and other GUI people! |
vpenquerch
Member #233
April 2000
|
Do not plan to abandon yours and join the common cause. EDIT: Some comments on the source. Well, part of it (the event.h file and don't assume left/middle/right buttons: make the button the message EVENT_LEFT_DROP: I'd suggest adding a type for your timestamps, not just int. It can prove Also, add a type for geometry (eg, Maybe a vec2, which is two coords, Don't put everything and the rest in the event struct. It's supposed to I'd remove the routines from the event struct, and move them into a new Have an EventQueue rather than statics in event to deal with the list. > Widget *root() const; That should be static, I assume it's a typo. Same for Widgets as for events, don't have too many statics, prefer a Sometimes a pain, but, when it makes sense, add two versions of your Widget *widgetAtXY(int,int); ///removes and destroys all children widgets SIGSEGV Good luck, and do not abandon it if you think it |
axilmar
Member #1,204
April 2001
|
Vincent, thanks for having a look at my code. Your comments are greatly appreciated. Let me ask you a few questions and comment on your proposals. Quote:
don't assume left/middle/right buttons: make the button the message EVENT_LEFT_DROP: In other words, replace EVENT_LEFT_BUTTON_DOWN, EVENT_RIGHT_BUTTON_DOWN, EVENT_MIDDLE_BUTTON_DOWN, EVENT_LEFT_BUTTON_UP, EVENT_RIGHT_BUTTON_UP, EVENT_MIDDLE_BUTTON_UP with EVENT_BUTTON_DOWN, EVENT_BUTTON_UP so as that the class itself can choose what to do e ? Something like this: bool buttonDown(const Event &event) { switch (event.button()) { case LeftButton: <bla bla>... case RightButton: <bla bla>... case MiddleButton: <bla bla>... } } Right now, if the buttons are reversed, the rightButtonDown and rightButtonUp will be called if the left button is pressed. What are the advantages of the implementation you are proposing ? Quote:
I'd suggest adding a type for your timestamps, not just int. It can prove I agree. How shall the type should be declared ? should it be global or part of the Event namespace ? Quote:
Also, add a type for geometry (eg, Maybe a vec2, which is two coords, Ok, the Rect class will be put back. I was hoping that noone will notice this!!! I did it to save the library from one more class, but anyway it was a not so clever thought from the start. A Rect class is useful anyway. Quote:
Don't put everything and the rest in the event struct. It's supposed to I wasn't planning for an event queue that custom events would go into. My definition of an event is either a mouse, a keyboard or a timer event. I.E. something coming from the hardware input devices only. The way it is designed, it is impossible to do it, because the Event class is simply a place holder for the event data. If you check the Event internals, you will see that everything is in plain C; there is a reason for this: I don't want to mix event callbacks that might be called from interrupts with C++ (for example, I can't lock STL containers with LOCK_VARIABLE). Another reason that I don't want Event to be a virtual base class is because if I did so, then the library would constantly allocate and deallocate Event-derived objects. Which means memory fragmentation. I don't think it is necessary to fragment the memory so much just to provide the programmer a feature to put his/her own events in the event queue. In case you know from other libs (Qt for example) that custom events are useful in a multithreaded application, I have other solutions for thread communication (which would be a different library from a GUI anyway). Quote:
Have an EventQueue rather than statics in event to deal with the list. I would like only one event queue. If there was an event queue class, the programmer would be misled that each time he/she wanted to make an event loop, he/she has to declare an EventQueue (assumingly with different contents). By not having an EventQueue class, it is implicitely understood that all events come from the same queue. To tell you the truth, I don't really see an advantage in what you are proposing. Would you care to elaborate with a few examples ? Quote: > Widget *root() const; That should be static, I assume it's a typo. No, not at all. The static method is: Widget *Widget::rootWidget(); which returns the current root (or desktop) widget. The plain 'root()' method returns the Widget that is root of the widget tree that is called from, which might not be currently on the screen. Quote:
Same for Widgets as for events, don't have too many statics, prefer a I tried that, but it did not look good enough to me. At one iteration of my design, I thought "let's make nothing static". The result was that I had to declare lots of "manager" type classes that holded the state of a gui, without significant gain: after all, there is only one screen, one widget tree active at a time, one mouse, one event queue...and this is unlikely to change in the near future. (Even if two or more screens where present, that would mean a "list" of root widgets, but not more than one event queues, not more than one case of drag-n-drop, etc). And then there is another problem : how to retrieve the current 'static' information from inside the widget, without the widget knowing the "manager" variable that holds the current state. I would have to have statics, it can't be avoided. So, instead of:
I go for :
Which is much simpler and does the same job. My line of thought is "keep it simple", simple enough to satisfy 90% of the user requirements. There is fine balance between simplicity and bloatness. I don't want my library to cross that limit. In other words, I don't want to put features that would be useful only in 10% of the use cases!!! the other 90% will blame me for not having followed the easiest way to do the job... |
vpenquerch
Member #233
April 2000
|
About events and mouse buttons: yes, that's what I meant. > What are the advantages of the implementation you are proposing ? Extensibility: when you decide to supprt a fourth button, you do > I agree. How shall the type should be declared ? should it be global Depends on whether you want it to be event specific or not. I'd > My definition of an event is either a mouse, a keyboard or a timer event. You don't cater for, say, tilt information from tablets. Even if you > I can't lock STL containers with LOCK_VARIABLE Interesting, I hadn't thought of that at all. > Another reason that I don't want Event to be a virtual base class It was only an image - but the memory problem you mention would apply > In case you know from other libs (Qt for example) Sorry, I don't. I'm just talking out of common sense and experience > I would like only one event queue. My point was more with the ability to control how it behaves. It can > If there was an event queue class, the programmer would be misled No, that is user error, and an easy one (assuming it is documented). > To tell you the truth, I don't really see an advantage in what you Here's one: I want my event queue to transform all occurences of right click and I see your point in making the lib simple though. My comments would Keep it up |
axilmar
Member #1,204
April 2001
|
Thanks Vincent, this is the type of discussion I expect on these boards. Quote:
Extensibility: when you decide to supprt a fourth button, you do Ok, proposition accepted. Quote:
Depends on whether you want it to be event specific or not. I'd In the end, maybe I put a namespace to the library. The time type would be a global type. Quote:
You don't cater for, say, tilt information from tablets. Even if you Maybe in the end I'll change the event internals, if it is requested by many. Right now, I don't think that anyone will care. Quote:
Another example: joystick: they would probably send other messages. Joystick to move the mouse around ? I don't see a reason for this. There is no computer without a mouse these days. Again, this will be implemented only if requested by many users. Quote:
It was only an image - but the memory problem you mention would apply Right now I am using a simple _EVENT struct to create a rotating buffer (struct _QUEUE). Very simple. If I add internal memory management on event allocation, I will make it very complex. I would like to avoid complexity. Quote:
Sorry, I don't. I'm just talking out of common sense and experience If I was to make a high level generic GUI toolkit, then I would definitely incorporate your proposals. Right now, I am thinking along the lines "a simple GUI library". Since I am solo, I don't have the time and appetite to add more functionality. I hope you understand this. Quote:
I want my event queue to transform all occurences of right click and This can be easily done from inside the mouse_callback. Doesn't Allegro offer the capability to emulate a 3 button mouse anyway ? Quote:
I see your point in making the lib simple though. My comments would Thank you. Really. A GUI lib is quite a complex thing, and I am alone. I have given much thought into many topics, but I can't handle it all alone. That's why I aim for simplicity and sacrifice a few complex functionalities. Do you have any proposition for the widget set ? which widgets would you like to see ? |
vpenquerch
Member #233
April 2000
|
> Joystick to move the mouse around ? I don't see a reason for this. No, this is just an example. The main point being, > This can be easily done from inside the Yes, but, once again, it's an example to show that |
axilmar
Member #1,204
April 2001
|
Yes, that's my purpose. If something comes up, I will modify the library, but for now, "keep it simple!!!"...as simple as it gets!!! Do you have a list of widgets that you would like to see implemented ? EDIT: Here is my list: static widgets(widgets that don't respond to user input): buttons: scrolling: Menus: Text editing: views: Windowing: Framework: Common dialogs: Please note that widget names are not definitive: if someone proposes something better, it will be accepted. I tried to keep the names as close to the common terminology as possible. The programming style would be very simple: just put one widget inside the either from parent to child, connect signals and slots and make an event loop. Example:
|
vpenquerch
Member #233
April 2000
|
Not particularly. |
spellcaster
Member #1,493
September 2001
|
Regarding labels: They do get userinput. One of the main features of a label is to provide a shortcut key for the widget it's associated to. So a label would react on the keypress by focusing / selecting the widget it's associated to. I'd also suggest to avoid a single root widget. If you're using c++ use a list (or any other container) as root. If you just have one root widget it doesn't hurt, and it allows you to have several widgets which don't have a common parent. If you decide to stick with your single root widget solution, don't make it a global. Create a class and/or struct to contain your global information, so the complete state of the gui is inside a single object. This allows the user to use several instances of the gui. -- |
axilmar
Member #1,204
April 2001
|
Quote:
Not particularly. Do you mean to have two libraries ? one for the 'window system' and one for the 'widgets' ? I tried that also. I tried to make a widget set using MxWindows as the gui. It works, but the actual window system is a tiny fraction of the toolkit, so, for simplicity reasons, I thought they should be intergrated. Just "#include <algui.h>", link with "algui.lib.so.whatever" and be done with it. Quote: Regarding labels: They do get userinput. One of the main features of a label is to provide a shortcut key for the widget it's associated to. So a label would react on the keypress by focusing / selecting the widget it's associated to Gotcha. This will be provided. Widget categorization above was for just showing what I have in my mind. Quote: I'd also suggest to avoid a single root widget. If you're using c++ use a list (or any other container) as root. If you just have one root widget it doesn't hurt, and it allows you to have several widgets which don't have a common parent. If you decide to stick with your single root widget solution, don't make it a global. Create a class and/or struct to contain your global information, so the complete state of the gui is inside a single object. This allows the user to use several instances of the gui AlGui does have one "root" widget, i.e. only one root widget is currently on the screen. But widget trees can happily live off the screen, until they are added to a widget that is on-screen or be made "root" with a call to 'setRoot()'. Here is the code: //returns the current "root" widget, i.e. the root widget that is on the screen static Widget *Widget::rootWidget(); //returns the root widget of this tree Widget *Widget::root() const; //sets the current root widget bool Widget::setRoot(); If the user wants to make a multiscreen application, he/she can call 'setRoot' to set a widget as the current root. He/she can construct multiple widget trees, each one with their own root (the local tree's root), and activate each widget tree by calling 'setRoot'. EDIT: To all: do you find the above widget list adequate ? any other widget suggestions ? |
vpenquerch
Member #233
April 2000
|
I find the above widget list comprehensive. |
spellcaster
Member #1,493
September 2001
|
Quote: AlGui does have one "root" widget, i.e. only one root widget is currently on the screen. But widget trees can happily live off the screen, until they are added to a widget that is on-screen or be made "root" with a call to 'setRoot()'.
Assume you hae a game. The gui should be displayed on top of the game running at 60 fps, but it should render itself / react to events only with 20fps. If you have several top level widgets, no problem. But how do you handle this with a single top level widget? -- |
axilmar
Member #1,204
April 2001
|
Quote:
(eg, an HTML renderer is not a It will only display HTML 1.0 and only some basic tags. It is necessary if an application must show help files. I have already done some of the work in past projects. Actually, it is not very difficult to make an HTML renderer. Basically, each HTML renderer widget is a giant "list box". Each row of the list box can contain text, graphics, widgets, etc. You can fill this special "list box" from the HTML stream, as the stream is retrieved from the disk/network. Each row's size will be modified according to the size of the elements of the received data on the fly. Quote:
Assume you hae a game. The gui should be displayed on top of the game running at 60 fps, but it should render itself / react to events only with 20fps. If you have several top level widgets, no problem. But how do you handle this with a single top level widget? You make a root widget that is the container of all these unconnected widgets. This root widget will draw nothing, it will be positioned at the screen 0, 0 pixel and it will have the size of the screen; its children, the widgets you are interested in, will have a x, y position relative to the root equal their screen position, since their parent is at screen 0, 0. In other words:
|
vpenquerch
Member #233
April 2000
|
> Actually, it is not very difficult to make an It's hard to make a good one |
axilmar
Member #1,204
April 2001
|
Quote: It's hard to make a good one It would be good to have one, though. For showing help files. The stack can't be avoided. |
|
|