[PB Cocoa] Methods, Tips & Tricks

Mac OSX specific forum
User avatar
Shardik
Addict
Addict
Posts: 1984
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: [PB Cocoa] Methods, Tips & Tricks

Post by Shardik »

Detect left click into ListIconGadget, display row and column of the clicked cell in StatusBar and display a focus ring around the clicked cell (successfully tested on Snow Leopard, Lion, Mountain Lion and Mavericks; on Mavericks no focus ring around the border of the ListIconGadget will be displayed; how to disable the focus ring for Snow Leopard up to Mountain Lion I have already demonstrated here):

Image

Code: Select all

EnableExplicit

#NSTableViewSelectionHighlightStyleNone = -1

Define CursorLocation.NSPoint
Define SelectedColumn.I
Define SelectedRow.I

OpenWindow(0, 200, 100, 430, 119, "Display focus ring around selected cell")
CreateStatusBar(0, WindowID(0))
AddStatusBarField(#PB_Ignore)
ListIconGadget(0, 10, 10, WindowWidth(0) - 20,
  WindowHeight(0) - 20 - StatusBarHeight(0), "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
  #PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")
CocoaMessage(0, GadgetID(0),
  "setSelectionHighlightStyle:", #NSTableViewSelectionHighlightStyleNone)
CocoaMessage(0, GadgetID(0), "setBackgroundColor:", CocoaMessage(0, 0,
  "NSColor clearColor"))

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0 And EventType() = #PB_EventType_LeftClick
        SelectedRow = GetGadgetState(0)
        CursorLocation\x = WindowMouseX(0)
        CursorLocation\y = WindowHeight(0) - WindowMouseY(0)
        CocoaMessage(@CursorLocation, GadgetID(0),
          "convertPoint:@", @CursorLocation, "fromView:", 0)
        SelectedColumn = CocoaMessage(0, GadgetID(0),
          "columnAtPoint:@", @CursorLocation)

        If SelectedColumn > -1
          CocoaMessage(0, GadgetID(0), "setFocusedColumn:", SelectedColumn)
          StatusBarText(0, 0, "Selected cell: " + Str(SelectedRow) + "," +
            Str(SelectedColumn), #PB_StatusBar_Center)
        EndIf
      EndIf
  EndSelect
ForEver
Problems on Yosemite: Unfortunately this solution doesn't work on Yosemite. Wilbert sent me a PM (thank you, Wilbert!) describing the problems on Yosemite:
Wilbert wrote:At first it shows a focus ring around the entire gadget when you click a cell. When I click another application and then back to the copied one it shows a focus ring around the last clicked cell but there's no realtime update when I click another cell. The focus ring only seems to update if the application regains focus.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: [PB Cocoa] Methods, Tips & Tricks

Post by wilbert »

Show a list of processes with time launched

Code: Select all

; *** Import some procedures ***

ImportC ""
  proc_listallpids(*buffer, buffersize)
  proc_pidpath(pid, *buffer, buffersize)
  sysctl(*name, namelen, *oldp, *oldlenp, *newp, newlen)
EndImport


; *** Init a few things ***

diffGMT = CocoaMessage(0, CocoaMessage(0, 0, "NSTimeZone systemTimeZone"), "secondsFromGMT")

Dim mib.l(3)
mib(0) = 1  ; #CTL_KERN 
mib(1) = 14 ; #KERN_PROC
mib(2) = 1  ; #KERN_PROC_PID

bufSize = 1024
Dim buffer.a(bufSize)


; *** Get a list of pid values ***

cnt = proc_listallpids(#Null, 0)
Dim pid.l(cnt - 1)
cnt = proc_listallpids(@pid(), cnt << 2) 


; *** Present pid with some process information ***

OpenWindow(0, 100, 100, 740, 400, "Running applications", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListIconGadget(0, 10, 10, 720, 380, "PID", 50, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_CheckBoxes)
AddGadgetColumn(0, 1, "Launched", 80)
AddGadgetColumn(0, 2, "Name", 400)
AddGadgetColumn(0, 3, "Path", 1800)

i = 0
While i < cnt
  
  ; get launched date
  mib(3) = pid(i)
  If sysctl(@mib(), 4, @buffer(), @bufSize, #Null, 0) = 0
    Launched.s = FormatDate("%hh:%ii:%ss", PeekL(@buffer()) + diffGMT)
  Else
    Launched.s = ""
  EndIf
  
  ; get path and extract process name
  FullPath.s = PeekS(@buffer(), proc_pidpath(pid(i), @buffer(), 1024), #PB_Ascii)
  Name.s = GetFilePart(FullPath)
  
  AddGadgetItem(0, i, Str(pid(i)) + #LF$ + Launched + #LF$ + Name + #LF$ + FullPath)
  
  ; present an icon and check 'isActive' if possible
  RunningApp = CocoaMessage(0, 0, "NSRunningApplication runningApplicationWithProcessIdentifier:", pid(i))
  If RunningApp
    SetGadgetItemImage(0, i, CocoaMessage(0, RunningApp, "icon"))
    If CocoaMessage(0, RunningApp, "isActive")
      SetGadgetItemState(0, i, #PB_ListIcon_Checked)
    EndIf
  EndIf
  
  i + 1
Wend

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

Re: [PB Cocoa] Methods, Tips & Tricks

Post by wilbert »

With PB 5.40 some imports, constants and structures are added.

Here's a small example

Code: Select all

; Requirements to run this source : PB 5.40+
; Requirements to use GameplayKit framework : PB x64, OSX 10.11+


; Show foundation version number using dlsym

; #NSFoundationVersionNumber10_0  = 397.40
; #NSFoundationVersionNumber10_1  = 425.00
; #NSFoundationVersionNumber10_2  = 462.00
; #NSFoundationVersionNumber10_3  = 500.00
; #NSFoundationVersionNumber10_4  = 567.00
; #NSFoundationVersionNumber10_5  = 677.00
; #NSFoundationVersionNumber10_6  = 751.00
; #NSFoundationVersionNumber10_7  = 833.10
; #NSFoundationVersionNumber10_8  = 945.00
; #NSFoundationVersionNumber10_9  = 1056.00
; #NSFoundationVersionNumber10_10 = 1151.16
; #NSFoundationVersionNumber10_11 = 1252.00
; #NSFoundationVersionNumber10_11_1 = 1255.10
; #NSFoundationVersionNumber10_11_2 = 1256.10

*FoundationVersion.Double = dlsym_(#RTLD_DEFAULT, "NSFoundationVersionNumber")
Debug "Foundation version : " + StrD(*FoundationVersion\d, 2)
Debug "-------------------------------------------"


; Use sel_registerName and sel_getName without ImportC statement
Sel = sel_registerName_("nextInt")
Debug PeekS(sel_getName_(Sel), -1, #PB_UTF8)


; Load GameplayKit framework if possible

If Not dlopen_("/Library/Frameworks/GameplayKit.framework/GameplayKit", #RTLD_LAZY)
  MessageRequester("Error", PeekS(dlerror_(), -1, #PB_UTF8))
Else

  ; Show twenty ARC4 random values between 1 and 5
  
  RandomDistribution = CocoaMessage(0, 0, "GKRandomDistribution distributionWithLowestValue:", 1, "highestValue:", 5)
  For i = 1 To 20
    Debug CocoaMessage(0, RandomDistribution, "nextInt")
  Next
  
EndIf
Windows (x64)
Raspberry Pi OS (Arm64)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: [PB Cocoa] Methods, Tips & Tricks

Post by wilbert »

I updated my LoadImageEx and CatchImageEx procedures from long ago
http://www.purebasic.fr/english/viewtop ... 73#p392073
They should be able to better handle some file types now with an alpha channel.
PureBasic uses unpremultiplied images while OSX usually doesn't so I added an unpremultiply.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Shardik
Addict
Addict
Posts: 1984
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: [PB Cocoa] Methods, Tips & Tricks

Post by Shardik »

Mindphazer wrote:I'm -again- asking for help.
Does anyone know how to set color to a specify cell (or line) in a ListIconGadget ?
The SetGadgetItemColor() function is not implemented on OSX, do you think it can be achieved via Cocoa ?

Thanks a lot
Since I recently needed to colorize single cells in a ListIconGadget, I have programmed a workaround for the SetGadgetItemColor() function which is still not implemented for MacOS X. The example below is cross-platform: only on MacOS X a macro will be defined which calls the procedure SetGadgetItemColorEx(), so that it's possible now to use SetGadgetItemColor() also on MacOS X... :wink:

My workaround utilizes the NSListView delegate method tableView:willDisplayCell:forTableColumn:row: to establish a callback which is called for every cell of a ListIconGadget before the drawing of a cell begins. I use the quad array ListIconCellColor.Q(Row.I, Column.I) to store any changed colors: the left Long part of a quad color value contains the front color and the right Long part contains the back color.

I have tested my code example successfully on MacOS X 10.6.8 "Snow Leopard" and MacOS X 10.11.4 "El Capitan" with PB 5.42 x86 and x64 and in both ASCII and Unicode mode and on Windows 7 x64.

Code: Select all

EnableExplicit

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  ImportC ""
    class_addMethod(Class.I, Selector.I, *Callback, Types.P-ASCII)
    sel_registerName(MethodName.P-ASCII)
  EndImport
  
  Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
    "NSApplication sharedApplication"), "delegate")
  Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
  Define Selector.I = sel_registerName("tableView:willDisplayCell:forTableColumn:row:")
  
  Dim ListIconCellColor.Q(0, 0)
  
  ProcedureC CellDisplayCallback(Object.I, Selector.I, TableView.I, Cell.I,
    *Column, Row.I)
    Shared ListIconCellColor.Q()
    
    Protected Alpha.CGFloat
    Protected BackColor.L
    Protected Blue.CGFloat
    Protected CellColor.Q
    Protected Column.I
    Protected FrontColor.L
    Protected Green.CGFloat
    Protected Red.CGFloat
    
    Column = Val(PeekS(CocoaMessage(0, CocoaMessage(0, *Column, "identifier"),
      "UTF8String"), -1, #PB_UTF8))
    CellColor = ListIconCellColor(Row, Column)
    
    If CellColor = 0
      CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
      CocoaMessage(0, Cell, 
        "setTextColor:", CocoaMessage(0, 0, "NSColor blackColor"))
    Else
      BackColor = CellColor & $FFFFFF
      
      If BackColor = 0
        CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
      Else
        CocoaMessage(0, Cell, "setDrawsBackground:", #YES)
        Alpha = 1
        Red = Red(BackColor) / 255
        Green = Green(BackColor) / 255
        Blue = Blue(BackColor) / 255
        CocoaMessage(0, Cell, "setBackgroundColor:", CocoaMessage(0, 0,
          "NSColor colorWithDeviceRed:@", @Red,
          "green:@", @Green,
          "blue:@", @Blue,
          "alpha:@", @Alpha))
      EndIf
      
      FrontColor = (CellColor >> 32) & $FFFFFF
      
      If FrontColor = 0
        CocoaMessage(0, Cell, 
          "setTextColor:", CocoaMessage(0, 0, "NSColor blackColor"))
      Else
        Alpha = 1
        Red = Red(FrontColor) / 255
        Green = Green(FrontColor) / 255
        Blue = Blue(FrontColor) / 255
        CocoaMessage(0, Cell, "setTextColor:", CocoaMessage(0, 0,
          "NSColor colorWithDeviceRed:@", @Red,
          "green:@", @Green,
          "blue:@", @Blue,
          "alpha:@", @Alpha))
      EndIf
    EndIf
  EndProcedure
  
  Procedure SetGadgetItemColorEx(GadgetID.I, Row.I, ColorType.I, Color.I,
    Column.I)
    Shared ListIconCellColor.Q()
 
    Protected CellColor.Q
    Protected ColumnCount.I
    Protected RowCount.I

    If ArraySize(ListIconCellColor()) = 0
      ColumnCount = CocoaMessage(0, GadgetID(GadgetID), "numberOfColumns")
      RowCount = CocoaMessage(0, GadgetID(GadgetID), "numberOfRows")
      Dim ListIconCellColor(RowCount - 1, ColumnCount - 1)
    EndIf

    CellColor = ListIconCellColor(Row, Column)

    Select ColorType
      Case #PB_Gadget_BackColor
        CellColor ! (Color & $FFFFFF)
      Case #PB_Gadget_FrontColor
        CellColor ! ((Color & $FFFFFF) << 32)
    EndSelect

    ListIconCellColor(Row, Column) = CellColor
  EndProcedure
CompilerEndIf

OpenWindow(0, 200, 100, 430, 101,
  "Change color of text and background in single cells")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20, "Name",
  100, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address",
  GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  Macro SetGadgetItemColor(GadgetID, Row, ColorType, Color, Column)
    SetGadgetItemColorEx(GadgetID, Row, ColorType, Color, Column)
  EndMacro

  class_addMethod(DelegateClass, Selector, @CellDisplayCallback(), "v@:@@@@")
  CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)
CompilerEndIf

; ----- Set background color of cell 2,0 to yellow
SetGadgetItemColor(0, 2, #PB_Gadget_BackColor, $FFFF, 0)

; ----- Set background color of cell 1,1 to X11 color "Aquamarine"
SetGadgetItemColor(0, 1, #PB_Gadget_BackColor, $D4FF7F, 1)

; ----- Set text color of cell 0,0 to blue
SetGadgetItemColor(0, 0, #PB_Gadget_FrontColor, $FF0000, 0)

; ----- Set text color of cell 1,1 to red
SetGadgetItemColor(0, 1, #PB_Gadget_FrontColor, $FF, 1)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
The code above only supports one single ListIconGadget. If you need to support multiple ListIconGadgets please take a look into this extended example.
Last edited by Shardik on Fri Sep 28, 2018 8:36 pm, edited 1 time in total.
Mindphazer
Enthusiast
Enthusiast
Posts: 340
Joined: Mon Sep 10, 2012 10:41 am
Location: Savoie

Re: [PB Cocoa] Methods, Tips & Tricks

Post by Mindphazer »

Works well
Thank you Shardik, you made my day !
MacBook Pro 14" M1 Pro - 16 Gb - MacOS 14 - Iphone 15 Pro Max - iPad at home
...and unfortunately... Windows at work...
User avatar
Shardik
Addict
Addict
Posts: 1984
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: [PB Cocoa] Methods, Tips & Tricks

Post by Shardik »

I have taken my example from above for the ListIconGadget and removed/changed some parts in order to implement SetGadgetItemColor() also for the ListViewGadget. Now it's possible to colorize the text color and background color of single rows in a ListViewGadget. This example is not cross-platform anymore because this feature is not implemented in the PB versions for Linux and Windows!

Code: Select all

EnableExplicit

ImportC ""
  class_addMethod(Class.I, Selector.I, *Callback, Types.P-ASCII)
  sel_registerName(MethodName.P-ASCII)
EndImport

Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Define i.I
Define Selector.I = sel_registerName("tableView:willDisplayCell:forTableColumn:row:")

Dim ListIconCellColor.Q(0)

ProcedureC CellDisplayCallback(Object.I, Selector.I, TableView.I, Cell.I,
  *Column, Row.I)
  Shared ListIconCellColor.Q()

  Protected Alpha.CGFloat
  Protected BackColor.L
  Protected Blue.CGFloat
  Protected CellColor.Q
  Protected FrontColor.L
  Protected Green.CGFloat
  Protected Red.CGFloat

  CellColor = ListIconCellColor(Row)

  If CellColor = 0
    CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
    CocoaMessage(0, Cell, 
      "setTextColor:", CocoaMessage(0, 0, "NSColor blackColor"))
  Else
    BackColor = CellColor & $FFFFFF

    If BackColor = 0
      CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
    Else
      CocoaMessage(0, Cell, "setDrawsBackground:", #YES)
      Alpha = 1
      Red = Red(BackColor) / 255
      Green = Green(BackColor) / 255
      Blue = Blue(BackColor) / 255
      CocoaMessage(0, Cell, "setBackgroundColor:", CocoaMessage(0, 0,
        "NSColor colorWithDeviceRed:@", @Red,
        "green:@", @Green,
        "blue:@", @Blue,
        "alpha:@", @Alpha))
    EndIf

    FrontColor = (CellColor >> 32) & $FFFFFF

    If FrontColor = 0
      CocoaMessage(0, Cell, 
        "setTextColor:", CocoaMessage(0, 0, "NSColor blackColor"))
    Else
      Alpha = 1
      Red = Red(FrontColor) / 255
      Green = Green(FrontColor) / 255
      Blue = Blue(FrontColor) / 255
      CocoaMessage(0, Cell, "setTextColor:", CocoaMessage(0, 0,
        "NSColor colorWithDeviceRed:@", @Red,
        "green:@", @Green,
        "blue:@", @Blue,
        "alpha:@", @Alpha))
    EndIf
  EndIf
EndProcedure

Procedure SetGadgetItemColorEx(GadgetID.I, Row.I, ColorType.I, Color.I)
  Shared ListIconCellColor.Q()

  Protected CellColor.Q
  Protected RowCount.I

  If ArraySize(ListIconCellColor()) = 0
    RowCount = CocoaMessage(0, GadgetID(GadgetID), "numberOfRows")
    Dim ListIconCellColor(RowCount - 1)
  EndIf

  CellColor = ListIconCellColor(Row)

  Select ColorType
    Case #PB_Gadget_BackColor
      CellColor ! (Color & $FFFFFF)
    Case #PB_Gadget_FrontColor
      CellColor ! ((Color & $FFFFFF) << 32)
  EndSelect

  ListIconCellColor(Row) = CellColor
EndProcedure

Macro SetGadgetItemColor(GadgetID, Row, ColorType, Color)
  SetGadgetItemColorEx(GadgetID, Row, ColorType, Color)
EndMacro

OpenWindow(0, 200, 100, 430, 150,
  "Change color of text and background in single rows")
ListViewGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20)

For i = 1 To 10
  AddGadgetItem(0, -1, "Line " + Str(i))
Next i

class_addMethod(DelegateClass, Selector, @CellDisplayCallback(), "v@:@@@@")
CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)

; ----- Set background color of line 1 to yellow
SetGadgetItemColor(0, 0, #PB_Gadget_BackColor, $FFFF)

; ----- Set background color of line 5 to X11 color "Aquamarine"
SetGadgetItemColor(0, 4, #PB_Gadget_BackColor, $D4FF7F)

; ----- Set text color of line 3 to blue
SetGadgetItemColor(0, 2, #PB_Gadget_FrontColor, $FF0000)

; ----- Set text color of line 5 to red
SetGadgetItemColor(0, 4, #PB_Gadget_FrontColor, $FF)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
The code above only supports one single ListViewGadget. If you need to support multiple ListViewGadgets please take a look into this extended example.

I had to modify this example to also work with the new PB 6.00 x64 Beta 7 because Fred modified the ListViewGadget and ListIconGadget internally:
Fred wrote:We now use a specialized PBIconTextCell for ListIconGadget and ListViewGadget (in the :dataCellForTableColumn callback). It allows us to properly display an icon in the same column as text for ListIconGadget() instead of having a separate column as before (which was not good looking).
You find the modified example (working in both PB 6.00 x64 Beta 7 and pre Beta 7) here.
Last edited by Shardik on Thu May 12, 2022 7:03 pm, edited 2 times in total.
User avatar
deseven
Enthusiast
Enthusiast
Posts: 362
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: [PB Cocoa] Methods, Tips & Tricks

Post by deseven »

Setting column title via Cocoa (that way you can set title for special columns such as image or checkbox) for ListIconGadget() and anything else that uses NSTableView.

Code: Select all

Procedure ListIconGadgetColumnTitle(gadget.i,index.i,title.s)
  Protected column = CocoaMessage(0,CocoaMessage(0,GadgetID(gadget),"tableColumns"),"objectAtIndex:",index)
  If column
    CocoaMessage(0,column,"setTitle:$",@title)
  EndIf
EndProcedure
EDIT: OS X 10.10+
Last edited by deseven on Thu Jul 21, 2016 9:52 pm, edited 2 times in total.
User avatar
Shardik
Addict
Addict
Posts: 1984
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: [PB Cocoa] Methods, Tips & Tricks

Post by Shardik »

deseven,

unfortunately your procedure ListIconGadgetColumnTitle() doesn't work on MacOS 10.6.8 (Snow Leopard) and MacOS 10.9.5 (Mavericks). It stops with the error message
PB Debugger wrote:[ERROR] Object does not respond to method "setTitle:".
Perhaps this is caused by Apple's API changes in the Cocoa framework of more recent MacOS versions from cell based to view based table views.

The following example works fine on Snow Leopard and Mavericks. Unfortunately my external hard disk with MacOS versions from Lion to El Capitan is damaged, so that I am currently unable to test the following example also on Yosemite or El Capitan:

Code: Select all

Procedure SetColumnTitle(ListIconID.I, ColumnIndex.I, Title.S)
  Protected Column = CocoaMessage(0, CocoaMessage(0, GadgetID(ListIconID),
    "tableColumns"), "objectAtIndex:", ColumnIndex)

  If Column
    CocoaMessage(0, CocoaMessage(0, Column, "headerCell"),
      "setStringValue:$", @Title.S)
  EndIf
EndProcedure

OpenWindow(0, 200, 100, 450, 110, "ListIcon Example")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
  "Name", 110)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
  #PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

SetColumnTitle(0, 0, "Title changed!")

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
For only changing the title of a column header you even don't need Cocoa functions at all. You only need the following native PB function: :wink:

Code: Select all

SetGadgetItemText(0, -1, "Title Changed!", 0)
User avatar
deseven
Enthusiast
Enthusiast
Posts: 362
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: [PB Cocoa] Methods, Tips & Tricks

Post by deseven »

Shardik wrote:For only changing the title of a column header you even don't need Cocoa functions at all.
Hello Shardik!

Unfortunately you misread my post (or maybe it's my fault that i can't explain why someone should need it), here is the example:

Code: Select all

OpenWindow(0,#PB_Ignore,#PB_Ignore,400,300,"ListIcon Example",#PB_Window_ScreenCentered)
ListIconGadget(0,10,10,380,280,"Column1",110,#PB_ListIcon_CheckBoxes)
AddGadgetColumn(0,1,"Column2",100)
AddGadgetItem(0,-1,"Text1" + Chr(10) + "Text2")

; you can't change the title of the special column with checkboxes (or icons)
; column #0 is actually column #1, etc
SetGadgetItemText(0,-1,"Title Changed!",0)

; however you can still do it with Cocoa
column = CocoaMessage(0,CocoaMessage(0,GadgetID(0),"tableColumns"),"objectAtIndex:",0)
CocoaMessage(0,column,"setTitle:$",@"Title Changed!")

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
It can lead to something like that (using special symbols as a column title):
Image
User avatar
Shardik
Addict
Addict
Posts: 1984
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: [PB Cocoa] Methods, Tips & Tricks

Post by Shardik »

Hello deseven,

yes, I misunderstood your description. You were talking about "Setting column title" and with "column title" I always associate the title of a column header. I think "cell content" or "column content" would have been more appropriate but I am not a native speaker of English, so may be I am wrong... :wink:

But thank you for your image and your new example code which makes all pretty clear.

Nevertheless, in MacOS 10.6.8 (Snow Leopard) and MacOS 10.9.5 (Mavericks) your new code example still throws the above mentioned error message (perhaps because of the already mentioned API changes in MacOS beginning with Yosemite from cell based to view based table views):
PB debugger wrote:[ERROR] Zeile: 12
[ERROR] Object does not respond to method "setTitle:".
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: [PB Cocoa] Methods, Tips & Tricks

Post by wilbert »

I'm a bit confused about this setting of column title.
As far as I can tell, the code posted by Shardik (headerCell / setStringValue) does exactly the same as setTitle :?
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
deseven
Enthusiast
Enthusiast
Posts: 362
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: [PB Cocoa] Methods, Tips & Tricks

Post by deseven »

Yes, "setStringValue" method should work on 10.6+, but "setTitle" works only on 10.10 or higher.
Shardik wrote:You were talking about "Setting column title" and with "column title" I always associate the title of a column header. I think "cell content" or "column content" would have been more appropriate
I don't know, but this api method called "setTitle" and it works with object called "NSTableColumn". Based on that i think that "column title" sounds ok.
Of course i am not a native english speaker too.
wilbert wrote:As far as I can tell, the code posted by Shardik (headerCell / setStringValue) does exactly the same as setTitle
The only difference is api changes, probably the correct way is to check the OS version and use the appropriate method based on that info.

Code: Select all

Procedure ListIconGadgetColumnTitle(gadget.i,index.i,title.s)
  Protected column = CocoaMessage(0,CocoaMessage(0,GadgetID(gadget),"tableColumns"),"objectAtIndex:",index)
  If column
    If OSVersion() >= #PB_OS_MacOSX_10_10
      CocoaMessage(0,column,"setTitle:$",@title)
    Else
      CocoaMessage(0,CocoaMessage(0,column,"headerCell"),"setStringValue:$",@title)
    EndIf
  EndIf
EndProcedure
User avatar
deseven
Enthusiast
Enthusiast
Posts: 362
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: [PB Cocoa] Methods, Tips & Tricks

Post by deseven »

Not the exact method, but a technique which shows how to create statusbar-based applications with the ability to restore a window by running the same .app again (most part of similar apps act like that).

Code: Select all

; in this example we're creating a complete app with status bar icon and the ability to turn it off or on

; if you'll turn off the status bar icon and close the main window
; you'll still be able to access it by running the same .app again

; compile it into .app bundle,
;
; edit the Info.plist like that:
; <key>LSUIElement</key>
;	<true/>
;
; run as a regular app

#NSWindowButtonMinimize = 1
#NSWindowButtonMaximize = 2

EnableExplicit

DataSection
  icon:
  IncludeBinary "icon.png"
EndDataSection

UsePNGImageDecoder()
CatchImage(0,?icon)
CocoaMessage(0,ImageID(0),"setTemplate:",#True)

; due to somehow strange PB behavior in managing windows we will use cocoa methods to hide or show our app
Define app.i = CocoaMessage(0,0,"NSApplication sharedApplication")

OpenWindow(0,#PB_Ignore,#PB_Ignore,170,40,"statusBar",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
StickyWindow(0,#True)
CheckBoxGadget(0,10,10,150,20,"enable status bar icon")
CocoaMessage(0,CocoaMessage(0,WindowID(0),"standardWindowButton:",#NSWindowButtonMinimize),"setHidden:",#YES)
CocoaMessage(0,CocoaMessage(0,WindowID(0),"standardWindowButton:",#NSWindowButtonMaximize),"setHidden:",#YES)

Procedure advancedStatusBar()
  Static statusBar.i,statusItem.i
  Shared app.i
  Protected itemLength.CGFloat = 24
  If GetGadgetState(0) = #PB_Checkbox_Checked
    If Not statusBar
      statusBar = CocoaMessage(0,0,"NSStatusBar systemStatusBar")
    EndIf
    If Not statusItem
      statusItem = CocoaMessage(0,CocoaMessage(0,statusBar,"statusItemWithLength:",itemLength),"retain")
    EndIf
    CreatePopupMenu(0)
    MenuItem(0,"Window")
    MenuBar()
    MenuItem(1,"Quit")
    CocoaMessage(0,statusItem,"setHighlightMode:",#YES)
    CocoaMessage(0,statusItem,"setLength:@",@itemLength)
    CocoaMessage(0,statusItem,"setImage:",ImageID(0))
    CocoaMessage(0,statusItem,"setMenu:",CocoaMessage(0,MenuID(0),"firstObject"))
  Else
    If statusBar And statusItem
      CocoaMessage(0,statusBar,"removeStatusItem:",statusItem)
    EndIf
    statusItem = 0
    If IsMenu(0) : FreeMenu(0) : EndIf
  EndIf
EndProcedure

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      advancedStatusBar()
    Case #PB_Event_Menu
      Select EventMenu()
        Case 0
          CocoaMessage(0,app,"activateIgnoringOtherApps:",#YES)
        Case 1
          Break
      EndSelect
    Case #PB_Event_CloseWindow
      If GetGadgetState(0) = #PB_Checkbox_Unchecked
        MessageRequester("",~"You're closing the main window without active status bar icon.\n\nThe app will still run in background.\n\nYou'll be able to open the main window if you have a valid .app by launching the same .app again.")
      EndIf
      CocoaMessage(0,app,"hide:")
  EndSelect
ForEver
icon.png

Sharing because i spent about 2 days trying to figure out how to do it safe and reliable :)
Tested on OS X 10.8 and 10.11.
User avatar
deseven
Enthusiast
Enthusiast
Posts: 362
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: [PB Cocoa] Methods, Tips & Tricks

Post by deseven »

Detect whether "dark mode" on OS X 10.10 or higher is active:

Code: Select all

Procedure isDarkMode()
  Protected appearance = CocoaMessage(0,CocoaMessage(0,0,"NSUserDefaults standardUserDefaults"),"stringForKey:$",@"AppleInterfaceStyle")
  If appearance
    appearance = CocoaMessage(0,appearance,"UTF8String")
    If PeekS(appearance,-1,#PB_UTF8) = "Dark"
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

If isDarkMode()
  Debug "dark mode enabled"
Else
  Debug "dark mode disabled"
EndIf
Can be useful if you use complex status bar icons which are not "setTemplate" compatible.
Post Reply