NSPopOver Functions

Mac OSX specific forum
mrbungle
Enthusiast
Enthusiast
Posts: 176
Joined: Wed Dec 30, 2020 3:18 am

NSPopOver Functions

Post by mrbungle »

This is a set of functions for NSPopOver functions:

Code: Select all

#NSMaxYEdge = 2 ; 0-3 change the orientation

Global popover = 0
Global vc = 0
Global contentView = 0
Global label = 0

; Create
Procedure.i CreateContentView(width, height)
  Protected rect.NSRect
  rect\origin\x = 0 : rect\origin\y = 0
  rect\size\width = width : rect\size\height = height
  Protected view = CocoaMessage(0, 0, "NSView alloc")
  view = CocoaMessage(0, view, "initWithFrame:@", @rect)
  ProcedureReturn view
EndProcedure

; Create a label
Procedure.i CreateLabel(parentView, x, y, w, h, text.s)
  Protected labelRect.NSRect
  labelRect\origin\x = x : labelRect\origin\y = y
  labelRect\size\width = w : labelRect\size\height = h
  Protected label = CocoaMessage(0, 0, "NSTextField alloc")
  label = CocoaMessage(0, label, "initWithFrame:@", @labelRect)
  CocoaMessage(0, label, "setStringValue:$", @text)
  CocoaMessage(0, label, "setEditable:", #NO)
  CocoaMessage(0, label, "setBordered:", #NO)
  CocoaMessage(0, label, "setDrawsBackground:", #NO)
  CocoaMessage(0, parentView, "addSubview:", label)
  ProcedureReturn label
EndProcedure

; Create effect
Procedure.i CreatePopover(contentView, *out_vc.Integer)
  Protected popover = CocoaMessage(0, 0, "NSPopover alloc")
  popover = CocoaMessage(0, popover, "init")
  Protected vc = CocoaMessage(0, 0, "NSViewController alloc")
  vc = CocoaMessage(0, vc, "init")
  CocoaMessage(0, vc, "setView:", contentView)
  CocoaMessage(0, popover, "setContentViewController:", vc)
  CocoaMessage(0, popover, "setAnimates:", #YES)
  CocoaMessage(0, popover, "setBehavior:", 0)
  If *out_vc
   *out_vc\i = vc
  EndIf
  ProcedureReturn popover
EndProcedure

; Show relative to a PB gadget
Procedure ShowPopover(popover, gadget, preferredEdge = #NSMaxYEdge)
  Protected gadgetID = GadgetID(gadget)
  Protected btnRect.NSRect
  CocoaMessage(@btnRect, gadgetID, "bounds")
  CocoaMessage(0, popover, "showRelativeToRect:@", @btnRect, "ofView:", gadgetID, "preferredEdge:", preferredEdge)
EndProcedure

; Hide/close
Procedure HidePopover(popover, windowID = 0)
  If popover
    If windowID
      CocoaMessage(0, popover, "performClose:", windowID)
    Else
      CocoaMessage(0, popover, "performClose:", 0)
    EndIf
  EndIf
EndProcedure

; Release popover
Procedure ReleasePopover(popover, vc, contentView = 0, label = 0)
  If popover
    CocoaMessage(0, popover, "close")
    CocoaMessage(0, popover, "setContentViewController:", 0)
    CocoaMessage(0, popover, "release")
  EndIf
  If vc
    CocoaMessage(0, vc, "setView:", 0)
    CocoaMessage(0, vc, "release")
  EndIf
  If contentView
    If label
      CocoaMessage(0, label, "removeFromSuperview")
      CocoaMessage(0, label, "release")
    EndIf
    CocoaMessage(0, contentView, "release")
  EndIf
EndProcedure

; Is it currently shown?
Procedure.i IsPopoverShown(popover)
  ProcedureReturn CocoaMessage(0, popover, "isShown")
EndProcedure

If OpenWindow(0, 0, 0, 400, 200, "Demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ButtonGadget(0, 150, 80, 100, 30, "Toggle Popover")

  Repeat
    Define ev = WaitWindowEvent()
    If ev = #PB_Event_Gadget And EventGadget() = 0
      If popover = 0
        contentView = CreateContentView(200, 80)
        label = CreateLabel(contentView, 20, 25, 160, 30, "Pop, Popover Muzik!")
        popover = CreatePopover(contentView, @vc)
      EndIf

      If IsPopoverShown(popover)
        HidePopover(popover, WindowID(0))
      Else
        ShowPopover(popover, 0)
      EndIf
    EndIf
  Until ev = #PB_Event_CloseWindow

  ; Clean up
  ReleasePopover(popover, vc, contentView, label)
EndIf
Wolfram
Enthusiast
Enthusiast
Posts: 608
Joined: Thu May 30, 2013 4:39 pm

Re: NSPopOver Functions

Post by Wolfram »

Nice!

A smal variation with a list...

Code: Select all

#NSMaxYEdge = 2 ; 0-3 change the orientation
#NSFocusRingTypeNone = 1

Global popover = 0
Global vc = 0
Global contentView = 0
Global label = 0
Global NSTableView

; Create
Procedure.i CreateContentView(width, height)
  Protected rect.NSRect
  rect\origin\x = 0 : rect\origin\y = 0
  rect\size\width = width : rect\size\height = height
  Protected view = CocoaMessage(0, 0, "NSView alloc")
  view = CocoaMessage(0, view, "initWithFrame:@", @rect)
  ProcedureReturn view
EndProcedure

; Create Popover Items
Procedure.i CreatePopoverItems(parentView, x, y, w, h, List items.s())
  Protected labelRect.NSRect
  labelRect\origin\x = x : labelRect\origin\y = y
  labelRect\size\width = w : labelRect\size\height = h
  
  NSTableView = ListViewGadget(#PB_Any, x, y, w, h)
  HideGadget(NSTableView, #True)
  
  label = GadgetID(NSTableView)
  CocoaMessage(0, label, "setFocusRingType:", #NSFocusRingTypeNone)
  CocoaMessage(0, label, "removeFromSuperview")
  
  CocoaMessage(0, parentView, "addSubview:", label)
  
  ForEach items()
    AddGadgetItem(NSTableView, -1, items() )
  Next
  
  CocoaMessage(0, label, "setFrame:@", @labelRect)
  ProcedureReturn label
EndProcedure

; Create effect
Procedure.i CreatePopover(contentView, *out_vc.Integer)
  Protected popover = CocoaMessage(0, 0, "NSPopover alloc")
  popover = CocoaMessage(0, popover, "init")
  Protected vc = CocoaMessage(0, 0, "NSViewController alloc")
  vc = CocoaMessage(0, vc, "init")
  CocoaMessage(0, vc, "setView:", contentView)
  CocoaMessage(0, popover, "setContentViewController:", vc)
  CocoaMessage(0, popover, "setAnimates:", #YES)
  CocoaMessage(0, popover, "setBehavior:", 0)
  If *out_vc
   *out_vc\i = vc
  EndIf
  ProcedureReturn popover
EndProcedure

; Show relative to a PB gadget
Procedure ShowPopover(popover, gadget, preferredEdge = #NSMaxYEdge)
  Protected gadgetID = GadgetID(gadget)
  Protected btnRect.NSRect
  CocoaMessage(@btnRect, gadgetID, "bounds")
  CocoaMessage(0, popover, "showRelativeToRect:@", @btnRect, "ofView:", gadgetID, "preferredEdge:", preferredEdge)
EndProcedure

; Hide/close
Procedure HidePopover(popover, windowID = 0)
  If popover
    If windowID
      CocoaMessage(0, popover, "performClose:", windowID)
    Else
      CocoaMessage(0, popover, "performClose:", 0)
    EndIf
  EndIf
EndProcedure

; Release popover
Procedure ReleasePopover(popover, vc, contentView = 0, label = 0)
  If popover
    CocoaMessage(0, popover, "close")
    CocoaMessage(0, popover, "setContentViewController:", 0)
    CocoaMessage(0, popover, "release")
  EndIf
  If vc
    CocoaMessage(0, vc, "setView:", 0)
    CocoaMessage(0, vc, "release")
  EndIf
  If contentView
    If label
      CocoaMessage(0, label, "removeFromSuperview")
      CocoaMessage(0, label, "release")
    EndIf
    CocoaMessage(0, contentView, "release")
  EndIf
EndProcedure

; Is it currently shown?
Procedure.i IsPopoverShown(popover)
  ProcedureReturn CocoaMessage(0, popover, "isShown")
EndProcedure

If OpenWindow(0, 0, 0, 400, 200, "Demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ButtonGadget(0, 150, 80, 100, 30, "Toggle Popover")

  Repeat
    Define ev = WaitWindowEvent()
    
    Select ev 
      Case #PB_Event_Gadget 
        
        Select EventGadget()
          Case 0
            If popover = 0
              NewList myItems.s()
              AddElement( myItems() )
              myItems() = "Hello"
              AddElement( myItems() )
              myItems() = "World"
              contentView = CreateContentView(200, 80)
              label = CreatePopoverItems(contentView, 10, 15, 180, 30, myItems() )
              popover = CreatePopover(contentView, @vc)
            EndIf
            
            If IsPopoverShown(popover)
              HidePopover(popover, WindowID(0))
            Else
              ShowPopover(popover, 0)
            EndIf
            
          Case NSTableView
            Select EventType()
              Case #PB_EventType_Change
                Debug "NSTableView Item " +GetGadgetState(NSTableView)
            EndSelect
        EndSelect
    EndSelect
    
  Until ev = #PB_Event_CloseWindow

  ; Clean up
  ReleasePopover(popover, vc, contentView, label)
EndIf
macOS Catalina 10.15.7
mrbungle
Enthusiast
Enthusiast
Posts: 176
Joined: Wed Dec 30, 2020 3:18 am

Re: NSPopOver Functions

Post by mrbungle »

Nice!
mrbungle
Enthusiast
Enthusiast
Posts: 176
Joined: Wed Dec 30, 2020 3:18 am

Re: NSPopOver Functions

Post by mrbungle »

NOTE: The NSPopOver is basically all Cocoa, so you can't use native PB Gadgets in it
Post Reply