Hello,
does anybody know how to add a menu to a column of ListView?
To be able to fill the item by a choice from a menu.
How to add a menu to a listView
How to add a menu to a listView
macOS Catalina 10.15.7
Re: How to add a menu to a listView
Take a look into my code example. It detects row and column of a right click and opens a popup menu which allows you to choose an entry to be written into the right-clicked cell (tested successfully on MacOS 10.6.8 "Snow Leopard" and 10.12.1 "Sierra" with PB 5.43 x86 and x64 in both ASCII and Unicode mode):
Code: Select all
EnableExplicit
; ----- Only necessary for compilation with PB x64 on MacOS 10.12 "Sierra"
; Import "-stdlib=libc++ -mmacosx-version-min=10.7" : EndImport
Define CursorLocation.NSPoint
Define SelectedColumn.I
Define SelectedRow.I
OpenWindow(0, 200, 100, 250, 101, "Right click to select sex")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
"Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Sex", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
#PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(0, -1, "Harry Rannit")
AddGadgetItem(0, -1, "Ginger Brokeit")
AddGadgetItem(0, -1, "Didi Foundit")
If CreatePopupMenu(0)
MenuItem(0, "Male")
MenuItem(1, "Female")
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
If EventGadget() = 0 And EventType() = #PB_EventType_RightClick
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
DisplayPopupMenu(0, WindowID(0))
EndIf
EndIf
Case #PB_Event_Menu
Select EventMenu()
Case 0
SetGadgetItemText(0, SelectedRow, "Male", SelectedColumn)
Case 1
SetGadgetItemText(0, SelectedRow, "Female", SelectedColumn)
EndSelect
EndSelect
ForEver
Re: How to add a menu to a listView
Thanks Shardik!
This helps.
But do you know how to build it like this in the picture.
This helps.
But do you know how to build it like this in the picture.
macOS Catalina 10.15.7
Re: How to add a menu to a listView
This new example code needs at least MacOS 10.7 (Lion). I tested it successfully on MacOS 10.8.6 (Mountain Lion) and 10.12.1 (Sierra) with PB 5.43 x86 and x64 in both ASCII and Unicode mode.
Since PureBasic is still using NSCells (deprecated cell-based approach, NSCells are not based on NSView, alot less flexible and therefore much harder to modify) to display the cell contents and according to Apple the cell-based and view-based approach may not be mixed, I had to use the delegate method tableView:viewForTableColumn:row: (introduced in Lion) and return a newly allocated view (NSComboBox for a column with a ComboBox or NSTextField for a normal column) for each cell that has to be displayed:
Since PureBasic is still using NSCells (deprecated cell-based approach, NSCells are not based on NSView, alot less flexible and therefore much harder to modify) to display the cell contents and according to Apple the cell-based and view-based approach may not be mixed, I had to use the delegate method tableView:viewForTableColumn:row: (introduced in Lion) and return a newly allocated view (NSComboBox for a column with a ComboBox or NSTextField for a normal column) for each cell that has to be displayed:
Code: Select all
EnableExplicit
; ----- Only necessary when compiling with PB x64 on MacOS 10.12 "Sierra"
; Import "-stdlib=libc++ -mmacosx-version-min=10.7" : EndImport
If OSVersion() < #PB_OS_MacOSX_10_7
MessageRequester("Compilation terminated",
"Sorry, but you need at least MacOS 10.7 (Lion) to compile this code!")
End
EndIf
#ListIcon = 0
Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
"NSApplication sharedApplication"), "delegate")
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Define RowHeight.CGFloat = 25
Define Selector.I = sel_registerName_("tableView:viewForTableColumn:row:")
ProcedureC GetViewForCellCallback(Object.I, Selector.I, TableView.I,
ColumnObject.I, Row.I)
Protected CellContent.S
Protected Column.I
Protected ColumnID.S = PeekS(CocoaMessage(0, CocoaMessage(0,
ColumnObject, "identifier"), "UTF8String"), -1, #PB_UTF8)
Protected ComboBox.I
Protected TextFrame.NSRect
Protected View.I
Column = Val(ColumnID)
If Column = 1
; ----- If column = 1, create ComboBox and return it
ComboBox = CocoaMessage(0, 0, "NSComboBox new")
CocoaMessage(0, ComboBox, "addItemWithObjectValue:$",
@"12 Parliament Way, Battle Street, By the Bay")
CocoaMessage(0, ComboBox, "addItemWithObjectValue:$",
@"130 PureBasic Road, BigTown, CodeCity")
CocoaMessage(0, ComboBox, "addItemWithObjectValue:$",
@"321 Logo Drive, Mouse House, Downtown")
View = ComboBox
Else
; ----- If Column <> 1, read current cell content, create new view with
; NSTextField, write current content into that view and return it
CellContent = GetGadgetItemText(#ListIcon, Row, Column)
TextFrame\size\width = GetGadgetItemAttribute(#ListIcon,
#PB_ListIcon_ColumnWidth, Column)
TextFrame\size\height = 18
View = CocoaMessage(0, CocoaMessage(0, 0, "NSTextField new"),
"initWithFrame:@", TextFrame)
CocoaMessage(0, View, "setStringValue:$", @CellContent)
EndIf
ProcedureReturn View
EndProcedure
OpenWindow(0, 200, 100, 430, 126, "ListIconGadget with ComboBox")
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")
AddGadgetItem(0, -1, "Ginger Brokeit")
AddGadgetItem(0, -1, "Didi Foundit")
; ----- Increase row height to be able to display larger ComboBox
CocoaMessage(0, GadgetID(0), "setRowHeight:@", @RowHeight)
; ----- Initialize callback that returns a new NSView (view-based) instead
; of the old NSCell (cell-based) for each cell drawn
class_addMethod_(DelegateClass, Selector, @GetViewForCellCallback(), "v@:@@@")
CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Re: How to add a menu to a listView
This is my experience as well: some OS X/macOS stuff is really outdated (examples: webgadget doesn't use WKWebview but the old webview, movie library still uses QuickTime instead of AVFoundation etc.)Shardik wrote:Since PureBasic is still using NSCells (deprecated cell-based approach...
Lets hope that Fred extends the next PureBasic version to be more up-to-date on macOS.
It's a bummer because there is no other easy to use programming language (that I know of) on macOS besides Swift 3.
On the flip-side I can see why it takes so long for the PureBasic team to update the PB-Libs:
Apple's macOS replacement libraries are not a 1 to 1 replacement. Lot's of stuff doesn't work the same.
In my experience it's a lot of trial and error because some lib-commands have been killed in the new library. And Apple's documentation is written in a way that it's assumed the reader is a well versed professional OS X programmer...
On top of that: XCode really sux big time, and the strange programming approach of half coding and the other half is disguised in some ui-event sub-menus where a "graphical connection" needs to be made in the interface builder...
I am to provide the public with beneficial shocks.
Alfred Hitshock
Re: How to add a menu to a listView
Although my code example posted above is working quite fine, it is a hack which messes around with PureBasic internals by returning view-based objects instead of cell-based objects. This prevents PureBasic events and PureBasic functions like GetGadgetItemText() to work correctly for the ListIconGadget! Therefore I programmed a more compatible cell-based approach using NSComboBoxCells. But now the ComboBoxes are not editable anymore. If you need editable ComboBoxes you should take a look into this more advanced code example.
This code example was tested successfully with PB 5.44 x86 and x64 in ASCII and Unicode mode on these MacOS versions:
- 10.6.8 (Snow Leopard) (it's only compilable with PB 5.44 x86; to compile it with x64 it's necessary to use PB 5.43 x64!)
- 10.8.6 (Mountain Lion)
- 10.9.5 (Mavericks)
- 10.12.1 (Sierra)
This code example was tested successfully with PB 5.44 x86 and x64 in ASCII and Unicode mode on these MacOS versions:
- 10.6.8 (Snow Leopard) (it's only compilable with PB 5.44 x86; to compile it with x64 it's necessary to use PB 5.43 x64!)
- 10.8.6 (Mountain Lion)
- 10.9.5 (Mavericks)
- 10.12.1 (Sierra)
Code: Select all
EnableExplicit
#ListIcon = 0
#ComboBoxColumn = 1
Define AppDelegate.I = CocoaMessage(0,
CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Define ColumnObject.I
Define i.I
Define ComboBoxCell.I
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Define NotificationCenter.I = CocoaMessage(0, 0,
"NSNotificationCenter defaultCenter")
Define RowHeight.CGFloat = 21
Define Selector.I = sel_registerName_("itemChanged:")
Define SubclassedComboBoxCell.I
ProcedureC ComboBoxSelectionChangedCallback(Object.I, Selector.I,
Notification.I)
Protected Cell.I
Protected ItemIndex.I
Protected ItemText.S
Protected Row.I
Cell = CocoaMessage(0, GadgetID(#ListIcon), "selectedCell")
If Cell
Row = CocoaMessage(0, GadgetID(#ListIcon), "selectedRow")
ItemIndex = CocoaMessage(0, Cell, "indexOfSelectedItem")
If ItemIndex >= 0
ItemText = PeekS(CocoaMessage(0, CocoaMessage(0,
Cell, "itemObjectValueAtIndex:", ItemIndex),
"UTF8String"), -1, #PB_UTF8)
If ItemText <> GetGadgetItemText(#ListIcon, Row, #ComboBoxColumn)
SetGadgetItemText(#ListIcon, Row, ItemText, #ComboBoxColumn)
EndIf
EndIf
EndIf
EndProcedure
OpenWindow(0, 200, 100, 250, 113, "ListIcon with ComboBoxes")
ListIconGadget(#ListIcon, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
"Friend", 70, #PB_ListIcon_GridLines)
AddGadgetColumn(#ListIcon, #ComboBoxColumn, "Country",
GadgetWidth(#ListIcon) - GetGadgetItemAttribute(#ListIcon, 0,
#PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(#ListIcon, -1, "Alice")
AddGadgetItem(#ListIcon, -1, "Bob")
AddGadgetItem(#ListIcon, -1, "Eve")
; ----- Increase row height to be able to display the larger ComboBox
CocoaMessage(0, GadgetID(#ListIcon), "setRowHeight:@", @RowHeight)
; ----- Disable highlighting of selected row
CocoaMessage(0, GadgetID(#ListIcon), "setSelectionHighlightStyle:", -1)
; ----- Center text in 1st column vertically
; Caution: _setVerticallyCentered: is an internal flag; it could simply
; disappear without warning in a future release and its use may lead
; to a rejection in Apple's AppStore!
ColumnObject = CocoaMessage(0, CocoaMessage(0,
GadgetID(#ListIcon), "tableColumns"), "objectAtIndex:", 0)
CocoaMessage(0, CocoaMessage(0, ColumnObject, "dataCell"),
"_setVerticallyCentered:", #YES)
; ----- Create a NSComboBoxCell (used internally as an editable ComboBox by
; PureBasic) and use it in all cells of column #ComboBoxColumn
ColumnObject = CocoaMessage(0, CocoaMessage(0,
GadgetID(#ListIcon), "tableColumns"), "objectAtIndex:", #ComboBoxColumn)
ComboBoxCell = CocoaMessage(0, 0, "NSComboBoxCell new")
CocoaMessage(0, ColumnObject, "setDataCell:", ComboBoxCell)
; ----- Remove border around button (special style for NSComboBoxCell in
; NSTableView)
CocoaMessage(0, ComboBoxCell, "setButtonBordered:", #NO)
; ----- Fill ComboBox
CocoaMessage(0, ComboBoxCell, "addItemWithObjectValue:$", @"France")
CocoaMessage(0, ComboBoxCell, "addItemWithObjectValue:$", @"Germany")
CocoaMessage(0, ComboBoxCell, "addItemWithObjectValue:$", @"USA")
; ----- Subclass ComboBoxCell
SubclassedComboBoxCell = objc_allocateClassPair_(CocoaMessage(0,
ComboBoxCell, "class"), "SubclassedComboBoxCell", 0)
objc_registerClassPair_(SubclassedComboBoxCell)
object_setClass_(ComboBoxCell, SubclassedComboBoxCell)
; ----- Set callback to detect selection change in ComboBox
class_addMethod_(DelegateClass, Selector, @ComboBoxSelectionChangedCallback(),
"v@:@")
CocoaMessage(0, NotificationCenter,
"addObserver:", AppDelegate,
"selector:", Selector,
"name:$", @"NSTableViewSelectionDidChangeNotification",
"object:", CocoaMessage(0, GadgetID(#ListIcon), "menu"))
SetActiveGadget(#ListIcon)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
; ----- Display countries currently selected in ComboBoxes
For i = 0 To 2
Debug Str(i + 1) + ". " + GetGadgetItemText(#ListIcon, i, 0) + " - " +
GetGadgetItemText(#ListIcon, i, #ComboBoxColumn)
Next i
CocoaMessage(0, NotificationCenter, "removeObserver:", AppDelegate)