COCOA quests?

Mac OSX specific forum
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: COCOA quests?

Post by wilbert »

mestnyi wrote:And generally, how do you convert the code of the apple into the code of the purebasic
why the apple documentation has two functions?
How to use these functions in the Purebasic?
I do not understand help me please.
UIView is for iOS, NSView is for MacOS.
A PB gadget is based on NSView.

As far as I can tell, bringSubviewToFront: is only available on iOS.
You can use addSubview:positioned:relativeTo: to add a subview above or below another subview.

Objective-C writes things like this

Code: Select all

[myView addSubview:mySubview]
which in PB becomes

Code: Select all

CocoaMessage(0, myView, "addSubview:", mySubview)
See also viewtopic.php?f=19&t=50795

To make things more complicated, while you can still use Objective-C with XCode, Swift has become the default language.
Using swift, it would be written like this

Code: Select all

myView.addSubview(mySubview)
Windows (x64)
Raspberry Pi OS (Arm64)
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

And what it will look like in purebasic code?

Code: Select all

func addSubview(NSView, positioned: NSWindow.OrderingMode, relativeTo: NSView?)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: COCOA quests?

Post by wilbert »

Bring a gadget to the front

Code: Select all

Procedure Gadget_BringToFront(Gadget)
  Protected.i v = GadgetID(Gadget)
  CocoaMessage(0, CocoaMessage(0, v, "superview"), "addSubview:", v)
EndProcedure
  

If OpenWindow(0, 0, 0, 600, 340, "Gadget Reordering", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
  
  RandomSeed(0)
  For i = 1 To 30
    ButtonGadget(i, Random(500), Random(310), 100, 30, "Button " + Str(i))
  Next
  
  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_Gadget
      Gadget_BringToFront(EventGadget())
    EndIf
  Until EventID = #PB_Event_CloseWindow
  
EndIf
Send a gadget to the back

Code: Select all

#NSWindowAbove = 1
#NSWindowBelow = -1

Procedure Gadget_SendToBack(Gadget)
  Protected.i v = GadgetID(Gadget)
  CocoaMessage(0, CocoaMessage(0, v, "superview"), 
               "addSubview:", v, "positioned:", #NSWindowBelow, "relativeTo:", #nil)
EndProcedure


If OpenWindow(0, 0, 0, 600, 340, "Gadget Reordering", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
  
  RandomSeed(0)
  For i = 1 To 30
    ButtonGadget(i, Random(500), Random(310), 100, 30, "Button " + Str(i))
  Next
  
  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_Gadget
      Gadget_SendToBack(EventGadget())
    EndIf
  Until EventID = #PB_Event_CloseWindow
  
EndIf
Windows (x64)
Raspberry Pi OS (Arm64)
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

Code: Select all

get_parent = CocoaMessage(0, GadgetID, "superview") ; this good
get_parent_window = CocoaMessage(0, GadgetID, "window") ; this good
get_childrens = CocoaMessage(0, WindowID, "subviews") ; - how?
How to get his "superview" by the window where gadgets are located
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

What's this?

Code: Select all

PBFlippedWindowView
PB_NSFlippedView
How to get them via GadgetID?
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: COCOA quests?

Post by wilbert »

mestnyi wrote:What's this?

Code: Select all

PBFlippedWindowView
PB_NSFlippedView
How to get them via GadgetID?
PureBasic uses flipped views sometimes to flip the coordinates.
Unfortunately these things are undocumented. Maybe Fred can explain when PB exactly uses them.

The code below shows the view hierarchy

Code: Select all

Procedure DebugSubviews(view, level=0)
  Protected subviews, i, n
  Debug Space(level*3) + PeekS(CocoaMessage(0, CocoaMessage(0, view, "className"), "UTF8String"), -1, #PB_UTF8)
  subviews = CocoaMessage(0, view, "subviews")
  n = CocoaMessage(0, subviews, "count") - 1
  For i = 0 To n
    DebugSubviews(CocoaMessage(0, subviews, "objectAtIndex:", i), level + 1)
  Next
EndProcedure

Procedure DebugViewHierarchy(Window)
  Debug "--- View hierarchy ---"
  DebugSubviews(CocoaMessage(0, WindowID(Window), "contentView"))
  Debug "---------------"  
EndProcedure


OpenWindow(0, 0, 0, 320, 320, "Canvas container", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

CanvasGadget(0, 10, 10, 300, 300, #PB_Canvas_Container)
ListViewGadget(1, 50, 10, 150, 50)
CloseGadgetList()
AddGadgetItem(1,-1, "ListView_1")
AddGadgetItem(1,-1, "ListView_2")

DebugViewHierarchy(0)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Windows (x64)
Raspberry Pi OS (Arm64)
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

That's what I wanted. The only problem with panelGadget.

Code: Select all

FlippedView = CocoaMessage(0, ParentID, "contentView")
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

wilbert Thanks works very well
viewtopic.php?f=3&t=61175&p=457517#p457517
Now some help is needed in clipping text and boxing. :)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: COCOA quests?

Post by wilbert »

mestnyi wrote:Thanks works very well
Glad to hear it is working.
mestnyi wrote:Now some help is needed in clipping text and boxing. :)
I don't see any clipping in your code :?
Can you be more specific ?
Windows (x64)
Raspberry Pi OS (Arm64)
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

wilbert wrote:
mestnyi wrote:Thanks works very well
Glad to hear it is working.
mestnyi wrote:Now some help is needed in clipping text and boxing. :)
I don't see any clipping in your code :?
Can you be more specific ?
I meant in this code.

Code: Select all

Procedure DrawRotatedText_(x, y, Text.s, Angle.f, FrontColor=$ffffff, BackColor=0)
  Protected.CGFloat r,g,b,a
  Protected.i NSString, Attributes, Color
  Protected Size.NSSize, Point.NSPoint
  
  CocoaMessage(@Attributes, 0, "NSMutableDictionary dictionaryWithCapacity:", 2)
  
  r = Red(FrontColor)/255 : g = Green(FrontColor)/255 : b = Blue(FrontColor)/255 : a = 1
  Color = CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@", @r, "green:@", @g, "blue:@", @b, "alpha:@", @a)
  CocoaMessage(0, Attributes, "setValue:", Color, "forKey:$", @"NSColor")
  
  r = Red(BackColor)/255 : g = Green(BackColor)/255 : b = Blue(BackColor)/255 : a = 0
  Color = CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@", @r, "green:@", @g, "blue:@", @b, "alpha:@", @a)
  CocoaMessage(0, Attributes, "setValue:", Color, "forKey:$", @"NSBackgroundColor")  
  
  NSString = CocoaMessage(0, 0, "NSString stringWithString:$", @Text)
  CocoaMessage(@Size, NSString, "sizeWithAttributes:", Attributes)
  
  Point\x = x : Point\y = OutputHeight()-Size\height-y
  CocoaMessage(0, NSString, "drawAtPoint:@", @Point, "withAttributes:", Attributes)
EndProcedure

Procedure ClipOutput_(x, y, width, height)
  Protected Rect.NSRect
  Rect\origin\x = x 
  Rect\origin\y = OutputHeight()-height-y
  Rect\size\width = width 
  Rect\size\height = height
  CocoaMessage(0, CocoaMessage(0, 0, "NSBezierPath bezierPathWithRect:@", @Rect), "setClip")
EndProcedure

Macro PB(Function)
  Function
EndMacro

Macro ClipOutput(x, y, width, height)
  PB(ClipOutput)(x, y, width, height)
  ClipOutput_(x, y, width, height)
EndMacro

Macro DrawRotatedText(x, y, Text, Angle, FrontColor=$ffffff, BackColor=0)
  DrawRotatedText_(x, y, Text, Angle, FrontColor, BackColor)
EndMacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; example
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Procedure draw_gadget(x, y, w, h)
  Protected i, iy
  ClipOutput(x, y, w, h)
  
  ; item of the gadget
  For i=0 To 10
    ix = i*16
    
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(x+ix,y,16, h)
    
    ; text of the item
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawRotatedText(x-20+ix, y, "clip output of the line "+Str(i), 270, 0)
  Next
  
  ; frame gadget
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(x,y, w,h, $FFFF00)
EndProcedure


OpenWindow(0, 0, 0, 300, 300, "sample demonstration fixes clip output", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

CreateImage(0, 300, 300, 24, $c0c0c0)
StartDrawing(ImageOutput(0))


; 1 - gadget
draw_gadget(50, 30, 80, 100)

; 2 - gadget
draw_gadget(150, 90, 80, 100)

; 3 - gadget
draw_gadget(50, 180, 80, 100)


StopDrawing() 
ImageGadget(0, 0, 0, 200, 200, ImageID(0))      

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: COCOA quests?

Post by wilbert »

mestnyi wrote:Now some help is needed in clipping text and boxing. :)
I think it should be something like this

Code: Select all

Procedure DrawRotatedText_(x.CGFloat, y.CGFloat, Text.s, Angle.CGFloat, FrontColor=$ffffff, BackColor=0)
  Protected.CGFloat r,g,b,a
  Protected.i Transform, NSString, Attributes, Color
  Protected Size.NSSize, ZeroPoint.NSPoint
    
  CocoaMessage(@Attributes, 0, "NSMutableDictionary dictionaryWithCapacity:", 2)
  
  r = Red(FrontColor)/255 : g = Green(FrontColor)/255 : b = Blue(FrontColor)/255 : a = 1
  Color = CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@", @r, "green:@", @g, "blue:@", @b, "alpha:@", @a)
  CocoaMessage(0, Attributes, "setValue:", Color, "forKey:$", @"NSColor")
  
  r = Red(BackColor)/255 : g = Green(BackColor)/255 : b = Blue(BackColor)/255 : a = 0
  Color = CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@", @r, "green:@", @g, "blue:@", @b, "alpha:@", @a)
  CocoaMessage(0, Attributes, "setValue:", Color, "forKey:$", @"NSBackgroundColor")  
  
  NSString = CocoaMessage(0, 0, "NSString stringWithString:$", @Text)
  CocoaMessage(@Size, NSString, "sizeWithAttributes:", Attributes)
  
  CocoaMessage(0, 0, "NSGraphicsContext saveGraphicsState")
  
  y = OutputHeight()-y
  Transform = CocoaMessage(0, 0, "NSAffineTransform transform")
  CocoaMessage(0, Transform, "translateXBy:@", @x, "yBy:@", @y)
  CocoaMessage(0, Transform, "rotateByDegrees:@", @Angle)
  x = 0 : y = -Size\height
  CocoaMessage(0, Transform, "translateXBy:@", @x, "yBy:@", @y)
  CocoaMessage(0, Transform, "concat")
  CocoaMessage(0, NSString, "drawAtPoint:@", @ZeroPoint, "withAttributes:", Attributes)
  
  CocoaMessage(0, 0,  "NSGraphicsContext restoreGraphicsState")
    
EndProcedure

Procedure ClipOutput_(x, y, width, height)
  Protected Rect.NSRect
  Rect\origin\x = x 
  Rect\origin\y = OutputHeight()-height-y
  Rect\size\width = width 
  Rect\size\height = height
  CocoaMessage(0, CocoaMessage(0, 0, "NSBezierPath bezierPathWithRect:@", @Rect), "setClip")
EndProcedure

Macro PB(Function)
  Function
EndMacro

Macro ClipOutput(x, y, width, height)
  PB(ClipOutput)(x, y, width, height)
  ClipOutput_(x, y, width, height)
EndMacro

Macro DrawRotatedText(x, y, Text, Angle, FrontColor=$ffffff, BackColor=0)
 DrawRotatedText_(x, y, Text, Angle, FrontColor, BackColor)
EndMacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; example
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Procedure draw_gadget(x, y, w, h)
  Protected i, ix, iy
  ClipOutput(x, y, w, h)
  
  ; item of the gadget
  For i=0 To 10
    ix = i*16
    
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(x+ix,y,16, h)
    
    ; text of the item
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawRotatedText(x+16+ix, y, "clip line "+Str(i)+" rotated text", 270, 0)
  Next
  
  ; frame gadget
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(x,y, w,h, $FFFF00)
EndProcedure


OpenWindow(0, 0, 0, 300, 300, "sample demonstration fixes clip output", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

CreateImage(0, 300, 300, 24, $c0c0c0)
StartDrawing(ImageOutput(0))


; 1 - gadget
draw_gadget(50, 30, 80, 100)

; 2 - gadget
draw_gadget(150, 90, 80, 100)

; 3 - gadget
draw_gadget(50, 180, 80, 100)


StopDrawing() 
ImageGadget(0, 0, 0, 200, 200, ImageID(0))      

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Windows (x64)
Raspberry Pi OS (Arm64)
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

wilbert wrote:
mestnyi wrote:Now some help is needed in clipping text and boxing. :)
I think it should be something like this
and why is it so sad works very well thanks again. :)
If Fred would also fix it, it would be great.
May it be good for you.
The only thing to remove the cut-off borders is this way or should it be done differently?

Code: Select all

Macro UnclipOutput()
      PB(UnclipOutput)()
      ClipOutput_(0, 0, OutputWidth(), OutputHeight())
    EndMacro
    
    
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: COCOA quests?

Post by wilbert »

mestnyi wrote:The only thing to remove the cut-off borders is this way or should it be done differently?
I think that should work fine.

Another way is to use
"NSGraphicsContext saveGraphicsState"
before you set a clipping region and use
"NSGraphicsContext restoreGraphicsState"
to restore the previous graphics state.
It's similar to what I did in the DrawRotatedText_ procedure.
Windows (x64)
Raspberry Pi OS (Arm64)
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: COCOA quests?

Post by mestnyi »

Hello to all
Why does DrawingFont(FontID(0)) not work?
nobody knows?

Thanks!

In the poppy, “Drawingfront ()” slows down drawing a lot, so I don’t want to use it, but without it the height and width of the text will not be applied correctly after changing the font.
So here's how to get the height using text or font

Code: Select all

Global DrawingFont

Procedure DrawRotatedText_(x.CGFloat, y.CGFloat, Text.s, Angle.CGFloat, FrontColor=$ffffff, BackColor=0)
  Protected.CGFloat r,g,b,a
  Protected.i Transform, NSString, Attributes, Color
  Protected Size.NSSize, ZeroPoint.NSPoint
   
  CocoaMessage(@Attributes, 0, "NSMutableDictionary dictionaryWithCapacity:", 2)
  
  If DrawingFont
    CocoaMessage(0, Attributes, "setValue:", DrawingFont, "forKey:$", @"NSFont")
  EndIf
  
  r = Red(FrontColor)/255 : g = Green(FrontColor)/255 : b = Blue(FrontColor)/255 : a = 1
  Color = CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@", @r, "green:@", @g, "blue:@", @b, "alpha:@", @a)
  CocoaMessage(0, Attributes, "setValue:", Color, "forKey:$", @"NSColor")
 
  r = Red(BackColor)/255 : g = Green(BackColor)/255 : b = Blue(BackColor)/255 : a = 0
  Color = CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@", @r, "green:@", @g, "blue:@", @b, "alpha:@", @a)
  CocoaMessage(0, Attributes, "setValue:", Color, "forKey:$", @"NSBackgroundColor")
 
  NSString = CocoaMessage(0, 0, "NSString stringWithString:$", @Text)
  CocoaMessage(@Size, NSString, "sizeWithAttributes:", Attributes)
 
  CocoaMessage(0, 0, "NSGraphicsContext saveGraphicsState")
 
  y = OutputHeight()-y
  Transform = CocoaMessage(0, 0, "NSAffineTransform transform")
  CocoaMessage(0, Transform, "translateXBy:@", @x, "yBy:@", @y)
  CocoaMessage(0, Transform, "rotateByDegrees:@", @Angle)
  x = 0 : y = -Size\height
  CocoaMessage(0, Transform, "translateXBy:@", @x, "yBy:@", @y)
  CocoaMessage(0, Transform, "concat")
  CocoaMessage(0, NSString, "drawAtPoint:@", @ZeroPoint, "withAttributes:", Attributes)
 
  CocoaMessage(0, 0,  "NSGraphicsContext restoreGraphicsState")
   
EndProcedure

Procedure ClipOutput_(x, y, width, height)
  Protected Rect.NSRect
  Rect\origin\x = x
  Rect\origin\y = OutputHeight()-height-y
  Rect\size\width = width
  Rect\size\height = height
  CocoaMessage(0, CocoaMessage(0, 0, "NSBezierPath bezierPathWithRect:@", @Rect), "setClip")
EndProcedure

Macro PB(Function)
  Function
EndMacro

Macro ClipOutput(x, y, width, height)
  PB(ClipOutput)(x, y, width, height)
  ClipOutput_(x, y, width, height)
EndMacro

Macro DrawRotatedText(x, y, Text, Angle, FrontColor=$ffffff, BackColor=0)
 DrawRotatedText_(x, y, Text, Angle, FrontColor, BackColor)
EndMacro

Macro DrawingFont(FontID)
  DrawingFont = FontID
  ; PB(DrawingFont)(FontID)
EndMacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; example
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LoadFont(0, "arial", 15)
LoadFont(1, "arial", 10)

Procedure draw_gadget(x, y, w, h)
  Protected i, ix, iy
  ClipOutput(x, y, w, h)
 
  ; item of the gadget
  For i=0 To 10
    ix = i*24
   
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(x,y+ix, h,24)
   
    ; text of the item
    If i=2
      DrawingFont(FontID(0))
    Else
      DrawingFont(FontID(1))
    EndIf
    
    Debug TextHeight("a")
    
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawRotatedText(x, y+ix+(24-TextHeight("a"))/2, "clip line "+Str(i)+" rotated text", 0, 0)
  Next
 
  ; frame gadget
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(x,y, w,h, $FFFF00)
EndProcedure


OpenWindow(0, 0, 0, 300, 300, "sample demonstration fixes clip output", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

CreateImage(0, 300, 300, 24, $c0c0c0)
StartDrawing(ImageOutput(0))


; 1 - gadget
draw_gadget(50, 30, 80, 100)

; 2 - gadget
draw_gadget(150, 90, 80, 100)

; 3 - gadget
draw_gadget(50, 180, 80, 100)


StopDrawing()
ImageGadget(0, 0, 0, 200, 200, ImageID(0))     

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Last edited by mestnyi on Sat Sep 07, 2019 11:38 am, edited 1 time in total.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: COCOA quests?

Post by wilbert »

mestnyi wrote:Why does DrawingFont(FontID(0)) not work?
It does not work because the drawing of the text is done with CocoaMessage and not the built in PB procedures.
Inside your DrawRotatedText_ procedure you can add a font attribute like

Code: Select all

  FontSize.CGFloat = 24.0
  Font = CocoaMessage(0, 0, "NSFont fontWithName:$", @"Arial", "size:@", @FontSize)
  CocoaMessage(0, Attributes, "setValue:", Font, "forKey:$", @"NSFont")
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply