List of changes that impact user-code (since 1.52 release)

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.

The PositionedRectangle class has been deleted - it was designed for the old jucer and will be superseded by all the RelativeCoordinate/RelativeRectangle classes in future. If you’ve got code that uses it (which seems a little unlikely, it was quite a niche class!), just take a copy of the last version of it and stick it in your code, where it’ll carry on working just fine. (This is what I’ve done for the old jucer, so there’s a copy of it in there if you’re looking for one).

I’ve updated the BorderSize class to be templated now, so that it matches all the Point/Line/Rectangle classes. If you’ve used it in your code, it’s an easy one to update: just replace “BorderSize” with “BorderSize” and everything will work as before.

The TimeSliceClient::useTimeSlice() method now returns an integer instead of a bool, to indicate the number of milliseconds that the thread should wait before calling it again. This provides a lot more control over the thread’s behaviour, and is easy to update your existing code - simply return 0 instead of ‘true’, and something like 500 instead of ‘false’. The return value -1 is also now a handy way to remove the client from the thread and stop it being called again.

The String class has had a major overhaul, to provide correct UTF encoding operations. Hopefully this shouldn’t affect too much code, but a few methods have had to change slightly to cope with it. The biggest changes are:

  • the juce_wchar type is now a 32-bit int on all platforms, even those (like win32) where the wchar_t type is not 32-bit.
  • the ‘tchar’ type has been removed
  • The T() or JUCE_T macro is still there, but not encouraged. Just use normal char strings or L"xyz" strings.
  • The String class now has toUTF8(), toUTF16() and toUTF32() methods which return their values as CharPointer_UTFx classes, which can themselves be used to convert between types.
  • The String constructors which took unsigned ints (to convert them to numeric strings) have had to be removed, because of type ambiguities when there are 32-bit juce_wchar definitions in use.

Ok, more String changes - the String class can now be set to use either utf-8, utf-16, or utf-32 as its internal encoding format!

Relevant facts about this change are:

  • by default it’s using utf-8, but you can set the JUCE_STRING_UTF_TYPE to 8, 16, or 32 to override this. Externally the string works in exactly the same way regardless.

  • you can no longer just cast a String to a const juce_wchar* or const char*, you need to explicitly call toUTF8(), toUTF16(), or toUTF32() when you want to get access to its data, and any of these methods may return a pointer to a temporary copy.

  • because utf-8 and utf-16 use variable-length chars, String::operator[] will run in O(n) time for those formats, so if you’ve got algorithm that takes a huge string and calls operator[] on every character, you may be in for a shock! If this is a problem you can use utf-32, which has instant access to any character, or you can re-write your algorithm to call getCharPointer() and get an iterator that you can use to quickly move around in the data.

After meaning to do this for a long time, I’ve finally moved the plugin wrapper code from the extras/audio plugins folder, putting the files into the main tree under src/audio/plugin_client. The structure of that folder is the same, but you may need to update your projects to point to their new locations. (If you’ve been using the introjucer to manage your projects, all you need to do is to re-save the project with the latest version of the introjucer, and it’ll update all the paths for you automatically).

…and I’ve also got rid of the AudioFilterStreamer class, which was redundant as it really provided nothing more than a container for an AudioProcessorPlayer and an AudioDeviceManager. If you were using it, you can just use these classes directly instead.

After a protracted nagging campaign by TheVinn, I’ve refactored the DragAndDropTarget callback methods, so that they now take a DragAndDropTarget::SourceDetails object as their parameter. This is a better design, which provides more info than the old parameters used to allow for, and lets you pass an arbitrary ReferenceCountedObject to the drag target for passing custom data. (It also means that any future changes to the way drag-and-drop works can be made by changing the SourceDetails structure rather than needing to change any virtual method parameters again).

Any code which uses the old parameters will fail to compile, but it should be easy enough to replace your parameters. If this is annoying, please send your complaints to TheVinn :wink:

Doing some clean-ups recently, I’ve been able to remove the need for the initialiseJuce_NonGUI/shutdownJuce_NonGUI methods (and therefore also the ScopedJuceInitialiser_NonGUI class). This will probably only affect people who were writing their own main() method, but if you get a compile error with any of those symbols, just remove them, it’ll work fine without them.

The initialiseJuce_GUI stuff is still there, but I’ve reduced the amount of responsibility it has, and am leaning more heavily on c++ static intialisation/destruction to handle things. Hopefully I’ll eventually figure out a way to get rid of all these housekeeping functions and have everything just initialised lazily.

Having been alerted that Apple have some strict (new?) guidelines on the folders that an app is allowed to use for storing its properties, I’ve had to have a bit of a shake-up of the PropertiesFile class.

Since it was impossible to fix these paths without breaking user-code (or causing silent failures), I’ve taken the opportunity to have a bit of a clear-up in the PropertiesFile class. I’ve refactored all of its options into a structure now, which is also used in the ApplicationProperties class, and this has eliminated quite a bit of messy/repeated code. The structure contains a value osxLibrarySubFolder which helps sort out the OSX location problem - see its comments for more details.

This does mean that you’ll need to rewrite any code that used PropertiesFile::createDefaultAppPropertiesFile() or ApplicationProperties::setStorageParameters(), but should be pretty straightforward, and leads to more readable code.

For a good example of how to rewrite this stuff, have a look in the Introjucer/Utility/StoredSettings.cpp, inside the StoredSettings::flush() method, where it also shows how to migrate an old preferences file to a new location without losing any settings.

Also as part of these OSX file location changes, I’ve had to tweak the InterprocessLock behaviour, to put its locking files into /var/tmp rather than the Library/Juce folder that it used to use, which is apparently now verboten. If you have an app which needs to use an interprocess lock, you’ll need to make sure that all the apps are built from the latest version of the codebase, so that they’re all looking in the same folder for their locking files.