setBackgroundColor: is broken when control is child of a canvas inside a container

The backgroundColor I have in XojoiOSWrapper has stopped working in 2017R1.

[code]Public Sub BackGroundColor(extends UIView as iOSControl, assigns Clr as Color)

Declare Function NSClassFromString Lib “Foundation” (className As CFStringRef) As Ptr
Declare Function colorWithRGBA Lib “UIKit” Selector “colorWithRed:green:blue:alpha:” ( _
UIColorClassRef As Ptr, red As CGFloat, green As CGFloat, blue As CGFloat, alpha As CGFloat) As Ptr
Declare Function view Lib “UIKit” Selector “view” (UIViewController As Ptr) As Ptr
Declare Sub setBackgroundColor Lib “UIKit” Selector “setBackgroundColor:” (UIView As Ptr, UIColor As Ptr)

Dim UIColorClassPtr As Ptr = NSClassFromString(“UIColor”)
Dim colorPtr As ptr = colorWithRGBA(UIColorClassPtr, (Clr.Red / 255), (Clr.Green / 255), (Clr.Blue / 255), 1-(Clr.Alpha/255))
Dim viewPtr As Ptr = UIView.Handle
setBackgroundColor(viewPtr, colorPtr)
End Sub
[/code]

It does not crash or anything. It simply does nothing.

I am a bit tired at the moment, the solution evades me. I will appreciate a hand.

OK. Just found out that backgroundcolor is broken when controls are on an iOSContainerControl. When the control rests on a view, BackgroundColor behaves as expected. So it must be something I don’t quite understand about view hierarchy.

I use a function from iOSKit and one difference I can see is the handling of 32/64 bit (Xojo runs a 32-bit app in debug mode in the simulator). Does it work if you change the declaration for colorWithRed:green:blue:alpha so that:

#if Target32Bit
Declare Function colorWithRGBA Lib "UIKit" Selector "colorWithRed:green:blue:alpha:" (c As Ptr, red As Single, green As Single, blue As Single, alpha As Single) As Ptr
#Else
Declare Function colorWithRGBA Lib "UIKit" Selector "colorWithRed:green:blue:alpha:" (c As Ptr, red As Double, green As Double, blue As Double, alpha As Double) As Ptr
#Endif

?

Thank you Jason, but no, it still does not work.

I can apply a setBackgroundColor to the ContainerControl itself fine, but no control on top of it. I wonder if this is a limitation of the platform, or some issue stemming from the way ContainerControl is implemented.

I am not familiar enough with the UI View structure to imagine what can be going on. Hopefully Jason King or Ulrich Bogun will chime in.

I could, but I have no clue either. Technically embedding a control means it becomes a subview of the parent view – the containercontrol in that case. Still should not change its functionality …

That is what I supposed, but I am way less familiar with iOS framework than you.

What is surprising is that absolutely no error is triggered, neither in Xojo, nor in Console.

The absence of an error does not surprise me. Your declare was perfectly fine, so no reason for an error.

I only wonder if the setBackground targets the correct view.
Do you have the declares necessary to examine the ContainerControl’s view and its subviews? It’s a slightly bit more difficult because

Declare Function subviews lib "UIKit" selector "subviews" (View as Ptr) As Ptr

gives you a NSArray containing the subviews.

Function ObjectAtIndex lib "Foundation" selector "objectAtIndex:" (Array as Ptr, Index As UInteger) As Ptr

gives you the subview at index, whereas

Function Count  lib "Foundation" selector "count" (Array As Ptr) As UInteger

tells you how many items are in that array.

I would, just for a test, try to cast the backgroundColor on the appropriate subview.

if you wonder if the object at a given index is your control,

Function DebugDescription lib "Foundation" selector "debugDescription" (id as ptr) as CFStringRef

should help.

Ah, that is an excellent way to investigate.

I was indeed starting to wonder if for some reason Xojo was not reporting the handle correctly. I will have to get at this tomorrow morning when I have a clear head and try to write the code to get all items, as well as their ID, and see what I get.

Thank you so much Ulrich. I will report my discoveries.

You’re very welcome, Michel.
Embedding may cause problems sometimes. I encountered a similar problem recently when I tried to help a user on macOS where he is using my AppleLib ScrollView. This works nicely when you just embed Xojo controls as a documentView – he did so with a Canvas. Sadly, macOS’ coordinate system is reversed and so the scrollview defaults to the bottom, not the top. You can handle this by using a Flipped view (an NSView with isFlipped being true) as documentView, but then you must embed another normal view in it or everything would be upside down. This NSView becomes the layer for everything that should be visible. The canvas being embedded so deeply results in its events not firing … It is there but will only draw once you trigger its DrawRect routine in the sublayer hierarchy; an invalidate on the Canvas itself did not work.

So I hope your problem can be solved similarly. Fingers crossed!

Fingers crossed :slight_smile:

OK.

Trying this morning, I encounter several hurdles.

[code]Declare Function subviews lib “UIKit” selector “subviews” (View as Ptr) As Ptr
'gives you a NSArray containing the subviews.

Declare Function ObjectAtIndex lib “Foundation” selector “objectAtIndex:” (Array as Ptr, Index As UInteger) As Ptr
'gives you the subview at index, whereas

Declare Function Count lib “Foundation” selector “count” (Array As Ptr) As UInteger

dim mainArray as new NSArray(ContainerControl11)
for q as integer = 0 to mainArray.Count - 1

next[/code]

Subviews is alright, but ObjectAtIndex and Count trigger a syntax error. I tried to look at what you did in iOSLib, I do not see the difference.

As for MainArray, I thought it could be part of iOSLib, but the type is unrecognized.

Have pity for the less taught…

dim mainArray as Ptr=subviews(ContainerControl11.handle)
dim n as Integer= Count(mainArray)-1 //so it’s like ubound
dim myView as Ptr
for q as integer=0 to n
myView=ObjectAtIndex(mainArray, q)

next

BTW setBackgroundColor works, probably you are using the wrong view

Hi Antonio.

Thank you for your helping hand.

You are right. SetBackgroundColor does work in a brand new ContainerControl in a small test project.

But my current project is a tad more complex.

I use a canvas as background to show a check on the screen.

Then on that canvas, I place an iOSTextArea whose color I want the color of to be the same as the canvas. That is when it goes wrong. The TextArea color never changes.

The very same TextArea directly placed onto the ContainerControl does indeed change color as planned.

When the TextArea is child of the iOSCanvas, setBackgroundColor stops working. If I make sure it stays child of the view, everything works as expected.

I shall experiment further, see if it is not an issue with a bad handle reported by the control, as suggested by Ulrich.

you should know the control name so instead of looking within the views you can navigate from the xojo side:
this should work:

//UIBackgroundColor is the method the works with pointer and declare, UIColor is a method to get Ptr for a color, you can translate it with your actual methods. Public Sub backGroundColor(extends cc as iosControl, assigns c as Color) UIBackgroundColor(cc.Handle, UIColor(c)) End Sub Public Sub backGroundColor(extends cc as iosControl, name as text, assigns c as Color) dim n as integer=cc.ControlCount-1 For i As Integer=0 To n if cc.Control(i) isA iOSControl and cc.Control(i).Name=name then UIBackgroundColor(cc.Control(i).Handle, UIColor(c)) Elseif cc.Control(i).ControlCount>0 Then cc.Control(i).backGroundColor(name)=c End If Next End Sub

In your case (if I have understood) you could call myCanvas.backgroundColor(“myTextArea”)=color.orange