Multi-row select for Grid control

From DFWiki

Jump to: navigation, search

Functionality

This code demonstrates how to select multiple rows in a Grid. The code will work no matter how many columns. The object of this code is to allow the user to use the SHIFT+RCLICK or CTRL+RCLICK key to select multiple rows just like a spreadsheet program.

Example

Paste this code into a test view to test it and see how it works. Once compiled, you will see a narrow column on the left that acts as a margin. Clicking this gray cell will highlight the row. Using SHIFT or CTRL and clicking another gray cell will select multiple rows.

 Object oGrid1 is a Grid
   Set Location to 7 26
   Set Size to 116 207
   Set Line_Width to 4 0
   Set Form_Width    0 to 8
   Set Header_Label  0 to ""
   Set Form_Width    1 to 60
   Set Header_Label  1 to "Column 1"
   Set Form_Width    2 to 60       
   Set Header_Label  2 to "Column 2"
   Set Form_Width    3 to 60       
   Set Header_Label  3 to "Column 3"
   // BEGIN MULTI-SELECT CODE
   // DO NOT MODIFY
   Set Select_Mode to Multi_Select
   Property Integer[] paiSelected
   Property Integer piLastSelected 0
   Procedure Select_Toggling Integer iItem Integer iState
       Integer iCurrent iCol iLast iCount iFrom iTo iRet iUpdate
       Integer[] aiSelected aiEmpty
       //
       Get Dynamic_Update_State to iUpdate
       Set Dynamic_Update_State to False
       // Get base item
       Move (Current_Item(Self)) to iCurrent
       Move (Mod(iCurrent , Line_Size(Self))) to iCol
       Subtract iCol from iCurrent
       // get list of selected items
       Move (paiSelected(Self)) to aiSelected
       Move (SizeOfArray(aiSelected)) to iCount
       //
       Move (GetAsyncKeyState(VK_CONTROL)) to iRet
       If (iRet<>0) Begin
           If (iState) Begin
               // add selected item
               Move iCurrent to aiSelected[iCount]
               // Update last selected with this item
               Set piLastSelected to iCurrent
               // Select Current row
               For iCol from 0 to (Line_Size(Self)-1)
                   Forward Send Select_Toggling (iCurrent+iCol) iState
               Loop
           End
           Else Begin
               // remove selected item
               For iItem from 0 to (iCount-1)
                   Move aiSelected[iItem] to iLast
                   If (iLast=iCurrent) Move -1 to aiSelected[iItem]
               Loop
               // Update last selected with this item
               Set piLastSelected to -1
           End
       End
       Else Begin
           // If shift is used, we will ignore
           // the state of the clicked row
           // unselect everything
           For iItem from 0 to (iCount-1)
               Move aiSelected[iItem] to iLast
               For iCol from 0 to (Line_Size(Self)-1)
                   Forward Send Select_Toggling (iLast+iCol) False
               Loop
           Loop
           Move aiEmpty to aiSelected
           //
           Move (GetAsyncKeyState(VK_SHIFT)) to iRet
           If ((iRet<>0) and (piLastSelected(Self)<>-1)) Begin
               // select everything in between
               // do not mark this as the last current row,
               // the first item of the shift remains
               If (iCurrent > piLastSelected(Self)) Begin
                   Move (piLastSelected(Self)) to iFrom
                   Move iCurrent to iTo
               End
               Else Begin
                   Move iCurrent to iFrom
                   Move (piLastSelected(Self)) to iTo
               End
               Move 0 to iCount
               For iItem from iFrom to (iTo+3)
                   // Add to array
                   Move iItem to aiSelected[iCount]
                   Increment iCount
                   // select
                   For iCol from 0 to (Line_Size(Self)-1)
                       Forward Send Select_Toggling (iItem+iCol) True
                   Loop
                   // next row
                   Add 3 to iItem
               Loop
           End
           Else Begin
               // no shift or control key was pressed
               // Update last selected with this item
               Move iCurrent to aiSelected[0]
               Set piLastSelected to iCurrent
               // Select Current item
               For iCol from 0 to (Line_Size(Self)-1)
                   Forward Send Select_Toggling (iCurrent+iCol) iState
               Loop
           End
       End
       Set Dynamic_Update_State to iUpdate
       Set paiSelected to aiSelected
   End_Procedure // Select_Toggling
   Procedure Mouse_Up Integer iWindowNumber Integer iPosition
       Integer iCol
       Move (Mod(iWindowNumber , Line_Size(Self))) to iCol
       Forward Send Mouse_Up iWindowNumber iPosition
       If (iCol<>1) Send Select_Toggling 0 False
   End_Procedure // Mouse_Up
   // END MULTI-SELECT CODE
   //Sample method of how to fill a grid
   Procedure DoFillGrid
       Integer iRow iMaxRows
       Move 20 to iMaxRows
       For iRow from 0 to iMaxRows
           Send Add_Item Msg_None ""
           Send Add_Item Msg_None ("Col 1, row " + String (iRow))
           Send Add_Item Msg_None ("Col 2, row " + String (iRow))
           Send Add_Item Msg_None ("Col 3, row " + String (iRow))
           Set Entry_State item (iRow*4) to False
           Set ItemColor item (iRow*4) to clBtnFace
       Loop
   End_Procedure // DoFillgrid
   Send DoFillgrid
 End_Object // oGrid1
 Object oButton1 is a Button
   Set Size to 14 70
   Set Location to 151 44
   Set Label to "Show Selection"
   // Example on how to get selected rows
   Procedure OnClick
       Integer[] aiSelected
       Integer iItem iCount
       Get paiSelected of oGrid1 to aiSelected
       Move (SizeOfArray(aiSelected)) to iCount
       Showln "Selected Row base_item(s) are"
       For iItem from 0 to (iCount-1)
           Showln (Character(9)) aiSelected[iItem]
       Loop
   End_Procedure // OnClick
 End_Object // oButton1
Personal tools