Things you should not rename in Xojo

There aren’t a lot of items in a Xojo desktop project that you can’t rename. You can change the name of the App instance, the default window, the default menu bar and many many others.

But there are a handful that, if you do rename them, you may inadvertently break your application. This is entirely due to how the Xojo framework works, and in part how macOS itself works.

One group of items you should not rename is several Edit Menu items. Do not rename EditCut, EditPaste, EditClear, and EditSelectAll. The reason is, that if you do, then certain classes in the Xojo framework will no longer handle those menu items by default.

The simplest demo of this is to

  • start a new desktop project
  • add a TextArea to the default window – Window1
  • run

Now if you type in text to the text area and press the shortcut for Select All (⌘-A or Ctrl-A) the text area will automatically handle selecting all the text.

Quit your little demo app and in the menu editor rename EditSelectAll to MyEditSelectAll.

Run the small sample again. Perform the same test by adding a bunch of text and trying to use the shortcut. This time the menu shortcut is NOT automatically handled and likely just beeps at you.

Several controls have behaviour that is pre-configured to rely on the Edit Menu items being named in a specific way. I’ve written about how you can do this as well before. Renaming the Edit Menu items then breaks that automatic configuration.

The other thing that renaming is specific to macOS. On macOS the OS will automatically add new menu items, the ones for Start Dictation and Emoji & Symbols, to the edit menu IF it the TEXT of the for the Edit Menu title is “Edit”.

If you alter it to anything else then macOS will not find the correct menu to insert these items and they will not be added to your Edit Menu.

Again this is easy to test with the tiny sample app we have so far. Just change the Edit menus text to Edit followed by a space and run. When you click on the Edit menu you will not longer have the 2 automatically added items.

New resources

This looks like it could be a nice forum as a place to learn about and discuss cross-platform app development, not specifically focused on Xojo (although that will be one of the topics I’m sure)

As an alternative to the Xojo forums where you cannot discuss other products etc this one is focused on cross platform – regardless of toolset

I’ll give it a chance. You should as well.

If you’re updating with every release

A small handful of changes in 2019r3.1

Module Color
alpha changed to Integer
Function CMY(cyan As Double, magenta As Double, yellow As Double, alpha As Integer = 0) As Color

ColorGroup
gained operator_compare
Function Operator_Compare(otherColor As Color) As Integer

Module Crypto
added PBKDF2 with HashAlgorithms parameter
Function PBKDF2(salt As String, data As MemoryBlock, iterations As Integer, desiredHashLength As Integer, hashAlgorithm As HashAlgorithms) As MemoryBlock

Class DatabaseColumn
now has a destructor
Sub Destructor()

Class DatabaseRow
added Column setter method
Sub Column(name As String, Assigns value As Variant)

added Destructor
Sub Destructor()

Module String
new overloads for IndexOf
Function IndexOf(Extends s As String, startPosition As Integer, searchString As String, options As ComparisonOptions = ComparisonOptions.CaseInsensitive, locale As Locale = Nil) As Integer

Function IndexOf(Extends s As String, searchString As String, options As ComparisonOptions = ComparisonOptions.CaseInsensitive, locale As Locale = Nil) As Integer

new method LastField
Function LastField(Extends s As String, separator As String) As String

Class TextArea
changed type of SelectionAlignment type
Property SelectionAlignment As TextAlignments

Cant say that so far I’ve used it much.

Creating custom controls

Xojo makes it possible for anyone to create custom controls for their projects. And its not really that hard. Yet many people don’t bother to take advantage of this capability and then try to place many independent instances on a layout and make several controls behave as though they are a single control.

This quick tutorial is aimed at trying to convince you that it really is worth investing the little bit of time required to create your own custom controls and then reuse them as many times as you want.

Often you can get away with just creating a new subclass of which ever control you want and then customizing how it behaves. Maybe you just need some custom drawing in a listbox. It may not make sense to create anything but a new subclass in that case.

In this example because we want to create something that does not exist and is a composite of other controls we are going to start with a CONTAINER CONTROL.

At this point, depending on what control you want to create you would add which ever controls you need to your container control.
In this example we want a label and a canvas because we’re going to make something that is like the color picker seen in the inspector. Make sure that when you place them on the container you set their SCOPE is set to PRIVATE.

Personally I always do this as code outside the container should NOT reach in and manipulate the controls in our container directly. If you find you think you need something like that add a method or event to make it possible for code outside to get a reference to the control or set a property instead.

Make sure you give the container control a good name as this name WILL show up in the library *. Use a descriptive name for your custom control. Naming it “fooControl” probably isn’t useful unless it literally has something to do with “foo” – whatever that might be. In this case since we’re making a “labeled color picker” we’ll name it labeledColorPicker

Now we’ll add properties that can be set in the inspector that will influence how our control works. We’ll add a label property, as string, that will be the text show in our control. As well we’ll add a currentColor property, as Color, that will be the current color the color picker shows in the canvas. Both of these should be added as COMPUTED PROPERTIES.

We will need a variable to store the value for our currentColor property that we can hold the value in and that we can return when the value is queried. Since we’re using a canvas for this purpose and it does NOT have a property we can use we will need to add a PRIVATE property to our ContainerControl to hold this. Add a PRIVATE property, mCurrentColor as Color, to the labeledColorPicker container control.

In the GET portion of the currentColor computed property put in the code
return mCurrentColor
In the SET portion of the currentColor computed property put in the code
mCurrentColor = value

The LABEL DOES have a property we can use so we aren’t going to need to add a property to our custom control. WE can make use of the LABEL’s text property
In the GET portion of the label computed property put in the code
return label1.text
In the SET portion of the label computed property put in the code
label1.text = value

Now to make it so we can expose these two custom added properties we need to RIGHT CLICK the labeledColorPickerControl in the navigator (the left hand list in the IDE)


In the contextual menu you should see an option for “Inspector Behaviour”. Select that item and you will a panel that will allow you to customize which properties are seen in the inspector.

**** WARNING **** DO NOT DISABLE ANY check boxes UNLESS you are using TEXT or XML projects as in binary projects getting them re-enabled is VERY difficult (see **)

To make a property, including computed properties, visible make sure the check box at the left is ENABLED

Now if you drag an instance of your custom control to a layout you will see the properties we just exposed in the inspector along with all the others the container normally has.

Note that at this point our control is NOT making full use of our new properties yet. Due to how the IDE works it does NOT give you a full WYSIWYG experience for custom controls. It does NOT execute your custom code for setting the newly added properties when it draws the layout. Changing the label text property or the currentColor will not redraw the IDE’s representation using those values. You MUST run the project to see any changes.

Lets make it so when the currentColor is changed that we see this change in the control at runtime. In our labeledColorPickerControl we’ll edit the SET method for the currentColor computed property. What we are going to do is SET the mCurrentColor property, which is already in place, AND make sure that the canvas shows this color change by making it redraw itself.

Make the currentColor SET method in the labeledColorPickerControl read as follows
mCurrentColor = value
canvas1.Invalidate

As well we need to add the PAINT event to the canvas control on the labeledColorPickerControl so the color is shown. Add the PAINT event to Canvas1 and in that event put
g.ForeColor = mCurrentColor
g.FillRect 0, 0, g.width, g.height

Now if you change the currentColor in the inspector & run you will see that color used in the canvas at runtime. And if you put code elsewhere that changes the currentColor of this custom control you will also see the change reflected at runtime. The same is true if you were to change the label text.

Congratulations – you have just created your first custom control. More complex examples abound but the principles are still much the same regardless of whether you start with a Canvas subclass that draws itself specially, or something more complex that uses a container control for a more complex UI element.

Foot Notes

(*)you can hide things from the library
if, for some reason, you DO NOT want you control to show in the library you can add an attribute to your control called HideFromLibrary and it will not show

(**) Note that IF you disable one getting it re-enabled is VERY difficult because of a bug in the IDE

Subclasses are your friends

There are a LOT of things that you will hav a hard time doing if you only ever add instances of controls from the Library in Xojo to your layouts. And you will spend a LOT of time trying to sort out how to beat them into submission to do what you want with some combination of handling the events, properties and methods on your layout.

Like this fun little request that came in on an off forum chat service.

When you do “CMD-A” in a listbox it selects ALL rows…. but is there a way to select all “but certain” rows… rows that should never be selected?

With just an instance on a layout and the handful of events you have available you could probably make this work – eventually.

But I made a subclass and within 5 minutes (or less) had this

And very quickly altered it to this

The reason I could do this so quickly ? A subclass.

In a subclass you can add methods, properties, events, new events using event definitions and you CAN also add things like Menu Handlers. And therein lies the crucial piece of information.

In an instance placed directly on a window you have no opportunity to add menu handlers so you have to devise some other means to catch the “Select All” keystroke or menu selection and try to do something else.

But in the subclass I CAN add whatever menu handlers I want – I can even add menu handlers for menu items that do not exist yet (yes really !). And this makes is possible for us to add a menu handler for EditSelectAll – the default name for that menu item in a desktop project. If you happen to rename this menu then you would need to update the menu handler implementation to match.

As soon as you do that and place an instance of your custom subclass on a layout you will now be able to handle the Select All menu however you want.

And that makes it possible for you to use all kinds of things that are not normally accessible when you put an instance directly on a layout and try to make it behave specially.

Subclassing is a VERY powerful way to make your customized versions of the normal controls and classes Xojo provides as part of its framework.

Why subclass ?

A recent discussion lead to an odd question. Why do you need to subclass things in Xojo ? Whats the point since they give you all these great controls and classes ? What would make you WANT to subclass things instead of just implementing the events of the existing controls ?

I was sort of surprised at this. And I can see where this line of thinking has some merit. It’s not often that I will subclass something like a pushbutton. I just use them as is from the library in the Xojo IDE.

And for many things this is true. They are perfectly suited to the task I need to accomplish as is. But, often, they aren’t. Sometimes I can make an instance do that tiny little bit special that I need just by implementing the various events. When I I need something special about how a listbox draws itself I can often just use the various paint events that it provides to do the customization. If I only need to do this customization once then a subclass may be more effort than I really want to invest.

But if I have several places where this same customization is required I’ll create a subclass, write my custom drawing code once in the subclass, and then put instances of this subclass in the many places its needed. It keeps me from repeated copying and pasting the same code over & over into multiple instances all over the place. And I also don’t have to remember to fix each one when I find a bug or need some additional tweaks to how things work. I fix the code once in the subclass and ALL instances now get that behaviour without touching each one.

Some times I need much more than just custom drawing. And that’s when I will choose to subclass a control to add some special behaviour to that subclass. A recent discussion was about how to make the SelectAll menu item behave in a special way for a specific listbox. In a subclass I can add menu handlers to handle Select All as well as many others – something I cannot do in an instance on a layout. There is no way to add a menu handler to an instance.

The other thing that a subclass will let me do is add new events that I can then implement in the instances I put on layouts. I can add new events for all kinds of purposes – even to ASK the outside world for more information about the environment the instance is running in (more on that in another post about events). Or you can add something like a “BeforeKeyPress”, “KeyPress”, “AfterKeyPress” for a control where you need this sort of functionality.

In addition to adding new events you can, in a subclass, hide existing events that the superclass exposes that your do not want your subclass to expose. You simply add the event handler to your subclass and do NOT leave it exposed to the rest of your code. You don’t have to put ANY code in the event handler.

Subclasses not only let you add new events, they let you add properties, methods and just about any other kind of code item you can think of. All of this can be open to the public or for private use only.

And the BEST thing about using subclasses is that your code then becomes much more self contained and reusable. You can alter the subclass code and not worry about whether altering that subclass’ code has somehow altered something else outside of its control. It limits the amount of side effects your code in the subclass can possibly cause.

Subclasses are for taking a more general purpose class and specializing it to do something unique.

Take advantage of that in your own applications.

Try Catch Finally

Xojo supports the use of exceptions and the error handling machnisms that makes possible.

in order to use exceptions effectively you need to use a language feature called a Try block. It has several parts to it. First there is the initial TRY statement which opens a new scope level AND delimits where the TRY block starts. Its entirely possible to simply have code like

TRY
   // some code enclosed by the block
END TRY

You are not forced to have a CATCH statement in a try block. This style can be useful if, for instance, in the try portion you assign a value to a variable when there is no exception raised and then check that variable after the block and behave accordingly. Perhaps something like

dim f as Folderitem
TRY
   f = SpecialFolder.ApplicationData.Child("my.app.bundleID")
END TRY

if f is nil then
   f.CreateAsFolder
end if

But not that this code _could_ have an issue of for some reason SpecialFolder.ApplicationData is nil. We didnt check that and should before just blindly using it. There are other ways to accomplish much the same task by dealing with whatever exceptions are raised. For instance you might rewrite the above code to

dim f as Folderitem
TRY
   f = SpecialFolder.ApplicationData
   f = f.Child("my.app.bundleID")
CATCH nilError as NILObjectException
   // hmmm this means SpecialFolder.ApplicationData is nil ?
   // we might show an error dialog to the user or something to 
   // let them know that the folder we were trying to create cant be 
   // created in the SpecialFolder.ApplicationData location 
   // and we might return here rather than try to carry on
END TRY

if f is nil then
   f.CreateAsFolder
end if

This style at least makes it so we have checked whether or not SpecialFolder.ApplicationData was nil – its unusual that it might be but can happen.

You can have as many CATCH statements as you want and they can be written in many different styles. Personally I always use the form

Catch ErrorParameter As ErrorType

with a name for the error parameter; which actually ends up being a local variable in the CATCH code you write, and a specific type. In my code you might see

TRY
CATCH noExc as NilObjectException
  // code to deal with the Nil Object Exception
CATCH ioExc as IOEXception
  // code to deal with the IO Exception
END TRY

and specific code where noted by the comments to deal with the situation. I do not recommends using a single catch with a long list of select statements using introspection etc to try and handle the various exceptions. The only time I might recommend that is when its the App.Unhandled exception event and you are trying to create a report that a user can send you. Even there you have to be careful of which exceptions you catch because a normally Quit application uses an exception to Quit normally.

The last part of a TRY CATCH block is the FINALLY block. This is code that runs after all the code in any TRY or CATCH sections executes. Some times there is code that you want to execute as part of clean up that needs to release memory, mutexes, semaphores etc.

However, some assume that it will ALWAYS execute regardless of what code you have in the TRY and CATCH portions. In some languages the code in the FINALLY block is ALWAYS executed. This is NOT the case in Xojo and, if you’re not careful, it CAN easily be skipped.

For instance, if you use RETURN as the last line of the TRY or a CATCH block that is executed the FINALLY block WILL be skipped.


Try
  Raise New NilObjectException
Catch
  Return
Finally
  Break
End Try

If you execute this code you will see that the BREAK in the finally block is NOT executed. And if you changed this to


Try
  Return
Catch
Finally
  Break
End Try

Again you will see the break in the finally clause is not executed. So be careful about the use of return in a TRY CATCH block IF you expect the FINALLY clause to always be executed.

The Law of Demeter

Recently I re-read The Pragmatic Programmer mostly while on a break in Mexico. I also did my fair share of sitting in the sun, eating and event drinking but I read a LOT as well.

And I keep learning, or at least reminding myself, of several things I think are really useful to all of us.

In terms of writing OOP code the Law Of Demeter is one that is really useful. Basically in this Law you should only access :

– items (properties, methods, constants, etc) of the of the object you are part of
– items (properties, methods, constants, etc) you are passed as parameters
– items (properties, methods, constants, etc) of objects you create in your code

This limits the knowledge your code needs of the internals of other objects.

Suppose we have a set up something like :

Global Dim someGlobalVar as integer

Class FooBar
   Dim i as integer
   Sub fubaz() as string
   End Sub
End Class

Class Bar
   Dim fubar as FooBar
   Sub Constructor()
     fubar = new FooBar
   End Sub 
 
   Sub Baz()
   End Sub
End Class

Class Foo
  Dim BarInstance as Bar

  Sub Constructor
    self.BarInstance = new Bar
  End Sub

  Function HasInstance() as Boolean
    // this one is OK !!!!!
    return (BarInstance is nil) = false   
  End Function

  Sub CallBazOfBar()
    // this one is OK !!!!!
    BarInstance.Baz()
  End function

  Function CallBazOfPassedInBar(b as Bar)
    // this one is OK !!!!!
    b.Baz()
  End Function

  Function CreateAndCallBazOfBar()
    // this one is OK !!!!!
    dim b as new Bar
    b.Baz()
  End Function

  Function ReachesThroughBarToFooBar() as integer
    return BarInstance.fubar.i
  End function

  Function ReliesOnGlobal() as integer
    return someGlobalVar
  End function

  
End Class 

Then for us to adhere to this principle the following new methods on our Class Foo would NOT be ok :

Function ReachesThroughBarToFooBar() as integer
   return BarInstance.fubar.i
End function

This one is NOT ok because it requires the Foo class to know more about the internals and implementation of the Bar class AND FooBar class than it should. Instead the Bar class should have a method on it that can be invoked to get details of its properties or classes it owns.

Function ReliesOnGlobal() as integer
   return someGlobalVar
End function

This one is NOT ok because it requires the Foo class to rely on a global variable that is outside the scope of the instance and the method using it.

Methods in our Foo class should ONLY use :

  1. methods in the instance itself (HasInstance is OK)
  2. methods of any parameters passed to the methods like CallBazOfPassedInBar(b as Bar)
  3. Any objects created/instantiated within the method like CreateAndCallBazOfBar
  4. methods in the instances properties (in this case methods of Bar like CallBazOfBar)
  5. A global variable, accessible by the instance, that is in the scope of the method (this last one is harder to explain)

I like the Wikipedia summary which is

 For many modern object oriented languages that use a dot as field identifier, the law can be stated simply as “use only one dot”. That is, the code a.b.Method() breaks the law where a.Method() does not.

https://en.wikipedia.org/wiki/Law_of_Demeter

When Apple does its own thing

I started up Xojo 2019r3 the other day and changed some colors while tracking down a nifty dark mode bug (see http://feedback.xojo.com/case/58695)

And after that all versions of Xojo would, when starting, immediately show the color picker panel like this :

Now lets be clear – I dont consider this to be a Xojo bug.

It seems that, Apple writes their own keys to the Xojo plist and these may influence whether the color picker panel shows up when you start Xojo.

If you open the Xojo plist in a text editor you may find that you have a bunch of keys like  NSColorPanelMode, NSColorPanelMode.modal, NSColorPanelToolbarIsShown.modal, NSColorPanelVisibleSwatchRows.modal, NSSplitView Subview Frames, NSColorPanelSplitView, NSToolbar Configuration com.apple.NSColorPanel. NSWindow Frame NSColorPanel, and NSWindow Frame NSColorPanel.modal

Apple adds these to the plist on its own (personally I find this less than helpful but there’s really no arguing with Apple about this sort of thing)

What I dont know is if Xojo can/could make sure that the color panel preferences get writtem in a way the color picker does not open on next launch or not.

If they can it would sure be nice.

In the mean time I’ve simply stripped those keys out when/if they appear and things go back to normal.