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.