It is currently Fri Jul 28, 2017 2:02 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: How to add a menu to a listView
PostPosted: Mon Oct 31, 2016 4:39 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 301
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.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a menu to a listView
PostPosted: Wed Nov 02, 2016 9:35 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1425
Location: Germany
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:
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


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a menu to a listView
PostPosted: Thu Nov 03, 2016 10:29 am 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 301
Thanks Shardik!

This helps.
But do you know how to build it like this in the picture.
Image


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a menu to a listView
PostPosted: Sun Nov 06, 2016 10:01 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1425
Location: Germany
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:
Code:
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


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a menu to a listView
PostPosted: Tue Nov 08, 2016 7:33 pm 
Offline
Addict
Addict
User avatar

Joined: Tue Apr 29, 2003 9:18 pm
Posts: 1443
Location: North by Northwest
Shardik wrote:
Since PureBasic is still using NSCells (deprecated cell-based approach...


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.)
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


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a menu to a listView
PostPosted: Sat Dec 17, 2016 10:51 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1425
Location: Germany
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)
Code:
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)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye