New Attributes in 2019r2

There’s a lot of things to digest in 2019r2

One of the handy things that was added is a new Attribute you can make use of in your own custom controls – DefaultEvent

By adding this attribute to your custom class’ attributes you can make it so any one of the events your custom controls exposes is the “default event”. This is the one that will be selected when a user puts an instance of your control on a layout and adds events to it.

Handy stuff.

Game of Code

Or “write code like you immediately forget what you wrote” so it’s not a guessing game to figure out why you wrote what you wrote way back when.

What do I mean by that ?

Write code CLEARLY. Use constants liberally and give them good meaningful names.

So instead of writing a line like

If asc(key) = 16 or asc(key) = 204 then

where 16 and 204 are not obvious to everyone maybe write this as

Const ctrlP = 16
Const F5 = 204

if asc(key) = ctrlP  or asc(key) = F5 then

And then even when you go back and look at this code in 6 months even you won’t have to guess what 16 and 204 mean.

Switch the window type at runtime

I’ve seen this question come up a couple times recently. And while it would be nice to do you cant.

The frame type is required to be set when the window is constructed. And there’s no constructor on a window that allows you to do something like

dim w as new Window(frametype)

So how can you have something like a document window on macOS and a movable modal on Windows ?

With a little inventiveness and some work.

First – make a container control that will be the windows content. All your common ui elements go in here. This is the common UI.

Then create a new window for macOS and set its frame type to whatever you need on macOS.

And one for Windows and Linux if needed.

One each embed, at design time, an instance of the container control you just created. Any non-common ui can be added directly to the windows themselves.

Now at runtime when you need an instance of this window you can use conditional compilation to make sure you get the right kind of window.

I’ve put together a small sample

Debugging tip

Sometime when you’re debugging your application you run into a situation where you get funky behaviour.

You might do something like Javier mentioned in his recent blog post on Xojo’s blog :

Dim ASource() As Integer = Array(1,2,3,4,5,6,7,8)
Dim ATarget() As Integer
ATarget = ASource

And, as he noted, you cant figure out why when you change one array you also appear to alter the other. This can also happen with other reference types as I noted in other posts.

For instance I’ve seen

Dim d As New Date
Dim d1 As date
d1 = d

d1.month = 2

and then the question of “why did d change?” arises

Again this has been covered before and it has to do with both arrays and dates, as well as many other type, being reference types.

One way to see that in fact these are the same object is not well documented in the Xojo documentation. Its buried in the Debugging pane of the preferences – Show Object IDs in variable lists.

Once you enable this setting what you see in the debugger pane makes it much easier to see when you have two references to the same object.

When viewing the following code

Dim ASource() As Integer = Array(1,2,3,4,5,6,7,8)
Dim ATarget() As Integer
ATarget = ASource

You can clearly see that ATarget and ASource have the same objectID. In Xojo’s runtime this means they are the same object – objectsID’s are unique to every instance and the only way you get two objectID’s that are the same is when two references refer to the same object.

I’d recommend always turning this setting on when debugging.

What scope should this be ?

This question isnt asked that often. But I think it should be.

When you create classes, modules, layouts or anything else in Xojo you should make everything as private as it needs to be. And no more. And as public as it needs to be. And no more.

But exactly what does that mean ?

I would say that you should normally start with most things in classes being protected. This means that any subclasses can access the items in the class. But code outside the class cant access it. This gives you a decent way to sort out what API you want the class to expose and grow that exposed API over time rather than just making everything publicly accessible all the time.

Code and controls on layouts I would treat similarly and make them all private since you only have private or public to chose from.

For modules public is also a good default for many of the same reasons. But in the case of a method or property in a module that is public it CAN be accessed by code outside the module it just has to be fully qualified so there’s no ambiguity when you are using such a thing.

In my time as a product engineer at Xojo I fixed a lot of bugs and many times the issue turned out to be code outside some class, module or layout that was accessing and changing or calling a method that wasnt protected or private and it was doing so at an inopportune time and so it appeared to be a bug in the Xojo framework.

Properly encapsulate your code and expose only as much as needs to be exposed whether thats by methods, events or properties. And by doing this you will prevent all kinds of weird coding bugs in your own projects.

Error handling speed

A question I was asked recently posed an interesting question about exceptions and the cost of using them as a general error handling mechanism.

Xojo uses whats know as “zero cost exception handling”. Essentially at runtime there is no penalty for having exception handling in place. It imposes no runtime overhead when NO exceptions are encountered. But, when exceptions are encountered, it can be “expensive”.

Expensive in this sense can mean it induces slowness or requires more memory. Or both.

So I put together a simple example that demonstrates the cost of using exception handling instead of error codes. Its very simple and uses a deprecated API that reported error codes instead of the newer one that raised an exception instead.

Its just a simple desktop application with a textarea on the default window and this code in the Window’s Open event

Dim f As folderitem = SpecialFolder.Desktop.Child("foo")

Dim errorcodeStart As Double = Microseconds
Dim errorCodeCount As Integer
For i As Integer = 1 To 1000
  
  Dim ts As TextInputStream = f.OpenasTextFile
  
  If f.LastErrorCode <> 0 Then
    errorCodeCount = errorCodeCount + 1
  End If
  
Next

Dim errorcodeEnd As Double = Microseconds

Dim exceptionStart As Double = Microseconds
Dim exceptionCount As Integer
For i As Integer = 1 To 1000
  
  Try
    Dim ts As TextInputStream = TextInputStream.Open(f)
    
  Catch IOX As IOException
    exceptionCount = exceptionCount + 1
  End Try
  
Next

Dim exceptionEnd As Double = Microseconds


Dim errorTotal As Double = errorcodeEnd - errorcodeStart
Dim exceptionTotal As Double = exceptionEnd - exceptionStart


TextArea1.AppendText "1000 iterations" + EndOfLine 
TextArea1.AppendText "Error Code = " + Str(errorTotal) + "ms" + EndOfLine 
TextArea1.AppendText "Exceptions = " + Str(exceptionTotal) + "ms" + EndOfLine 

In a debug run on my compute I get the following output.

1000 iterations
Error Code = 28096.87ms
Exceptions = 41711.62ms

The version using exceptions is juts about 50% slower over 1000 iterations when debugging.

In a version compiled with the DEFAULT setting the difference is less, but still present.

1000 iterations
Error Code = 28367.42ms
Exceptions = 35925.94ms

Exceptions are still about 25% slower than error codes. The Moderate optimization setting is similar

1000 iterations
Error Code = 29292.96ms
Exceptions = 34415.9ms

Aggressive settings remain similar

1000 iterations
Error Code = 28222.49ms
Exceptions = 35309.52ms

There are some advantages to exceptions. Unlike error codes they are impossible to ignore at runtime. At some point you MUST put code in place to handle them or your application will just quit with an unhandled exception error.

However, there’s nothing in Xojo that helps you make sure you have handled the possible exceptions that can be raised, and also nothing that tells you what exceptions might be raised.

So heads up before you dive into using exceptions everywhere as a general error handling mechanism in your applications. There are costs to doing this and they could manifest themselves in slower code or code that requires more memory. Or both.

More good habits

On the forum there was a suggestion that a person should use a container control that had a few controls embedded in it at design time. And then when using that container control that they should skip providing an API that the container presented and just reach inside the container and manipulate the controls it contain directly.

Personally I would recommend against this.

I’d start by saying when you create a container control ALL the controls in it should be private by default to prevent this. And that if you want to expose functionality of the controls on the container you do so by defining methods and events on the container that any code OUTSIDE the container can call or react to just as if the container control was any other single control and not a composite one like it is.

Why would I make such a recommendation ?

  1. good habits
  2. encapsulation
  3. reusability
  4. long term flexibility and maintainability

The first point is just that this is a good habit to get into. And the reason its a good habit is because of points 2, 3 and 4. Properly encapsulating and hiding the details from other bits of your code is a good thing. Code outside the container doesnt need to know HOW the container does what it does. Just that it does what is expected when you call its methods, change its properties and react to the events it exposes. Thats it. It should be a black box like the built in Xojo listbox, pushbutton, or any other built in control is. You dont need to know how those do what they do, just that they do what you expect when you call the methods, set the properties and react to their events.

And the bonus to doing this is that it makes the likelihood you, or others, can reuse your control in more places in your project or in other projects much higher because the control is self contained.

Long term it also lets you do things like completely swap out the implementation of the container for some other means and as long as you dont need to change the API nothing outside the container control even needs to be aware this has happened. This makes your own code easier to maintain since you no longer have to look through all the code outside of the container to know if you also need to alter it because something in the container changed.

These are all good things regardless of whether this code is for your own use, more general distribution or possibly for sale or to give away.

I’d encourage everyone to keep these things in mind when ever they write their own custom controls.

Of bounds and positions

Windows have two sets of properties that all relate to positioning a window.

However, they are not all quite created equally.

There are, of course, the typical top, left, width and height properties. And also the “bounds” property which is a Rect.

If you examine the bounds property for a Document window, and the top, left, width and height you will find that the Bounds.top is not the same as the top property value. Nor is the height. Now why is that ?

In the following image the BOUNDS are the area enclosed by the red rectangle. And the top, left, width and height properties describe the area in light blue.

If you only had the top, left, width and height properties to use to position a window you would have to somehow figure out what the real size of the window was and account for the title bar size and possibly the outer window frame size. There may or may not be one depending on platform and window type.

And if you add a toolbar this further complicates that. The following image is the same window with a toolbar and once again marked with a red rectangle around the bounds and the blue area is the rectangle described by the top, left, width and height properties.

If, for some reason, you want to know the height of the title bar you can use the difference between the bounds top and the windows top property to see how tall it is.

Note that you cant use this difference to know how tall the title bar and toolbar independently. And toolbars dont appear to propertly report their top, left, width, or height at runtime. 🙁

Still the difference between the bounds properties and the windows other properties will let you determine how tall the title bar + any toolbar is.

Careful with those bounds out there.

Generics

One of the things that Xojo lacks is the notion of generics.

So what are these things and why would they be useful ?

In many programming languages you might want to define a class that behaves like a List. But you want to be able to make this generic enough that when you go to use one you can make a List of Strings, a List of Classes, a List of controls etc.

Right now the only way to do this in Xojo is to make all the the parameters and return values be variants in the interface definition. The downside to this is that you lose all compile time type checking and have to rely solely on runtime checks YOU put in the code.

If you could declare a List variable like

Dim myStringList as List<String>

This would indicate that the list should use String as the “generic type” for all the method parameters and return types. The interface declaration might have to change to something like

Interface List<Type>

  Sub AddRow(ParamArray values() as <Type>)
  End Sub
  
  Sub AddRowAt(ParamArray values() as <Type>, zeroBasedInxed as integer)
  End Sub
  
  Sub FirstRowIndex() as integer
  End Sub
  
  Sub LastAddedRowIndex() as integer
  End Sub
  
  Sub LastRowIndex() as integer
  End Sub
  
  Sub RemoveAllRows()
  End Sub
  
  Sub RemoveRowAt(zeroBasedIndex as integer)
  End Sub
  
  Sub RowCount() as integer
  End Sub
  
  Sub RowTag() as Variant
  End Sub
  
  Sub RowTagAt(zeroBasedIndex as integer) as <Type>
  End Sub
  
  Sub RowValue() as <Type>
  End Sub
  
  Sub RowValueAt(zeroBasedIndex as integer) as <Type>
  End Sub
  
  Sub SelectedRowCount() as Integer
  End Sub
  
  Sub SelectedRowIndex() as integer
  End Sub
End Interface

And now we have a generic interface AND a way to define a list that will, at compile time, have a specific and known type so the compiler can detect any incompatible type errors.

This would make interfaces even more useful than they are now.

Good habits when creating custom controls

Suppose you have the need to create a custom control like I did recently

One of the things that you should do so people do not get confused about using your control is to “implement” any events in whatever you use as your base class that should not be exposed to end users of your control. If you dont inplement these events then a user could, and that might end up in surprising behaviour in your carefully crafted control.

If you dont implement the Open event for your custom control a user could put an instance on a layout and implement that event. If this causes problems than you can make it so they cannot implement the Open event simply by adding that event handler to your custom control.

There may be events, like ConstructContextualMenu, DragEnter, DragMove, etc that make no sense for your custom control and so implementing them in your class would make it so users cant.

And this should make your custom controls easier for others to use.