Page 1 of 4

MicroGrid ~ Rev 0.97 now available.

Posted: Wed Sep 18, 2013 3:17 pm
by RichardL
MicroGrid

17th April 2014

uGrid has been further developed and improved and is now at rev 0.97
Please see my posting of the above date for a link from which the latest version can be downloaded.

Cheers,
RichardL

Code: Select all

; ====================================
; An entry level Editable Grid written for an Amateur Radio 
; project requiring a visible table editor, and then did a 'Topsy...'
;
; Name:      MicroGrid
; Version:   0.93
; Author:    RichardL
; Date:      20th January 2014
; OS:        Windows
; PB ver     5.11
; Copyright: (c)Richard Leman 2013.
; License:   Free to copy/use/plunder entirely at your own risk.
; ====================================
;   Info  - Where to get some nice Images for ImageCells  http://cooltext.com/

; Rev 0.93  LARGER IMAGE CELLS
;   Mod    - uGridService() tidied up and much simplified
;   Added  - Grid and Title fonts may now be specified individually.
;   Added  - Option to specify the height of image cells. ALL cells on grid use this height.
;   Added  - Text and caret position adjusted to keep text centralised vertically
;   Added  - Demo shows all above working.


; Known bugs/deficiences/'in-the-works' :-
; - *** Better/More Callbacks.
; - **  Feedback - FLAT version... no border
; - **  Started uGridDeleteGadget()
; - *   Centre/Right alignment conflicts with editor... may be removed.
; - *   Move to PB 5.20 and tidy up.

EnableExplicit

;{ Procedure declarations
Declare uGridGetCellPtr(GadNum,Col.i,Row.i)
Declare uGridRefreshGrid(GadNum)
Declare uGridWriteCellText(GadNum,cx,cy,text.s)
Declare uGridCallback(uGridNum,uGMsg,uGW,uGL)
Declare uGridDrawCell(GadNum,*Q=0,Flag=0)
Declare FindField(String$,Search$,Sep$,CaseFlag=0)
;}
;{ Globals, constants, etc...
; Flags to control auto-sizing of CanvasGadget()
#uGrid_AutoSizeX   = %00000001
#uGrid_AutoSizeY   = %00000010
#uGrid_UseAuxH     = %00000100

; Cell flags
; Use with uGridSetCellType()
#uGrid_CellDefault   = %000000000000 ; 00 Alpha/Numeric Mixed case
#uGrid_CellNoEdit    = %000000000010 ; 01 Cell data is no editable
#uGrid_CellUcase     = %000000000100 ; 02 Characters are all UCASE
#uGrid_CellLCase     = %000000001000 ; 03 Characters are all LCASE
#uGrid_CellNumOnly   = %000000010000 ; 04 Numbers only 0-9
#uGrid_CellHexOnly   = %000000100000 ; 05 Hex          0-9 A-F
#uGrid_CellFloat     = %000001000000 ; 06 Float        -nnn.nnn
#uGrid_CellList      = %000010000000 ; 07 List         Tom|Dick|Harry|  etc
#uGrid_CellImageFlip = %000100000000 ; 08 Image, two state image button

; Used with uGridCellFlags()
#uGrid_CellAlignR  = %000000000001   ; 00 Leave alone! Text Alignment. (Under threat from over-complication!)
#uGrid_CellAlignC  = %000000000010   ; 01 Default is to left alignment. 
#uGrid_CellToggle  = %000000000100   ; 10 For cell type _CellImageFlip this bit defines image 0 / 1

; Callback flags
Enumeration 1
  #uGridEvent_DeSelect               ; User moved away, time to check his input?
  #uGridEvent_SelecT                 ; A good time to preload a cell 
  #uGridEvent_GridLostFocus
  #uGridEvent_RightKey               ; User clicked on cell with right mouse button
  #uGridEvent_TitleClick             ; User clicked on titlebar
  #uGridEvent_CellChar               ; User types a key to go into cell contents
  #uGridEvent_CellXY                 ; Cell under mouse
  #uGridEvent_CellImageFlip          ; User has changed state of two0state image cell
EndEnumeration

; Redraw options
#RD_HiLtC = %00001                   ; Redraw the highlight box - Coloured
#RD_HiLtB = %00010                   ; Redraw the highlight box - Backdrop
#RD_Text  = %00100                   ; Redraw the text
#RD_Caret = %01000                   ; Redraw the Caret
#RD_Image = %10000                   ; Redraw the Image

Global GridCount.i                   ; Number of grids 
Global uGridCallbackFlag.i = 0 

; Cell edit related variables
Global EdSwitch                ; True if a cell is active for edits
Global EdWin                   ; Win# containing grid
Global EdGrid=-1               ; Grid# being edited
Global EdIndex                 ; Index to GRID in table
Global EdCellX                 ; Co-ords of cell
Global EdCellY           
Global *EdCell = -1            ; Pointer to current cell's structure
Global EdKeepContent$          ; Original content... for ESC
Global EdCaretPos
Global EdCarX
Global EdCarY
Global EdCarH

Structure GRIDFEFAULTS
  TitleBackColour.i
  TitleTextColour.i
  TextBackColour.i
  TextColour.i
  ListSelectColour.i
  SelectColour.i
  LineColour.i
  
  GridFont.s
  GridFontH.i
  
  TitleFont.s
  TitleFontH.i
  
  ImageCellH.i
  
  EditStart.i
  
EndStructure
Global uGridDefaults.GRIDFEFAULTS; Default values for user to setup before creating grid

; Default values that user can modified BEFORE
; creating a grid. Values are transferred to the new grid
; and defaults may then be changed for the next one.
With uGridDefaults
  \TitleBackColour  = RGB($E1,$F7,$FF)
  \TitleTextColour  = #Black
  \TextBackColour   = #White 
  \TextColour       = #Blue
  \SelectColour     = #Blue
  \ListSelectColour = #Blue
  \LineColour       = #Red
  \GridFont         = "Arial"  ; Used for grid
  \GridFontH        = 8        
  \TitleFont        = "Courier" ; Title
  \TitleFontH       = 12  
  \ImageCellH       = 25
  \EditStart        = #PB_EventType_LeftDoubleClick ;#PB_EventType_LeftButtonDown
EndWith

Structure GRIDOPTIONS
  GridWin.i          ; The Window the grid is created in
  GridPBNum.i        ; PureBasic gadget number
  GridColCount.i     ; Number of columns
  GridRowCount.i     ; Number of rows
  GridFlags.i        ; Flags to control features of the grid
  GridCellPointer.i  ; Pointer to structure defining cell being edited
  GridColTitle.s[32] ; Titles for columns. 32 seems big enough... could be set larger.
  GridCellX.i[32]    ; X position of print position in cell
  GridColW.i[32]     ; Cell width including L&R borders and one grid line (Total +5)
  
  GridPixW.i         ; Pixel width of grid including borders (NOT CanvasGadget() borders).
  GridPixH.i         ; Pixel height of grid.....
  
  ; Each GRID has (a) a backdrop image which includes the gridlines and titles
  ; and (b) an image with the current backdrop and the current grid data.
  GridBackImage.i    ; Image with Grid lines and Titles
  GridDataImage.i    ; Copy of BackImage with data drawn over it
  
  ; Default values copied into all cells when a new grid created
  GridTitleBackColour.i
  GridTitleTextColour.i
  
  GridTextColour.i
  GridTextBackColour.i

  GridLineColour.i
  GridSelectColour.i
  GridListSelectColour.i
  
  GridFont.s  
  GridFontH.i
  GridFontNum.i 
  GridFontID.i
  
  TitleFont.s  
  TitleFontH.i
  TitleFontNum.i 
  TitleFontID.i 
  
  ImageCellH.i       ; Alternative grid height, overrides using font height
 
  GridEditStart.i    ; Flag: SingleLeftClick / DoubleLeftClick 
  
  ; Editing strings flags etc
  GEP.s                         ; Scratchpad for CNTRL C / V / X
  
  ; Cell edit related variables
  GridEditCell.i                ; Pointer to structure defining the cell being edited
  GridCaretPos.i                ; Caret position (characters from left)
  GridSortOrder.i
  
EndStructure
Global Dim uGrid.GRIDOPTIONS(1) ; Description of each GRID

Structure CellOptions
  CellX.i                       ; Note: X,Y,W,H values relate to the PIXEL text position and size.
  CellY.i                       ; within the edit selection box
  CellW.i
  CellH.i
  
  CellTextDY.i                  ; Y pixs to centralise text in when cell H increased.
  
  CellGX.i                      ; Cell's logical position within the grid
  CellGY.i
  
  CellType.i                    ; Text, Numeric, Hex etc...
  CellFlags.i                   ; Bitwise flags: sort toggle, image toggle, etc...
  CellContent.s
  CellMaxChars.i
  CellData.i                    ; User write/read data value 
  CellListString.s              ; Optional cell string values
  
  CellTextColour.i
  CellBackColour.i
  CellFontID.i
  
  CellImage.i[2]                ; Image# for toggle images. 0 & 1
  CellHelp.s                    ; Help  / comment string
  
EndStructure
Global uG.CellOptions           ; Descriptions of each CELL
;}
Procedure uGridGetGridIndex(GadNum)                ; Returns index into uGrid.GRIDOPIONS(n) (0 => GridCount-1) or -1 if not found
  Protected n
  For n = 0 To GridCount-1
    If uGrid(n)\GridPBNum  = GadNum
      ProcedureReturn n
    EndIf
  Next
  ProcedureReturn -1
EndProcedure
Procedure uGridSelectCell(GadNum,cx,cy)            ; Set a cell to edit mode, show highlight etc...
  
  Protected GI, *P, *CellDat.CellOptions
  
  ; Find index of uGrid in grid table (-1 if not found)
  GI = uGridGetGridIndex(GadNum) 
  
  ; uGrid NOT found
  If GI  = -1
    MessageRequester("Programming error","Gadget# not found :"+Str(GadNum))
    ProcedureReturn #False
  EndIf
   
  *P = uGridGetCellPtr(GadNum,cx,cy)              ; Get pointer to cell
  If *P
    *CellDat.CellOptions = *P
    
    If *CellDat\CellType & #uGrid_CellNoEdit     ; Prevent focus going to a non-editable cell
      ProcedureReturn #False
    EndIf
    
    ; Save selected CELL co-ords etc...
    EdWin          = GetActiveWindow()
    EdGrid         = GadNum
    *EdCell        = *P                        ; Keep pointer to cell structure
    EdCellX        = cx                        ; Cell co-ords...
    EdCellY        = cy
    EdCarX         = GadgetX(GadNum)
    EdCarY         = GadgetY(GadNum)
    EdCarH         = uGrid(GI)\GridFontH
    EdKeepContent$ = *CellDat\CellContent      ; Keep a copy for Restore (=ESC)
    EdCaretPos     = Len(*CellDat\CellContent) ; Cursor position is end of current content
    EdSwitch       = #True                     ; Enable edits
    
    SetActiveGadget(GadNum)
    uGridDrawCell(GadNum,*CellDat,#RD_Text|#RD_HiLtC|#RD_Caret)
    
  EndIf
  
EndProcedure
Procedure uGridDrawCell(GadNum,*Q=0,Flag=0)        ; Draw Backdrop+Text / HighLightBox / Caret 
  ; Gadnum : CanvesGadget.
  ; *Q     : Pointer to cell's structure.
  ; Flags  : Bitwise flags for what is to be drawn.
  
  Static LastGadnum, *LastP=-1, *P, *CellDat.CellOptions
  Protected T,m,q$,C
  
  ; *Q=0: Special case for de-selecting cell from previous call 
  If *Q = 0             
    If *LastP = -1      ; But not the very first time!
      ProcedureReturn
    EndIf
    GadNum = LastGadnum ; The previous cell's gadget,
    *P   = *LastP       ; and structure
    Flag = #RD_HiLtB    ; 
  Else
    *P = *Q
  EndIf
  *CellDat.CellOptions = *P
  
  ; Callbacks... MUST be outside Start/StopDrawing() so callback can involve drawing.
  If uGridCallbackFlag
    If (Flag & #RD_HiLtB) : uGridCallback(GadNum,#uGridEvent_DeSelect,0,*P): EndIf
    If (Flag & #RD_HiLtC) : uGridCallback(GadNum,#uGridEvent_SelecT,0,*P) : EndIf
    If (Flag & #RD_Image) : uGridCallback(GadNum,#uGridEvent_CellImageFlip,*CellDat\CellFlags & #uGrid_CellToggle,*P) : EndIf 
  EndIf
  
  With *CellDat
    If StartDrawing(CanvasOutput(GadNum))
        DrawingFont(\CellFontID) 
        q$ = \CellContent
        If Flag & #RD_Image   ;{- Redraw an Image cell
          ; Two images are available, selected by \CellFlag & #uGrid_CellToggle
          If \CellFlags & #uGrid_CellToggle
            DrawImage(ImageID(\CellImage[1]),\CellX-2,\CellY-2)
          Else
            DrawImage(ImageID(\CellImage[0]),\CellX-2,\CellY-2)
          EndIf
          ;}
        EndIf           
        If Flag & #RD_Text    ;{- Clear cell and draw text
          
          ; Draw empty cell (Leave highlight in place)
          If \CellType & #uGrid_CellList                         ; List cell
            Box(\CellX , \CellY-1, \CellW - 7, \CellH+2, \CellBackColour)     
            EdSwitch = #False
          Else
            Box(\CellX,\CellY,\CellW,\CellH,\CellBackColour)  ; Normal cell
          EndIf
          
          ; Calculate text offset to suit cell alignment
          T = \CellFlags
          m = 0 
          If T & #uGrid_CellAlignC : m = (\CellW-TextWidth(\CellContent))/2 : EndIf
          If T & #uGrid_CellAlignR : m = (\CellW-TextWidth(\CellContent))   : EndIf
          
          ; Draw text, limited to width of cell
          DrawingMode(#PB_2DDrawing_Transparent)
          While TextWidth(q$) > \CellW
            q$ = Left(q$,Len(q$)-1)
          Wend
          DrawText(\CellX+m,\CellY+\CellTextDY,q$,\CellTextColour)
          ;}
        EndIf
        If (Flag & #RD_HiLtB) ;{- Remove selection box from a cell
          
          If \CellType & #uGrid_CellImageFlip ; Image Flip cell...
            If \CellFlags & #uGrid_CellToggle 
              DrawImage(ImageID(\CellImage[1]),\CellX-2,\CellY-2)
            Else
              DrawImage(ImageID(\CellImage[0]),\CellX-2,\CellY-2)
            EndIf
          Else                                ; Text cell...
            C = \CellBackColour 
            
            ; Remove selection box from cell
            DrawingMode(#PB_2DDrawing_Outlined)
            Box(\CellX-2, \CellY-2, \CellW+4, \CellH+4,C)
            If \CellH > 15
              Box(\CellX-1, \CellY-1, \CellW+2, \CellH+2,C)
            EndIf
            
            ; Remove list cell indicator
            If \CellType & #uGrid_CellList
              DrawingMode(#PB_2DDrawing_Default)
              Box(\CellX + \CellW - 7, \CellY-1, 8, \CellH+2, C)
            EndIf
            
            DestroyCaret_()
          EndIf
          ;}  
        EndIf
        If (Flag & #RD_HiLtC) ;{- Draw selection box on a cell 
          If (\CellType & #uGrid_CellNoEdit) =0   ; ... but not if a no-edit cell
            
            ; Select colour to be used and make Caret
            If \CellType & #uGrid_CellList Or \CellType & #uGrid_CellImageFlip  ; List cell colour
              C = uGrid(EdIndex)\GridListSelectColour
            Else
              C = uGrid(EdIndex)\GridSelectColour ; Text cells
              
              CreateCaret_(WindowID(EdWin),0,1,EdCarH) ; Create a cursor...
              ShowCaret_(WindowID(EdWin))
            EndIf
            
            ; Draw selection box on cell
            DrawingMode(#PB_2DDrawing_Outlined)
            Box(\CellX-2, \CellY-2, \CellW+4, \CellH+4,C)
            If \CellH > 15
              Box(\CellX-1, \CellY-1, \CellW+2, \CellH+2,C)
            EndIf
            
            ; Draw indicator for list selector
            If \CellType & #uGrid_CellList
              DrawingMode(#PB_2DDrawing_Default)
              Box(\CellX + \CellW - 7, \CellY-1, 8, \CellH+2, uGrid(EdIndex)\GridListSelectColour)
              Circle(\CellX + \CellW - 4, \CellY+(\CellH/2),2,#Red)
            EndIf
            
          EndIf
          ;}
        EndIf
        If Flag & #RD_Caret   ;{- Draw the Caret
          T = TextWidth(Left(q$,EdCaretPos))+2
          If T < \CellW
            SetCaretPos_( EdCarX+\CellX+T,EdCarY+\CellY+2+\CellTextDY)     ; Position the cursor
          EndIf
          ;}  
        EndIf
      StopDrawing()
    EndIf
  EndWith
  
  ; Keep Gadget and Cell ID for de-selecting cell.
  LastGadnum = GadNum
  *LastP     = *P  
  
EndProcedure
Procedure uGridService(GadNum)                     ;/ Cell Selection and edit
  
  Protected ReDraw,px,py,cx,cy,lx,rx,*T,*CellDat.CellOptions
  Protected CKey, CMod, Lp$,Rp$,Np$,k$,MPtr,KeyOK,T
  Protected KeepEdCellX,KeepEdCellY,X,Y,Move, GridIndex
  Static *OldT

  ReDraw = 0
  Move = #False
  
  ; Find index of uGrid in table of grids  (-1 if not found)
  GridIndex = uGridGetGridIndex(GadNum)
  
  ; Grid NOT found... this will always be a design error.
  If GridIndex = -1
    MessageRequester("Programming error","uGridService(): Gadget# not found :"+Str(GadNum))
    ProcedureReturn #False
  EndIf
  

  ; Some events need the mouses's CELL X and Y positions... 
  If EventType() & #PB_EventType_LeftDoubleClick | #PB_EventType_LeftButtonDown |#PB_EventType_RightButtonDown |#PB_EventType_MouseMove ;{
    
    ; Get mouse position within working area
    px = GetGadgetAttribute(GadNum,#PB_Canvas_MouseX)
    py = GetGadgetAttribute(GadNum,#PB_Canvas_MouseY)
    
    ; Calculate the CELL column number
    lx = 0 : rx = 00
    For cx = 0 To  uGrid(GridIndex)\GridColCount-1
      rx + uGrid(GridIndex)\GridColW[cx]
      If px>lx And px<rx
        Break 
      EndIf
      lx = rx
    Next
    
    ; Calculate the CELL row number
    If py < (uGrid(GridIndex)\TitleFontH + 5)             ; Title bar
      cy = -1
    Else  
      py - (uGrid(GridIndex)\TitleFontH + 5)              ; Subtract titlebar height
      If uGrid(GridIndex)\GridFlags &  #uGrid_UseAuxH   
        cy = py / uGrid(GridIndex)\ImageCellH
      Else
        cy = py /(uGrid(GridIndex)\GridFontH + 5)   
      EndIf
    EndIf
   ;} 
  EndIf
  
  Select EventType()
    Case #PB_EventType_LeftDoubleClick, #PB_EventType_LeftButtonDown ;{ Left mouse: Grid / Cell selection 
      ;{ Detect user selecting a new GRID
      If GadNum <> EdGrid             ; Change?
        
        ; Tidy up the previous grid
        If EdGrid <> -1    
          uGridRefreshGrid(EdGrid)
        EndIf
        
        ; Check the entry mode is correct (single / double click)
        If EventType() <> uGrid(GridIndex)\GridEditStart 
          ProcedureReturn #False
        EndIf
        
        ; Set up for editing
        EdWin    = EventWindow() 
        EdGrid   = GadNum
        EdIndex  = GridIndex
        EdCellX  = -1                 ; Force cell location later...
        EdSwitch = #True
        
      EndIf
      ;}
      ;{ Detect user selecting a new CELL
      ; Title bar clicked?
      If cy = -1
        uGridCallback(GadNum,#uGridEvent_TitleClick,cx,0)
        ProcedureReturn
      EndIf
      
      ; Make pointer to new target cell structure...
      *T = uGrid(EdIndex)\GridCellPointer + (cy * uGrid(EdIndex)\GridColCount * SizeOf(uG)) + (cx * SizeOf(uG))
      *CellDat.CellOptions = *T  
      
      If *CellDat\CellType & #uGrid_CellNoEdit = 0  ; Check target cell is not barred from selection
        uGridDrawCell(0,0,#RD_HiLtB)                ; Remove the last selection (It may even be on a different grid.)
       
        ; Save new cell co-ords, structure pointer etc
        *EdCell = *T
        EdCellX = cx
        EdCellY = cy
        EdCarX  = GadgetX(GadNum)
        EdCarY  = GadgetY(GadNum)
        EdCarH  = uGrid(EdIndex)\GridFontH
        
        If *CellDat\CellType & #uGrid_CellImageFlip
          ; User clicked an 'Image cell'...
          *CellDat\CellFlags ! #uGrid_CellToggle     ; Flip the image select bit
          EdSwitch  = #False
          DestroyCaret_()
          ReDraw = #RD_Image | #RD_HiLtC             ; Request redraw of Image with Selector box
          While WindowEvent() : Wend
        Else                                         
          ; User clicked on a 'Text cell'...
          EdKeepContent$ = *CellDat\CellContent      ; Keep cell contents for ESC exit restore.
          EdCaretPos = Len(*CellDat\CellContent)
          EdSwitch  = #True
          ReDraw = #RD_Text | #RD_Caret | #RD_HiLtC  ; Request redraw of Text, Caret and Selector box
        EndIf
        
      EndIf
      ;}
      ;}
    Case #PB_EventType_RightButtonDown ;{ Right mouse 
      If uGridCallbackFlag 
        
        If cy = -1 :  ProcedureReturn :  EndIf ; Title bar...
        
        ; Calculate pointer to cell data
        *T = uGrid(GridIndex)\GridCellPointer + (cy * uGrid(GridIndex)\GridColCount * SizeOf(uG)) + (cx * SizeOf(uG))
        *CellDat.CellOptions = *T
        
        ; If an editable cell then Callback
        If Not *CellDat\CellType & #uGrid_CellNoEdit
          uGridCallback(GadNum,#uGridEvent_RightKey,0,*T) 
        EndIf
        
      EndIf
      ;}
    Case #PB_EventType_KeyDown         ;{ Edit and cursor movement keys
      ; CR exits the edit
      ; ESC replaces the original string and exits
      ; Edits are effective keystroke by keystroke 
      
      CKey = GetGadgetAttribute(GadNum,#PB_Canvas_Key)
      CMod = GetGadgetAttribute(GadNum,#PB_Canvas_Modifiers) ; 0,1,4 
      
      *CellDat.CellOptions =  *EdCell
      
      With uGrid(EdIndex)
        Select CMod ; Modifiers (0,1,2,4, None,SHIFT,ALT,CNTRL)
          Case 0,1 ;{ L/R Cursor keys, CR, ESC etc
            If EdSwitch = #True
              Lp$ = Left(*CellDat\CellContent,EdCaretPos)
              Rp$ = Mid( *CellDat\CellContent,EdCaretPos + 1)
              
              ; Text EDIT control keys
              Select CKey
                Case 8  ;{ BS
                  Lp$ = Left(Lp$,Len(Lp$)-1)
                  If EdCaretPos
                    EdCaretPos - 1
                  EndIf
                  *CellDat\CellContent = Lp$ + Rp$
                  ReDraw | #RD_Text | #RD_Caret
                  ;}              
                Case 46 ;{ DEL
                  Rp$=Mid(Rp$,2)
                  *CellDat\CellContent = Lp$ + Rp$
                  ReDraw | #RD_Text | #RD_Caret
                  ;}
                Case 35 ;{ END
                  EdCaretPos = Len(*CellDat\CellContent)
                  Lp$ = *CellDat\CellContent
                  Rp$= ""
                  ReDraw | #RD_Text | #RD_Caret
                  ;}
                Case 36 ;{ HOME
                  EdCaretPos = 0
                  Lp$ = ""
                  Rp$= *CellDat\CellContent
                  ReDraw | #RD_Text | #RD_Caret
                  ;}
                Case 37 ;{ LEFT Cursor
                  If  EdCaretPos
                    EdCaretPos - 1
                    Lp$ = Left(*CellDat\CellContent,EdCaretPos)
                    Rp$ = Mid(*CellDat\CellContent,EdCaretPos + 1)
                  EndIf
                  ReDraw | #RD_Text | #RD_Caret
                  ;}
                Case 39 ;{ RIGHT Cursor
                  If  EdCaretPos < Len(*CellDat\CellContent)
                    EdCaretPos + 1
                    Lp$ = Left(*CellDat\CellContent,EdCaretPos)
                    Rp$ = Mid(*CellDat\CellContent,EdCaretPos + 1)
                  EndIf
                  ReDraw | #RD_Text | #RD_Caret
                  ;}
                Case 13 ;{ CR
                  uGridDrawCell(0,0) ; Remove selection
                  ReDraw | #RD_Text
                  EdSwitch = #False
                  EdCellX  = -1
                  ;}
                Case 27 ;{ ESC
                  *CellDat\CellContent = EdKeepContent$ ; Replace old contents
                  ReDraw | #RD_Text                     ; Request a text redraw
                  uGridDrawCell(0,0)                    ; Remove selection box
                  EdSwitch = #False                     ; Stop edits
                  EdCellX  = -1                         ; Ensure new grid posn..
                  ;}
              EndSelect
              
            Else 
              
              If *CellDat\CellType & #uGrid_CellList ; List cell?...
                Select CKey
                  Case 40 ;{ Up Cursor
                    
                    k$ = UCase(*CellDat\CellContent)           ; Current content of cell
                    T = FindField(*CellDat\CellListString,k$,"|")
                    If T>1 
                      T-1
                      *CellDat\CellContent = StringField(*CellDat\CellListString,T,"|")
                      ReDraw = #RD_Text
                    EndIf
                    ;}
                  Case 38 ;{ Down Cursor
                    k$ = UCase(*CellDat\CellContent)              ; Current content of cell
                    If k$=""
                      T = 0
                    Else
                      T = FindField(*CellDat\CellListString,k$,"|")
                    EndIf
                    
                    If T < CountString(*CellDat\CellListString,"|")
                      T+1
                      *CellDat\CellContent = StringField(*CellDat\CellListString,T,"|")
                      ReDraw = #RD_Text 
                    EndIf
                    ;}
                EndSelect
              EndIf
              
            EndIf
            ;}
          Case 4   ;{ CNTRL C/V/X and CNTRL Left/Right/Up/Down Cursor keys
            MPtr = 0
            KeepEdCellX = EdCellX ; Keep pointers in case we cannot go
            KeepEdCellY = EdCellY ; to a cell.
            
            Select CKey
                ;- Copy, Paste and Cut
              Case 'C'
                \GEP = *CellDat\CellContent
                
              Case 'V'
                *CellDat\CellContent = \GEP
                EdCaretPos = Len(*CellDat\CellContent)
                ReDraw | #RD_Text | #RD_Caret
                
              Case 'X'
                \GEP = *CellDat\CellContent
                *CellDat\CellContent = ""
                EdCaretPos = 0
                ReDraw | #RD_Text | #RD_Caret
                
                ; Grid navigation with CNTRL + cursor keys
              Case '%'      ;- Cursor Left
                X = EdCellX - 1                         ; Current cell 'X' position
                MPtr = - SizeOf(CellOptions)            ; Cell data pointer step size
                While X > - 1                           ; 
                  *CellDat.CellOptions = *EdCell + MPtr 
                  If *CellDat\CellType & #uGrid_CellNoEdit = 0; If we CAN go there..
                    EdCellX = X                         ; Adjust X position
                    Move = #True                        ; Set flag to force move,
                    Break                               ; Done...
                  EndIf
                  X - 1                                 ; Move test position left one cell
                  MPtr - SizeOf(CellOptions)            ; and data test pointer one cell prior
                Wend
                
              Case Asc("'") ;- Cursor Right
                X = EdCellX + 1
                MPtr = SizeOf(CellOptions)
                While X < \GridColCount
                  *CellDat.CellOptions = *EdCell + MPtr
                  If *CellDat\CellType & #uGrid_CellNoEdit = 0 
                    EdCellX = X
                    Move = #True
                    Break
                  EndIf
                  MPtr + SizeOf(CellOptions)
                  X + 1
                Wend
                
              Case '&'      ;- Cursor Up
                Y = EdCellY - 1
                MPtr = -(SizeOf(CellOptions) * (\GridColCount))
                While Y > -1
                  *CellDat.CellOptions = *EdCell + MPtr
                  If *CellDat\CellType & #uGrid_CellNoEdit = 0
                    EdCellY = Y
                    Move = #True
                    Break
                  EndIf
                  MPtr - (SizeOf(CellOptions) * (\GridColCount))
                  Y - 1
                Wend
                
              Case '('      ;- Cursor Down
                Y = EdCellY + 1
                MPtr = (SizeOf(CellOptions) * (\GridColCount))
                While Y < \GridRowCount
                  *CellDat.CellOptions = *EdCell + MPtr
                  If *CellDat\CellType & #uGrid_CellNoEdit = 0 
                    EdCellY = Y
                    Move = #True
                    Break
                  EndIf
                  MPtr + (SizeOf(CellOptions) * (\GridColCount))
                  Y + 1
                Wend
                
            EndSelect
            
            ; Move to new cell...
            If Move                                       ; If moving is OK...
              uGridDrawCell(0,0)                          ; Clear prior selection
              *EdCell + MPtr                              ; Set new cell structure pointer
              *CellDat.CellOptions = *EdCell
              
              ; Save new cell co-ords, structure pointer etc...
              EdCellX = *CellDat\CellGX ; cx
              EdCellY = *CellDat\CellGY ; cy
              EdCarH  = uGrid(uGridGetGridIndex(GadNum))\GridFontH
              EdCarX  = GadgetX(GadNum)
              EdCarY  = GadgetY(GadNum)
              
              If *CellDat\CellType & #uGrid_CellImageFlip
                ; User moved to an 'Image cell'...
                EdSwitch  = #False
                ReDraw =  #RD_HiLtC                        ; Request redraw of Image with Selector box
                While WindowEvent() : Wend
              Else                                         
                ; User moved to a 'Text cell'...
                EdKeepContent$ = *CellDat\CellContent      ; Keep cell contents for ESC exit restore.
                EdCaretPos = Len(*CellDat\CellContent)
                EdSwitch  = #True
                ReDraw = #RD_Text | #RD_Caret | #RD_HiLtC  ; Request redraw of Text, Caret and Selector box
              EndIf
              
            EndIf
          ;}
        EndSelect
      EndWith
      ;}
    Case #PB_EventType_Input           ;{ Text input keys
      If EdSwitch = #True 
        
        CKey = GetGadgetAttribute(GadNum,#PB_Canvas_Input)  ; Get user key input
        Np$ = Chr(CKey)                                     ; New text from pressed key
        *CellDat.CellOptions = *EdCell                      
        
        ; Character filters...
        KeyOK = #True
        Select *CellDat\CellType & %000011111111 
          Case #uGrid_CellDefault  ; No restrictions
          Case #uGrid_CellNoEdit  : KeyOK = #False
          Case #uGrid_CellUcase   : Np$ = UCase(Np$)
          Case #uGrid_CellLCase   : Np$ = LCase(Np$) 
          Case #uGrid_CellNumOnly 
            If CKey<'0' Or CKey>'9' : KeyOK = #False :  EndIf       ; Allow numbers only and
            If EdCaretPos = 0 And Np$ = "-" : KeyOK = #True : EndIf ; allow '-' as first character
          Case #uGrid_CellFloat
            If CKey<'0' Or CKey>'9' : KeyOK = #False :  EndIf       ; Allow numbers only and
            If EdCaretPos = 0 And Np$ = "-" : KeyOK = #True : EndIf ; allow '-' as first character
            If CKey = '.' And FindString(*CellDat\CellContent,".",1)=0 : KeyOK = #True : EndIf ; and just one '.'
          Case #uGrid_CellHexOnly 
            k$ = UCase(Chr(CKey))
            If Not ((k$ >="0" And k$ <="9") Or (k$ >= "A" And k$ <= "F"))
              KeyOK = #False
            Else
              Np$ = k$
            EndIf 
        EndSelect
        
        ; Build/modify string for CELL
        If KeyOK = #True  
         uGridCallback(GadNum,#uGridEvent_CellChar,CKey,*EdCell)
          
          
          Lp$ = Left(*CellDat\CellContent,EdCaretPos)    ; Text to left of caret.
          Rp$ = Mid(*CellDat\CellContent,EdCaretPos + 1) ; Text to right of caret.
          k$ = Lp$ + Np$ + Rp$                           ; join them all back together 
          If Len(k$) <= *CellDat\CellMaxChars            ; If the text will fit in the cell...
            *CellDat\CellContent =  k$                   ; Save text,
            EdCaretPos + 1                               ; move caret one char right and
            ReDraw | #RD_Text  | #RD_Caret               ; set flags to redraw the cell on the CanvasGadget().
          Else
            ReDraw = 0
          EndIf
          
        EndIf
        
      EndIf
      
      ;}  
    Case #PB_EventType_LostFocus       ;{ Grid Lost focus
      If uGridCallbackFlag
        uGridCallback(EdGrid,#uGridEvent_GridLostFocus,0,*EdCell)
      EndIf
      
      uGridDrawCell(0,0) ; Clear select box
      EdSwitch = 0       ; No more edits
      EdCellX  = -1      ; Force re-discovery
      ;}
    Case #PB_EventType_MouseMove       ;{ Cursor movement. Reports to uGridCallback()
      If EventGadget() = EdGrid
        If cy > -1
          
          ; Safety check on max X and Y... 'cos gadget may be oversized
          If cy < uGrid(EdIndex)\GridRowCount  And cx < uGrid(EdIndex)\GridColCount And cx>-1
            
            ; Calculate the cell data address pointer
            *T = uGrid(EdIndex)\GridCellPointer
            *T + (cy * uGrid(EdIndex)\GridColCount * SizeOf(uG))
            *T + (cx * SizeOf(uG))
            
            ; Decide when to report a new cell
            If *T <> *OldT
              *OldT = *T
              uGridCallback(GadNum,#uGridEvent_CellXY,0,*T)
            EndIf
            
          EndIf
          
        EndIf
        
      EndIf
      ;}
  EndSelect
  
  ;Redraw the cell contents
  If ReDraw   
    uGridDrawCell(EdGrid,*EdCell,ReDraw)
  EndIf

EndProcedure 
Procedure uGridGetCellPtr(GadNum,Col.i,Row.i)      ; Return the address of a Cell's structure for a uGridGadget/Col/Row
  Protected *P, n
 
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum)
  
  ; Check grid and limits... development stage check
  If n >-1 
    If Col<0 Or Col>uGrid(n)\GridColCount Or Row<0 Or Row > uGrid(n)\GridRowCount
      MessageRequester("Error","Cell("+Str(Col)+") Or Row("+Str(Row)+") is out of bounds")
      *P = 0
    Else
      *P = uGrid(n)\GridCellPointer
      *P + (Row * uGrid(n)\GridColCount * SizeOf(uG))
      *P + (Col * SizeOf(uG))
    EndIf
  Else
    MessageRequester("Error","Gadget("+Str(GadNum)+") is out of bounds")
  EndIf

  
  ProcedureReturn *P
EndProcedure
Procedure uGridEnableCallback(Flag)
  uGridCallbackFlag = Flag
EndProcedure
Procedure uGridGetFlipImageNum(GadNum,cx,cy,state) ; Return the Image# for CellImageFlip() defined by 'state' (0/1)
  Protected *P, *CellDat.CellOptions
  *P = uGridGetCellPtr(GadNum,cx,cy)
  If *P
    *CellDat.CellOptions = *P
    If *CellDat\CellType & #uGrid_CellImageFlip
      ProcedureReturn *CellDat\CellImage[state & 1]
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure
Procedure uGridSetFlipImageState(GadNum,cx,cy,state) ; Set the Image# for CellImageFlip() defined by 'state' (0/1)
  Protected *P, *CellDat.CellOptions
  *P = uGridGetCellPtr(GadNum,cx,cy)
  If *P
    *CellDat.CellOptions = *P
    If *CellDat\CellType & #uGrid_CellImageFlip
      If state & 1
        *CellDat\CellFlags | #uGrid_CellToggle
      Else
        *CellDat\CellFlags & ($FFFF ! #uGrid_CellToggle)
      EndIf
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure
Procedure uGridSetCellData(GadNum,cx,cy,D.i)       ; Save an integer data value at the specified cell.
  Protected *P, *CellDat.CellOptions
  *P = uGridGetCellPtr(GadNum,cx,cy)
  If *P
    *CellDat.CellOptions = *P
    *CellDat\CellData = D
  EndIf
EndProcedure
Procedure uGridGetCellData(GadNum,cx,cy)           ; Return integer data value saved with uGridSetCellData()
  Protected *P, *CellDat.CellOptions
  *P = uGridGetCellPtr(GadNum,cx,cy)
  If *P
    *CellDat.CellOptions = *P
    ProcedureReturn *CellDat\CellData
  EndIf
EndProcedure
Procedure uGridSetCellMaxChars(GadNum,cx,cy,cw,ch,CharNum) ; Set maximum number of characters allowed in a block of cells.
  Protected *P, *CellDat.CellOptions
  Protected n,X,Y,Y2,X2
  
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum)
  
  If n> -1
    
    ; Option to set X/Y range to full width/height
    If cy = 0 And ch=-1 : ch = uGrid(n)\GridRowCount : EndIf
    If cx = 0 And cw=-1 : cw = uGrid(n)\GridColCount : EndIf
    
    ; Check and apply limits
    Y2 = cy+ch-1 : If Y2 >  uGrid(n)\GridRowCount-1 : Y2 =  uGrid(n)\GridRowCount-1 : EndIf
    X2 = cx+cw-1 : If X2 >  uGrid(n)\GridColCount-1 : X2 =  uGrid(n)\GridColCount-1 : EndIf
    
    ; Set cell flags
    For Y = cy To Y2
      For X = cx To X2              
        *P = uGridGetCellPtr(GadNum,X,Y)
        If *P 
          *CellDat.CellOptions = *P
          *CellDat\CellMaxChars = CharNum
        EndIf
      Next
    Next
    
  EndIf
  
EndProcedure
Procedure uGridSetCellList(GadNum,cx,cy,cw,ch,ListString.s) ; Set option strings for a block of list cells
Protected *P, *CellDat.CellOptions
Protected n,X,Y,Y2,X2
 
  ; Find index of uGrid in grid table (-1 if not found)
n = uGridGetGridIndex(GadNum) 

If n >-1
  
  ; Option to set X/Y range to full width/height
  If cy = 0 And ch=-1 : ch = uGrid(n)\GridRowCount : EndIf
  If cx = 0 And cw=-1 : cw = uGrid(n)\GridColCount : EndIf
  
  ; Check and apply limits
  Y2 = cy+ch-1 : If Y2 >  uGrid(n)\GridRowCount-1 : Y2 =  uGrid(n)\GridRowCount-1 : EndIf
  X2 = cx+cw-1 : If X2 >  uGrid(n)\GridColCount-1 : X2 =  uGrid(n)\GridColCount-1 : EndIf
  
  ; Set cell flags
  For Y = cy To Y2
    For X = cx To X2              
      *P = uGridGetCellPtr(GadNum,X,Y)
      If *P 
        *CellDat.CellOptions    = *P
        *CellDat\CellType       = #uGrid_CellList
        *CellDat\CellListString = ListString
      EndIf
    Next
  Next
  
EndIf

EndProcedure
Procedure uGridSetCellHelp(GadNum,cx,cy,cw,ch,HelpString.s) ; Set 'Help' string for a cell / block-of-cells
  Protected *P, *CellDat.CellOptions
  Protected n,X,Y,Y2,X2
  
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum) 
  
  If n >-1 
    
    ; Option to set X/Y range to full width/height
    If cy = 0 And ch=-1 : ch = uGrid(n)\GridRowCount : EndIf
    If cx = 0 And cw=-1 : cw = uGrid(n)\GridColCount : EndIf
    
    ; Check and apply limits
    Y2 = cy+ch-1 : If Y2 >  uGrid(n)\GridRowCount-1 : Y2 =  uGrid(n)\GridRowCount-1 : EndIf
    X2 = cx+cw-1 : If X2 >  uGrid(n)\GridColCount-1 : X2 =  uGrid(n)\GridColCount-1 : EndIf
    
    ; Set cell flags
    For Y = cy To Y2
      For X = cx To X2              
        *P = uGridGetCellPtr(GadNum,X,Y)
        If *P 
          *CellDat.CellOptions = *P
          *CellDat\CellHelp    = HelpString
        EndIf
      Next
    Next
    
  EndIf
  
EndProcedure
Procedure.s uGridGetCellHelp(GadNum,cx,cy)         ; Get 'Help' string for a cell
  Protected *P, *CellDat.CellOptions
  
  *P = uGridGetCellPtr(GadNum,cx,cy) 
  If *P
    *CellDat.CellOptions = *P
    ProcedureReturn *CellDat\CellHelp
  EndIf
  ProcedureReturn ""
  
EndProcedure
Procedure uGridRefreshGrid(GadNum)                 ; Re-draw the visible grid area
  
  Protected n,*P,*CellDat.CellOptions,Y,X,T,m
  
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum) 
  
  ; uGridGadget() NOT found
  If n = -1
    MessageRequester("Error","GridRefresh() Gadget# not found ")
    ProcedureReturn #False
  EndIf
  
  If StartDrawing(ImageOutput(uGrid(n)\GridDataImage))
      
      ; Draw backdrop... grid lines etc
      DrawImage(ImageID(uGrid(n)\GridBackImage),0,0)
      
      ; Draw text in CELLs...
      DrawingMode(#PB_2DDrawing_Transparent)
      *P = uGrid(n)\GridCellPointer
      For Y = 0 To uGrid(n)\GridRowCount - 1
        For X = 0 To uGrid(n)\GridColCount - 1
          
          *CellDat.CellOptions = *P
          With *CellDat
            
            If \CellType & #uGrid_CellImageFlip ; Image cell...
              
              ; Two images are available, defined by \CellFlag & #uGrid_CellToggle
              T = 0 : If \CellFlags & #uGrid_CellToggle : T = 1 : EndIf
              DrawImage(ImageID(\CellImage[T]),\CellX-2,\CellY-2)
              
            Else ; Text cell...
              Box(\CellX-2,\CellY-2,\CellW+4,\CellH+4,\CellBackColour)
              
              ; Calculate text offset to suit cell alignment
              DrawingFont(\CellFontID)
              T = \CellFlags
              m = 0 
              If T & #uGrid_CellAlignC : m = (\CellW-TextWidth(\CellContent))/2 : EndIf
              If T & #uGrid_CellAlignR : m = (\CellW-TextWidth(\CellContent))   : EndIf
              
              ; Draw the text
              DrawText(\CellX+m,\CellY+\CellTextDY,\CellContent,\CellTextColour) 
            EndIf
            
          EndWith
          
          *P + SizeOf(uG)  
        Next
      Next
      
    StopDrawing()
    
    If StartDrawing(CanvasOutput(uGrid(n)\GridPBNum)) 
        DrawImage(ImageID(uGrid(n)\GridDataImage),0,0)
      StopDrawing()
    EndIf
    
  EndIf

EndProcedure
Procedure uGridClearCell(GadNum,cx,cy,cw,ch)       ; Clear a cell \ range of cells
  Protected *P, *CellDat.CellOptions
  Protected n,X,Y,Y2,X2
  
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum) 
  
  If n >-1
    
    ; Option to set X/Y range to full width/height
    If cy = 0 And ch=-1 : ch = uGrid(n)\GridRowCount : EndIf
    If cx = 0 And cw=-1 : cw = uGrid(n)\GridColCount : EndIf
    
    ; Check and apply limits
    Y2 = cy+ch-1 : If Y2 >  uGrid(n)\GridRowCount-1 : Y2 =  uGrid(n)\GridRowCount-1 : EndIf
    X2 = cx+cw-1 : If X2 >  uGrid(n)\GridColCount-1 : X2 =  uGrid(n)\GridColCount-1 : EndIf
    
    ; Set cell flags
    StartDrawing(CanvasOutput(GadNum))
      For Y = cy To Y2
        For X = cx To X2              
          *P = uGridGetCellPtr(GadNum,X,Y)
          If *P 
            *CellDat.CellOptions = *P
            With *CellDat
              If \CellType & #uGrid_CellImageFlip = 0                           ; If NOT an image cell...
                \CellContent = ""                                               ; Clear cell contents in structure
                Box(\CellX,\CellY,\CellW,\CellH,\CellBackColour)                ; Erase visible screen cell 
                If \CellGX = EdCellX And \CellGY = EdCellY  And GadNum = EdGrid ; If cell is current selected cell...
                  EdCaretPos = 0                                                ; move caret to 'home' 
                  SetCaretPos_( EdCarX+\CellX+2,EdCarY+\CellY+2)
                EndIf
              EndIf
            EndWith
          EndIf
        Next
      Next
    StopDrawing()
    
  EndIf
 
EndProcedure
Procedure uGridWriteCellText(GadNum,cx,cy,text.s)  ; Write text to a specific CELL structure at co-ords cx,cy
  Protected *P,*CellDat.CellOptions 
  
  *P = uGridGetCellPtr(GadNum,cx,cy)
  If *P 
    *CellDat.CellOptions = *P
    *CellDat\CellContent = text
    uGridDrawCell(GadNum,*P,#RD_Text)
  EndIf
EndProcedure
Procedure.s uGridReadCellText(GadNum,cx,cy)        ; Read text from a specific GRID at CELL co-ords cx,cy
  Protected *P,*CellDat.CellOptions
  
  *P = uGridGetCellPtr(GadNum,cx,cy)
  If *P 
    *CellDat.CellOptions = *P
    ProcedureReturn *CellDat\CellContent
  EndIf
EndProcedure
Procedure uGridSetCellType(GadNum,cx,cy,cw,ch,Flag,FlagSwitch=#True) ; Set CELL type for a range X,Y,W,H
  
  ; Specify the range of cells in conventional X,Y,W,H format.
  ; Set cw and ch to 1 to set the FLAGS of a single cell at cx, cy
  ; To specify whole column(s) set cy as 0 and ch as -1
  ; To specify whole row(s) set cx as 0 and cw as -1
  
  Protected X,Y,X2,Y2,*CellDat.CellOptions,*P,n,C,T
  
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum) 
  
  If n >-1
    ; Option to set X/Y range to full width/height
    If cy = 0 And ch=-1 : ch = uGrid(n)\GridRowCount : EndIf
    If cx = 0 And cw=-1 : cw = uGrid(n)\GridColCount : EndIf
    
    ; Check and apply limits
    Y2 = cy+ch-1 : If Y2 >  uGrid(n)\GridRowCount-1 : Y2 =  uGrid(n)\GridRowCount-1 : EndIf
    X2 = cx+cw-1 : If X2 >  uGrid(n)\GridColCount-1 : X2 =  uGrid(n)\GridColCount-1 : EndIf
    
    ; Adjust cell flags
    For Y = cy To Y2
      For X = cx To X2              
        *P = uGridGetCellPtr(GadNum,X,Y) ; Get pointer to cell structure
        
        If *P 
          *CellDat.CellOptions = *P
          
          With *CellDat
            If FlagSwitch
              \CellType | Flag
            Else
              \CellType = \CellType & (Flag ! $FFFF)
            EndIf
            
            ; For image cells create a pair of default images 
            If \CellType & #uGrid_CellImageFlip
              C = RGB(220,255,220)
              For T = 0 To 1
                If \CellImage[T] = 0
                  \CellImage[T] = CreateImage(#PB_Any,\CellW+4,\CellH+4) ;+4? Images FILL cell, including selection box area
                  If StartDrawing(ImageOutput(\CellImage[T]))
                      Box(0,0,\CellW+4,\CellH+4,C)
                    StopDrawing()
                  EndIf
                EndIf
                C = RGB(255,220,220)
              Next
            EndIf
            
          EndWith
        EndIf
        
      Next
    Next
    
  EndIf
  
EndProcedure
Procedure uGridSetCellColour(GadNum,cx,cy,cw,ch,FCol=-1,BCol=-1) ; Set Front and Backcolour for a range of cells
  
  ; Specify the range of cells in conventional X,Y,W,H format.
  ; Set cw and ch to 1 to colour a single cell at cx, cy
  ; Specify the colours or use -1,-1 to use defaults.
  ; To specify whole column(s) set cy as 0 and ch as -1
  ; To specify whole row(s) set cx as 0 and cw as -1
  
  Protected X,Y,X2,Y2,*P,*CellDat.CellOptions,n
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum) 
  
  If n >-1
    
    ; Option to use default colours
    If FCol = -1 : FCol= uGrid(n)\GridTextColour     : EndIf
    If BCol = -1 : BCol= uGrid(n)\GridTextBackColour : EndIf
    
    ; Option to set X/Y range to full width/height
    If cy = 0 And ch=-1 : ch = uGrid(n)\GridRowCount : EndIf
    If cx = 0 And cw=-1 : cw = uGrid(n)\GridColCount : EndIf
    
    ; Check and apply limits
    Y2 = cy+ch-1 : If Y2 >  uGrid(n)\GridRowCount-1 : Y2 =  uGrid(n)\GridRowCount-1 : EndIf
    X2 = cx+cw-1 : If X2 >  uGrid(n)\GridColCount-1 : X2 =  uGrid(n)\GridColCount-1 : EndIf
    
    ; Adjust specified cells
    For Y = cy To Y2
      For X = cx To X2              
        *P = uGridGetCellPtr(GadNum,X,Y)
        If *P 
          *CellDat.CellOptions = *P
          If StartDrawing(ImageOutput(uGrid(n)\GridDataImage))
              With *CellDat
                \CellTextColour = FCol
                \CellBackColour = BCol
              StopDrawing()
            EndWith
          EndIf
        EndIf
      Next
    Next
    
    ; Re-draw the grid
    uGridRefreshGrid(GadNum)
  EndIf
  
EndProcedure
Procedure uGridSwapRowContents(GadNum,Y1,Y2,SwapData=#False)     ; Swap row contents and optionally the CellData values. 
  Protected m,n,*P1,*P2,*P3,Pitch,Q,ContOffset
  
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum) 
  
  If n >-1
    
    Pitch = uGrid(n)\GridColCount * SizeOf(uG)               ; Size of one line of data/pointers
    ContOffset = OffsetOf(CellOptions\CellContent) 
    SwapData & %001
    
    Repeat
      
      *P1 = uGrid(n)\GridCellPointer + (Y1*Pitch) + ContOffset ; Pointer to first contents cell on line Y1...
      *P2 = uGrid(n)\GridCellPointer + (Y2*Pitch) + ContOffset ; and Y2
      *P3 = @Q ; an integer
      
      For m = 0 To uGrid(n)\GridColCount -1 
        CopyMemory(*P1,*P3,SizeOf(Q))
        CopyMemory(*P2,*P1,SizeOf(Q))
        CopyMemory(*P3,*P2,SizeOf(Q))
        *P1 + SizeOf(uG)
        *P2 + SizeOf(uG)
      Next
      
      ContOffset = OffsetOf(CellOptions\CellData)
      
      SwapData -1 
    Until SwapData = -1
    
  EndIf
  
EndProcedure
Procedure uGridSort(GadNum,ColNum,SortOrder=#False) ; Sort the data, selected by column title click.
  
  Protected n, GridH,X,Y,SType,NumCol,*CellDat.CellOptions
  Protected First,m,StepDir,T,u,SwapVal,k$,Empty
  
  
  ; Find index of uGrid in grid table (-1 if not found)
  n = uGridGetGridIndex(GadNum) 
  
  If n = -1 : ProcedureReturn : EndIf
  
  ; Determine the size of the grid
  GridH = uGrid(n)\GridRowCount       ; get the number of rows,
  NumCol= uGrid(n)\GridColCount       ; and columns.
  SortOrder & 1   
  
  ; Determine the column's variable type.
  X = ColNum                                          ; Column number (X? lazy typist!)
  *CellDat.CellOptions =  uGridGetCellPtr(GadNum,X,0) ; Get pointer for top cell in column (Assumes all of col is the same!)
  SType = *CellDat\CellType &  %000001111100          ; Get the cell type flags
  
  ; Set up sort parameters
  If SortOrder
    First = 0         : StepDir = 1  : u = 1
  Else  
    First = GridH -1  : StepDir = -1 : u = -1
  EndIf
  
  ; Perform the sort on the stored grid data... this does NOT update the display
  SwapVal = #True
  While SwapVal
    SwapVal = #False
    n = First
    For m = 1 To GridH - 1
      T = #False
      Select SType
          Case #uGrid_CellUcase   : If uGridReadCellText(GadNum,X,n)         > uGridReadCellText(GadNum,X,n+u)         : T = #True : EndIf ; UCASE
          Case #uGrid_CellLCase   : If uGridReadCellText(GadNum,X,n)         > uGridReadCellText(GadNum,X,n+u)         : T = #True : EndIf ; LCASE
          Case #uGrid_CellNumOnly : If Val(uGridReadCellText(GadNum,X,n))    > Val(uGridReadCellText(GadNum,X,n+u))    : T = #True : EndIf ; Integers
          Case #uGrid_CellHexOnly : If Val("$"+uGridReadCellText(GadNum,X,n))> Val("$"+uGridReadCellText(GadNum,X,n+u)): T = #True : EndIf ; Hex     
          Case #uGrid_CellFloat   : If ValF(uGridReadCellText(GadNum,X,n))   > ValF(uGridReadCellText(GadNum ,X,n+u))  : T = #True : EndIf ; Float 
          Default                 : If uGridReadCellText(GadNum,X,n)         > uGridReadCellText(GadNum,X,n+u)         : T = #True : EndIf ; Not specified
      EndSelect
      If T 
        uGridSwapRowContents(GadNum,n,n+u)
        SwapVal = #True
      EndIf
      n + StepDir 
    Next
  Wend
  
  ; Remove blank lines from top of display. This can be complicated by the
  ; presence of negative numeric values or partially occupied lines so
  ; after many false starts I cracked the peanut with a sledge hammer!
  
  For Y = 0 To GridH-1  ; Scan the grid,
    
    Empty = #True       ; scan a line to see if ALL cols are empty,
    For X = 0 To NumCol-1
      If Trim(uGridReadCellText(GadNum,X,Y))
        Empty = #False
      EndIf 
    Next
    
    If Empty            ; find an occupied row further down,
      For m = Y To GridH-1
        For X = 0 To NumCol-1
          If Trim(uGridReadCellText(GadNum,X,m)) ; Not empty so...
            uGridSwapRowContents(GadNum,m,Y)     ; swap row with the empty one
            Break 2
          EndIf 
        Next
      Next
    EndIf
    
  Next
  
  ; Make the changes visible.
  uGridRefreshGrid(GadNum)  
  
EndProcedure
Procedure uGridGadget(GadNum.i,gX,Gy,width,height,ColTitles.s,RowCount,flags) ; Create a new MicroGrid
  ; Syntax
  ; GadNum       MicroGrid gadget number or #PB_Any.
  ; X,Y          Grid position
  ; Width,Height Size of grid
  ; Titles.s     Number of columns defined by the number of title elements
  ;              Column titles have '|' separators. 
  ;              The column widths are defined by the appended value [Width]
  ; RowCount     Number of rows in Grid. ALL MUST BE VISIBLE.
  
  Protected Result = 0, *P,*CellDat.CellOptions,T,cx,cy,px,py,Pl,Pr,n,k$,X,Y
  Protected ColCount = CountString(ColTitles,"|")
  
  ; Create storage for 2nd and later grids
  If GridCount > 1
    Redim uGrid(GridCount)        
  EndIf
  
  ; Create memory block for CELL data
  *P = AllocateMemory(SizeOf(uG) * ColCount * RowCount) 
  If *P = 0 : ProcedureReturn 0 : EndIf
  
  ; Save essential data of the new GRID
  With uGrid(GridCount)
    \GridWin         = GetActiveWindow()
    \GridCellPointer = *P
    \GridColCount    = ColCount
    \GridRowCount    = RowCount
    \GridFlags       = flags
    
    ; Set default grid, cell,cursor and font colours
    \GridTitleBackColour= uGridDefaults\TitleBackColour
    \GridTitleTextColour= uGridDefaults\TitleTextColour
    \GridTextBackColour = uGridDefaults\TextBackColour 
    \GridTextColour     = uGridDefaults\TextColour
    \GridLineColour     = uGridDefaults\LineColour
    \GridSelectColour   = uGridDefaults\SelectColour
    \GridListSelectColour = uGridDefaults\ListSelectColour
    
    ; Click / DClick to start CELL edit
    \GridEditStart   = uGridDefaults\EditStart     
    
    ; Font for Cells
    \GridFont         = uGridDefaults\GridFont
    \GridFontH        = uGridDefaults\GridFontH
    \GridFontNum      = LoadFont(#PB_Any,\GridFont,\GridFontH)
    \GridFontID       = FontID(\GridFontNum)

    
    ; Get true pixel height of for CELLS
    T = CreateImage(#PB_Any,100,100)
    If StartDrawing(ImageOutput(T))
        DrawingFont(\GridFontID)
        \GridFontH = TextHeight("Xy") ; Replace user's value with 'real'
      StopDrawing()
    EndIf
    FreeImage(T)    
    
    \TitleFont    = uGridDefaults\TitleFont
    \TitleFontH   = uGridDefaults\TitleFontH
    \TitleFontNum = LoadFont(#PB_Any,\TitleFont,\TitleFontH)
    \TitleFontID  = FontID(\TitleFontNum)
    
    ; Get true pixel height for TITLE 
    T = CreateImage(#PB_Any,100,100)
    If StartDrawing(ImageOutput(T))
        DrawingFont(\TitleFontID)
        \TitleFontH = TextHeight("Xy") ; Replace user's value with 'real'
      StopDrawing()
    EndIf
    FreeImage(T)
    
    \ImageCellH = uGridDefaults\ImageCellH
    
    ; Parse the column title definitions, save CELL X 
    ; offsets and total GRID width.
    cx = 3 ; Space for border(2)+ gridLine(1)
    For n = 0 To ColCount - 1
      Pl = 1
      k$ = StringField(ColTitles,n+1,"|")
      Pl = FindString(k$,"[",Pl)
      Pr = FindString(k$,"]",Pl)
      \GridColTitle[n] = Left(k$,Pl-1) 
      k$ = Mid(k$,Pl+1,Pr-Pl-1)
      \GridCellX[n] = cx
      \GridColW[n] = Val(k$) + 5 ; 5? Border(2)+GridLine(1)+Border(2)
      cx + \GridColW[n]
    Next
    
    ; Width of whole grid
    \GridPixW = cx-2
    
    ; Each GRID has a block of CELL descriptors stacked in order 
    ; GRID left to right and down the page.
    
    ; Create CELL descriptors table 
    cy = 3 + \TitleFontH + 5      ; Space for title
    For Y = 0 To RowCount-1
      For X = 0 To ColCount-1
        *CellDat.CellOptions = *P
        
        ; Cell type
        *CellDat\CellType = #uGrid_CellDefault
        
        ; Cell X,Y,W,H in pixels
        *CellDat\CellX = \GridCellX[X]
        *CellDat\CellY = cy
        *CellDat\CellW = \GridColW[X]-5
        
        If \GridFlags & #uGrid_UseAuxH  
          *CellDat\CellH = \ImageCellH ; Increased height cell
          *CellDat\CellTextDY = (\ImageCellH - \GridFontH )/2
        Else
          *CellDat\CellH = \GridFontH  ; Normal cell H
          *CellDat\CellTextDY = 0
        EndIf
        
        ; Cell logical X,Y
        *CellDat\CellGX = X
        *CellDat\CellGY = Y
        
        ; Cell colours
        *CellDat\CellTextColour     = \GridTextColour 
        *CellDat\CellBackColour     = \GridTextBackColour
        
        ; Cell character info
        *CellDat\CellFontID         = \GridFontID
        *CellDat\CellMaxChars       = 256 
        *CellDat\CellHelp           = "X="+Str(X)+"  Y="+Str(Y) ; For testing
        
        *P + SizeOf(uG)
        
      Next X
      cy + *CellDat\CellH + 5
    Next Y
    
    ; Height of whole grid
    \GridPixH = cy - 2 
    
    ; Manual sizing option
    If Not \GridFlags & #uGrid_AutoSizeX : \GridPixW = width  : EndIf
    If Not \GridFlags & #uGrid_AutoSizeY : \GridPixH = height : EndIf 
    
    ; Create CanvasGadget()
    T = #PB_Canvas_ClipMouse|#PB_Canvas_Keyboard|#PB_Canvas_DrawFocus|#PB_Canvas_Border
    Result = CanvasGadget(GadNum, gX, Gy, \GridPixW+4,\GridPixH+4,T)
    If GadNum = #PB_Any : GadNum = Result : EndIf
    
    \GridPBNum       = GadNum ; Save the gadget number
    \GridSortOrder   = 0
    ;{ Create Images for rendering backdrop and data
    \GridBackImage = CreateImage(#PB_Any,\GridPixW+2,\GridPixH+2)  
    \GridDataImage = CreateImage(#PB_Any,\GridPixW+2,\GridPixH+2) 
    ;}
    ;{ Draw Gridlines and column titles 
    If StartDrawing(ImageOutput(\GridBackImage))
        DrawingMode(#PB_2DDrawing_Transparent)
        DrawingFont(\TitleFontID)  
        
        ; Backdrop for grid
        Box(0,0,\GridPixW,\GridPixH,\GridTextBackColour)
        
        ; Horizontal lines
        LineXY(0,0,\GridPixW,0,\GridLineColour)   ; Above title
        cy = \TitleFontH + 5
        LineXY(0,cy,\GridPixW,cy,\GridLineColour) ; Under title
        
        *P = \GridCellPointer
        For Y = 0 To RowCount - 1
          *CellDat.CellOptions = *P
          py = *CellDat\CellY + *CellDat\CellH  +2
          LineXY(0,py ,\GridPixW, py, \GridLineColour) ; Under each row
          *P + (SizeOf(uG)* ColCount)
        Next
        
        ; Vertical lines, title box and title
        *P = \GridCellPointer
        For X = 0 To ColCount-1
          *CellDat.CellOptions = *P
          px = \GridCellX[X] - 3                                     ; Grid line is 3 pix left of text area
          LineXY(px,0 ,px,\GridPixH,\GridLineColour)                 ; DrawColumn edge
          T = (\GridColW[X] - TextWidth(\GridColTitle[X]))/2         ; Title offset
          Box(px+1,1,\GridColW[X],\TitleFontH+4,\GridTitleBackColour); Title backdrop
          DrawText(px+T,3,\GridColTitle[X],\GridTitleTextColour)     ; Draw title
          *P + SizeOf(uG)
        Next
        px + \GridColW[ColCount-1]
        LineXY(px,0 ,px,\GridPixH,\GridLineColour)                   ; DrawColumn edge
        
      StopDrawing()
    EndIf
    ;}
    GridCount + 1
    
  EndWith
  uGridRefreshGrid(GadNum)
  
  ProcedureReturn Result
EndProcedure
Procedure uGridDeleteGrid(GadNum)                ; *****  Work in progress****
  Protected Gr
 
  Gr = uGridGetGridIndex(GadNum)  ; Find index of uGrid in grid table (-1 if not found)
  If Gr =-1 : ProcedureReturn 0 : EndIf
  
  ; Ensure associated canvas does not have focus
  With uGrid(Gr)
    FreeImage(\GridBackImage)    ; Free bitmaps
    FreeImage(\GridDataImage)
    ClearStructure(@uGrid(Gr),GRIDOPTIONS); Free any strings associated with GRID
    
    ; For Y ; Free all strings associated with CELLs
      ; For X
    ; 
      ; Next
    ; Next
        
    FreeMemory(\GridCellPointer) ; Free grid data memory
    FreeGadget(\GridPBNum)       ; Destroy Canvas()
  EndWith
  
  ; Move higher table references down
  
  If GridCount > 1; Re-dim table one smaller
    GridCount - 1 ; Decrease number of grids
    Redim uGrid(GridCount)
  EndIf
  
  
EndProcedure
Procedure FindField(String$,Search$,Sep$,CaseFlag=0); Return the field number for 'Search$' in the longer string 'String$'
  ; ASCII only.
  ; Default is to case independent search. Set CaseFlag 'True' to match cases.
  
  Protected n
  
  If FindString(Search$,Sep$)
    MessageRequester("ERROR: FindField()","'Search$' cannot include 'Sep$'")
    ProcedureReturn 0
  EndIf
  
  ; Case independent match...
  If CaseFlag = 0
    String$ = UCase(String$)
    Search$ = UCase(Search$)
  EndIf
  
  ; Compare fields
  For n = 1 To CountString(String$,Sep$) + 1
    If StringField(String$,n,Sep$) = Search$
      ProcedureReturn n
    EndIf
  Next
  
  ProcedureReturn 0
  
EndProcedure

DisableExplicit
; Append test code here...

Re: MicroGrid ~ An entry level editable grid. (Rev 0.5)

Posted: Wed Sep 18, 2013 3:18 pm
by RichardL
Micro-Grid
(a.k.a uGrid)

These notes relate to version 0.94

uGrid is an editable grid written in Pure Basic and based on the CanvasGadget(). Ugrid was written for a main project involving several fixed displays and is not a 'scrollable' grid. This does not prevent it from being used as a window on to a large array of data.

For applications requiring a more comprehensive set of features the author of uGrid commends the products written by Stephen Rodriguez ('srod' on the PB site.)

Micro-Grid Basic features:
- Text may be written to or read from a cell by software means.
- A cell may be selected for editing with a single click, a double click or by software.
- The cell selection may be moved around the grid using the CTRL key in conjunction with the four cursor keys.
- Edits become effective immediately. Use the ESC key to quit anedit and restore it's original contents.
- The range of cells that can be edited may be controlled by setting cell flags on a single cell, a row, column or block of cells.
- The colour of the text and background of a single cell, row, column or block of cells may be changed.
- A cell or block of cells may be restricted to receiving alpha numeric, numeric only (with a leading '-'), hex characters or have letters forced to upper or lower case.
- A cell or block of cells may be specified as an ImageFlipCell with two images associated with each. Clicking the cell toggles between the two images or the cell may be changed by software.
- A column of cells may be sorted in ascending or descending order by clicking on the column title.
- Each cell may have a text string associated with it and the string read back at any time, the foundation for a cell specific 'Help' feature.
- Each cell may have an Integer 'data' value associated with it, useful for storing a cell specific numeric value or a pointer to a cell specific structure.
- CNTRL C will copy the contents of a cell to a scratch-pad.
- CNTRL V will clear a cell and paste the scratch-pad contents.
- CNTRL X clears a cell.
- A callback is accessed when a cell is selected and on other occasions and the uGrid gadget number and a pointer to a structure defining the cell are passed to it. The structure contains the cell contents, it's co-ordinates and other information so user code can make appropriate actions.

Limitations, bugs and work in progress 8th January 2014
- Maximum of 32 columns (Default... can be set higher)
-The current code will edit strings that fit inside a cell and you may set a maximum string length (in characters)
-There is no intention to allow multi line cells... at present.
-The procedure uGridDeleteGadget() is work in progress. Until it is available do NOT create temporary grids repeatedly, develop code using HideWindow() or HideGadget() and reveal them when needed.

NOTE:
Commands with the format uGridxxxxxxxx(GadGet#,cx,cy,cw,ch,xxxxx) relate to adjusting the parameters of one or more cells and the cx,cy,cw,ch parameters relate the the top left, width and height of the block of cells to be adjusted.

There are two special cases that provide a convenient way to make adjustments to a complete column, a complete row or the entire grid.

If 'cx' = 0 and cw= -1 the value of 'ch' is interpreted as the height of the grid.
If 'cy' = 0 and ch = -1 the value of 'cw' is interpreted as the width of the grid.
Iif 'cx' and 'cy' are both 0 and 'cw' and 'ch' are both -1 the whole grid is adjusted.

This currently applies to the following procedures:

uGridSetCellMaxChars(GadNum,cx,cy,cw,ch,CharNum)
uGridSetCellFlags(GadNum,cx,cy,cw,ch,Flag,FlagSwitch=#True)
uGridSetCellColour(GadNum,cx,cy,cw,ch,FCol=-1,BCol=-1)
uGridSetCellList(gadNum,cx,cy,cw,ch,ListString.s)
uGridSetCellHelp(GadNum,cx,cy,cw,ch,HelpString.s)
uGridSetCellType(GadNum,cx,cy,cw,ch,Flag,FlagSwitch=#True)

uGrid Navigation
A cell in a micro-grid may be selected by clicking upon it, causing a selection box to be drawn around the cell.
Selecting an image cell will also cause the image to be toggled between one of two alternatives.
The selection box may be moved around the grid using the cursor up/down/left/right keys in conjunction with the CNTRL key.
Flags may be set to define text cells that may not be edited. These cells cannot be selected by clicking on them. When using the CNTRL key in conjunction with the cursor keys the selection box will jump-over the embargoed cells.

Cell types
Micro-grid provides three types of cell:

- Text cells that may be limited to text, numeric, float or hex input or may be non-editable.

- Image cells that have two states, useful for simulating two state controls.

- List cells that can show one of a number of options specified in a reference string.

The default cell is alpha-numeric and editable.

Individual cells, rows, columns or blocks of text cells may have their type set.
The background and text colour may similarly be changed at any time.


uGridGadget()

Syntax : uGridGadget(#Gadget,x,y,w,h,Titles$,Rows,Flags)

Description: Creates a new uGrid gadget

#Gadget An explicit value or #PB_Any.
x,y The grid co-ordinates
w,h The grid dimensions
Titles$ The titles for the columns as in the following example:
Col1[100]|Col2[80]|........ Last[50]|”
The title of each column is followed by the column width in pixels and a '|' separator.
Rows The number of rows excluding the title row.
Flags Bitwise flags, currently specified as follows:

#uGrid_AutoSizeX causes the 'w' parameter to be ignored and the width is calculated and set automatically.
#uGrid_AutoSizeY causes the 'h' parameter to be ignored and the height is calculated from the number of rows and the size of the font specified.
#uGrid_UseAuxH. If set True this flag causes the cell height to be defined by a fixed value instead of being determined by the height of the grid's font. This allows much higher cells to be created suitable for showing pictures.

Several uGrids may be opened at one time.



uGgridService()

Syntax : uGridService(EventGadget())

Description: Supports the functionality of all the uGridGadget() in an application.

Example :

Code: Select all

XIncludeFile "MicroGrid03.pbi"

OpenWindow(10,0,0,300,300,"Test")

T = #uGrid_AutoSizeX|#uGrid_AutoSizeY
uGridGadget(42,10,10,280,260, "Frequency[70]|Notes[130]| #[30]|",10,T)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
      
    Case #PB_Event_Gadget
      Select EventGadget()
          
          ; 'uGrids' all grouped in order to simplify coding 
        Case 42 To 42 ; First to last uGrid
          uGridService(EventGadget())
          
      EndSelect
  EndSelect
  
ForEver

Procedure uGridCallback(Gad,z1,z2,*Cell)
   ; User's Code here
EndProcedure
    

UgridSetCellColour()

Syntax: uGridSetCellColour(Gadget,cx,cy,cw,ch,FCol=-1,BCol=-1)

Description: Sets the colour of a range of cells.

Gadget The uGridGadget number
cx, cy The coordinates of the top left of the block of cells the be coloured.
cw,ch The size of the block of cells to be coloured.
FCol The foreground colour to be used. (-1 = Default)
BCol The background co0lour to be used. (-1 = Default)

After a call to uGridSetCellColour() the grid is refreshed so changes take immediate effect.


uGridSetCellType()

Syntax : uGridSetCellType(Gadget,cx,cy,cw,ch,Flag,FlagSwitch=#True)

Description: Sets the cell type for a blocks of cells.

Gadget# The uGridGadget number
cx, cy The coordinates of the top left of a block of cells
cw,ch The size of the range of cells
Flag The flag or a combination of flags to be changed.
FlagSwitch If #True (default) the specified flags are set, else the flags are cleared.

Cell type flag values:
#uGrid_CellDefault Alpha/Numeric, mixed case
#uGrid_CellNoEdit Cell data is fixed and cannot be edited
#uGrid_CellUcase Characters are forced to UCASE
#uGrid_CellLCase Characters are forced to LCASE
#uGrid_CellNumOnly Numbers only 0 9 and a leading '-'
#uGrid_CellHexOnly Cells limited to 0 - 9, A - F
#uGrid_CellFloat Numbers only, leading '-' and one '.'
#uGrid_CellList A simple 'option' list with values taken from a reference string.
#uGrid_CellImageFlip A cell that can display either of two defined images.


Text alignment flags (Under threat from over-complication!)
Text default is to left alignment.
#uGrid_CellAlignR Right align text
#uGrid_CellAlignC Centre align text
#uGrid_UseAuxH

uGridReadCellText()

Syntax : uGridReadCellText(Gadget#,cx,cy)

Description: Retrieves the current text from a cell

Gadget# The uGridGadget number
cx,cy Coordinates of cell to be accessed

Return.s The contents of the specified cell

uGridWriteCellText
Syntax : uGridWriteCellText(Gadget#,cx,cy,Text.s)

Description : Writes text to a specified cell

Gadget# The uGridGadget number
cx,cy Coordinates of cell to be written to
Text.s The string to be written to the cell


uGridRefreshGrid()

Syntax: uGridRefreshGrid(Gadget#)

Description: Redraws the current grid excluding the edit box.

Gadget# The uGridGadget number


uGridEnableCallback()

Syntax uGridEnableCallback(#False / #True)

Description: Enables calls to user provided callback

The callback procedure must be included in the user code even if not required. The callback procedure name must be:

uGridCallback(uGridNum,uGridEvent,IParam.i,*uGridCell)

During program execution the procedure will be called each time a specific opertion occurs and the following information is provided:

uGridNum The grid initiating the call
uGridEvent An identifier for the event causing the call. At version 0.94 the following events are signalled:

#uGridEvent_DSelect ; User moved away from cell, time to check his input?
#uGridEvent_Select : A good time to pre-load a cell.
#uGridEvent_GridLostFocus: Refresh grid, write contents elsewhere etc.
#uGridEvent_RightKey ; User clicked on a cell with right mouse button.
#uGridEvent_TitleClick ; User clicked on title bar. IParam contains the col#
#uGridEvent_CellChar : User pressed a key while a text cell was selected.
#uGridEvent_CellXY : The mouse pointer moved to a new cell
#uGridEvent_CellImageFlip : User clicked an image cell and it changed state.

IParam An additional parameter specific to the call.

#uGridEvent_DeSelect : 0
#uGridEvent_Select : 0
#uGridEvent_GridLostFocus : 0
#uGridEvent_RightKey : 0
#uGridEvent_TitleClick : Column 0 to number of columns -1
#uGridEvent_CellChar : Key pressed
#uGridEvent_CellXY : 0
#uGridEvent_CellImageFlip : 0 / NZ to signal the current image option.

*uGridCell A pointer to the Cell structure at the time the call


uGridSelectCell()

Syntax : uGridSetEditCell(Gadget#,cx,cy)

Description: Places the cell select box at the specified position. The cell is then ready to accept immediate user input.

Gadget# The uGridGadget number
cx,cy Coordinates of cell to be selected


uGridSetCellData()

Syntax : uGridSetCellData(Gadget#,cx,cy,d.i)

Description: Stores an Integer value at the specified cell for any purpose required by the user.

Gadget# The uGridGadget number
cx,cy Coordinates of cell to be written to
d Integer value to be written to the cell's data location



uGridGetCellData()

Syntax : d.i = uGridGetCellData(Gadget#,x,y)

Description : Returns the integer value saved with uGridSetCellData()

Gadget# The uGridGadget number
cx,cy Coordinates of cell to return the data value from

Return: The stored data value


uGridSetCellMaxChars()

Syntax : uGridSetCellMaxChars(GadGet#,cx,cy,cw,ch,CharNum)

Description : Sets maximum number of characters allowed in a block of cells

Gadget The uGridGadget number
cx, cy The coordinates of the top left of a block of cells
cw,ch The size of the range of cells
Charnum Maximum number of characters allowed.


uGridClearCell()

Syntax : uGridClearCell(GadNum,cx,cy,cw,ch)

Description : Clear a range of text cells

Gadget The uGridGadget number
cx, cy The coordinates of the top left of a block of cells
cw,ch The range of cells to be cleared


uGridSetCellList()

Syntax: uGridSetCellList(gadNum,cx,cy,cw,ch,ListString.s)

Description: Set a range of cells to have a fixed list of alternative inputs.

The specified cell/s cannot be edited but may receive one of a range of pre-defined cell values selected with the up/down cursor key.

Example snip:

Code: Select all

Days$ = "Sat|Sun|Mon|Tue|Wed|Thu|Fri"
uGridSetCellList(#Gad_Grid1,5,0,1,-1,Days$)

uGridSwapRowContents
Syntax : uGridSwapRowContents(gadNum,Y1,Y2,SwapData=#False)

Description: Exchange the contents of two rows and optionally swap the corresponding CellData values. (See: uGridSetCellData())

The effect of the change does not become visible until uGridRefreshGrid() is called or some other mechanism redraws the grid.

Important note: The row swap is achieved by exchanging the contents of the cell structures between each cell in the two rows. Each structure contains a number of elements and some are swapped and other are not. The following items are swapped.

CellTextColour
CellBackColour
CellFontID
CellImage[2]
CellData
CellContent
CellListString


UgridSort()

Syntax : uGridSort(GadNum,ColNum,SortOrder=#False)

Description: Sort the grid data, selected by column title click.

The grid is sorted in ascending / descending order. After the sort the grid contents are moved up to occupy any blank lines at the top of the display.

The sort takes account of the variable type (text,number,hex,float) as defined by the top element of the column, assuming all elements in a column are of the same type.

The sort and subsequent tidying up use uGridSwapRowContents() so the items listed in the previous description are kept in sync when the column is sorted.


UgridGetFlipImageNum

Syntax : uGridGetFlipImageNum(GadNum,cx,cy,state)

Description: Return the Image# for CellImageFlip() defined by 'state' (0/1)

When a FlipImage cell is created two default images are created and by default coloured light red and light green. The image numbers may be retrieved and the images edited by user code to suit individual requirements.


UgridSetFlipImageState

Syntax : uGridSetFlipImageState(GadNum,cx,cy,state)

Description: Set the Image# for CellImageFlip() defined by 'state' (0/1)

Use this command to switch a FlipImageCell between the two images. The grid will need to be refreshed after changes have been made.

UgridDrawFileImage

Syntax : uGridDrawFileImage(*uGridCell,state,FileName$,NoScale=#False)

Description : Scales an image from a file (.bmp/jpg/pbg) and writes it to the the FlipImage cell identified by a structure pointer. The pointer values may be retrieved with uGridGetCellPtr(). Each cell supports two images (0/1) and the file is written to the image defined by 'State'. The FileName must include the full path and have the appropriate extension.

Code: Select all

  UseJPEGImageDecoder()     ; Use JPG files
  
  FileName$ =  "c:\temp\Image1.jpg" 
  T = uGridGetCellPtr(#Gad_Grid3,2,0)
  uGridDrawFileImage(T,0,FileName$)
The file image is scaled to fit the cell, taking account of the aspect ratios of the cell and the file image. If necessary horizontal or vertical bands will be inserted to prevent distortion of the picture. You may choose to have the file image fill the cell regardless of any aspect ratio distortion by setting 'NoScale' to True.


UgridDrawTextImage()
Syntax : uGridDrawTextImage(GadNum,*uGridCell,state,Text$,NoClear=#True)

Description : Draws a text string on a FlipImage cell. The string is not editable.

The font and font colour used are the same as the grid's normal text cell font.
Multiple lines of text may be drawn by using the '|' symbol to force a new line.
By default the cell is cleared to the grid's background colour before the text is drawn. If 'NoClear' is set True# the cell is not cleared before the text is drawn which allows a caption to be drawn on an image that has been previously loaded.


uGridGetGridIndex()
Syntax : uGridGetGridIndex(GadNum)

Description: Returns index into uGrid.GRIDOPIONS(n) (0 => GridCount-1) or -1 if not found

This command is used to retrieve the index of a specified grid in the list of all the grids in a project. It is heavily used within the uGrid code to access data specific to a grid identified by it's underlying CanvasGadget() number.


Grid Parameters
The following parameters may be set by the user before a MicroGrid is created, their names provide a description of their purpose:

TitleBackColour.i
TitleTextColour.i
TextBackColour.i
TextColour.i
SelectColour.i
LineColour.i
Font.s
FontH.i
EditStart.i

Example snip:

Code: Select all

With uGridDefaults
  \TitleBackColour	= RGB($E1,$F7,$FF)
  \TitleTextColour	= #Black
  \TextBackColour 	= #White 
  \TextColour     	= #Blue
  \SelectColour   	= #Blue
  \LineColour     	= #Red
  \Font           	= "Arial"
  \FontH          	= 12
  \EditStart      	= #PB_EventType_LeftButtonDown  				                ;#PB_EventType_LeftDoubleClick
EndWith
  
k$ = "Mon[35]|Tu[35]|Wed[35]|Thur[35]|Fri[35]|Comments[140]|"
T = #uGrid_AutoSizeX|#uGrid_AutoSizeY
MyGrid3 = uGridGadget(#PB_Any,550,10,400,120,k$,10,T)

Re: MicroGrid ~ An entry level editable grid. (Rev 0.3)

Posted: Wed Sep 18, 2013 3:25 pm
by IdeasVacuum
Thanks for sharing RichardL, looks good 8)

Enumeration 4242? :shock:

Edit: ...perhaps a future version could have a flat border option?

Re: MicroGrid ~ An entry level editable grid. (Rev 0.3)

Posted: Wed Sep 18, 2013 3:41 pm
by Tenaja
Cool; thanks for sharing.

Found a bug, which I was unable to duplicate.
Ran the program (demo presumed).
Edited a few of the values in the lower grid.
Clicked (or double) on the right grid. One of the values I'd entered in the first grid appeared in this one.

Tried to do it again, but could not figure it out.

Re: MicroGrid ~ An entry level editable grid. (Rev 0.3)

Posted: Wed Sep 18, 2013 6:25 pm
by Demivec
Tenaja wrote:Cool; thanks for sharing.

Found a bug, which I was unable to duplicate.
Ran the program (demo presumed).
Edited a few of the values in the lower grid.
Clicked (or double) on the right grid. One of the values I'd entered in the first grid appeared in this one.

Tried to do it again, but could not figure it out.
I did the same thing by making an entry in the first grid then hitting Tab and clicking in the second grid and then typing.

Re: MicroGrid ~ An entry level editable grid. (Rev 0.3)

Posted: Wed Sep 18, 2013 9:49 pm
by RichardL
Hi guys,
Thanks for the comments on the problem caused by the TAB key. PB is following Windoze practice and moving the focus to the next gadget. uGrid sees this as a loss of focus and removes the Select box, kills editing and forces the next uGrid mouse down to discover the cell X/Y. I'm looking for a route for text to be carried over to the next grid selected but (a) it isn't obvious and (b) it is past my bedtime!

Also, I have not been able to replicate the text carry over... if you can replicate it I would be grateful if you would kindly let me have an exact key by key way of making it happen. Thanks.

Oh, and your Windoze version please!

RichardL

Re: MicroGrid ~ Added New SORT feature (Rev 0.6)

Posted: Thu Dec 19, 2013 10:07 am
by RichardL
Hi Folks,
I found a presentational bug with the new uGridSort() feature when negative numbers or partial blank rows are included in the display. The numbers are right but the management of blank lines is wrong. I'm rather busy at the moment but will fix this in a day or so.
RichardL

Re: MicroGrid ~ Added New SORT feature (Rev 0.6)

Posted: Fri Dec 20, 2013 10:19 am
by Kwai chang caine
Very great job, and very usefull 8)
Perhaps a day you can resize the column ????

Thanks a lot for sharing 8)

Re: MicroGrid ~ Added New SORT feature (Rev 0.7)

Posted: Tue Dec 24, 2013 10:24 am
by RichardL
TEST / DEMO CODE FOR REV 0.91/0.93 ~ Now with column sort and BIGGER image cells.

20th January 2014

Hi,
This is the test and demo code for uGrid. I had to split it from the main library because together they totalled over 60,000 characters. Just append it to the library (first posting in this topic) and save and compile together.

RichardL

Code: Select all


CompilerIf #PB_Compiler_IsMainFile
  ; *************************************
  ;            Test code
  ;{ *************************************

  Enumeration 4242
    #Win_Test
    #Gad_Grid1
    #Gad_Grid2
    #Gad_Grid3
    #Gad_Grid4
  EndEnumeration
  Global GadHelp  
  OpenWindow(#Win_Test,0,0,920,535,"MicroGrid Test 0.93",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  AddKeyboardShortcut(#Win_Test,#PB_Shortcut_Tab,2000)
  
  ;- Demo Cell types
  ; Set font and entry mode for the grid we are going to define
  With uGridDefaults
    \EditStart      = #PB_EventType_LeftButtonDown
    \GridFont           = "Arial"
    \GridFontH          = 8
  EndWith
  
  uGridEnableCallback(#True)
  
  ; Define the column Titles and widths
  Titles$ = "No Edit[60]|Numbers[60]|Hex[60]|Float[60]|UCase[60]|LCase[60]|All[60]|List[70]|"
  
  ; Create the grid
  TextGadget(#PB_Any,10,5,200,25,"Cell Types demo")
  uGridGadget(#Gad_Grid1,10,30,0,0, Titles$,10,#uGrid_AutoSizeX|#uGrid_AutoSizeY)
  
  ; Set the column styles
  uGridSetCellType(#Gad_Grid1,0,0,1,-1,#uGrid_CellNoEdit)  ; Cell data is not editable
  ; uGridSetCellFlags(#Gad_Grid1,0,0,1,-1,#uGrid_CellAlignC) ; Cell data is not editable
  uGridSetCellType(#Gad_Grid1,1,0,1,-1,#uGrid_CellNumOnly) ; Numbers only
  uGridSetCellType(#Gad_Grid1,2,0,1,-1,#uGrid_CellHexOnly) ; Hex
  uGridSetCellType(#Gad_Grid1,3,0,1,-1,#uGrid_CellFloat)   ; Float
  uGridSetCellType(#Gad_Grid1,4,0,1,-1,#uGrid_CellUcase)   ; Characters are all UCASE
  uGridSetCellType(#Gad_Grid1,5,0,1,-1,#uGrid_CellLCase)   ; Characters are all LCASE
  uGridSetCellType(#Gad_Grid1,6,0,1,-1,#uGrid_CellDefault) ; Alpha/Numeric Mixed case
  uGridSetCellList(#Gad_Grid1,7,0,1,-1,"Saturday|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|") ; A column of LIST cells
  uGridSetCellMaxChars(#Gad_Grid1,0,0,-1,-1,10)             ; Set all grid to max 10 chars per cell
  
  ; Put some fixed text in column 0
  For n = 0 To 9
    uGridWriteCellText(#Gad_Grid1,0,n,"Row "+Str(n))
  Next
  
  ;- Memory Display demo
  k$ = "Addr[80]|"
  For n = 0 To 15
    k$+Hex(n)+"[26]|"
  Next
  With uGridDefaults
    \GridFont           = "CourierNew"
    \GridFontH          = 12
    \LineColour     = #Blue
  EndWith
  TextGadget(#PB_Any,10,255,200,25,"Hex Display")
  uGridGadget(#Gad_Grid2,10,280,400,120,k$,8,#uGrid_AutoSizeX|#uGrid_AutoSizeY)
  
  GadHelp = TextGadget(#PB_Any,10,285+GadgetHeight(#Gad_Grid2),GadgetWidth(#Gad_Grid2),20,"  Help...",#PB_Text_Border)
  SetGadgetColor(GadHelp,#PB_Gadget_BackColor,RGB(255,255,160))       ; For help
  
  ; Make some test data and write it in the cell AND also keep it in the cell's data
  ; store so user edits can be compared with the original value.
  *P = AllocateMemory(128)
  PokeS(*P,"0123456789abcdefghijklmnopqrstuvwxyz Hello Fred, have a nice day")
  *U = *P
  For Y = 0 To 7
    uGridWriteCellText(#Gad_Grid2,0,Y,"$"+Hex(*U))                    ; Address
    For X = 0 To 15
      uGridSetCellType(#Gad_Grid2,X+1,Y,1,1,#uGrid_CellHexOnly)      ; Limit user to HEX input
      uGridWriteCellText(#Gad_Grid2,X+1,Y,RSet(Hex(PeekB(*U)),2,"0")) ; Draw the HEX value
      uGridSetCellData(#Gad_Grid2,X+1,Y,*U)                           ; Keep copy of original data
      *U + 1
    Next
  Next
  
  uGridSetCellMaxChars(#Gad_Grid2,1,0,16,8,2)                         ; Limit cells to two characters
  uGridSetCellType(#Gad_Grid2,0,0,1,-1,#uGrid_CellNoEdit)            ; No editing of address column
  uGridRefreshGrid(#Gad_Grid2)    
  
  ;- Non-editable cells, block colouring and 'Help' 
   With uGridDefaults
    \TitleBackColour= RGB(180,255,180)
    \TextBackColour = #White
    \TextColour     = #Black
    \SelectColour   = #Black
    \EditStart      = #PB_EventType_LeftButtonDown
    \GridFont           = "Arial"
    \GridFontH          = 8
    \TitleFont      = "Courier"
    \TitleFontH         = 8
  EndWith
  k$= "A[34]|B[34]|C[34]|D[34]|E[34]|F[34]|G[34]|H[34]|I[34]|"
  TextGadget(#PB_Any,555,5,250,25,"Colour block and Cursor skip test")
  MyGrid3 = uGridGadget(#PB_Any,555,30,400,120,k$,09,#uGrid_AutoSizeX|#uGrid_AutoSizeY)

  ; Make blocks of cells non-editable... colour them red.
  For X = 0 To 8 Step 3
    For Y =0 To 8 Step 3
      If T & %01 
        uGridSetCellColour(MyGrid3,X,Y,3,3,0,RGB(255,210,210)) ; Red and 
        uGridSetCellType(MyGrid3,X,Y,3,3,#uGrid_CellNoEdit)   ; no edits.
        uGridWriteCellText(MyGrid3,X,Y,"No Go!")
      Else
        uGridSetCellColour(MyGrid3,X,Y,3,3,0,RGB(230,255,230))
      EndIf
      T+1
    Next
  Next
  
  ; Install a 'Help' string
  uGridSetCellHelp(MyGrid3,3,3,3,3,"Hello Fred")
  
  ;- Demo Title click + sort columns
  TextGadget(#PB_Any,620,255,110,25,"Sort test (Click title)")
  k$ = "Freq[50]|Station[50]|"
  uGridGadget(#Gad_Grid4,620,280,00,00,k$,10,#uGrid_AutoSizeX|#uGrid_AutoSizeY)
  uGridSetCellType(#Gad_Grid4,0,0,1,-1,#uGrid_CellFloat)
  uGridSetCellType(#Gad_Grid4,1,0,1,-1,#uGrid_CellUcase)
  k$= "Tom,Dick,Harry,Nelly,Jim1,Ted,Jim2" 
  For n = 0 To 6
    uGridWriteCellText(#Gad_Grid4,1,n,UCase(StringField(k$,n+1,",")))
    uGridWriteCellText(#Gad_Grid4,0,n,"7."+RSet(Str(Random(1000)),4,"0"))
  Next
  
  ;- Demo two state Image cells
  With uGridDefaults
    \GridFont       = "Arial"
    \GridFontH      = 8
    \TitleFont      = "CourierNew"
    \TitleFontH     = 12
    \ImageCellH     = 40 ; Cell height when #uGrid_UseAuxH specified **
  EndWith
  TextGadget(#PB_Any,760,255,180,25,"Image buttons")
  k$ = "Col1[70]|Col2[35]|"
  uGridGadget(#Gad_Grid3,760,280,0,0,k$,3,#uGrid_AutoSizeX|#uGrid_AutoSizeY|#uGrid_UseAuxH) ; Make grid with tall cells **
  uGridSetCellType(#Gad_Grid3,1,0,1,-1,#uGrid_CellImageFlip)                ; Second column cells to be images.
  
  ; Make right column into Option buttons
  For Y = 0 To 2
    C = #White
    For n = 0 To 1
      T = uGridGetFlipImageNum(#Gad_Grid3,1,Y,n)  ; Get Image# for state 'n'
      If T 
        W = ImageWidth(T) : H = ImageHeight(T)    ; Size of image
        If StartDrawing(ImageOutput(T))
            Box(0,0,W,H,#White)                   ; Backdrop for cell
            Circle(W/2,H/2,4,#Black)              ; Draw the 'Option Button'
            Circle(W/2,H/2,3,C)
          StopDrawing()
        EndIf
      EndIf
      C = #Red
    Next
  Next
  
  ; Set state of column 1 'Option button'
  For Y = 0 To 2
    uGridSetFlipImageState(#Gad_Grid3,1,Y,Y&1)
  Next
  
  uGridRefreshGrid(#Gad_Grid3)                                               ; show initial states.
  
  ;-       
  ButtonGadget(#PB_Any,760,465,100,30,"Button")
  
  uGridSelectCell(#Gad_Grid1,1,2) ; Place selection at specified cell
  uGridSetCellData(#Gad_Grid1,1,1,42424242)
  
  SetActiveGadget(-1)
  
Repeat
  Select WaitWindowEvent(10)
    Case #PB_Event_CloseWindow
      Break
      
    Case #PB_Event_Gadget
      Select EventGadget()
          
          ; 'uGrids' grouped in order simplifies coding 
        Case #Gad_Grid1 To #Gad_Grid4, MyGrid3 
          uGridService(EventGadget())
          
      EndSelect
  EndSelect
  
ForEver

Procedure uGridCallback(uGridNum,uGridEvent,IParam.i,*uGridCell)
  ; This procedure receives calls from uGrid correseponding with various events
  Static GridSortOrder
  
  ;- USEFUL DEBUG STUFF
  ; uGridNum   = Grid's CanvasGadget() number.
  ; uGridEvent = Reason for the call. Values are defined....
  ; Iparam     = Allocated according to uGridEvent type
  ; *uGridCell = If not zero is pointer to the structure defining the cell
  Debug ""
  Debug "Here because..."
  Select uGridEvent
    Case #uGridEvent_DeSelect      : Debug "Cell de-selected" 
    Case #uGridEvent_SelecT        : Debug "Cell Selected"  
    Case #uGridEvent_GridLostFocus : Debug "Grid lost focus"
    Case #uGridEvent_RightKey      : Debug "Right mouse click on cell"
    Case #uGridEvent_TitleClick    : Debug "Title click on Col "+Str(IParam)
    Case #uGridEvent_CellChar      : Debug "Key pressed = "+Chr(IParam)
    Case #uGridEvent_CellXY        : Debug "Mouse cell X,Y changed"
    Case #uGridEvent_CellImageFlip : Debug "Image cell flipped"
  EndSelect
  
  ; Show useful info for cell
  If *uGridCell
    *CellDat.CellOptions = *uGridCell
    With *CellDat
      Debug "Grid #     " + Str(uGridNum)
      Debug "Grid index "+Str(uGridGetGridIndex(uGridNum)) ; Index into uGrid.GRIDOPIONS(n) (0 => GridCount-1) or -1 if not found
      Debug "Cell GX    " + Str(\CellGX)
      Debug "Cell GY    " + Str(\CellGY)
      Debug "Content   <" + \CellContent+">"
      Debug "Cell type %" + Bin(\CellType)
      Debug "Cell flags%" + Bin(\CellFlags)
      Debug "Help      '" + \CellHelp+"'"
      Debug "DY         " + Str(\CellTextDY)
      
      If \CellType & #uGrid_CellImageFlip
        Debug "Images     #"+Str(\CellImage[0])+" and #"+Str(\CellImage[1])
        Debug "Select     :"+Str(\CellFlags & #uGrid_CellToggle) ; Treat as 0/1
      EndIf
      
      ; Example: Use right mouse button to delete text cell contents
      If uGridEvent = #uGridEvent_RightKey
        uGridClearCell(uGridNum,\CellGX,\CellGY,1,1)
      EndIf
      
    EndWith
  EndIf
  
  ;- Program Grid / Cell specific operations
  Select uGridNum 
    
    Case #Gad_Grid2  ; Edit Memory display...
      
      ; Highlight edits in the HEX memory display example
      Select uGridEvent 
        
        Case #uGridEvent_DeSelect,#uGridEvent_RightKey       
          If *uGridCell                                                                 
            *CellDat.CellOptions = *uGridCell
            With *CellDat
              k$ = \CellContent
              If k$="" : uGridWriteCellText(uGridNum,\CellGX,\CellGY,"00"): EndIf        ; Swap blank to '00'
              If Len(k$)=1:uGridWriteCellText(uGridNum,\CellGX,\CellGY,"0"+k$): EndIf
              If Val("$" + k$) <> PeekB(*CellDat\CellData)                               ; If NEW uGrid value,
                uGridSetCellColour(uGridNum,\CellGX,\CellGY,1,1,#Black,RGB(255,150,150)) ; Edit = Red backdrop.
              Else
                uGridSetCellColour(uGridNum,\CellGX,\CellGY,1,1,-1,-1)                   ; No edit / Redo = plain backdrop
              EndIf
            EndWith
          EndIf
          
        Case #uGridEvent_CellXY  ; Copy Help text for cell to display window
          If *uGridCell 
          *CellDat.CellOptions = *uGridCell
          SetGadgetText(GadHelp,"  Cell : "+*CellDat\CellHelp)
          EndIf
          
        Case  #uGridEvent_GridLostFocus
          SetGadgetText(GadHelp,"")
          
      EndSelect
      
      
      ; Recover 'Help' string for cell
      If uGridEvent =  #uGridEvent_CellXY 
        *CellDat.CellOptions = *uGridCell
        Debug uGridGetCellHelp(uGridNum,*CellDat\CellGX,*CellDat\CellGY)
      EndIf
      
    Case #Gad_Grid4                                                                    ; Test/Demo Sort grid  
      If uGridEvent = #uGridEvent_TitleClick
        GridSortOrder ! 1                                                              ; Toggle the sort order
        uGridSort(uGridNum,IParam,GridSortOrder & 1)
        While WindowEvent() : Wend                                                     ; Absorb double event.
      EndIf
      
  EndSelect
  
EndProcedure
;}
CompilerEndIf


Re: MicroGrid ~ Now with 'Image Cells' (Rev 0.91)

Posted: Wed Jan 08, 2014 6:46 pm
by aaaaaaaargh
Wow!
This is excellent stuff!
Works fine on PB5.21 WIN32 & 64
Thanks for sharing!

Re: MicroGrid ~ Now with 'Image Cells' (Rev 0.91)

Posted: Thu Jan 09, 2014 12:06 am
by falsam
Hi RichardL,

If I copy the code from the first message :

line 1366

Code: Select all

n + StepDir  Next
Compile : Error end of line. I corrected this line but I have a new error : uGridCallBack is not define.

Re: MicroGrid ~ Now with 'Image Cells' (Rev 0.91)

Posted: Thu Jan 09, 2014 9:22 am
by Kwai chang caine
+1

Re: MicroGrid ~ Now with 'Image Cells' (Rev 0.91)

Posted: Thu Jan 09, 2014 9:41 am
by davido
Very, very nice. Thank you for sharing. :D

Line 1366 gives 'garbage at end of line' Error Message.

I simply split the line before 'Next' and it appeared to run perfectly. Is this OK?

Re: MicroGrid ~ Now with 'Image Cells' (Rev 0.91)

Posted: Thu Jan 09, 2014 9:42 am
by davido
Very, very nice. Thank you for sharing. :D

Line 1366 gives 'garbage at end of line' Error Message.

I simply split the line before 'Next' and it appeared to run perfectly. Is this OK?

Re: MicroGrid ~ Now with 'Image Cells' (Rev 0.91)

Posted: Thu Jan 09, 2014 10:12 am
by RichardL
Good morning,

Whoops!
I don't know how the line 1366 error crept in; I must have been a bit careless when pasting from jaPBe into the forum's form, sorry.
The error is now corrected.

@falsam: uGridCallback(uGridNum,uGridEvent,IParam.i,*uGridCell) is present in the demo code and must be present in an application of your creation.
Did you append the demo code to the main library code?

RichardL