EmbeddedWindowControl

If you’ve ever used a container control on a layout and then tried to manipulate the controls at runtime with code like


For i As Integer = 0 To Self.ControlCount - 1
  Dim ctrl As Control = Self.Control(i)  
  // now manipulate this control or call its methods
Next

you’ve probably run into the EmbeddedWindowControl

Its what you get when you use a Container Control on a layout either by placing one at design time or dynamically adding one at runtime.

Note that you get an EmbeddedWindowControl – not an instance of the Container you placed there. So any code you use that tests if a control ISA specific instance will fail for your containers. You don’t get a reference to the instance you get this EmbeddedWindowControl instead. So you cant call any methods you have added to the container control or reference any properties of it.

Its been most annoying. There have been several requests for something to be done so the container the EmbeddedWindowControl was created from can be accessed. Like this one and this one and this one.

And today, for a project I was working on, I needed this and decided to figure out how to make this possible.

The result is this little sample program with one module that extends EmbeddedWindowControl in a way you can get the container control that the embedded window control was created from.

To make use of this simply copy the EmbeddedWindowControlExtensions module into your project. Then when you iterate a set of controls on a layout you can do

For i As Integer = 0 To Self.ControlCount - 1
  
  Dim ctrl As Control = Self.Control(i)
  
  If ctrl IsA EmbeddedWindowControl Then
    
    Dim cc As ContainerControl = EmbeddedWindowControl(ctrl).Container 
    
    If cc <> Nil Then
      // you now have an actual reference to the container control
      // so you can use its methods, properties, etc
      // but you will need to cast it first
    End If
    
  End If
  
Next

Enjoy !

Knowing if a property thats an enum has been set

Interesting question from a dev I’ve know for a long time.

If I have a property that’s an enum, how do I tell that it’s not been set?

And this is a good question.

Because an enum is, at its core, an integer when you declare one and run its always initialized to the default value for an integer – 0.

And so if you use this fact you can actually detect that its been set or cleared.

Simply make you list of enumerated values NOT use 0 as a valid value.

Public Enum myEnum
valueName1 = 1
valueName2 = 2
valueName3 = 3
End Enum

And now any time the value is 0 when your code starts to run you can tell any property that is declared to be a myEnum is or is not set by checking

Private Property someProperty as myEnum

Sub Open() Handles Open
  
  If 0 = Integer(someProperty) Then
    break
    // someProperty has never been set or has been deliberately set to 0
  End If
End Sub

Interfaces

Interfaces are one of those things in Xojo, and many other computing languages, that can really help you make your code more reusable and generic.

For instance, suppose you need a class that is a “List”. You could write a single class, called list, that you could add items to, remove items from, and generally manipulate in a “list like way”. You might go so far as to look up some other languages implementation of list and create a Xojo equivalent. But in general you would have (as wikipedia notes)

Operations
Implementation of the list data structure may provide some of the following operations:
- a constructor for creating an empty list;
- an operation for testing whether or not a list is empty;
- an operation for prepending an entity to a list
- an operation for appending an entity to a list
- an operation for determining the first component (or the "head") of a list
- an operation for referring to the list consisting of all the components of a list except for its first (this is called the "tail" of the list.)
- an operation for accessing the element at a given index.

But note that wikipedia, and most other place that have such a “spec” dont say how this is implemented. Just what the API is. And this is a perfect place to use an interface.

Now in Xojo MOST times you dont need to define the CONSTRUCTOR in an interface. You can but it is unusual and depending on what classes you intend to have implement this interface there can be restrictions on which constructors must exist (ie/ if you want a UI control like listbox to implement this interface it may need a constructor with no parameters)

So I would NOT add this to the interface.

But everything else can be specified in an interface.

an operation for testing whether or not a list is empty - possibly a method named "IsEmpty" that returns a boolean ?
an operation for prepending an entity to a list - possibly a method named "Prepend" that takes an element and adds it to the "front" of the list
an operation for appending an entity to a list - possibly a method named "Append" that takes an element and adds it to the "end" of the list
an operation for determining the first component (or the "head") of a list - maybe a method called "FirstItem" or "Head" that returned the first item
an operation for referring to the list consisting of all the components of a list except for its first (this is called the "tail" of the list.) a method called "Tail" that returns the list with the first item removed
an operation for accessing the element at a given index - a method called "ElementAt" that takes an index parameter and returns the element at that index

And that would be an interface that confirmed to Wikipedias notion of “List”

The interstingthing is that Xojo already has many classes that behave in ways that are “list like” in many ways. Listboix, popupmenu,combobx and a few others already have methods like AddRow, RemoveRow and many of the others that are “list manipulation and inquiry” type methods. You can find out if a listbox is empty (listcount = 0), you can remove and access rows at specific positions.

But Xojo doesnt define and use an interface for this class or any other that share similarties. However, you can add your own.

In order to do this you need to define the interface in a very generic way so that adding a row to a listbox, which may have 1 or more columns, still makes sense. Some input parameters might need to be variants instead of something more specific. And, for some things the right return value may have to be a variant instead of something more specific.

Still you might come up with an API for “list” like things that looks like :

Interface List
  Sub AddRow(ParamArray values() as string)
  End Sub
  
  Sub AddRowAt(ParamArray values() as string, 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 variant
  End Sub
  
  Sub RowValue() as Variant
  End Sub
  
  Sub RowValueAt(zeroBasedIndex as integer) as Variant
  End Sub
  
  Sub SelectedRowCount() as Integer
  End Sub
  
  Sub SelectedRowIndex() as integer
  End Sub
End Interface

And then you can apply this to your own classes. custom subclasses of listbox, combobox, popup menu and other controls that have list like aspects to them.

Once you do this you can then write generic methods that manipulate Lists, without regard to whether its a custom user class implementing the interface, a listbox, a popupmenu etc because all of them will return TRUE when you do

If <something that implements list> IsA List Then
End If

This is very handy and very powerful and wildly under utilised.

Computed Constants

Kind of an oxymoron. A constant should be .. well .. constant.

However there are times you want that constant to be permanent, or constant, and unchangeable but it needs to be computed at compile time.

And it turns out that in Xojo you can do that IF you define a constant in code like :

Const foo = 123
Const bar = 345
Const foobar = foo + bar

If you assigned these constants to variables so you could inspect them like

Dim iFoo As Integer = foo
Dim iBar As Integer = bar
Dim iFooBar As Integer = foobar

break

you would see that iFoo, iBar and iFooBar have the values 123, 345, and 468 as expected. So constants can be formed from other constants and literals at compile time and they are then permanent in your application.

But you cannot do this in a constant defined using the IDE’s constant editor. It does not compute the values in the same way as it does when you define the value in code as shown above.

If you try to define constants, cFoo = 123, cBar = 345 and cFooBar = cFoo + cBar you will find that cFoo and cBar are ok and are numeric. But cFooBar will not compile if you set its type to Number. The usual trick of using #ConstantName which works in other places in the IDE wont work in the default value field of a Const defined this way. This has lead me to submit a bug report.

In the mean time whats a person to do ?

As it sits right now the BEST we can do is a workaround.

Constant-ness is a behavioural thing in most respects. Basically its a value that never changes. Like the value of Pi, Avogadro’s number, or the gravitational constant. In our code we would like a value that never chnages once it’s compiled for these sorts of values.

But if its one of our own making using an expression that is computed at compile time would be really nice. Something like bit flags for error conditions is a common use.

It might be that we have

Const Error = 1
Const IsFatal = 2
Const FatalError = Error + isFatal

And so we can see that a fatal error is computed from the Error & isFatal flags.

Currently the only way to provide a computed constant, or something that behaves like it, is a Computed Property that only has its getter implemented.

We could then have

ComputedProperty FatalError as Integer
  Get
    return Fatal + IsError
  End Get
  Set
  End Set
End ComputedProperty

Semantically this would behave like a const.

The downside is that

  1. every time it’s accessed the value is recomputed (this can be worked around somewhat)
  2. every time it’s accessed there is method call overhead

While not a perfect replacement for a constant it’s what is possible today.

Making platform specific error codes generic

A few threads on the forums have commented that the URLConnection isnt quite as easy to use as many might expect. In particular there are comments about having to know what error codes a platform might return makes it harder to use than it should be.

Normally Xojo hides this level of detail from us.

I was thinking about this problem and have come up with something of a solution that makes it possible to both know the specific error code and yet still write code that is portable.

My solution relies on the fact that, at compile time, numeric constants will take on one of many possible values if you set up platform specific versions of a numeric constant. Its possible to set up a constant with a specific value for macOS, Windows, Linux, and iOS (as well as a couple that are legacy types) as follows :

If you were to compile this code on macOS the Foo constant would have the value 1, on Windows it would be 2 and so on. The nice thing is that code could simply use the symbolic constant Foo instead of having to rely on the specific value. Instead of writing

// is someVariable = Foo on macOS ?
if someVariable = 1 then
   // do whatever should be done 
end if

you could, and probably should write

// is someVariable = Foo on macOS ?
if someVariable = Foo then
   // do whatever should be done 
end if

This is has the added benefit of making your code more robust since a simple change to a constant is all thats required to instead of finding all the magic number 1’s everywhere. But how does this help us to making generic platform specific error codes (which I admit is a bit of an oxymoron ?)

An enumerated value can be set from one of several possible sources. It can have no specific value assigned, have a literal value, an enumerated value from another enum, or a constant.

IF Enum2 is is defined as

Public Enum Enum2
  value1 = 10
End Enum

Enum1 can be defined as

Public Enum Enum1
  value1 // no specific value assigned
  value2 = 99999
  value3 = enum2.value1
  value4 = kConst
End Enum

That we can use a constant is especially notable as we just saw we can make a constant platform specific. So its possible to have an enumerated value that takes on the value of a platform specific version of a constant (but be careful with this as you would not want to have many enumerated values with the same value as that makes them harder to use)

If we defined our enum as

Public Enum kDemoEnum
  value1 = kConstant
End Enum

and the constant as

Public Const kConstant as Number = -1
  OS X, default language, 1
  Windows, default language, 2
end Const  

when we compiled on macOS the value for kDemoEnum.value1 would be 1, on Windows 2 and on any other it would be -1 (the default for the enum)

So now you can make enumerations that give you the flexibility of named values without having to know the specific values AND a generic set of enumerated values that reflect platform specific values taken from constants.

Use carefully.

The default app templates

A lot of times people have common code that they want in EVERY application they start working on. And there are a number of ways people achieve this – copy & paste, svn externals, or a whole host of other means.

But there is a much simpler way to start off with all that common code.

Project Templates !

With templates you can not only create new “types” of projects, you can even override the default projects that the IDE starts with when you start a new Desktop, Web, iOS and Console project. So you dont even have to think about making sure you start new projects from your list of Templates. You can just select the Desktop, Web, iOS or Console items in the New Project dialog and your template project with all your common code will be used.

So how to make all this work ? We’ll start by creating a new Template project. Once you see how easy that is it’s a small step to make the IDE use always your template as the default.

A template project will, by design, always be for one of the specific types of Xojo projects. There’s no way to make a single project that is a Desktop, Web, iOS and Console project all at the same time (there is this feature request though). Every template you create will only create one kind of project.

With that in mind let’s create a new template that we can use for desktop projects.

A common complaint is that Desktop projects don’t move from Windows or macOS to Linux very well. Linux uses different default controls sizes and so your very carefully crafted UI that looks fine on macOS and Windows suddenly has overlapping controls and looks awful on Linux.

There is a very handy module from several forum posters who use Linux a lot that resolves this issue. It modifies the normal GTK3 CSS so that the defaults are more in line with those used on Windows & macOS so your design will look correct when run on Linux.

Having a Template would make it so your Desktop projects incorporate this particular module from the outset.

Unzip and open the ModGTK3 project in the unzipped result. The IDE is going to ask you to find the Build Automation item. Press Cancel and a new one will be created. There is no harm here and I’ve asked Jim to upload this file so this minor issues can be resolved.

Create a new Desktop project in Xojo. This will form the basis of our Template. Switch back to the ModGTk3 project and COPY the ENTIRE GTK3 folder from the MODGTk3 project and all contents. A right click on the GTK3 folder and selecting “copy” in the contextual menu works nicely to do this.
Switch back to the new desktop project you created and PASTE into your project.

Add the OPEN event to your apps App instance if it does not already exist.
If it does make the first 3 lines

modGTK3.initGtkEntryFix
modGTK3.initGtkWidgetHeightFix
modGTK3.InitGlobalGTK3Style

Now we need to save the Template. Templates need to be either BINARY or XML projects.

Navigate to the directory next to your executable copy of Xojo and Save the project as a binary or XML project named PiReadyDesktopApplication.

IF you cannot save in the Project Templates location save it to the desktop and move it to the Project Templates directory next to the Xojo IDE executable.

Close the project we just saved and start a new project.

In the dialog presented (shown above) select PiReadyDesktopApplication.

When the project opens there is the new project with all the GTK3 modifications & classes we inserted previously. And if you Save you will be prompted for a new location to save the new project so you do not accidentally overwrite the Template.

To make the IDE use this template as the default every time you select Desktop from the New Project dialog all you need to do is rename the PiReadyDesktopApplication to Default Desktop Project including the spaces (don’t change the file extension). Now every time you start a new desktop project it will be using your template.

And you can do the same for Web, iOS and Console templates.

see 
http://docs.xojo.com/UserGuide:IDE_Overview 
http://docs.xojo.com/UserGuide:Project_Types 

App vs App

App Battles ! Winner takes all. Last man standing and all that !

No – nothing quite so fun (although it can be a lot of fun)

This has to do with the App class at design time vs the App METHOD (yes it’s a method) at runtime.

The app class at design time can be renamed however you want. You could call it “MyApp”. And for most things that would have no impact. But, you’ll note I don’t say for ALL things.

If you start a new Desktop Application and rename the App class to MyApp I can demonstrate where there are differences.

In the new app’s Window1. Open event lets just do something simple like

dim s as string = App.<press tab>

What you should notice is that none of the defined constants autocomplete. The methods and properties of any Application will show. But no defined constants.

This makes sense because the constants do not exist on Application but they do exist on MyApp.

If we add a few properties to MyApp they also won’t autocomplete. Again the App METHOD, at runtime, returns an Application (or Console Application, Service Application, WebApplication or iosApplication depending on the project type)

Again none of the instances that the App method returns define any of the properties we added to our custom Application instance. And so they will not autocomplete.

What’s an App to do ?

We can definitely deal with this.

One way is to not rename the App class in your project – although this wont alleviate all issues. It will just ignore some for a while. And that is, for many uses, OK.

Or we could cast the return value of the App method to be our defined class type with code like

dim s as string = MyApp(App).<press tab>

This is ALMOST always safe – except in the handful of spots that App can actually be NIL – yay !

It may be better to write something like

dim s as string
if App isa MyApp then
  s = MyApp(App).<press tab>
end if

so a nil return from App won’t matter

Either way the confusion comes from the App METHOD and the App class in your project having the same name. This can make it very unclear whats wrong. And then, when you REALLY need to know why this is, if you’ve ignored this until now you wont know why this weirdness exists.

Unless of course you read this post 😛

About Attributes

A recent feedback case made me think that there may be a real lack of information about attributes.

A lot of people believe that attributes are key value pairs that must have a valid identifier as the NAME and ALWAYS have a quoted string for a value.

This is incorrect.

Attribute name can be quoted strings – meaning you can, by using a quoted string for the name – have names that include spaces that would normally be invalid.

Secondly you CAN have an attribute VALUE that is NOT a quoted string. When you do this the value that you will see at runtime comes from a CONSTANT with the name placed in the value.

An example is here

Named parameters

Currently when you call a method in Xojo the parameters are matched up starting from the first to the last from left to right. They are matched up based on their position in the argument list.

One thing some other languages support is “named parameters”.

What this allows is a certain degree of flexibility that doesn’t exist with positional parameters like Xojo uses.

For instance in Xojo if you have a method, Foo, with parameters as follows

Sub Foo(a as integer, b as string, c as Date)

you can call it only using the correct types of parameters in the correct order like

Foo(123, "345", new Date)

There are ways, with optional parameters, to modify this normal operations. If that method was defined as

Sub Foo(a as integer = -1, b as string = "", c as Date = nil)

You could call this like

Foo()
Foo(123)
Foo(123, "345")
Foo(123, "345", new Date)

All the parameters are optional and any that are not supplied a default value as shown in the declaration. But everything is still positional. And there are things you cannot do like skip one parameter. None of these will compile.


Foo(, ,New Date)
Foo( , "345" ,New Date)
Foo(123, ,New Date)

So how would named parameters help ? Named parameters can let you say, explicitly, “this value is for this parameter” rather than just matching up by position. For instance out call to Foo might look like

Foo()
Foo( a:123)
Foo( a:123, b:"345")
Foo( a:123, b:"345", c:new Date)

And you might also be able to do something like

Foo( b:"345", a:123 )
Foo( a:123, c:new Date, b:"345")

And not have to worry about the order. And this might let you do something like

Foo(c:New Date)
Foo( b:"345" , c:New Date)
Foo(a:123, c:New Date)

which skips certain parameters in a manner that you cannot do today.

Certainly this would not be a trivial change to Xojo to support positional and/or named parameters. But there are languages that do this.

In the mean time its possible to manually create your own support for “named parameters”.

If we create Foo with two signatures like

Sub Foo(a as integer = -1, b as string = "", c as Date = nil)
End Sub
Sub Foo(paramarray values as Pair)
End Sub

Then Foo could be called as

Foo(123, "345")
Foo(123, "345", New Date)
Foo( "c":New Date)
Foo( "b":"345" , "c":New Date)
Foo( "a":123, "c":New Date)

NOTE that the “names” of the parameters have to be a literal type – in this case a string.

In this set up though we cant use no parameters. So let’s alter the set up to have at least one parameter otherwise the compiler will have an ambiguous overload in the case there are no parameters. It couldn’t distinguish between the call to Foo where it should use all default parameters and an empty paramarray. So now our declarations look like

Sub Foo(a as integer = -1, b as string = "", c as Date = nil)
End Sub
Sub Foo(value as pair, paramarray values as Pair)
End Sub

And we’ll be able to call this like

// these are positional
Foo
Foo(123)
Foo(123, "345")
Foo(123, "345", New Date)

// the use "named" parameters
Foo( "c":New Date)
Foo( "b":"345" , "c":New Date)
Foo( "a":123, "c":New Date)

So we’re on our way to being able to use either positional parameters OR named parameters. Now how do we make use of the overload that supports named parameters to call the one that supports positional parameters ?

In this method we need to

  • make sure we declare one local variable of the same type for each positional parameter
  • make sure we set these local variables default value to the same default values as the version that uses positional parameters
  • process the FIRST pair and all subsequent pairs in the same fashion and assign values to the local variables

Following all those admonitions the code in the version of foo using named parameters looks like

Dim a As Integer = -1
Dim b As String 
Dim c As Date

Select Case value.Left
Case "a"
  a = value.Right.IntegerValue
Case "b"
  b = value.Right.StringValue
Case "c"
  c = value.Right
End Select

For i As Integer = 0 To values.ubound
  
  Select Case values(i).Left
  Case "a"
    a =  values(i).Right.IntegerValue
  Case "b"
    b =  values(i).Right.StringValue
  Case "c"
    c =  values(i).Right
  End Select
  
Next

foo(a, b, c)

There are caveats to this technique though. Positional parameters will be checked by the compiler for type, the “named parameter” version will only be checked that the passed items ARE pairs. The names and values contained by those pairs are variants and so can be anything. And you can pass the same named parameter multiple times since the compiler is unaware of named parameters. And you can’t use “byref” parameters with the named parameter version – you COULD use reference types though.

I’d love to see Xojo support named and positional parameters using a syntax that looks like “pairs” as first presented.

In the mean time this is what we have.

Simple code sharing on macOS

For anyone not using version control perhaps the easiest way to share code between various projects is to use external items. However, not everything cam be made external. Modules that contain classes & other modules cant be shared via external items.

So how can you share these ?

On macOS the answer is … ALIASES !!!!!

The trick is how you set things up when you want to share such a thing between various projects. But this only works for TEXT projects because text projects save everything in separate files. For binary & XML projects you really dont have much in the way of choices when it comes to sharing Modules with other classes & modules in them.

And, if you ARE using TEXT projects then its also very likely you ARE using version control. So this tip is really for a very narrow set of use cases.

Basically what we need to do is set up an aliases that refers to the code we want to share instead of the code in our project.

Lets walk through a really simple example.

First create a new folder on your desktop – I called mine Code Sharing Example.

Now lets create a new project and add a module that we’re going to share between this new project and others.

And we’ll save this in a new folder we create inside the new folder we created earlier. I named the folder this is saved in Originator since we’re going to have the original source in this project and others will use it.Make sure you save the project as a TEXT, or Xojo Project. I also named the project Originator.xojo_project

This forms the basis of what we want to share.

Start a new desktop project. In this example I happen to use a desktop project but it could be a web or console app. iOS is harder to do this with because it uses the new, now deprecated Xojo framework so data type compatibility may be an issue. However, if you are using the new framework in desktop or other apps then you can use the same technique.

In this new app we are going to add a PROXY module that we will fix up manually later. Its just a placeholder. But it does make life simpler if you name this the same as the one we wanted to bring in from the other project. So we’ll name it ToBeShared like in the Originator project.

Now save this project in a new folder inside the Code Sharing Folder. I named mine Second Project and the project also named Second Project.

And now the manual work to make it so we can share the module.

A module, when saved as a text project, is a file. If you look in the folder that holds the Originator Project you will see a file named ToBeShared.xojo_code as well as a directory named ToBeShared.

In order to get Second Project to read the Originator Projects module and contained classes we need to replace the Second Projects file on disk with an alias named exactly the same – extension and everything. And we also need to make sure we have an alias to the directory with the ToBeShared name so the IDE realizes that this is a module with contents.

Since we added the proxy in the Second Project with the exact name we do not need to do anything to the project manifest.

First navigate to Second Project and remove ToBeShared.xojo_code

Then navigate to Originator Project and select ToBeShared.xojo_code and the ToBeShared directory. And press Cmd + Ctrl + A (or right click and select make alias)

Move these two aliases to the Second Project directory.

We’re almost done.

Navigate to Second Project.

Change ToBeShared alias so its names is only ToBeShared without the alias as part of the name. And ToBeShared.xojo_code alias to ToBeShared.xojo_code again with the alias part removed.

Open the Originator project & add a method to the Shareable class and the ToBeShared module. Save.

Now open the Second Project and you should see those just added items.

And here is where norm realizes he missed a step 😛

Thats ok though.

I’ll show you how I fixed it and what I messed up earlier.

To explain the problem. We should have added not just a proxy that we’d fix for the module but the Shareable class inside it as well. This would have made it so we did not need to manually fix the manifest and creating the aliases would have been sufficient. If you were to go back to that step & add the class then everything would just work now.

But since I missed that step I’ll manually fix the manifest. If you opened the Second project what was missing is the class that we added inside the ToBeSharedModule. The reason is that the manifest does not know there is such a class.

In the Originator project you would see something like

Module=ToBeShared;ToBeShared.xojo_code;&h000000000F00AFFF;&h0000000000000000;false
Class=ShareableClass;ToBeShared/ShareableClass.xojo_code;&h00000000580AC7FF;&h000000000F00AFFF;false

But when you open the Second Project manifest, because we did not add the class to the module, you only see something like

Module=ToBeShared;ToBeShared.xojo_code;&h0000000042EA77FF;&h0000000000000000;false

and no entry for the class. And thats the problem. The manifest lists everything a project is composed of and since there is no entry for the class the class contained by the module doesnt show. And the fix is simply to copy the lines for the module & class in the manifest from the Originator project and replace the one line for the module in the Second Project.*

And once you copy that across & save the manifest and reopen the project there’s the code from the Originator project. And if you make chnages to this code in the second project and reopen the originator project the changes will exist there as well.

One thing to take care with – do NOT open both projects at the same time and edit in both. You are sure to cause yourself problems.

If you add new classes to either Originator or Second Project you will have to do many of the same manifest file changes over again so each project knows about the added items.

*When manually editing a manifest there are some things to be careful about. One is the two hexadecimal entries on the line. The first is the items id and the second the id of the item that contains this one. These items need to be unique within a project. Take care to make sure this is true otherwise you run the very real risk of messing your project manifest up to the point your project won’t load.