Subclasses, modules and compatibility flags 😛
In Xojo it never used to require a lot of hard work to work across multiple versions. If you simply avoided using the new features then a project could mostly move back and forth between versions without much effort. You could even deal with a lot of newer version changes with a few #If XojoVersion wrappers around bits of code.
2019R2 makes this a little more challenging.
Most of the issues I’ve experienced are because one clients code has a lot of custom control subclasses and these subclasses defined new events. And now, with the takeover of so many event names, these subclass events conflict with the names Xojo took over. It makes it so these client projects no longer just open and compile in 2019r2. They get thousands of compilation errors.
This makes updating to 2019r2 tricky for this client. Especially since they also want to maintain the ability to compile and work in older versions of Xojo to be able to compile for older versions of the OSes they support.
If you’re in the same position there is a way to make it so the event names that were taken over won’t affect client projects.
How ? I created a set of subclass of the built in controls and classes which all client subclasses could be based on and, depending on the build version of Xojo, I could switch these custom subclasses on and off and the rest of the clients subclasses are unaware this has occurred.
What I am not sure of is how far back this technique will work.
Really old versions MAY not interpret compatibility flags quite right.
Now for the HOW TO guide :
- In this project I opened it in 2019r2
- I created a module called For2019r2
- I cleared ALL the compatibility flags for the module so its not compatible with ANY targets
- In this module I created new subclasses of every control used and set their scope To “global”
- In each subclass I add new event definitions for all the OLD events
- In these subclasses I implemented the new event handlers that got renamed to raise the old events added in step 5.
I implemented the “new events” and simply had them raise an event with the old name & params. I could have name these events anything I wanted. By doing this I could add my own methods, properties, etc or even rename any properties Xojo also renamed. I could also handle any exceptions raised and just set error codes or whatever I wanted. I’ve written before about how to do this shadowing “properly”. Thats the technique in use here. What we’re adding this time is the ability to have two different sets of these properly subclassed and shadowed controls that we can switch between.
I saved this project and then in 2019r1.1 I reopened this project as there is some work you cannot do in 2019r2. In the subclasses in the For2019r2 module we also need to add the OLD events which still exist but, because you started the project in2019r2, you can’t see them nor can you add them in 2019r2. We need to also implement the old event handlers and have them raise the event with the old name as well. This is important otherwise in R2 you will get errors about the event definition existing and colliding.
For older IDE’s we create a new module named For2019r1AndEarlier and do much the same adding subclasses of all the controls we need. This time we add just the old event name and a matching event definition for the old event.
The important thing to do is in the module fore 2019r2 if you named the Canvas subclass MySubClass then in the 2019r1 module name the canvas subclass the exact same thing. The same is true for all other control subclasses. They need to be named the same in the For2019r2 and For2019r1AndEarlier modules. This way when you create a new instance on a layout and make its super MySubclass, depending on which module has its compatibility flag enabled you will actually be creating an instance derived from a different superclass.
Now when I want to compile in R2 I select the For2019r2 module & enable the Desktop 32 and 64 bit compatibility flags so my custom subclasses which are outside this module use the base classes inside this module.
When I want to compile using 2019r1.1 and earlier I disable the compat flags on the For2019r2 module and enable the compt flag on the For2019r1AndEarlier so my other classes now use these as their base class.
And you can now ignore R2 event name changes and name these events to whatever you want.
Caveat – i have found a couple interesting bugs in the 2019r1.1 IDE doing this
When moving some control subclasses into a folder insances on a layout may “lose” their super especially if neither of the modules has a compat flag set.
So you get an error like
Can't find a type with this name. Did you mean class For2019r1andEarlier.MyTextFieldBase?
Fixing this amounts to enabling one of the compat flags and then going to the super field of the affected control and putting the cursor in the super field and pressing enter
Here’s an example that shows how I’ve set things up