Bernie Wylde wrote: > Thanks Alain > Bernie, I have toyed a bit to implement my suggestion about the drag & drop operation in the DataBrowser. Unfortunately, I'm stuck with fn BrowserSetItemRow that doesn't seem to work as I would expect. I have yet to figure out why. Anyway, to get you started with the drag & drop feature: define three new vectors in the general settings: list.procs[_AcceptDrag] = @Fn MyAcceptDrag list.procs[_AddDragItem] = @Fn MyAddDragItem list.procs[_ReceiveDrag] = @Fn MyReceiveDrag The DataBrowser will call the program on different occasions: 1 - when it is time to add an item in the drag operation (AddDragItem) 2 - when it needs to know if a drag is acceptable on a specific target (AcceptDrag) 3 - when it is time for the prog to retrieve and handle the dropped item (ReceiveDrag) 1 - Adding an identifier to the drag operation: In the tiny example, it is rather simple, because the end-user can only drag a single item at a time. MyAddDragItem might look like this: clear local fn MyAddDragItem( browser as ControlRef, ¬ theDrag as DragReference, ¬ inItemID as DataBrowserItemID, ¬ dragItemRef as .ItemReference ) dim as OSStatus err dim as DataBrowserItemID @ draggedItemID draggedItemID = inItemID // must be in RAM err = fn AddDragItemFlavor( theDrag, ¬ dragItemRef.nil&, ¬ _"item", ¬ draggedItemID, ¬ sizeof(DataBrowserItemID), ¬ 0 ) End Fn = _true // for translucent dragging The DataBrowser tells the program which item is being dragged (inItemID). We will add that itemID to the dragItemRef with a custom flavor that we will name _"item" for example. Actually, the data we must store is a long integer (DataBrowserItemID). Note that we can easily store also the string referenced by the identifier being dragged. We would use a flavor of type _"TEXT", so that other applications like TeachText could deal with the dragged item too. we would have just to add the following: dim as str255 ourString ourString = str&(gWordListH, draggedItemID) err = fn AddDragItemFlavor( theDrag, ¬ dragItemRef.nil&, ¬ _"TEXT", ¬ @ourString[1], ¬ ourString[0], ¬ 0 ) the _"TEXT" type is a stream of characters and not a Pascal string so we need to skip the length byte, hence @ourString[1]. 2 - Accepting a drag: The DataBrowser will ask the program if the drag is acceptable. In our case, we could accept the drag in any circumstances that means that we only have to return _true. However, we will refuse the drag if the item being dragged is the same as the item that is the target of the drag (the item would be dropped onto itself). clear local fn MyAcceptDrag( browser as ControlRef, ¬ theDrag as DragReference, ¬ itemID as DataBrowserItemID ) dim selItemH as handle dim result as boolean result = _true // assume the drag is acceptable selItemH = fn BrowserGetSelectedItems(gBrowser) long if selItemH select selItemH..4& case itemID : result = _false case else : result = _true end select DisposeHandle(selItemH) end if End Fn = result The item being dragged is the item selected in the list, therefore we will compare the target of the drag with the selected item, if they are the same, we return _false. Like I said in a previous post, we get the selection in a handle, but we must skip the first identifier (long integer) in that memory block because it is used by the DBFD library to store a possible parent identifier. 3 - Receiving the dropped item: The DataBrowser tells us which item is the target of the drag and gives us the drag reference, so we just have to get the dragItemRef and extract from there the data of our specific flavor to retrieve the identifier that has been dropped. clear local fn MyReceiveDrag( browser as ControlRef, ¬ theDrag as DragReference, ¬ targetItemID as DataBrowserItemID ) dim as OSStatus err dim as size @ dataSize dim as ItemReference @ dragItemRef dim as UInt16 @ numItems dim as DataBrowserItemID @ droppedItemID err = fn GetDragItemReferenceNumber( theDrag, 1, dragItemRef ) long if err = _noErr dataSize = sizeof(DataBrowserItemID)// must be in RAM err = fn GetFlavorData( theDrag, ¬ dragItemRef, ¬ _"item", ¬ droppedItemID, ¬ dataSize, ¬ 0) Long If err = _noErr dim targetRow as long targetRow = Fn BrowserGetItemRow( browser, targetItemID ) Fn BrowserSetItemRow( browser,droppedItemID, targetRow ) //def debugnumber(droppedItemID) //def debugnumber(targetRow) end if end if end fn = ( err = _noErr ) My attempt shows that we can get the right row for the target as well as the right itemID that has been dropped, nevertheless BrowserSetItemRow fails to change the display in the list and returns _noErr. Maybe someone will have an idea as to why the DataBrowser does not update its list. Until a solution is found, perhaps you can adopt another strategy from there. I have tried at my side to maintain a duplicate of the list handled by the DataBrowser, but it's a real pain in the butt. I have declared a dynamic array (gIndex (_maxInt) as long) and stored the itemIDs sequentially. Like so: long if gWordListH dim i as long for i = 1 to gWordListH..nil% gIndex(i) = i next compress dynamic gIndex& fn BrowserAddItems( gBrowser, gWordListH..nil%, #0 ) end if Oddly enough, if the for/next loop is placed right after the addition of the items in the DataBrowser, the 10 or so first strings are not displayed in the list (double clicking on the empty cells showed the items were there), only Lord and maybe Apple know why. I'm puzzled because the two lists are not related. Of course I had to change the code for the display, in MyGetSetItemData and in some other places. For example, I had to write things like this: err = Fn BrowserSetString( itemData, str&(gWordListH,gIndex(itemID)) ) I believe that the handling of the drag & drop feature would be a nightmare compared to the simplicity above. I just tried the following in the receiveDrag fn swap gIndex(targetRow),gIndex(itemRow) but, no matter what I did to update the list in the DataBrowser (BrowserUpdate, DrawOneControl, InvalRect), nothing worked until I destroyed the list in the Browser and recreated it (like with child items in a hierarchical list): fn DeleteAllItemsInBrowser( gBrowser ) fn BrowserAddItems( gBrowser, gWordListH..nil%, #0 ) Afterward the list is displayed like I want, i.e. with two items that have exchanged their respective position. The DataBrowser seems to be a very strange land to explore. Alain