Drag and drop within the same Grid in a Visual LANSA component

This Q&A forum allows users to post and respond to "How Do I Do ....." questions. Please do not use to report (suspected) errors - you must use your regional help desk for this. The information contained in this forum has not been validated by LANSA and, as such, LANSA cannot guarantee the accuracy of the information.
Post Reply
HamadSheikh
Posts: 27
Joined: Fri Mar 18, 2016 3:49 am
Location: USA
Contact:

Drag and drop within the same Grid in a Visual LANSA component

Post by HamadSheikh » Wed Sep 19, 2018 1:29 am

I have been trying to write a simple VL Form that shows how to move a grid list entry within the displayed list by simply dragging and dropping the entry from one location to another. So far, I have not been able to make things work. I am unable to retrieve the current row number where the drop will take place. Here is my VL Form:

Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_FORM) Clientwidth(484) Clientheight(438) Componentversion(2) Left(850) Top(187)
Define_Com Class(#PRIM_GRID) Name(#Grid1) Captionnoblanklines(True) Columnscroll(False) Componentversion(1) Displayposition(1) Left(16) Parent(#COM_OWNER) Showselection(True) Showselectionhilight(False) Showsortarrow(True) Tabposition(1) Top(8) Height(385) Width(217) Columnbuttonheight(33) Selectionstyle(WholeRow) Dragcolumns(True) Dragstyle(Automatic)
Define_Com Class(#PRIM_GDCL) Name(#GridColumn1) Displayposition(1) Parent(#Grid1) Source(#EMPNO) Width(32)
Define_Com Class(#PRIM_GDCL) Name(#GridColumn2) Displayposition(2) Parent(#Grid1) Source(#SALARY) Width(41) Widthtype(Remainder)
Define_Com Class(#PRIM_STBR) Name(#StatusBar1) Displayposition(2) Height(24) Left(0) Messageposition(1) Parent(#COM_OWNER) Tabposition(2) Tabstop(False) Top(414) Width(484)

Define Field(#HoverEntry) Reffld(#std_num)
Define Field(#WEMPNO) Reffld(#EMPNO)
Define Field(#WSalary) Reffld(#Salary)
Def_List Name(#wrklst) Fields(#EMPNO #SALARY) Type(*WORKING) Entrys(1)

Evtroutine Handling(#com_owner.CreateInstance)
Select Fields(#Grid1) From_File(PSLMST)
Add_Entry To_List(#Grid1)
Endselect
#grid1.DragStyle := Automatic
Endroutine

Evtroutine Handling(#Grid1.StartDrag) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
#std_num := #Grid1.CurrentItem.Entry
Clr_List Named(#wrklst)
Add_Entry To_List(#wrklst)
Endroutine

Evtroutine Handling(#Grid1.DragDrop) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
Dlt_Entry Number(#STD_NUM) From_List(#Grid1)
Get_Entry Number(1) From_List(#wrklst)
Add_Entry To_List(#Grid1) After(#HoverEntry)
Endroutine

Evtroutine Handling(#grid1.DragOver) Acceptdrop(#AcceptDrop)
Set Com(#AcceptDrop) Value(True)
Endroutine

Evtroutine Handling(#Grid1.MouseHover) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
#HoverEntry := #Grid1.FocusItem.Entry
Endroutine
End_Com

I was wondering if anyone else has done this? Can you share your code?

TomC
Posts: 10
Joined: Thu Mar 10, 2016 10:01 am

Re: Drag and drop within the same Grid in a Visual LANSA component

Post by TomC » Wed Sep 19, 2018 5:17 am

Have you looked at the sample form in the IDE xDemoDragandDrop?

It shows dragging and dropping within a single list view (to reorder), as well as from one list view to another.

HamadSheikh
Posts: 27
Joined: Fri Mar 18, 2016 3:49 am
Location: USA
Contact:

Re: Drag and drop within the same Grid in a Visual LANSA component

Post by HamadSheikh » Thu Sep 20, 2018 4:39 am

Thanks Tom, there were some very good pointers in that example, though it uses a Tree view. I needed to use a Grid or List view, so I used that example to come up with a working example. Here it is:

Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_FORM) Caption('Drag and Drop') Height(491) Left(865) Width(400) Clientwidth(384) Clientheight(452)
Define_Com Class(#PRIM_GRID) Name(#GridList) Columnbuttonheight(19) Displayposition(1) Height(378) Left(0) Parent(#COM_OWNER) Tabposition(1) Top(32) Width(380) Selectionstyle(Multiple) Dragstyle(Automatic)
Define_Com Class(#PRIM_GDCL) Name(#GridColumn1) Displayposition(1) Parent(#GridList) Source(#xDemoCaption) Widthtype(Remainder)

Define_Com Class(#PRIM_LABL) Name(#Label) Caption('Drag items between lists and within the same list') Displayposition(2) Tabstop(False)
Define_Com Class(#xDemoDragandDropImage) Name(#DragImage)
Define Field(#wxdemocaption) Reffld(#xDemoCaption)

Evtroutine Handling(#Com_owner.CreateInstance)
* Populate Grid list with some data
Begin_Loop To(10)
#xDemoCaption := ("Left &1").Substitute( (#GridList.Items.ItemCount + 1).AsString )
Add_Entry To_List(#GridList)
End_Loop
Endroutine

* The user has started a dragging operation
Evtroutine Handling(#GridList.StartDrag) Com_Sender(#Sender) Continue(#Continue) Payload(#Payload) Draglist(#DragList)
* Get the selected items from the list firing the event and store in the drag payload
#Payload <= #Com_owner.GetSelectedItems( #Sender )
* Drag can continue if there's something in the payload
#Continue := (#Payload *As #Prim_acol<#prim_gdit>).ItemCount > 0
* Drag to use a popup panel as the drag image
#DragList.DragListStyle := Popup
* Hook up the Dragimage Popup
#DragList.DragPopup <= #DragImage
* Set the drag image appearance
#DragImage.DragCaption := (#Payload *As #Prim_acol<#prim_gdit>).ItemCount.AsString
#DragImage.DragImage <= #xImageFavorites32
* Store the selected entry values
#wxdemocaption := #xDemoCaption
#std_num := #GridList.CurrentItem.Entry
Endroutine

* Allow Dragover on the Grid list and highlight the selected grid rows
Evtroutine Handling(#GridList.DragOver) Com_Sender(#Sender) Acceptdrop(#Accept) Payload(#Payload) Source(#Source) Showdrophilight(#DropHilight)
* Highlight the item
#DropHilight := True
* Allow the drop if the payload is not empty
#Accept := (#Payload *As #Prim_acol<#prim_gdit>).ItemCount > 0
Endroutine

* Drop into the Grid List
Evtroutine Handling(#GridList.DragDrop) Payload(#Payload) Dragresult(#DragResult) Source(#Source)
#COM_OWNER.DoGridDrop Source(#source) Dropitem(#GridList.CurrentItem) Payload(#Payload *As #Prim_acol<#prim_gdit>)
#DragResult := Accepted
Endroutine

Mthroutine Name(DoGridDrop) Access(*PRIVATE)
Define_Map For(*INPUT) Class(#Prim_objt) Name(#Source) Pass(*BY_REFERENCE)
Define_Map For(*INPUT) Class(#Prim_gdit) Name(#DropItem) Pass(*BY_REFERENCE)
Define_Map For(*INPUT) Class(#Prim_acol<#prim_gdit>) Name(#Payload) Pass(*BY_REFERENCE)

* Iterate over the items in the payload
For Each(#Item) In(#Payload)
* Set the Field value(s)
#xDemoCaption := #item.ValueAt<1>
* Delete the old row
Dlt_Entry Number(#Item.entry) From_List(#GridList)

#std_num := #DropItem.Position - 1
If (#STD_NUM <= 2)
#std_num := 2
Endif
* Add the deleted row into the new position
Add_Entry To_List(#GridList) After((#DropItem.Position - 1))
#STD_NUM := 0
Endfor
Endroutine

Mthroutine Name(GetSelectedItems) Access(*PRIVATE)
Define_Map For(*INPUT) Class(#Prim_GRID) Name(#Grid) Pass(*BY_REFERENCE)
Define_Map For(*RESULT) Class(#Prim_acol<#prim_gdit>) Name(#Result) Pass(*BY_REFERENCE)
#Result <= *New #Prim_acol<#prim_gdit>
For Each(#Item) In(#Grid.Items)
Continue If(*Not #Item.Selected)
#Result.Insert( #Item )
Endfor
Endroutine
End_Com

Note that the code would have been significantly simpler if the .Position property could be set in a Grid or List component.
Position is settable in a Tree view. I have logged that as an Enhancement request.

Post Reply