
Is it possible to add "non-standard" items in a toolbar using some sort of CocoaMessage() code? And how?
This is what I mean:

Thanks!!!

Code: Select all
EnableExplicit
#NSToolbarSizeModeRegular = 1
Define ItemArray.I
Define ItemSize.NSSize
Define SearchField.I
Define SearchFieldFrame.NSRect
Define ToolbarItem.I
OpenWindow(0, 270, 100, 260, 50, "ToolBar with search field",
#PB_Window_SystemMenu | #PB_Window_Invisible)
; ----- Define search field
SearchField = CocoaMessage(0, 0, "NSSearchField new")
CocoaMessage(0, SearchField, "sizeToFit")
CocoaMessage(@SearchFieldFrame, SearchField, "frame")
ToolbarItem = CocoaMessage(0, CocoaMessage(0, 0, "NSToolbarItem alloc"),
"initWithItemIdentifier:$", @"SearchToolbarItemIdentifier")
; ----- Create empty dummy image
CreateImage(0, 24, 24)
; ----- Create standard ToolBar
CreateToolBar(0, WindowID(0))
; ----- Change size of ToolBar to larger icons
CocoaMessage(0, ToolBarID(0), "setSizeMode:", #NSToolbarSizeModeRegular)
; ----- Add empty dummy image to ToolBar
ToolBarImageButton(0, ImageID(0))
; ----- Get item object of ToolBar button
ItemArray = CocoaMessage(0, ToolBarID(0), "items")
ToolbarItem = CocoaMessage(0, ItemArray, "objectAtIndex:", 0)
; ----- Replace ToolBar button by search field
CocoaMessage(0, ToolbarItem, "setView:", SearchField)
; ----- Change ToolBar button size to search field size
ItemSize\width = 150
ItemSize\height = 23
CocoaMessage(0, ToolbarItem, "setMaxSize:@", @ItemSize)
CocoaMessage(0, ToolbarItem, "setMinSize:@", @ItemSize)
; ----- Make window visible now in order to hide previous ToolBar modification
HideWindow(0, #False)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
NSSearchField is a subclass of NSControl.Shardik wrote:This is a first try using a wierd hack by replacing a toolbar button with a search field. But because a search field is no native PureBasic control, I currently don't see a way how to detect and react on entries into the search field...
Code: Select all
EnableExplicit
#NSToolbarSizeModeRegular = 1
ImportC ""
sel_registerName(MethodName.S)
class_addMethod(Class.I, Selector.I, Implementation.I, Types.S)
EndImport
Define ItemArray.I
Define ItemSize.NSSize
Define SearchField.I
Define SearchFieldFrame.NSRect
Define ToolbarItem.I
ProcedureC ToolBarCallback(Object.I, Selector.I, Sender.I)
Shared SearchField.I
If Sender = SearchField
Debug "New content of search field: " +
PeekS(CocoaMessage(0, CocoaMessage(0, Sender, "stringValue"),
"UTF8String"), -1, #PB_UTF8)
EndIf
EndProcedure
Procedure SetToolBarCallback(Callback.I, Control.I)
Protected AppDelegate.I
Protected DelegateClass.I
AppDelegate = CocoaMessage(0, CocoaMessage(0, 0,
"NSApplication sharedApplication"), "delegate")
DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
class_addMethod(DelegateClass, sel_registerName("forwardAction:"), Callback,
"v@:@")
CocoaMessage(0, Control, "setAction:", sel_registerName("forwardAction:"))
EndProcedure
OpenWindow(0, 270, 100, 260, 50, "ToolBar with search field",
#PB_Window_SystemMenu | #PB_Window_Invisible)
; ----- Define search field
SearchField = CocoaMessage(0, 0, "NSSearchField new")
CocoaMessage(0, SearchField, "sizeToFit")
CocoaMessage(@SearchFieldFrame, SearchField, "frame")
ToolbarItem = CocoaMessage(0, CocoaMessage(0, 0, "NSToolbarItem alloc"),
"initWithItemIdentifier:$", @"SearchToolbarItemIdentifier")
SetToolBarCallback(@ToolBarCallback(), SearchField)
; ----- Create empty dummy image
CreateImage(0, 24, 24)
; ----- Create standard ToolBar
CreateToolBar(0, WindowID(0))
; ----- Change size of ToolBar to larger icons
CocoaMessage(0, ToolBarID(0), "setSizeMode:", #NSToolbarSizeModeRegular)
; ----- Add button with empty dummy image to ToolBar
ToolBarImageButton(0, ImageID(0))
; ----- Get item object of ToolBar button
ItemArray = CocoaMessage(0, ToolBarID(0), "items")
ToolbarItem = CocoaMessage(0, ItemArray, "objectAtIndex:", 0)
; ----- Replace ToolBar button with search field
CocoaMessage(0, ToolbarItem, "setView:", SearchField)
; ----- Change ToolBar button size to search field size
ItemSize\width = 150
ItemSize\height = 23
CocoaMessage(0, ToolbarItem, "setMaxSize:@", @ItemSize)
CocoaMessage(0, ToolbarItem, "setMinSize:@", @ItemSize)
; ----- Make window visible now in order to hide previous ToolBar modification
HideWindow(0, #False)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Code: Select all
EnableExplicit
ImportC ""
class_addMethod(cls.i, name.i, imp.i, *types)
sel_registerName(*str)
EndImport
DataSection
types_myActionCB:
!db 'v@:@', 0
sel_myActionCB:
!db 'myActionCB:',0
EndDataSection
Global.i SEL_MyActionCB = sel_registerName(?sel_myActionCB)
DeclareC MyActionCB(Object.i, Selector.i, Sender.i)
Procedure InitMyActionCB()
Protected AppDelegate.i = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Protected DelegateClass.i = CocoaMessage(0, AppDelegate, "class")
class_addMethod(DelegateClass, SEL_MyActionCB, @MyActionCB(), ?types_myActionCB)
EndProcedure
InitMyActionCB()
; *** main code ***
#NSToolbarSizeModeRegular = 1
Global.i SearchField
ProcedureC MyActionCB(Object.i, Selector.i, Sender.i)
Select Sender
Case SearchField
Debug "New content of search field: " +
PeekS(CocoaMessage(0, CocoaMessage(0, Sender, "stringValue"),
"UTF8String"), -1, #PB_UTF8)
EndSelect
EndProcedure
Define ItemArray.i
Define ItemSize.NSSize
Define SearchFieldFrame.NSRect
Define ToolbarItem.i
OpenWindow(0, 270, 100, 260, 50, "ToolBar with search field",
#PB_Window_SystemMenu | #PB_Window_Invisible)
; ----- Define search field
SearchField = CocoaMessage(0, 0, "NSSearchField new")
CocoaMessage(0, SearchField, "sizeToFit")
CocoaMessage(@SearchFieldFrame, SearchField, "frame")
ToolbarItem = CocoaMessage(0, CocoaMessage(0, 0, "NSToolbarItem alloc"),
"initWithItemIdentifier:$", @"SearchToolbarItemIdentifier")
CocoaMessage(0, SearchField, "setAction:", SEL_MyActionCB)
; ----- Create empty dummy image
CreateImage(0, 24, 24)
; ----- Create standard ToolBar
CreateToolBar(0, WindowID(0))
; ----- Change size of ToolBar to larger icons
CocoaMessage(0, ToolBarID(0), "setSizeMode:", #NSToolbarSizeModeRegular)
; ----- Add button with empty dummy image to ToolBar
ToolBarImageButton(0, ImageID(0))
; ----- Get item object of ToolBar button
ItemArray = CocoaMessage(0, ToolBarID(0), "items")
ToolbarItem = CocoaMessage(0, ItemArray, "objectAtIndex:", 0)
; ----- Replace ToolBar button with search field
CocoaMessage(0, ToolbarItem, "setView:", SearchField)
; ----- Change ToolBar button size to search field size
ItemSize\width = 150
ItemSize\height = 23
CocoaMessage(0, ToolbarItem, "setMaxSize:@", @ItemSize)
CocoaMessage(0, ToolbarItem, "setMinSize:@", @ItemSize)
; ----- Make window visible now in order to hide previous ToolBar modification
HideWindow(0, #False)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Code: Select all
EnableExplicit
Global.i SEL_MyActionCB = sel_registerName_("myActionCB:")
DeclareC MyActionCB(Object.i, Selector.i, Sender.i)
Procedure InitMyActionCB()
Protected AppDelegate.i = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Protected DelegateClass.i = CocoaMessage(0, AppDelegate, "class")
class_addMethod_(DelegateClass, SEL_MyActionCB, @MyActionCB(), "v@:@")
EndProcedure
InitMyActionCB()
; *** main code ***
#NSToolbarSizeModeRegular = 1
Global.i SearchField
ProcedureC MyActionCB(Object.i, Selector.i, Sender.i)
Select Sender
Case SearchField
Debug "New content of search field: " +
PeekS(CocoaMessage(0, CocoaMessage(0, Sender, "stringValue"),
"UTF8String"), -1, #PB_UTF8)
EndSelect
EndProcedure
Define ItemArray.i
Define ItemSize.NSSize
Define SearchFieldFrame.NSRect
Define ToolbarItem.i
OpenWindow(0, 270, 100, 260, 50, "ToolBar with search field",
#PB_Window_SystemMenu | #PB_Window_Invisible)
; ----- Define search field
SearchField = CocoaMessage(0, 0, "NSSearchField new")
CocoaMessage(0, SearchField, "sizeToFit")
CocoaMessage(@SearchFieldFrame, SearchField, "frame")
ToolbarItem = CocoaMessage(0, CocoaMessage(0, 0, "NSToolbarItem alloc"),
"initWithItemIdentifier:$", @"SearchToolbarItemIdentifier")
CocoaMessage(0, SearchField, "setAction:", SEL_MyActionCB)
; ----- Create empty dummy image
CreateImage(0, 24, 24)
; ----- Create standard ToolBar
CreateToolBar(0, WindowID(0))
; ----- Change size of ToolBar to larger icons
CocoaMessage(0, ToolBarID(0), "setSizeMode:", #NSToolbarSizeModeRegular)
; ----- Add button with empty dummy image to ToolBar
ToolBarImageButton(0, ImageID(0))
; ----- Get item object of ToolBar button
ItemArray = CocoaMessage(0, ToolBarID(0), "items")
ToolbarItem = CocoaMessage(0, ItemArray, "objectAtIndex:", 0)
; ----- Replace ToolBar button with search field
CocoaMessage(0, ToolbarItem, "setView:", SearchField)
; ----- Change ToolBar button size to search field size
ItemSize\width = 150
ItemSize\height = 23
CocoaMessage(0, ToolbarItem, "setMaxSize:@", @ItemSize)
CocoaMessage(0, ToolbarItem, "setMinSize:@", @ItemSize)
; ----- Make window visible now in order to hide previous ToolBar modification
HideWindow(0, #False)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Thank you again, Wilbert, for your explanation and heads up. I have modified my above example.wilbert wrote:@Shardik,
I used setTag: to create some sort of universal option with a single callback but you don't need that in this case.
setTarget: is required when you use PureBasic gadgets to overwrite the target PB sets but if you create an object like a search field yourself, the target is nil by default meaning that it will follow the responder chain that ends with the app delegate.
So in this case the only thing you need to set on the control is the action with setAction: the other two can be omitted.
If you would add multiple custom objects like for example also a NSSegmentedControl and make the objects global variables, you could simply identify by the sender what object is calling the toolbar callback.
I tested with .S on Snow Leopard and compiled with PB 5.22 x86 and x64 in ASCII and Unicode mode and was astonished that I didn't experience any problems. Therefore I didn't insert my ConvertToUTF8() workaround from previous code examples...wilbert wrote:One concern might be the .S in your import statements when using unicode.
It looks like the types argument is ignored and because you can define the selector yourself and don't need an existing one, it seems to work fine with both unicode and ascii.Shardik wrote:I tested with .S on Snow Leopard and compiled with PB 5.22 x86 and x64 in ASCII and Unicode mode and was astonished that I didn't experience any problems. Therefore I didn't insert my ConvertToUTF8() workaround from previous code examples...
Actually it's one button made of multiple segments. It's an instance of the NSSegmentedControl class.ergrull0 wrote:What about the creation of that sort of "grouped" buttons gadget?
ergrull0 wrote:What about the creation of that sort of "grouped" buttons gadget?
Code: Select all
EnableExplicit
#NSSegmentSwitchTrackingSelectOne = 0
#NSSegmentSwitchTrackingSelectAny = 1
#NSSegmentSwitchTrackingMomentary = 2
#NSToolbarSizeModeRegular = 1
ImportC ""
sel_registerName(MethodName.S)
class_addMethod(Class.I, Selector.I, Implementation.I, Types.S)
EndImport
Define GadgetID.I
Define ItemArray.I
Define ItemSize.NSSize
Define SegmentedCell.I
Define SegmentedControl.I
Define ToolbarItem.I
Procedure.S ConvertToUTF8(String.S)
Protected UTF8String.S = Space(StringByteLength(String))
PokeS(@UTF8String, String, -1, #PB_UTF8)
ProcedureReturn UTF8String
EndProcedure
ProcedureC ToolBarCallback(Object.I, Selector.I, Sender.I)
Shared SegmentedControl.I
If Sender = SegmentedControl
Debug "Selected segment = " + CocoaMessage(0, Sender, "selectedSegment")
EndIf
EndProcedure
Procedure SetToolBarCallback(Callback.I, Control.I)
Protected AppDelegate.I
Protected DelegateClass.I
AppDelegate = CocoaMessage(0, CocoaMessage(0, 0,
"NSApplication sharedApplication"), "delegate")
DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
class_addMethod(DelegateClass,
sel_registerName(ConvertToUTF8("forwardAction:")), Callback,
ConvertToUTF8("v@:@"))
CocoaMessage(0, Control, "setAction:",
sel_registerName(ConvertToUTF8("forwardAction:")))
EndProcedure
OpenWindow(0, 270, 100, 395, 220, "ToolBar with SegmentedControl",
#PB_Window_SystemMenu | #PB_Window_Invisible)
FrameGadget( 0, 10, 10, 170, 185, "Button style")
OptionGadget( 1, 20, 35, 150, 22, "Rounded")
OptionGadget( 2, 20, 60, 150, 22, "Textured + rounded")
OptionGadget( 3, 20, 85, 150, 22, "Rounded rectangle")
OptionGadget( 4, 20, 110, 150, 22, "Textured + squared")
OptionGadget( 5, 20, 135, 150, 22, "Capsule")
OptionGadget( 6, 20, 160, 150, 22, "Small + squared")
SetGadgetState(1, #True)
FrameGadget( 7, 190, 10, 195, 115, "Selection behaviour")
OptionGadget( 8, 200, 35, 175, 22, "Only one always selected")
OptionGadget( 9, 200, 60, 175, 22, "Multiple always selected")
OptionGadget(10, 200, 85, 175, 22, "One momentarily selected")
SetGadgetState(8, #True)
; ----- Define SegmentedControl
SegmentedControl = CocoaMessage(0, 0, "NSSegmentedControl new")
CocoaMessage(0, SegmentedControl,
"setSegmentCount:", 4)
CocoaMessage(0, SegmentedControl,
"setImage:", CocoaMessage(0, 0, "NSImage imageNamed:$", @"NSGoLeft"),
"forSegment:", 0)
CocoaMessage(0, SegmentedControl,
"setImage:", CocoaMessage(0, 0, "NSImage imageNamed:$", @"NSGoRight"),
"forSegment:", 1)
CocoaMessage(0, SegmentedControl,
"setImage:", CocoaMessage(0, 0, "NSImage imageNamed:$", @"NSQuickLook"),
"forSegment:", 2)
CocoaMessage(0, SegmentedControl,
"setImage:", CocoaMessage(0, 0, "NSImage imageNamed:$", @"NSAction"),
"forSegment:", 3)
CocoaMessage(0, SegmentedControl,
"setSelected:", #YES,
"forSegment:", 2)
SetToolBarCallback(@ToolBarCallback(), SegmentedControl)
SegmentedCell = CocoaMessage(0, SegmentedControl, "cell")
; ----- Create empty dummy image
CreateImage(0, 24, 24)
; ----- Create standard ToolBar
CreateToolBar(0, WindowID(0))
; ----- Change size of ToolBar to larger icons
CocoaMessage(0, ToolBarID(0), "setSizeMode:", #NSToolbarSizeModeRegular)
; ----- Add button with empty dummy image to ToolBar
ToolBarImageButton(0, ImageID(0))
; ----- Get item object of ToolBar button
ItemArray = CocoaMessage(0, ToolBarID(0), "items")
ToolbarItem = CocoaMessage(0, ItemArray, "objectAtIndex:", 0)
; ----- Replace ToolBar button with SegmentedControl
CocoaMessage(0, ToolbarItem, "setView:", SegmentedControl)
; ----- Change ToolBar button size to SegmentedControl's size
ItemSize\width = 150
ItemSize\height = 24
CocoaMessage(0, ToolbarItem, "setMaxSize:@", @ItemSize)
CocoaMessage(0, ToolbarItem, "setMinSize:@", @ItemSize)
; ----- Make window visible now in order to hide previous ToolBar modification
HideWindow(0, #False)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
GadgetID = EventGadget()
Select GadgetID
Case 1 To 6
CocoaMessage(0, SegmentedControl, "setSegmentStyle:", GadgetID)
Case 8 To 10
CocoaMessage(0, SegmentedCell,
"setTrackingMode:", GadgetID - 8)
EndSelect
EndSelect
ForEver
Code: Select all
ProcedureC ToolBarCallback(Object.I, Selector.I, Sender.I)
Shared SegmentedControl.I
If Sender = SegmentedControl
Debug "Selected segment = " + CocoaMessage(0, Sender, "selectedSegment")
EndIf
EndProcedure
Procedure SetToolBarCallback(Callback.I, Control.I)
Protected AppDelegate.I
Protected DelegateClass.I
AppDelegate = CocoaMessage(0, CocoaMessage(0, 0,
"NSApplication sharedApplication"), "delegate")
DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
class_addMethod(DelegateClass,
sel_registerName(ConvertToUTF8("forwardAction:")), Callback,
ConvertToUTF8("v@:@"))
CocoaMessage(0, Control, "setAction:",
sel_registerName(ConvertToUTF8("forwardAction:")))
EndProcedure
When using Mac controls which are not implemented by PureBasic (because they are only available on the Mac and hence not cross-plattform like the SegmentedControl), you need to evaluate user actions from these controls. When pressing a button of a SegmentedControl, it's not possible to evaluate that button press in PB's event loop because PB simply doesn't know a SegmentedControl or search field. Therefore you have to setup a callback which is called whenever one of your Mac-specific controls is activated. The procedure SetToolBarCallback() in principal sets up the callback ToolBarCallback(). ToolBarCallback() is called from MacOS whenever one of your special controls is activated by the program's user.ergrull0 wrote:May I ask you how do you came up with this code? I mean...what does this piece of code do and how does it work?