X Platform drawing

@jotter I think you also miss the use of VARIANT as wholly unhelpful

A person could pass in an integer - and the method call would compile and fail spectacularly at run time
Pushing errors out to runtime is probably one of the worst things about this design
The earlier you catch errors the better
Catch them at design time they are easy to fix - no code written yet
Change the design

At compile time - well not perfect but no code has shipped

But at runtime its way too late !

I’m sure I hear the

Oh but just TEST the type at runtime to make sure its a Graphics or WebGraphics !
So now the code is

#If TargetDesktop Or TargetMobile Then
   if (context isa graphics) = false then
       return
    end if
    Var g As Graphics = context
#EndIf
 
#If TargetWeb Then
   if (context isa WebGraphics) = false then
       return
    end if
   Var g As WebGraphics = context
#EndIf

That still leaves the issue as a RUNTIME one
and the CALLER is 100% unaware that their call has failed when passing the wrong parameter type (ICK !)

The compiler cant help you at all (which I personally think is a huge downfall)

An interface would certainly make life a bit easier - at least the graphics & web graphics would present a similar API

Variants subvert the type subsystem in Xojo and should be avoided so the compiler CAN help warn about wrong parameter types, type mismatches etc

Having to resort to them for this code is great example of a bad design leaking into the wild where you have no choice but to deal with that bad choice

3 Likes

Something you MIGHT consider is writing your own wrapper class
So DrawBoard looks like

 DrawBoard(context as MyWrapper)

And calls to it are like

Var cb As New Checkerboard

dim wrapper as new MyWrapper(g) 
cb.DrawBoard( wrapper(g) )
cb.DrawCheckers(wrapper(g) )

MyWrapper then can have one constructor for Web and one for Desktop (thanks to compatibility flags)

the web only constructor

Public Sub Constructor(g as webGraphics)
        instance = g  
End Sub

the desktop only constructor

Public Constructor(g as Graphics)
         instance = g
end

Instance might be a variant property internally (not exposed to the world)

And then the MyWrapper exposes the various drawing methods of whatever it got called with

Sub DrawingColor(assigns c as Color)

   #If TargetDesktop Or TargetMobile Then
     Var g As Graphics = context
   #EndIf
 
   #If TargetWeb Then
     Var g As WebGraphics = context
   #EndIf 
 
   g.drawingColor = c

end sub

function DrawingColor() as color

   #If TargetDesktop Or TargetMobile Then
     Var g As Graphics = context
   #EndIf
 
   #If TargetWeb Then
     Var g As WebGraphics = context
   #EndIf 
 
   return g.DrawingColor
end function

and so on

At least this way YOU can provide some consistency by wrapping it however you want
And the compiler can help you out by flagging erroneous calls and usage

1 Like

For their Example Project it would be enough to just use the Constructors approach (without the overhead of the Wrapper class - you know… they’re marketing for “citizen developer”, not more experienced ones :wink: ).

Class 'Checkerboard':

Public Sub Constructor(g As WebGraphics) // Include in Web only, Public
  context = g
End Sub


Public Sub Constructor(g As Graphics) // Include in Desktop and Mobile, Public
  context = g
End Sub

Private Sub Constructor() // Private, so you can't instantiate without Parameter
  
End Sub

And I’d also change the conditional compilation parts… What if at some time it’s neither TargetDesktop, TargetMobile and also not TargetWeb? Not good enough to just check with #If for a single case.

#If TargetDesktop Or TargetMobile Then
  Var g As Graphics = context
#ElseIf TargetWeb Then
  Var g As WebGraphics = context
#Else
  #Pragma Error "Unsupported Target"
#EndIf 

Oh well… I guess we all have ideas and suggestions how to do better.

All I wanted to point out on TOF is that providing such example projects (and even marketing them via Blog…) doesn’t look good for them :wink:

5 Likes

Variants are so bad in these situations. Feels like typical Xojo ‘solution’ though.

3 Likes

THIS!!!
On the other hand… have you expected something else?
Let’s wait till the first comes around and offers an Addon to sell…

1 Like

I ran into this exact same issue with one of their blog posts, and this was pretty much the same answer, it’s just an example of how it could be done.

new users are going to think

This comes from the CEO. He MUST know what he’s doing

and run with it as if its great code

And this sort of thing sets them on a bad path

1 Like

and don’t forget any AI parsing through their side and learning BS

Personally I feel the approach discussed is bullshit.

It is better to integrate and use Skia for cross platform drawing functions.