Codejock Grid with ProgressBar

From DataFlex Wiki
Jump to navigationJump to search

Author and origin

This example code was written by Peter Bragg and comes from the following post at the forum:

https://support.dataaccess.com/Forums/showthread.php?62699-cDBCJGrid-with-ProgressBar

cDBCJGrid with ProgressBar

Here's how to do this.

First, we have the following mixin class (with included use statements and defines etc):

  Define clHexOffice_Turquoise    for '#1abc9c'  //Turquoise
  Define clHexOffice_DrkTurquoise for '#16a085'  //GreenSea
  Define clHexOffice_Green        for '#2ecc71'  //Emerald 
  Define clHexOffice_LightGreen   for '#7ee2a8'
  Define clHexOffice_DrkGreen     for '#27ae60'  //Nephritis
  Define clHexOffice_BrightBlue   for '#3498db'  //PeterRiver
  Define clHexOffice_Blue         for '#2980b9'  //BelizeHole
  Define clHexOffice_Purple       for '#9b59b6'  //Amethyst
  Define clHexOffice_DrkPurple    for '#8e44ad'  //Wisteria
  Define clHexOffice_DrkBlue      for '#34495e'  //WetAsphalt
  Define clHexOffice_MidnightBlue for '#2c3e50'  //MidnightBlue
  Define clHexOffice_BrightYellow for '#f1c40f'  //Sunflower
  Define clHexOffice_Yellow       for '#f39c12'  //Orange
  Define clHexOffice_Orange       for '#e67e22'  //Carrot 
  Define clHexOffice_DrkOrange    for '#d35400'  //Pumpkin
  Define clHexOffice_Red          for '#e74c3c'  //Alizarin
  Define clHexOffice_DrkRed       for '#c0392b'  //Pomegranate 
  Define clHexOffice_White        for '#ecf0f1'  //Clouds 
  Define clHexOffice_Silver       for '#bdc3c7'  //Silver
  Define clHexOffice_Grey         for '#95a5a6'  //Concrete
  Define clHexOffice_DrkGrey      for '#7f8c8d'  //Asbestos
  
  
  Enum_List
    Define eProgressStyle_Normal
    Define eProgressStyle_TrafficLight
  End_Enum_List
  
  
  Class mixin_cCJGridProgressBar is a Mixin
  
    Procedure Define_cCJGridProgressBar_Properties
      {Category="Appearance" InitialValue=False}
      Property Boolean pbProgress         False
      {Category="Appearance" InitialValue=True}
      Property Boolean pbProgressLabel    True
      {Category="Appearance" EnumList="eProgressStyle_Normal,eProgressStyle_TrafficLight" InitialValue=eProgressStyle_Normal}
      Property Integer peProgressStyle    eProgressStyle_Normal  
    End_Procedure  
  
    {MethodType=Event}
    Procedure OnSetProgressBarValue Boolean ByRef bVisible String ByRef sLabel Number ByRef nPercentage Integer iRow
    End_Procedure
  
    {Visibility=Private}
    Function DisplayProgress Number nPercentageValue Returns String
      Number  nPercentage nWidth nProgress
      Integer iPercentage eStyle iRow
      String  sProgress sXAML sColor sColorBorder sLightColor sLabel sGBPSymbol
      Boolean bProgress bVisible 
      
      If (num_arguments>0) Begin
          Move nPercentageValue to nPercentage
      End
  
  
      Get pbProgress to bProgress
      If (bProgress) Begin
          Send OnSetProgressBarValue (&bVisible) (&sLabel) (&nPercentage)          
          If (bVisible) Begin
              Get peProgressStyle to eStyle
              // Compose XAML string
              // We need to know the width of the cell
              Get ComWidth to nWidth
              Subtract 6 from nWidth // Margin
              // Calculate length of progressbar:
              Move (nWidth * (nPercentage / 100)) to nProgress
              // If you want to use colors, you'll need to use Hexadecimal colors.
              Move clHexOffice_Grey to sColorBorder
              Case Begin
                  Case ((nProgress<33.3) and (eStyle=eProgressStyle_TrafficLight))
                      Move clHexOffice_Red to sColor
                      Move clHexOffice_Red to sLightColor
                      Case Break
                  Case ((nProgress<66.6) and (eStyle=eProgressStyle_TrafficLight))
                      Move clHexOffice_Orange to sColor
                      Move clHexOffice_Red to sLightColor
                      Case Break
                  Case (nProgress<100)
                      Move clHexOffice_Green to sColor
                      Move clHexOffice_LightGreen to sLightColor
                      Case Break
                  Case Else
                      Move clHexOffice_DrkGreen to sColor
                      Move clHexOffice_Green to sLightColor
              Case End
  
              Move (Integer(nPercentage)) to iPercentage
              // Compose XAML string                
              Move "<Grid><Border BorderBrush='%2' BorderThickness='1' CornerRadius='5' Height='13' Width='%4'> " to sXAML
              Add " <Border.Background><LinearGradientBrush StartPoint='0, 0' EndPoint='1,0'> <GradientStop Color='#C0CBDF' />" to sXAML
              Add " <GradientStop Color='#DCE9FA' Offset='1'/></LinearGradientBrush></Border.Background>" to sXAML
              Add " <Border HorizontalAlignment='Left' CornerRadius='5,0,0,5' Background='%3'" to sXAML
              Add " Width='%5'><Border.Background><LinearGradientBrush StartPoint='0, 0' EndPoint='1,0'>" to sXAML
              Add " <GradientStop Color='#658C4B' Offset='1'/><GradientStop Color='#A4DB64'/></LinearGradientBrush>" to sXAML 
              Add " </Border.Background></Border></Border><TextBlock VerticalAlignment='Center'"  to sXAML 
              Add " HorizontalAlignment='Center' Text='%1'></TextBlock></Grid>"  to sXAML
              If (pbProgressLabel(Self) and Trim(sLabel)='') Begin
                  Move (String(iPercentage)-'%') to sLabel
              End
              Move (SFormat(sXAML,sLabel,sColorBorder,sColor,String(nWidth),String(nProgress),sLightColor)) to sXAML            
              Move sXAML to sProgress
          End
      End
      Function_Return sProgress
    End_Function    
  End_Class

We then incorporate that into a subclass of the cDbCJGridColumn class as follows:

  Class cDemoDbCJGridColumn is a cDbCJGridColumn
    Import_Class_Protocol mixin_cCJGridProgressBar
    
    Procedure Construct_Object
      Forward Send Construct_Object
      
      Send Define_cCJGridProgressBar_Properties
    End_Procedure
    
    Procedure OnCreateColumn
      Boolean bProgress 
      
      Forward Send OnCreateColumn
      Get pbProgress to bProgress
      If bProgress Begin
          Delegate Set ComEnableMarkup to True
      End
    End_Procedure
    
    Procedure OnSetCalculatedValue String ByRef sValue
      Boolean bProgress
      
      Get pbProgress to bProgress
      If (bProgress) Begin
          Get DisplayProgress to sValue    
      End
      Forward Send OnSetCalculatedValue (&sValue)
    End_Procedure   
  End_Class

And then you can use this, just as in the Order Entry view, as follows:

Inside the oOrderDtl_Grid object, replace the oInvt_Description column with...


  Object oProgressBar is a cDemoDbCJGridColumn
    Set piWidth to 213
    Set psCaption to "Progress"
    Set pbProgress to True
            
    Procedure OnSetProgressBarValue Boolean ByRef bVisible String ByRef sLabel Number ByRef nPercentage
      Move (OrderHea.Order_Total>0) to bVisible
      If bVisible Begin
          Move (((OrderDtl.Price*OrderDtl.Qty_Ordered)/OrderHea.Order_Total)*100) to nPercentage
          Move (String(nPercentage)+"%") to sLabel
      End
    End_Procedure    
  End_Object

You can set the label to anything you want - here (above) I've simply set it to show the percentage value, so that you can see it is dynamic. You just have to make sure that it is encoded correctly.

cCJGrid and progressbar

Ok, so same mixin class as before, but this time we use it in a cCjGridColumn (not a cDbCjGridColumn)

  Class cDemoCJGridColumn is a cCJGridColumn
    Import_Class_Protocol mixin_cCJGridProgressBar
    
    Procedure Construct_Object
        Forward Send Construct_Object
        
        Send Define_cCJGridProgressBar_Properties
    End_Procedure
    
    Procedure OnCreateColumn
        Boolean bProgress 
        
        Forward Send OnCreateColumn
        Get pbProgress to bProgress
        If bProgress Begin
            Delegate Set ComEnableMarkup to True
        End
    End_Procedure 
  End_Class

And then we can use this inside an example view. Here I've taken the example for a cCjGrid (from the help) but I've added an additional column to show a progress bar

    Object oCustomerGrid is a cCJGrid
        Set Size to 200 300
        Set peAnchors to anAll
        Set pbReadOnly to True
        Set pbSelectionEnable to True      
            
        Object oCustomer_Customer_Number is a cCJGridColumn
            Set piWidth to 71
            Set psCaption to "Number"
            Set peDataType to Mask_Numeric_Window
            Set psMask to "######"
        End_Object
    
        Object oCustomer_Name is a cCJGridColumn
            Set piWidth to 257
            Set psCaption to "Customer Name"
        End_Object
    
        Object oCustomer_Status is a cCJGridColumn
            Set piWidth to 66
            Set psCaption to "Status"
            Set pbCheckbox to True
            Set psCheckboxTrue to "Y"
            Set psCheckboxFalse to "N"
        End_Object
        
        Object oProgressBar_Column is a cDemoCJGridColumn
            Set piWidth to 206
            Set psCaption to "Progress"
            Set pbProgress to True
            
            // Here you will need to determine what values to use. Typically this might be a global buffer value
            Procedure OnSetProgressBarValue Boolean ByRef bVisible String ByRef sLabel Number ByRef nPercentage
                Integer iRecs
                
                Move True to bVisible
                Move "Example" to sLabel
                Get_Attribute DF_FILE_RECORDS_USED of (RefTable(Customer)) to iRecs
                Move ((Customer.Customer_Number/iRecs)*100) to nPercentage
            End_Procedure
        End_Object
        
        Procedure LoadData 
            Handle hoDataSource
            tDataSourceRow[] TheData
            Boolean bFound
            Integer iRows iNum iName iStatus iProgress
            
            Get phoDataSource to hoDataSource
            
            // Get the datasource indexes of the various columns
            Get piColumnId of oCustomer_Customer_Number to iNum
            Get piColumnId of oCustomer_Name            to iName
            Get piColumnId of oCustomer_Status          to iStatus
            Get piColumnId of oProgressBar_Column       to iProgress
            
            // Load all data into the datasource array
            Clear Customer
            Find ge Customer by 1
            Move (Found) to bFound
            While (bFound)
                Move Customer.Customer_Number to TheData[iRows].sValue[iNum] 
                Move Customer.Name            to TheData[iRows].sValue[iName] 
                Move Customer.Status          to TheData[iRows].sValue[iStatus] 
                
                Get DisplayProgress of oProgressBar_Column to TheData[iRows].sValue[iProgress]
                
                Find gt Customer by 1
                Move (Found) to bFound
                Increment iRows
            Loop
            
            // Initialize Grid with new data
            Send InitializeData TheData
            Send MovetoFirstRow
        End_Procedure


Obviously this is just a silly example in which I'm calculating a progress value based on the customer number and total number of customer records, but you get the point.