DrawableComposite insertDrawable


#1

Hi Jules,

I’ve seen that you have removed DrawableComposite::insertDrawable.

I suppose that code using this should be updated to addAndMakeVisible(nameOfMyDrawablePath .createCopy());

Problem is that the code above do not display something anymore.

Any ideas ?

FWIW, I use resetContentAreaAndBoundingBoxToFitChildren following this line.

Here is the whole code where it’s used

static const float sqrt3div2 = sqrt(3.f)/2.f;

juce::Path triangleClosed; 
triangleClosed.addTriangle(0.5, -sqrt3div2, -1, 0, 0.5, sqrt3div2); 
juce::DrawablePath triangle; 
triangle.setPath(triangleClosed); 
triangle.setFill(juce::Colour(0xff000000)); 

juce::DrawableComposite normal; 
normal.insertDrawable(triangle); 
normal.addAndMakeVisible(triangle.createCopy());
normal.resetContentAreaAndBoundingBoxToFitChildren(); 

juce::DrawableButton *pButton = new juce::DrawableButton("previous", juce::DrawableButton::ImageOnButtonBackground); 
pButton->setImages(&normal, &normal, &normal, &normal, &normal, &normal, &normal, &normal); 

Thanks,


#2

Sorry, I’m still doing some extensive refactoring of drawables, and had broken the createCopy() method - try again now!


#3

Fixed.

Thanks,


#4

I am at a bit of a loss here.. I have to replace some old code:

DrawableComposite* drawableComposite = new DrawableComposite (); drawableComposite->insertDrawable (markerDrawable); drawableComposite->insertDrawable (plusDrawable, AffineTransform::translation (1.5f, 0.2f));

where markerDrawable and plusDrawable are DrawablePaths contained in a rectangle of size 1… how do I replace it with the new addAndMakeVisible()?

This is what I have tried, but it doesn’t correctly displace the second drawable from the first one: both of them are centered and overlapped

drawableComposite->addAndMakeVisible (markerDrawable); drawableComposite->addAndMakeVisible (plusDrawable); plusDrawable->setOriginWithOriginalSize (Point (1.5f, 0.2f)); drawableComposite->resetContentAreaAndBoundingBoxToFitChildren ();

#5

If you want to apply a transform to the child drawable, you'd just use the normal Component::setTransform method.


#6

I get the same result (and I would have been surprosed of the contrary, since setOriginWithOriginalSize actually makes a call to Component::setTransform() as you suggested)


#7

Ah, ok. Not sure then - TBH I can't remember the details of how it used to work.. 


#8

I did some testing with the example code that follows:

                Component content;

                Path horizSegmentPath;
                horizSegmentPath.startNewSubPath (0.5f, 0.5f);
                horizSegmentPath.lineTo (1.0f, 0.5f);
                ScopedPointer <DrawablePath> horizSegmentDrawable (new DrawablePath ());
                horizSegmentDrawable->setPath (horizSegmentPath);
                horizSegmentDrawable->setStrokeThickness (0.1f);
                horizSegmentDrawable->setStrokeFill (Colours::blue.withAlpha (0.5f));

                Path vertSegmentPath;
                vertSegmentPath.startNewSubPath (0.5f, 0.5f);
                vertSegmentPath.lineTo (0.5f, 1.0f);
                ScopedPointer <DrawablePath> vertSegmentDrawable (new DrawablePath ());
                vertSegmentDrawable->setPath (vertSegmentPath);
                vertSegmentDrawable->setStrokeThickness (0.1f);
                vertSegmentDrawable->setStrokeFill (Colours::green.withAlpha (0.5f));
                vertSegmentDrawable->setTransform (AffineTransform::rotation (float_Pi / 4.0f));

                Path squarePath;
                squarePath.addRectangle (0.25f, 0.25f, 0.50f, 0.50f);
                ScopedPointer <DrawablePath> squareDrawable (new DrawablePath ());
                squareDrawable->setPath (squarePath);
                squareDrawable->setStrokeThickness (0.1f);
                squareDrawable->setStrokeFill (Colours::black.withAlpha (0.5f));
                squareDrawable->setFill (Colours::transparentBlack);

                ScopedPointer <DrawableComposite> composite (new DrawableComposite ());
                composite->addAndMakeVisible (horizSegmentDrawable->createCopy ());
                composite->addAndMakeVisible (vertSegmentDrawable->createCopy ());
                composite->addAndMakeVisible (squareDrawable->createCopy ());
                composite->resetContentAreaAndBoundingBoxToFitChildren ();

                DrawableButton drawableButton ("drawableButton", DrawableButton::ImageOnButtonBackground);
                drawableButton.setImages (composite);

                content.setSize (120, 120);
                drawableButton.setBounds (10, 10, 100, 100);
                content.addAndMakeVisible (&drawableButton);

                ResizableWindow window ("Drawables", true);
                window.setUsingNativeTitleBar (true);
                window.setContentNonOwned (&content, true);
                window.centreWithSize (window.getWidth(), window.getHeight ());
                window.setVisible (true);

This is the outcome:

As you can see, there are two problems:

1) Even considering that the DrawableComposite children are contained in a rectangle that has its origin in (0.25, 0.25) and is 0.75x0.75 in size, when drawn over the button background, the (0.25, 0.25) origin is mapped to the (0, 0) point in the button, and the whole size is stretched over it.

2) The Transform applied to vertSegmentDrawable (a rotation of 45 degrees) is completely disregarded

 


#9

Hi Jules,

as a developer, I am aware that my last post here is nothing but annoying, because I bet you are working on much more exciting things and fixing such a boring bug is plainly, as I said, annoying and boring.

Knowing that, I have made my fair attempt at fixing it myself, trying to come back to the forum with a sensible solution that you could just review and integrate in your code.

Unfortunately, the conversion of Drawable to be a subclass of Component is one of the few parts of JUCE that I can't completely "grasp" in order to work on it with confidence.. I have wasted some time trying to figure out things and to pinpoint the place where a change is needed to fix the two issues numbered above. Unfortunately, I have been unable to do so.

Is there any chance you can have a look at it?


#10

Sorry, I wasn't ignoring you, just wasn't aware of your post. I get too many requests to keep track of them all, and things get lost/forgotten!

Yes, I'll have a look soon, though I suspect that there's probably nothing actually *wrong* with the classes, it's most likely just a misunderstanding of how to use them.. It's very complicated, and when I converted the drawables to be components, it changed some behaviours.


#11

..ok, I don't really understand the problem - the code you posted is doing exactly what it's supposed to do. You can position the composite object using DrawableComposite::setBoundingBox and setContentArea - the methods are documented, though I admit it's a complicated system.


#12

Well, this may be true for issue #1 reported above, but how is the #2 possibly correct?

I have vertSegmentDrawable which represent a vertical green segment, then a rotation of pi/4 (45 degrees) is applied to it:


vertSegmentDrawable->setTransform (AffineTransform::rotation (float_Pi / 4.0f));

and this is added as a child to the DrawableComposite that's displayed on top of the button:


composite->addAndMakeVisible (vertSegmentDrawable->createCopy ());

I would have expected the transform applied to vertSegmentDrawable to be retained displaying a diagonal green segment, as it would have been if it had been a regular Component added as a child inside its parent Component.

What's the rationale for ignoring such transform here? is the "createCopy" method copying the drawable discarding transforms applied to it?


#13

Actually, looking at the code, most of the Drawable classes use the transform themselves internally to manage their layout - e.g. setBoundingBox, etc will set up a transform to produce the required layout. So yes, createCopy will probably ignore your custom transform and the new object will recalculate its own.