List of changes that affect user-code (up to 1.52 release)

In pursuit of c++ perfection, I’ll occasionally refactor or tweak Juce classes in such a way that might require changes to the code that uses them.

The changes involved are usually small, but when you download the latest Juce version and your code fails to compile with it, the error message might not always make it obvious what you need to do.

So this thread is a place where I’ll post details of any such changes, which will hopefully make it easier to find an answer if you hit this situation…

SparseSet: Many of the methods now take/return Range objects instead of separate start/end values.

Line: Refactored the Line class to make it templated, in the same way that Point and Rectangle work. To update existing code, just change “Line” to “Line”. You might also need to tweak a couple of its methods, where I’ve changed the parameters to use Point objects rather than just raw coordinates, but the behaviour should all still be the same. The Line::clipToPath() method has moved to become Path::getClippedLine().

LassoSource::findLassoItemsInArea now takes a Rectangle as its parameter.

Replaced the old atomic operations with a new templated Atomic class with much more flexibility.

So e.g. instead of having an int and calling static methods to manipulate it atomically, you’d create an Atomic object and use its methods to change it.

Removed the VoidArray class - if you’ve used this, it’s very easy to replace, just use Array<void*> instead.

I’m refactoring the Drawable classes at the moment, as they’ll be central to the new jucer’s vector editor - I’ve just changed the way the transforms are structured, and will probably need to change them a few more times before they’re stable…

I’ve made an important change to the way that the Image class is used…

(I’ve been wanting to do this for years, but finally decided it was a good time when I hit a problem that I just couldn’t solve cleanly with the current Image class…)

Previously, you’d create an Image object, keep a pointer to it, and delete it when you’d finished. This was fine, but there were all sorts of places in the code where images were shared or passed around, and the responsibility for owning and deleting them was very confusing. This provided lots of opportunities for dangling pointers, leaks, or unnecessary copying of images, as well as making it a PITA to make sure you were using them safely by using ScopedPointers and other tricks.

I’ve now changed the design, so that an Image is a lightweight object with value semantics, which internally points to a shared, reference-counted object that actually holds the data. That means that instead of keeping a pointer to an image, you just pass them around by value, and when they go out of scope, their image data gets released automatically. Being ref-counted makes it easy to share the same image data between separate tasks.

This has lots of benefits: it makes your code cleaner, safer, less prone to leaks, and it’s impossible to get a dangling pointer to an image. The ImageCache class is now much simpler, and you don’t have to worry about releasing the objects that it gives you. Likewise when you use the ImageFormat classes to create an image, you don’t need to worry about deleting it.

So code like this:

Image* im = ImageCache::getFromFile (f);
g.drawImage (im, x, y)
ImageCache::release (im);[/code]

becomes:

[code]g.drawImage (ImageCache::getFromFile (f), x, y);

The changes also mean that you can use images in places that you previously couldn’t, e.g. Array.

Since the Image copy constructor now simply creates a reference to a shared image rather than actually duplicating the image, I’ve added a new method Image::duplicateIfShared(). This will internally duplicate an image if there is are any other references to it, so that if you’ve been given an image but don’t know whether it’s in use elsewhere, calling this method will make sure that you’re drawing onto your own private copy, and not onto a shared image.

The changes will, of course, break some code. Although most of the Image class member functions are the same, all the Juce functions that used to take or return an Image* now use a const Image& instead… Updating is really straightforward though, and in every place that I’ve had to change my code for this, the result has been much cleaner and more concise than it was before.

An image can also now be ‘null’, if you just create it with the default constructor. So where you’d previously have written:

Image* im = ImageFileFormat::loadFrom (f); if (im != 0) { doSomething (im); delete im; }

You’d now write

Image im = ImageFileFormat::loadFrom (f); if (im.isValid()) doSomething (im);

I’ve updated the (old) Jucer to generate code that’s compatible with the new class - let me know if you have any problems with that.

I think the only pitfall that you might need to watch out for would be if you’ve used the Image copy constructor anywhere to deliberately create a copy, and if it’s important to your code that the image actually gets duplicated, then you’d need to make sure you add a call to duplicateIfShared().

1 Like

The ReduceOpacityEffect class has finally been removed, and replaced by Component::setAlpha(), which lets you give any component a settable transparency level.

I’ve removed the Component::getComponentUID() method. I’ve been trying to slim down and simplify the Component class, and it seemed to be unnecessary baggage - the original reason for having it was for use by the not-very-reliable ComponentDeletionChecker class, which has now been replaced by Component::SafePointer.

If you need to give your component an ID now, you can easily use the getProperties() set to assign whatever kind of value you need to it.

The old MAC address stuff in SystemStats has now been replaced by a proper MACAddress class to handle them properly.

I’ve done a bit of cleaning up in the event classes - the ChangeBroadcaster::sendChangeMessage method no longer takes a parameter, and the ChangeListener::changeMessageCallback() method now has a parameter which is a ChangeBroadcaster* instead of a void*. It should be easy to update your code to accommodate this - you can just pretty much cut-and-paste “changeMessageCallback (void*” for “changeMessageCallback (ChangeBroadcaster*”.

In doing this I’ve eliminated the ChangeListenerList and ActionListenerList classes, because all their functionality is already provided by ChangeBroadcaster and ActionBroadcaster, so they were just adding unnecessary clutter.

I’ve just converted all the Drawable classes to inherit from Component. This means that rather than loading or creating a Drawable and then painting it in your paint routine, you can just add it to your component and let it handle repainting itself. This also means that you can twiddle their settings and it’ll automatically repaint itself.

I’ve left the old draw methods in the Drawable class, so your old code should still work (apart from having to rename getBounds to getDrawableBounds), but I’d encourage you to think about using them in this new approach.

The tolerance value used by PathFlatteningIterator wasn’t being used correctly (and was spelt wrong!) I’ve changed it now so that the value now represents the greatest possible distance of a flattened line from the curve - if you were using values for this, you’ll probably need to adjust them, or your shapes may appear jagged!

I’ve just had a clear-out of a few old classes:

  • MagnifierComponent is gone. You can use Component::setTransform as a much better replacement for this. If you want to see an example of a drop-in-replacement for the old MagnifierClass, have a look in the old Jucer, where I wrote a quick class to do this (it’s also called “MagnifierComponent” so that it works with the existing jucer code).

  • MouseHoverDetector is gone. Not sure why I ever wrote the class, it was never useful for anything, and was just cluttering up the place. If you used it, please just take a copy of the old code and put it in your project, it’ll still work fine.

  • PopupMenuCustomComponent is now called PopupMenu::CustomComponent (but works just the same).

I’ve also just changed Viewport::visibleAreaChanged() to take a Rectangle parameter instead of raw ints.