Thread: GUI Design Question (Seeking an opinion)

  1. #1
    Registered User
    Join Date
    Aug 2004
    Posts
    77

    GUI Design Question (Seeking an opinion)

    In my spare time I've been constructing a cross platform API in my basement. Not that I expect anyone to use it, there's certainly better options available, its just been a heck of a challenge and forced me to learn many things I may not have looked into otherwise.

    Anyway, I'm to the point where I'm building GUI controls. The basic label/static controls, buttons, text boxes, etc. I'm torn on how the event callbacks should work and how to set the control properties.


    Since all of my controls will be class based I can use virtual functions to give the events to the users. However, that means all events need individual functions. Sometimes thats a bit of a pain and using a single callback function would be nicer.

    So if you were dealing with a GUI API what would you rather deal with? Essentially C callback functions which can be used for one or more events, or virtual functions that would deal with a single event.

    I suppose I could permit both, but how do you determine which one the user wants to use? Particularly if the user attempts to set both.


    The next question I had was how to handle the properties for all the windows and controls. I liked the VB style where you just set a value and that was it. Obviously you can't do that in C, so whats the next best choice?

    I had though about using a generic SetProperty() function that accepted a property name and a variant style value to set the property. The problem I have with that is getting properties that use multiple values. Like the position has an X and Y value/coordinate; and background or foreground colors have three values the red, blue, and green components. The only way to do that would be to have specific function calls for those particular properties.

    I don't much like the look of the extra overhead in supporting both methods of setting the properties. Particularly if most people would use one type almost exclusively, so once again were you dealing with a GUI API which would rather use?


    Thanks in advance for any thoughts on these.
    So, do you understand everything you know about this yet?

    "Begin at the beginning," the King said, very gravely, "and go on till you come to the end; then stop."

  2. #2
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Essentially C callback functions which can be used for one or more events, or virtual functions that would deal with a single event.
    Well, since you can subclass (is that just a Java term?) several times, you can derive a BasicButton class that overrides the functions you want shared, and then derive your actual button classes from that one and specialize each to their unique needs.

    Both callbacks and overridden virtuals have their advantages. Virtuals have the advantage of being intuitively defined as part of the class, as the popular trend seems to go, but have the disadvantage of (if you plan to share functions) being potentially quite messy - and, of course, virtuals mean you'll have to derive some classes yourself, which I find a pain in the butt. Callbacks can also be messy, but you can organize them into their own files/namespaces/other organizing stuff. The disadvantage of using callbacks is that you'd need to have some mechanism for identifying the object in question when the callback is invoked.

    I had though about using a generic SetProperty() function that accepted a property name and a variant style value to set the property.
    By 'property name' I'm assuming you mean you'll be defining constants (or an enumeration) that indexes an array of properties, rather than doing a string lookup for each time you set a property. Also, by 'variant style', do you mean you'll have a whole pile of overloaded SetProperty() functions, or do you mean you'll have it accept a string and then convert it as appropriate?

    >>The problem I have with that is getting properties that use multiple values.
    Consider creating a Property struct, and deriving child structs that contain any data you need contained:
    Code:
    struct Property
    {
       std::size_t structSize;
    };
    
    struct PositionProperty : public Property
    {
       PositionProperty() :structSize(sizeof(*this)) {}
       int x;
       int y;
    };
    
    Property* SetProperty(int property, Property* value)
    {
       if(value->structSize != properties[property]->structSize)
          return value;  //Return of same property signals 'no change'
    
       Property* temp = properties[property];
       properties[property] = value;
       return temp;  //Return old property
    }
    
    ...
    
    (internal implementation)
    PositionProperty& p = *((PositionProperty*)(theObject.getProperty(PROPERTY_POS)));
    theObject.drawObject(p.x, p.y);
    Something like that should work, though it's quite messy.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  3. #3
    Registered User
    Join Date
    Aug 2004
    Posts
    77
    Quote Originally Posted by Hunter2
    By 'property name' I'm assuming you mean you'll be defining constants (or an enumeration) that indexes an array of properties, rather than doing a string lookup for each time you set a property. Also, by 'variant style', do you mean you'll have a whole pile of overloaded SetProperty() functions, or do you mean you'll have it accept a string and then convert it as appropriate?
    Yeah, you have those right. Guess I could have explained those better. The properties would be an enumerated list of values that define how the window looks and acts. The basic window settings (size, postion, colors, etc) as well as functional things that are specific to the control (call back functions if they end up an option, text to display, tab stops, and so on). Any value of importance for controlling the window can assumed to be represented as a property.
    As for the variants, I had in mind using a variant class that basically does what you said. You feed it a value and it converts it to a number of formats (strings, floats, ints, etc), but still only dealing with 1 value no arrays inside the variant. So essentially you could pass it a string and let it convert it.
    So, do you understand everything you know about this yet?

    "Begin at the beginning," the King said, very gravely, "and go on till you come to the end; then stop."

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>but still only dealing with 1 value no arrays inside the variant.
    I suppose, you could always just store each value separately (i.e. not in arrays).. after all, that's how most of the VB stuff is done (.Left and .Top instead of pos.x, pos.y). The reason I suggested what I did was because Windows API does something similar with SelectObject() - it takes a HGDIOBJ, which appears simply to be a generic pointer-type thing that all GDI object types can be typecasted to, but depending on exactly what kind of GDI object is passed to it the function behaves differently (i.e. HBRUSH, HBITMAP, etc. with their different properties).
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #5
    Registered User
    Join Date
    Aug 2004
    Posts
    77
    To be honest I really liked your suggestion over the use of variants. It gives me more flexibility in the property types. I highly doubt any variant type would permit function pointers as a value, and I wanted to allow callback function pointers as a proprty.
    So, do you understand everything you know about this yet?

    "Begin at the beginning," the King said, very gravely, "and go on till you come to the end; then stop."

  6. #6
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    That's an interesting way of going about mixing virtual/callback
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  7. #7
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    In my spare time I've been constructing a cross platform API in my basement. Not that I expect anyone to use it, there's certainly better options available, its just been a heck of a challenge and forced me to learn many things I may not have looked into otherwise.
    You're probably best off doing a smaller version, for instance, writing a diagram library.

    Anyway, I'm to the point where I'm building GUI controls. The basic label/static controls, buttons, text boxes, etc. I'm torn on how the event callbacks should work and how to set the control properties.
    Since all of my controls will be class based I can use virtual functions to give the events to the users. However, that means all events need individual functions. Sometimes thats a bit of a pain and using a single callback function would be nicer.
    You might find the pattern Java uses for it's models. Here's an example. Say you have a button model
    class ButtonModel { }
    This model stores data(in Java some GUI elements have two models, one which is display data and another which is the abstraction). When the data inside the ButtonModel changes it notifies a ButtonChangeListener.
    Code:
    class ButtonChangeListener {
    public:
             virtual void stateChanged(const ButtonChangeEvent& e) = 0;
    };
    The ButtonChangeEvent of course has data about the event which took place: which view modified the model, which type of event, and perhaps some other form of data used by the event.

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You might want to use the Boost.Signals library for the events.
    http://www.boost.org/

    Among other things, it allows you to use member functions bound to an object as the callbacks. I had this implemented at home, but I can't access the code right now.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Registered User
    Join Date
    Aug 2004
    Posts
    77
    If I'm understanding things right, it sounds like the Java set and the boost.org signals library are fairly similar.

    I would create one class that represents the control, then the users essentially create another class that I send the events to. It avoids the user having to create a wrapper around all of the control classes.
    So, do you understand everything you know about this yet?

    "Begin at the beginning," the King said, very gravely, "and go on till you come to the end; then stop."

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    If I'm understanding things right, it sounds like the Java set and the boost.org signals library are fairly similar.
    No, actually not at all. Boost.Signals is far more alike to the C# delegate model.


    But the purpose for which you would use it would be similar.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 12-22-2006, 11:50 PM
  2. design question: opinion
    By ggs in forum C Programming
    Replies: 2
    Last Post: 01-29-2003, 11:59 AM
  3. Replies: 4
    Last Post: 11-19-2002, 09:18 PM
  4. OO design question
    By PJYelton in forum C++ Programming
    Replies: 8
    Last Post: 10-10-2002, 12:52 PM
  5. GUI Design for the first time!
    By westie in forum C Programming
    Replies: 5
    Last Post: 11-22-2001, 11:45 PM