Steema Issues Database

Note: This database is for bugs and wishes only. For technical support help, if you are a customer please visit our online forums;
otherwise you can use StackOverflow.
Before using this bug-tracker we recommend a look at this document, Steema Bug Fixing Policy.



Bug 525

Summary: Matching values on pie chart can swap colors on refresh
Product: VCL TeeChart Reporter: swensonk
Component: ChartAssignee: Steema Issue Manager <issuemanager>
Status: RESOLVED FIXED    
Severity: normal CC: david
Priority: ---    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows   
Chart Series: --- Delphi / C++ Builder RAD IDE Version:
Attachments: Example of the original followed by the refresh

Description swensonk 2013-12-20 12:39:45 EST
Created attachment 63 [details]
Example of the original followed by the refresh

We are using a chart with a gradient and marks.  But when we print these we disable the gradient and marks, and refresh the chart.  If you have two matching values, these can items can swap colors in the legend.

The following is the code we are using that is during the swap in colors.

procedure TfrmPieChart.tbPrintClick(Sender: TObject);
var OldOrient : TPrinterOrientation;
begin

   PieChart.PrintMargins.Left := 3;
   PieChart.PrintMargins.Top := 3;
   PieChart.PrintMargins.Right := 3;
   PieChart.PrintMargins.Bottom := 3;
   PieChart.Gradient.Visible := False; 
   PieChart.Border.Visible := False;
   PieChart.Shadow.Visible := False;
   PieChart.BevelOuter := bvNone;

  Series1.Marks.Visible := False;
  Series2.Marks.Visible := False;
  Series3.Marks.Visible := False;
  Series4.Marks.Visible := False;

   Printer.PrinterIndex := Printer.Printers.IndexOf(SysObject.ReportPrinter);
   if (Printer.PrinterIndex > -1) and (SysObject.ReportPrinterTray <> '') then begin
      SelectPrinterBin(PrinterBinGetIndex(SysObject.ReportPrinter, SysObject.ReportPrinterTray));
   end;

   OldOrient := Printer.Orientation;
   Printer.Orientation := poLandscape;

   if printdialog1.Execute then begin
      Printer.BeginDoc;
      try
         PieChart.Canvas := TTeeCanvas3D.Create;
         PieChart.PrintPartial(PieChart.ChartPrintRect);
      finally
         Printer.EndDoc
      end;
   end;
   Printer.Orientation := OldOrient;

   PieChart.Canvas:=TGDIPlusCanvas.Create;
   PieChart.Gradient.Visible := True;

  Series1.Marks.Visible := True;
  Series2.Marks.Visible := True;
  Series3.Marks.Visible := True;
  Series4.Marks.Visible := True;

   PieChart.Refresh; //Reset chart to original settings
end;
Comment 1 david berneda 2013-12-23 10:09:25 EST
This problem is caused because there are duplicated Pie series values, and PieValues.Order :=  loAscending.

The internal sorting algorithm to order pie slices is a QuickSort, which is an "unstable" algorithm (it will swap duplicate values each run).

Code below reproduces the problem, clicking Button1:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Series1.Repaint;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Series1.Clear;
  Series1.Add(887,'a');
  Series1.Add(514,'b');
  Series1.Add(565,'c');
  Series1.Add(109,'d');
  Series1.Add(116,'e');
  Series1.Add(116,'f');
  Series1.Add(985,'g');
  Series1.Add(898,'h');

  Series1.PieValues.Order:=loAscending;
end;


We'll try to modify QuickSort to make it "stable", to avoid reordering.
Comment 2 david berneda 2013-12-23 10:40:01 EST
Fixed. Changed source code below (TeEngine.pas unit, TChartSeries.CompareValueIndex method)

Function TChartValueList.CompareValueIndex(a,b:Integer):Integer;
var tmpA : TChartValue;
    tmpB : TChartValue;
begin
  tmpA:=Value[a];
  tmpB:=Value[b];

  if tmpA<tmpB then result:=-1
  else
  if tmpA>tmpB then result:=1
  else
  begin
    // Use "a" and "b" indexes to avoid "unstable" results:

    if a<b then
       result:=-1  // -1 always, for both cases FOrder ascending or descending
    else
       result:=0;

    Exit;
  end;

  if FOrder=loDescending then
     result:=-result;
end;