First of all, like snake5 said, only use DOD when necessary. If your GUI code already works and takes only 1-5% execution time, don't even try to rewrite it. It's not worth it. If you haven't written most of it, you could consider it, but only if you have a really fancy UI that's going to take a lot of processing power.
Or maybe you just feel like writing some code using DOD, in that case just go ahead and play with it.
Now to answer your question. Yes you're right, different widgets have different data and maybe they're rendered differently. Are they really that different though? I don't know the features you need for your UI, but I can imagine lots of components share a lot of data. Some examples:
- All widgets have a position and size (and bounding box)
- Buttons, checkboxes, textboxes, etc all listen to mouse events using the bounding box
- Images, buttons, labels can all have images to render
- Buttons, labels, textboxes, textfields etc all have to render text
I'm sure there are more similarities if you take some more time to think about it. So we've established similarities and if you look at the description above, you can see that each widget type is composed of several (let's call them) "components". Let's take a button for example, it consists of:
- Spatial element
- Text renderer
- Image renderer
- Mouse handler
While a textbox consists of:
- Spatial element
- Text renderer
- Mouse event listener
- Keyboard handler
So let's create a struct (or class) with the data for each component. For instance:
struct Spatial {
vector2 position;
vector2 size;
float depth;
rectangle boundingBox;
bool dirty; //set to true when pos or size is changed, calculates bBox again
}
Then, create a manager for Spatial. The manager has a flat list of Spatial structs, and when update is called it will go through all of them and update the boundingBox if dirty is true
Do the same for each of the other components. TextRenderer updates and renders text on the screen, MouseHandler can call button callbacks or set checkbox state or determine which element has focus. KeyboardHandler updates the text of a textfield if it has focus.
Now, when we want to add a button, we don't actually add a button, but a set of components to the respective managers. The last thing we need is a UIElement class which has pointers/indices of all the components in the different handlers, so we can find them back, for instance when we want to delete it, or when one component needs info from another component.
So there you have the pitfall of OOP. You think of widgets as an object. Therefore, you naturally come to the conclusion that it's full of unique data and needs a class hierarchy and virtual functions. When you take DOD, you look at the data and you immediately notice the similarities between the widget's data and functionality. By splitting the UI elements into separate components, you can now update these components in batches, which improves things like cache utilization. Another advantage, you've made the codebase a whole lot easier to read. Instead of spreading (and sometimes even duplicating) code over a whole hierarchy of widget classes and subclasses, code is now located in a component that simply does what the name implies.
Now before I leave it at this, a few disclaimers. Let's start with the fact that I just thought this system up while writing. So there is loooots of room for improvement here. Take your time when you create your own system and think things through before you create something. Another thing to note is that I have no idea if my system is that much faster than a OO-based UI system. It depends (as always) on the data, how much there is and what usage patterns there are. Maybe OO is faster in your case. Maybe a hybrid approach works best. I don't know :) My idea is just a simple example of how you can apply DOD principles to what may seem like a perfect example for OOP at first sight.
One last thing, I don't want to take credit for the approach above. It is heavily based on component systems, which are used in lots of games and have been developed by people a lot smarter than I am. If you want to read more about it, there is a lot of info to be found just on google (just search "game component system") or on Stack Exchange.