The code above creates a new RGB image with a certain width and height and adds a new layer to that image. As you can see to just add the layer I need a reference to image twice. The GIMP API dictates that you can only create a layer if you know the image ID. What I was looking for was something with a bit more DSL (Domain Specific Language) like syntax. Something like in the next code fragment:

This code uses the C# collection initializer that was introduced in version 3.0. The first step to make this work is to make Image implement the IEnumerable interface. The slightly weird thing is that this interface doesn’t even have to be functional:

The above code is already sufficient. Instead of the AddLayer we now have to supply an Add method with the following signature:

public void Add(Layer layer, int position)

Now a problem becomes visible: in the original code we first construct image and use this variable as the first paramter in the layer constructor. However, when we use a collection initializer, we don’t have this variable available. And constructing a layer without an image is not possible in the GIMP API. To solve this problem I introduced a delayed constructor and do the actual construction in the Image.Add method, where the image is available as the this parameter. The Layer class looks like this:

This delayed constructor trick works quite nice. In the same way I can add GIMP channels and vectors. It is even possible to add channels, layers and vectors in one collection initializer since the Add methods all have different signatures.

So, where is the catch? There is a (minor) one: since I now have added a layer constructor without the image parameter, it is possible to call the constructor outside the collection initializer context:

Share this:

Like this:

Related

You could introduce another class, LayerPrototype, that has no actual Layer functionality except your delayed constructor. Added bonus: that prototype instance could be used in more than one Image, or even more than once per image.

Thanks for the feedback! I have thought about that solution as well. It is perfectly workable although I slightly dislike that it is now very visible that you are not constructing a ‘real’ layer. Maybe all code should use a LayerFactory class that creates Layers based on a LayerPrototype. In that case one would never be able to construct Layers directly.

I like the kind of things your doing now… I should get out of my ‘C world’ more often….

One question though: I don’t get the last code. If you create this ‘unusable’ layer. And then do image.Add(layer, 0), doesn’t that then create a NEW layer (in the delayed constructor), which is added to the Image? And therefore, won’t that unusable layer still be unusable?

Best regards,

Arnaud

P.S. Didn’t have the time to code some small example code to test this myself…

Yes, you can use regular method. I just think this is some kind of syntax sugar that we are adding on top of existing API. So it is ad hoc feature and it should be located in separate place. I feel we are not going to change public contract of Image class, so we should not change the set of its public methods. This is just my feeling.

That surely would be possible. However that would also mean that the GIMP# API would behave differently from the GIMP API, because in the latter case it is possible to call methods on a layer without it being attached to an image.