Codejock Grid with ProgressBar
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.