Reputation: 1286
I am writing a cross-platform UI toolkit for a variety of targets, some of which are embedded. Some of these platforms support a "retained" rendering mode, and some of them are more "immediate", so I am thinking that for my visuals I have two trees - pseudocode:
abstract class Visual
{
Visual( Widget widget ) { this.widget = widget; }
}
abstract class RetainedVisual : Visual
{
abstract void Setup( Renderer r );
abstract void Teardown( Renderer r );
}
abstract class ImmediateVisual : Visual
{
abstract void Paint( Renderer r );
}
So far so good. But now I also have ContainerVisual
classes which encode the widget hierarchy:
abstract class ContainerVisual : Visual
{
void AddChild( Visual child ) {}
}
which sort of forces me into having an ImmediateContainerVisual
and a RetainedContainerVisual
classes which is starting to look bloated. Ideas for a better design?
Upvotes: 0
Views: 293
Reputation: 11813
It's hard to decide what way to go without having more information: What's the difference between Retained/Immediate in terms of functionality? What does a Container do?
But nevertheless, in C++ you might consider to use a class template for things like Container:
template <typename BaseType>
class ContainerVisual : public BaseType
{
public:
void AddChild(BaseType & /*or smart pointer or whatever*/ child ) {}
}
Upvotes: 0
Reputation: 1207
Best alternative is to combine the 3 classes to same Visual class:
class Visual {
Visual(Widget w);
bool SupportsSetupTearDown();
bool SupportsPaint();
abstract void Setup(Renderer r);
abstract void TearDown(Renderer r);
abstract void Paint(Renderer r);
};
Then there wont be any problems with container widgets. All visuals should implement both methods of rendering, and when the target changes, the system will start calling different functions. This also allows conditionally not implement one way, and special visuals could be built which convert from SetupTearDown to Paint and from Paint to SetupTearDown.
Upvotes: 1