View RSS Feed

Development Team Blog

Using Other Graphic Formats in Your cCJGrids

Rate this Entry
About a year ago (November 2010) I posted a blog about how to use other graphic formats in the headers of a cCJGrid. A couple of days ago there was a request about how to use other graphic formats in the grid itself. While all the information is in the one-year-old blog I feel you all want to see an example on how to do this. So that is what this blog is about.

In the previous blog I started with describing a column named oYellowCards. The blog was written shortly after the 2010 World Championships Football (ok Soccer for some of you). Since the year 2000 - the year in which Holland and Belgium were the host of the European Football Championships - Data Access Europe hosts, every 2 years, a website to predict scores for the Data Access customers worldwide. You can also win a nice prize. We will do the same again in 2012 and of course hope the Dutch will win again as in 1988 (it is time again)... I tell you this because the grid was built on top of data coming from this website. The website keeps track of the numbers in total and by player and expose this via a webservice to the rest of the world. The graphics in this website are GIF and JPEG pictures.

In this screenshot you see a grid with the football player names and the number of yellow and red cards they scored. In the first column the grid uses the country flag for a player instead of the name of the country.

The data shown in the grid is retrieved via a webservice function call and the flag pictures are downloaded automatically from the website based on the country flag URL returned by the webservice function call.



How can you make this grid yourself? Of course you start with a cCJGrid object. In there you need to add the five columns as shown in the picture. The first column is a current row indicator column (cCJGridColumnRowIndicator class). The second column - the one we are after - is a simple cCJGridColumn. One of the enhancement is that pictures are shown centered. This is done by setting the property peIconAlignment to xtpAlignmentIconCenter.

Code:
Object oCountryFlag is a cCJGridColumn
    Set piWidth to 30
    Set psCaption to "Country"            
    Set peIconAlignment to xtpAlignmentIconCenter
A more important enhancement is that I use the OnSetDisplayMetrics event to show the picture. The implemented code for this is:
Code:
Procedure OnSetDisplayMetrics Handle hoGridItemMetrics Integer iRow String ByRef sValue
    If (sValue <> "") Begin
        Set ComItemIcon of hoGridItemMetrics to sValue
    End
End_Procedure
Now of course you need to know how to get the picture in the sValue parameter of this grid cell. For this we have to look at the webservice and the returned information. Via the http://footballpool.dataaccess.eu/data/info.wso?wsdl URL you can create a cClientWebService class and base an object on this. For the grid data we use the function named wsAllPlayersWithYellowOrRedCards. The function returns an array of tWStPlayersWithCards data blocks. This struct is defined - by the WSDL parser in the Visual DataFlex Studio as:
Code:
Struct tWStPlayersWithCards
    string     sName
    integer    iYellowCards
    integer    iRedCards
    string     sTeamName
    string     sTeamFlag
End_Struct // tWStPlayersWithCards
Each element of the array contains the name of the player, the number of yellow and red cards received, the name of team (country) he is playing for and an URL to the flag of the country. An example of the data is:

The code to call the webservice for the data is added to the method LoadData - a name that is quite often used in our examples about the CodeJock grids.
Code:
Procedure LoadData
    tWStPlayersWithCards[] Cards
    tDataSourceRow[] Data
    String sImageFileName
    Integer eTransferStatus iElements iElement iImage
    Boolean bFileExist
    
    Get wsAllPlayersWithYellowOrRedCards of oWSFootballPoolService False False False to Cards
    Get peTransferStatus of oWSFootballPoolService to eTransferStatus
    If (eTransferStatus = wssOk) Begin
        Move (SizeOfArray (Cards)) to iElements
        Decrement iElements
        For iElement from 0 to iElements
The next step in the process is to download the country flag which I do with a self written method named DownloadFile and this method is called as follows:
Code:
Get DownloadFile Cards[iElement].sTeamFlag (&bFileExist) to sImageFileName
The DownLoadFile method creates and uses an object of the cHTTPTransfer class. To avoid that a picture is downloaded multiple times the code checks if the picture is present locally already or not. The full DownloadFile method is:
Code:
Function DownloadFile String sFilePath Boolean ByRef bFileExist Returns String
    Handle hoHTTP hoWorkspace
    String sDownloadedFileName sRemoteHost sBitmapPaths sFileLocation sFileName
    Integer iPos iResult
    
    Get phoWorkspace of ghoApplication to hoWorkspace
    Get psBitmapPath of hoWorkspace to sBitmapPaths
    Get PathAtIndex of hoWorkspace sBitmapPaths 1 to sFileLocation
    
    Move (Pos ('\\', sFilePath) or Pos ('//', sFilePath)) to iPos
    If (iPos > 0) Begin
        Move (Right (sFilePath, Length (sFilePath) - iPos - 1)) to sFilePath
    End
    Move (Pos ('\', sFilePath) or Pos ('/', sFilePath)) to iPos
    If (iPos > 0) Begin
        Move (Left (sFilePath, iPos - 1)) to sRemoteHost
        Move (Right (sFilePath, Length (sFilePath) - iPos)) to sFilePath
    End
    
    If (sRemoteHost <> "" and sFilePath <> "" and sFileLocation <> "") Begin
        If (Right (sFileLocation, 1) <> '\') Begin
            Move (sFileLocation - '\') to sFileLocation                    
        End
        Move (RightPos ('\', sFilePath) or RightPos ('/', sFilePath)) to iPos
        If (iPos > 0) Begin
            Move (Right (sFilePath, Length (sFilePath) - iPos)) to sFileName
        End
        Move (sFileLocation - sFileName) to sDownloadedFileName
        Move (DoesFileExist (sDownloadedFileName)) to bFileExist
        If (not (bFileExist)) Begin
            Get Create (RefClass (cHTTPTransfer)) to hoHTTP
            Set psRemoteHost of hoHTTP to sRemoteHost
            Set psAcceptTypes of hoHTTP to "image/*"
            Set psSaveAsFile of hoHTTP to sDownloadedFileName
            Get HTTPGetRequest of hoHTTP sFilePath to iResult
            If (iResult = 0) Begin
                Move '' to sDownloadedFileName
            End
            Send Destroy of hoHTTP
        End
    End
    
    Function_Return sDownloadedFileName
End_Function
The downloaded file is added to the set of images for the cCJGrid object with the AddImage function which we augmented in the previous blog. The code for this is:
Code:
Get AddImage sImageFileName 0 to Data[iElement].sValue[1]
EraseFile sImageFileName
The AddImage returns the handle to the image which is stored in the data used for the grid. The full LoadData is coded as:
Code:
Procedure LoadData
    tWStPlayersWithCards[] Cards
    tDataSourceRow[] Data
    String sImageFileName
    Integer eTransferStatus iElements iElement iImage
    Boolean bFileExist
    
    Get wsAllPlayersWithYellowOrRedCards of oWSFootballPoolService False False False to Cards
    Get peTransferStatus of oWSFootballPoolService to eTransferStatus
    If (eTransferStatus = wssOk) Begin
        Move (SizeOfArray (Cards)) to iElements
        Decrement iElements
        For iElement from 0 to iElements
            Get DownloadFile Cards[iElement].sTeamFlag (&bFileExist) to sImageFileName
            Get AddImage sImageFileName 0 to Data[iElement].sValue[1]
            EraseFile sImageFileName
            
            Move Cards[iElement].sTeamName to Data[iElement].vTag
            
            Move Cards[iElement].sName to Data[iElement].sValue[2]
            If (Cards[iElement].iYellowCards > 0) Begin
                Move Cards[iElement].iYellowCards to Data[iElement].sValue[3]
            End
            Else Begin
                Move '-' to Data[iElement].sValue[3]
            End
            If (Cards[iElement].iRedCards > 0) Begin
                Move Cards[iElement].iRedCards to Data[iElement].sValue[4]
            End
            Else Begin
                Move '-' to Data[iElement].sValue[4]
            End
        Loop
        
        Send InitializeData Data
    End
End_Procedure
If your images are present in a local environment you can of course skip the whole download part and go for loading the image directly.

Have fun with the above code.
Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	YellowAndRedCardsPerPlayer.jpg 
Views:	2662 
Size:	83.1 KB 
ID:	4598   Click image for larger version. 

Name:	RedAndYellowCardData.jpg 
Views:	2529 
Size:	75.7 KB 
ID:	4599  

Updated 2-Dec-2013 at 02:21 AM by Vincent Oorsprong (Images enlarged)

Categories
Uncategorized

Comments