It is currently Sun Apr 23, 2017 10:43 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: How to add a second Callback ???
PostPosted: Wed Nov 23, 2016 4:39 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 253
How can I add a second Callback to a ListIconGadget() ?
I need one to be able to edit the items and one to add a ComboBoxGadget() in one row of the ListIconGadget().


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a second Callback ???
PostPosted: Wed Nov 23, 2016 6:36 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 2812
Location: Netherlands
I'm not sure what you mean by a second callback.
Can't you use BindEvent ?

_________________
MacOS 10.12, PB 5.51 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a second Callback ???
PostPosted: Wed Nov 23, 2016 6:54 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 253
wilbert wrote:
I'm not sure what you mean by a second callback.
Can't you use BindEvent ?


In this example only one callback work. If I remove the first one the second will work.

Code:
ImportC ""
  sel_registerName(MethodName.S)
  class_addMethod(Class.I, Selector.I, Implementation.I, Types.S)
EndImport

Procedure.S ConvertToUTF8(String.S)
  Protected UTF8String.S = Space(StringByteLength(String))
  PokeS(@UTF8String, String, -1, #PB_UTF8)
  ProcedureReturn UTF8String
EndProcedure

ProcedureC EditingFinishedCallback(Object.I, Selector.I, Notification.I)
  Protected EditedCell.I
  Protected EditedColumn.I = CocoaMessage(0, GadgetID(0), "editedColumn")
  Protected EditedRow.I = CocoaMessage(0, GadgetID(0), "editedRow")
  Protected EditedText.S

  EditedCell = CocoaMessage(0, Notification, "object")
  EditedText = PeekS(CocoaMessage(0, CocoaMessage(0, EditedCell, "stringValue"),
    "UTF8String"), -1, #PB_UTF8)
  SetGadgetItemText(0, EditedRow, EditedText, EditedColumn)
  Debug "Edit finished"
EndProcedure

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:$",
      @"AAA")
    CocoaMessage(0, ComboBox, "addItemWithObjectValue:$",
      @"BBB")
    CocoaMessage(0, ComboBox, "addItemWithObjectValue:$",
      @"CCC")
    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(0, Row, Column)
    TextFrame\size\width = GetGadgetItemAttribute(0,
      #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


Define CursorLocation.NSPoint
Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Define NotificationCenter.I = CocoaMessage(0, 0,
  "NSNotificationCenter defaultCenter")
Define SelectedColumn.I
Define Selector.I = sel_registerName(ConvertToUTF8("textDidEndEditing:"))


Define RowHeight.CGFloat = 25
Define Selector2.I = sel_registerName_("tableView:viewForTableColumn:row:")


OpenWindow(0, 200, 100, 430, 195, "Editable ListIconGadget demo II")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20, "Name", 110)
AddGadgetColumn(0, 1, "Address1", 292)
AddGadgetColumn(0, 2, "Address2", GadgetWidth(0) - GetGadgetItemAttribute(0,
  0, #PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ + "")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ + "")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ + "")
CocoaMessage(0, GadgetID(0), "setSelectionHighlightStyle:", -1)


; ----- 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, Selector2, @GetViewForCellCallback(), "v@:@@@")
CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)

class_addMethod(DelegateClass, Selector, @EditingFinishedCallback(), "v@:@")
CocoaMessage(0, NotificationCenter,
             "addObserver:", AppDelegate,
             "selector:", Selector,
             "name:$", @"NSControlTextDidEndEditingNotification",
             "object:", GadgetID(0))



Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0 And EventType() = #PB_EventType_LeftClick
        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)
        CocoaMessage(0, GadgetID(0),
          "editColumn:", SelectedColumn,
          "row:", GetGadgetState(0),
          "withEvent:", 0,
          "select:", #YES)
      EndIf
  EndSelect
ForEver


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a second Callback ???
PostPosted: Wed Nov 23, 2016 10:27 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1411
Location: Germany
Sorry, but your problem can't be solved by a second callback. You have taken my example for adding ComboBoxes to cells in a column of a ListIconGadget and added my example to edit single cells. Unfortunately my first example is a hack. Although the example is working fine, it's messing around with PureBasic internals by replacing PureBasic's NSCells (cell-based) in the ListIconGadget with view-based NSComboBoxes and NSTextFields. As a result the PureBasic event loop doesn't work correctly anymore for the ListIconGadget, so that the method editColumn:row:withEvent:select: in the event loop is never called!

The only solution seems to be to replace PureBasic's NSCell objects (cell-based) by NSComboBoxCell objects (also cell-based). This seems to work so far, but until now I wasn't able to detect the selection of a ComboBox element and display the chosen element in the ComboBox. After selecting an element from the ComboBox, the selected element is always briefly displayed in the ComboBox but cleared after a very short period. I currently don't know whether this technique is possibly interfering with PureBasic internals... :oops:


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a second Callback ???
PostPosted: Sat Dec 17, 2016 7:47 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1411
Location: Germany
I have finally found a solution which utilizes NSComboBoxCells to display ComboBoxes in a column of a ListIconGadget. It's possible to edit the content of normal cells and ComboBox cells (and thereby add new ComboBox items). You may disable the editing of ComboBox cells by setting #ComboBoxEdtitableState to #False.

I have tested this example successfully with PB 5.44 x86 and x64 in ASCII and Unicode mode with 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
#ComboBoxEditableState = #True ; #True enables editing of ComboBox,
                               ; #False disables it

Define AppDelegate.I = CocoaMessage(0,
  CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Define ColumnObject.I
Define i.I
Define ComboBoxCell.I
Define CursorLocation.NSPoint
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Define NotificationCenter.I = CocoaMessage(0, 0,
  "NSNotificationCenter defaultCenter")
Define RowHeight.CGFloat = 21
Define SelectedCell.I
Define SelectedColumn.I
Define SelectedRow.I
Define Selector1.I = sel_registerName_("itemChanged:")
Define Selector2.I = sel_registerName_("textDidEndEditing:")
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

ProcedureC EditingEndedCallback(Object.I, Selector.I, Notification.I)
  Shared ComboBoxCell.I

  Protected Cell.I
  Protected Column.I = CocoaMessage(0, GadgetID(0), "editedColumn")
  Protected Row.I = CocoaMessage(0, GadgetID(0), "editedRow")
  Protected Text.S

  Cell = CocoaMessage(0, Notification, "object")
  Text = PeekS(CocoaMessage(0, CocoaMessage(0, Cell, "stringValue"),
    "UTF8String"), -1, #PB_UTF8)

  If Column = #ComboBoxColumn
    If Trim(Text) <> ""
      If CocoaMessage(0, ComboBoxCell,
        "indexOfItemWithObjectValue:$", @Text) = #NSNotFound
        CocoaMessage(0, ComboBoxCell, "addItemWithObjectValue:$", @Text)
      EndIf
    EndIf
  EndIf
 
  SetGadgetItemText(0, Row, Text, Column)
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 column 0 vertically
;       Caution: _setVerticallyCentered: is an internal flag; it could simply
;       disappear without warning in a future MacOS 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, Selector1, @ComboBoxSelectionChangedCallback(),
  "v@:@")
CocoaMessage(0, NotificationCenter,
  "addObserver:", AppDelegate,
  "selector:", Selector1,
  "name:$", @"NSTableViewSelectionDidChangeNotification",
  "object:", CocoaMessage(0, GadgetID(#ListIcon), "menu"))

; ----- Set callback to detect end of editing in ListIcon cell
class_addMethod_(DelegateClass, Selector2, @EditingEndedCallback(), "v@:@")
CocoaMessage(0, NotificationCenter,
  "addObserver:", AppDelegate,
  "selector:", Selector2,
  "name:$", @"NSControlTextDidEndEditingNotification",
  "object:", GadgetID(#ListIcon))

SetActiveGadget(#ListIcon)

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

        If SelectedColumn = #ComboBoxColumn
          SelectedCell = CocoaMessage(0, ColumnObject,
            "dataCellForRow:", SelectedRow)
          CocoaMessage(0, SelectedCell, "setEditable:", #ComboBoxEditableState)
          CocoaMessage(0, GadgetID(#ListIcon),
            "editColumn:", SelectedColumn,
            "row:", GetGadgetState(#ListIcon),
            "withEvent:", 0,
            "select:", #YES)
        Else
          CocoaMessage(0, GadgetID(#ListIcon),
            "editColumn:", SelectedColumn,
            "row:", GetGadgetState(#ListIcon),
            "withEvent:", 0,
            "select:", #YES)
        EndIf
      EndIf
  EndSelect
ForEver

; ----- 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


Top
 Profile  
Reply with quote  
 Post subject: Re: How to add a second Callback ???
PostPosted: Sat Dec 17, 2016 11:47 am 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 253
Thanks a lot!


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