Bevelbutton redux

At the end of June I posted about a replacement for the bevel button that I’d created.

Since then I’ve had some feedback and some updates & fixes submitted for it and a newer versions has been posted.

If you’ve used it in your projects you might want to grab the latest version.

Delegates

The Xojo docs about delegates are quite sparse about what you can or cannot do with them and whether they can or cannot take certain kinds of parameters. What they do say is that

A Delegate data type is an object representing a specific method. It is a function pointer with a method signature.

I was recently asked if a delegate that did not make use of any external dynamic library could take an object parameter. The delegate definition and the code creating the delegate are all inside a single Xojo project.

Delegates are kind of esoteric but like many things, when you need one you need one and it may be the only way to do what it is you want to do.

Inside a single Xojo project “delegation” can be done in several ways. Before Delegates what you might often find that an interface would be used. This would work for code all in the same project, but could lead to a lot of interfaces with one method just to be able to declare the delegate. When you use a delegate definition and AddressOf to create the delegate the difference is negligible. In both cases you define a new type, either the interface or the delegate, and then in some way have to implement that type so you can make use of it.

One key difference is that with an interface you can’t just use it with any method that has the proper signature. It has to be implemented by a class and then you need an instance of that class. So there can be more work with an interface in this case.

But notice I wrote that both a Delegate and and Interface define a new data type. What that means is that you can use the delegate name in a DIM statement just like you would use Integer, String, Color, Text etc.

dim delegateReference as MydelegateType

And then you can assign values to it – but in the case of a delegate you need to make sure you assign values that match the signature the delegate was defined with. This is the same as if you declare a variable as an integer you can’t assign a string to it.

For instance if we had the following :

Delegate NoParamDelegate() 
Delegate OneIntParamDelegate(i as integer)

Sub NoParamMethod()
End Sub
Sub OneParamMethod(i as integer)
End Sub
Sub InvalidOneParmMethod(s as string)
End Sub

dim noParam as NoParamDelegate
dim oneParam as OneIntParamDelegate

We have two delegates defined – the NoParamDelegate and OneIntParamDelegate. One takes no parameters. The other takes one integer parameter.

What that means is that the NoParamDelegate can ONLY be assigned to contain the AddressOf a method that takes NO parameters. It cannot hold ANY other pointer to any other method. Given the previous definitions :

// would compile
noParam = AddressOf NoParamMethod
oneParam = AddressOf OneIntParamMethod

// will not compile - you get a type mimatch
noParam = AddressOf OneIntParamMethod
oneParam = AddressOf NoParamMethod

// will not compile 
// although this method has one param the parms do not match types
noParam = AddressOf InvalidOneParmMethod
oneParam = AddressOf InvalidOneParmMethod

Delegates are “fussy” – you MUST assign the addressof a method that has the EXACT SAME SIGNATURE the delegate was defined with.

But once you do this you CAN pass whatever data types you want within your own project.

If you happen to use a delegate to call EXTERNAL code, which is sometimes done in the case of interfacing with system libraries and other non-Xojo code, you often use a Ptr although you can use a delegate as well if you make sure you define the delegate with the signature that matches the external codes (this can be tricky sometimes)

If you do match up the types one thing you will run into is that Xojo objects can not be passed to external code this way. You can only pass ptr’s, structures – careful here as you need to know the specific calling conventions in use – and other simple types. Xojo will coerce many things to the correct type for you just as it does for declares.

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 !

Universal Project : II

In a previous article I detailed some of the things I’d like to see the IDE do to make it so a “Universal Project” that could, from a single source code base, produce one, or more, compiled applications.

The up side to this would be that if you have a suite of related applications the code that is common between them, perhaps business specific logic, would only need to be altered in one place and could immediately be tested across all the related apps much more simply than by using external items, SVN externals, or the Git equivalent.

Currently it’s almost possible to do this on your own in a single project. Except for how the IDE behaves. If you save a Desktop project as a text project you’ll see the project manifest has one set of key value pairs. And if you save a Console project you’ll see there is a lot of commonality but they are not identical. The same is true for a Web and iOS projects. They all share a common set of key value pairs but each type has some that are unique to that type of project.

The downside here is that each project type only reads and saves those key value pairs that it recognizes, and throws away any others. This is easy to test simply by adding your own to any manifest, opening it in the IDE, altering a project setting then saving.

In order to make it so a single project could be a desktop, web, iOS, or console project ALL key value pairs across all these project types would need to be preserved, even if they are not used.

If the IDE did this it would be one step along the path to creating a Universal app.

The Universal project

It’s long been a desire of Xojo users to have a single project thay they can open and compile a desktop app, web app, iOS app and console apps from the same project.

This would make it so if you have a suite of related applications that all use common code sharing that common code would be easier since its all in the same project and just by selecting a different target in the build settings you could compile whichever one you selected.

This would be a really handy capability. One that I’ve used in other IDE’s like Metrowerks CodeWarrior. In there you created a new “Target” and then could designate which “files” were part of the target. Since XOjo isn’t file oriented in that way it would make sense to have some other way to designate which targets a class/module/layout was part of.

In a way this already exists.

If you wrote a module and set its “compatibility” flags either on the whole module you can designate whether that module is compatible with Desktop, Web, iOS, or Console apps. You could create it, save it and then drop it into any one of those kinds of projects and based on those compatibility flag settings it would or would not compile for whatever kind of project you were creating.

Right now the only things that can be selected as compatibility settings are Desktop, Web, iOS, and Console. Either 32 or 64 bits. And when you put a check mark next to one of those items in the Build Settings boolean flags are set (TargetMacOS, TargetWeb, TargetiOS, TargetConsole and either Target32bit or Target64bit)

What if you could add your own targets ? Instead of just desktop, web, ios and console we could create new “Targets”.

When you select “Target” this creates a new spot in the IDE under macOS, Windows, Linux where we could add build steps like we do for macOS, Windows, Linux, Web. And it can be checked or not checked like the other build targets. Then like the others, when checked, a boolean “Target<whatevername we gave it>” should also be crated like happens for macOS, Windows, Linux and others. Then in code we could write

#if TargetUserDefined
#endif

exactly the same as we do with #If TargetMacOS etc.

The other thing we would need is for the compatibility flags editor to have extra rows in it, one for each of the targets we define. That way we could set the proper compatibility settings right in the IDE.

There are still a couple issues that would have to be sorted out in the IDE but this would be one step to making the “Universal Project” that has so long been desired.

If you have interest in this sign on to this case

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

Leaky abstractions and how to plug some

Every once in a while you run into some code that tries to present a fairly abstract API to some class / module. Maybe this is in your own code or in code you have received from some other source.

But as you work with it you find that the abstraction reveals internal implementation details that really should not be known outside the class. One way to hide these sorts of details from other portions of your code is to use an API defined in an interface.

However, even that doesnt always work.

Suppose you have some set of classes where you want to make it possible for one to contain many of the others and that the internal storage mechanism should be invisible, or at least not easily guessable, from other classes. Something like you see in the IDE where you have Folders that can contain all kinds of other items, or Modules that can also contains other items.

It would make sense for the classes that represent such a Container type to implement the Xojo.Core.Iterable interface so you could use either in a For … Next loop.

Lets start by assuming we’re going to create a set up like

Class ContainerType
   Implements Xojo.Core.Iterator

   Function MoveNext() as Boolean
   End Function

   Function Value() as Auto
   End Function
End Class

Class FolderType
   Inherits ContainerType
End Class

Class ModuleType
   Inherits ContainerType
End Class

We’ll have a base ContainerType class and then two subclasses*. The names of the classes I’ve chosen don’t conflict with built in ones.

At this point you might think you could write

Dim f As New ContainerType

For Each foo As Auto In f
    
Next

but you can’t. In a for .. each you need an item that implements Xojo.Core.Iterator – not Xojo.Core.Iterable.

OK we need an iterator so we’ll add one like

Class ContainerTypeIterator
  Implements Xojo.Core.Iterator

   Function MoveNext() as Boolean
   End Function

   Function Value() as Auto
   End Function
End Class

As well we need to make our initial class implement Xojo.Core.Iterable

Class ContainerType
   Implements Xojo.Core.Iterable

   Function GetIterator() as Xojo.Core.Iterator
   End Function

End Class

Class FolderType
   Inherits ContainerType
End Class

Class ModuleType
   Inherits ContainerType
End Class

And now we can write

Dim f As New ContainerType // or new FolderType or new ModuleType

For Each foo As Auto In f
    
Next

But how do we make the Iterator itself work ? Unfortunately there don’t seem to be any Xojo code examples and the docs are kind of light on this.

The iterator isnt a “friend” of our base class so it cannot reach into its guts and grab whatever data it wants. Especially not if that data is protected or private in any way. So our Iterator needs some api to be able to get the data it needs from our ContainerType classes. So we need an API for that.

But whatever API we put on the ContainerType class is also going to be usable outside the Iterator. There’s no way straight forward simple way to restrict an API to ONLY being by one class in Xojo. (This is where “friend” classes would be handy as they could have a “special” relationship and be allowed to use some private api that no other class could – there are hacky ways to achieve this though)

And so however you implement the Iterator & its access to the individual members of each class that implements Iterable those API’s are usable by ANY other code. And so that abstraction of “iterable” and how it’s implemented leaks out to the rest of the world.

Stopping this leakage can be done – in a limited way. In a module you can have an interafce that is private to that module and then classes that are in that module can implement that interface. Only methods and other classes in that module can then use that interface.

Module Containers
  Private Interface PrivateContainerAccessors
     Function MoveNext() as boolean
     Function Value() as Variant
  End Interface

  Class ContainerType
    Implements Xojo.Core.Iterable

    Function GetIterator() as Xojo.Core.Iterator
    End Function

     Function MoveNext() as boolean
     End Function

     Function Value() as Variant
     End Function

  End Class

  Class FolderType
    Inherits ContainerType

     Function MoveNext() as boolean
     End Function

     Function Value() as Variant
     End Function

  End Class

  Class ModuleType
    Inherits ContainerType
     Function MoveNext() as boolean
     End Function

     Function Value() as Variant
     End Function

  End Class
End Module
      

And now only classes IN the module can cast the classes that implement this interface in a way they can call the interface methods. This is quite handy – but it does have a drawback. Nothing outside this module can implement that interface. And that limits its usefulness to code you write and put in that module.

Friend scope would be really handy. In the mean time this is as close as you get and can stop your Iterable abstraction and the implementation from leaking out into the rest of your code.

*This really is JUST an example and not actual Xojo IDE code for those of you who might be suspiciously minded – I can assure you the IDE is vastly different than this – this is JUST an example that you can relate to from using the IDE

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 interesting thing is that Xojo already has many classes that behave in ways that are “list like” in many ways. Listbox, 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.